00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <lib/sconfig.h>
00018
00019 #include <lib/serror.h>
00020 #include <lib/tl/linkedlist.h>
00021 #include <lib/lex/location.h>
00022 #include <lib/sourcepos/sparchive.h>
00023 #include <lib/tl/tlstring.h>
00024 #include <lib/message/message.h>
00025
00026 #include <unistd.h>
00027 #include <stdio.h>
00028 #include <errno.h>
00029
00030
00031
00032 #undef _InternalFlexScannerBase
00033 #include "scannerbase.h"
00034
00035
00036
00037
00038 _InternalFlexScannerBase::Config::Config()
00039 {
00040
00041 loc_use_lpos=1;
00042 tab_width=8;
00043 max_file_depth=32;
00044 ahead_toks_wanted=1;
00045 old_toks_wanted=16;
00046 }
00047
00048
00049
00050 bool _InternalFlexScannerBase::TokenEntry::MayBeCleared() const
00051 {
00052
00053
00054 return(1);
00055 }
00056
00057 void _InternalFlexScannerBase::TokenEntry::clear(bool )
00058 {
00059
00060
00061 token=-1;
00062 lloc=SCLocationRange();
00063 }
00064
00065
00066 _InternalFlexScannerBase::TokenEntry *_InternalFlexScannerBase::
00067 AllocTokenEntry()
00068 {
00069 return new TokenEntry();
00070 }
00071
00072
00073
00074
00075 ssize_t _InternalFlexScannerBase::LexerInput::read(char *buf,size_t len)
00076 {
00077
00078
00079 if(fp)
00080 {
00081 errno=0;
00082 size_t result;
00083 if(feof(fp))
00084 { result=0; }
00085 else while( (result = fread(buf,1,len,fp))==0 && ferror(fp) )
00086 {
00087 if(errno!=EINTR)
00088 {
00089 fprintf(stderr,"reading %s failed: %s\n",
00090 fp_path.str(),strerror(errno));
00091 return(-1);
00092 break;
00093 }
00094 errno=0;
00095 clearerr(fp);
00096 }
00097
00098
00099 return(result);
00100 }
00101
00102 return(0);
00103 }
00104
00105
00106 int _InternalFlexScannerBase::LexerInput::OpenFile(const TLString &path,
00107 SError &error)
00108 {
00109
00110
00111 if(fp) return(1);
00112
00113 if(path)
00114 {
00115 fp=fopen(path.str(),"r");
00116 if(!fp)
00117 { error=SError("Open failed blah blah",1); return(-2); }
00118
00119 fp_path=path;
00120 }
00121 else
00122 {
00123 fp=stdin;
00124 fp_path="[stdin]";
00125 }
00126
00127 return(0);
00128 }
00129
00130
00131 _InternalFlexScannerBase::LexerInput::LexerInput(LexerInput *_down) :
00132 down(_down),
00133 fp(NULL),
00134 fp_path(),
00135 saved(-1,-1),
00136 must_pop_state(0),
00137 must_pop_pos_arch(0),
00138 read_eof(0),
00139 special_next_tok(-1),
00140 next_toks(),
00141 prev_toks()
00142 {
00143
00144 }
00145
00146 _InternalFlexScannerBase::LexerInput::~LexerInput()
00147 {
00148 if(fp)
00149 {
00150 if(fp!=stdin) fclose(fp);
00151 fp=NULL;
00152 }
00153
00154 while(!next_toks.IsEmpty())
00155 {
00156 Error("OOPS: ~ALSInput: Token %d left in next_toks.",
00157 next_toks.first()->token);
00158 next_toks.first()->clear(1);
00159 delete next_toks.PopFirst();
00160 }
00161
00162
00163
00164 while(!prev_toks.IsEmpty())
00165 { delete prev_toks.PopFirst(); }
00166 }
00167
00168
00169
00170 SCLocation _InternalFlexScannerBase::_MakeCurrLoc() const
00171 {
00172 return(SCLocation(pos_arch->GetPos(p0.line,
00173 cfg.loc_use_lpos ? p0.lpos : -1)));
00174 }
00175
00176 SCLocation _InternalFlexScannerBase::_MakeCurrEndLoc() const
00177 {
00178 return(SCLocation(pos_arch->GetPos(p1.line,
00179 cfg.loc_use_lpos ? p1.lpos : -1)));
00180 }
00181
00183 SCLocationRange _InternalFlexScannerBase::_MakeCurrLocRange() const
00184 {
00185 return(SCLocationRange(_MakeCurrLoc(),_MakeCurrEndLoc()));
00186 }
00187
00188
00189
00190 void _InternalFlexScannerBase::_pi_char(char c)
00191 {
00192 switch(c)
00193 {
00194 case '\n': _pi_line(); break;
00195 case '\r': break;
00196 case '\t': _pi_tab(); break;
00197 default: ++p1.lpos; break;
00198 }
00199 }
00200
00201 void _InternalFlexScannerBase::_pi_str(const char *str,size_t len)
00202 {
00203 for(const char *c=str,*cend=str+len; c<cend; c++)
00204 { _pi_char(*c); }
00205 }
00206
00207 void _InternalFlexScannerBase::_pi_eof()
00208 {
00209 Assert(top_inp);
00210 top_inp->read_eof=1;
00211
00212 }
00213
00214
00215
00216
00217
00218 int _InternalFlexScannerBase::SetInput(const TLString &path,SError &error,
00219 bool included,
00220 int first_token,XYPos alt_pos,SourcePositionArchive *alt_pos_arch)
00221 {
00222 Assert(magic==MyMagic);
00223
00224
00225 if(included && alt_pos_arch) return(-3);
00226 if(scanner && !included) return(1);
00227
00228 if(included && file_depth>=cfg.max_file_depth) return(-4);
00229
00230
00231 LexerInput *inp=new LexerInput(NULL);
00232 if(inp->OpenFile(path,error))
00233 { DELETE(inp); return(-2); }
00234
00235
00236 if(first_token>=0)
00237 { inp->special_next_tok=first_token; }
00238
00239
00240 if(!scanner)
00241 { _lex_init(&scanner); }
00242
00243 int rv=_SetInputBH(inp,included,alt_pos,alt_pos_arch);
00244
00245
00246 inp->down=top_inp;
00247 top_inp=inp;
00248
00249 return(rv);
00250 }
00251
00252
00253 _InternalFlexScannerBase::TokenEntry *_InternalFlexScannerBase::LexNextToken()
00254 {
00255 if(!scanner) return(NULL);
00256
00257 for(;;)
00258 {
00259 cont2:;
00260
00261
00262
00263
00264
00265
00266 Assert(magic==MyMagic);
00267 Assert(top_inp);
00268
00269 if(!read_inp)
00270 { read_inp=top_inp; }
00271
00272
00273
00274 LexerInput *from_inp=NULL;
00275
00276
00277
00278
00279
00280 if(read_inp!=top_inp)
00281 {
00282
00283 if(read_inp->next_toks.IsEmpty())
00284 {
00285
00286 read_inp=top_inp;
00287 }
00288 else
00289 { from_inp=read_inp; }
00290 }
00291 if(read_inp==top_inp)
00292 {
00293
00294 LexerInput *inp=top_inp;
00295
00296
00297 int n_next=inp->next_toks.count();
00298 int n_prev=inp->prev_toks.count();
00299
00300
00301 while(n_next<cfg.ahead_toks_wanted && !inp->read_eof)
00302 {
00303
00304 TokenEntry *te=NULL;
00305 if(n_prev>cfg.old_toks_wanted)
00306 {
00307 te=inp->prev_toks.PopFirst();
00308 --n_prev;
00309
00310 if(te->MayBeCleared())
00311 { te->clear(); }
00312 else
00313 {
00314 zombie_list.append(te);
00315 ++zombie_list_nents;
00316 te=NULL;
00317 }
00318 }
00319 if(!te)
00320 { te=AllocTokenEntry(); }
00321
00322
00323 bool state_change=0;
00324 _RawYYLex(te);
00325 if(inp!=top_inp)
00326 { inp=top_inp; state_change=1; }
00327 inp->next_toks.append(te);
00328 ++n_next;
00329
00330
00331 if(state_change)
00332 { goto cont2; }
00333 }
00334 while(n_prev>cfg.old_toks_wanted)
00335 {
00336 TokenEntry *tmp=inp->prev_toks.PopFirst();
00337 --n_prev;
00338
00339 if(tmp->MayBeCleared())
00340 { delete tmp; }
00341 else
00342 { zombie_list.append(tmp); ++zombie_list_nents; }
00343
00344 if(!inp->read_eof)
00345 { Warning("HMMM: Del Old Tok."); }
00346 }
00347 from_inp=inp;
00348 }
00349
00350 _TidyUpZombieList();
00351
00352
00353 TokenEntry *te=from_inp->next_toks.PopFirst();
00354 Assert(te);
00355
00356
00357
00358 Assert(cfg.ahead_toks_wanted>1 || from_inp->next_toks.IsEmpty());
00359
00360 from_inp->prev_toks.append(te);
00361
00362
00363
00364
00365 if(te->token)
00366 {
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 return(te);
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 read_inp=NULL;
00390 if(_wrap())
00391 {
00392
00393 break;
00394 }
00395 }
00396
00397 return(NULL);
00398 }
00399
00400
00401 void _InternalFlexScannerBase::_RawYYLex(TokenEntry *dest)
00402 {
00403 Assert(magic==MyMagic);
00404
00405
00406 p0=p1;
00407
00408
00409 int tok_rv;
00410 if(top_inp->special_next_tok>=0)
00411 {
00412 tok_rv=top_inp->special_next_tok;
00413 top_inp->special_next_tok=-1;
00414 }
00415 else
00416 {
00417 lex_token=dest;
00418 tok_rv=_lex(scanner);
00419 lex_token=NULL;
00420 }
00421
00422
00423 dest->token=tok_rv;
00424 if(!tok_rv) Assert(top_inp->read_eof || n_errors);
00425
00426
00427 dest->lloc=_MakeCurrLocRange();
00428
00429
00430
00431
00432
00433 }
00434
00435
00436
00437 void _InternalFlexScannerBase::__TidyUpZombieList(bool force)
00438 {
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 int _cnt=0,_nforce=0,_ntry=0;
00451 int ncheck = force ? -1 : 2*zombie_list_threash;
00452 for(TokenEntry *_i=zombie_list.last(); _i && ncheck; ncheck--)
00453 {
00454 TokenEntry *i=_i;
00455 _i=_i->prev;
00456
00457 bool we_may=i->MayBeCleared();
00458 if(force && !we_may)
00459 { ++_nforce; we_may=1; }
00460
00461 if(we_may)
00462 {
00463 i->clear(force);
00464
00465 delete zombie_list.dequeue(i);
00466 --zombie_list_nents;
00467 ++_cnt;
00468 }
00469
00470 ++_ntry;
00471 }
00472
00473
00474 if(_cnt<_ntry || (force && (_cnt || _nforce)))
00475 { Warning(
00476 "Hmmm: deleted %d (%d forced, %d tried) zombie tokens, %d left "
00477 "(force=%d).",
00478 _cnt,_nforce,_ntry,zombie_list_nents,int(force)); }
00479 if(force)
00480 { Assert(zombie_list_nents==0); }
00481
00482 Assert(zombie_list_nents==zombie_list.count());
00483 last_zombie_list_nents=zombie_list_nents;
00484 }
00485
00486
00487 void _InternalFlexScannerBase::_reset(bool no_virtuals)
00488 {
00489
00490
00491 Assert(magic==MyMagic);
00492
00493
00494 Assert(!lex_token);
00495
00496 if(scanner)
00497 {
00498
00499 read_inp=NULL;
00500 while(!_wrap());
00501
00502 Assert(!file_depth);
00503 Assert(!top_inp);
00504
00505 _lex_destroy(scanner);
00506 scanner=NULL;
00507 }
00508
00509 p0.line=1; p1.line=1;
00510 p0.lpos=0; p1.lpos=0;
00511
00512 if(pos_arch)
00513 {
00514 if(pos_arch_allocated)
00515 { delete pos_arch; }
00516 pos_arch=NULL;
00517 pos_arch_allocated=0;
00518 }
00519
00520 _TidyUpZombieList(1);
00521
00522 n_errors=0;
00523
00524 top_inp=NULL;
00525 read_inp=NULL;
00526 file_depth=0;
00527
00528
00529 if(!no_virtuals)
00530 { reset(); }
00531 }
00532
00533
00534 void _InternalFlexScannerBase::reset()
00535 {
00536
00537
00538 }
00539
00540
00541 _InternalFlexScannerBase::_InternalFlexScannerBase() :
00542 zombie_list(),
00543 p0(1,0),
00544 p1(1,0),
00545 cfg()
00546 {
00547 magic=MyMagic;
00548 scanner=NULL;
00549 lex_token=NULL;
00550
00551 top_inp=NULL;
00552 read_inp=NULL;
00553
00554 zombie_list_nents=0;
00555 last_zombie_list_nents=0;
00556
00557 pos_arch=NULL;
00558 pos_arch_allocated=0;
00559
00560
00561
00562
00563 }
00564
00565 _InternalFlexScannerBase::~_InternalFlexScannerBase()
00566 {
00567
00568
00569
00570
00571 Assert(!scanner);
00572
00573 Assert(!top_inp);
00574 Assert(!read_inp);
00575
00576 Assert(magic==MyMagic);
00577 magic=0;
00578 }
00579
00580
00581
00582 int _InternalFlexScannerBase::_lex(void * )
00583 {
00584
00585 CritAssert(0);
00586 }
00587
00588 int _InternalFlexScannerBase::_lex_init(void ** )
00589 {
00590
00591 CritAssert(0);
00592 }
00593
00594 void _InternalFlexScannerBase::_lex_destroy(void * )
00595 {
00596
00597 CritAssert(0);
00598 }
00599
00600 int _InternalFlexScannerBase::_wrap()
00601 {
00602
00603 CritAssert(0);
00604 return(0);
00605 }
00606
00607 int _InternalFlexScannerBase::_SetInputBH(LexerInput * ,
00608 bool ,
00609 XYPos ,SourcePositionArchive * )
00610 {
00611
00612 CritAssert(0);
00613 return(-5);
00614 }