matiec 指针分析

178 阅读4分钟

image.png

错误的POUS.c
void PROGRAM0_init__(PROGRAM0 *data__, BOOL retain) {
  __INIT_VAR(data__->A,250,retain)
  __INIT_VAR(data__->PT,data__->A,retain)
}

// Code part
void PROGRAM0_body__(PROGRAM0 *data__) {
  // Initialise TEMP variables

  __SET_VAR(data__->,A,,520);

  goto __end;

__end:
  return;
} // PROGRAM0_body__() 

相关代码

普通变量的初始化
else if (this->current_var_init_symbol != NULL) {
    s4o.print(nv->get());
    s4o.print(INIT_VAR);
    s4o.print("(");
    this->print_variable_prefix();
    list->get_element(i)->accept(*this);
    s4o.print(",");
    this->current_var_init_symbol->accept(*this);
    print_retain();
    s4o.print(")");
}
symbol_c *current_var_type_symbol;
symbol_c *current_var_init_symbol;
void update_type_init(symbol_c *symbol /* a spec_init_c, subrange_spec_init_c, etc... */ ) {
  this->current_var_type_symbol = spec_init_sperator_c::get_spec(symbol);
  this->current_var_init_symbol = spec_init_sperator_c::get_init(symbol);
  if (NULL == this->current_var_type_symbol) ERROR;
  if (NULL == this->current_var_init_symbol) {
    /* We try to find the data type's default value... */
    this->current_var_init_symbol = type_initial_value_c::get(this->current_var_type_symbol);
  /* Note that Function Block 'data types' do not have a default value, so we cannot abort if no default value is found! */
  /*
  if (NULL == this->current_var_init_symbol)
    ERROR;
  */
  }
  /* When handling arrays we must make sure that we use the base datatype, since arrays use an aliased name in the C code!
   *   This is done using a stage4 annotation (on the base datatype class) named "generate_c_annotaton__implicit_type_id"
   *   Note that we do this only _after_ determining the initial value, since in principle the derived array could have
   *   a default initial different to the base array datatype!
   */
  if (NULL == this->current_var_type_symbol->datatype) {debug_c::print(this->current_var_type_symbol); ERROR;}
  if (get_datatype_info_c::is_array(this->current_var_type_symbol))
    this->current_var_type_symbol = this->current_var_type_symbol->datatype; 
  if (NULL == this->current_var_type_symbol) ERROR;      
}
symbol_c *spec_init_sperator_c::get_init(symbol_c *spec_init) {
   search_what = search_init;
   return (symbol_c *)spec_init->accept(*get_class_instance());
}
spec_init_sperator_c *spec_init_sperator_c::get_class_instance(void) {
  if (NULL == class_instance)
    class_instance = new spec_init_sperator_c();

  if (NULL == class_instance)
    ERROR;

  return class_instance;
}

