Beispiel #1
0
resource_type make_resource(id_type id, const_type c)
{
   resource_type r = (resource_type) SafeMalloc(sizeof(resource_struct));
   id_type old_id;

   id->ownernum = st.curclass;

   /* Left-hand side must not have appeared before, except maybe in dbase */
   old_id = lookup_id(id);
   switch(id->type) {
   case I_UNDEFINED:
      id->source = COMPILE;
      add_identifier(id, I_RESOURCE);
      break;

   case I_RESOURCE:
      /* Allow redefinition of resources listed in database file */
      if (id->source == COMPILE)
	 action_error("Resource %s is defined twice", id->name);
      else
	 old_id->source = COMPILE;

      id->source = COMPILE;
      break;
      
   default:
      action_error("Duplicate identifier %s", id->name);
   }

   r->lhs = id;
   r->rhs = c;
   return r;
}
Beispiel #2
0
static void
parse_next_action(struct action_context *ctx)
{
    if (!ctx->n_tables) {
        action_error(ctx, "\"next\" action not allowed here.");
    } else if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
        int ltable;

        if (!action_get_int(ctx, &ltable)) {
            return;
        }
        if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
            action_syntax_error(ctx, "expecting `)'");
            return;
        }

        if (ltable >= ctx->n_tables) {
            action_error(ctx, "\"next\" argument must be in range 0 to %d.",
                         ctx->n_tables - 1);
            return;
        }

        emit_resubmit(ctx, ctx->first_ptable + ltable);
    } else {
        if (ctx->cur_ltable < ctx->n_tables) {
            emit_resubmit(ctx, ctx->first_ptable + ctx->cur_ltable + 1);
        } else {
            action_error(ctx, "\"next\" action not allowed in last table.");
        }
    }
}
Beispiel #3
0
expr_type make_expr_from_id(id_type id)
{
   expr_type e = (expr_type) SafeMalloc(sizeof(expr_struct));
   
   /* Id must be a parameter, local, property, constant, or resource */
   lookup_id(id);		
   switch(id->type)
   {
   case I_LOCAL:
   case I_PROPERTY:
   case I_CLASSVAR:
      e->type = E_IDENTIFIER;
      e->value.idval = id;
      break;

   case I_RESOURCE:
   {
      const_type c = (const_type) SafeMalloc(sizeof(const_struct));

      /* Turn resource id reference into the resource # itself */
      c->type = C_RESOURCE;
      c->value.numval = id->idnum; 

      e->type = E_CONSTANT;
      e->value.constval = c;
      return e;
   }

   case I_CONSTANT:
   {
      const_type c = (const_type) SafeMalloc(sizeof(const_struct));
      id_type temp;

      /* Turn constant id reference into the constant itself */
      c->type = C_NUMBER;

      temp = (id_type) list_find_item(st.constants, id, id_compare);
      c->value.numval = temp->source; /* Value is stored in source field */

      e->type = E_CONSTANT;
      e->value.constval = c;
      break;
   }
   case I_UNDEFINED:
   case I_MISSING:
      action_error("Unknown identifier %s", id->name);
      /* Put in something so that compilation can continue */
      e = make_expr_from_constant(make_nil_constant());
      break;

   default:
      action_error("Identifier %s in expression has wrong type", id->name);
      /* Put in something so that compilation can continue */
      e = make_expr_from_constant(make_nil_constant());
      break;
   }
   e->lineno = lineno;
   return e;
}
Beispiel #4
0
param_type make_parameter(id_type id, expr_type e)
{
   param_type p = (param_type) SafeMalloc(sizeof(param_struct));

   if (e->type != E_CONSTANT)
   {
      action_error("Parameter can only be initialized to a constant");
      return p;
   }

   lookup_id(id);

   /* Left-hand side must not have appeared before, except perhaps as a parameter */
   switch (id->type) {
   case I_MISSING:
      /* The parameter has been referenced in a function call, but not declared anywhere 
       * We should use the existent id # and remove the id from the missing list.
       * First we must make sure that the missing id is supposed to be a missing parameter.
       */
      if (id->source != I_PARAMETER)
      {
	 action_error("Parameter %s was referenced elsewhere with different type", id->name);
	 break;
      }
      
      /* Insert directly into global table to preserve id # */
      id->type = I_PARAMETER;
      id->source = COMPILE;
      table_insert(st.globalvars, (void *) id, id_hash, id_compare);

      /* Remove from missing list */
      table_delete_item(st.missingvars, id, id_hash, id_compare);
      break;

   case I_UNDEFINED:   /* New parameter # */
      id->ownernum = st.curmessage;
      add_identifier(id, I_PARAMETER);
      break;

   case I_PARAMETER:
      /* Legal only if it hasn't yet appeared in this message */
      if (id->ownernum == st.curmessage && id->source == COMPILE)
	 action_error("Parameter %s appears twice", id->name);
      break;

   default:            /* Other types indicate name already used */
      action_error("Duplicate identifier %s", id->name);
   }

   p->lhs = id;
   p->rhs = e->value.constval;
   return p;
}
Beispiel #5
0
const_type make_literal_message(id_type id)
{
   const_type c = (const_type) SafeMalloc(sizeof(const_struct));

   lookup_id(id);		
   switch (id->type)
   {
   case I_MESSAGE:
      break;

   case I_MISSING:
      if (id->source != I_MESSAGE)
	 action_error("Identifier %s was referenced earlier with different type", id->name);
      break;

   default: 
      add_identifier(id, I_MISSING);
      id->source = I_MESSAGE;
      break;     
   }
   /* Make a constant expression whose value is the id # */
   c->type = C_MESSAGE;
   c->value.numval = id->idnum; 

   return c;
}
Beispiel #6
0
const_type make_number_from_constant_id(id_type id)
{
   const_type c = (const_type) SafeMalloc(sizeof(const_struct));

   lookup_id(id);
   switch(id->type)
   {

   case I_CONSTANT:
      c->type = C_NUMBER;
      c->value.numval = id->source;  /* Value is stored in source field */
      break;

   case I_RESOURCE:
      /* Turn resource id reference into the resource # itself */
      c->type = C_RESOURCE;
      c->value.numval = id->idnum;       
      break;

   default:
      action_error("Identifier %s can only be a constant here", id->name);
      return NULL;      
   }
      
   return c;
}
Beispiel #7
0
message_handler_type make_message_handler(message_header_type header, char *comment,
					  list_type locals, list_type stmts)
{
   message_handler_type h = (message_handler_type) SafeMalloc(sizeof(message_handler_struct));
   stmt_type stmt;

   /* Last statement of body must be PROPAGATE or RETURN */
   stmt = (stmt_type) list_last_item(stmts);

   if (stmt == NULL || (stmt->type != S_RETURN && stmt->type != S_PROP)) 
      action_error("Last statement must be PROPAGATE or RETURN");
   
   h->header  = header;
   h->locals  = locals;
   h->body    = stmts;
   if (comment == NULL)
      h->comment = NULL;
   else h->comment = make_string_constant(comment);

   /* Clean out local variable table.  We must do this at the end of 
    * each handler, since in make_message_header we have already checked
    * parameters names against old variables, which includes parameters
    * from the current function in the local table.
    */
   table_delete(st.localvars);
   st.maxlocals = -1; /* So that first local is numbered 0 */

   return h;
}
Beispiel #8
0
static void
emit_ct(struct action_context *ctx, bool recirc_next, bool commit)
{
    struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
    ct->flags |= commit ? NX_CT_F_COMMIT : 0;

    /* If "recirc" is set, we automatically go to the next table. */
    if (recirc_next) {
        if (ctx->cur_ltable < ctx->n_tables) {
            ct->recirc_table = ctx->first_ptable + ctx->cur_ltable + 1;
        } else {
            action_error(ctx, "\"ct_next\" action not allowed in last table.");
            return;
        }
    } else {
        ct->recirc_table = NX_CT_RECIRC_NONE;
    }

    ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
    ct->zone_src.ofs = 0;
    ct->zone_src.n_bits = 16;

    /* We do not support ALGs yet. */
    ct->alg = 0;

    /* CT only works with IP, so set up a prerequisite. */
    struct expr *expr;
    char *error;

    expr = expr_parse_string("ip", ctx->symtab, &error);
    ovs_assert(!error);
    ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
}
Beispiel #9
0
int CompareParameters(void *param1, void *param2)
{
   param_type p1 = (param_type) param1;
   param_type p2 = (param_type) param2;
   if (p1->lhs->idnum == p2->lhs->idnum)
      action_error("Duplicate parameter %s!", p1->lhs->name);

   return (p1->lhs->idnum < p2->lhs->idnum);
}
Beispiel #10
0
classvar_type make_classvar(id_type id, expr_type e)
{
   classvar_type cv;

   cv = (classvar_type) SafeMalloc(sizeof(classvar_struct));

   if (e->type != E_CONSTANT)
   {
      action_error("Classvar can only be initialized to a constant");
      return cv;
   }

   lookup_id(id);
   switch(id->type) 
   {
   case I_CONSTANT:
   case I_PROPERTY:
      action_error("Duplicate identifier %s", id->name);
      break;
      
      /* Legal if it hasn't yet appeared in this class */
   case I_CLASSVAR:
      if (id->ownernum == st.curclass && id->source == COMPILE)
	 action_error("Class variable %s appears twice", id->name);
      else 
      {
	 id->ownernum = st.curclass;
	 id->source = COMPILE;
	 add_identifier(id, I_CLASSVAR);
      }
      break;

   default:
      id->source = COMPILE;
      id->ownernum = st.curclass;
      add_identifier(id, I_CLASSVAR);
      break;
   }

   cv->id = id;
   cv->rhs = e->value.constval;
   return cv;   
}
Beispiel #11
0
stmt_type make_for_stmt(id_type id, expr_type expr, list_type stmts)
{
   stmt_type stmt = (stmt_type) SafeMalloc(sizeof(stmt_struct));
   for_stmt_type s = (for_stmt_type) SafeMalloc(sizeof(for_stmt_struct));

   /* Loop variable must be a local, property or parameter */
   lookup_id(id);
   if (id->type == I_UNDEFINED || id->type == I_MISSING)
      action_error("Unknown identifier %s", id->name);
   else
      if (id->type != I_LOCAL && id->type != I_PROPERTY)
	 action_error("Loop variable %s has wrong type", id->name);

   s->id = id;
   s->condition = expr;
   s->body = stmts;

   stmt->type = S_FOR;
   stmt->value.for_stmt_val = s;
   return stmt;
}
Beispiel #12
0
stmt_type make_prop_stmt()
{
   stmt_type stmt = (stmt_type) SafeMalloc(sizeof(stmt_struct));
   list_type l;

   /* Find current class */
   for (l = st.classes; l != NULL; l = l->next)
      if (st.curclass == ((class_type) (l->data))->class_id->idnum)
	 break;
      
   if ( ((class_type) (l->data))->superclass == NULL)
      action_error("Can't PROPAGATE in a class with no superclass");
   stmt->type = S_PROP; 
   return stmt;
}
Beispiel #13
0
stmt_type make_assign_stmt(id_type id, expr_type expr)
{
   stmt_type stmt = (stmt_type) SafeMalloc(sizeof(stmt_struct));
   assign_stmt_type s = (assign_stmt_type) SafeMalloc(sizeof(assign_stmt_struct));

   /* Left-hand side must be a local or property */
   lookup_id(id);
   if (id->type == I_UNDEFINED || id->type == I_MISSING)
      action_error("Unknown identifier %s", id->name);
   else
      if (id->type != I_PROPERTY && id->type != I_LOCAL)
	 action_error("Identifier %s cannot be assigned to", id->name);

   /* Can't assign to SELF */
   if (id->type == I_PROPERTY && id->idnum == 0)
      action_error("Can't assign to self");

   s->lhs = id;
   s->rhs = expr;

   stmt->type = S_ASSIGN;
   stmt->value.assign_stmt_val = s;
   return stmt;
}
Beispiel #14
0
/* Parses an assignment or exchange action. */
static void
parse_set_action(struct action_context *ctx)
{
    struct expr *prereqs;
    char *error;

    error = expr_parse_assignment(ctx->lexer, ctx->symtab, ctx->ports,
                                  ctx->ofpacts, &prereqs);
    if (error) {
        action_error(ctx, "%s", error);
        free(error);
        return;
    }

    ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
}
Beispiel #15
0
id_type make_var(id_type id)
{
   /* Add to list of local variables, if it hasn't been defined */
   lookup_id(id);

   switch(id->type)
   {
   case I_LOCAL:
      action_error("Duplicate identifier %s", id->name);

   default:
      id->ownernum = st.curmessage;
      add_identifier(id, I_LOCAL);
      break;

   }
   return id;
}
Beispiel #16
0
void check_continue(void)
{
   if (loop_depth == 0)
      action_error("Continue statement must appear inside a loop");
}
Beispiel #17
0
void check_break(void)
{
   if (loop_depth == 0)
      action_error("Break statement must appear inside a loop");
}
Beispiel #18
0
property_type make_property(id_type id, expr_type e)
{
   property_type p = (property_type) SafeMalloc(sizeof(property_struct));

   if (e->type != E_CONSTANT)
   {
      action_error("Property can only be initialized to a constant");
      return p;
   }

   /* Left-hand side must not have appeared as a property before, except possibly as a
    * property of one of our superclasses.  Properties shadow other global names. */
   lookup_id(id);
   switch(id->type) {

   case I_CONSTANT:
      action_error("Duplicate identifier %s", id->name);
      break;
      
      /* Legal if it hasn't yet appeared in this class */
   case I_PROPERTY:
      if (id->ownernum == st.curclass && id->source == COMPILE)
	 action_error("Property %s appears twice", id->name);
      else 
      {
	 id->ownernum = st.curclass;
	 id->source = COMPILE;
	 add_identifier(id, I_PROPERTY);
      }
      break;

   case I_CLASSVAR:
      if (id->ownernum == st.curclass && id->source == COMPILE)
	 action_error("Property and classvar %s both appear in same class\n", id->name);
      else
      {
	 classvar_type new_cv;
	 id_type new_id;
	 const_type new_const;
	 
	 // Override classvar with special tag value
	 new_cv = (classvar_type) SafeMalloc(sizeof(classvar_struct));
	 new_const = (const_type) SafeMalloc(sizeof(const_struct));
	 new_id = duplicate_id(id);

	 new_cv->id = new_id;
	 new_cv->rhs = new_const;
	 new_id->ownernum = st.curclass;
	 new_id->source = COMPILE;
	 new_const->type = C_OVERRIDE;
	 
	 // Replace classvar with property in table
	 table_delete_item(st.classvars, id, id_hash, id_compare);
	 id->ownernum = st.curclass;
	 id->source = COMPILE;
	 add_identifier(id, I_PROPERTY);

	 // Store # of property in class var
	 new_const->value.numval = id->idnum;

	 st.override_classvars = list_add_item(st.override_classvars, new_cv);	 
      }
      break;

   default:
      id->source = COMPILE;
      id->ownernum = st.curclass;
      add_identifier(id, I_PROPERTY);
      break;
   }

   p->id = id;
   p->rhs = e->value.constval;
   return p;   
}
Beispiel #19
0
message_header_type make_message_header(id_type id, list_type args)
{
   message_header_type s = (message_header_type) SafeMalloc(sizeof(message_header_struct));
   id_type old_id, temp_id;
   param_type param;
   list_type l;

   /* Messsage name must be unique in this class, but may be the same
    * as a message in a different class. */
   old_id = lookup_id(id);

   switch (id->type) {
   case I_MISSING:
      /* The message has been referenced in a function call, but not declared anywhere.
       * We should use the existent message # and remove the id from the missing list 
       */
      if (id->source != I_MESSAGE)
      {
	 action_error("Message %s was referenced elsewhere with different type", id->name);
	 break;
      }

      /* Insert directly into global table to preserve id # */
      id->type = I_MESSAGE;
      id->ownernum = st.curclass;
      id->source = COMPILE;
      table_insert(st.globalvars, (void *) id, id_hash, id_compare);

      /* Remove from missing list */
      table_delete_item(st.missingvars, id, id_hash, id_compare);

      break;

   case I_UNDEFINED:   /* New message # */
      id->ownernum = st.curclass;
      add_identifier(id, I_MESSAGE);
      break;

   case I_MESSAGE:     /* Make sure message hasn't appeared in this class */
      if (id->ownernum == st.curclass && id->source == COMPILE)
	 action_error("Message handler %s defined twice in same class", id->name);
      old_id->ownernum = st.curclass;
      old_id->source = COMPILE;
      break;

   default:            /* Other types indicate name already used */
      action_error("Duplicate identifier %s", id->name);
   }

   s->message_id = id;
   /* Sort parameters in increasing id # order */
   s->params = SortParameterList(args);

   /* Add parameters as handler's local variables--this must be done AFTER sorting */
   for (l = s->params; l != NULL; l = l->next)
   {
      param = (param_type) l->data;
      
      /* Make a copy of the id for the local table */
      temp_id = duplicate_id(param->lhs);
      temp_id->type = I_LOCAL;

      if (table_insert(st.localvars, (void *) temp_id, id_hash, id_compare) == 0)
	 temp_id->idnum = ++st.maxlocals;      
   }

   st.curmessage = id->idnum;

   return s;
}
Beispiel #20
0
class_type make_class_signature(id_type class_id, id_type superclass_id)
{
   list_type l;
   id_type old_id;
   class_type c = (class_type) SafeMalloc(sizeof(class_struct));
   c->superclass = NULL;  /* Will be set for real below */

   c->class_id = class_id;

   /* Class name must not have appeared before */
   old_id = lookup_id(class_id);

   switch(class_id->type)
   {
   case I_MISSING:
      /* The class has been referenced in a function call, but not declared anywhere 
       * We should use the existent class # and remove the id from the missing list 
       */
      if (class_id->source != I_CLASS)
      {
	 action_error("Class %s was referenced elsewhere with different type", class_id->name);
	 break;
      }

      /* Insert directly into global table to preserve id # */
      class_id->type = I_CLASS;
      class_id->source = COMPILE;
      table_insert(st.globalvars, (void *) class_id, id_hash, id_compare);

      /* Remove from missing list */
      table_delete_item(st.missingvars, class_id, id_hash, id_compare);

      break;
      
   case I_UNDEFINED:
      /* New class name--continue normally */
      add_identifier(class_id, I_CLASS);
      break;

   case I_CLASS:
      /* We are recompiling a previously existing class.  This is rather ugly, since
       * we want to replace all the old class's data with our new data.  However, to give
       * previously compiled subclasses a chance of working with the new version, we
       * should try to match class numbers, message #s, etc. with the old class.
       *   At this point, all the old class's data have been inserted into our hash
       * tables.  The new class will be inserted into st.globalvars.  We must remove the old class 
       * from the class list.
       */

      /* If class is given twice in source files, that's an error */
      if (class_id->source == COMPILE)
	 action_error("Class %s is given twice", class_id->name);
      else 
	 /* Change the existent class id to reflect the fact that the class has now
	  * been recompiled. */
	 old_id->source = COMPILE;

      class_id->source = COMPILE;

      /* Delete self from list of existent classes.  Give warnings for subclasses. */
	 
      for (l = st.classes; l != NULL; l = l->next)
	 if (is_parent(c, (class_type) l->data))
	 {
	    if (((class_type) l->data)->class_id->idnum == c->class_id->idnum)
	       st.classes = list_delete_item(st.classes, l->data, class_compare);
	    else
	       /* Don't give warning if deleted self from list */
	    {
	       recompile_type recompile_info = 
		  (recompile_type) SafeMalloc(sizeof(recompile_struct));
	       recompile_info->class_id = ((class_type) (l->data))->class_id;
	       recompile_info->superclass = c->class_id;
	       
	       /* Only add to list if it isn't already there */
	       if (list_find_item(st.recompile_list, recompile_info->class_id, 
				  recompile_compare) == NULL)
		  st.recompile_list = list_add_item(st.recompile_list, (void *) recompile_info);
	    }
	    
	 }
      break;
      
   default:
      action_error("Duplicate identifier %s", class_id->name);
   }

   /* Delete this class from list of those that need to be recompiled */
   st.recompile_list = 
      list_delete_item(st.recompile_list, (void *) c->class_id, recompile_compare);

   c->resources  = NULL;
   c->properties = NULL;
   c->messages   = NULL;
   c->is_new = True; /* We should generate code for this class */

   /* Superclass must be defined, if one is given */
   if (superclass_id != NULL)
   {
      lookup_id(superclass_id);
      if (superclass_id->type != I_CLASS)
	 action_error("Can't find superclass %s", superclass_id->name);
      else if (class_id->idnum == superclass_id->idnum)
	 action_error("Can't subclass from self", superclass_id->name);	 
      else 
      {
	 /* Find superclass's data and store a pointer to it. */
	 for (l = st.classes; l != NULL; l = l->next)
	    if (superclass_id->idnum == ((class_type) (l->data))->class_id->idnum)
	    {
	       c->superclass = (class_type) l->data;
	       break;
	    }

	 if (c->superclass == NULL)
	    action_error("Unable to find superclass %s", superclass_id->name);
      }
      
   }
   else c->superclass = NULL;

   st.curclass = class_id->idnum;

   /* Now add superclasses' properties to our own property table, but delete
    * them from our property list.  This way the table will hold all properties 
    * that can be referenced in the class, but the property list will only 
    * hold those that were declared in this class (need to know this for code gen) */
   add_parent_properties(c, c->superclass);

   /* Similarly, add superclasses' classvars.  This must be done AFTER adding the properties,
    * since some properties in a superclass could be overriding classvars in a superclass */
   add_parent_classvars(NULL, c, c->superclass);

   /* Add to list of classes */
   st.classes = list_add_item(st.classes, (void *) c);

   return c;   
}
Beispiel #21
0
stmt_type make_call(id_type function_id, list_type args)
{
   stmt_type stmt = (stmt_type) SafeMalloc(sizeof(stmt_struct));
   call_stmt_type s = (call_stmt_type) SafeMalloc(sizeof(call_stmt_struct));
   int argnum = 0, argtype, continuation = ANONE, minargs = 0, i, index;
   const char *fname;
   arg_type arg;
   id_type id, new_id;

   s->args = NULL;

   /* Verify that id is the name of a built-in function */
   lookup_id(function_id);

   if (function_id->type != I_FUNCTION)
   {
      action_error("Expecting a function name; found %s", function_id->name);
      return stmt;
   }

   index = function_id->idnum;  /* index # of function to call */

   fname = Functions[index].name;
   s->function = Functions[index].opcode;
      
   /* Check that types of arguments match "function prototype" in table */
   for ( ; args != NULL; args = args->next)
   {
      argtype = Functions[index].params[argnum];

      /* See if we are looking for one or more expressions or parameters */
      if (continuation != ANONE)
	 argtype = continuation;

      arg = (arg_type) args->data;
      switch (argtype) 
      {
      case ANONE:
	 action_error("Extra argument #%d to function %s", argnum+1, fname);
	 return stmt; /* Ignore additional extra arguments */
	 break;

      case AEXPRESSIONS:
	 continuation = AEXPRESSION;
	 /* fall through */
      case AEXPRESSION:
	 /* Must have an expression here */
	 if (arg->type != ARG_EXPR)
	    action_error("Expecting expression in argument #%d",
			 argnum+1, fname);
	 else
	    s->args = list_add_item(s->args, (void *) arg);
	 break;

      case ASETTINGS:
	 continuation = ASETTING;
	 /* fall through */
      case ASETTING:
	 if (arg->type != ARG_SETTING)
	 {
	    action_error("Expecting setting (i.e. #a=b ) in argument #%d",
			 argnum+1, fname);
	    break;
	 }
	 
	 /* Find parameter id */
	 id = arg->value.setting_val->id;
	 lookup_id(id);
	 
	 switch(id->type)
	 {
	 case I_UNDEFINED:
	    /* If parameter hasn't been defined yet, put on missing list */
	    add_identifier(id, I_MISSING);

	    /* Use source field to indicate where id came from for later checking */
	    id->source = I_PARAMETER;

	    s->args = list_add_item(s->args, (void *) arg);
	    break;
	    
	 case I_MISSING:
	    if (id->source != I_PARAMETER)
	    {
	       action_error("Duplicate identifier %s", id->name);
	       break;
	    }
	    s->args = list_add_item(s->args, (void *) arg);
	    break;

	    /* The tag here should be I_PARAMETER, but parameters also inserted as locals.
	     */
	 case I_LOCAL: 
	    /* Unfortunately, we want the parameter id #, and not the local id #.  So
	     * we have to look up the id again in the global table. */
	    new_id = (id_type) table_lookup(st.globalvars, (void *) id, id_hash, id_compare);

	    /* If it isn't there, then there happens to be a local variable of the same
	     * name as this parameter, and the parameter hasn't appeared before.  Thus the
	     * parameter id should be added as a missing variable.  We can't use the normal
	     * lookup_id and add_identifier procs, since the local variable will mask
	     * the missing one.
	     */
	    if (new_id == NULL)
	    {
	       /* Of course, the id might already have been inserted as a missing var */
	       new_id = (id_type) table_lookup(st.missingvars, (void *) id, id_hash, id_compare);
	       if (new_id == NULL)
	       {
		  id->source = I_PARAMETER;
		  id->type = I_MISSING;
		  id->idnum = ++st.maxid;
		  table_insert(st.missingvars, (void *) id, id_hash, id_compare);
	       }
	       else 
	       {
		  /* If it was already there, make sure that it was a parameter */
		  if (new_id->source != I_PARAMETER)
		     action_error("Duplicate identifier %s", id->name);
		  id->source = new_id->source;
		  id->type = I_MISSING;
		  id->source = I_PARAMETER;
		  id->idnum = new_id->idnum;
	       }
	       
	    }
	    else 
	    {
	       id = new_id;
	       if (id->type != I_PARAMETER)
		  action_error("Can't find parameter %s", id->name);
	    }

	    arg->value.setting_val->id = id;
	    /* If literal exists, proceed normally */
	    s->args = list_add_item(s->args, (void *) arg);
	    break;

	    /* But if the identifier is from another handler, might not be local */
	 case I_PARAMETER:
	    s->args = list_add_item(s->args, (void *) arg);
	    break;

	 default:
	    action_error("Literal %s is a duplicate identifier", id->name);
	 }
	 break;
      }
      
      argnum++;
   }
   /* Check that no arguments left out */
   for (i=0; i < MAXARGS; i++)
   {
      argtype = Functions[index].params[i];
      if (argtype == ANONE || argtype == ASETTINGS || argtype == AEXPRESSIONS)
	 break; /* Zero or more arguments follow */
      
      minargs++;
   }
   if (argnum < minargs)
      action_error("Expecting %d arguments to %s; found %d", minargs, fname, argnum);

   /* Sort parameter arguments in increasing order for server efficiency */
   s->args = SortArgumentList(s->args);

   stmt->type = S_CALL;
   stmt->value.call_stmt_val = s;
   return stmt;
}
Beispiel #22
0
/*
 * SimplifyExpression:  Attempt to simplify given expression.  Modifies e.
 */
