plcopen/structures.py
changeset 18 ee18a387e80a
parent 15 fc897b7bfa7b
child 19 0b499416ebd7
equal deleted inserted replaced
17:faa048f4172e 18:ee18a387e80a
   141 """
   141 """
   142 Ordored list of common data types defined in the IEC 61131-3
   142 Ordored list of common data types defined in the IEC 61131-3
   143 Each type is associated to his direct parent type. It defines then a hierarchy
   143 Each type is associated to his direct parent type. It defines then a hierarchy
   144 between type that permits to make a comparison of two types
   144 between type that permits to make a comparison of two types
   145 """
   145 """
   146 
   146 TypeHierarchy_list = [
   147 TypeHierarchy = {"ANY" : None,
   147 	("ANY" , None),
   148                  "ANY_DERIVED" : "ANY",
   148 	("ANY_DERIVED" , "ANY"),
   149                  "ANY_ELEMENTARY" : "ANY",
   149 	("ANY_ELEMENTARY" , "ANY"),
   150                  "ANY_MAGNITUDE": "ANY_ELEMENTARY",
   150 	("ANY_MAGNITUDE", "ANY_ELEMENTARY"),
   151                  "ANY_BIT" : "ANY_ELEMENTARY",
   151 	("ANY_BIT" , "ANY_ELEMENTARY"),
   152                  "ANY_STRING" : "ANY_ELEMENTARY",
   152 	("ANY_STRING" , "ANY_ELEMENTARY"),
   153                  "ANY_DATE" : "ANY_ELEMENTARY",
   153 	("ANY_DATE" , "ANY_ELEMENTARY"),
   154                  "ANY_NUM" : "ANY_MAGNITUDE",
   154 	("ANY_NUM" , "ANY_MAGNITUDE"),
   155                  "ANY_REAL" : "ANY_NUM",
   155 	("ANY_REAL" , "ANY_NUM"),
   156                  "ANY_INT" : "ANY_NUM",
   156 	("ANY_INT" , "ANY_NUM"),
   157                  "REAL" : "ANY_REAL",
   157 	("REAL" , "ANY_REAL"),
   158                  "LREAL" : "ANY_REAL",
   158 	("LREAL" , "ANY_REAL"),
   159                  "SINT" : "ANY_INT",
   159 	("SINT" , "ANY_INT"),
   160                  "INT" : "ANY_INT",
   160 	("INT" , "ANY_INT"),
   161                  "DINT" : "ANY_INT",
   161 	("DINT" , "ANY_INT"),
   162                  "LINT" : "ANY_INT",
   162 	("LINT" , "ANY_INT"),
   163                  "USINT" : "ANY_INT",
   163 	("USINT" , "ANY_INT"),
   164                  "UINT" : "ANY_INT",
   164 	("UINT" , "ANY_INT"),
   165                  "UDINT" : "ANY_INT",
   165 	("UDINT" , "ANY_INT"),
   166                  "ULINT" : "ANY_INT",
   166 	("ULINT" , "ANY_INT"),
   167                  "TIME" : "ANY_MAGNITUDE",
   167 	("TIME" , "ANY_MAGNITUDE"),
   168                  "BOOL" : "ANY_BIT",
   168 	("BOOL" , "ANY_BIT"),
   169                  "BYTE" : "ANY_BIT",
   169 	("BYTE" , "ANY_BIT"),
   170                  "WORD" : "ANY_BIT",
   170 	("WORD" , "ANY_BIT"),
   171                  "DWORD" : "ANY_BIT",
   171 	("DWORD" , "ANY_BIT"),
   172                  "LWORD" : "ANY_BIT",
   172 	("LWORD" , "ANY_BIT"),
   173                  "STRING" : "ANY_STRING",
   173 	("STRING" , "ANY_STRING"),
   174                  "WSTRING" : "ANY_STRING",
   174 	("WSTRING" , "ANY_STRING"),
   175                  "DATE" : "ANY_DATE",
   175 	("DATE" , "ANY_DATE"),
   176                  "TOD" : "ANY_DATE",
   176 	("TOD" , "ANY_DATE"),
   177                  "DT" : "ANY_DATE"
   177 	("DT" , "ANY_DATE")]
   178 }
   178 
       
   179 TypeHierarchy = dict(TypeHierarchy_list)
   179 
   180 
   180 """
   181 """
   181 returns true if the given data type is the same that "reference" meta-type or one of its types.
   182 returns true if the given data type is the same that "reference" meta-type or one of its types.
   182 """
   183 """
   183 
   184 
   192 returns list of all types that correspont to the ANY* meta type
   193 returns list of all types that correspont to the ANY* meta type
   193 """
   194 """
   194 def GetSubTypes(reference):
   195 def GetSubTypes(reference):
   195     return [ typename for typename in TypeHierarchy.iterkeys() if typename[:3] != "ANY" and IsOfType(typename, reference)]
   196     return [ typename for typename in TypeHierarchy.iterkeys() if typename[:3] != "ANY" and IsOfType(typename, reference)]
   196 
   197 
       
   198 
       
   199 def IsATime(iectype):
       
   200 	return IsOfType(iectype, TIME) or IsOfType(iectype, ANY_DATE)
       
   201 
       
   202 
   197 """
   203 """
   198 take a .csv file and translate it it a "csv_table"
   204 take a .csv file and translate it it a "csv_table"
   199 """            
   205 """            
   200 def csv_file_to_table(file):
   206 def csv_file_to_table(file):
   201 	return [ map(string.strip,line.split(';')) for line in file.xreadlines()]
   207 	return [ map(string.strip,line.split(';')) for line in file.xreadlines()]
   218 	variables = find_section("Standard_functions_variables_types", table)
   224 	variables = find_section("Standard_functions_variables_types", table)
   219 	standard_funtions_input_variables = {}
   225 	standard_funtions_input_variables = {}
   220 	fields = [True,True]
   226 	fields = [True,True]
   221 	while(fields[1]):
   227 	while(fields[1]):
   222 		fields = table.pop(0)
   228 		fields = table.pop(0)
   223 		variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:])])
   229 		variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ!=''])
   224 		standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type']
   230 		standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type']
   225 	return standard_funtions_input_variables
   231 	return standard_funtions_input_variables
   226 	
   232 	
   227 """
   233 """
   228 translate .csv file input declaration into PLCOpenEditor interessting values
   234 translate .csv file input declaration into PLCOpenEditor interessting values
   232 def csv_input_translate(str_decl, variables, base):
   238 def csv_input_translate(str_decl, variables, base):
   233 	decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',')
   239 	decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',')
   234 	param_types = []
   240 	param_types = []
   235 	param_names = []
   241 	param_names = []
   236 	modifiers = []
   242 	modifiers = []
   237 	if len(decl)>1 : suffix = str(base)
   243 
       
   244 	len_of_not_predifined_variable = 0
       
   245 	for param_type in decl:
       
   246 		predifined_variable_param_type = variables.get(param_type,None)
       
   247 		if not predifined_variable_param_type :
       
   248 			len_of_not_predifined_variable += 1
       
   249 
       
   250 	if len_of_not_predifined_variable>1 : suffix = str(base)
   238 	else: suffix = ''
   251 	else: suffix = ''
   239 	
   252 	
   240 	for param_type in decl:
   253 	for param_type in decl:
   241 		predifined_variable_param_type = variables.get(param_type,None)
   254 		predifined_variable_param_type = variables.get(param_type,None)
   242 		if predifined_variable_param_type :
   255 		if predifined_variable_param_type :
   263 			"baseinputnumber" : lambda x:int(x),
   276 			"baseinputnumber" : lambda x:int(x),
   264 			"extensible" : lambda x: {"yes":True, "no":False}[x],
   277 			"extensible" : lambda x: {"yes":True, "no":False}[x],
   265 			"inputs" : lambda x:csv_input_translate(x,variables,Function_decl.get("baseinputnumber",1)),
   278 			"inputs" : lambda x:csv_input_translate(x,variables,Function_decl.get("baseinputnumber",1)),
   266 			"outputs":lambda x:[("OUT",x,"none")]}
   279 			"outputs":lambda x:[("OUT",x,"none")]}
   267 		Function_decl[field] = translate.get(field,lambda x:x)(val)
   280 		Function_decl[field] = translate.get(field,lambda x:x)(val)
   268 	#Function_decl.pop("baseinputnumber")
       
   269 	Function_decl.pop("overloaded")
       
   270 	return Function_decl
   281 	return Function_decl
       
   282 
       
   283 
       
   284 def ANY_TO_ANY_FORMAT_GEN(fdecl):
       
   285 
       
   286 	ANY_T0_ANY_LIST=[
       
   287 		(("ANY_NUM","ANY_BIT"),("ANY_NUM","ANY_BIT"), "(%(return_type)s)%(IN_value)s"),
       
   288 		(("ANY_NUM","ANY_BIT"),("ANY_DATE","TIME"), "(%(return_type)s)real_to_time(%(IN_value)s)"), 
       
   289 		(("ANY_DATE","TIME"), ("ANY_NUM","ANY_BIT"), "(%(return_type)s)time_to_real(%(IN_value)s)"), 
       
   290 		(("ANY_DATE","TIME"), ("ANY_STRING",), "(%(return_type)s)time_to_string(%(IN_value)s)"),
       
   291 		(("ANY_STRING",), ("ANY_DATE","TIME"), "(%(return_type)s)string_to_time(%(IN_value)s)"),
       
   292 		(("ANY_BIT",), ("ANY_STRING",), "(%(return_type)s)int_to_string(%(IN_value)s, 16)"),
       
   293 		(("ANY_NUM",), ("ANY_STRING",), "(%(return_type)s)int_to_string(%(IN_value)s, 10)"),
       
   294 		(("ANY_STRING",), ("ANY_BIT",), "(%(return_type)s)string_to_int(%(IN_value)s, 16)"),
       
   295 		(("ANY_STRING",), ("ANY_NUM",), "(%(return_type)s)string_to_int(%(IN_value)s, 10)")]
       
   296 	
       
   297 	for (InTypes, OutTypes, Format) in ANY_T0_ANY_LIST:
       
   298 		inps = reduce(lambda a,b: a or b, map(lambda testtype : IsOfType(fdecl["outputs"][0][1],testtype), InTypes))
       
   299 		#print "IN     ",inps , fdecl["outputs"][0][1], InTypes
       
   300 		outs = reduce(lambda a,b: a or b, map(lambda testtype : IsOfType(fdecl["inputs"][0][1],testtype), OutTypes))
       
   301 		#print "OUT    ",outs , fdecl["inputs"][0][1], OutTypes
       
   302 		if (inps and outs ):
       
   303 		 	return Format
       
   304 
       
   305 	#print "IN:", fdecl["outputs"][0][1], "    OUT:", fdecl["inputs"][0][1]
       
   306 	
       
   307 	return "#error %s_TO_%s not implemented!"%(fdecl["inputs"][0][1],fdecl["outputs"][0][1])
       
   308 
   271 
   309 
   272 """
   310 """
   273 Returns this kind of declaration for all standard functions
   311 Returns this kind of declaration for all standard functions
   274 
   312 
   275             [{"name" : "Numerical", 'list': [   {   
   313             [{"name" : "Numerical", 'list': [   {   
   297 				if Current_section: 
   335 				if Current_section: 
   298 					Standard_Functions_Decl.append(Current_section)
   336 					Standard_Functions_Decl.append(Current_section)
   299 				Current_section = { "name" : fields[0], "list" : [] }
   337 				Current_section = { "name" : fields[0], "list" : [] }
   300 				Function_decl_list = []
   338 				Function_decl_list = []
   301 		
   339 		
   302 			dico_from_table = zip(fonctions, fields[1:])
   340 			dico_from_table = [ (champ,val) for champ,val in zip(fonctions, fields[1:]) if champ ]
   303 			Function_decl = decl_function(dico_from_table,variables)
   341 			Function_decl = decl_function(dico_from_table,variables)
   304 			
   342 			if Function_decl["name"].startswith('*') :
   305 			if Function_decl["name"].startswith("*"):
   343 				input_types = [ GetSubTypes(inpdecl[1]) for inpdecl in Function_decl["inputs"] ]
   306 				input_types = GetSubTypes(Function_decl["inputs"][0][1])
   344 				input_ovrloading_types = input_types[map(len,input_types).index(max(map(len,input_types)))]
   307 			else:
   345 			else:
   308 				input_types = [None]
   346 				input_ovrloading_types = [None]
   309 			if Function_decl["name"].endswith("**"):
   347 				
       
   348 			if Function_decl["name"].endswith('*') :
   310 				output_types = GetSubTypes(Function_decl["outputs"][0][1])
   349 				output_types = GetSubTypes(Function_decl["outputs"][0][1])
   311 			else:
   350 			else:
   312 				output_types = [None]
   351 				output_types = [None]
   313 				
   352 				
   314 			funcdecl = Function_decl["name"]
   353 			funcdeclname_orig = Function_decl["name"]
   315 			for intype in input_types:
   354 			funcdeclname = Function_decl["name"].strip('*_')
       
   355 			fdc = Function_decl["inputs"][:]
       
   356 			for intype in input_ovrloading_types:
   316 				if intype != None:
   357 				if intype != None:
   317 					decl_tpl = Function_decl["inputs"][0]
   358 					Function_decl["inputs"] = []
   318 					Function_decl["inputs"] = [decl_tpl[:1] + (intype,) + decl_tpl[2:]] + Function_decl["inputs"][1:]
   359 					for decl_tpl in fdc:
   319 					funcdeclin = funcdecl.replace("*_", intype + '_')
   360 						if IsOfType(intype, decl_tpl[1]):
   320 					Function_decl["name"] = funcdeclin
   361 							Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])]
       
   362 						else:
       
   363 							Function_decl["inputs"] += [(decl_tpl)]
       
   364 						
       
   365 						if funcdeclname_orig.startswith('*'):
       
   366 							funcdeclin = intype + '_' + funcdeclname 
       
   367 						else:
       
   368 							funcdeclin = funcdeclname
       
   369 				else:
       
   370 					funcdeclin = funcdeclname
       
   371 							
       
   372 
       
   373 				if Function_decl["return_type_rule"] == "copy_input":
       
   374 					output_types = [intype]
       
   375 				elif Function_decl["return_type_rule"] == "defined":
       
   376 					pass
   321 
   377 
   322 				for outype in output_types:
   378 				for outype in output_types:
   323 					if outype != None:
   379 					if outype != None:
   324 						decl_tpl = Function_decl["outputs"][0]
   380 						decl_tpl = Function_decl["outputs"][0]
   325 						Function_decl["outputs"] = [decl_tpl[:1] + (outype,) + decl_tpl[2:]] + Function_decl["outputs"][1:]
   381 						Function_decl["outputs"] = [ (decl_tpl[0] , outype,  decl_tpl[2])]
   326 						funcdeclout = funcdeclin.replace("_**", '_' + outype)
   382 						if funcdeclname_orig.endswith('*'):
   327 						Function_decl["name"] = funcdeclout
   383 							funcdeclout =  funcdeclin + '_' + outype
   328 					
   384 						else:
   329 					# create the copy of decl dict to be appended to section
   385 							funcdeclout =  funcdeclin
   330 					Function_decl_copy = Function_decl.copy()
   386 					else:
   331 					# Have to generate type description in comment with freshly redefined types
   387 						funcdeclout =  funcdeclin
   332 					Function_decl_copy["comment"] += ("\n (" +
   388 					Function_decl["name"] = funcdeclout
   333 						str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["inputs"]]).strip("[]").replace("'",'') +
   389 
   334 						" ) => (" +
   390 
   335 						str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["outputs"]]).strip("[]").replace("'",'') +
   391 					try:
   336 						" )")
   392 						fdecl = Function_decl
   337 					Current_section["list"].append(Function_decl_copy)
   393 						res = eval(Function_decl["python_eval_c_code_format"])
       
   394 					except Exception,e:
       
   395 						res = None
       
   396 
       
   397 					if res != None :
       
   398 						# create the copy of decl dict to be appended to section
       
   399 						Function_decl_copy = Function_decl.copy()
       
   400 						# Have to generate type description in comment with freshly redefined types
       
   401 						Function_decl_copy["comment"] += (
       
   402 							"\n (" +
       
   403 							str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["inputs"]]).strip("[]").replace("'",'') +
       
   404 							" ) => (" +
       
   405 							str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["outputs"]]).strip("[]").replace("'",'') +
       
   406 							" )")
       
   407 						Current_section["list"].append(Function_decl_copy)
       
   408 						#pp.pprint(Function_decl_copy)
       
   409 						
       
   410 	Standard_Functions_Decl.append(Current_section)
   338 	
   411 	
   339 	return Standard_Functions_Decl
   412 	return Standard_Functions_Decl
   340 
   413 
   341 #-------------------------------------------------------------------------------
   414 #-------------------------------------------------------------------------------
   342 #                             Test identifier
   415 #                             Test identifier
   414 IEC_KEYWORDS.extend([keyword for keyword in SFC_KEYWORDS if keyword not in IEC_KEYWORDS])
   487 IEC_KEYWORDS.extend([keyword for keyword in SFC_KEYWORDS if keyword not in IEC_KEYWORDS])
   415 IEC_KEYWORDS.extend([keyword for keyword in IL_KEYWORDS if keyword not in IEC_KEYWORDS])
   488 IEC_KEYWORDS.extend([keyword for keyword in IL_KEYWORDS if keyword not in IEC_KEYWORDS])
   416 IEC_KEYWORDS.extend([keyword for keyword in ST_KEYWORDS if keyword not in IEC_KEYWORDS])
   489 IEC_KEYWORDS.extend([keyword for keyword in ST_KEYWORDS if keyword not in IEC_KEYWORDS])
   417 
   490 
   418 if __name__ == '__main__':
   491 if __name__ == '__main__':
       
   492 	
   419 	import pprint
   493 	import pprint
   420 	pp = pprint.PrettyPrinter(indent=4)
   494 	pp = pprint.PrettyPrinter(indent=4)
   421 	std_decl = get_standard_funtions(csv_file_to_table(open("iec_std.csv")))
   495 
   422 	pp.pprint(std_decl)
   496 	def ANY_to_compiler_test_type_GEN(typename, paramname):
       
   497 		return {"ANY" : "",
       
   498 		"ANY_BIT" : "if(search_expression_type->is_binary_type(%(paramname)s_param_value))",
       
   499 		"ANY_NUM" : "if(search_expression_type->is_num_type(%(paramname)s_param_value))",
       
   500 		"ANY_REAL" : "if(search_expression_type->is_real_type(%(paramname)s_param_value))",
       
   501 		"ANY_INT" : "if(search_expression_type->is_integer_type(%(paramname)s_param_value))"
       
   502 		}.get(typename,
       
   503 			"if (typeid(*last_type_symbol) == typeid(%(typename)s_type_name_c))")%{
       
   504 					"paramname" : paramname, "typename": typename.lower()}
       
   505 	
       
   506 	def recurse_and_indent(fdecls, indent):
       
   507 		if type(fdecls) != type(tuple()):
       
   508 			res = ""
       
   509 			for Paramname, ParamTypes in fdecls.iteritems():
       
   510 				res += ("""
       
   511 {
       
   512 	indentifier_c param_name("%(input_name)s");
       
   513 	/* Get the value from a foo(<param_name> = <param_value>) style call */
       
   514 	symbol_c *%(input_name)s_param_value = function_call_param_iterator.search(&param_name);
       
   515 	
       
   516 	/* Get the value from a foo(<param_value>) style call */
       
   517 	if (%(input_name)s_param_value == NULL)
       
   518 	  %(input_name)s_param_value = function_call_param_iterator.next();
       
   519 	symbol_c *%(input_name)s_type_symbol = search_expression_type->get_type(%(input_name)s_param_value);
       
   520 	last_type_symbol = last_type_symbol && search_expression_type->is_same_type(%(input_name)s_type_symbol, last_type_symbol) ? search_expression_type->common_type(%(input_name)s_type_symbol, last_type_symbol) : %(input_name)s_type_symbol ;
       
   521 """%{"input_name":Paramname})
       
   522 				
       
   523 				for ParamType,NextParamDecl in ParamTypes.iteritems():
       
   524 				
       
   525 					res += ("""	
       
   526 	%(type_test)s
       
   527 	{
       
   528 %(if_good_type_code)s
       
   529 	}
       
   530 """%{
       
   531 	"type_test":ANY_to_compiler_test_type_GEN(ParamType,Paramname), 
       
   532 	"if_good_type_code":recurse_and_indent(NextParamDecl,indent).replace('\n','\n	')})
       
   533 
       
   534 				res += """	
       
   535 	ERROR;
       
   536 }
       
   537 """
       
   538 			
       
   539 			return res.replace('\n','\n'+indent)
       
   540 		else:
       
   541 			res = "\n"
       
   542 			fdecl=fdecls[0]
       
   543 			
       
   544 			result_type_rule = fdecl["return_type_rule"]
       
   545 			res += {
       
   546 				"copy_input" : "symbol_c * return_type_symbol = last_type_symbol;\n",
       
   547 				"defined" : "symbol_c * return_type_symbol = &%s_type_name_c;\n"%fdecl["outputs"][0][1].lower(),
       
   548 				}.get(result_type_rule, "symbol_c * return_type_symbol = %s;\n"%result_type_rule)
       
   549 			
       
   550 			
       
   551 			try:
       
   552 				code_gen = eval(fdecl["python_eval_c_code_format"])
       
   553 			except Exception:
       
   554 				code_gen = "#error in eval of " + fdecl["name"]
       
   555 
       
   556 			code_gen_dic_decl = {}
       
   557 			for paramname,paramtype,unused in fdecl["inputs"]:
       
   558 				code_gen_dic_decl[paramname+"_value"] = '");\n%s_param_value->accept(*this);\ns4o.print("'%(paramname)
       
   559 				code_gen_dic_decl[paramname+"_type"] = '");\n%s_type_symbol->accept(*this);\ns4o.print("'%(paramname)
       
   560 			code_gen_dic_decl["return_type"] = '");\nreturn_type_symbol->accept(*this);\ns4o.print("'
       
   561 			code_gen_dic_decl["param_count"] = '");\ns4o.print_integer(nb_param);\ns4o.print("'
       
   562 
       
   563 			if type(code_gen) == type(tuple()):
       
   564 				res += 's4o.print("%s");\n'%(code_gen[0]%code_gen_dic_decl)
       
   565 				static_param_accept_list = []
       
   566 				for paramname,paramtype,unused in fdecl["inputs"]:
       
   567 					static_param_accept_list.append("%s_param_value->accept(*this);\n"%(paramname))
       
   568 				res += ('s4o.print("%s");\n'%(code_gen[1])).join(static_param_accept_list)
       
   569 				code = 's4o.print("%s");\nparam_value->accept(*this);\n'%(code_gen[1])
       
   570 				end_code = 's4o.print("%s");\nreturn NULL;\n'%(code_gen[2])
       
   571 			else:
       
   572 				code = ''
       
   573 				end_code = ('s4o.print("' + code_gen%code_gen_dic_decl + '");\nreturn NULL;\n').replace('s4o.print("");\n','')
       
   574 
       
   575 			if fdecl["extensible"]:
       
   576 				res += ("""
       
   577 int base_num = %d
       
   578 do{
       
   579 	char my_name[10];
       
   580 	sprintf(my_name, "IN%%d", base_num++);
       
   581 	indentifier_c param_name(my_name);
       
   582 	
       
   583 	/* Get the value from a foo(<param_name> = <param_value>) style call */
       
   584 	symbol_c *param_value = function_call_param_iterator.search(&param_name);
       
   585 	
       
   586 	/* Get the value from a foo(<param_value>) style call */
       
   587 	if (param_value == NULL)
       
   588 	  param_value = function_call_param_iterator.next();
       
   589 	if (param_value != NULL){
       
   590 		symbol_c *current_type_symbol = search_expression_type->get_type(param_value);
       
   591 		last_type_symbol = last_type_symbol && search_expression_type->is_same_type(current_type_symbol, last_type_symbol) ? search_expression_type->common_type(current_type_symbol, last_type_symbol) : current_type_symbol ;
       
   592 	
       
   593 		/*Function specific CODE */
       
   594 		%s
       
   595 	}
       
   596 	
       
   597 }while(param_value != NULL)
       
   598 %s
       
   599 """%(fdecl["baseinputnumber"]+2, code.replace('\n','\n		'), end_code))
       
   600 			else:
       
   601 				#res += code + end_code
       
   602 				res += end_code
       
   603 				
       
   604 			return res.replace('\n','\n'+indent)
       
   605 
       
   606 ###################################################################
       
   607 ###                                                             ###
       
   608 ###                           MAIN                              ###
       
   609 ###                                                             ###
       
   610 ###################################################################
       
   611 
       
   612 	# Get definitions
       
   613 	std_decl = get_standard_funtions(csv_file_to_table(open("iec_std.csv")))#, True)
       
   614 	
       
   615 	# Reorganize into a dict of dict, according 
       
   616 	# fname : paramname : paramtype : paraname : paramtype...
       
   617 	# Keep ptrack of original order in a separated list
       
   618 	std_fdecls = {}
       
   619 	official_order = []
       
   620 	for section in std_decl:
       
   621 		for fdecl in section["list"]:
       
   622 			if len(official_order)==0 or official_order[-1] != official_order:
       
   623 				official_order.append(fdecl["name"])
       
   624 			# store all func by name in a dict
       
   625 			std_fdecls_fdecl_name = std_fdecls.get(fdecl["name"], {})
       
   626 			current = std_fdecls_fdecl_name
       
   627 			for i in fdecl["inputs"]:
       
   628 				current[i[0]] = current.get(i[0], {})
       
   629 				current = current[i[0]]
       
   630 				last = current
       
   631 				current[i[1]] = current.get(i[1], {})
       
   632 				current = current[i[1]]
       
   633 			last[i[1]]=(fdecl,)
       
   634 			std_fdecls[fdecl["name"]] = std_fdecls_fdecl_name
       
   635 
       
   636 	# Generate the long enumeration of std function types
       
   637 	function_type_decl =  """
       
   638 /****
       
   639  * IEC 61131-3 standard function lib
       
   640  * generated code, do not edit by hand
       
   641  */
       
   642 typedef enum {
       
   643 """
       
   644 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   645 		function_type_decl += "	function_"+fname.lower()+",\n"
       
   646 
       
   647 	function_type_decl += """	function_none
       
   648 } function_type_t;
       
   649 """
       
   650 
       
   651 	# Generate the funct thaat return enumerated according function name
       
   652 	get_function_type_decl = """
       
   653 function_type_t get_function_type(identifier_c *function_name) {
       
   654 """
       
   655 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   656 		get_function_type_decl += """
       
   657 	if (!strcasecmp(function_name->value, "%s"))
       
   658 		return function_%s;
       
   659 """%(fname,fname.lower())
       
   660 
       
   661 	get_function_type_decl += """
       
   662 	else return function_none;
       
   663 }
       
   664 
       
   665 """
       
   666 
       
   667 	# Generate the part of generate_cc_st_c::visit(function_invocation)
       
   668 	# that is responsible to generate C code for std lib calls.
       
   669 	st_code_gen = "switch(current_function_type){\n"	
       
   670 	
       
   671 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   672 		st_code_gen += """
       
   673 /****
       
   674  *%s
       
   675  */
       
   676 	case function_%s :
       
   677 	{
       
   678 		symbol_c *last_type_symbol = NULL;
       
   679 """	%(fname, fname.lower())
       
   680 		indent =  "	"
       
   681 
       
   682 		st_code_gen += recurse_and_indent(fdecls, indent).replace('\n','\n	')
       
   683 		
       
   684 		st_code_gen += """
       
   685 	}/*function_%s*/
       
   686 	break;
       
   687 """	%(fname.lower())
       
   688 	st_code_gen += "}"
       
   689 
       
   690 	# Now, print that out, or write to files from sys.argv
       
   691 	print function_type_decl
       
   692 	print get_function_type_decl
       
   693 	print st_code_gen #.replace("\n", "\\\n")
       
   694 	
   423 else:
   695 else:
   424 	# Put standard functions declaration in Bloktypes
   696 	# Put standard functions declaration in Bloktypes
   425 	BlockTypes.extend(get_standard_funtions(csv_file_to_table(open(os.path.join(sys.path[0], "plcopen/iec_std.csv")))))
   697 	BlockTypes.extend(get_standard_funtions(csv_file_to_table(open(os.path.join(sys.path[0], "plcopen/iec_std.csv")))))
   426 	
   698