pstatmnt.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  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. obj:=obj^.childof;
  320. inc(levelcount);
  321. end;
  322. symtab^.next:=symtablestack;
  323. symtablestack:=withsymtable;
  324. end;
  325. recorddef : begin
  326. symtab:=precdef(p^.resulttype)^.symtable;
  327. levelcount:=1;
  328. withsymtable:=new(psymtable,init(symtable.withsymtable));
  329. withsymtable^.root:=symtab^.root;
  330. withsymtable^.next:=symtablestack;
  331. withsymtable^.defowner:=obj;
  332. symtablestack:=withsymtable;
  333. end;
  334. end;
  335. if token=COMMA then
  336. begin
  337. consume(COMMA);
  338. {$ifdef tp}
  339. right:=_with_statement;
  340. {$else}
  341. right:=_with_statement();
  342. {$endif}
  343. end
  344. else
  345. begin
  346. consume(_DO);
  347. if token<>SEMICOLON then
  348. right:=statement
  349. else
  350. right:=nil;
  351. end;
  352. for i:=1 to levelcount do
  353. symtablestack:=symtablestack^.next;
  354. _with_statement:=genwithnode(withsymtable,p,right,levelcount);
  355. end
  356. else
  357. begin
  358. Message(parser_e_false_with_expr);
  359. { try to recover from error }
  360. if token=COMMA then
  361. begin
  362. consume(COMMA);
  363. {$ifdef tp}
  364. hp:=_with_statement;
  365. {$else}
  366. hp:=_with_statement();
  367. {$endif}
  368. end
  369. else
  370. begin
  371. consume(_DO);
  372. { ignore all }
  373. if token<>SEMICOLON then
  374. statement;
  375. end;
  376. _with_statement:=nil;
  377. end;
  378. end;
  379. function with_statement : ptree;
  380. begin
  381. consume(_WITH);
  382. with_statement:=_with_statement;
  383. end;
  384. function raise_statement : ptree;
  385. var
  386. p1,p2 : ptree;
  387. begin
  388. p1:=nil;
  389. p2:=nil;
  390. consume(_RAISE);
  391. if token<>SEMICOLON then
  392. begin
  393. p1:=comp_expr(true);
  394. if (token=ID) and (pattern='AT') then
  395. begin
  396. consume(ID);
  397. p2:=comp_expr(true);
  398. end;
  399. end
  400. else
  401. begin
  402. if not(in_except_block) then
  403. Message(parser_e_no_reraise_possible);
  404. end;
  405. raise_statement:=gennode(raisen,p1,p2);
  406. end;
  407. function try_statement : ptree;
  408. var
  409. p_try_block,p_finally_block,first,last,
  410. p_default,p_specific : ptree;
  411. ot : pobjectdef;
  412. sym : pvarsym;
  413. old_in_except_block : boolean;
  414. exceptsymtable : psymtable;
  415. objname : stringid;
  416. begin
  417. procinfo.flags:=procinfo.flags or
  418. pi_uses_exceptions;
  419. p_default:=nil;
  420. p_specific:=nil;
  421. { read statements to try }
  422. consume(_TRY);
  423. first:=nil;
  424. inc(statement_level);
  425. while (token<>_FINALLY) and (token<>_EXCEPT) do
  426. begin
  427. if first=nil then
  428. begin
  429. last:=gennode(statementn,nil,statement);
  430. first:=last;
  431. end
  432. else
  433. begin
  434. last^.left:=gennode(statementn,nil,statement);
  435. last:=last^.left;
  436. end;
  437. if token<>SEMICOLON then
  438. break;
  439. consume(SEMICOLON);
  440. emptystats;
  441. end;
  442. p_try_block:=gensinglenode(blockn,first);
  443. if token=_FINALLY then
  444. begin
  445. consume(_FINALLY);
  446. p_finally_block:=statements_til_end;
  447. try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  448. dec(statement_level);
  449. end
  450. else
  451. begin
  452. consume(_EXCEPT);
  453. old_in_except_block:=in_except_block;
  454. in_except_block:=true;
  455. p_specific:=nil;
  456. if token=_ON then
  457. { catch specific exceptions }
  458. begin
  459. repeat
  460. consume(_ON);
  461. if token=ID then
  462. begin
  463. getsym(pattern,false);
  464. objname:=pattern;
  465. consume(ID);
  466. { is a explicit name for the exception given ? }
  467. if token=COLON then
  468. begin
  469. sym:=new(pvarsym,init(objname,nil));
  470. exceptsymtable:=new(psymtable,init(stt_exceptsymtable));
  471. exceptsymtable^.insert(sym);
  472. consume(COLON);
  473. getsym(pattern,false);
  474. consume(ID);
  475. if srsym^.typ=unitsym then
  476. begin
  477. consume(POINT);
  478. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  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,objname);
  502. consume(ID);
  503. end;
  504. consume(ID);
  505. if (srsym^.typ=typesym) and
  506. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  507. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  508. ot:=pobjectdef(ptypesym(srsym)^.definition)
  509. else
  510. begin
  511. message(type_e_class_type_expected);
  512. ot:=pobjectdef(generrordef);
  513. end;
  514. exceptsymtable:=nil;
  515. end;
  516. end
  517. else
  518. consume(ID);
  519. consume(_DO);
  520. if p_specific=nil then
  521. begin
  522. last:=gennode(onn,nil,statement);
  523. p_specific:=last;
  524. end
  525. else
  526. begin
  527. last^.left:=gennode(onn,nil,statement);
  528. last:=last^.left;
  529. end;
  530. { set the informations }
  531. last^.excepttype:=ot;
  532. last^.exceptsymtable:=exceptsymtable;
  533. last^.disposetyp:=dt_onn;
  534. { remove exception symtable }
  535. if assigned(exceptsymtable) then
  536. dellexlevel;
  537. if token<>SEMICOLON then
  538. break;
  539. consume(SEMICOLON);
  540. emptystats;
  541. until (token=_END) or(token=_ELSE);
  542. if token=_ELSE then
  543. { catch the other exceptions }
  544. begin
  545. consume(_ELSE);
  546. p_default:=statements_til_end;
  547. end
  548. else
  549. consume(_END);
  550. end
  551. else
  552. { catch all exceptions }
  553. begin
  554. p_default:=statements_til_end;
  555. end;
  556. dec(statement_level);
  557. in_except_block:=old_in_except_block;
  558. try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  559. end;
  560. end;
  561. function exit_statement : ptree;
  562. var
  563. p : ptree;
  564. begin
  565. consume(_EXIT);
  566. if token=LKLAMMER then
  567. begin
  568. consume(LKLAMMER);
  569. p:=comp_expr(true);
  570. consume(RKLAMMER);
  571. if procinfo.retdef=pdef(voiddef) then
  572. Message(parser_e_void_function)
  573. else
  574. procinfo.funcret_is_valid:=true;
  575. end
  576. else
  577. p:=nil;
  578. exit_statement:=gensinglenode(exitn,p);
  579. end;
  580. function _asm_statement : ptree;
  581. var
  582. asmstat : ptree;
  583. begin
  584. if (aktprocsym^.definition^.options and poinline)<>0 then
  585. Begin
  586. Message1(parser_w_not_supported_for_inline,'asm statement');
  587. Message(parser_w_inlining_disabled);
  588. aktprocsym^.definition^.options:= aktprocsym^.definition^.options and not poinline;
  589. End;
  590. case aktasmmode of
  591. {$ifdef i386}
  592. {$ifndef NoRA386Att}
  593. I386_ATT : asmstat:=ra386att.assemble;
  594. {$endif NoRA386Att}
  595. {$ifndef NoRA386Int}
  596. I386_INTEL : asmstat:=ra386int.assemble;
  597. {$endif NoRA386Int}
  598. {$ifndef NoRA386Dir}
  599. I386_DIRECT : asmstat:=ra386dir.assemble;
  600. {$endif NoRA386Dir}
  601. {$endif}
  602. {$ifdef m68k}
  603. {$ifndef NoRA68kMot}
  604. M68K_MOT : asmstat:=ra68kmot.assemble;
  605. {$endif NoRA68kMot}
  606. {$endif}
  607. else
  608. Message(parser_f_assembler_reader_not_supported);
  609. end;
  610. { Read first the _ASM statement }
  611. consume(_ASM);
  612. { END is read }
  613. if token=LECKKLAMMER then
  614. begin
  615. { it's possible to specify the modified registers }
  616. consume(LECKKLAMMER);
  617. asmstat^.object_preserved:=true;
  618. if token<>RECKKLAMMER then
  619. repeat
  620. { uppercase, because it's a CSTRING }
  621. uppervar(pattern);
  622. {$ifdef i386}
  623. if pattern='EAX' then
  624. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  625. else if pattern='EBX' then
  626. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  627. else if pattern='ECX' then
  628. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  629. else if pattern='EDX' then
  630. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  631. else if pattern='ESI' then
  632. begin
  633. usedinproc:=usedinproc or ($80 shr byte(R_ESI));
  634. asmstat^.object_preserved:=false;
  635. end
  636. else if pattern='EDI' then
  637. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  638. {$endif i386}
  639. {$ifdef m68k}
  640. if pattern='D0' then
  641. usedinproc:=usedinproc or ($800 shr word(R_D0))
  642. else if pattern='D1' then
  643. usedinproc:=usedinproc or ($800 shr word(R_D1))
  644. else if pattern='D6' then
  645. usedinproc:=usedinproc or ($800 shr word(R_D6))
  646. else if pattern='A0' then
  647. usedinproc:=usedinproc or ($800 shr word(R_A0))
  648. else if pattern='A1' then
  649. usedinproc:=usedinproc or ($800 shr word(R_A1))
  650. {$endif m68k}
  651. else consume(RECKKLAMMER);
  652. consume(CSTRING);
  653. if token=COMMA then consume(COMMA)
  654. else break;
  655. until false;
  656. consume(RECKKLAMMER);
  657. end
  658. else usedinproc:=$ff;
  659. _asm_statement:=asmstat;
  660. end;
  661. function new_dispose_statement : ptree;
  662. var
  663. p,p2 : ptree;
  664. ht : ttoken;
  665. again : boolean; { dummy for do_proc_call }
  666. destrukname : stringid;
  667. sym : psym;
  668. classh : pobjectdef;
  669. pd,pd2 : pdef;
  670. store_valid : boolean;
  671. tt : ttreetyp;
  672. begin
  673. ht:=token;
  674. if token=_NEW then consume(_NEW)
  675. else consume(_DISPOSE);
  676. if ht=_NEW then
  677. tt:=hnewn
  678. else
  679. tt:=hdisposen;
  680. consume(LKLAMMER);
  681. p:=comp_expr(true);
  682. { calc return type }
  683. cleartempgen;
  684. Store_valid := Must_be_valid;
  685. Must_be_valid := False;
  686. do_firstpass(p);
  687. Must_be_valid := Store_valid;
  688. {var o:Pobject;
  689. begin
  690. new(o,init); (*Also a valid new statement*)
  691. end;}
  692. if token=COMMA then
  693. begin
  694. { extended syntax of new and dispose }
  695. { function styled new is handled in factor }
  696. consume(COMMA);
  697. { destructors have no parameters }
  698. destrukname:=pattern;
  699. consume(ID);
  700. pd:=p^.resulttype;
  701. pd2:=pd;
  702. if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  703. begin
  704. Message(type_e_pointer_type_expected);
  705. p:=factor(false);
  706. consume(RKLAMMER);
  707. new_dispose_statement:=genzeronode(errorn);
  708. exit;
  709. end;
  710. { first parameter must be an object or class }
  711. if ppointerdef(pd)^.definition^.deftype<>objectdef then
  712. begin
  713. Message(parser_e_pointer_to_class_expected);
  714. new_dispose_statement:=factor(false);
  715. consume_all_until(RKLAMMER);
  716. consume(RKLAMMER);
  717. exit;
  718. end;
  719. { check, if the first parameter is a pointer to a _class_ }
  720. classh:=pobjectdef(ppointerdef(pd)^.definition);
  721. if (classh^.options and oois_class)<>0 then
  722. begin
  723. Message(parser_e_no_new_or_dispose_for_classes);
  724. new_dispose_statement:=factor(false);
  725. { while token<>RKLAMMER do
  726. consume(token); }
  727. consume_all_until(RKLAMMER);
  728. consume(RKLAMMER);
  729. exit;
  730. end;
  731. { search cons-/destructor, also in parent classes }
  732. sym:=nil;
  733. while assigned(classh) do
  734. begin
  735. sym:=classh^.publicsyms^.search(pattern);
  736. srsymtable:=classh^.publicsyms;
  737. if assigned(sym) then
  738. break;
  739. classh:=classh^.childof;
  740. end;
  741. { the second parameter of new/dispose must be a call }
  742. { to a cons-/destructor }
  743. if (sym^.typ<>procsym) then
  744. begin
  745. Message(parser_e_expr_have_to_be_destructor_call);
  746. new_dispose_statement:=genzeronode(errorn);
  747. end
  748. else
  749. begin
  750. p2:=gensinglenode(tt,p);
  751. if ht=_NEW then
  752. begin
  753. { Constructors can take parameters.}
  754. p2^.resulttype:=ppointerdef(pd)^.definition;
  755. do_member_read(false,sym,p2,pd,again);
  756. end
  757. else
  758. { destructors can't.}
  759. p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  760. { we need the real called method }
  761. cleartempgen;
  762. do_firstpass(p2);
  763. if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  764. Message(parser_e_expr_have_to_be_constructor_call);
  765. if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  766. Message(parser_e_expr_have_to_be_destructor_call);
  767. if ht=_NEW then
  768. begin
  769. p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  770. p2^.right^.resulttype:=pd2;
  771. end;
  772. new_dispose_statement:=p2;
  773. end;
  774. end
  775. else
  776. begin
  777. if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  778. Begin
  779. Message(type_e_pointer_type_expected);
  780. new_dispose_statement:=genzeronode(errorn);
  781. end
  782. else
  783. begin
  784. if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) then
  785. Message(parser_w_use_extended_syntax_for_objects);
  786. case ht of
  787. _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  788. _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  789. end;
  790. end;
  791. end;
  792. consume(RKLAMMER);
  793. end;
  794. function statement_block(starttoken : ttoken) : ptree;
  795. var
  796. first,last : ptree;
  797. filepos : tfileposinfo;
  798. begin
  799. first:=nil;
  800. filepos:=tokenpos;
  801. consume(starttoken);
  802. inc(statement_level);
  803. while not(
  804. (token=_END) or
  805. ((starttoken=_INITIALIZATION) and (token=_FINALIZATION))
  806. ) 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=_END) or
  819. ((starttoken=_INITIALIZATION) and (token=_FINALIZATION)) then
  820. break
  821. else
  822. begin
  823. { if no semicolon, then error and go on }
  824. if token<>SEMICOLON then
  825. begin
  826. consume(SEMICOLON);
  827. { while token<>SEMICOLON do
  828. consume(token); }
  829. consume_all_until(SEMICOLON);
  830. end;
  831. consume(SEMICOLON);
  832. end;
  833. emptystats;
  834. end;
  835. { don't consume the finalization token, it is consumed when
  836. reading the finalization block !
  837. }
  838. if token=_END then
  839. consume(_END);
  840. dec(statement_level);
  841. last:=gensinglenode(blockn,first);
  842. set_tree_filepos(last,filepos);
  843. statement_block:=last;
  844. end;
  845. function statement : ptree;
  846. var
  847. p : ptree;
  848. code : ptree;
  849. labelnr : plabel;
  850. filepos : tfileposinfo;
  851. label
  852. ready;
  853. begin
  854. filepos:=tokenpos;
  855. case token of
  856. _GOTO : begin
  857. if not(cs_support_goto in aktmoduleswitches)then
  858. Message(sym_e_goto_and_label_not_supported);
  859. consume(_GOTO);
  860. if (token<>INTCONST) and (token<>ID) then
  861. begin
  862. Message(sym_e_label_not_found);
  863. code:=genzeronode(errorn);
  864. end
  865. else
  866. begin
  867. getsym(pattern,true);
  868. consume(token);
  869. if srsym^.typ<>labelsym then
  870. begin
  871. Message(sym_e_id_is_no_label_id);
  872. code:=genzeronode(errorn);
  873. end
  874. else
  875. code:=genlabelnode(goton,
  876. plabelsym(srsym)^.number);
  877. end;
  878. end;
  879. _BEGIN : code:=statement_block(_BEGIN);
  880. _IF : code:=if_statement;
  881. _CASE : code:=case_statement;
  882. _REPEAT : code:=repeat_statement;
  883. _WHILE : code:=while_statement;
  884. _FOR : code:=for_statement;
  885. _NEW,_DISPOSE : code:=new_dispose_statement;
  886. _WITH : code:=with_statement;
  887. _TRY : code:=try_statement;
  888. _RAISE : code:=raise_statement;
  889. { semicolons,else until and end are ignored }
  890. SEMICOLON,
  891. _ELSE,
  892. _UNTIL,
  893. _END:
  894. code:=genzeronode(niln);
  895. _CONTINUE:
  896. begin
  897. consume(_CONTINUE);
  898. code:=genzeronode(continuen);
  899. end;
  900. _FAIL : begin
  901. { internalerror(100); }
  902. if (aktprocsym^.definition^.options and poconstructor)=0 then
  903. Message(parser_e_fail_only_in_constructor);
  904. consume(_FAIL);
  905. code:=genzeronode(failn);
  906. end;
  907. {
  908. _BREAK:
  909. begin
  910. consume(_BREAK);
  911. code:=genzeronode(breakn);
  912. end;
  913. }
  914. _EXIT : code:=exit_statement;
  915. _ASM : begin
  916. code:=_asm_statement;
  917. end;
  918. else
  919. begin
  920. if (token=INTCONST) or
  921. ((token=ID) and
  922. not((cs_delphi2_compatible in aktmoduleswitches) and
  923. (pattern='RESULT'))) then
  924. begin
  925. getsym(pattern,true);
  926. lastsymknown:=true;
  927. lastsrsym:=srsym;
  928. { it is NOT necessarily the owner
  929. it can be a withsymtable !!! }
  930. lastsrsymtable:=srsymtable;
  931. if assigned(srsym) and (srsym^.typ=labelsym) then
  932. begin
  933. consume(token);
  934. consume(COLON);
  935. if plabelsym(srsym)^.defined then
  936. Message(sym_e_label_already_defined);
  937. plabelsym(srsym)^.defined:=true;
  938. { statement modifies srsym }
  939. labelnr:=plabelsym(srsym)^.number;
  940. lastsymknown:=false;
  941. { the pointer to the following instruction }
  942. { isn't a very clean way }
  943. {$ifdef tp}
  944. code:=gensinglenode(labeln,statement);
  945. {$else}
  946. code:=gensinglenode(labeln,statement());
  947. {$endif}
  948. code^.labelnr:=labelnr;
  949. { sorry, but there is a jump the easiest way }
  950. goto ready;
  951. end;
  952. end;
  953. p:=expr;
  954. if not(p^.treetype in [calln,assignn,breakn,inlinen,
  955. continuen]) then
  956. Message(cg_e_illegal_expression);
  957. { specify that we don't use the value returned by the call }
  958. { Question : can this be also improtant
  959. for inlinen ??
  960. it is used for :
  961. - dispose of temp stack space
  962. - dispose on FPU stack }
  963. if p^.treetype=calln then
  964. p^.return_value_used:=false;
  965. code:=p;
  966. end;
  967. end;
  968. ready:
  969. if assigned(code) then
  970. set_tree_filepos(code,filepos);
  971. statement:=code;
  972. end;
  973. function block(islibrary : boolean) : ptree;
  974. var
  975. funcretsym : pfuncretsym;
  976. begin
  977. if procinfo.retdef<>pdef(voiddef) then
  978. begin
  979. { if the current is a function aktprocsym is non nil }
  980. { and there is a local symtable set }
  981. funcretsym:=new(pfuncretsym,init(aktprocsym^.name,@procinfo));
  982. { insert in local symtable }
  983. symtablestack^.insert(funcretsym);
  984. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  985. procinfo.retoffset:=-funcretsym^.address;
  986. procinfo.funcretsym:=funcretsym;
  987. end;
  988. read_declarations(islibrary);
  989. { temporary space is set, while the BEGIN of the procedure }
  990. if (symtablestack^.symtabletype=localsymtable) then
  991. procinfo.firsttemp := -symtablestack^.datasize
  992. else procinfo.firsttemp := 0;
  993. { space for the return value }
  994. { !!!!! this means that we can not set the return value
  995. in a subfunction !!!!! }
  996. { because we don't know yet where the address is }
  997. if procinfo.retdef<>pdef(voiddef) then
  998. begin
  999. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  1000. { if (procinfo.retdef^.deftype=orddef) or
  1001. (procinfo.retdef^.deftype=pointerdef) or
  1002. (procinfo.retdef^.deftype=enumdef) or
  1003. (procinfo.retdef^.deftype=procvardef) or
  1004. (procinfo.retdef^.deftype=floatdef) or
  1005. (
  1006. (procinfo.retdef^.deftype=setdef) and
  1007. (psetdef(procinfo.retdef)^.settype=smallset)
  1008. ) then }
  1009. begin
  1010. { the space has been set in the local symtable }
  1011. procinfo.retoffset:=-funcretsym^.address;
  1012. if (procinfo.flags and pi_operator)<>0 then
  1013. {opsym^.address:=procinfo.call_offset; is wrong PM }
  1014. opsym^.address:=-procinfo.retoffset;
  1015. { eax is modified by a function }
  1016. {$ifdef i386}
  1017. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1018. {$endif}
  1019. {$ifdef m68k}
  1020. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1021. {$endif}
  1022. end;
  1023. end;
  1024. {Unit initialization?.}
  1025. if (lexlevel=1) and (current_module^.is_unit) then
  1026. if (token=_END) then
  1027. begin
  1028. consume(_END);
  1029. block:=nil;
  1030. end
  1031. else
  1032. begin
  1033. if token=_INITIALIZATION then
  1034. begin
  1035. current_module^.flags:=current_module^.flags or uf_init;
  1036. block:=statement_block(_INITIALIZATION);
  1037. end
  1038. else if (token=_FINALIZATION) then
  1039. begin
  1040. if (current_module^.flags and uf_finalize)<>0 then
  1041. block:=statement_block(_FINALIZATION)
  1042. else
  1043. begin
  1044. block:=nil;
  1045. exit;
  1046. end;
  1047. end
  1048. else
  1049. begin
  1050. current_module^.flags:=current_module^.flags or uf_init;
  1051. block:=statement_block(_BEGIN);
  1052. end;
  1053. end
  1054. else
  1055. block:=statement_block(_BEGIN);
  1056. end;
  1057. function assembler_block : ptree;
  1058. begin
  1059. read_declarations(false);
  1060. { temporary space is set, while the BEGIN of the procedure }
  1061. if symtablestack^.symtabletype=localsymtable then
  1062. procinfo.firsttemp := -symtablestack^.datasize
  1063. else procinfo.firsttemp := 0;
  1064. { assembler code does not allocate }
  1065. { space for the return value }
  1066. if procinfo.retdef<>pdef(voiddef) then
  1067. begin
  1068. if ret_in_acc(procinfo.retdef) then
  1069. begin
  1070. { in assembler code the result should be directly in %eax
  1071. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1072. procinfo.firsttemp:=procinfo.retoffset; }
  1073. {$ifdef i386}
  1074. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1075. {$endif}
  1076. {$ifdef m68k}
  1077. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1078. {$endif}
  1079. end
  1080. else if not is_fpu(procinfo.retdef) then
  1081. { should we allow assembler functions of big elements ? }
  1082. Message(parser_e_asm_incomp_with_function_return);
  1083. end;
  1084. { set the framepointer to esp for assembler functions }
  1085. { but only if the are no local variables }
  1086. { added no parameter also (PM) }
  1087. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1088. (aktprocsym^.definition^.localst^.datasize=0) and
  1089. (aktprocsym^.definition^.parast^.datasize=0) then
  1090. begin
  1091. {$ifdef i386}
  1092. procinfo.framepointer:=R_ESP;
  1093. {$endif}
  1094. {$ifdef m68k}
  1095. procinfo.framepointer:=R_SP;
  1096. {$endif}
  1097. { set the right value for parameters }
  1098. dec(aktprocsym^.definition^.parast^.call_offset,sizeof(pointer));
  1099. dec(procinfo.call_offset,sizeof(pointer));
  1100. end;
  1101. assembler_block:=_asm_statement;
  1102. { becuase the END is already read we need to get the
  1103. last_endtoken_filepos here (PFV) }
  1104. last_endtoken_filepos:=tokenpos;
  1105. end;
  1106. end.
  1107. {
  1108. $Log$
  1109. Revision 1.39 1998-09-21 10:26:07 peter
  1110. * merged fix
  1111. Revision 1.38.2.1 1998/09/21 10:24:43 peter
  1112. * fixed error recovery with with
  1113. Revision 1.38 1998/09/04 08:42:04 peter
  1114. * updated some error messages
  1115. Revision 1.37 1998/08/21 14:08:52 pierre
  1116. + TEST_FUNCRET now default (old code removed)
  1117. works also for m68k (at least compiles)
  1118. Revision 1.36 1998/08/20 21:36:41 peter
  1119. * fixed 'with object do' bug
  1120. Revision 1.35 1998/08/20 09:26:42 pierre
  1121. + funcret setting in underproc testing
  1122. compile with _dTEST_FUNCRET
  1123. Revision 1.34 1998/08/17 10:10:09 peter
  1124. - removed OLDPPU
  1125. Revision 1.33 1998/08/12 19:39:30 peter
  1126. * fixed some crashes
  1127. Revision 1.32 1998/08/10 14:50:17 peter
  1128. + localswitches, moduleswitches, globalswitches splitting
  1129. Revision 1.31 1998/08/02 16:41:59 florian
  1130. * on o : tobject do should also work now, the exceptsymtable shouldn't be
  1131. disposed by dellexlevel
  1132. Revision 1.30 1998/07/30 16:07:10 florian
  1133. * try ... expect <statement> end; works now
  1134. Revision 1.29 1998/07/30 13:30:37 florian
  1135. * final implemenation of exception support, maybe it needs
  1136. some fixes :)
  1137. Revision 1.28 1998/07/30 11:18:18 florian
  1138. + first implementation of try ... except on .. do end;
  1139. * limitiation of 65535 bytes parameters for cdecl removed
  1140. Revision 1.27 1998/07/28 21:52:55 florian
  1141. + implementation of raise and try..finally
  1142. + some misc. exception stuff
  1143. Revision 1.26 1998/07/27 21:57:14 florian
  1144. * fix to allow tv like stream registration:
  1145. @tmenu.load doesn't work if load had parameters or if load was only
  1146. declared in an anchestor class of tmenu
  1147. Revision 1.25 1998/07/14 21:46:53 peter
  1148. * updated messages file
  1149. Revision 1.24 1998/07/10 10:48:42 peter
  1150. * fixed realnumber scanning
  1151. * [] after asmblock was not uppercased anymore
  1152. Revision 1.23 1998/06/25 08:48:18 florian
  1153. * first version of rtti support
  1154. Revision 1.22 1998/06/24 14:48:36 peter
  1155. * ifdef newppu -> ifndef oldppu
  1156. Revision 1.21 1998/06/24 14:06:34 peter
  1157. * fixed the name changes
  1158. Revision 1.20 1998/06/23 14:00:16 peter
  1159. * renamed RA* units
  1160. Revision 1.19 1998/06/08 22:59:50 peter
  1161. * smartlinking works for win32
  1162. * some defines to exclude some compiler parts
  1163. Revision 1.18 1998/06/05 14:37:35 pierre
  1164. * fixes for inline for operators
  1165. * inline procedure more correctly restricted
  1166. Revision 1.17 1998/06/04 09:55:43 pierre
  1167. * demangled name of procsym reworked to become independant of the mangling scheme
  1168. Revision 1.16 1998/06/02 17:03:04 pierre
  1169. * with node corrected for objects
  1170. * small bugs for SUPPORT_MMX fixed
  1171. Revision 1.15 1998/05/30 14:31:06 peter
  1172. + $ASMMODE
  1173. Revision 1.14 1998/05/29 09:58:14 pierre
  1174. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  1175. (probably a merging problem)
  1176. * errors at start of line were lost
  1177. Revision 1.13 1998/05/28 17:26:50 peter
  1178. * fixed -R switch, it didn't work after my previous akt/init patch
  1179. * fixed bugs 110,130,136
  1180. Revision 1.12 1998/05/21 19:33:33 peter
  1181. + better procedure directive handling and only one table
  1182. Revision 1.11 1998/05/20 09:42:35 pierre
  1183. + UseTokenInfo now default
  1184. * unit in interface uses and implementation uses gives error now
  1185. * only one error for unknown symbol (uses lastsymknown boolean)
  1186. the problem came from the label code !
  1187. + first inlined procedures and function work
  1188. (warning there might be allowed cases were the result is still wrong !!)
  1189. * UseBrower updated gives a global list of all position of all used symbols
  1190. with switch -gb
  1191. Revision 1.10 1998/05/11 13:07:56 peter
  1192. + $ifdef NEWPPU for the new ppuformat
  1193. + $define GDB not longer required
  1194. * removed all warnings and stripped some log comments
  1195. * no findfirst/findnext anymore to remove smartlink *.o files
  1196. Revision 1.9 1998/05/06 08:38:46 pierre
  1197. * better position info with UseTokenInfo
  1198. UseTokenInfo greatly simplified
  1199. + added check for changed tree after first time firstpass
  1200. (if we could remove all the cases were it happen
  1201. we could skip all firstpass if firstpasscount > 1)
  1202. Only with ExtDebug
  1203. Revision 1.8 1998/05/05 12:05:42 florian
  1204. * problems with properties fixed
  1205. * crash fixed: i:=l when i and l are undefined, was a problem with
  1206. implementation of private/protected
  1207. Revision 1.7 1998/05/01 16:38:46 florian
  1208. * handling of private and protected fixed
  1209. + change_keywords_to_tp implemented to remove
  1210. keywords which aren't supported by tp
  1211. * break and continue are now symbols of the system unit
  1212. + widestring, longstring and ansistring type released
  1213. Revision 1.6 1998/04/30 15:59:42 pierre
  1214. * GDB works again better :
  1215. correct type info in one pass
  1216. + UseTokenInfo for better source position
  1217. * fixed one remaining bug in scanner for line counts
  1218. * several little fixes
  1219. Revision 1.5 1998/04/29 10:33:59 pierre
  1220. + added some code for ansistring (not complete nor working yet)
  1221. * corrected operator overloading
  1222. * corrected nasm output
  1223. + started inline procedures
  1224. + added starstarn : use ** for exponentiation (^ gave problems)
  1225. + started UseTokenInfo cond to get accurate positions
  1226. Revision 1.4 1998/04/08 16:58:05 pierre
  1227. * several bugfixes
  1228. ADD ADC and AND are also sign extended
  1229. nasm output OK (program still crashes at end
  1230. and creates wrong assembler files !!)
  1231. procsym types sym in tdef removed !!
  1232. }