.NAME Operands for loop counter

.DESCRIPTION
	If loop-counter is not modified by -- or ++, then, within 
condition, the loop-counter shall only be used as an 
operand to <=, <, > or >=. 

.COMMENT V7.0

.SEVERITY Required

.COMMENT
Please refer to the MISRA C++:2008 document for further details (www.misra-cpp.com)

.COMMAND tcl

.CODE

::logiscope::include -once common utilities.tcl

proc compute {standardName tree} {
  variable CurrentParameterList
  # Check all ... nodes
  utilities::filterTree $tree [list [namespace current]::check]
}

proc check { node } {
  set curOperator [::logiscope::treeOperator $node]
  set curOperatorName [::logiscope::opName $curOperator]

  # Look for a "for" loop
  if {[string equal $curOperatorName for]} {
    # Extract the test and modifier part of the "for" loop
	set testList [processForStatement [::logiscope::treeGetSon $node EXPR_OPT_2]]
	set modList [processForStatement [::logiscope::treeGetSon $node EXPR_OPT_3]]
	# Analyze these two lists and look for violations
	processFor $node $testList $modList
  }
  return 1
}

# This procedure analyzes a "for" loop statement (the test or modifier one) and produces a list of identifier/action
# Example: for ( i = 1, j=0; j!=3 , i != 10; --i, j+=1);
# The test statement is j!=3 , i != 10
# The modifier statement is --i, j+=1
# When called with the test statement node, this procedure returns INDEX_NAME_j neq INDEX_NAME_i neq 
# When called with the modifier statement node, this procedure returns INDEX_NAME_i pre_decr INDEX_NAME_j plus_ass 
# Note that all identifiers are prefixed with "INDEX_NAME_"
proc processForStatement {node} {
  set resultList ""
  # Retrieve the node's operator and name
  set curOpeName [::utilities::getName $node]
  # If the operator is an expr, parse its children
  if {[string equal $curOpeName expr]} {
	::logiscope::forobj son $node treeChild {
		if {[expr [::logiscope::treeLength $son] >= 1]} {
			::logiscope::forobj unknownNode $son treeChild {
				set identifierName ""
				set unknownNodeName [::logiscope::opName [::logiscope::treeOperator $unknownNode]]
				if {[expr [lsearch [list none errortree] $curOpeName] == -1]} {
					if {[string equal $unknownNodeName identifier]} {
						set identifierName [::logiscope::nameString [::logiscope::treeAtomValue $unknownNode]]
						set curActionName [::logiscope::opName [::logiscope::treeOperator $son]]
						set curIdActionPair [concat INDEX_NAME_$identifierName  $curActionName]
						set resultList [concat $resultList $curIdActionPair]
				  }
				}
			}
		}
	}	
  } else {
    # If the operator is not an expression, simply retrieve the identifier
	if {[expr [::logiscope::treeLength $node] >= 1]} {
		::logiscope::forobj unknownNode $node treeChild {
			set identifierName ""
			set unknownNodeName [::logiscope::opName [::logiscope::treeOperator $unknownNode]]
			if {[expr [lsearch [list none errortree] $curOpeName] == -1]} {
				if {[string equal $unknownNodeName identifier]} {
					set identifierName [::logiscope::nameString [::logiscope::treeAtomValue $unknownNode]]
					# In this case, the action name is the operator name
					set curIdActionPair [concat INDEX_NAME_$identifierName  $curOpeName]
					set resultList [concat $resultList $curIdActionPair]
			  }
			}
		}
	}
  }
  return $resultList
}

# This procedure checks the testList and modList for forbidden combinations 
proc processFor {node testList modList} {
  # Find the number of identifiers used in the test statement
  set nbIdentifiers [expr [llength $testList]/2]
  # Parse all identifiers, and look for them in the modifier statement
  for {set curIdx 0} {$curIdx<$nbIdentifiers} {incr curIdx} {
    set curIdentifierName [lindex $testList [expr $curIdx*2]]
    set curIdentifierTest [lindex $testList [expr $curIdx*2+1]]
	set foundIndex [lsearch $modList $curIdentifierName]
	set foundModifier ""
	if {[expr $foundIndex == -1]} {
	  set foundModifier none
	} else {
	  set foundModifier [lindex $modList [expr $foundIndex +1]]
	}
	
	# We now have for the current identifier, its test and modifier. 
	# All we do now is check if the test and modifiers are accepted by the rule
	if {![string equal $foundModifier pre_incr] && ![string equal $foundModifier pre_decr] && ![string equal $foundModifier post_incr] && ![string equal $foundModifier post_decr] } {
		if {[string equal $curIdentifierTest eq] || [string equal $curIdentifierTest neq]|| [string equal $curIdentifierTest call]} {
 	      ::logiscope::addViolation $node
		}
	}
  }
}