void *visit(ref_expression_c *symbol) {
  s4o.print("(");  
  if (this->is_variable_prefix_null()) {  
    /* For code in FUNCTIONs */
    s4o.print("&(");  
    symbol->exp->accept(*this);    
    s4o.print(")");  
  } else {
    /* For code in FBs, and PROGRAMS... */
    s4o.print("(");  
    unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_);
    if (vartype == search_var_instance_decl_c::external_vt) {
      if (!get_datatype_info_c::is_type_valid    (symbol->exp->datatype)) ERROR;
      if ( get_datatype_info_c::is_function_block(symbol->exp->datatype))
        s4o.print(GET_EXTERNAL_FB_REF);
      else
        s4o.print(GET_EXTERNAL_REF);
    }
    else if (vartype == search_var_instance_decl_c::located_vt)
      s4o.print(GET_LOCATED_REF);
    else
      s4o.print(GET_VAR_REF);
    
    variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; 
    s4o.print("(");
    wanted_variablegeneration = complextype_base_vg;
    print_variable_prefix();
    symbol->exp->accept(*this);
    s4o.print(",");
    wanted_variablegeneration = complextype_suffix_vg;
    symbol->exp->accept(*this);
    s4o.print(")");
    wanted_variablegeneration = old_wanted_variablegeneration;
    
    s4o.print(")");  
  }
  s4o.print(")");  

  return NULL;
}
/* ref_type_decl: identifier ':' ref_spec_init */
// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
void *visit(ref_type_decl_c *symbol) {
  TRACE("ref_type_decl_c");

  /* NOTE  An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
   *       and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
   *       However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
   *       to the same identifier (e.g: __REF_TO_INT).
   *       In order for the C compiler not to find the same datatype being defined two or more times, 
   *       we will keep track of the datatypes that have already been declared, and henceforth
   *       only declare the datatypes that have not been previously defined.
   */
  identifier_c *tmp_id;
  tmp_id = dynamic_cast<identifier_c *>(symbol->ref_type_name);
  if (NULL == tmp_id) ERROR;
  if (datatypes_already_defined.find(tmp_id->value) != datatypes_already_defined.end())
    return NULL; // already defined. No need to define it again!!
  datatypes_already_defined[tmp_id->value] = 1; // insert this datatype into the list of already defined arrays!
  
  current_type_name = NULL;
  current_typedefinition = none_td;

  s4o_incl.print("__DECLARE_REFTO_TYPE(");
  symbol->ref_type_name->accept(*generate_c_typeid);
  s4o_incl.print(", ");
  symbol->ref_spec_init->accept(*this); // always calls ref_spec_init_c
  s4o_incl.print(")\n");

  current_type_name = NULL;
  current_typedefinition = none_td;

  return NULL;
}
ref_spec_init: /* defined in IEC 61131-3 v3 */
  ref_spec
	{$$ = new ref_spec_init_c($1, NULL, locloc(@$));}
/*  For the moment, we do not support initialising reference data types... */
| ref_spec ASSIGN ref_expression 
	{$$ = new ref_spec_init_c($1, $3, locloc(@$));}

;

ref_type_decl:  /* defined in IEC 61131-3 v3 */
/* PRE_PARSING or SINGLE_PHASE_PARSING */
/*  The following rules will be run either by:
 *      - the pre_parsing phase of two phase parsing (when preparsing command line option is chosen).
 *      - the standard single phase parser (when preparsing command line option is not chosen).
 */
  identifier ':' ref_spec_init  {library_element_symtable.insert($1, prev_declared_ref_type_name_token);}
	{if (!get_preparse_state()) $$ = new ref_type_decl_c($1, $3, locloc(@$));}
/* POST_PARSING */
/*  These rules will be run after the preparser phase of two phase parsing has finished (only gets to execute if preparsing command line option is chosen). */
| prev_declared_ref_type_name ':' ref_spec_init
	{$$ = new ref_type_decl_c(new identifier_c(((token_c *)$1)->value, locloc(@1)), $3, locloc(@$));}  // change the derived_datatype_identifier_c into an identifier_c, as it will be taking the place of an identifier!
;

ref_expression:
  REF '(' symbolic_variable ')'
	{$$ = new ref_expression_c($3, locloc(@$));}
;
/* Taken fron IEC 61131-3 v3
 * // Table 14 - Reference operations
 * Ref_Type_Decl  : Ref_Type_Name ':' Ref_Spec_Init ;
 * Ref_Spec_Init  : Ref_Spec ( ':=' Ref_Value )? ;
 * Ref_Spec       : 'REF_TO' Non_Gen_Type_Name ;
 * Ref_Type_Name  : Identifier ;
 * Ref_Name       : Identifier ;
 * Ref_Value      : Ref_Addr | 'NULL' ;
 * Ref_Addr       : 'REF' '(' (Symbolic_Variable | FB_Name | Class_Instance_Name ) ')' ;
 * Ref_Assign     : Ref_Name ':=' (Ref_Name | Ref_Deref | Ref_Value ) ;
 * Ref_Deref      : 'DREF' '(' Ref_Name ')' ;
 */
 
 /* REF_TO (non_generic_type_name | function_block_type_name) */
SYM_REF1(ref_spec_c, type_name)

/* ref_spec [ ASSIGN ref_initialization ]; */
/* NOTE: ref_initialization may be NULL!!  */
SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)

