pstatmnt.pas 51 KB

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