00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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();
00096 }
00097
00098
00099 void AssemblerFile_Plaintext::_SkipUntilPop(uint32 ,
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
00107 for(;;)
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
00128 if(!scan.insn_storage) return;
00129
00130
00131
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
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
00147
00148
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;
00154 }
00155
00156
00157 if(ide->codemark_off)
00158 {
00159
00160 char *prg_inst_adr =
00161 &scan.insn_storage->index(adr+ide->codemark_off) ;
00162 CodeMark cmark=*(CodeMark*)prg_inst_adr;
00163
00164
00165 bool known;
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
00174 }
00175
00176
00177 int32 delta=int32(mark_adr)-int32(adr);
00178
00179
00180
00181 *(PrgAdr*)prg_inst_adr=(PrgAdr)delta;
00182 }
00183
00184
00185 adr+=ide->size;
00186 }
00187
00188
00189 scan.insn_storage->TightenSize();
00190 program.AddFunction(scan.insn_storage);
00191 scan.insn_storage=NULL;
00192
00193
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);
00207 return(*known);
00208 }
00209 return(NULL);
00210 }
00211
00212
00213 void AssemblerFile_Plaintext::_ParseSymbols_Class_Base(ClassInfo *parent)
00214 {
00215
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
00265 goto breakout;
00266 }
00267 }
00268 breakout:;
00269 }
00270 }
00271
00272
00273 void AssemblerFile_Plaintext::_ParseSymbols_Class_VTable(ClassInfo *parent)
00274 {
00275
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
00325 goto breakout;
00326 }
00327 }
00328 breakout:;
00329 }
00330 }
00331
00332
00333 void AssemblerFile_Plaintext::_ParseSymbols_Class_Size(ClassInfo *parent)
00334 {
00335
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
00353
00354
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
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
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
00417 goto breakout;
00418 }
00419 }
00420 breakout:;
00421 }
00422 }
00423
00424
00425 void AssemblerFile_Plaintext::_ParseSymbols_Symbols(NamespaceInfo *parent)
00426 {
00427
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:
00440 case TextAsmScanner::TS_varsym:
00441 {
00442 if(tok->symref<0)
00443 {
00444
00445
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
00484 {
00485
00486 name.sprintf("%s%%%x",tok->str_val,(uint)file_num);
00487 }
00488
00489 sent.name=name;
00490 sent.symref=tok->symref;
00491
00492
00493
00494
00495 parent->symbol.PushHead(sent);
00496 NamespaceInfo::SymbolEntryE *se=parent->symbol.head();
00497
00498
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
00509
00510 Assert(se->symref>=0);
00511 int srv=parent->map_name2symbol.store(se,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
00529 goto breakout;
00530 }
00531 }
00532 breakout:;
00533 }
00534
00535
00536 void AssemblerFile_Plaintext::_ParseSymbols_Global()
00537 {
00538
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
00563
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
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
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
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
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
00667 nsi=new ClassInfo(name,tok->tid,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);
00674
00675
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
00689
00690
00691
00692
00693
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
00731 goto breakout;
00732 }
00733 }
00734 breakout:;
00735 }
00736
00737
00738 void AssemblerFile_Plaintext::_ParseInfoSection()
00739 {
00740 while(tok)
00741 {
00742 switch(_CurrTokID())
00743 {
00744 case TextAsmScanner::TI_abivers:
00745 abi_version=tok->str_val;
00746 _LexNextToken();
00747 break;
00748
00749 case TextAsmScanner::T_info:
00750 case TextAsmScanner::T_symbols:
00751 case TextAsmScanner::T_locations:
00752 case TextAsmScanner::T_program:
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
00769 if(!nspc_root)
00770 {
00771
00772 nspc_root=new NamespaceInfo(TLString(),NULL);
00773 nspc_root->asm_loc=tok->lloc.loc0;
00774 }
00775
00776 while(tok)
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:
00791 case TextAsmScanner::TS_pglobal:
00792 _ParseSymbols_Global();
00793 break;
00794
00795 case TextAsmScanner::T_info:
00796 case TextAsmScanner::T_symbols:
00797 case TextAsmScanner::T_locations:
00798 case TextAsmScanner::T_program:
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
00815 CritAssert(0);
00816 }
00817
00818
00819 void AssemblerFile_Plaintext::_ParseProgram_Label()
00820 {
00821
00822
00823 switch(_CurrTokID())
00824 {
00825 case TextAsmScanner::TP_mlabel:
00826 {
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;
00837 codemark2prgadr.AddNode(tok->codemark,
00838 scan.insn_storage->length(),&is_known);
00839
00840
00841
00842
00843
00844
00845
00846
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 {
00858
00859
00860 _ParseProgram_FinishFunction();
00861
00862 if(tok->symref<0)
00863 {
00864
00865
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
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);
00883 DELETE(scan.insn_storage); Assert(!scan.insn_storage);
00884
00885
00886 }
00887
00888 } break;
00889 case TextAsmScanner::TP_slabel:
00890 {
00891
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);
00902
00903 if(sa->pfunc)
00904 {
00905 Error(tok->lloc,"duplicate definition of label %s",
00906 tok->str_val);
00907 ++n_errors;
00908
00909
00910 }
00911 else
00912 {
00913
00914
00915
00916
00917
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
00924 sa->se.name.sprintf("init~%%%x",(uint)file_num);
00925 }
00926 else
00927 { sa->se.name=tok->str_val; }
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
00943
00944 sa->pfunc=new ProgramStorage::Function(
00945 0,tok->lloc.loc0);
00946 sa->pfunc->se=&sa->se;
00947
00948
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)
00963 {
00964 switch(_CurrTokID())
00965 {
00966 case TextAsmScanner::TP_slabel:
00967 case TextAsmScanner::TP_mlabel:
00968 case TextAsmScanner::TP_rlabel:
00969 _ParseProgram_Label();
00970 break;
00971
00972 case TextAsmScanner::T_info:
00973 case TextAsmScanner::T_symbols:
00974 case TextAsmScanner::T_locations:
00975 case TextAsmScanner::T_program:
00976 goto breakout;
00977
00978 default:
00979 _ExpectError("label or instruction ");
00980 _LexNextToken();
00981 break;
00982 }
00983 }
00984 breakout:;
00985
00986
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,0);
00997 if(rv)
00998 {
00999
01000 Assert(rv!=1);
01001
01002 return(1);
01003 }
01004
01005
01006 _LexNextToken();
01007
01008
01009 this->filename=scan.CurrLoc();
01010 this->filename.pos->SetLine(-1);
01011 this->filename.pos->SetLPos(-1);
01012
01013 while(tok)
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 }