/**** * * Implementation of TransInterface. * */ #include #include #include "strlist.h" #include "new-features-stubs.h" // The next is line is part of std-macros++.h, but it's put here directly // to expedite compilation. I.e., it's a hack. #define newstr(s) strcpy(new char[strlen(s)+1], s) #include "trans-interface.h" #include "browser-hooks++.h" TransInterface::TransInterface(int argc, char** argv) { /* * Construct by initializing each of the major lists. * * * OLD COMMENT: * Call the translator on the given command line args. In the current * imple, the translator will NOT handle any checking of .rsg files. * This checking will be done as the files are opened by the user. In a * later imple, we might want the translator to perform at least initial * checking of of .rsg's by scanning the files for defs of graphic object * names that appear in picture attr decls. This is not really a * critical issue, so it can be done later. */ Init(); this->argc = argc; this->argv = argv; } void TransInterface::Init() { mods = new EntityStructList(); objs = new EntityStructList(); ops = new EntityStructList(); others = new EntityStructList(); browserSymtab = new EntitySymtab(); graphicsSymtab = new EntitySymtab(); } int TransInterface::Translate(int argc, char** argv) { /* * Call the translator on the given command line args, and return what * translator() returns. Viz., return 1 if translation succeeds * entirely, 0 if there are undefined entities but translation otherwise * ducceeds, -1 if there are fatal translation errors. * * In the current imple, the translator will NOT handle any checking of * .rsg files. This checking will be done as the files are opened by the * user. In a later imple, we might want the translator to perform at * least initial checking of of .rsg's by scanning the files for defs of * graphic object names that appear in picture attr decls. This is not * really a critical issue, so it can be done later. */ return translator(argc, argv); } int TransInterface::ReTranslate(int argc, char** argv) { /* * Call translator again, in response to Rescan command. */ /* delete mods; delete objs; delete ops; delete others; delete browserSymtab; */ Init(); return translator(argc, argv); } bool TransInterface::TranslateOne(const char* filename) { /* * Call the translator with just on one file; used to handle File.Open * menu command. */ char* argv[2]; int result; argv[1] = newstr(filename); if ((result = Translate(2, argv)) >= 0) { delete argv[1]; return true; } else { delete argv[1]; return false; } } void TransInterface::CallFun(const char* funname) { /* * Call the function of the given name if it can be found. */ SymtabEntry* sym; /* * Lookup the function of the given name in the current environment (which * is most liketly the global environment. */ } BrowserSymLists* TransInterface::GetAllSyms() { /* * Get the complete list of translated symbols, including module names, * object names, and op names. Inter-module namespace conflicts are * resolved by appending " (in Module M)" to each symbol with the same * name as one or more other symbols in other modules. */ SymtabEntry *e, *e1, *preve; EntityStructList* l = new EntityStructList(); List* locs = new List; EntityStruct* n; int i; char *s, *sp, s1[300], *s2, *s3; int pp; bool same_mod; /* * Get the module names from the separate module symtab that the translator * built for us. Also, build the individual per-module sym lists that are * used for building the individual per-module dictionaries. */ GetModSyms(); /* * Move to the browser symtab that the translator was kind enough to build * for us. This symtab has all of the translated symbols that we're after * right now. Name conflicts are not yet resolved -- symbols of the same * name in two or more modules are each entered under the same name in the * table (i.e., they're all in the same bucket). We sort this out here and * embody the disambiguation in the string names (i.e., suffix with "(in * module X)"). */ MoveToBrowserSymtab(); /* * Check the case that we're entirely empty, which can happen when we have * one or more empty, but legal, modules. */ preve = NextEntry(); if (not preve) { return SortSyms(); } /* * Cruise the table via the enum generator, looking for dup names. The * algorithm is a bit tricky, but no biggie. The basic idea is that we * keep track of the prev symbol in the enumeration, and compare it with * the current. If they are the same name, we append a disambiguating * module name to both. As we cruise, we build the lists of syms for * modules, objs, ops, and others. */ pp = 0; while (e = NextEntry()) { /* * Get the string name of the symtab entry and disambiguate it if * necessary. */ if (e->Symbol == preve->Symbol) { pp++; if (InSameModule(e, preve)) { s = browserSymtab->BuildDisambiguatedStr(preve, pp); same_mod = true; } else { s = browserSymtab->BuildDisambiguatedStr(preve, 0); same_mod = false; } } else if (pp > 0) { if (same_mod) { s = browserSymtab->BuildDisambiguatedStr(preve, pp+1); } else { s = browserSymtab->BuildDisambiguatedStr(preve, 0); } pp = 0; } else { s = preve->Symbol; } /* * Put the symbol in the appropriate list and enter into browserSymtab. * * NOTE: An earlier thot was that we would compute all of * necesary lists for display in the browser menubar within PutSym. * The problem with this is that PutSym needs to do lookups, and the * names wont yet be disambiguated in this pass. Hence, we'll build * the browserSymtab in this pass, and then cruise it in another pass * to build the menubar-necessary lists. */ PutSym(s, preve); /* * Move on to the next sym in the enumeration. */ preve = e; } /* * Handle the last enumerated symbol. */ if (pp > 0) { if (same_mod) { s = browserSymtab->BuildDisambiguatedStr(preve, pp+1); } else { s = browserSymtab->BuildDisambiguatedStr(preve, 0); } } else { s = preve->Symbol; } PutSym(s, preve); /* * Now do the second pass to build the brXXX symtab fields. */ while (n = browserSymtab->Enum()) { EnterInfo(n->GetSym()); } /* * Sort each list and stick them in the return structure. */ return SortSyms(); } bool TransInterface::InSameModule(SymtabEntry* s1, SymtabEntry* s2) { switch (s1->Class) { case C_Obj: return (s2->Class == C_Obj) and (s1->Info.Obj.parent == s2->Info.Obj.parent); case C_Op: return (s2->Class == C_Op) and (s1->Info.Op.parent == s2->Info.Op.parent); default: return false; } } void TransInterface::GetModSyms() { /* * Get the module names from the separate browser symtab that the translator * builds for us. Also, build the individual per-module sym lists that are * used for building the individual per-module dictionaries. Finally, set * num_mods to the count of the total number of modules. */ SymtabEntry* e; MoveToBrowserModuleSymtab(); for (num_mods = 0; e = NextEntry(); num_mods++) { mods->Put(new EntityStruct(e->Symbol, (void*) e)); } } void TransInterface::PutSym(char* s, SymtabEntry* preve) { /* * Put the given symbol name and symtab entry in the appro list based on its * class, viz. module, obj, op, or other. As we do so, we compute the info for * the brwoser lists that will be used to display the pulldown menus in the * browser menubar. */ // printf("%s\n", preve->Symbol); /* * Install it in the appro list. */ switch (preve->Class) { case C_Obj: objs->Put(new EntityStruct(s, (void*) preve)); break; case C_Op: ops->Put(new EntityStruct(s, (void*) preve)); break; default: others->Put(new EntityStruct(s, (void*) preve)); break; } /* * Install in overall browser symtab. */ browserSymtab->EnterSym(new EntityStruct(s, (void*) preve)); } BrowserSymLists* TransInterface::SortSyms() { /* * Sort the symbol lists and stick them in a BrowserSymLists structure * for use by RSLBrowser::InstallNames, q.v. Note that we suffix names * with the disambiguating module name. Hence the primary sort key is * the symbol name; the secondary sort key is the module name. */ BrowserSymLists* rtn = new BrowserSymLists( mods->Sort(), objs->Sort(), ops->Sort(), others->Sort()); // SortIndivLists(rtn) rtn->num_mods = num_mods; return rtn; } BrowserSymLists::BrowserSymLists(EntityStructList* mods, EntityStructList* objs, EntityStructList* ops, EntityStructList* others) { /* * Construct by init'ing each data member. */ this->mods = mods; this->objs = objs; this->ops = ops; this->others = others; } void TransInterface::DebugPrint(EntityStructList* l) { /* * For system debugging purposes only -- dump all of the syms. */ EntityStruct* n; char *s, *s1, *s2, *s3; SymtabEntry *e, *e1; for (n = l->Enum(); n; n = l->Enum()) { s = n->GetData()->Convert(); /* * The grab-straight-from-the-list approach. */ e = (SymtabEntry*) n->GetAuxData(); printf("Name: %s\n Line: %d\n Col: %d\n File: %s\n", s, e->Loc.line, e->Loc.col, e->Loc.file); /* * The lookup-in-module approach. */ /* * Skip over " (in Module )" */ if (strchr(s, ' ')) { strcpy(s1, s); s2 = strtok(s1, " "); /* 1st token = */ strtok(0, " "); /* 2nd token = "(in" */ strtok(0, " "); /* 3rd token = "Module" */ s3 = strtok(0, ")"); /* 4th token = */ e1 = LookupStringIn(s2, LookupStringIn(s3, Level0Symtab)->Info.Module.Symtab); } else { e1 = LookupString(s); } printf("Name: %s\n Line: %d\n Col: %d\n File: %s\n", s, e1->Loc.line, e1->Loc.col, e1->Loc.file); } } EntityStructList* TransInterface::GetComponents(SymtabEntry* s) { /* * Return a sorted list containing the names of the current entity's * components, given the symtab entry of the current entity. Use the * brComponents field of the symtab entry. */ if (s->Class == C_Obj) return s->Info.Obj.brComponents; else return s->Info.Op.brComponents; } EntityStructList* TransInterface::GetUnsortedComponents(SymtabEntry* s) { if (s->Class == C_Obj) return s->Info.Obj.brComponentsU; else return null; } EntityStructList* TransInterface::GetInstances(SymtabEntry* s) { /* * Return a sorted list of the current entity's instances. Use the brInstances * field of the symtab entry. */ if (s->Class == C_Obj) return s->Info.Obj.brInstances; else return s->Info.Op.brInstances; } EntityStructList* TransInterface::GetParents(SymtabEntry* s) { /* * Return a sorted list of the current entity's hierarchical parents. Use the * brPartof field of the symtab entry. */ if (s->Class == C_Obj) return s->Info.Obj.brPartof; else return s->Info.Op.brPartof; } EntityStructList* TransInterface::GetClassParents(SymtabEntry* s) { /* * Return a sorted list of the current entity's superclasses. Use the * brInstanceof field in the symtab entry. */ if (s->Class == C_Obj) return s->Info.Obj.brInstanceof; else return s->Info.Op.brInstanceof; } EntityStructList* TransInterface::GetOperations(SymtabEntry* s) { /* * Return a sorted list of the current entity's operations. Use the brOps * field of the symtab entry. */ return s->Info.Obj.brOps; } EntityStructList* TransInterface::GetInputs(SymtabEntry* s) { /* * Return a sorted list of the current entity's inputs. Use the brIns field of * the symtab entry. */ return s->Info.Op.brIns; } EntityStructList* TransInterface::GetOutputs(SymtabEntry* s) { /* * Return a sorted list of the current entity's outputs. Use the brOuts field * of the symtab entry. */ return s->Info.Op.brOuts; } EntityStructList* TransInterface::GetLinks(SymtabEntry* s) { /* * Return a sorted list of lists of current entity's links. Use the brLinks * field of the symtab entry. Note that we're bending the use of the * EntityStructList return value here. The return value is a list of lists, * where each top-level list elem contains a link name, and a sublist pointer. * In a genuine EntityStructList, the sublist pointer is a sym pointer, so we * need to coerce it when we use it (see menus.c:LinksMenu::InstallNames). * * A whole new datatype might be in order, since link names might be viewed as * entities in some conceivable future, say, where we wanted to move the * browser to where the attr was defined. Thinking about it this way, in fact, * it seems like link names, which are, afterall, attributes, can in fact be * considered a third type of entity. Cf. RMF. Later. */ if (s->Class == C_Obj) return s->Info.Obj.brLinks; else return s->Info.Op.brLinks; } void TransInterface::EnterInfo(SymtabEntry* sym) { /* * For a given entity, make all the browser-specific lists. Cf. comment above * re. how the translator really "ought not" do this but that it's a boatload * easier if the translator does in fact do this. * * There's a bit of a hack going on here while the interp is still written in * plain C. Viz., the interp puts names in plain C lists. These names are * then extracted from the plain C list onto a C++ str list. We might try to * push our luck by having a compatible str list between plain C and C++, but I * dont feel like pushing today. What we do do along these lines is have sym.h * declare the brXXX fields as List* and sym++.h declare the same fields as * EntityStructList*. This should be fine since we're just dealing with * one-word pointers. */ switch (sym->Class) { case C_Obj: EnterObjInfo(sym); break; case C_Op: EnterOpInfo(sym); break; } } void TransInterface::EnterObjInfo(SymtabEntry* sym) { EnterObjComponents(sym); EnterObjInstances(sym); EnterObjParents(sym); EnterObjClassParents(sym); EnterObjOperations(sym); EnterObjLinks(sym); /* DEBUGGING: * printf("Symbol %s's type:", sym->Symbol); pp(sym->Type); printf("\n"); * */ } void TransInterface::EnterObjComponents(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Obj.brComponents), &(sym->Info.Obj.brComponentsU)); } void TransInterface::EnterGeneralValues(SymtabEntry* sym, EntityStructList** brValuesPtr, EntityStructList** brUnsortedValuesPtr) { EntityStructList* l = new EntityStructList(); EntityStructList* ul; PlainCAuxListElem e; EntityStruct* es; if (not *brValuesPtr) { *brValuesPtr = l; return; } if (brUnsortedValuesPtr != null) { ul = new EntityStructList(); } while (e = (PlainCAuxListElem) EnumList( (PlainCList) *brValuesPtr)) { if (e->AuxData) { es = browserSymtab->LookupAmbigSym(e->AuxData); if (es) { l->Put(new EntityStruct(es->GetName(), (void*) es->GetSym())); if (brUnsortedValuesPtr != null) { ul->Put(new EntityStruct(es->GetName(), (void*) es->GetSym())); } } else { l->Put(new EntityStruct(e->Data, null)); if (brUnsortedValuesPtr != null) { ul->Put(new EntityStruct(e->Data, null)); } } } else { l->Put(new EntityStruct(e->Data, null)); if (brUnsortedValuesPtr != null) { ul->Put(new EntityStruct(e->Data, null)); } } } if (brUnsortedValuesPtr != null) { *brUnsortedValuesPtr = ul; } *brValuesPtr = l->Sort(); } void TransInterface::EnterObjInstances(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Obj.brInstances), null); } void TransInterface::EnterObjParents(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Obj.brPartof), null); } void TransInterface::EnterObjClassParents(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Obj.brInstanceof), null); } void TransInterface::EnterObjOperations(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Obj.brOps), null); } void TransInterface::EnterObjLinks(SymtabEntry* sym) { EnterLinks(sym, &(sym->Info.Obj.brLinks)); } void TransInterface::EnterLinks(SymtabEntry* sym, EntityStructList** brLinksPtr) { /* * See lengthy commennt the .h file. */ EntityStructList* l1 = new EntityStructList(); EntityStructList* l2; PlainCAuxListElem l, e; EntityStruct* es; /* DEBUGGING PlainCList pl1 = (PlainCList)l->AuxData, pl2 = (PlainCList)*brLinksPtr; */ if (not *brLinksPtr) { *brLinksPtr = l1; return; } while (l = (PlainCAuxListElem) EnumList( (PlainCList) *brLinksPtr)) { l2 = new EntityStructList(); while (e = (PlainCAuxListElem) EnumList((PlainCList)(l->AuxData))) { if (e->AuxData) { es = browserSymtab->LookupAmbigSym(e->AuxData); if (es) l2->Put(new EntityStruct(es->GetName(), (void*) es->GetSym())); else l2->Put(new EntityStruct(es->GetName(), null)); } else l2->Put(new EntityStruct(e->Data, null)); /* * Enter picture names in graphics cross ref symtab. */ if (streq(l->Data, "picture")) EnterGraphicsName(e->Data, sym); } l1->Put(new EntityStruct(l->Data, (void*) l2->Sort())); } *brLinksPtr = l1->Sort(); } void TransInterface::EnterGraphicsName(char* name, SymtabEntry* sym) { /* * Enter picture names in graphics cross ref symtab. */ EntityStruct* gs = graphicsSymtab->LookupSym(name); EntityStructList* l; if (gs) { l = (EntityStructList*) gs->GetSym(); } else { l = new EntityStructList(); graphicsSymtab->EnterSym(new EntityStruct(name, (void*) l)); } l->Put(new EntityStruct(sym->Symbol, (void*) sym)); } EntityStruct* TransInterface::LookupGraphicsName(char* name) { return graphicsSymtab->LookupSym(name); } void TransInterface::EnterOpInfo(SymtabEntry* sym) { EnterOpComponents(sym); EnterOpInstances(sym); EnterOpParents(sym); EnterOpClassParents(sym); EnterOpInputs(sym); EnterOpOutputs(sym); EnterOpLinks(sym); } void TransInterface::EnterOpComponents(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Op.brComponents), null); } void TransInterface::EnterOpInstances(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Op.brInstances), null); } void TransInterface::EnterOpParents(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Op.brPartof), null); } void TransInterface::EnterOpClassParents(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Op.brInstanceof), null); } void TransInterface::EnterOpInputs(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Op.brIns), null); } void TransInterface::EnterOpOutputs(SymtabEntry* sym) { EnterGeneralValues(sym, &(sym->Info.Op.brOuts), null); } void TransInterface::EnterOpLinks(SymtabEntry* sym) { EnterLinks(sym, &(sym->Info.Op.brLinks)); } void TransInterface::SetBrowser(RSLBrowser* browser) { this->browser = browser; } bool TransInterface::IsAtomic(SymtabEntry* sym) { } char* TransInterface::GetAtomicType(SymtabEntry* sym) { } EquationsList* TransInterface::GetEquations(SymtabEntry* sym) { } WhereClauseList* TransInterface::GetWhereClause(SymtabEntry* sym) { } StrList* TransInterface::GetPreCond(SymtabEntry* sym) { } StrList* TransInterface::GetPostCond(SymtabEntry* sym) { } StrList* TransInterface::GetImports(SymtabEntry* sym) { } StrList* TransInterface::GetExports(SymtabEntry* sym) { } StrList* TransInterface::GetAttrDefs(SymtabEntry* sym) { } EntitySymtab* TransInterface::GetBrowserSymtab() { return browserSymtab; }