pstatmnt.pas 46 KB

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