示例#1
0
/*
* RscAddCallback:  Called for each new resource that's loaded from a file.
*   Add given resource to table.
*/
bool RscAddCallback(char *fname, int res, int lang_id, char *string)
{
   resource_type r;

   // Check for existing resource first, since we might want to add
   // another language string to it.
   r = (resource_type) table_lookup(t, &res, IdHash, IdResourceCompare);
   if (r == NULL)
   {
      r = (resource_type) SafeMalloc(sizeof(resource_struct));
      r->idnum = res;

      for (int i = 0; i < MAX_LANGUAGE_ID; i++)
         r->resource[i] = NULL;
   }
   else
      table_delete_item(t, r, ResourceHash, ResourceCompare);

   // Shouldn't be able to compile blakod with multiple strings
   // of the same language type.
   if (r->resource[lang_id])
      SafeFree(r->resource[lang_id]);
   r->resource[lang_id] = (char *) SafeMalloc(strlen(string) + 1);
   strcpy(r->resource[lang_id], string);

   available_languages[lang_id] = True;

   // Replace the existing resource if we used it.
   table_insert(t, r, ResourceHash, ResourceCompare);

   return true;
}
示例#2
0
/*
* RscAddCallback:  Called for each new resource that's loaded from a file.
*   Add given resource to table.
*/
bool RscAddCallback(char *fname, int res, char *string)
{
	resource_type entry, r;
	
	entry = (resource_type) SafeMalloc(sizeof(resource_struct));
	
	entry->idnum = res;
	entry->data = (char *) SafeMalloc(strlen(string) + 1);
	strcpy(entry->data, string);
	
	if (table_insert(t, entry, ResourceHash, ResourceCompare) != 0)
	{
		if (!ignore_duplicates)
		{
			ClientError(hInst, hMain, IDS_DUPRESOURCE, res, fname);
			FreeRsc(entry);
		}
		else
		{
			// Free existing resource
			r = (resource_type) table_lookup(t, &res, IdHash, IdResourceCompare);
			if (r != NULL)
			{
				table_delete_item(t, r, ResourceHash, ResourceCompare);
				FreeRsc(r);
				table_insert(t, entry, ResourceHash, ResourceCompare);
			}
		}
	}
	
	return true;
}
示例#3
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;
}
示例#4
0
void ChangeResource(ID res, char *value)
{
	resource_type r, entry;
	
	//   debug(("got new resource %d, type = %d, value = %s\n", res, type, value));
	r = (resource_type) table_lookup(t, &res, IdHash, IdResourceCompare);
	if (r != NULL)
	{
		table_delete_item(t, r, ResourceHash, ResourceCompare);
		FreeRsc(r);
	}
	
	entry = (resource_type) SafeMalloc(sizeof(resource_struct));
	
	entry->data = (char *) SafeMalloc(strlen(value) + 1);
	strcpy(entry->data, value);
	entry->idnum = res;
	table_insert(t, entry, ResourceHash, ResourceCompare);
}
示例#5
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;   
}
示例#6
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;   
}
示例#7
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;
}