pstatmnt.pas 49 KB

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