pstatmnt.pas 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441
  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. if is_64bitint(procinfo.retdef) then
  1007. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  1008. {$endif}
  1009. {$ifdef m68k}
  1010. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1011. if is_64bitint(procinfo.retdef) then
  1012. usedinproc:=usedinproc or ($800 shr byte(R_D1))
  1013. {$endif}
  1014. end;
  1015. end;
  1016. {Unit initialization?.}
  1017. if (lexlevel=unit_init_level) and (current_module^.is_unit) then
  1018. if (token=_END) then
  1019. begin
  1020. consume(_END);
  1021. block:=nil;
  1022. end
  1023. else
  1024. begin
  1025. if token=_INITIALIZATION then
  1026. begin
  1027. current_module^.flags:=current_module^.flags or uf_init;
  1028. block:=statement_block(_INITIALIZATION);
  1029. end
  1030. else if (token=_FINALIZATION) then
  1031. begin
  1032. if (current_module^.flags and uf_finalize)<>0 then
  1033. block:=statement_block(_FINALIZATION)
  1034. else
  1035. begin
  1036. block:=nil;
  1037. exit;
  1038. end;
  1039. end
  1040. else
  1041. begin
  1042. current_module^.flags:=current_module^.flags or uf_init;
  1043. block:=statement_block(_BEGIN);
  1044. end;
  1045. end
  1046. else
  1047. block:=statement_block(_BEGIN);
  1048. end;
  1049. function assembler_block : ptree;
  1050. begin
  1051. read_declarations(false);
  1052. { temporary space is set, while the BEGIN of the procedure }
  1053. if symtablestack^.symtabletype=localsymtable then
  1054. procinfo.firsttemp := -symtablestack^.datasize
  1055. else procinfo.firsttemp := 0;
  1056. { assembler code does not allocate }
  1057. { space for the return value }
  1058. if procinfo.retdef<>pdef(voiddef) then
  1059. begin
  1060. if ret_in_acc(procinfo.retdef) then
  1061. begin
  1062. { in assembler code the result should be directly in %eax
  1063. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1064. procinfo.firsttemp:=procinfo.retoffset; }
  1065. {$ifdef i386}
  1066. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1067. {$endif}
  1068. {$ifdef m68k}
  1069. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1070. {$endif}
  1071. end
  1072. else if not is_fpu(procinfo.retdef) then
  1073. { should we allow assembler functions of big elements ? }
  1074. Message(parser_e_asm_incomp_with_function_return);
  1075. end;
  1076. { set the framepointer to esp for assembler functions }
  1077. { but only if the are no local variables }
  1078. { added no parameter also (PM) }
  1079. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1080. (aktprocsym^.definition^.localst^.datasize=0) and
  1081. (aktprocsym^.definition^.parast^.datasize=0) then
  1082. begin
  1083. {$ifdef i386}
  1084. procinfo.framepointer:=R_ESP;
  1085. {$endif}
  1086. {$ifdef m68k}
  1087. procinfo.framepointer:=R_SP;
  1088. {$endif}
  1089. { set the right value for parameters }
  1090. dec(aktprocsym^.definition^.parast^.call_offset,target_os.size_of_pointer);
  1091. dec(procinfo.call_offset,target_os.size_of_pointer);
  1092. end;
  1093. { force the asm statement }
  1094. if token<>_ASM then
  1095. consume(_ASM);
  1096. assembler_block:=_asm_statement;
  1097. { becuase the END is already read we need to get the
  1098. last_endtoken_filepos here (PFV) }
  1099. last_endtoken_filepos:=tokenpos;
  1100. end;
  1101. end.
  1102. {
  1103. $Log$
  1104. Revision 1.51 1998-12-10 09:47:24 florian
  1105. + basic operations with int64/qord (compiler with -dint64)
  1106. + rtti of enumerations extended: names are now written
  1107. Revision 1.50 1998/11/13 15:40:25 pierre
  1108. + added -Se in Makefile cvstest target
  1109. + lexlevel cleanup
  1110. normal_function_level main_program_level and unit_init_level defined
  1111. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  1112. (test added in code !)
  1113. * -Un option was wrong
  1114. * _FAIL and _SELF only keyword inside
  1115. constructors and methods respectively
  1116. Revision 1.49 1998/11/12 12:55:17 pierre
  1117. * fix for bug0176 and bug0177
  1118. Revision 1.48 1998/11/05 23:43:24 peter
  1119. * fixed assembler directive and then not an ASM statement
  1120. Revision 1.47 1998/10/30 16:20:22 peter
  1121. * fixed dispose(destructor) crash when destructor didn't exists
  1122. Revision 1.46 1998/10/20 08:06:53 pierre
  1123. * several memory corruptions due to double freemem solved
  1124. => never use p^.loc.location:=p^.left^.loc.location;
  1125. + finally I added now by default
  1126. that ra386dir translates global and unit symbols
  1127. + added a first field in tsymtable and
  1128. a nextsym field in tsym
  1129. (this allows to obtain ordered type info for
  1130. records and objects in gdb !)
  1131. Revision 1.45 1998/10/19 08:55:01 pierre
  1132. * wrong stabs info corrected once again !!
  1133. + variable vmt offset with vmt field only if required
  1134. implemented now !!!
  1135. Revision 1.44 1998/10/13 13:10:27 peter
  1136. * new style for m68k/i386 infos and enums
  1137. Revision 1.43 1998/10/08 13:46:22 peter
  1138. * added eof message
  1139. * fixed unit init section parsing with finalize
  1140. Revision 1.42 1998/09/26 17:45:38 peter
  1141. + idtoken and only one token table
  1142. Revision 1.41 1998/09/24 23:49:15 peter
  1143. + aktmodeswitches
  1144. Revision 1.40 1998/09/23 21:53:04 florian
  1145. * the following doesn't work: on texception do, was a parser error, fixed
  1146. Revision 1.39 1998/09/21 10:26:07 peter
  1147. * merged fix
  1148. Revision 1.38.2.1 1998/09/21 10:24:43 peter
  1149. * fixed error recovery with with
  1150. Revision 1.38 1998/09/04 08:42:04 peter
  1151. * updated some error messages
  1152. Revision 1.37 1998/08/21 14:08:52 pierre
  1153. + TEST_FUNCRET now default (old code removed)
  1154. works also for m68k (at least compiles)
  1155. Revision 1.36 1998/08/20 21:36:41 peter
  1156. * fixed 'with object do' bug
  1157. Revision 1.35 1998/08/20 09:26:42 pierre
  1158. + funcret setting in underproc testing
  1159. compile with _dTEST_FUNCRET
  1160. Revision 1.34 1998/08/17 10:10:09 peter
  1161. - removed OLDPPU
  1162. Revision 1.33 1998/08/12 19:39:30 peter
  1163. * fixed some crashes
  1164. Revision 1.32 1998/08/10 14:50:17 peter
  1165. + localswitches, moduleswitches, globalswitches splitting
  1166. Revision 1.31 1998/08/02 16:41:59 florian
  1167. * on o : tobject do should also work now, the exceptsymtable shouldn't be
  1168. disposed by dellexlevel
  1169. Revision 1.30 1998/07/30 16:07:10 florian
  1170. * try ... expect <statement> end; works now
  1171. Revision 1.29 1998/07/30 13:30:37 florian
  1172. * final implemenation of exception support, maybe it needs
  1173. some fixes :)
  1174. Revision 1.28 1998/07/30 11:18:18 florian
  1175. + first implementation of try ... except on .. do end;
  1176. * limitiation of 65535 bytes parameters for cdecl removed
  1177. Revision 1.27 1998/07/28 21:52:55 florian
  1178. + implementation of raise and try..finally
  1179. + some misc. exception stuff
  1180. Revision 1.26 1998/07/27 21:57:14 florian
  1181. * fix to allow tv like stream registration:
  1182. @tmenu.load doesn't work if load had parameters or if load was only
  1183. declared in an anchestor class of tmenu
  1184. Revision 1.25 1998/07/14 21:46:53 peter
  1185. * updated messages file
  1186. Revision 1.24 1998/07/10 10:48:42 peter
  1187. * fixed realnumber scanning
  1188. * [] after asmblock was not uppercased anymore
  1189. Revision 1.23 1998/06/25 08:48:18 florian
  1190. * first version of rtti support
  1191. Revision 1.22 1998/06/24 14:48:36 peter
  1192. * ifdef newppu -> ifndef oldppu
  1193. Revision 1.21 1998/06/24 14:06:34 peter
  1194. * fixed the name changes
  1195. Revision 1.20 1998/06/23 14:00:16 peter
  1196. * renamed RA* units
  1197. Revision 1.19 1998/06/08 22:59:50 peter
  1198. * smartlinking works for win32
  1199. * some defines to exclude some compiler parts
  1200. Revision 1.18 1998/06/05 14:37:35 pierre
  1201. * fixes for inline for operators
  1202. * inline procedure more correctly restricted
  1203. Revision 1.17 1998/06/04 09:55:43 pierre
  1204. * demangled name of procsym reworked to become independant of the mangling scheme
  1205. Revision 1.16 1998/06/02 17:03:04 pierre
  1206. * with node corrected for objects
  1207. * small bugs for SUPPORT_MMX fixed
  1208. Revision 1.15 1998/05/30 14:31:06 peter
  1209. + $ASMMODE
  1210. Revision 1.14 1998/05/29 09:58:14 pierre
  1211. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  1212. (probably a merging problem)
  1213. * errors at start of line were lost
  1214. Revision 1.13 1998/05/28 17:26:50 peter
  1215. * fixed -R switch, it didn't work after my previous akt/init patch
  1216. * fixed bugs 110,130,136
  1217. Revision 1.12 1998/05/21 19:33:33 peter
  1218. + better procedure directive handling and only one table
  1219. Revision 1.11 1998/05/20 09:42:35 pierre
  1220. + UseTokenInfo now default
  1221. * unit in interface uses and implementation uses gives error now
  1222. * only one error for unknown symbol (uses lastsymknown boolean)
  1223. the problem came from the label code !
  1224. + first inlined procedures and function work
  1225. (warning there might be allowed cases were the result is still wrong !!)
  1226. * UseBrower updated gives a global list of all position of all used symbols
  1227. with switch -gb
  1228. Revision 1.10 1998/05/11 13:07:56 peter
  1229. + $ifdef NEWPPU for the new ppuformat
  1230. + $define GDB not longer required
  1231. * removed all warnings and stripped some log comments
  1232. * no findfirst/findnext anymore to remove smartlink *.o files
  1233. Revision 1.9 1998/05/06 08:38:46 pierre
  1234. * better position info with UseTokenInfo
  1235. UseTokenInfo greatly simplified
  1236. + added check for changed tree after first time firstpass
  1237. (if we could remove all the cases were it happen
  1238. we could skip all firstpass if firstpasscount > 1)
  1239. Only with ExtDebug
  1240. Revision 1.8 1998/05/05 12:05:42 florian
  1241. * problems with properties fixed
  1242. * crash fixed: i:=l when i and l are undefined, was a problem with
  1243. implementation of private/protected
  1244. Revision 1.7 1998/05/01 16:38:46 florian
  1245. * handling of private and protected fixed
  1246. + change_keywords_to_tp implemented to remove
  1247. keywords which aren't supported by tp
  1248. * break and continue are now symbols of the system unit
  1249. + widestring, longstring and ansistring type released
  1250. Revision 1.6 1998/04/30 15:59:42 pierre
  1251. * GDB works again better :
  1252. correct type info in one pass
  1253. + UseTokenInfo for better source position
  1254. * fixed one remaining bug in scanner for line counts
  1255. * several little fixes
  1256. Revision 1.5 1998/04/29 10:33:59 pierre
  1257. + added some code for ansistring (not complete nor working yet)
  1258. * corrected operator overloading
  1259. * corrected nasm output
  1260. + started inline procedures
  1261. + added starstarn : use ** for exponentiation (^ gave problems)
  1262. + started UseTokenInfo cond to get accurate positions
  1263. Revision 1.4 1998/04/08 16:58:05 pierre
  1264. * several bugfixes
  1265. ADD ADC and AND are also sign extended
  1266. nasm output OK (program still crashes at end
  1267. and creates wrong assembler files !!)
  1268. procsym types sym in tdef removed !!
  1269. }