generate_IEC_std.py
changeset 1389 fb19c6226ff5
parent 1388 67c9a9482d24
child 1390 0f4d32a033e0
equal deleted inserted replaced
1388:67c9a9482d24 1389:fb19c6226ff5
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard. 
       
     6 #
       
     7 #Copyright (C) 2007-2011: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU General Public
       
    22 #License along with this library; if not, write to the Free Software
       
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    24 
       
    25 """
       
    26  THIS CODE GENARATES C++ CODE FOR IEC2C COMPILER
       
    27 """
       
    28 
       
    29 file_list = [
       
    30         ('absyntax_utils',      'function_type_decl','h'        ),
       
    31         ('absyntax_utils',      'get_function_type_decl','c'    ),
       
    32         ('absyntax_utils',      'search_type_code','c'          ),
       
    33         ('stage4/generate_c',   'st_code_gen','c'               ),
       
    34         ('stage4/generate_c',   'il_code_gen','c'               ),
       
    35         ('stage1_2',            'standard_function_names','c'   ),
       
    36         ('lib',                 'iec_std_lib_generated','h'     )
       
    37         ]
       
    38 
       
    39 # Get definitions
       
    40 from plcopen.structures import *
       
    41 
       
    42 if len(sys.argv) != 2 :
       
    43     print "Usage: " + sys.argv[0] + " path_name\n -> create files in path_name"
       
    44     sys.exit(0)
       
    45 
       
    46 #import pprint
       
    47 #pp = pprint.PrettyPrinter(indent=4)
       
    48 
       
    49 matiec_header = """/*
       
    50  * Copyright (C) 2007-2011: Edouard TISSERANT and Laurent BESSARD
       
    51  *
       
    52  * See COPYING and COPYING.LESSER files for copyright details.
       
    53  *
       
    54  * This program is free software: you can redistribute it and/or modify
       
    55  * it under the terms of the GNU General Public License as published by
       
    56  * the Free Software Foundation, either version 3 of the License, or
       
    57  * (at your option) any later version.
       
    58  *
       
    59  * This program is distributed in the hope that it will be useful,
       
    60  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    61  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    62  * GNU General Public License for more details.
       
    63  *
       
    64  * You should have received a copy of the GNU General Public License
       
    65  * along with this program. If not, see <http://www.gnu.org/licenses/>.
       
    66  *
       
    67  */
       
    68 
       
    69 /****
       
    70  * IEC 61131-3 standard function library
       
    71  * generated code, do not edit by hand
       
    72  */
       
    73  
       
    74  """
       
    75 
       
    76 matiec_lesser_header = """/*
       
    77  * Copyright (C) 2007-2011: Edouard TISSERANT and Laurent BESSARD
       
    78  *
       
    79  * See COPYING and COPYING.LESSER files for copyright details.
       
    80  *
       
    81  * This library is free software; you can redistribute it and/or
       
    82  * modify it under the terms of the GNU Lesser General Public
       
    83  * License as published by the Free Software Foundation; either
       
    84  * version 3 of the License, or (at your option) any later version.
       
    85  *
       
    86  * This library is distributed in the hope that it will be useful,
       
    87  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    88  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    89  * Lesser General Public License for more details.
       
    90  * 
       
    91  * You should have received a copy of the GNU Lesser General Public License 
       
    92  * along with this library. If not, see <http://www.gnu.org/licenses/>.
       
    93  *
       
    94  */
       
    95 
       
    96 /****
       
    97  * IEC 61131-3 standard function library
       
    98  * generated code, do not edit by hand
       
    99  */
       
   100 
       
   101  """
       
   102 
       
   103 def ANY_to_compiler_test_type_GEN(typename, paramname):
       
   104     """
       
   105     Convert ANY_XXX IEC type declaration into IEC2C's generated type test.
       
   106     This tests are defined in search_expression_type.cc 
       
   107     """
       
   108     return {"ANY" : "",
       
   109     "ANY_BIT" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_binary_type(%(paramname)s_type_symbol))",
       
   110     "ANY_NBIT" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_nbinary_type(%(paramname)s_type_symbol))",
       
   111     "ANY_NUM" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_num_type(%(paramname)s_type_symbol))",
       
   112     "ANY_REAL" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_real_type(%(paramname)s_type_symbol))",
       
   113     "ANY_INT" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_integer_type(%(paramname)s_type_symbol))"
       
   114     }.get(typename,
       
   115         #"if (typeid(*last_type_symbol) == typeid(%(typename)s_type_name_c))")%{
       
   116         "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_same_type(&search_constant_type_c::%(typename)s_type_name, last_type_symbol))")%{
       
   117                 "paramname" : paramname, "typename": typename.lower()}
       
   118 
       
   119 def recurse_and_indent(fdecls, indent, do_type_search_only = False, do_il = False):
       
   120     """
       
   121     This function generate visit(function_invocation) code for 
       
   122         - ST code generator
       
   123         - IL code generator
       
   124         - search_expression_type class for ST
       
   125         - search_expression_type class for IL
       
   126         
       
   127     Input data is a 
       
   128     "{fname : {IN[0]paramname : {IN[0]paramtype : {IN[1]paraname : {IN[1]paramtype : {... : {IN[N]paraname : {IN[N]paramtype : (fdecl,)}}}}}}"
       
   129     nested dictionary structure.
       
   130     """
       
   131     if type(fdecls) != type(tuple()):
       
   132         res = ""
       
   133         for Paramname, ParamTypes in fdecls.iteritems():
       
   134             if do_il:
       
   135                 res += """
       
   136 {"""
       
   137                 if not do_type_search_only:
       
   138                     res += """
       
   139     symbol_c *%(input_name)s_param_name = (symbol_c *)(new identifier_c("%(input_name)s"));
       
   140     /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   141     symbol_c *%(input_name)s_param_value = &this->default_variable_name;
       
   142 """%{"input_name":Paramname}
       
   143                 res += """
       
   144     symbol_c *%(input_name)s_type_symbol = param_data_type;
       
   145     last_type_symbol = %(input_name)s_type_symbol;
       
   146 """%{"input_name":Paramname}
       
   147             else:
       
   148                 res += """
       
   149 {
       
   150     symbol_c *%(input_name)s_param_name = (symbol_c *)(new identifier_c("%(input_name)s"));
       
   151     /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   152     symbol_c *%(input_name)s_param_value = function_call_param_iterator.search_f(%(input_name)s_param_name);
       
   153     symbol_c *%(input_name)s_type_symbol = NULL;
       
   154     
       
   155     /* Get the value from a foo(<param_value>) style call */
       
   156     if (%(input_name)s_param_value == NULL)
       
   157       %(input_name)s_param_value = function_call_param_iterator.next_nf();
       
   158     if (%(input_name)s_param_value != NULL) {
       
   159       %(input_name)s_type_symbol = search_expression_type->get_type(%(input_name)s_param_value);
       
   160       last_type_symbol = last_type_symbol && %(input_name)s_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 ;
       
   161     }
       
   162 """%{"input_name":Paramname}
       
   163                                 
       
   164             for ParamType,NextParamDecl in ParamTypes.iteritems():
       
   165             
       
   166                 res += """    
       
   167     %(type_test)s
       
   168     {
       
   169 %(if_good_type_code)s
       
   170     }
       
   171 """%{
       
   172     "type_test":ANY_to_compiler_test_type_GEN(ParamType,Paramname), 
       
   173     "if_good_type_code":recurse_and_indent(NextParamDecl,indent,do_type_search_only).replace('\n','\n    ')}
       
   174 
       
   175             res += """    
       
   176     
       
   177     ERROR;
       
   178 }
       
   179 """
       
   180         
       
   181         return res.replace('\n','\n'+indent)
       
   182     else:
       
   183         res = "\n"
       
   184         fdecl=fdecls[0]
       
   185         
       
   186         if not do_type_search_only:
       
   187             code_gen = eval(fdecl["python_eval_c_code_format"])
       
   188             
       
   189             if code_gen[1] is not None:
       
   190                 res += "function_name = (symbol_c*)(new pragma_c(\"%s\"));\n"%code_gen[1]
       
   191             if fdecl["extensible"]:
       
   192                 res += """
       
   193 if (nb_param < %(min_nb_param)d)
       
   194   nb_param = %(min_nb_param)d;
       
   195 char* nb_param_str = new char[10];
       
   196 sprintf(nb_param_str, "%%d", nb_param);
       
   197 symbol_c * nb_param_name = (symbol_c *)(new identifier_c("nb_param"));
       
   198 ADD_PARAM_LIST(nb_param_name, (symbol_c*)(new integer_c((const char *)nb_param_str)), (symbol_c*)(new int_type_name_c()), function_param_iterator_c::direction_in)
       
   199 """%{"min_nb_param" : len(fdecl["inputs"])}
       
   200             for paramname,paramtype,unused in fdecl["inputs"]:
       
   201                 res += """
       
   202 if (%(input_name)s_type_symbol == NULL)
       
   203   %(input_name)s_type_symbol = last_type_symbol;
       
   204 ADD_PARAM_LIST(%(input_name)s_param_name, %(input_name)s_param_value, %(input_name)s_type_symbol, function_param_iterator_c::direction_in)
       
   205 """%{"input_name" : paramname}
       
   206             if fdecl["extensible"]:
       
   207                 res += """
       
   208 int base_num = %d;
       
   209 symbol_c *param_value = NULL;
       
   210 symbol_c *param_name = NULL;
       
   211 do{
       
   212     char my_name[10];
       
   213     sprintf(my_name, "IN%%d", base_num++);
       
   214     param_name = (symbol_c*)(new identifier_c(my_name));
       
   215     
       
   216     /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   217     param_value = function_call_param_iterator.search_f(param_name);
       
   218     
       
   219     /* Get the value from a foo(<param_value>) style call */
       
   220     if (param_value == NULL)
       
   221       param_value = function_call_param_iterator.next_nf();
       
   222     if (param_value != NULL){
       
   223         symbol_c *current_type_symbol = search_expression_type->get_type(param_value);
       
   224         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 ;
       
   225     
       
   226         /*Function specific CODE */
       
   227         ADD_PARAM_LIST(param_name, param_value, current_type_symbol, function_param_iterator_c::direction_in)
       
   228     }
       
   229     
       
   230 }while(param_value != NULL);
       
   231 """%(fdecl["baseinputnumber"] + 2)
       
   232         
       
   233         result_type_rule = fdecl["return_type_rule"]
       
   234         res += {
       
   235             "copy_input" : "symbol_c * return_type_symbol = last_type_symbol;\n",
       
   236             "defined" : "symbol_c * return_type_symbol = &search_constant_type_c::%s_type_name;\n"%fdecl["outputs"][0][1].lower(),
       
   237             }.get(result_type_rule, "symbol_c * return_type_symbol = %s;\n"%result_type_rule)
       
   238         
       
   239         if not do_type_search_only:
       
   240             if code_gen[0] is not None:
       
   241                 res += "function_type_prefix = %s;\n"%{"return_type" : "return_type_symbol"}.get(code_gen[0], "(symbol_c*)(new pragma_c(\"%s\"))"%code_gen[0])
       
   242             if code_gen[2] is not None:
       
   243                 res += "function_type_suffix = %s_symbol;\n"%{"common_type" : "last_type"}.get(code_gen[2], code_gen[2])
       
   244             
       
   245             any_common = reduce(lambda x, y: {"ANY": lambda x: x,
       
   246                                           "ANY_BIT": lambda x: {"ANY": y, "ANY_NUM": y}.get(y, x),
       
   247                                           "ANY_NUM": lambda x: {"ANY": y}.get(y, x),
       
   248                                           "ANY_REAL": lambda x: {"ANY": y, "ANY_NUM": y}.get(y, x)}.get(x, y), 
       
   249                                 [paramtype for paramname,paramtype,unused in fdecl["inputs"]], "BOOL")
       
   250             
       
   251             first = True
       
   252             for list, test_type, default_type in [(["ANY", "ANY_NUM"], "integer", "lint"),
       
   253                                                   (["ANY_BIT"], "integer", "lword"),
       
   254                                                   (["ANY", "ANY_REAL"], "real", "lreal")]:
       
   255             
       
   256                 if any_common in list:
       
   257                     if not first:
       
   258                         res += "else "
       
   259                     first = False
       
   260                     res += """if (search_expression_type->is_literal_%s_type(function_type_suffix))
       
   261     function_type_suffix = &search_constant_type_c::%s_type_name;
       
   262 """%(test_type, default_type)
       
   263         
       
   264             res += "break;\n"
       
   265         else:
       
   266             res += "return return_type_symbol;\n"
       
   267         
       
   268         return res.replace('\n','\n'+indent)
       
   269 
       
   270 def get_default_input_type(fdecls):
       
   271     if type(fdecls) != type(tuple()) and len(fdecls) == 1:
       
   272         ParamTypes = fdecls.values()[0]
       
   273         if len(ParamTypes) == 1:
       
   274             ParamType_name, ParamType_value = ParamTypes.items()[0]
       
   275             if not ParamType_name.startswith("ANY") and type(ParamType_value) == type(tuple()):
       
   276                 return "&search_constant_type_c::%s_type_name" % ParamType_name.lower()
       
   277     return "NULL"
       
   278     
       
   279 ###################################################################
       
   280 ###                                                             ###
       
   281 ###                           MAIN                              ###
       
   282 ###                                                             ###
       
   283 ###################################################################
       
   284 
       
   285 """
       
   286 Reorganize std_decl from structure.py
       
   287 into a nested dictionnary structure (i.e. a tree):
       
   288 "{fname : {IN[0]paramname : {IN[0]paramtype : {IN[1]paraname : {IN[1]paramtype : {... : {IN[N]paraname : {IN[N]paramtype : (fdecl,)}}}}}}"
       
   289 Keep ptrack of original declaration order in a 
       
   290 separated list called official_order
       
   291 """
       
   292 std_fdecls = {}
       
   293 official_order = []
       
   294 for section in std_decl:
       
   295     for fdecl in section["list"]:
       
   296         if len(official_order)==0 or fdecl["name"] not in official_order:
       
   297             official_order.append(fdecl["name"])
       
   298         # store all func by name in a dict
       
   299         std_fdecls_fdecl_name = std_fdecls.get(fdecl["name"], {})
       
   300         current = std_fdecls_fdecl_name
       
   301         for i in fdecl["inputs"]:
       
   302             current[i[0]] = current.get(i[0], {})
       
   303             current = current[i[0]]
       
   304             last = current
       
   305             current[i[1]] = current.get(i[1], {})
       
   306             current = current[i[1]]
       
   307         last[i[1]]=(fdecl,)
       
   308         std_fdecls[fdecl["name"]] = std_fdecls_fdecl_name
       
   309 
       
   310 ###################################################################
       
   311 
       
   312 """
       
   313 Generate the long enumeration of std function types
       
   314 """
       
   315 function_type_decl =  matiec_header + """
       
   316 typedef enum {
       
   317 """
       
   318 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   319     function_type_decl += "    function_"+fname.lower()+",\n"
       
   320 
       
   321 function_type_decl += """    function_none
       
   322 } function_type_t;
       
   323 """
       
   324 ###################################################################
       
   325 """
       
   326 Generate the funct that return enumerated according function name
       
   327 """
       
   328 get_function_type_decl = matiec_header + """
       
   329 function_type_t get_function_type(identifier_c *function_name) {
       
   330 """
       
   331 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   332     get_function_type_decl += """
       
   333 if (!strcasecmp(function_name->value, "%s"))
       
   334     return function_%s;
       
   335 """%(fname,fname.lower())
       
   336 
       
   337 get_function_type_decl += """
       
   338     else return function_none;
       
   339 }
       
   340 
       
   341 """
       
   342 ###################################################################
       
   343 """
       
   344 Generate the part of generate_c_st_c::visit(function_invocation)
       
   345 that is responsible to generate C code for std lib calls.
       
   346 """
       
   347 st_code_gen = matiec_header + """
       
   348 switch(current_function_type){
       
   349 """
       
   350 
       
   351 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   352     st_code_gen += """
       
   353 /****
       
   354  *%s
       
   355  */
       
   356     case function_%s :
       
   357     {
       
   358         symbol_c *last_type_symbol = %s;
       
   359 """    %(fname, fname.lower(), get_default_input_type(fdecls))
       
   360     indent =  "    "
       
   361 
       
   362     st_code_gen += recurse_and_indent(fdecls, indent).replace('\n','\n    ')
       
   363     
       
   364     st_code_gen += """
       
   365     }/*function_%s*/
       
   366     break;
       
   367 """    %(fname.lower())
       
   368 st_code_gen +=  """
       
   369     case function_none :
       
   370     ERROR;
       
   371 }
       
   372 """
       
   373 
       
   374 ###################################################################
       
   375 """
       
   376 Generate the part of generate_c_il_c::visit(il_function_call)
       
   377 that is responsible to generate C code for std lib calls.
       
   378 """
       
   379 il_code_gen = matiec_header + """
       
   380 switch(current_function_type){
       
   381 """
       
   382 
       
   383 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   384     il_code_gen += """
       
   385 /****
       
   386  *%s
       
   387  */
       
   388     case function_%s :
       
   389     {
       
   390         symbol_c *last_type_symbol = %s;
       
   391 """    %(fname, fname.lower(), get_default_input_type(fdecls))
       
   392     indent =  "    "
       
   393 
       
   394     il_code_gen += recurse_and_indent(fdecls, indent, do_il=True).replace('\n','\n    ')
       
   395     
       
   396     il_code_gen += """
       
   397     }/*function_%s*/
       
   398     break;
       
   399 """    %(fname.lower())
       
   400 il_code_gen +=  """
       
   401     case function_none :
       
   402     ERROR;
       
   403 }
       
   404 """
       
   405 
       
   406 ###################################################################
       
   407 """
       
   408 Generate the part of search_expression_type_c::visit(function_invocation)
       
   409 that is responsible of returning type symbol for function invocation.
       
   410 """
       
   411 search_type_code = matiec_header + """
       
   412 
       
   413 void *search_expression_type_c::compute_standard_function_default(function_invocation_c *st_symbol = NULL, il_formal_funct_call_c *il_symbol = NULL) {
       
   414   function_type_t current_function_type;
       
   415   function_call_param_iterator_c *tmp_function_call_param_iterator;
       
   416   if (st_symbol != NULL && il_symbol == NULL) {
       
   417     current_function_type = get_function_type((identifier_c *)st_symbol->function_name);
       
   418     tmp_function_call_param_iterator = new function_call_param_iterator_c(st_symbol);
       
   419   }
       
   420   else if (st_symbol == NULL && il_symbol != NULL) {
       
   421     current_function_type = get_function_type((identifier_c *)il_symbol->function_name);
       
   422     tmp_function_call_param_iterator = new function_call_param_iterator_c(il_symbol);
       
   423   }
       
   424   else
       
   425     ERROR;
       
   426   function_call_param_iterator_c function_call_param_iterator(*tmp_function_call_param_iterator);
       
   427   search_expression_type_c* search_expression_type = this;
       
   428 
       
   429   switch(current_function_type){
       
   430 """
       
   431 
       
   432 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   433     search_type_code += """
       
   434 /****
       
   435  *%s
       
   436  */
       
   437     case function_%s :
       
   438     {
       
   439         symbol_c *last_type_symbol = %s;
       
   440 """    %(fname, fname.lower(), get_default_input_type(fdecls))
       
   441     indent =  "    "
       
   442 
       
   443     search_type_code += recurse_and_indent(fdecls, indent, True).replace('\n','\n    ')
       
   444     
       
   445     search_type_code += """
       
   446     }/*function_%s*/
       
   447     break;
       
   448 """    %(fname.lower())
       
   449 search_type_code += """
       
   450     case function_none :
       
   451     ERROR;
       
   452   }
       
   453   return NULL;
       
   454 }
       
   455 
       
   456 void *search_expression_type_c::compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type) {
       
   457   
       
   458   function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
       
   459   function_call_param_iterator_c function_call_param_iterator(symbol);  
       
   460   search_expression_type_c* search_expression_type = this;
       
   461 
       
   462   switch(current_function_type){
       
   463 """
       
   464 
       
   465 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   466     search_type_code += """
       
   467 /****
       
   468  *%s
       
   469  */
       
   470     case function_%s :
       
   471     {
       
   472         symbol_c *last_type_symbol = %s;
       
   473 """    %(fname, fname.lower(), get_default_input_type(fdecls))
       
   474     indent =  "    "
       
   475 
       
   476     search_type_code += recurse_and_indent(fdecls, indent, True, True).replace('\n','\n    ')
       
   477     
       
   478     search_type_code += """
       
   479     }/*function_%s*/
       
   480     break;
       
   481 """    %(fname.lower())
       
   482 search_type_code += """
       
   483     case function_none :
       
   484     ERROR;
       
   485   }
       
   486   return NULL;
       
   487 }
       
   488 """
       
   489 
       
   490 ###################################################################
       
   491 ###################################################################
       
   492 ###################################################################
       
   493 """
       
   494 Generate the standard_function_names[] for inclusion in bizon generated code
       
   495 """
       
   496 standard_function_names = matiec_header + """
       
   497 const char *standard_function_names[] = {
       
   498 """
       
   499 for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   500     standard_function_names += "\""+fname+"\",\n"
       
   501 standard_function_names += """
       
   502 /* end of array marker! Do not remove! */
       
   503 NULL
       
   504 };
       
   505 
       
   506 """
       
   507 
       
   508 ###################################################################
       
   509 ###################################################################
       
   510 ###################################################################
       
   511 """
       
   512 Generate the C implementation of the IEC standard function library.
       
   513 """
       
   514 iec_std_lib_generated = matiec_lesser_header + """
       
   515 
       
   516 /* Macro that expand to subtypes */
       
   517 """
       
   518 for typename, parenttypename in TypeHierarchy_list:
       
   519     if (typename.startswith("ANY")):
       
   520         iec_std_lib_generated += "#define " + typename + "(DO)"
       
   521         for typename2, parenttypename2 in TypeHierarchy_list:
       
   522             if(parenttypename2 == typename):
       
   523                 if(typename2.startswith("ANY")):
       
   524                     iec_std_lib_generated +=  " " + typename2 + "(DO)"
       
   525                 else:
       
   526                     iec_std_lib_generated +=  " DO(" + typename2 + ")"
       
   527         iec_std_lib_generated +=  "\n"
       
   528     else:
       
   529         break
       
   530 
       
   531 # Now, print that out, or write to files from sys.argv
       
   532 for path, name, ext in file_list :
       
   533     fd = open(os.path.join(sys.argv[1], path, name+'.'+ext),'w')
       
   534     fd.write(eval(name))
       
   535     fd.close()
       
   536     
       
   537 #print "/* Code to eventually paste in iec_std_lib.h if type hierarchy changed */"
       
   538 #print "/* you also have to change iec_std_lib.h according to new types        */\n\n"
       
   539 #print iec_std_lib_generated