pstatmnt.pas 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl
  4. Does the parsing of the statements
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pstatmnt;
  19. interface
  20. uses tree;
  21. var
  22. { true, if we are in a except block }
  23. in_except_block : boolean;
  24. { reads a block }
  25. function block(islibrary : boolean) : ptree;
  26. { reads an assembler block }
  27. function assembler_block : ptree;
  28. implementation
  29. uses
  30. globtype,systems,tokens,
  31. strings,cobjects,globals,files,verbose,
  32. symtable,aasm,pass_1,types,scanner,hcodegen,ppu
  33. ,pbase,pexpr,pdecl
  34. {$ifdef i386}
  35. ,i386,tgeni386
  36. {$ifndef NoRa386Int}
  37. ,ra386int
  38. {$endif NoRa386Int}
  39. {$ifndef NoRa386Att}
  40. ,ra386att
  41. {$endif NoRa386Att}
  42. {$ifndef NoRa386Dir}
  43. ,ra386dir
  44. {$endif NoRa386Dir}
  45. {$endif i386}
  46. {$ifdef m68k}
  47. ,m68k,tgen68k
  48. {$ifndef NoRa68kMot}
  49. ,ra68kmot
  50. {$endif NoRa68kMot}
  51. {$endif m68k}
  52. ;
  53. const
  54. statement_level : longint = 0;
  55. function statement : ptree;forward;
  56. function if_statement : ptree;
  57. var
  58. ex,if_a,else_a : ptree;
  59. begin
  60. consume(_IF);
  61. ex:=comp_expr(true);
  62. consume(_THEN);
  63. if token<>_ELSE then
  64. if_a:=statement
  65. else
  66. if_a:=nil;
  67. if token=_ELSE then
  68. begin
  69. consume(_ELSE);
  70. else_a:=statement;
  71. end
  72. else
  73. else_a:=nil;
  74. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  75. end;
  76. { creates a block (list) of statements, til the next END token }
  77. function statements_til_end : ptree;
  78. var
  79. first,last : ptree;
  80. begin
  81. first:=nil;
  82. while token<>_END do
  83. begin
  84. if first=nil then
  85. begin
  86. last:=gennode(statementn,nil,statement);
  87. first:=last;
  88. end
  89. else
  90. begin
  91. last^.left:=gennode(statementn,nil,statement);
  92. last:=last^.left;
  93. end;
  94. if token<>SEMICOLON then
  95. break
  96. else
  97. consume(SEMICOLON);
  98. while token=SEMICOLON do
  99. consume(SEMICOLON);
  100. end;
  101. consume(_END);
  102. statements_til_end:=gensinglenode(blockn,first);
  103. end;
  104. function case_statement : ptree;
  105. var
  106. { contains the label number of currently parsed case block }
  107. aktcaselabel : plabel;
  108. firstlabel : boolean;
  109. root : pcaserecord;
  110. { the typ of the case expression }
  111. casedef : pdef;
  112. procedure newcaselabel(l,h : longint;first:boolean);
  113. var
  114. hcaselabel : pcaserecord;
  115. procedure insertlabel(var p : pcaserecord);
  116. begin
  117. if p=nil then p:=hcaselabel
  118. else
  119. if (p^._low>hcaselabel^._low) and
  120. (p^._low>hcaselabel^._high) then
  121. if (hcaselabel^.statement = p^.statement) and
  122. (p^._low = hcaselabel^._high + 1) then
  123. begin
  124. p^._low := hcaselabel^._low;
  125. freelabel(hcaselabel^._at);
  126. dispose(hcaselabel);
  127. end
  128. else
  129. insertlabel(p^.less)
  130. else
  131. if (p^._high<hcaselabel^._low) and
  132. (p^._high<hcaselabel^._high) then
  133. if (hcaselabel^.statement = p^.statement) and
  134. (p^._high+1 = hcaselabel^._low) then
  135. begin
  136. p^._high := hcaselabel^._high;
  137. freelabel(hcaselabel^._at);
  138. dispose(hcaselabel);
  139. end
  140. else
  141. insertlabel(p^.greater)
  142. else Message(parser_e_double_caselabel);
  143. end;
  144. begin
  145. new(hcaselabel);
  146. hcaselabel^.less:=nil;
  147. hcaselabel^.greater:=nil;
  148. hcaselabel^.statement:=aktcaselabel;
  149. hcaselabel^.firstlabel:=first;
  150. getlabel(hcaselabel^._at);
  151. hcaselabel^._low:=l;
  152. hcaselabel^._high:=h;
  153. insertlabel(root);
  154. end;
  155. var
  156. code,caseexpr,p,instruc,elseblock : ptree;
  157. hl1,hl2 : longint;
  158. begin
  159. consume(_CASE);
  160. caseexpr:=comp_expr(true);
  161. { determines result type }
  162. cleartempgen;
  163. do_firstpass(caseexpr);
  164. casedef:=caseexpr^.resulttype;
  165. if not(is_ordinal(casedef)) then
  166. Message(type_e_ordinal_expr_expected);
  167. consume(_OF);
  168. inc(statement_level);
  169. root:=nil;
  170. instruc:=nil;
  171. repeat
  172. getlabel(aktcaselabel);
  173. firstlabel:=true;
  174. { may be an instruction has more case labels }
  175. repeat
  176. p:=expr;
  177. cleartempgen;
  178. do_firstpass(p);
  179. if (p^.treetype=rangen) then
  180. begin
  181. { type checking for case statements }
  182. if not is_subequal(casedef, p^.left^.resulttype) then
  183. Message(parser_e_case_mismatch);
  184. { type checking for case statements }
  185. if not is_subequal(casedef, p^.right^.resulttype) then
  186. Message(parser_e_case_mismatch);
  187. hl1:=get_ordinal_value(p^.left);
  188. hl2:=get_ordinal_value(p^.right);
  189. testrange(casedef,hl1);
  190. testrange(casedef,hl2);
  191. if hl1>hl2 then
  192. Message(parser_e_case_lower_less_than_upper_bound);
  193. newcaselabel(hl1,hl2,firstlabel);
  194. end
  195. else
  196. begin
  197. { type checking for case statements }
  198. if not is_subequal(casedef, p^.resulttype) then
  199. Message(parser_e_case_mismatch);
  200. hl1:=get_ordinal_value(p);
  201. testrange(casedef,hl1);
  202. newcaselabel(hl1,hl1,firstlabel);
  203. end;
  204. disposetree(p);
  205. if token=COMMA then
  206. consume(COMMA)
  207. else
  208. break;
  209. firstlabel:=false;
  210. until false;
  211. consume(COLON);
  212. { handles instruction block }
  213. p:=gensinglenode(labeln,statement);
  214. p^.labelnr:=aktcaselabel;
  215. { concats instruction }
  216. instruc:=gennode(statementn,instruc,p);
  217. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  218. consume(SEMICOLON);
  219. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  220. if (token=_ELSE) or (token=_OTHERWISE) then
  221. begin
  222. if token=_ELSE then consume(_ELSE)
  223. else consume(_OTHERWISE);
  224. elseblock:=statements_til_end;
  225. end
  226. else
  227. begin
  228. elseblock:=nil;
  229. consume(_END);
  230. end;
  231. dec(statement_level);
  232. code:=gencasenode(caseexpr,instruc,root);
  233. code^.elseblock:=elseblock;
  234. case_statement:=code;
  235. end;
  236. function repeat_statement : ptree;
  237. var
  238. first,last,p_e : ptree;
  239. begin
  240. consume(_REPEAT);
  241. first:=nil;
  242. inc(statement_level);
  243. while token<>_UNTIL do
  244. begin
  245. if first=nil then
  246. begin
  247. last:=gennode(statementn,nil,statement);
  248. first:=last;
  249. end
  250. else
  251. begin
  252. last^.left:=gennode(statementn,nil,statement);
  253. last:=last^.left;
  254. end;
  255. if token<>SEMICOLON then
  256. break;
  257. consume(SEMICOLON);
  258. while token=SEMICOLON do
  259. consume(SEMICOLON);
  260. end;
  261. consume(_UNTIL);
  262. dec(statement_level);
  263. first:=gensinglenode(blockn,first);
  264. p_e:=comp_expr(true);
  265. repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  266. end;
  267. function while_statement : ptree;
  268. var
  269. p_e,p_a : ptree;
  270. begin
  271. consume(_WHILE);
  272. p_e:=comp_expr(true);
  273. consume(_DO);
  274. p_a:=statement;
  275. while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  276. end;
  277. function for_statement : ptree;
  278. var
  279. p_e,tovalue,p_a : ptree;
  280. backward : boolean;
  281. begin
  282. { parse loop header }
  283. consume(_FOR);
  284. p_e:=expr;
  285. if token=_DOWNTO then
  286. begin
  287. consume(_DOWNTO);
  288. backward:=true;
  289. end
  290. else
  291. begin
  292. consume(_TO);
  293. backward:=false;
  294. end;
  295. tovalue:=comp_expr(true);
  296. consume(_DO);
  297. { ... now the instruction }
  298. p_a:=statement;
  299. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  300. end;
  301. function _with_statement : ptree;
  302. var
  303. right,hp,p : ptree;
  304. i,levelcount : longint;
  305. withsymtable,symtab : psymtable;
  306. obj : pobjectdef;
  307. begin
  308. Must_be_valid:=false;
  309. p:=comp_expr(true);
  310. do_firstpass(p);
  311. right:=nil;
  312. if (not codegenerror) and
  313. (p^.resulttype^.deftype in [objectdef,recorddef]) then
  314. begin
  315. case p^.resulttype^.deftype of
  316. objectdef : begin
  317. obj:=pobjectdef(p^.resulttype);
  318. withsymtable:=new(pwithsymtable,init);
  319. withsymtable^.root:=obj^.publicsyms^.root;
  320. withsymtable^.defowner:=obj;
  321. symtab:=withsymtable;
  322. levelcount:=1;
  323. obj:=obj^.childof;
  324. while assigned(obj) do
  325. begin
  326. symtab^.next:=new(pwithsymtable,init);
  327. symtab:=symtab^.next;
  328. symtab^.root:=obj^.publicsyms^.root;
  329. symtab^.defowner:=obj;
  330. obj:=obj^.childof;
  331. inc(levelcount);
  332. end;
  333. symtab^.next:=symtablestack;
  334. symtablestack:=withsymtable;
  335. end;
  336. recorddef : begin
  337. symtab:=precdef(p^.resulttype)^.symtable;
  338. levelcount:=1;
  339. withsymtable:=new(pwithsymtable,init);
  340. withsymtable^.root:=symtab^.root;
  341. withsymtable^.next:=symtablestack;
  342. withsymtable^.defowner:=obj;
  343. symtablestack:=withsymtable;
  344. end;
  345. end;
  346. if token=COMMA then
  347. begin
  348. consume(COMMA);
  349. {$ifdef tp}
  350. right:=_with_statement;
  351. {$else}
  352. right:=_with_statement();
  353. {$endif}
  354. end
  355. else
  356. begin
  357. consume(_DO);
  358. if token<>SEMICOLON then
  359. right:=statement
  360. else
  361. right:=nil;
  362. end;
  363. for i:=1 to levelcount do
  364. symtablestack:=symtablestack^.next;
  365. _with_statement:=genwithnode(pwithsymtable(withsymtable),p,right,levelcount);
  366. end
  367. else
  368. begin
  369. Message(parser_e_false_with_expr);
  370. { try to recover from error }
  371. if token=COMMA then
  372. begin
  373. consume(COMMA);
  374. {$ifdef tp}
  375. hp:=_with_statement;
  376. {$else}
  377. hp:=_with_statement();
  378. {$endif}
  379. end
  380. else
  381. begin
  382. consume(_DO);
  383. { ignore all }
  384. if token<>SEMICOLON then
  385. statement;
  386. end;
  387. _with_statement:=nil;
  388. end;
  389. end;
  390. function with_statement : ptree;
  391. begin
  392. consume(_WITH);
  393. with_statement:=_with_statement;
  394. end;
  395. function raise_statement : ptree;
  396. var
  397. p1,p2 : ptree;
  398. begin
  399. p1:=nil;
  400. p2:=nil;
  401. consume(_RAISE);
  402. if token<>SEMICOLON then
  403. begin
  404. p1:=comp_expr(true);
  405. if (token=ID) and (pattern='AT') then
  406. begin
  407. consume(ID);
  408. p2:=comp_expr(true);
  409. end;
  410. end
  411. else
  412. begin
  413. if not(in_except_block) then
  414. Message(parser_e_no_reraise_possible);
  415. end;
  416. raise_statement:=gennode(raisen,p1,p2);
  417. end;
  418. function try_statement : ptree;
  419. var
  420. p_try_block,p_finally_block,first,last,
  421. p_default,p_specific,hp : ptree;
  422. ot : pobjectdef;
  423. sym : pvarsym;
  424. old_in_except_block : boolean;
  425. exceptsymtable : psymtable;
  426. objname : stringid;
  427. begin
  428. procinfo.flags:=procinfo.flags or
  429. pi_uses_exceptions;
  430. p_default:=nil;
  431. p_specific:=nil;
  432. { read statements to try }
  433. consume(_TRY);
  434. first:=nil;
  435. inc(statement_level);
  436. while (token<>_FINALLY) and (token<>_EXCEPT) do
  437. begin
  438. if first=nil then
  439. begin
  440. last:=gennode(statementn,nil,statement);
  441. first:=last;
  442. end
  443. else
  444. begin
  445. last^.left:=gennode(statementn,nil,statement);
  446. last:=last^.left;
  447. end;
  448. if token<>SEMICOLON then
  449. break;
  450. consume(SEMICOLON);
  451. emptystats;
  452. end;
  453. p_try_block:=gensinglenode(blockn,first);
  454. if token=_FINALLY then
  455. begin
  456. consume(_FINALLY);
  457. p_finally_block:=statements_til_end;
  458. try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  459. dec(statement_level);
  460. end
  461. else
  462. begin
  463. consume(_EXCEPT);
  464. old_in_except_block:=in_except_block;
  465. in_except_block:=true;
  466. p_specific:=nil;
  467. if token=_ON then
  468. { catch specific exceptions }
  469. begin
  470. repeat
  471. consume(_ON);
  472. if token=ID then
  473. begin
  474. getsym(pattern,false);
  475. objname:=pattern;
  476. consume(ID);
  477. { is a explicit name for the exception given ? }
  478. if token=COLON then
  479. begin
  480. consume(COLON);
  481. getsym(pattern,true);
  482. consume(ID);
  483. if srsym^.typ=unitsym then
  484. begin
  485. consume(POINT);
  486. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  487. consume(ID);
  488. end;
  489. if (srsym^.typ=typesym) and
  490. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  491. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  492. ot:=pobjectdef(ptypesym(srsym)^.definition)
  493. else
  494. begin
  495. message(type_e_class_type_expected);
  496. ot:=pobjectdef(generrordef);
  497. end;
  498. sym:=new(pvarsym,init(objname,ot));
  499. exceptsymtable:=new(psymtable,init(stt_exceptsymtable));
  500. exceptsymtable^.insert(sym);
  501. { insert the exception symtable stack }
  502. exceptsymtable^.next:=symtablestack;
  503. symtablestack:=exceptsymtable;
  504. end
  505. else
  506. begin
  507. { only exception type }
  508. if srsym^.typ=unitsym then
  509. begin
  510. consume(POINT);
  511. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  512. consume(ID);
  513. end;
  514. if (srsym^.typ=typesym) and
  515. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  516. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  517. ot:=pobjectdef(ptypesym(srsym)^.definition)
  518. else
  519. begin
  520. message(type_e_class_type_expected);
  521. ot:=pobjectdef(generrordef);
  522. end;
  523. exceptsymtable:=nil;
  524. end;
  525. end
  526. else
  527. consume(ID);
  528. consume(_DO);
  529. hp:=gennode(onn,nil,statement);
  530. if ot^.deftype=errordef then
  531. begin
  532. disposetree(hp);
  533. hp:=genzeronode(errorn);
  534. end;
  535. if p_specific=nil then
  536. begin
  537. last:=hp;
  538. p_specific:=last;
  539. end
  540. else
  541. begin
  542. last^.left:=hp;
  543. last:=last^.left;
  544. end;
  545. { set the informations }
  546. last^.excepttype:=ot;
  547. last^.exceptsymtable:=exceptsymtable;
  548. last^.disposetyp:=dt_onn;
  549. { remove exception symtable }
  550. if assigned(exceptsymtable) then
  551. dellexlevel;
  552. if token<>SEMICOLON then
  553. break;
  554. consume(SEMICOLON);
  555. emptystats;
  556. until (token=_END) or(token=_ELSE);
  557. if token=_ELSE then
  558. { catch the other exceptions }
  559. begin
  560. consume(_ELSE);
  561. p_default:=statements_til_end;
  562. end
  563. else
  564. consume(_END);
  565. end
  566. else
  567. { catch all exceptions }
  568. begin
  569. p_default:=statements_til_end;
  570. end;
  571. dec(statement_level);
  572. in_except_block:=old_in_except_block;
  573. try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  574. end;
  575. end;
  576. function exit_statement : ptree;
  577. var
  578. p : ptree;
  579. begin
  580. consume(_EXIT);
  581. if token=LKLAMMER then
  582. begin
  583. consume(LKLAMMER);
  584. p:=comp_expr(true);
  585. consume(RKLAMMER);
  586. if procinfo.retdef=pdef(voiddef) then
  587. Message(parser_e_void_function)
  588. else
  589. procinfo.funcret_is_valid:=true;
  590. end
  591. else
  592. p:=nil;
  593. exit_statement:=gensinglenode(exitn,p);
  594. end;
  595. function _asm_statement : ptree;
  596. var
  597. asmstat : ptree;
  598. Marker : Pai;
  599. begin
  600. if (aktprocsym^.definition^.options and poinline)<>0 then
  601. Begin
  602. Message1(parser_w_not_supported_for_inline,'asm statement');
  603. Message(parser_w_inlining_disabled);
  604. aktprocsym^.definition^.options:= aktprocsym^.definition^.options and not poinline;
  605. End;
  606. case aktasmmode of
  607. {$ifdef i386}
  608. {$ifndef NoRA386Att}
  609. asmmode_i386_att:
  610. asmstat:=ra386att.assemble;
  611. {$endif NoRA386Att}
  612. {$ifndef NoRA386Int}
  613. asmmode_i386_intel:
  614. asmstat:=ra386int.assemble;
  615. {$endif NoRA386Int}
  616. {$ifndef NoRA386Dir}
  617. asmmode_i386_direct:
  618. asmstat:=ra386dir.assemble;
  619. {$endif NoRA386Dir}
  620. {$endif}
  621. {$ifdef m68k}
  622. {$ifndef NoRA68kMot}
  623. asmmode_m68k_mot:
  624. asmstat:=ra68kmot.assemble;
  625. {$endif NoRA68kMot}
  626. {$endif}
  627. else
  628. Message(parser_f_assembler_reader_not_supported);
  629. end;
  630. { Read first the _ASM statement }
  631. consume(_ASM);
  632. { END is read }
  633. if token=LECKKLAMMER then
  634. begin
  635. { it's possible to specify the modified registers }
  636. consume(LECKKLAMMER);
  637. asmstat^.object_preserved:=true;
  638. if token<>RECKKLAMMER then
  639. repeat
  640. { uppercase, because it's a CSTRING }
  641. uppervar(pattern);
  642. {$ifdef i386}
  643. if pattern='EAX' then
  644. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  645. else if pattern='EBX' then
  646. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  647. else if pattern='ECX' then
  648. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  649. else if pattern='EDX' then
  650. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  651. else if pattern='ESI' then
  652. begin
  653. usedinproc:=usedinproc or ($80 shr byte(R_ESI));
  654. asmstat^.object_preserved:=false;
  655. end
  656. else if pattern='EDI' then
  657. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  658. {$endif i386}
  659. {$ifdef m68k}
  660. if pattern='D0' then
  661. usedinproc:=usedinproc or ($800 shr word(R_D0))
  662. else if pattern='D1' then
  663. usedinproc:=usedinproc or ($800 shr word(R_D1))
  664. else if pattern='D6' then
  665. usedinproc:=usedinproc or ($800 shr word(R_D6))
  666. else if pattern='A0' then
  667. usedinproc:=usedinproc or ($800 shr word(R_A0))
  668. else if pattern='A1' then
  669. usedinproc:=usedinproc or ($800 shr word(R_A1))
  670. {$endif m68k}
  671. else consume(RECKKLAMMER);
  672. consume(CSTRING);
  673. if token=COMMA then consume(COMMA)
  674. else break;
  675. until false;
  676. consume(RECKKLAMMER);
  677. end
  678. else usedinproc:=$ff;
  679. { mark the start and the end of the assembler block for the optimizer }
  680. If Assigned(AsmStat^.p_asm) Then
  681. Begin
  682. Marker := New(Pai_Marker, Init(AsmBlockStart));
  683. AsmStat^.p_asm^.Insert(Marker);
  684. Marker := New(Pai_Marker, Init(AsmBlockEnd));
  685. AsmStat^.p_asm^.Concat(Marker);
  686. End;
  687. _asm_statement:=asmstat;
  688. end;
  689. function new_dispose_statement : ptree;
  690. var
  691. p,p2 : ptree;
  692. ht : ttoken;
  693. again : boolean; { dummy for do_proc_call }
  694. destrukname : stringid;
  695. sym : psym;
  696. classh : pobjectdef;
  697. pd,pd2 : pdef;
  698. store_valid : boolean;
  699. tt : ttreetyp;
  700. begin
  701. ht:=token;
  702. if token=_NEW then consume(_NEW)
  703. else consume(_DISPOSE);
  704. if ht=_NEW then
  705. tt:=hnewn
  706. else
  707. tt:=hdisposen;
  708. consume(LKLAMMER);
  709. p:=comp_expr(true);
  710. { calc return type }
  711. cleartempgen;
  712. Store_valid := Must_be_valid;
  713. Must_be_valid := False;
  714. do_firstpass(p);
  715. Must_be_valid := Store_valid;
  716. {var o:Pobject;
  717. begin
  718. new(o,init); (*Also a valid new statement*)
  719. end;}
  720. if token=COMMA then
  721. begin
  722. { extended syntax of new and dispose }
  723. { function styled new is handled in factor }
  724. consume(COMMA);
  725. { destructors have no parameters }
  726. destrukname:=pattern;
  727. consume(ID);
  728. pd:=p^.resulttype;
  729. pd2:=pd;
  730. if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  731. begin
  732. Message(type_e_pointer_type_expected);
  733. p:=factor(false);
  734. consume(RKLAMMER);
  735. new_dispose_statement:=genzeronode(errorn);
  736. exit;
  737. end;
  738. { first parameter must be an object or class }
  739. if ppointerdef(pd)^.definition^.deftype<>objectdef then
  740. begin
  741. Message(parser_e_pointer_to_class_expected);
  742. new_dispose_statement:=factor(false);
  743. consume_all_until(RKLAMMER);
  744. consume(RKLAMMER);
  745. exit;
  746. end;
  747. { check, if the first parameter is a pointer to a _class_ }
  748. classh:=pobjectdef(ppointerdef(pd)^.definition);
  749. if (classh^.options and oo_is_class)<>0 then
  750. begin
  751. Message(parser_e_no_new_or_dispose_for_classes);
  752. new_dispose_statement:=factor(false);
  753. { while token<>RKLAMMER do
  754. consume(token); }
  755. consume_all_until(RKLAMMER);
  756. consume(RKLAMMER);
  757. exit;
  758. end;
  759. { search cons-/destructor, also in parent classes }
  760. sym:=nil;
  761. while assigned(classh) do
  762. begin
  763. sym:=classh^.publicsyms^.search(pattern);
  764. srsymtable:=classh^.publicsyms;
  765. if assigned(sym) then
  766. break;
  767. classh:=classh^.childof;
  768. end;
  769. { the second parameter of new/dispose must be a call }
  770. { to a cons-/destructor }
  771. if (not assigned(sym)) or (sym^.typ<>procsym) then
  772. begin
  773. Message(parser_e_expr_have_to_be_destructor_call);
  774. new_dispose_statement:=genzeronode(errorn);
  775. end
  776. else
  777. begin
  778. p2:=gensinglenode(tt,p);
  779. if ht=_NEW then
  780. begin
  781. { Constructors can take parameters.}
  782. p2^.resulttype:=ppointerdef(pd)^.definition;
  783. do_member_read(false,sym,p2,pd,again);
  784. end
  785. else
  786. { destructors can't.}
  787. p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  788. { we need the real called method }
  789. cleartempgen;
  790. do_firstpass(p2);
  791. if not codegenerror then
  792. begin
  793. if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  794. Message(parser_e_expr_have_to_be_constructor_call);
  795. if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  796. Message(parser_e_expr_have_to_be_destructor_call);
  797. if ht=_NEW then
  798. begin
  799. p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  800. p2^.right^.resulttype:=pd2;
  801. end;
  802. end;
  803. new_dispose_statement:=p2;
  804. end;
  805. end
  806. else
  807. begin
  808. if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  809. Begin
  810. Message(type_e_pointer_type_expected);
  811. new_dispose_statement:=genzeronode(errorn);
  812. end
  813. else
  814. begin
  815. if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) then
  816. Message(parser_w_use_extended_syntax_for_objects);
  817. case ht of
  818. _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  819. _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  820. end;
  821. end;
  822. end;
  823. consume(RKLAMMER);
  824. end;
  825. function statement_block(starttoken : ttoken) : ptree;
  826. var
  827. first,last : ptree;
  828. filepos : tfileposinfo;
  829. begin
  830. first:=nil;
  831. filepos:=tokenpos;
  832. consume(starttoken);
  833. inc(statement_level);
  834. while not(token in [_END,_FINALIZATION]) do
  835. begin
  836. if first=nil then
  837. begin
  838. last:=gennode(statementn,nil,statement);
  839. first:=last;
  840. end
  841. else
  842. begin
  843. last^.left:=gennode(statementn,nil,statement);
  844. last:=last^.left;
  845. end;
  846. if (token in [_END,_FINALIZATION]) then
  847. break
  848. else
  849. begin
  850. { if no semicolon, then error and go on }
  851. if token<>SEMICOLON then
  852. begin
  853. consume(SEMICOLON);
  854. consume_all_until(SEMICOLON);
  855. end;
  856. consume(SEMICOLON);
  857. end;
  858. emptystats;
  859. end;
  860. { don't consume the finalization token, it is consumed when
  861. reading the finalization block, but allow it only after
  862. an initalization ! }
  863. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  864. consume(_END);
  865. dec(statement_level);
  866. last:=gensinglenode(blockn,first);
  867. set_tree_filepos(last,filepos);
  868. statement_block:=last;
  869. end;
  870. function statement : ptree;
  871. var
  872. p : ptree;
  873. code : ptree;
  874. labelnr : plabel;
  875. filepos : tfileposinfo;
  876. label
  877. ready;
  878. begin
  879. filepos:=tokenpos;
  880. case token of
  881. _GOTO : begin
  882. if not(cs_support_goto in aktmoduleswitches)then
  883. Message(sym_e_goto_and_label_not_supported);
  884. consume(_GOTO);
  885. if (token<>INTCONST) and (token<>ID) then
  886. begin
  887. Message(sym_e_label_not_found);
  888. code:=genzeronode(errorn);
  889. end
  890. else
  891. begin
  892. getsym(pattern,true);
  893. consume(token);
  894. if srsym^.typ<>labelsym then
  895. begin
  896. Message(sym_e_id_is_no_label_id);
  897. code:=genzeronode(errorn);
  898. end
  899. else
  900. code:=genlabelnode(goton,
  901. plabelsym(srsym)^.number);
  902. end;
  903. end;
  904. _BEGIN : code:=statement_block(_BEGIN);
  905. _IF : code:=if_statement;
  906. _CASE : code:=case_statement;
  907. _REPEAT : code:=repeat_statement;
  908. _WHILE : code:=while_statement;
  909. _FOR : code:=for_statement;
  910. _NEW,_DISPOSE : code:=new_dispose_statement;
  911. _WITH : code:=with_statement;
  912. _TRY : code:=try_statement;
  913. _RAISE : code:=raise_statement;
  914. { semicolons,else until and end are ignored }
  915. SEMICOLON,
  916. _ELSE,
  917. _UNTIL,
  918. _END:
  919. code:=genzeronode(niln);
  920. _FAIL : begin
  921. { internalerror(100); }
  922. if (aktprocsym^.definition^.options and poconstructor)=0 then
  923. Message(parser_e_fail_only_in_constructor);
  924. consume(_FAIL);
  925. code:=genzeronode(failn);
  926. end;
  927. _EXIT : code:=exit_statement;
  928. _ASM : begin
  929. code:=_asm_statement;
  930. end;
  931. _EOF : begin
  932. Message(scan_f_end_of_file);
  933. end;
  934. else
  935. begin
  936. if (token=INTCONST) or
  937. ((token=ID) and
  938. not((m_result in aktmodeswitches) and
  939. (pattern='RESULT'))) then
  940. begin
  941. getsym(pattern,true);
  942. lastsymknown:=true;
  943. lastsrsym:=srsym;
  944. { it is NOT necessarily the owner
  945. it can be a withsymtable !!! }
  946. lastsrsymtable:=srsymtable;
  947. if assigned(srsym) and (srsym^.typ=labelsym) then
  948. begin
  949. consume(token);
  950. consume(COLON);
  951. if plabelsym(srsym)^.defined then
  952. Message(sym_e_label_already_defined);
  953. plabelsym(srsym)^.defined:=true;
  954. { statement modifies srsym }
  955. labelnr:=plabelsym(srsym)^.number;
  956. lastsymknown:=false;
  957. { the pointer to the following instruction }
  958. { isn't a very clean way }
  959. {$ifdef tp}
  960. code:=gensinglenode(labeln,statement);
  961. {$else}
  962. code:=gensinglenode(labeln,statement());
  963. {$endif}
  964. code^.labelnr:=labelnr;
  965. { sorry, but there is a jump the easiest way }
  966. goto ready;
  967. end;
  968. end;
  969. p:=expr;
  970. if not(p^.treetype in [calln,assignn,breakn,inlinen,
  971. continuen]) then
  972. Message(cg_e_illegal_expression);
  973. { specify that we don't use the value returned by the call }
  974. { Question : can this be also improtant
  975. for inlinen ??
  976. it is used for :
  977. - dispose of temp stack space
  978. - dispose on FPU stack }
  979. if p^.treetype=calln then
  980. p^.return_value_used:=false;
  981. code:=p;
  982. end;
  983. end;
  984. ready:
  985. if assigned(code) then
  986. set_tree_filepos(code,filepos);
  987. statement:=code;
  988. end;
  989. function block(islibrary : boolean) : ptree;
  990. var
  991. funcretsym : pfuncretsym;
  992. begin
  993. if procinfo.retdef<>pdef(voiddef) then
  994. begin
  995. { if the current is a function aktprocsym is non nil }
  996. { and there is a local symtable set }
  997. funcretsym:=new(pfuncretsym,init(aktprocsym^.name,@procinfo));
  998. { insert in local symtable }
  999. symtablestack^.insert(funcretsym);
  1000. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  1001. procinfo.retoffset:=-funcretsym^.address;
  1002. procinfo.funcretsym:=funcretsym;
  1003. end;
  1004. read_declarations(islibrary);
  1005. { temporary space is set, while the BEGIN of the procedure }
  1006. if (symtablestack^.symtabletype=localsymtable) then
  1007. procinfo.firsttemp := -symtablestack^.datasize
  1008. else procinfo.firsttemp := 0;
  1009. { space for the return value }
  1010. { !!!!! this means that we can not set the return value
  1011. in a subfunction !!!!! }
  1012. { because we don't know yet where the address is }
  1013. if procinfo.retdef<>pdef(voiddef) then
  1014. begin
  1015. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  1016. { if (procinfo.retdef^.deftype=orddef) or
  1017. (procinfo.retdef^.deftype=pointerdef) or
  1018. (procinfo.retdef^.deftype=enumdef) or
  1019. (procinfo.retdef^.deftype=procvardef) or
  1020. (procinfo.retdef^.deftype=floatdef) or
  1021. (
  1022. (procinfo.retdef^.deftype=setdef) and
  1023. (psetdef(procinfo.retdef)^.settype=smallset)
  1024. ) then }
  1025. begin
  1026. { the space has been set in the local symtable }
  1027. procinfo.retoffset:=-funcretsym^.address;
  1028. if (procinfo.flags and pi_operator)<>0 then
  1029. {opsym^.address:=procinfo.call_offset; is wrong PM }
  1030. opsym^.address:=-procinfo.retoffset;
  1031. { eax is modified by a function }
  1032. {$ifdef i386}
  1033. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  1034. if is_64bitint(procinfo.retdef) then
  1035. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  1036. {$endif}
  1037. {$ifdef m68k}
  1038. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1039. if is_64bitint(procinfo.retdef) then
  1040. usedinproc:=usedinproc or ($800 shr byte(R_D1))
  1041. {$endif}
  1042. end;
  1043. end;
  1044. {Unit initialization?.}
  1045. if (lexlevel=unit_init_level) and (current_module^.is_unit) then
  1046. if (token=_END) then
  1047. begin
  1048. consume(_END);
  1049. block:=nil;
  1050. end
  1051. else
  1052. begin
  1053. if token=_INITIALIZATION then
  1054. begin
  1055. current_module^.flags:=current_module^.flags or uf_init;
  1056. block:=statement_block(_INITIALIZATION);
  1057. end
  1058. else if (token=_FINALIZATION) then
  1059. begin
  1060. if (current_module^.flags and uf_finalize)<>0 then
  1061. block:=statement_block(_FINALIZATION)
  1062. else
  1063. begin
  1064. block:=nil;
  1065. exit;
  1066. end;
  1067. end
  1068. else
  1069. begin
  1070. current_module^.flags:=current_module^.flags or uf_init;
  1071. block:=statement_block(_BEGIN);
  1072. end;
  1073. end
  1074. else
  1075. block:=statement_block(_BEGIN);
  1076. end;
  1077. function assembler_block : ptree;
  1078. begin
  1079. read_declarations(false);
  1080. { temporary space is set, while the BEGIN of the procedure }
  1081. if symtablestack^.symtabletype=localsymtable then
  1082. procinfo.firsttemp := -symtablestack^.datasize
  1083. else procinfo.firsttemp := 0;
  1084. { assembler code does not allocate }
  1085. { space for the return value }
  1086. if procinfo.retdef<>pdef(voiddef) then
  1087. begin
  1088. if ret_in_acc(procinfo.retdef) then
  1089. begin
  1090. { in assembler code the result should be directly in %eax
  1091. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1092. procinfo.firsttemp:=procinfo.retoffset; }
  1093. {$ifdef i386}
  1094. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1095. {$endif}
  1096. {$ifdef m68k}
  1097. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1098. {$endif}
  1099. end
  1100. else if not is_fpu(procinfo.retdef) then
  1101. { should we allow assembler functions of big elements ? }
  1102. Message(parser_e_asm_incomp_with_function_return);
  1103. end;
  1104. { set the framepointer to esp for assembler functions }
  1105. { but only if the are no local variables }
  1106. { added no parameter also (PM) }
  1107. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1108. (aktprocsym^.definition^.localst^.datasize=0) and
  1109. (aktprocsym^.definition^.parast^.datasize=0) then
  1110. begin
  1111. {$ifdef i386}
  1112. procinfo.framepointer:=R_ESP;
  1113. {$endif}
  1114. {$ifdef m68k}
  1115. procinfo.framepointer:=R_SP;
  1116. {$endif}
  1117. { set the right value for parameters }
  1118. dec(aktprocsym^.definition^.parast^.call_offset,target_os.size_of_pointer);
  1119. dec(procinfo.call_offset,target_os.size_of_pointer);
  1120. end;
  1121. { force the asm statement }
  1122. if token<>_ASM then
  1123. consume(_ASM);
  1124. Procinfo.Flags := ProcInfo.Flags Or pi_is_assembler;
  1125. assembler_block:=_asm_statement;
  1126. { becuase the END is already read we need to get the
  1127. last_endtoken_filepos here (PFV) }
  1128. last_endtoken_filepos:=tokenpos;
  1129. end;
  1130. end.
  1131. {
  1132. $Log$
  1133. Revision 1.62 1999-01-27 13:06:57 pierre
  1134. * memory leak in case optimization fixed
  1135. Revision 1.61 1999/01/25 22:49:09 peter
  1136. * more fixes for the on bug with unknown id
  1137. Revision 1.60 1999/01/23 23:29:38 florian
  1138. * first running version of the new code generator
  1139. * when compiling exceptions under Linux fixed
  1140. Revision 1.59 1999/01/21 16:41:02 pierre
  1141. * fix for constructor inside with statements
  1142. Revision 1.58 1999/01/05 08:20:07 florian
  1143. * mainly problem with invalid case ranges fixed (reported by Jonas)
  1144. Revision 1.57 1998/12/29 18:48:15 jonas
  1145. + optimize pascal code surrounding assembler blocks
  1146. Revision 1.56 1998/12/23 22:52:56 peter
  1147. * fixed new(x) crash if x contains an error
  1148. Revision 1.55 1998/12/16 12:30:59 jonas
  1149. * released CaseRange
  1150. Revision 1.54 1998/12/15 22:32:24 jonas
  1151. + convert consecutive case labels to a single range (-dCaseRange)
  1152. Revision 1.53 1998/12/15 11:52:18 peter
  1153. * fixed dup release of statement label in case
  1154. Revision 1.52 1998/12/11 00:03:37 peter
  1155. + globtype,tokens,version unit splitted from globals
  1156. Revision 1.51 1998/12/10 09:47:24 florian
  1157. + basic operations with int64/qord (compiler with -dint64)
  1158. + rtti of enumerations extended: names are now written
  1159. Revision 1.50 1998/11/13 15:40:25 pierre
  1160. + added -Se in Makefile cvstest target
  1161. + lexlevel cleanup
  1162. normal_function_level main_program_level and unit_init_level defined
  1163. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  1164. (test added in code !)
  1165. * -Un option was wrong
  1166. * _FAIL and _SELF only keyword inside
  1167. constructors and methods respectively
  1168. Revision 1.49 1998/11/12 12:55:17 pierre
  1169. * fix for bug0176 and bug0177
  1170. Revision 1.48 1998/11/05 23:43:24 peter
  1171. * fixed assembler directive and then not an ASM statement
  1172. Revision 1.47 1998/10/30 16:20:22 peter
  1173. * fixed dispose(destructor) crash when destructor didn't exists
  1174. Revision 1.46 1998/10/20 08:06:53 pierre
  1175. * several memory corruptions due to double freemem solved
  1176. => never use p^.loc.location:=p^.left^.loc.location;
  1177. + finally I added now by default
  1178. that ra386dir translates global and unit symbols
  1179. + added a first field in tsymtable and
  1180. a nextsym field in tsym
  1181. (this allows to obtain ordered type info for
  1182. records and objects in gdb !)
  1183. Revision 1.45 1998/10/19 08:55:01 pierre
  1184. * wrong stabs info corrected once again !!
  1185. + variable vmt offset with vmt field only if required
  1186. implemented now !!!
  1187. Revision 1.44 1998/10/13 13:10:27 peter
  1188. * new style for m68k/i386 infos and enums
  1189. Revision 1.43 1998/10/08 13:46:22 peter
  1190. * added eof message
  1191. * fixed unit init section parsing with finalize
  1192. Revision 1.42 1998/09/26 17:45:38 peter
  1193. + idtoken and only one token table
  1194. Revision 1.41 1998/09/24 23:49:15 peter
  1195. + aktmodeswitches
  1196. Revision 1.40 1998/09/23 21:53:04 florian
  1197. * the following doesn't work: on texception do, was a parser error, fixed
  1198. Revision 1.39 1998/09/21 10:26:07 peter
  1199. * merged fix
  1200. Revision 1.38.2.1 1998/09/21 10:24:43 peter
  1201. * fixed error recovery with with
  1202. Revision 1.38 1998/09/04 08:42:04 peter
  1203. * updated some error messages
  1204. Revision 1.37 1998/08/21 14:08:52 pierre
  1205. + TEST_FUNCRET now default (old code removed)
  1206. works also for m68k (at least compiles)
  1207. Revision 1.36 1998/08/20 21:36:41 peter
  1208. * fixed 'with object do' bug
  1209. Revision 1.35 1998/08/20 09:26:42 pierre
  1210. + funcret setting in underproc testing
  1211. compile with _dTEST_FUNCRET
  1212. Revision 1.34 1998/08/17 10:10:09 peter
  1213. - removed OLDPPU
  1214. Revision 1.33 1998/08/12 19:39:30 peter
  1215. * fixed some crashes
  1216. Revision 1.32 1998/08/10 14:50:17 peter
  1217. + localswitches, moduleswitches, globalswitches splitting
  1218. Revision 1.31 1998/08/02 16:41:59 florian
  1219. * on o : tobject do should also work now, the exceptsymtable shouldn't be
  1220. disposed by dellexlevel
  1221. Revision 1.30 1998/07/30 16:07:10 florian
  1222. * try ... expect <statement> end; works now
  1223. Revision 1.29 1998/07/30 13:30:37 florian
  1224. * final implemenation of exception support, maybe it needs
  1225. some fixes :)
  1226. Revision 1.28 1998/07/30 11:18:18 florian
  1227. + first implementation of try ... except on .. do end;
  1228. * limitiation of 65535 bytes parameters for cdecl removed
  1229. Revision 1.27 1998/07/28 21:52:55 florian
  1230. + implementation of raise and try..finally
  1231. + some misc. exception stuff
  1232. Revision 1.26 1998/07/27 21:57:14 florian
  1233. * fix to allow tv like stream registration:
  1234. @tmenu.load doesn't work if load had parameters or if load was only
  1235. declared in an anchestor class of tmenu
  1236. Revision 1.25 1998/07/14 21:46:53 peter
  1237. * updated messages file
  1238. Revision 1.24 1998/07/10 10:48:42 peter
  1239. * fixed realnumber scanning
  1240. * [] after asmblock was not uppercased anymore
  1241. Revision 1.23 1998/06/25 08:48:18 florian
  1242. * first version of rtti support
  1243. Revision 1.22 1998/06/24 14:48:36 peter
  1244. * ifdef newppu -> ifndef oldppu
  1245. Revision 1.21 1998/06/24 14:06:34 peter
  1246. * fixed the name changes
  1247. Revision 1.20 1998/06/23 14:00:16 peter
  1248. * renamed RA* units
  1249. Revision 1.19 1998/06/08 22:59:50 peter
  1250. * smartlinking works for win32
  1251. * some defines to exclude some compiler parts
  1252. Revision 1.18 1998/06/05 14:37:35 pierre
  1253. * fixes for inline for operators
  1254. * inline procedure more correctly restricted
  1255. Revision 1.17 1998/06/04 09:55:43 pierre
  1256. * demangled name of procsym reworked to become independant of the mangling scheme
  1257. Revision 1.16 1998/06/02 17:03:04 pierre
  1258. * with node corrected for objects
  1259. * small bugs for SUPPORT_MMX fixed
  1260. Revision 1.15 1998/05/30 14:31:06 peter
  1261. + $ASMMODE
  1262. Revision 1.14 1998/05/29 09:58:14 pierre
  1263. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  1264. (probably a merging problem)
  1265. * errors at start of line were lost
  1266. Revision 1.13 1998/05/28 17:26:50 peter
  1267. * fixed -R switch, it didn't work after my previous akt/init patch
  1268. * fixed bugs 110,130,136
  1269. Revision 1.12 1998/05/21 19:33:33 peter
  1270. + better procedure directive handling and only one table
  1271. Revision 1.11 1998/05/20 09:42:35 pierre
  1272. + UseTokenInfo now default
  1273. * unit in interface uses and implementation uses gives error now
  1274. * only one error for unknown symbol (uses lastsymknown boolean)
  1275. the problem came from the label code !
  1276. + first inlined procedures and function work
  1277. (warning there might be allowed cases were the result is still wrong !!)
  1278. * UseBrower updated gives a global list of all position of all used symbols
  1279. with switch -gb
  1280. Revision 1.10 1998/05/11 13:07:56 peter
  1281. + $ifdef NEWPPU for the new ppuformat
  1282. + $define GDB not longer required
  1283. * removed all warnings and stripped some log comments
  1284. * no findfirst/findnext anymore to remove smartlink *.o files
  1285. Revision 1.9 1998/05/06 08:38:46 pierre
  1286. * better position info with UseTokenInfo
  1287. UseTokenInfo greatly simplified
  1288. + added check for changed tree after first time firstpass
  1289. (if we could remove all the cases were it happen
  1290. we could skip all firstpass if firstpasscount > 1)
  1291. Only with ExtDebug
  1292. Revision 1.8 1998/05/05 12:05:42 florian
  1293. * problems with properties fixed
  1294. * crash fixed: i:=l when i and l are undefined, was a problem with
  1295. implementation of private/protected
  1296. Revision 1.7 1998/05/01 16:38:46 florian
  1297. * handling of private and protected fixed
  1298. + change_keywords_to_tp implemented to remove
  1299. keywords which aren't supported by tp
  1300. * break and continue are now symbols of the system unit
  1301. + widestring, longstring and ansistring type released
  1302. Revision 1.6 1998/04/30 15:59:42 pierre
  1303. * GDB works again better :
  1304. correct type info in one pass
  1305. + UseTokenInfo for better source position
  1306. * fixed one remaining bug in scanner for line counts
  1307. * several little fixes
  1308. Revision 1.5 1998/04/29 10:33:59 pierre
  1309. + added some code for ansistring (not complete nor working yet)
  1310. * corrected operator overloading
  1311. * corrected nasm output
  1312. + started inline procedures
  1313. + added starstarn : use ** for exponentiation (^ gave problems)
  1314. + started UseTokenInfo cond to get accurate positions
  1315. Revision 1.4 1998/04/08 16:58:05 pierre
  1316. * several bugfixes
  1317. ADD ADC and AND are also sign extended
  1318. nasm output OK (program still crashes at end
  1319. and creates wrong assembler files !!)
  1320. procsym types sym in tdef removed !!
  1321. }