void SimplifyExpression(expr_type e)
{
   expr_type e1, e2;
   const_type c1, c2;

   switch (e->type)
   {
   case E_UNARY_OP:
      e1 = e->value.unary_opval.exp;
      if (e1->type != E_CONSTANT)
    break;

      c1 = e1->value.constval;
      if (c1->type != C_NUMBER)
         break;

      switch (e->value.unary_opval.op)
      {
      case NEG_OP:
         c1->value.numval = -c1->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case NOT_OP:
         c1->value.numval = !c1->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case BITNOT_OP:
         c1->value.numval = ~c1->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case PRE_INC_OP:
         c1->value.numval = ++c1->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case PRE_DEC_OP:
         c1->value.numval = --c1->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;
      }
      break;

   case E_BINARY_OP:
      e1 = e->value.binary_opval.left_exp;
      e2 = e->value.binary_opval.right_exp;
      if (e1->type != E_CONSTANT || e2->type != E_CONSTANT)
         break;

      c1 = e1->value.constval;
      c2 = e2->value.constval;

      if (c1->type != C_NUMBER || c2->type != C_NUMBER)
         break;

      switch (e->value.binary_opval.op)
      {
      case PLUS_OP:
         c1->value.numval = c1->value.numval + c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case MINUS_OP:
         c1->value.numval = c1->value.numval - c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case AND_OP:
         c1->value.numval = c1->value.numval && c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case OR_OP:
         c1->value.numval = c1->value.numval || c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case MULT_OP:
         c1->value.numval = c1->value.numval * c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case DIV_OP:
         if (c2->value.numval == 0)
         {
            action_error("Division by zero");
            break;
         }
         c1->value.numval = c1->value.numval / c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case MOD_OP:
         if (c2->value.numval == 0)
         {
            action_error("Division by zero");
            break;
         }
         c1->value.numval = c1->value.numval % c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case BITAND_OP:
         c1->value.numval = c1->value.numval & c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;

      case BITOR_OP:
         c1->value.numval = c1->value.numval | c2->value.numval;
         e->type = E_CONSTANT;
         e->value.constval = c1;
         break;
      }
      break;
   }
}
Beispiel #23
0
id_type make_constant_id(id_type id, expr_type expr)
{
   int numeric_val;

   /* Right hand side must be a number or a negative number */
   switch (expr->type)
   {
   case E_CONSTANT:
   {
      const_type c = (const_type) expr->value.constval;
      if (c->type == C_NUMBER)
	 numeric_val = c->value.numval;
      else action_error("Right hand side must be a numeric constant");
      break;
   }
   case E_UNARY_OP:
   {
      const_type c;
      expr_type sub_expr = expr->value.unary_opval.exp;
      int op = expr->value.unary_opval.op;
      
      if (op != NEG_OP || sub_expr->type != E_CONSTANT)
      {
         action_error("Right hand side must be a numeric constant");
         break;
      }
      
      c = (const_type) sub_expr->value.constval;
      if (c->type == C_NUMBER)
         numeric_val = - c->value.numval;
      else action_error("Right hand side must be a numeric constant");
      break;
   }
   default:
      action_error("Right hand side must be a numeric constant");
   }
   

   lookup_id(id);

   /* Left hand side cannot have appeared before */
   switch (id->type)
   {
   case I_UNDEFINED:
      id->ownernum = st.curclass;
      /* Store value in source field.  This is kind of a hack, but now we can 
	 insert just the id in st.constants, making it easy to find later. */
      id->source = numeric_val;
      add_identifier(id, I_CONSTANT);
      break;
      
   default:
      action_error("Duplicate identifier %s", id->name);
      break;
   }

   /* Add to list of constants in this class */
   st.constants = list_add_item(st.constants, id);
   
   return id;
}