.NAME Use of main

.DESCRIPTION
The identifier main shall not be used for a function 
other than the global function main. 

.COMMENT V7.0

.SEVERITY Required

.COMMENT
Please refer to the MISRA C++:2008 document for further details (www.misra-cpp.com)
This rule accepts a list of possible entry points as parameters (for Windows platforms, these parameters could be "main" "WinMain" "DllMain")
If no parameters are provided, only the main function is considered.

.PARAMETERS "main" "WinMain" "DllMain"

.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 isInNamespace { node } {
	while { ![utilities::isNullObject $node]} {
		if { [::utilities::isTreeOperator $node namespace_def] } {
			return 1
		}
		set node [::logiscope::treeUp $node]
	}
	return 0
}

proc check { node } {
	variable CurrentParameterList 
	# If no parameters are provided to the rule, the default behavior is to consider the main function only
	if {[expr [llength $CurrentParameterList] == 0]} {
		set CurrentParameterList "main"
	}
	
	if { [::utilities::isTreeOperator $node fndef] } {
        set nameNode [::logiscope::treeGetSonFromPath $node {
            {DECLARATOR func_dcltr} 
            {ANY_DECLARATOR identifier}
            }]
		if { ![utilities::isNullObject $nameNode] } {
			set name [::utilities::treeAtomString $nameNode]
			if { [expr [lsearch $CurrentParameterList $name] != -1]} {
				set vio 0
				if { [isInNamespace $node] } {
					set vio 1
				} else {
					set specifiers [::logiscope::treeGetSonFromPath $node {
                        {DECLARATION_SPECIFIERS declaration_specifiers} 
                        {DECLARATION_SPECIFIER* storage_class}
                        }]
                    foreach spec $specifiers {
                        set kind [::utilities::treeAtomString $spec]
                        if { "$kind" == "static" } {
                            set vio 1
                        }
                    }
				}
				if { $vio } {
					::logiscope::addViolation $node
				}
			}
		}
		return 0
	}
	return 1
}