/* identifier ':' ref_spec_init */
SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
 
simple_spec_init:
  simple_specification
  /* The following commented line was changed to the 
   * next two lines so that we wouldn't
   * have the first element of a simple_spec_init_c()
   * pointing to another simple_spec_init_c!
   */
/*
| simple_specification ASSIGN constant
	{$$ = new simple_spec_init_c($1, $3);}
*/
| elementary_type_name ASSIGN constant
	{$$ = new simple_spec_init_c($1, $3, locloc(@$));}
| prev_declared_simple_type_name ASSIGN constant
	{$$ = new simple_spec_init_c($1, $3, locloc(@$));}
/* ERROR_CHECK_BEGIN */
| elementary_type_name constant
	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in specification with initialization."); yynerrs++;}
| prev_declared_simple_type_name constant
	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in specification with initialization."); yynerrs++;}
| elementary_type_name ASSIGN error
	{$$ = NULL;
	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in specification with initialization.");}
	 else {print_err_msg(locf(@3), locl(@3), "invalid initial value in specification with initialization."); yyclearin;}
	 yyerrok;
	}
| prev_declared_simple_type_name ASSIGN error
	{$$ = NULL;
	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in specification with initialization.");}
	 else {print_err_msg(locf(@3), locl(@3), "invalid initial value in specification with initialization."); yyclearin;}
	 yyerrok;
	}
/* ERROR_CHECK_END */
;
数组的初始化
/*  identifier ':' array_spec_init */
SYM_REF2(array_type_declaration_c, identifier, array_spec_init)

/* array_specification [ASSIGN array_initialization] */
/* array_initialization may be NULL ! */
SYM_REF2(array_spec_init_c, array_specification, array_initialization)


/* var1_list ':' array_spec_init */
SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
/*  var1_list ':' array_spec_init */
// SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
void *visit(array_var_init_decl_c *symbol) {
  TRACE("array_var_init_decl_c");
  /* Please read the comments inside the var1_init_decl_c
   * visitor, as they apply here too.
   */

  /* Start off by setting the current_var_type_symbol and
   * current_var_init_symbol private variables...
   */
  update_type_init(symbol->array_spec_init);

  /* now to produce the c equivalent... */
  if (wanted_varformat == constructorinit_vf) {
    generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o);
    array_initialization->set_variable_prefix(get_variable_prefix());
    array_initialization->init_array(symbol->var1_list, this->current_var_type_symbol, this->current_var_init_symbol);
    delete array_initialization;
  }
  else
    symbol->var1_list->accept(*this);

  /* Values no longer in scope, and therefore no longer used.
   * Make an effort to keep them set to NULL when not in use
   * in order to catch bugs as soon as possible...
   */
  void_type_init();

  return NULL;
}
void init_array(symbol_c *var1_list, symbol_c *array_specification, symbol_c *array_initialization) {
  int i;

  init_array_size(array_specification);

  s4o.print("\n");
  s4o.print(s4o.indent_spaces + "{\n");
  s4o.indent_right();
  s4o.print(s4o.indent_spaces);
  s4o.print("static const ");

  current_mode = typedecl_am;
  array_specification->accept(*this);
  s4o.print(" temp = ");

  init_array_values(array_initialization);

  s4o.print(";\n");
  var1_list->accept(*this);
  s4o.indent_left();
  s4o.print(s4o.indent_spaces + "}");
}
void init_array_values(symbol_c *array_initialization) {
  s4o.print("{{");

  current_mode = initializationvalue_am;
  array_initialization->accept(*this);

  if (array_default_initialization != NULL && defined_values_count < array_size)
    array_default_initialization->accept(*this);
  if (defined_values_count < array_size) {
    for (unsigned long long int i = defined_values_count; i < array_size; i++) {
      if (defined_values_count > 0)
        s4o.print(",");
      array_default_value->accept(*this);
      defined_values_count++;
    }
  }

  s4o.print("}}");
}
指针的初始化
/* ref_spec [ ASSIGN ref_initialization ]; */
/* NOTE: ref_initialization may be NULL!!  */
SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)

/* identifier ':' ref_spec_init */
SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)