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; }
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; }
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; }
void parse_macro(char* line){ uint8_t action, length, i, j = 0; if(memcmp(line,"[MACRO_",7)==0){ macro_idx = line[7] - '0' - 1; } else { ptr = line; j=0; while((token = strtok_r(ptr, ",", &rest)) != NULL) { ptr2 = token; i = length = action = 0; while((token2 = strtok_r(ptr2, ":", &rest2)) != NULL) { if(i==0){ length = atoi(token2); } else if(i == 1){ action = lookup_id(token2); } i++; ptr2 = rest2; } phex(action); phex(length); print("\n"); macro_steps[macro_idx][(j*2)] = action; macro_steps[macro_idx][(j*2)+1] = length; ptr = rest; j++; } macro_sizes[macro_idx] = j; //for(j=0;j<macro_sizes[macro_idx];){ // phex(j);phex(macro_steps[macro_idx][j++]); phex(macro_steps[macro_idx][j++]);print(" "); //} } }
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; }
struct scope_tree_node * traverse_identifier(struct node * n, struct scope_tree_node * parent_scope) { #ifdef DEBUG printf("traverse_identifier\n"); #endif lookup_id(n->data.identifier.name); return parent_scope; }
int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **ret) { int r; uint16_t id = GENL_ID_CTRL; if (family != SD_GENL_ID_CTRL) { r = lookup_id(nl, family, &id); if (r < 0) return r; } return genl_message_new(nl, family, id, cmd, ret); }
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; }
static int sfs_idbyname (const char *id, bool_t gid, dev_t dev) { struct id_cache *ic_elm; ic_elm = lookup_ic (dev); if (!ic_elm) return -1; return lookup_id (ic_elm, gid, (char *)id); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
static int post_cb(int op, int id, int subid, void *ex) { const char *idstr, *exstr = ""; char asctmp[20]; int keytype = -1; #ifdef FIPS_POST_TIME static struct timespec start, end, tstart, tend; #endif switch(id) { case FIPS_TEST_INTEGRITY: idstr = "Integrity"; break; case FIPS_TEST_DIGEST: idstr = "Digest"; exstr = lookup_id(subid); break; case FIPS_TEST_CIPHER: exstr = lookup_id(subid); idstr = "Cipher"; break; case FIPS_TEST_SIGNATURE: if (ex) { EVP_PKEY *pkey = ex; keytype = pkey->type; exstr = lookup_id(keytype); } idstr = "Signature"; break; case FIPS_TEST_HMAC: exstr = lookup_id(subid); idstr = "HMAC"; break; case FIPS_TEST_CMAC: idstr = "CMAC"; exstr = lookup_id(subid); break; case FIPS_TEST_GCM: idstr = "GCM"; break; case FIPS_TEST_XTS: idstr = "XTS"; exstr = lookup_id(subid); break; case FIPS_TEST_CCM: idstr = "CCM"; break; case FIPS_TEST_X931: idstr = "X9.31 PRNG"; sprintf(asctmp, "keylen=%d", subid); exstr = asctmp; break; case FIPS_TEST_DRBG: idstr = "DRBG"; if (*(int *)ex & DRBG_FLAG_CTR_USE_DF) { sprintf(asctmp, "%s DF", lookup_id(subid)); exstr = asctmp; } else exstr = lookup_id(subid); break; case FIPS_TEST_PAIRWISE: if (ex) { EVP_PKEY *pkey = ex; keytype = pkey->type; exstr = lookup_id(keytype); } idstr = "Pairwise Consistency"; break; case FIPS_TEST_CONTINUOUS: idstr = "Continuous PRNG"; break; default: idstr = "Unknown"; break; } switch(op) { case FIPS_POST_BEGIN: #ifdef FIPS_POST_TIME clock_getres(CLOCK_REALTIME, &tstart); printf("\tTimer resolution %ld s, %ld ns\n", (long)tstart.tv_sec, (long)tstart.tv_nsec); clock_gettime(CLOCK_REALTIME, &tstart); #endif printf("\tPOST started\n"); break; case FIPS_POST_END: printf("\tPOST %s\n", id ? "Success" : "Failed"); #ifdef FIPS_POST_TIME clock_gettime(CLOCK_REALTIME, &tend); printf("\t\tTook %f seconds\n", (double)((tend.tv_sec+tend.tv_nsec*1e-9) - (tstart.tv_sec+tstart.tv_nsec*1e-9))); #endif break; case FIPS_POST_STARTED: printf("\t\t%s %s test started\n", idstr, exstr); #ifdef FIPS_POST_TIME clock_gettime(CLOCK_REALTIME, &start); #endif break; case FIPS_POST_SUCCESS: printf("\t\t%s %s test OK\n", idstr, exstr); #ifdef FIPS_POST_TIME clock_gettime(CLOCK_REALTIME, &end); printf("\t\t\tTook %f seconds\n", (double)((end.tv_sec+end.tv_nsec*1e-9) - (start.tv_sec+start.tv_nsec*1e-9))); #endif break; case FIPS_POST_FAIL: printf("\t\t%s %s test FAILED!!\n", idstr, exstr); break; case FIPS_POST_CORRUPT: if (fail_id == id && (fail_key == -1 || fail_key == keytype) && (fail_sub == -1 || fail_sub == subid)) { printf("\t\t%s %s test failure induced\n", idstr, exstr); return 0; } break; } return 1; }
enum datatype resolve_datatype(struct ast* expr, struct ast* function){ if(expr == NULL){ return NONE; } switch(expr->type){ case ASSIGN: return resolve_datatype(expr->_assign.expr, function); break; case LITERAL: return expr->_literal.type; break; case IDENT: { struct lookup_result l = lookup_id(function, expr->_ident.name); if(l.ast != NULL && (l.ast->type == VARDEC || l.ast->type == PARAM)){ return resolve_decalaration_type(l.ast,function); }else{ return INVALID_DATATYPE; } } case CALL: { struct lookup_result l = lookup_id(function, expr->_ident.name); if(l.ast != NULL && l.ast->type == FUNCDEC){ return resolve_decalaration_type(l.ast,function); }else{ return INVALID_DATATYPE; } } break; case BINARY: { enum datatype lhs_type = resolve_datatype(expr->_binary.lhs, function); enum datatype rhs_type = resolve_datatype(expr->_binary.rhs, function); switch(expr->_binary.op){ case ADD: case SUB: case DIV: case MUL: switch(lhs_type){ case DOUBLE: switch(rhs_type){ case DOUBLE: return DOUBLE; case INT: return DOUBLE; default: return INVALID_DATATYPE; } break; case INT: switch(rhs_type){ case DOUBLE: return DOUBLE; case INT: return INT; default: return INVALID_DATATYPE; } break; default: return INVALID_DATATYPE; break; } break; case LE: case LT: case EQ: case NE: case GT: case GE: switch(lhs_type){ case DOUBLE: switch(rhs_type){ case DOUBLE: return INT; case INT: return INT; default: return INVALID_DATATYPE; } break; case INT: switch(rhs_type){ case DOUBLE: return INT; case INT: return INT; default: return INVALID_DATATYPE; } break; default: return INVALID_DATATYPE; break; } break; case MOD: switch(lhs_type){ case DOUBLE: switch(rhs_type){ case DOUBLE: return INVALID_DATATYPE; case INT: return INVALID_DATATYPE; default: return INVALID_DATATYPE; } break; case INT: switch(rhs_type){ case DOUBLE: return INVALID_DATATYPE; case INT: return INT; default: return INVALID_DATATYPE; } break; default: return INVALID_DATATYPE; break; } break; default: return INVALID_DATATYPE; } } break; case UNARY: { enum datatype operand = resolve_datatype(expr->_unary.operand, function); switch(expr->_unary.op){ case CHS: switch(operand){ case INT: return INT; case DOUBLE: return DOUBLE; default: return INVALID_DATATYPE; } break; case NOT: switch(operand){ case INT: return INT; case DOUBLE: return INVALID_DATATYPE; default: return INVALID_DATATYPE; } break; default: return INVALID_DATATYPE; } } break; case LIST: { struct ast* last = expr; while(last->_list.next != NULL){ last = last->_list.next; } return resolve_datatype(last->_list.item, function); } break; case IF: { enum datatype then_type = resolve_datatype(expr->_if.thenstmt, function); enum datatype else_type = then_type; if(expr->_if.elsestmt != NULL){ else_type = resolve_datatype(expr->_if.elsestmt, function); } switch(then_type){ case DOUBLE: switch(else_type){ case DOUBLE: return DOUBLE; case INT: return DOUBLE; case NONE: return NONE; default: return INVALID_DATATYPE; } break; case INT: switch(else_type){ case DOUBLE: return DOUBLE; case INT: return INT; case NONE: return NONE; default: return INVALID_DATATYPE; } break; case NONE: return NONE; break; default: return INVALID_DATATYPE; break; } } break; case WHILE: return NONE; break; default: return INVALID_DATATYPE; } }
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; }
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; }