Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/vm/input/tasm/parser.cc

Go to the documentation of this file.
00001 /*
00002  * vm/input/tasm/parser.cc
00003  * 
00004  * VM plaintext assembly parser (syntactical analysis). 
00005  * 
00006  * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00007  * 
00008  * This file may be distributed and/or modified under the terms of the 
00009  * GNU General Public License version 2 as published by the Free Software 
00010  * Foundation. (See COPYING.GPL for details.)
00011  * 
00012  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014  * 
00015  */
00016 
00017 #include "tasm-file.h"
00018 #include <lib/message/message.h>
00019 #include <vm/input/classinfo.h>
00020 #include <vm/instruction/instruction.h>
00021 
00022 
00023 namespace VM
00024 {
00025 
00026 void AssemblerFile_Plaintext::_ExpectError(const char *str)
00027 {
00028     if(tok)
00029     {  Error(tok->lloc,"parser expects %s not %s",str,
00030         scan.TokID2String(_CurrTokID()));  }
00031     else
00032     {  Error("early EOF; parser expects %s not %s",str,
00033         scan.TokID2String(TextAsmScanner::T_EOF));  }
00034     
00035     ++n_errors;
00036 }
00037 
00038 
00039 void AssemblerFile_Plaintext::_AlreadySetError()
00040 {
00041     Assert(tok);
00042     Error(tok->lloc,"%s already set",scan.TokID2String(_CurrTokID()));
00043     ++n_errors;
00044 }
00045 
00046 
00047 void AssemblerFile_Plaintext::_LocFirstDefError(const SCLocation &loc)
00048 {
00049     Error(loc,"  this is the location of the first definition");
00050     ++n_errors;
00051 }
00052 
00053 
00054 VarType AssemblerFile_Plaintext::_ParseVarType(
00055     const TextAsmScanner::Token::Type *t)
00056 {
00057     VarType vt;
00058     
00059     int idx=0;
00060     if(t->tchar[idx]=='a')
00061     {  vt.array=1;  ++idx;  }
00062     switch(t->tchar[idx])
00063     {
00064         case 'b':  vt.id=VarType::Byte;   break;
00065         case 's':  vt.id=VarType::Short;  break;
00066         case 'i':  vt.id=VarType::Int;    break;
00067         case 'l':  vt.id=VarType::Long;   break;
00068         case 'f':  vt.id=VarType::Flt;    break;
00069         case 'd':  vt.id=VarType::Dbl;    break;
00070         case 'p':  vt.id=VarType::Ptr;    break;
00071         default:  Assert(0);
00072     }
00073     if(idx==0)
00074     {  Assert(!t->tchar[1] || t->tchar[1]=='>');  }
00076     
00077     return(vt);
00078 }
00079 
00080 
00081 FuncType AssemblerFile_Plaintext::_ParseFuncType(char ftype)
00082 {
00083     // Captial letters are non-exported. 
00084     switch(ftype)
00085     {
00086         case 'f':  return(FuncType(FuncType::Function,1));
00087         case 'm':  return(FuncType(FuncType::Method,  1));
00088         case 'v':  return(FuncType(FuncType::VMethod, 1));
00089         case 'F':  return(FuncType(FuncType::Function,0));
00090         case 'M':  return(FuncType(FuncType::Method,  0));
00091         case 'V':  return(FuncType(FuncType::VMethod, 0));
00092     }
00093     
00094     Assert(0);
00095     return FuncType();  // gcc-3.4 CAN parse return(FuncType());
00096 }
00097 
00098 
00099 void AssemblerFile_Plaintext::_SkipUntilPop(uint32 /*_unused_ num*/,
00100     TextAsmScanner::TokID skip_a,TextAsmScanner::TokID skip_b)
00101 {
00102     if(skip_b==TextAsmScanner::T_EOF)  skip_b=skip_a;
00103     
00104     _LexNextToken();
00105     
00106     // Skip block. 
00107     for(/*uint32 cnt=0; cnt<num; cnt++*/;;)
00108     {
00109         TextAsmScanner::TokID c=_CurrTokID();
00110         if(c==skip_a || c==skip_b)
00111         {  _LexNextToken();  }
00112         else 
00113         {
00114             if(c==TextAsmScanner::T_pop)
00115             {  _LexNextToken();  }
00116             break;
00117         }
00118     }
00119     
00120     if(_CurrTokID()==TextAsmScanner::T_pop)
00121     {  _LexNextToken();  }
00122 }
00123 
00124 
00125 void AssemblerFile_Plaintext::_ParseProgram_FinishFunction()
00126 {
00127     // See if we have a function. 
00128     if(!scan.insn_storage)  return;
00129     
00130     // Warn about empty functions. These will surely make a problem as 
00131     // they even do not have a return at the end. 
00132     if(scan.insn_storage->length()<2)
00133     {
00134         Warning(scan.insn_storage->loc,
00135             "empty function with symref $%d",
00136             (int)scan.insn_storage->symref);
00137     }
00138     
00139     // Resolve CodeMark jumps in the program. 
00140     for(PrgAdr adr=0; adr<scan.insn_storage->length(); )
00141     {
00142         const INST::DescEntry *ide=
00143             INST::Desc(scan.insn_storage->InstructionAt(adr));
00144         if(!ide)
00145         {
00146             // Unfortunately, we have not yet looked up the name. 
00147             // Actually, we could do that for the error but it is not 
00148             // sure that the information was already read in. 
00149             Error(scan.insn_storage->loc,
00150                 "illegal instruction at address 0x%x (symref $%d)",
00151                 (uint)adr,(int)scan.insn_storage->symref);
00152             ++n_errors;
00153             break;  // No use to go on; we cannto compute the size of the skip. 
00154         }
00155         
00156         // Only instructions with a codemark are interesting. 
00157         if(ide->codemark_off)
00158         {
00159             // Extract CodeMark from program memory: 
00160             char *prg_inst_adr = 
00161                 &scan.insn_storage->index(adr+ide->codemark_off) ;
00162             CodeMark cmark=*(CodeMark*)prg_inst_adr;
00163             
00164             // Look up CodeMark: 
00165             bool known;  // unset
00166             PrgAdr mark_adr=codemark2prgadr.lookup(cmark,&known);
00167             if(!known)
00168             {
00169                 Error(scan.insn_storage->loc,
00170                     "unknown CodeMark &%u at address 0x%x",
00171                     (uint)cmark,(uint)adr);
00172                 ++n_errors;
00173                 // mark_adr=0 in this case. 
00174             }
00175             
00176             // Compute relative jumpaddress; using signed value. 
00177             int32 delta=int32(mark_adr)-int32(adr);
00178             //fprintf(stderr,"DELTA=%d\n",delta);
00179             
00180             // Write result back into program memory. 
00181             *(PrgAdr*)prg_inst_adr=(PrgAdr)delta;
00182         }
00183         
00184         // Skip to next instruction. 
00185         adr+=ide->size;
00186     }
00187     
00188     // Append function to program storage. 
00189     scan.insn_storage->TightenSize();
00190     program.AddFunction(scan.insn_storage);
00191     scan.insn_storage=NULL;
00192     
00193     // Purge CodeMark -> PrgAdr lookup table (is per-function). 
00194     codemark2prgadr.clear();
00195 }
00196 
00197 
00198 NamespaceInfo *AssemblerFile_Plaintext::_CheckNspcNameKnown(
00199     NamespaceInfo *parent,const TLString &name)
00200 {
00201     NamespaceInfo **known=parent->map_name2child.search(name);
00202     if(known)
00203     {
00204         Error(tok->lloc,"duplicate definition of namespace/class \"%s\"",
00205             (*known)->CompleteName().str());
00206         _LocFirstDefError((*known)->asm_loc);  // <-- does ++n_errors;
00207         return(*known);
00208     }
00209     return(NULL);
00210 }
00211 
00212 
00213 void AssemblerFile_Plaintext::_ParseSymbols_Class_Base(ClassInfo *parent)
00214 {
00215     //Assert(_CurrTokID()==TextAsmScanner::TS_base);
00216     
00217     if(parent->base.n())
00218     {
00219         _AlreadySetError();
00220         _SkipUntilPop(parent->base.n(),TextAsmScanner::TS_baseent);
00221     }
00222     else
00223     {
00224         parent->base.alloc(tok->num);
00225         _LexNextToken();
00226         
00227         uint32 cnt=0;
00228         for(;;)
00229         {
00230             switch(_CurrTokID())
00231             {
00232                 case TextAsmScanner::T_pop:
00233                     if(cnt!=parent->base.n())
00234                     {
00235                         Error(tok->lloc,"too few (%u/%u) base entries",
00236                             cnt,parent->base.n());
00237                         ++n_errors;
00238                         for(; cnt<parent->base.n(); cnt++)
00239                         {  parent->base[cnt].tid=0;  parent->base[cnt].off=0;  }
00240                     }
00241                     _LexNextToken();
00242                     goto breakout;
00243                 
00244                 case TextAsmScanner::TS_baseent:
00245                     if(cnt>=parent->base.n())
00246                     {
00247                         if(cnt==parent->base.n())
00248                         {
00249                             Error(tok->lloc,"too many (>%u) base entries",
00250                                 parent->base.n());
00251                             ++n_errors;
00252                         }
00253                         _LexNextToken();
00254                         break;
00255                     }
00256                     parent->base[cnt].tid=tok->tid;
00257                     parent->base[cnt].off=tok->off;
00258                     ++cnt;
00259                     _LexNextToken();
00260                     break;
00261                 
00262                 default:
00263                     _ExpectError("base entry or ';'");
00264                     // Assume forgotten ';'. 
00265                     goto breakout;
00266             }
00267         }
00268         breakout:;
00269     }
00270 }
00271 
00272 
00273 void AssemblerFile_Plaintext::_ParseSymbols_Class_VTable(ClassInfo *parent)
00274 {
00275     //Assert(_CurrTokID()==TextAsmScanner::TS_vtable);
00276     
00277     if(parent->vtable.n())
00278     {
00279         _AlreadySetError();
00280         _SkipUntilPop(parent->vtable.n(),TextAsmScanner::TS_symref);
00281     }
00282     else
00283     {
00284         parent->vtable.alloc(tok->num);
00285         _LexNextToken();
00286         
00287         uint32 cnt=0;
00288         for(;;)
00289         {
00290             switch(_CurrTokID())
00291             {
00292                 case TextAsmScanner::T_pop:
00293                     if(cnt!=parent->vtable.n())
00294                     {
00295                         Error(tok->lloc,"too few (%u/%u) vtable entries",
00296                             cnt,parent->vtable.n());
00297                         ++n_errors;
00298                         for(; cnt<parent->vtable.n(); cnt++)
00299                         {  parent->vtable[cnt].symref=0;  }
00300                     }
00301                     _LexNextToken();
00302                     goto breakout;
00303                 
00304                 case TextAsmScanner::TS_symref:
00305                     if(cnt>=parent->vtable.n())
00306                     {
00307                         if(cnt==parent->vtable.n())
00308                         {
00309                             Error(tok->lloc,"too many (>%u) vtable entries",
00310                                 parent->vtable.n());
00311                             ++n_errors;
00312                         }
00313                         _LexNextToken();
00314                         break;
00315                     }
00316                     parent->vtable[cnt].symref=tok->symref;
00317                     ++cnt;
00318                     
00319                     _LexNextToken();
00320                     break;
00321                 
00322                 default:
00323                     _ExpectError("vtable entry or ';'");
00324                     // Assume forgotten ';'. 
00325                     goto breakout;
00326             }
00327         }
00328         breakout:;
00329     }
00330 }
00331 
00332 
00333 void AssemblerFile_Plaintext::_ParseSymbols_Class_Size(ClassInfo *parent)
00334 {
00335     //Assert(_CurrTokID()==TextAsmScanner::TS_size);
00336     
00337     if(parent->membvar.n() || parent->size)
00338     {
00339         _AlreadySetError();
00340         _SkipUntilPop(parent->membvar.n(),TextAsmScanner::TS_varent);
00341     }
00342     else
00343     {
00344         parent->size=tok->size;
00345         uint32 nmembvars=tok->num_p;
00346         if(cfg.read_non_pointer_members)
00347         {  nmembvars+=tok->num_v;  }
00348         parent->membvar.alloc(nmembvars);
00349         
00350         _LexNextToken();
00351         
00352         // The VM-Description says: 
00353         // The "size" spec must be before the member var specs in a class. 
00354         // The member var specs must be sorted by ascenting offset. 
00355         
00356         uint32 cnt=0;
00357         for(;;)
00358         {
00359             switch(_CurrTokID())
00360             {
00361                 case TextAsmScanner::T_pop:
00362                     if(cnt!=parent->membvar.n())
00363                     {
00364                         Error(tok->lloc,"too few (%u/%u) member var entries",
00365                             cnt,parent->membvar.n());
00366                         ++n_errors;
00367                         for(; cnt<parent->membvar.n(); cnt++)
00368                         {
00369                             parent->membvar[cnt].off=0;
00370                             // vtype and name need not be set. 
00371                         }
00372                     }
00373                     _LexNextToken();
00374                     goto breakout;
00375                 
00376                 case TextAsmScanner::TS_varent:
00377                 {
00378                     VarType vt(_ParseVarType(&tok->t));
00379                     if(vt.IsPointerType() || cfg.read_non_pointer_members)
00380                     {
00381                         if(cnt>=parent->membvar.n())
00382                         {
00383                             if(cnt==parent->membvar.n())
00384                             {
00385                                 Error(tok->lloc,
00386                                     "too many (>%u) member var entries",
00387                                     parent->membvar.n());
00388                                 ++n_errors;
00389                             }
00390                             _LexNextToken();
00391                             continue;
00392                         }
00393                         
00394                         parent->membvar[cnt].vtype=vt;
00395                         parent->membvar[cnt].off=tok->off;
00396                         if(cfg.read_member_var_names)
00397                         {  parent->membvar[cnt].name=TLString(tok->str_val);  }
00398                         
00399                         // Make sure they are sorted in ascenting order. 
00400                         if(cnt && 
00401                             parent->membvar[cnt-1].off>=
00402                                 parent->membvar[cnt].off)
00403                         {
00404                             Error(tok->lloc,"member var entries not sorted "
00405                                 "in ascenting order");
00406                             ++n_errors;
00407                         }
00408                         
00409                         ++cnt;
00410                     }
00411                     _LexNextToken();
00412                 }   break;
00413                 
00414                 default:
00415                     _ExpectError("member var entry or ';'");
00416                     // Assume forgotten ';'. 
00417                     goto breakout;
00418             }
00419         }
00420         breakout:;
00421     }
00422 }
00423 
00424 
00425 void AssemblerFile_Plaintext::_ParseSymbols_Symbols(NamespaceInfo *parent)
00426 {
00427     //Assert(_CurrTokID()==TextAsmScanner::TS_symbols);
00428     
00429     _LexNextToken();
00430     
00431     for(;;)
00432     {
00433         switch(_CurrTokID())
00434         {
00435             case TextAsmScanner::T_pop:
00436                 _LexNextToken();
00437                 goto breakout;
00438             
00439             case TextAsmScanner::TS_funcsym:   // fall through
00440             case TextAsmScanner::TS_varsym:
00441             {
00442                 if(tok->symref<0)
00443                 {
00444                     // We actually should not see this as the lexer will 
00445                     // reject negative sign in the matching regexp. 
00446                     Error(tok->lloc,"symref <0 for symbol \"%s\" is reserved "
00447                         "for internal use ",tok->str_val);
00448                     ++n_errors;
00449                     break;
00450                 }
00451                 
00452                 NamespaceInfo::SymbolEntryE sent(parent);
00453                 
00454                 bool exported=1;
00455                 if(_CurrTokID()==TextAsmScanner::TS_funcsym)
00456                 {
00457                     sent.extid=NamespaceInfo::SymbolEntryE::ExtFunction;
00458                     sent.ftype=_ParseFuncType(tok->ftype);
00459                     exported=sent.ftype.exported;
00460                 }
00461                 else if(_CurrTokID()==TextAsmScanner::TS_varsym)
00462                 {
00463                     sent.extid=NamespaceInfo::SymbolEntryE::ExtVariable;
00464                     sent.vtype=_ParseVarType(&tok->t);
00465                 }
00466                 else Assert(0);
00467                 
00468                 TLString name;
00469                 if(exported)
00470                 {
00471                     char *ptr=strchr(tok->str_val,'%');
00472                     if(ptr)
00473                     {
00474                         Error(tok->lloc,"'%%'-spec not allowed in exported "
00475                             "symbol \"%s\"",
00476                             tok->str_val);
00477                         ++n_errors;
00478                         *ptr='\0';
00479                     }
00480                     
00481                     name=TLString(tok->str_val);
00482                 }
00483                 else // !exported
00484                 {
00485                     // Append %-suffix. 
00486                     name.sprintf("%s%%%x",tok->str_val,(uint)file_num);
00487                 }
00488                 
00489                 sent.name=name;
00490                 sent.symref=tok->symref;
00491                 //sent.nspc=parent;  // <-- set in constructor
00492                 
00493                 // First, add the symbol entry to the "array" (is a queue). 
00494                 // This will copy it and we may then take the address of it. 
00495                 parent->symbol.PushHead(sent);
00496                 NamespaceInfo::SymbolEntryE *se=parent->symbol.head();
00497                 
00498                 // Add symref to the mapping. 
00499                 NamespaceInfo::SymbolEntryE *known=symref2symbol.AddNode(se);
00500                 if(known)
00501                 {
00502                     Error(tok->lloc,"symref $%d already defined for "
00503                         "symbol \"%s\"",
00504                         (int)tok->symref,known->CompleteName().str());
00505                     ++n_errors;
00506                 }
00507                 
00508                 // Add symbol to the name lookup map. We only have non-internal 
00509                 // symbols here. 
00510                 Assert(se->symref>=0);
00511                 int srv=parent->map_name2symbol.store(se,/*allow_update=*/0);
00512                 if(srv==1)
00513                 {
00514                     Error(tok->lloc,"duplicate symbol name \"%s\" (symref $%d)"
00515                         "in %s %s",
00516                         se->name.str(),(int)tok->symref,
00517                         NamespaceInfo::NSType2String(parent->nstype),
00518                         parent->CompleteName().str());
00519                     ++n_errors;
00520                 }
00521                 else Assert(srv==0);
00522                 
00523                 _LexNextToken();
00524             }   break;
00525             
00526             default:
00527                 _ExpectError("symbol entry or ';'");
00528                 // Assume forgotten ';'. 
00529                 goto breakout;
00530         }
00531     }
00532     breakout:;
00533 }
00534 
00535 
00536 void AssemblerFile_Plaintext::_ParseSymbols_Global()
00537 {
00538     //Assert(_CurrTokID()==TextAsmScanner::TS_[vp]global);
00539     
00540     _GlobVars *gvar;
00541     if(_CurrTokID()==TextAsmScanner::TS_pglobal)
00542     {  gvar=&gvar_p;  }
00543     else if(_CurrTokID()==TextAsmScanner::TS_vglobal)
00544     {  gvar=&gvar_v;  }
00545     else Assert(0);
00546     
00547     gvar->size=tok->size;
00548     _LexNextToken();
00549     
00550     for(;;)
00551     {
00552         switch(_CurrTokID())
00553         {
00554             case TextAsmScanner::T_pop:
00555                 _LexNextToken();
00556                 goto breakout;
00557             
00558             case TextAsmScanner::TS_globvar:
00559             {
00560                 if(tok->symref<0)
00561                 {
00562                     // We actually should not see this as the lexer will 
00563                     // reject negative sign in the matching regexp. 
00564                     Error(tok->lloc,"symref <0 for symbol \"%s\" is reserved "
00565                         "for internal use ",tok->str_val);
00566                     ++n_errors;
00567                     break;
00568                 }
00569                 
00570                 {
00571                     GlobalVarEntry tmp;
00572                     tmp.vtype=_ParseVarType(&tok->t);
00573                     tmp.off=tok->off;
00574                     tmp.symref=tok->symref;
00575                     
00576                     gvar->globvarq.PushHead(tmp);
00577                 }
00578                 
00579                 GlobalVarEntry *gve=gvar->globvarq.head();
00580                 GlobalVarEntry *known=symref2globvar.AddNode(tok->symref,gve);
00581                 if(known)
00582                 {
00583                     Error(tok->lloc,"duplicate definition of global var "
00584                         "with symref $%d",(int)tok->symref);
00585                     ++n_errors;
00586                 }
00587                 
00588                 _LexNextToken();
00589             }   break;
00590             
00591             default:
00592                 _ExpectError("global var entry or ';'");
00593                 // Assume forgotten ';'. 
00594                 goto breakout;
00595         }
00596     }
00597     breakout:;
00598 }
00599 
00600 
00601 void AssemblerFile_Plaintext::_ParseSymbols_Namespace(NamespaceInfo *parent)
00602 {
00603     NamespaceInfo *nsi=NULL;
00604     
00605     do {
00606         TLString name(tok->str_val);
00607         if(_CheckNspcNameKnown(parent,name))  break;
00608         
00609         // Allocate new child. 
00610         nsi=new NamespaceInfo(name,parent);
00611         nsi->asm_loc=tok->lloc.loc0;
00612     } while(0);
00613     
00614     _LexNextToken();
00615     
00616     if(!nsi)
00617     {
00618         // Read comment at the same position in _ParseSymbols_Class(). (FIXME?)
00619         return;
00620     }
00621     
00622     for(;;)
00623     {
00624         switch(_CurrTokID())
00625         {
00626             case TextAsmScanner::TS_namespace:
00627                 _ParseSymbols_Namespace(nsi);
00628                 break;
00629             case TextAsmScanner::TS_class:
00630                 _ParseSymbols_Class(nsi);
00631                 break;
00632             case TextAsmScanner::TS_symbols:
00633                 _ParseSymbols_Symbols(nsi);
00634                 break;
00635             
00636             case TextAsmScanner::T_pop:
00637                 _LexNextToken();
00638                 goto breakout;
00639             
00640             default:
00641                 _ExpectError("namespace entry "
00642                     "(namespace/class/symbols) or ';'");
00643                 // Assume forgotten ';'. 
00644                 goto breakout;
00645         }
00646     }
00647     breakout:;
00648 }
00649 
00650 
00651 void AssemblerFile_Plaintext::_ParseSymbols_Class(NamespaceInfo *parent)
00652 {
00653     ClassInfo *nsi=NULL;
00654     do {
00655         if(tok->tid<0)
00656         {
00657             Error(tok->lloc,"negative typeids (%d) reserved for internal use",
00658                 tok->tid);
00659             ++n_errors;
00660             break;
00661         }
00662         
00663         TLString name(tok->str_val);
00664         if(_CheckNspcNameKnown(parent,name))  break;
00665         
00666         // Allocate new child. 
00667         nsi=new ClassInfo(name,tok->tid,/*parent=*/parent);
00668         
00669         ClassInfo *known=tid2classinfo.AddNode(nsi);
00670         if(known)
00671         {
00672             Error(tok->lloc,"typeid %d already defined",(int)tok->tid);
00673             _LocFirstDefError(known->asm_loc);  // <-- does ++n_errors;
00674             
00675             // Need to get rid of the child again. 
00676             DELETE(nsi);  Assert(!nsi);
00677             
00678             break;
00679         }
00680         
00681         nsi->asm_loc=tok->lloc.loc0;
00682     } while(0);
00683     
00684     _LexNextToken();
00685     
00686     if(!nsi)
00687     {
00688         // In order to handle the error gracefully, we should probably 
00689         // skip the complete class here. But that is not as easy and 
00690         // I will not do that now. Anyways, it _is_ an error which 
00691         // has to be corrected in the input assembly file and there is 
00692         // not much point in spending much time on delaing with it 
00693         // in an especially nice way. (FIXME?)
00694         return;
00695     }
00696     
00697     for(;;)
00698     {
00699         switch(_CurrTokID())
00700         {
00701             case TextAsmScanner::TS_class:
00702                 _ParseSymbols_Class(nsi);
00703                 break;
00704             case TextAsmScanner::TS_symbols:
00705                 _ParseSymbols_Symbols(nsi);
00706                 break;
00707             
00708             case TextAsmScanner::T_pop:
00709                 _LexNextToken();
00710                 goto breakout;
00711             
00712             case TextAsmScanner::TS_base:
00713                 _ParseSymbols_Class_Base(nsi);
00714                 break;
00715             case TextAsmScanner::TS_size:
00716                 _ParseSymbols_Class_Size(nsi);
00717                 break;
00718             case TextAsmScanner::TS_virtual:
00719                 if(nsi->nvirtuals)  _AlreadySetError();
00720                 else  nsi->nvirtuals=tok->num;
00721                 _LexNextToken();
00722                 break;
00723             case TextAsmScanner::TS_vtable:
00724                 _ParseSymbols_Class_VTable(nsi);
00725                 break;
00726             
00727             default:
00728                 _ExpectError("class entry "
00729                     "(class/funcent/symbols/...) or ';'");
00730                 // Assume forgotten ';'. 
00731                 goto breakout;
00732         }
00733     }
00734     breakout:;
00735 }
00736 
00737 
00738 void AssemblerFile_Plaintext::_ParseInfoSection()
00739 {
00740     while(tok)  // while not EOF
00741     {
00742         switch(_CurrTokID())
00743         {
00744             case TextAsmScanner::TI_abivers:
00745                 abi_version=tok->str_val;  // TLString assignment. 
00746                 _LexNextToken();
00747                 break;
00748             
00749             case TextAsmScanner::T_info:        // fall...
00750             case TextAsmScanner::T_symbols:     //   ...
00751             case TextAsmScanner::T_locations:   //    ...
00752             case TextAsmScanner::T_program:     // ...through
00753                 goto breakout;
00754             
00755             default:
00756                 _ExpectError("abiversion "
00757                     "or section marker");
00758                 _LexNextToken();
00759                 break;
00760         }
00761     }
00762     breakout:;
00763 }
00764 
00765 
00766 void AssemblerFile_Plaintext::_ParseSymbolSection()
00767 {
00768     // Allocate namespace root if not yet there. 
00769     if(!nspc_root)
00770     {
00771         // The root is always plain NamespaceInfo and name is a NULL ref. 
00772         nspc_root=new NamespaceInfo(/*name=*/TLString(),/*parent=*/NULL);
00773         nspc_root->asm_loc=tok->lloc.loc0;
00774     }
00775     
00776     while(tok)  // while not EOF
00777     {
00778         switch(_CurrTokID())
00779         {
00780             case TextAsmScanner::TS_namespace:
00781                 _ParseSymbols_Namespace(nspc_root);
00782                 break;
00783             case TextAsmScanner::TS_class:
00784                 _ParseSymbols_Class(nspc_root);
00785                 break;
00786             case TextAsmScanner::TS_symbols:
00787                 _ParseSymbols_Symbols(nspc_root);
00788                 break;
00789             
00790             case TextAsmScanner::TS_vglobal:   // fall through
00791             case TextAsmScanner::TS_pglobal:
00792                 _ParseSymbols_Global();
00793                 break;
00794             
00795             case TextAsmScanner::T_info:        // fall...
00796             case TextAsmScanner::T_symbols:     //   ...
00797             case TextAsmScanner::T_locations:   //    ...
00798             case TextAsmScanner::T_program:     // ...through
00799                 goto breakout;
00800             
00801             default:
00802                 _ExpectError("namespace/class/funcent/symbols "
00803                     "or section marker");
00804                 _LexNextToken();
00805                 break;
00806         }
00807     }
00808     breakout:;
00809 }
00810 
00811 
00812 void AssemblerFile_Plaintext::_ParseLocationSection()
00813 {
00814     // Not yet implementd. 
00815     CritAssert(0); // not yet implemented
00816 }
00817 
00818 
00819 void AssemblerFile_Plaintext::_ParseProgram_Label()
00820 {
00821     //Assert(_CurrTokID()==TextAsmScanner::TP_[ms]label);
00822     
00823     switch(_CurrTokID())
00824     {
00825         case TextAsmScanner::TP_mlabel:
00826         {   // Codemark label. 
00827             if(!scan.insn_storage)
00828             {
00829                 Error(tok->lloc,
00830                     "codemark label &%u outside function",
00831                     (int)tok->codemark);
00832                 ++n_errors;
00833             }
00834             else
00835             {
00836                 bool is_known;  // Need NOT be set up. 
00837                 codemark2prgadr.AddNode(tok->codemark,
00838                     scan.insn_storage->length(),&is_known);
00839                 
00840                 // In order to handle codemark labels, we create a map 
00841                 // with the label positions and then resolve all these 
00842                 // labels in _ParseProgram_FinishFunction(). 
00843                 // We can then purge the map again; this makes it possible 
00844                 // to have the same labels multiple times as long as they 
00845                 // appear only once per function. 
00846                 // Should make the compiler easier. And should parse faster. 
00847                 if(is_known)
00848                 {
00849                     Error(tok->lloc,"duplicate definition of codemark "
00850                         "label &%u",
00851                         (uint)tok->codemark);
00852                     ++n_errors;
00853                 }
00854             }
00855         }   break;
00856         case TextAsmScanner::TP_rlabel:
00857         {   // Symref label. 
00858             // This marks the beginning of a function. 
00859             // If we're currently in a function, finish that off first. 
00860             _ParseProgram_FinishFunction();
00861             
00862             if(tok->symref<0)
00863             {
00864                 // We actually should not see this as the lexer will 
00865                 // reject negative sign in the matching regexp. 
00866                 Error(tok->lloc,"symref <0 for symbol \"%s\" is reserved "
00867                     "for internal use ",tok->str_val);
00868                 ++n_errors;
00869                 break;
00870             }
00871             
00872             // Start a new function. 
00873             scan.insn_storage=new ProgramStorage::Function(
00874                 tok->symref,tok->lloc.loc0);
00875             
00876             ProgramStorage::Function *known=symref2function.AddNode(
00877                 tok->symref,scan.insn_storage,NULL);
00878             if(known)
00879             {
00880                 Error(tok->lloc,"duplicate definition of function with "
00881                     "symref $%d",(int)tok->symref);
00882                 _LocFirstDefError(known->loc);  // <-- does ++n_errors;
00883                 DELETE(scan.insn_storage);  Assert(!scan.insn_storage);
00884                 // This will provoke some more errors about instructions 
00885                 // outside functions, but oh well...
00886             }
00887             
00888         }   break;
00889         case TextAsmScanner::TP_slabel:
00890         {
00891             // If we're currently in a function, finish that off first. 
00892             _ParseProgram_FinishFunction();
00893             
00894             SLabelInfo *sa;
00895             bool exported;
00896             bool is_init=0;
00897             if(!strcmp(tok->str_val,".init"))
00898             {  sa=&slabel_init;  exported=0;  is_init=1;  }
00899             else if(!strcmp(tok->str_val,".start"))
00900             {  sa=&slabel_start;  exported=1;  }
00901             else Assert(0);   // -> see lexer
00902             
00903             if(sa->pfunc)
00904             {
00905                 Error(tok->lloc,"duplicate definition of label %s",
00906                     tok->str_val);
00907                 ++n_errors;
00908                 // This will provoke some more errors about instructions 
00909                 // outside functions, but oh well...
00910             }
00911             else
00912             {
00913                 // These special functions are (currently) not added to 
00914                 // the symref2function map. They require special treatment 
00915                 // anyways and are never called directly. 
00916                 
00917                 // Set up a nice SymbolEntryE for the function. 
00918                 sa->se.extid=NamespaceInfo::SymbolEntryE::ExtFunction;
00919                 sa->se.ftype=FuncType(FuncType::Function,exported);
00920                 sa->se.nspc=nspc_root;
00921                 if(is_init)
00922                 {
00923                     // Generate %-suffix. 
00924                     sa->se.name.sprintf("init~%%%x",(uint)file_num);
00925                 }
00926                 else
00927                 {  sa->se.name=tok->str_val;  }  // <-- Assignment to TLString. 
00928                 
00929                 {
00930                     NamespaceInfo::SymbolEntryE **known=
00931                         nspc_root->map_name2symbol.search(sa->se.name);
00932                     if(known)
00933                     {
00934                         Error((*known)->nspc->asm_loc,
00935                             "cannot use reserved symbol name \"%s\" "
00936                             "(symref $%d)",
00937                             sa->se.name.str(),(int)(*known)->symref);
00938                         ++n_errors;
00939                     }
00940                 }
00941                 
00942                 // Start a new function. Set symref=0 here as we will 
00943                 // substitute the se pointer immidiately below. 
00944                 sa->pfunc=new ProgramStorage::Function(
00945                     /*symref=*/0,tok->lloc.loc0);
00946                 sa->pfunc->se=&sa->se;
00947                 
00948                 // Go on adding instructions here: 
00949                 scan.insn_storage=sa->pfunc;
00950             }
00951             
00952         }   break;
00953         default: Assert(0);
00954     }
00955     
00956     _LexNextToken();
00957 }
00958 
00959 
00960 void AssemblerFile_Plaintext::_ParseProgramSection()
00961 {
00962     while(tok)  // while not EOF
00963     {
00964         switch(_CurrTokID())
00965         {
00966             case TextAsmScanner::TP_slabel:  // fall...
00967             case TextAsmScanner::TP_mlabel:  //   ...through
00968             case TextAsmScanner::TP_rlabel:
00969                 _ParseProgram_Label();
00970                 break;
00971             
00972             case TextAsmScanner::T_info:        // fall...
00973             case TextAsmScanner::T_symbols:     //   ...
00974             case TextAsmScanner::T_locations:   //     ...
00975             case TextAsmScanner::T_program:     // ...through
00976                 goto breakout;
00977             
00978             default:
00979                 _ExpectError("label or instruction ");
00980                 _LexNextToken();
00981                 break;
00982         }
00983     }
00984     breakout:;
00985     
00986     // Make sure we do not leave a function dangling. 
00987     _ParseProgram_FinishFunction();
00988 }
00989 
00990 
00991 int AssemblerFile_Plaintext::ParseFile(const TLString &fname,SError &error,
00992     uint32 _file_num)
00993 {
00994     file_num=_file_num;
00995     
00996     int rv=scan.SetInput(fname,error,/*included=*/0);
00997     if(rv)
00998     {
00999         // If this fails; attempt to read in more than one file. 
01000         Assert(rv!=1);
01001         
01002         return(1);
01003     }
01004     
01005     // Yeah, then let's parse!
01006     _LexNextToken();
01007     
01008     // Set file name member. 
01009     this->filename=scan.CurrLoc();
01010     this->filename.pos->SetLine(-1);
01011     this->filename.pos->SetLPos(-1);
01012     
01013     while(tok)  // while not EOF
01014     {
01015         switch(_CurrTokID())
01016         {
01017             case TextAsmScanner::T_info:
01018                 _LexNextToken();
01019                 _ParseInfoSection();
01020                 break;
01021             case TextAsmScanner::T_symbols:
01022                 _LexNextToken();
01023                 _ParseSymbolSection();
01024                 break;
01025             case TextAsmScanner::T_locations:
01026                 _LexNextToken();
01027                 _ParseLocationSection();
01028                 break;
01029             case TextAsmScanner::T_program:
01030                 _LexNextToken();
01031                 _ParseProgramSection();
01032                 break;
01033             default:
01034                 _ExpectError("section marker (symbols/locations/program)");
01035                 _LexNextToken();
01036                 break;
01037         }
01038     }
01039     
01040     tok=NULL;
01041     
01042     return(scan.NErrors()+n_errors);
01043 }
01044 
01045 }  // end of namespace VM

Generated on Sat Feb 19 22:33:47 2005 for Ray by doxygen 1.3.5