pstatmnt.pas 48 KB

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