/* Perform quasi-semantic checking of a spec. * * TODO ITEMS: * * * Check that signatures defined in the operations field of an object * agree with the inputs and outputs in the corresponding operation * definitions. In more detail, do this when type checking is done. * Check to make sure each name in the var name list is a member * of the parts list. Match each name with the parm in the operation. * Can classes needing specialization call or be called? * * Do the instance checks described at the end of the ChkObj and ChkOp * functions below. * * Perform full type checking on the predicates in pre/post conds and * equations. */ #include "std-macros.h" #include "parse-tree.h" #include "sym.h" #include "parser.h" #include "tokens.h" #include "sym-aux.h" #include "chkspec.h" #include "lex.h" #include "token-mapping.h" #include extern int yylineno; /* * Top-level check is recursive descent of parse tree for each module. */ void ChkSpec() { SymtabEntry *e; Symtab *Tab; int i; void ChkSpecModule(Symtab *tab); MoveToSymtab(Level0Symtab); Tab = CurSymtab; for (i=0; iSize; i++) { for (e=Tab->Entries[i]; e; e=e->Next) { if (e->Class == C_Module) { PushSymtab(); MoveToSymtab(e->Info.Module.Symtab); ChkSpecModule(e->Info.Module.Symtab); PopSymtab(); } } } } /* * Check all the entities in a spec module. Since nested modules are not * allowed, no recursing will happen. */ void ChkSpecModule(Symtab *tab) { nodep t, n; void ChkObj(nodep t); void ChkOp(nodep t); t = tab->Tree; printf("Checking module %s\n", t->components.module.name->components.atom.val.text); n = t->components.module.body; /* * Cruises the parse tree entities list. */ for (n=t->components.module.body->components.spec.entities; n; n=n->components.decl.next) { switch (n->header.name) { case YOBJ: printf("Checking object %s\n", n->components.decl.kind.obj.name-> components.atom.val.text); ChkObj(n); break; case YOP: printf("Checking operation %s\n", n->components.decl.kind.op.name-> components.atom.val.text); ChkOp(n); break; } } } void ChkObj(nodep t) { nodep n,n1, opsigIn, opsigOut, opsigName, In, Out, InName, OutName, name; nodep parent, speclpart, newnd, part; SymtabEntry *sym, *sym1; bool found = false; nodep MakeSpecialList(nodep t); nodep ConcatAtomLists(nodep l1, nodep l2); /* void Inherit(TypeStruct type, nodep parents, SymClasses class); */ SymtabEntry* MakeRecord(nodep t,TokenType type,SymClasses class, nodep typenode,int line); void ResetList(); /* * Get its symtab entry. */ sym = LookupString(t->components.decl.kind.obj.name-> components.atom.val.text); /* * Help out the browser. */ BrowserEnter(sym); /* To prevent recursive type checking */ sym->Flags |= beenChecked; /* * Make the list of parts requiring specialization */ /* Seems not to work (at all?): * sym->Info.Obj.speclreq = MakeSpecialList(sym->Info.Obj.speclreq); */ sym->Info.Obj.speclreq = null; /* * If the object is not a class and there are parts needing specialization * then it is an error */ if (!(sym->Flags & isClass) && (sym->Info.Obj.speclreq)) error(" Parts requiring specialization illegal in non-class objects\n"); /* * Inherit parts from parents * NUKED 8sep92. */ /* if (sym->Info.Obj.instanceof) Inherit(sym->Type, sym->Info.Obj.instanceof,sym->Class); */ /* * n will point to an uninitialized symbol table. n1 will point to the * parts parse tree. */ n = sym->Type; n1 = sym->Info.Obj.parts; /* object defs do not have a parts parse tree so n1 is null hence the if.*/ if (n1) n->header.name = n1->header.name; /* * CurSymtab needs to point to the uninitialized parts symbol table * NOT -- changed but will soon be nuked. */ NewLevel(sym, 128, null, YOBJ); /* * Enter parts into parts symbol table. InitList will contain a list * of SymtabEntrys that have an initial value. */ sym->Info.Obj.InitList = MakeRecord(n1, null, C_Obj, n, sym->Loc.line); ResetList(); PopSymtab(); LeaveLevel(); /* If the object is both an instance and a class then each part is * checked to see if it specializes a part in one or more parents. */ if ((sym->Flags & isClass) && (sym->Flags & isInstance)) { for (parent = sym->Info.Obj.inheritsfrom; parent; parent = parent->components.atom.next) { /* check if parent is defined */ if (!(sym1 = LookupString(parent->components.atom.val.text))) error(" Class %s not defined\n", parent->components.atom.val.text); else { /* check if parent is an object */ if (sym1->Class != C_Obj) error(" Class %s is not an object\n", parent->components.atom.val.text); /* check if parent is a class */ if (!(sym1->Flags & isClass)) error(" Parent %s is not a class\n", parent->components.atom.val.text); else { /* * parent is defined and is an object so compare each part * requiring specialization in parent to those in child to see * if there is one that specializes a parent part. Those that * are not specialized are added to speclreq list of child. */ for (speclpart = sym1->Info.Obj.speclreq; speclpart; speclpart = speclpart->components.atom.next) { /* child's parts list */ part = sym->Info.Obj.namelist; /* do comparison */ while (!found && part) { if (!strcmp(part->components.atom.val.text, speclpart->components.atom.val.text)) found = true; part = part->components.atom.next; } /* * part is not specialized so a copy is added to child's * list of unspecialized parts */ if (!found) { newnd = NewNode(ATOM_NODE, Yident, EmptyLoc); bcopy( speclpart, newnd, sizeof(struct node)); newnd->components.atom.next = null; sym->Info.Obj.speclreq = ConcatAtomLists(sym->Info.Obj.speclreq, newnd); } found = false; } } } } } /* * TODO: * If the object is an instance, and not itself a class, * then check to see that it specializes all * of the parent class(es)' parts that require specialization. Parts that * require specialization are those of the form "Name:". */ if (!(sym->Flags & isClass) && (sym->Flags & isInstance) && (sym->Info.Obj.speclreq)) error(" Not all parts requiring specialization have been specialized\n"); /* * If the object is an instance but not an class then make sure all * parts requiring specialization are specialized. Look up each parent, * make sure it is an object, then make sure each part in its speclreq * list has been specialized by the instance. */ if ((sym->Flags & isInstance) && (!(sym->Flags & isClass))) { for (parent = sym->Info.Obj.inheritsfrom; parent; parent = parent->components.atom.next) { if (!(sym1 = LookupString(parent->components.atom.val.text))) error(" Class %s not defined\n", parent->components.atom.val.text); else { if (sym1->Class != C_Obj) error(" Class %s is not an object\n", parent->components.atom.val.text); /* check if parent is a class */ if (!(sym1->Flags & isClass)) error(" Parent %s is not a class\n", parent->components.atom.val.text); else { for (speclpart = sym1->Info.Obj.speclreq; speclpart; speclpart = speclpart->components.atom.next) { name = sym->Info.Obj.namelist; while (!found && name) { if (!strcmp(name->components.atom.val.text, speclpart->components.atom.val.text)) found = true; name = name->components.atom.next; } if (!found) { error(" Specialization of %s from parent %s needed\n", speclpart->components.atom.val.text, parent->components.atom.val.text); } found = false; } } } } } } void ChkOp(nodep t) { nodep n, n1, n2, name; nodep parent, speclpart; SymtabEntry *sym, *sym1; bool found; SymtabEntry* MakeRecord(nodep t,TokenType type,SymClasses class, nodep typenode,int line); SymtabEntry* MakeInsRecord(nodep t, int line, char *InOrOut); void ResetList(); /* * Get its symtab entry. */ sym = LookupString(t->components.decl.kind.op.name-> components.atom.val.text); /* * Help out the browser. */ BrowserEnter(sym); /* To prevent recursive type checking and printing */ sym->Flags |= beenChecked; /* * Enter parts, inputs and outputs into their symbol tables. */ n = sym->Type; n1 = sym->Info.Op.outstree; if (n1) n->header.name = n1->header.name; NewLevel(sym, 128, null, YOP); sym->Info.Op.OutsInitList = MakeInsRecord(n1, null, "Output"); n = sym->Info.Op.ins; n1 = sym->Info.Op.instree; if (n1) n->header.name = n1->header.name; sym->Info.Op.InsInitList = MakeInsRecord(n1, null, "Input"); n = sym->Info.Op.parts; n1 = sym->Info.Op.partstree; if (n1) n->header.name = n1->header.name; sym->Info.Op.InitList = MakeRecord(n1, null, C_Op, n, sym->Loc.line); ResetList(); LeaveLevel(); /* * Check that all the referenced ins and outs are defined. */ /* for (n=t->components.decl.kind.op.ins; n; n=n->components.decl.next) { n1 = n->components.decl.kind.initdecl.decl; n2 = n1->components.decl.kind.attr.name; if (!(sym1 = LookupString(n2->components.atom.val.text))) error(" Input %s not defined\n", n2->components.atom.val.text); } for (n=t->components.decl.kind.op.outs; n; n=n->components.decl.next) { n1 = n->components.decl.kind.initdecl.decl; n2 = n1->components.decl.kind.attr.name; if (!(sym1 = LookupString(n2->components.atom.val.text))) error(" Output %s not defined\n", n2->components.atom.val.text); } */ /* * TODO: * If the object is an instance, then check to see that it specializes all * of the parent class(es)' parts that require specialization. Parts that * require specialization are those of the form "Name:". */ if ((sym->Flags & isInstance) && (!(sym->Flags & isClass))) { for (parent = sym->Info.Op.inheritsfrom; parent; parent = parent->components.atom.next) { if (!(sym1 = LookupString(parent->components.atom.val.text))) error(" Class %s not defined\n", parent->components.atom.val.text); else { if ((sym1->Class != C_Op) /* and (not streq(sym1->Symbol, "none")) and (not streq(sym1->Symbol, "empty")) */ ) error(" Class %s is not an operation\n", parent->components.atom.val.text); /* check if parent is a class */ if (!(sym1->Flags & isClass)) error(" Parent %s is not a class\n", parent->components.atom.val.text); else { for (speclpart = sym1->Info.Op.speclreq; speclpart; speclpart = speclpart->components.atom.next) { name = sym->Info.Op.namelist; while (!found && name) { if (!strcmp(name->components.atom.val.text, speclpart->components.atom.val.text)) found = true; name = name->components.atom.next; } if (!found) { error(" Specialization of %s from parent %s needed\n", speclpart->components.atom.val.text, parent->components.atom.val.text); } found = false; } } } } } } /* * Check that the ender name in a def matches the declared name. */ void ChkEnder(nodep n1, nodep n2) { SrcLoc loc; nodep newnd; if (!n2 or !streq(n1->components.atom.val.text, n2->components.atom.val.text)) { newnd = NewNode(null, null, CurSrcLoc()); lwarn(newnd, "End name does not match name declared on line %d.\n", n1->header.loc.line); } } /* * Add a top-level entity decl to the list of entities in Main It's done * this way rather than incrementally so that forw refs in components wont * all show up as undeclared. */ static nodep ChkListHead, ChkListTail; void AddToChkList(nodep t) { if (!ChkListHead) { t->components.decl.next = null; ChkListHead = ChkListTail = t; } else { ChkListTail->components.decl.next = t; ChkListTail = t; } } /* * Check the list of top-level decls, if any. Remember, these are all in the * Main symtab. */ void ChkList() { nodep n; void ChkObj(nodep t); /* * Move to the proper context of Main. */ MoveToSymtab(MainSymtab); /* * Cruise the list. */ for (n=ChkListHead; n; n=n->components.decl.next) { switch (n->header.name) { case YOBJ: printf("Checking object %s\n", n->components.decl.kind.obj.name-> components.atom.val.text); ChkObj(n); break; case YOP: printf("Checking operation %s\n", n->components.decl.kind.op.name-> components.atom.val.text); ChkOp(n); break; } } } /* * Some init. */ void InitMainChkList() { ChkListHead = ChkListTail = null; } /* * Let who want to know the size of the main check list. */ bool IsMainListEmpty() { return ChkListHead ? true : false; } /* * The following is old crap from Greg's versions of sym.c and sym-aux.c that * must soon go. It's here now so we can compile. */ static SymtabEntry *head; #define PARTSIZE 32 #define TEMPSIZE 32 #define structPart 0x10 #define unionPart 0x40 /* An ORed component */ #define listPart 0x20 /* A list object */ #define used 0x01 /* On if a symbol ever gets used */ void InitList() { head = AllocSymtabEntry(null,null,null,null); } SymtabEntry* MakeRecord(nodep t,TokenType type,SymClasses class, nodep typenode,int line) { struct Sym *sym; nodep t1; char *n, *v; nodep NewPartLevel (SymtabEntry *Entry, TokenType type, int Size); SymtabEntry *MakeEntry(nodep t, SymClasses class, int line); if (!t) return head; switch(t->header.kind) { case BINOP_NODE: switch (t->header.name) { case YAND: switch (type) { case YAND: MakeRecord(t->components.binop.left_operand,YAND,class,typenode,line); MakeRecord(t->components.binop.right_operand,YAND,class,typenode,line); return head; break; case YOR: n = xitoa((CurSymtab->Mask)+1); n--; *n = 'p'; SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); sym->Loc.line = line; PushSymtab(); typenode = NewPartLevel(sym, YAND, PARTSIZE); MakeRecord(t->components.binop.left_operand,YAND,class,typenode,line); MakeRecord(t->components.binop.right_operand,YAND,class,typenode,line); PopSymtab(); return head; break; default: MakeRecord(t->components.binop.left_operand,YAND,class,typenode,line); MakeRecord(t->components.binop.right_operand,YAND,class,typenode,line); return head; break; } break; case YOR: switch (type) { case YAND: case YOR: MakeRecord(t->components.binop.left_operand,YOR,class,typenode,line); MakeRecord(t->components.binop.right_operand,YOR,class,typenode,line); return head; break; /* case null: n = xitoa((CurSymtab->Mask)+1); printf("n is %s\n",n); n--; *n = 'p'; printf("n is now %s\n",n); SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); PushSymtab(); typenode = NewPartLevel(sym, YOR, PARTSIZE); MakeRecord(t->components.binop.left_operand, YOR, class,typenode); MakeRecord(t->components.binop.right_operand,YOR, class,typenode); PopSymtab(); break; */ default: MakeRecord(t->components.binop.left_operand,YOR,class,typenode,line); MakeRecord(t->components.binop.right_operand,YOR,class,typenode,line); return head; break; } break; case '(': t1 = t->components.binop.left_operand; n = t1->components.atom.val.text; SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); sym->Loc.line = line; PushSymtab(); t1 = t->components.binop.right_operand; typenode = NewPartLevel(sym, t1->header.name, PARTSIZE); MakeRecord(t->components.binop.right_operand,'(',class,typenode,line); PopSymtab(); return head; break; } break; case UNOP_NODE: switch (t->header.name) { case YLIST: switch (type) { case YLIST: /* n = xitoa((CurSymtab->Mask)+1); n--; *n = 'p'; SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); PushSymtab(); NewPartLevel(sym, YLIST, PARTSIZE); */ (typenode->components.type.kind.parts.dimensions)++; (typenode->components.type.kind.parts.references)++; MakeRecord(t->components.unop.operand, YLIST, class,typenode,line); return head; /* PopSymtab(); */ break; default: (typenode->components.type.kind.parts.dimensions)++; (typenode->components.type.kind.parts.references)++; MakeRecord(t->components.unop.operand, YLIST, class,typenode,line); return head; break; } break; case '(': switch (type) { case YLIST: n = xitoa((CurSymtab->Mask)+1); n--; *n = 'p'; SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); sym->Loc.line = line; PushSymtab(); t1 = t->components.unop.operand; typenode = NewPartLevel(sym, t1->header.name, PARTSIZE); MakeRecord(t->components.unop.operand, '(', class,typenode,line); PopSymtab(); return head; break; default: n = xitoa((CurSymtab->Mask)+1); n--; *n = 'p'; SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); sym->Loc.line = line; PushSymtab(); t1 = t->components.unop.operand; typenode = NewPartLevel(sym, t1->header.name, PARTSIZE); MakeRecord(t->components.unop.operand, '(', class,typenode,line); PopSymtab(); return head; break; } } break; case DECL_NODE: sym = MakeEntry(t, class,line); if (sym) { sym->Chain = head->Chain; head->Chain = sym; } return head; case ATOM_NODE: sym = LookupThisScope(t->components.atom.val.text); switch (type) { case YAND: sym->Flags = structPart; break; case YOR: sym->Flags = unionPart; break; case YLIST: sym->Flags = listPart; } return head; } } /* * Make an entry for an input or output object. The only place this function * is called from is MakeInsRecord, which handles both input and output lists. */ SymtabEntry* MakeOpEntry(nodep t, int line, char *InOrOut) { nodep initValue; struct Sym *sym; char *n; initValue = t->components.decl.kind.initdecl.init; t = t->components.decl.kind.initdecl.decl; if (t->components.decl.kind.attr.value) { n = t->components.decl.kind.attr.name->components.atom.val.text; PushSymtab(); sym= CurSymtab->ParentEntry; while (sym->Class != C_Op) { sym = CurSymtab->ParentEntry; CurSymtab = CurSymtab->ParentTab; } if (!(sym = LookupString(t->components.decl.kind.attr.value-> components.atom.val.text))) { /* error(" Object %s not defined\n", n); */ error(" %s %s not defined\n", InOrOut, t->components.decl.kind.attr.value-> components.atom.val.text); PopSymtab(); return null; } else if (sym->Class != C_Obj) { error(" %s %s is not an object\n", InOrOut, n); PopSymtab(); return null; } else { PopSymtab(); SeqEnter(sym = AllocSymtabEntry(n, C_Name, sym->Type, CurSymtab->Level+1)); sym->Loc.line = line; sym->Info.Parm.initValue = initValue; return sym; } } else { n = t->components.decl.kind.attr.name->components.atom.val.text; PushSymtab(); sym= CurSymtab->ParentEntry; while (sym->Class != C_Op) { sym = CurSymtab->ParentEntry; CurSymtab = CurSymtab->ParentTab; } if (!(sym = LookupString(n))) { error(" %s %s not defined\n", InOrOut, n); PopSymtab(); return null; } else if (sym->Class != C_Obj) { error(" %s %s is not an object\n", InOrOut, n); PopSymtab(); return null; } else { PopSymtab(); SeqEnter(sym = AllocSymtabEntry(n, C_Name, sym->Type, CurSymtab->Level+1)); sym->Loc.line = line; sym->Info.Parm.initValue = initValue; return sym; } } } SymtabEntry* MakeInsRecord(nodep t, int line, char *InOrOut) { struct Sym *sym; nodep t1; char *n, *v; nodep NewPartLevel (SymtabEntry *Entry, TokenType type, int Size); if (!t) return head; switch(t->header.kind) { case BINOP_NODE: switch (t->header.name) { case YAND: MakeInsRecord(t->components.binop.left_operand, line, InOrOut); MakeInsRecord(t->components.binop.right_operand, line, InOrOut); return head; break; default: printf("MakeInsRecord: YAND binop node. Find out why here\n"); } break; case UNOP_NODE: switch (t->header.name) { case YLIST: n = xitoa((CurSymtab->Mask)+1); n--; *n = 'p'; SeqEnter(sym = AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); sym->Loc.line = line; PushSymtab(); t1 = t->components.unop.operand; NewPartLevel(sym, t1->header.name, PARTSIZE); MakeInsRecord(t->components.unop.operand, line, InOrOut); PopSymtab(); return head; break; default: printf("MakeInsRecord: YLIST unop node. Find out why here\n"); } break; case DECL_NODE: sym = MakeOpEntry(t, line, InOrOut); if (sym) { sym->Chain = head->Chain; head->Chain = sym; } break; } } Symtab *NewSym() { Symtab *Sym; Sym = AllocSymtab(TEMPSIZE); Sym->ParentTab = CurSymtab; Sym->Level = CurSymtab->Level + 1; Sym->ParentEntry = HashAllocSymtabEntry("temp", C_Module, null, 0); Sym->Mask = 0; return Sym; } void ResetList() { head->Chain = null; } int SeqEnter(SymtabEntry *np) { int i, AlreadyDefd; register SymtabEntry *hp; register SymtabEntry *p; register SymtabEntry *rp; AlreadyDefd = 0; if (CurSymtab->Mask < CurSymtab->Size) { i = (CurSymtab->Mask)++; hp = CurSymtab->Entries[i]; np->Next = hp; CurSymtab->Entries[i] = np; return AlreadyDefd; } else return (!AlreadyDefd); } SymtabEntry *SeqLookup(register char *s) { register SymtabEntry *p; register SymtabEntry *q; register int i; Symtab *st; nodep t; if (s == NIL) return (NIL); /* * Symbol table is first searched at that level doing entry by entry * string comparison. If not found, then each entry string is examined * to see if it is a pi type string, if so then that symtab is entered * and the string is searched for there. If not found pop back up and * look for the next pi type entry. */ st = CurSymtab; for (i = 0; i < st->Mask; i++) { p = st->Entries[i]; if (strcmp(p->Symbol, s) == 0) { p->Flags |= used; /* Hint for Milestone 3 */ return (p); } } for (i = 0; i < st->Mask; i++) { p = st->Entries[i]; if ((strncmp(p->Symbol, "p", 1) == 0) && isdigit(p->Symbol[1])) { t = p->Type; PushSymtab(); CurSymtab = t->components.type.kind.parts.parts; p = (SeqLookup(s)); PopSymtab(); return (p); } } return (NIL); } /* * For the spec lang, we install a default level 1 main module to hold entities * that are not inside any explicitly declared module. */ void InstallMain() { SymtabEntry *sym; nodep t, t1; Enter(sym=HashAllocSymtabEntry("Main", C_Module, null, 1)); NewLevel(sym, 1024, null, YMODULE); MainSymtab = CurSymtab; /* * Also build a dummy parsetree so that it looks like other * modules to the checker. */ MainSymtab->Tree = t = NewNode(MODULE_NODE, YOBJ, EmptyLoc); t->components.module.name = t1 = NewNode(ATOM_NODE, Yident, EmptyLoc); t1->components.atom.val.text = hashsave("Main"); t->components.module.body = t1 = NewNode(SPEC_NODE, null, EmptyLoc); t1->components.spec.entities = null; } /* * Clear out an obj entry that's already in the symtab. */ void ClearObjEntry(SymtabEntry *sym) { char *p; int i; p = (char *) sym; for (i=0; iheader.kind) { case MODULE_NODE: /* DONE ALREADY IN ExitModule CurSymtab->Tree = t; */ break; case DECL_NODE: AddToMainList(t); break; } } /* * Add a new top-level entity_spec_list to Main module. Note call to * MergeDeclLists instead of AddToDeclList. The incoming t is an entity spec * list, which is an unfixed decl list. We want to merge in all of its items, * which maintaining the unfixed structure for any upcoming merges of same * kind. */ void AddToMainList(nodep t) { nodep t1; nodep InitDeclList(nodep t); nodep AddToDeclList(nodep list, nodep item); nodep MergeDeclLists(nodep t1, nodep t2); t1 = MainSymtab->Tree->components.module.body; if (!t1->components.spec.entities) t1->components.spec.entities = t; else t1->components.spec.entities = MergeDeclLists( t1->components.spec.entities, t); } /* * Fix up the finished entity def list in Main. */ void FixMainList() { nodep t1; nodep FixDeclList(nodep t); t1 = MainSymtab->Tree->components.module.body; t1->components.spec.entities = FixDeclList( t1->components.spec.entities); } nodep NewPartLevel (SymtabEntry *Entry, TokenType type, int Size) { Symtab *st; nodep n; if (Entry != NILSYM) { n = NewNode(TYPE_NODE, type, EmptyLoc); st = AllocSymtab (Size); Entry->Type = n; n->components.type.kind.parts.parts = st; st->ParentTab = CurSymtab; st->ParentEntry = Entry; st->Level = CurSymtab == (Symtab *)0 ? 0 : CurSymtab->Level + 1; st->Mask = 0; CurSymtab = st; return n; } } bool noRedefinition(register char *s) { register SymtabEntry *p; register SymtabEntry *q; register int i; Symtab *st; nodep t; if (s == NIL) return (NIL); /* * Symbol table is first searched at that level doing entry by entry * string comparison. If not found, then each entry string is examined * to see if it is a pi type string, if so then that symtab is entered * and the string is searched for there. If not found pop back up and * look for the next pi type entry. */ st = CurSymtab; for (i = st->Offset; i < st->Mask; i++) { p = st->Entries[i]; if (strcmp(p->Symbol, s) == 0) { return false; } } for (i = 0; i < st->Mask; i++) { p = st->Entries[i]; if (strcmp(p->Symbol, s) == 0) { /* if (!(p->Flags & needSpec)) */ return false; } } return true; } SymtabEntry *SpecializationNeeded(char *s) { Symtab *st; int i; SymtabEntry *p; st = CurSymtab; for (i = 0; i < st->Mask; i++) { p = st->Entries[i]; if (strcmp(p->Symbol, s) == 0) { /* if (p->Flags & needSpec) */ return st->Entries[i]; } } return null; } SymtabEntry *MakeEntry(nodep t, SymClasses class, int line) { nodep initValue; struct Sym *sym, *sym1; char *n; initValue = t->components.decl.kind.initdecl.init; t = t->components.decl.kind.initdecl.decl; if (t->components.decl.kind.attr.colon) { /* * "name : " case (i.e., a spcialization-required field in a class) */ n = t->components.decl.kind.attr.name->components.atom.val.text; if (noRedefinition(n)) { if (!SpecializationNeeded(n)) { SeqEnter(sym= AllocSymtabEntry(n, C_Name, null, CurSymtab->Level+1)); sym->Loc.line = line; if (initValue) error(" Illegal initialization of unspecialized part\n"); /* sym->Flags |= needSpec; */ return null; } } else { error(" Redefinition 1 of %s\n", n); return null; } } else if (t->components.decl.kind.attr.value) { /* * "name : value" case (i.e, a full name/value pair) */ n = t->components.decl.kind.attr.name->components.atom.val.text; PushSymtab(); sym = CurSymtab->ParentEntry; while ((sym->Class != C_Obj) && (sym->Class != C_Op)) { sym = CurSymtab->ParentEntry; CurSymtab = CurSymtab->ParentTab; } if (!(sym = LookupString(t->components.decl.kind.attr.value-> components.atom.val.text))) { error(" Component %s not defined\n", n); PopSymtab(); return null; } /* * New case to fix error when same obj name is used more than once * in a components list. E.g * components: a and a; * The problem is that the first a is entered as a name, and so it * gets found by the local lookup, but it's not the obj name we * want. */ if (sym->Class == C_Name) { sym = CurSymtab->ParentEntry; CurSymtab = CurSymtab->ParentTab; } if (!(sym = LookupString(t->components.decl.kind.attr.value-> components.atom.val.text))) { error(" Component %s not defined\n", n); PopSymtab(); return null; } if (class == C_Obj) { if (sym->Class != C_Obj) { error(" Component %s is not an object\n", n); PopSymtab(); return null; } } else if (class == C_Op) { if ((sym->Class != C_Op) and (not streq(n, "none")) and (not streq(n, "empty"))) { error(" Component %s is not an operation\n", n); PopSymtab(); return null; } } PopSymtab(); if ( noRedefinition(n)) { if (sym1 = SpecializationNeeded(n)) { sym1->Type = sym->Type; /* sym->Info.Name.initValue = initValue; */ return sym; } else { SeqEnter(sym = AllocSymtabEntry(n, C_Name, sym->Type, CurSymtab->Level+1)); sym->Loc.line = line; /* sym->Info.Name.initValue = initValue; */ return sym; } } else { error(" Redefinition 2 of %s\n",n); return null; } } else { /* * "name" case (i.e., just a name with no ": value" given) */ n = t->components.decl.kind.attr.name->components.atom.val.text; PushSymtab(); sym = CurSymtab->ParentEntry; while ((sym->Class != C_Obj) && (sym->Class != C_Op)) { sym = CurSymtab->ParentEntry; CurSymtab = CurSymtab->ParentTab; } if (!(sym = LookupString(n))) { error(" Component %s not defined\n", n); PopSymtab(); return null; } /* New case to fix error when same obj name is used more than once * in a components list. E.g * components: a and a; * The problem is that the first a is entered as a name, and so it * gets found by the local lookup, but it's not the obj name we * want. */ if (sym->Class == C_Name) { sym = CurSymtab->ParentEntry; CurSymtab = CurSymtab->ParentTab; } if (!(sym = LookupString(n))) { error(" Component %s not defined\n", n); PopSymtab(); return null; } if (class == C_Obj) { if (sym->Class != C_Obj) { error(" Component %s is not an object\n", n); PopSymtab(); return null; } } else if (class == C_Op) { if ((sym->Class != C_Op) and (not streq(n, "none")) and (not streq(n, "empty"))) { error(" Component %s is not an operation\n", n); PopSymtab(); return null; } } PopSymtab(); if ( noRedefinition(n)) { if (sym1 = SpecializationNeeded(n)) { sym1->Type = sym->Type; /* sym->Info.Name.initValue = initValue; */ return sym; } else { SeqEnter(sym = AllocSymtabEntry(n, C_Name, sym->Type, CurSymtab->Level+1)); sym->Loc.line = line; /* sym->Info.Name.initValue = initValue; */ return sym; } } else { /* Nuke this message, since it has to do with bogus * auto name stuff. Yes, we are calling this stuff bogus * now! error(" Redefinition 3 of %s\n",n); return null; */ return sym; } } } /* * Taken from misc.c. Make of browser in../hyperlinks cant include ./misc.o * since stralloc gets mult def'd. Hence, we leave stralloc in ./misc.c, but * stick in xitoa here from misc.c. Note that it's been renamed from iota to * xiota to avoid conflict with lib CYGWIN lib version of iota, which has a * different signature than this. */ char *xitoa(int n) { #define max 20 #define AsciiNum 0x30 int place = 10; int i; char* str; str = (char*)malloc(max * sizeof(char)); for (i = 1;i 0) { i = n % place; n /= place; str--; *str = i + AsciiNum; } return str; }