pstatmnt.pas 47 KB

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