pstatmnt.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  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. case p^.resulttype^.deftype of
  291. objectdef : begin
  292. obj:=pobjectdef(p^.resulttype);
  293. { this creates the stack in the wrong order !!
  294. levelcount:=0;
  295. while assigned(obj) do
  296. begin
  297. symtab:=obj^.publicsyms;
  298. withsymtable:=new(psymtable,init(symtable.withsymtable));
  299. withsymtable^.root:=symtab^.root;
  300. withsymtable^.next:=symtablestack;
  301. symtablestack:=withsymtable;
  302. obj:=obj^.childof;
  303. inc(levelcount);
  304. end; }
  305. withsymtable:=new(psymtable,init(symtable.withsymtable));
  306. withsymtable^.root:=obj^.publicsyms^.root;
  307. withsymtable^.defowner:=obj;
  308. symtab:=withsymtable;
  309. levelcount:=1;
  310. obj:=obj^.childof;
  311. while assigned(obj) do
  312. begin
  313. symtab^.next:=new(psymtable,init(symtable.withsymtable));
  314. symtab:=symtab^.next;
  315. symtab^.root:=obj^.publicsyms^.root;
  316. obj:=obj^.childof;
  317. inc(levelcount);
  318. end;
  319. symtab^.next:=symtablestack;
  320. symtablestack:=withsymtable;
  321. end;
  322. recorddef : begin
  323. symtab:=precdef(p^.resulttype)^.symtable;
  324. levelcount:=1;
  325. withsymtable:=new(psymtable,init(symtable.withsymtable));
  326. withsymtable^.root:=symtab^.root;
  327. withsymtable^.next:=symtablestack;
  328. withsymtable^.defowner:=obj;
  329. symtablestack:=withsymtable;
  330. end;
  331. else
  332. begin
  333. Message(parser_e_false_with_expr);
  334. { try to recover from error }
  335. if token=COMMA then
  336. begin
  337. consume(COMMA);
  338. {$ifdef tp}
  339. hp:=_with_statement;
  340. {$else}
  341. hp:=_with_statement();
  342. {$endif}
  343. end
  344. else
  345. begin
  346. consume(_DO);
  347. { ignore all }
  348. if token<>SEMICOLON then
  349. statement;
  350. end;
  351. _with_statement:=nil;
  352. exit;
  353. end;
  354. end;
  355. if token=COMMA then
  356. begin
  357. consume(COMMA);
  358. {$ifdef tp}
  359. right:=_with_statement;
  360. {$else}
  361. right:=_with_statement();
  362. {$endif}
  363. end
  364. else
  365. begin
  366. consume(_DO);
  367. if token<>SEMICOLON then
  368. right:=statement
  369. else
  370. right:=nil;
  371. end;
  372. for i:=1 to levelcount do
  373. symtablestack:=symtablestack^.next;
  374. _with_statement:=genwithnode(withsymtable,p,right,levelcount);
  375. end;
  376. function with_statement : ptree;
  377. begin
  378. consume(_WITH);
  379. with_statement:=_with_statement;
  380. end;
  381. function raise_statement : ptree;
  382. var
  383. p1,p2 : ptree;
  384. begin
  385. p1:=nil;
  386. p2:=nil;
  387. consume(_RAISE);
  388. if token<>SEMICOLON then
  389. begin
  390. p1:=comp_expr(true);
  391. if (token=ID) and (pattern='AT') then
  392. begin
  393. consume(ID);
  394. p2:=comp_expr(true);
  395. end;
  396. end
  397. else
  398. begin
  399. if not(in_except_block) then
  400. Message(parser_e_no_reraise_possible);
  401. end;
  402. raise_statement:=gennode(raisen,p1,p2);
  403. end;
  404. function try_statement : ptree;
  405. var
  406. p_try_block,p_finally_block,first,last,
  407. p_default,p_specific : ptree;
  408. ot : pobjectdef;
  409. sym : pvarsym;
  410. old_in_except_block : boolean;
  411. exceptsymtable : psymtable;
  412. objname : stringid;
  413. begin
  414. procinfo.flags:=procinfo.flags or
  415. pi_uses_exceptions;
  416. p_default:=nil;
  417. p_specific:=nil;
  418. { read statements to try }
  419. consume(_TRY);
  420. first:=nil;
  421. inc(statement_level);
  422. while (token<>_FINALLY) and (token<>_EXCEPT) do
  423. begin
  424. if first=nil then
  425. begin
  426. last:=gennode(statementn,nil,statement);
  427. first:=last;
  428. end
  429. else
  430. begin
  431. last^.left:=gennode(statementn,nil,statement);
  432. last:=last^.left;
  433. end;
  434. if token<>SEMICOLON then
  435. break;
  436. consume(SEMICOLON);
  437. emptystats;
  438. end;
  439. p_try_block:=gensinglenode(blockn,first);
  440. if token=_FINALLY then
  441. begin
  442. consume(_FINALLY);
  443. p_finally_block:=statements_til_end;
  444. try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  445. dec(statement_level);
  446. end
  447. else
  448. begin
  449. consume(_EXCEPT);
  450. old_in_except_block:=in_except_block;
  451. in_except_block:=true;
  452. p_specific:=nil;
  453. if token=_ON then
  454. { catch specific exceptions }
  455. begin
  456. repeat
  457. consume(_ON);
  458. if token=ID then
  459. begin
  460. getsym(pattern,false);
  461. objname:=pattern;
  462. consume(ID);
  463. { is a explicit name for the exception given ? }
  464. if token=COLON then
  465. begin
  466. sym:=new(pvarsym,init(objname,nil));
  467. exceptsymtable:=new(psymtable,init(stt_exceptsymtable));
  468. exceptsymtable^.insert(sym);
  469. consume(COLON);
  470. getsym(pattern,false);
  471. consume(ID);
  472. if srsym^.typ=unitsym then
  473. begin
  474. consume(POINT);
  475. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  476. consume(ID);
  477. end;
  478. if (srsym^.typ=typesym) and
  479. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  480. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  481. ot:=pobjectdef(ptypesym(srsym)^.definition)
  482. else
  483. begin
  484. message(type_e_class_type_expected);
  485. ot:=pobjectdef(generrordef);
  486. end;
  487. sym^.definition:=ot;
  488. { insert the exception symtable stack }
  489. exceptsymtable^.next:=symtablestack;
  490. symtablestack:=exceptsymtable;
  491. end
  492. else
  493. begin
  494. { only exception type }
  495. if srsym^.typ=unitsym then
  496. begin
  497. consume(POINT);
  498. getsymonlyin(punitsym(srsym)^.unitsymtable,objname);
  499. consume(ID);
  500. end;
  501. consume(ID);
  502. if (srsym^.typ=typesym) and
  503. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  504. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  505. ot:=pobjectdef(ptypesym(srsym)^.definition)
  506. else
  507. begin
  508. message(type_e_class_type_expected);
  509. ot:=pobjectdef(generrordef);
  510. end;
  511. exceptsymtable:=nil;
  512. end;
  513. end
  514. else
  515. consume(ID);
  516. consume(_DO);
  517. if p_specific=nil then
  518. begin
  519. last:=gennode(onn,nil,statement);
  520. p_specific:=last;
  521. end
  522. else
  523. begin
  524. last^.left:=gennode(onn,nil,statement);
  525. last:=last^.left;
  526. end;
  527. { set the informations }
  528. last^.excepttype:=ot;
  529. last^.exceptsymtable:=exceptsymtable;
  530. last^.disposetyp:=dt_onn;
  531. { remove exception symtable }
  532. if assigned(exceptsymtable) then
  533. dellexlevel;
  534. if token<>SEMICOLON then
  535. break;
  536. consume(SEMICOLON);
  537. emptystats;
  538. until (token=_END) or(token=_ELSE);
  539. if token=_ELSE then
  540. { catch the other exceptions }
  541. begin
  542. consume(_ELSE);
  543. p_default:=statements_til_end;
  544. end
  545. else
  546. consume(_END);
  547. end
  548. else
  549. { catch all exceptions }
  550. begin
  551. p_default:=statements_til_end;
  552. end;
  553. dec(statement_level);
  554. in_except_block:=old_in_except_block;
  555. try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  556. end;
  557. end;
  558. function exit_statement : ptree;
  559. var
  560. p : ptree;
  561. begin
  562. consume(_EXIT);
  563. if token=LKLAMMER then
  564. begin
  565. consume(LKLAMMER);
  566. p:=comp_expr(true);
  567. consume(RKLAMMER);
  568. if procinfo.retdef=pdef(voiddef) then
  569. Message(parser_e_void_function)
  570. else
  571. procinfo.funcret_is_valid:=true;
  572. end
  573. else
  574. p:=nil;
  575. exit_statement:=gensinglenode(exitn,p);
  576. end;
  577. function _asm_statement : ptree;
  578. var
  579. asmstat : ptree;
  580. begin
  581. if (aktprocsym^.definition^.options and poinline)<>0 then
  582. Begin
  583. Message1(parser_w_not_supported_for_inline,'asm statement');
  584. Message(parser_w_inlining_disabled);
  585. aktprocsym^.definition^.options:= aktprocsym^.definition^.options and not poinline;
  586. End;
  587. case aktasmmode of
  588. {$ifdef i386}
  589. {$ifndef NoRA386Att}
  590. I386_ATT : asmstat:=ra386att.assemble;
  591. {$endif NoRA386Att}
  592. {$ifndef NoRA386Int}
  593. I386_INTEL : asmstat:=ra386int.assemble;
  594. {$endif NoRA386Int}
  595. {$ifndef NoRA386Dir}
  596. I386_DIRECT : asmstat:=ra386dir.assemble;
  597. {$endif NoRA386Dir}
  598. {$endif}
  599. {$ifdef m68k}
  600. {$ifndef NoRA68kMot}
  601. M68K_MOT : asmstat:=ra68kmot.assemble;
  602. {$endif NoRA68kMot}
  603. {$endif}
  604. else
  605. Message(parser_f_assembler_reader_not_supported);
  606. end;
  607. { Read first the _ASM statement }
  608. consume(_ASM);
  609. { END is read }
  610. if token=LECKKLAMMER then
  611. begin
  612. { it's possible to specify the modified registers }
  613. consume(LECKKLAMMER);
  614. asmstat^.object_preserved:=true;
  615. if token<>RECKKLAMMER then
  616. repeat
  617. { uppercase, because it's a CSTRING }
  618. uppervar(pattern);
  619. {$ifdef i386}
  620. if pattern='EAX' then
  621. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  622. else if pattern='EBX' then
  623. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  624. else if pattern='ECX' then
  625. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  626. else if pattern='EDX' then
  627. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  628. else if pattern='ESI' then
  629. begin
  630. usedinproc:=usedinproc or ($80 shr byte(R_ESI));
  631. asmstat^.object_preserved:=false;
  632. end
  633. else if pattern='EDI' then
  634. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  635. {$endif i386}
  636. {$ifdef m68k}
  637. if pattern='D0' then
  638. usedinproc:=usedinproc or ($800 shr word(R_D0))
  639. else if pattern='D1' then
  640. usedinproc:=usedinproc or ($800 shr word(R_D1))
  641. else if pattern='D6' then
  642. usedinproc:=usedinproc or ($800 shr word(R_D6))
  643. else if pattern='A0' then
  644. usedinproc:=usedinproc or ($800 shr word(R_A0))
  645. else if pattern='A1' then
  646. usedinproc:=usedinproc or ($800 shr word(R_A1))
  647. {$endif m68k}
  648. else consume(RECKKLAMMER);
  649. consume(CSTRING);
  650. if token=COMMA then consume(COMMA)
  651. else break;
  652. until false;
  653. consume(RECKKLAMMER);
  654. end
  655. else usedinproc:=$ff;
  656. _asm_statement:=asmstat;
  657. end;
  658. function new_dispose_statement : ptree;
  659. var
  660. p,p2 : ptree;
  661. ht : ttoken;
  662. again : boolean; { dummy for do_proc_call }
  663. destrukname : stringid;
  664. sym : psym;
  665. classh : pobjectdef;
  666. pd,pd2 : pdef;
  667. store_valid : boolean;
  668. tt : ttreetyp;
  669. begin
  670. ht:=token;
  671. if token=_NEW then consume(_NEW)
  672. else consume(_DISPOSE);
  673. if ht=_NEW then
  674. tt:=hnewn
  675. else
  676. tt:=hdisposen;
  677. consume(LKLAMMER);
  678. p:=comp_expr(true);
  679. { calc return type }
  680. cleartempgen;
  681. Store_valid := Must_be_valid;
  682. Must_be_valid := False;
  683. do_firstpass(p);
  684. Must_be_valid := Store_valid;
  685. {var o:Pobject;
  686. begin
  687. new(o,init); (*Also a valid new statement*)
  688. end;}
  689. if token=COMMA then
  690. begin
  691. { extended syntax of new and dispose }
  692. { function styled new is handled in factor }
  693. consume(COMMA);
  694. { destructors have no parameters }
  695. destrukname:=pattern;
  696. consume(ID);
  697. pd:=p^.resulttype;
  698. pd2:=pd;
  699. if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  700. begin
  701. Message(type_e_pointer_type_expected);
  702. p:=factor(false);
  703. consume(RKLAMMER);
  704. new_dispose_statement:=genzeronode(errorn);
  705. exit;
  706. end;
  707. { first parameter must be an object or class }
  708. if ppointerdef(pd)^.definition^.deftype<>objectdef then
  709. begin
  710. Message(parser_e_pointer_to_class_expected);
  711. new_dispose_statement:=factor(false);
  712. consume_all_until(RKLAMMER);
  713. consume(RKLAMMER);
  714. exit;
  715. end;
  716. { check, if the first parameter is a pointer to a _class_ }
  717. classh:=pobjectdef(ppointerdef(pd)^.definition);
  718. if (classh^.options and oois_class)<>0 then
  719. begin
  720. Message(parser_e_no_new_or_dispose_for_classes);
  721. new_dispose_statement:=factor(false);
  722. { while token<>RKLAMMER do
  723. consume(token); }
  724. consume_all_until(RKLAMMER);
  725. consume(RKLAMMER);
  726. exit;
  727. end;
  728. { search cons-/destructor, also in parent classes }
  729. sym:=nil;
  730. while assigned(classh) do
  731. begin
  732. sym:=classh^.publicsyms^.search(pattern);
  733. srsymtable:=classh^.publicsyms;
  734. if assigned(sym) then
  735. break;
  736. classh:=classh^.childof;
  737. end;
  738. { the second parameter of new/dispose must be a call }
  739. { to a cons-/destructor }
  740. if (sym^.typ<>procsym) then
  741. begin
  742. Message(parser_e_expr_have_to_be_destructor_call);
  743. new_dispose_statement:=genzeronode(errorn);
  744. end
  745. else
  746. begin
  747. p2:=gensinglenode(tt,p);
  748. if ht=_NEW then
  749. begin
  750. { Constructors can take parameters.}
  751. p2^.resulttype:=ppointerdef(pd)^.definition;
  752. do_member_read(false,sym,p2,pd,again);
  753. end
  754. else
  755. { destructors can't.}
  756. p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  757. { we need the real called method }
  758. cleartempgen;
  759. do_firstpass(p2);
  760. if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  761. Message(parser_e_expr_have_to_be_constructor_call);
  762. if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  763. Message(parser_e_expr_have_to_be_destructor_call);
  764. if ht=_NEW then
  765. begin
  766. p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  767. p2^.right^.resulttype:=pd2;
  768. end;
  769. new_dispose_statement:=p2;
  770. end;
  771. end
  772. else
  773. begin
  774. if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  775. Begin
  776. Message(type_e_pointer_type_expected);
  777. new_dispose_statement:=genzeronode(errorn);
  778. end
  779. else
  780. begin
  781. if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) then
  782. Message(parser_w_use_extended_syntax_for_objects);
  783. case ht of
  784. _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  785. _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  786. end;
  787. end;
  788. end;
  789. consume(RKLAMMER);
  790. end;
  791. function statement_block(starttoken : ttoken) : ptree;
  792. var
  793. first,last : ptree;
  794. filepos : tfileposinfo;
  795. begin
  796. first:=nil;
  797. filepos:=tokenpos;
  798. consume(starttoken);
  799. inc(statement_level);
  800. while not(
  801. (token=_END) or
  802. ((starttoken=_INITIALIZATION) and (token=_FINALIZATION))
  803. ) do
  804. begin
  805. if first=nil then
  806. begin
  807. last:=gennode(statementn,nil,statement);
  808. first:=last;
  809. end
  810. else
  811. begin
  812. last^.left:=gennode(statementn,nil,statement);
  813. last:=last^.left;
  814. end;
  815. if (token=_END) or
  816. ((starttoken=_INITIALIZATION) and (token=_FINALIZATION)) then
  817. break
  818. else
  819. begin
  820. { if no semicolon, then error and go on }
  821. if token<>SEMICOLON then
  822. begin
  823. consume(SEMICOLON);
  824. { while token<>SEMICOLON do
  825. consume(token); }
  826. consume_all_until(SEMICOLON);
  827. end;
  828. consume(SEMICOLON);
  829. end;
  830. emptystats;
  831. end;
  832. { don't consume the finalization token, it is consumed when
  833. reading the finalization block !
  834. }
  835. if token=_END then
  836. consume(_END);
  837. dec(statement_level);
  838. last:=gensinglenode(blockn,first);
  839. set_tree_filepos(last,filepos);
  840. statement_block:=last;
  841. end;
  842. function statement : ptree;
  843. var
  844. p : ptree;
  845. code : ptree;
  846. labelnr : plabel;
  847. filepos : tfileposinfo;
  848. label
  849. ready;
  850. begin
  851. filepos:=tokenpos;
  852. case token of
  853. _GOTO : begin
  854. if not(cs_support_goto in aktmoduleswitches)then
  855. Message(sym_e_goto_and_label_not_supported);
  856. consume(_GOTO);
  857. if (token<>INTCONST) and (token<>ID) then
  858. begin
  859. Message(sym_e_label_not_found);
  860. code:=genzeronode(errorn);
  861. end
  862. else
  863. begin
  864. getsym(pattern,true);
  865. consume(token);
  866. if srsym^.typ<>labelsym then
  867. begin
  868. Message(sym_e_id_is_no_label_id);
  869. code:=genzeronode(errorn);
  870. end
  871. else
  872. code:=genlabelnode(goton,
  873. plabelsym(srsym)^.number);
  874. end;
  875. end;
  876. _BEGIN : code:=statement_block(_BEGIN);
  877. _IF : code:=if_statement;
  878. _CASE : code:=case_statement;
  879. _REPEAT : code:=repeat_statement;
  880. _WHILE : code:=while_statement;
  881. _FOR : code:=for_statement;
  882. _NEW,_DISPOSE : code:=new_dispose_statement;
  883. _WITH : code:=with_statement;
  884. _TRY : code:=try_statement;
  885. _RAISE : code:=raise_statement;
  886. { semicolons,else until and end are ignored }
  887. SEMICOLON,
  888. _ELSE,
  889. _UNTIL,
  890. _END:
  891. code:=genzeronode(niln);
  892. _CONTINUE:
  893. begin
  894. consume(_CONTINUE);
  895. code:=genzeronode(continuen);
  896. end;
  897. _FAIL : begin
  898. { internalerror(100); }
  899. if (aktprocsym^.definition^.options and poconstructor)=0 then
  900. Message(parser_e_fail_only_in_constructor);
  901. consume(_FAIL);
  902. code:=genzeronode(failn);
  903. end;
  904. {
  905. _BREAK:
  906. begin
  907. consume(_BREAK);
  908. code:=genzeronode(breakn);
  909. end;
  910. }
  911. _EXIT : code:=exit_statement;
  912. _ASM : begin
  913. code:=_asm_statement;
  914. end;
  915. else
  916. begin
  917. if (token=INTCONST) or
  918. ((token=ID) and
  919. not((cs_delphi2_compatible in aktmoduleswitches) and
  920. (pattern='RESULT'))) then
  921. begin
  922. getsym(pattern,true);
  923. lastsymknown:=true;
  924. lastsrsym:=srsym;
  925. { it is NOT necessarily the owner
  926. it can be a withsymtable !!! }
  927. lastsrsymtable:=srsymtable;
  928. if assigned(srsym) and (srsym^.typ=labelsym) then
  929. begin
  930. consume(token);
  931. consume(COLON);
  932. if plabelsym(srsym)^.defined then
  933. Message(sym_e_label_already_defined);
  934. plabelsym(srsym)^.defined:=true;
  935. { statement modifies srsym }
  936. labelnr:=plabelsym(srsym)^.number;
  937. lastsymknown:=false;
  938. { the pointer to the following instruction }
  939. { isn't a very clean way }
  940. {$ifdef tp}
  941. code:=gensinglenode(labeln,statement);
  942. {$else}
  943. code:=gensinglenode(labeln,statement());
  944. {$endif}
  945. code^.labelnr:=labelnr;
  946. { sorry, but there is a jump the easiest way }
  947. goto ready;
  948. end;
  949. end;
  950. p:=expr;
  951. if not(p^.treetype in [calln,assignn,breakn,inlinen,
  952. continuen]) then
  953. Message(cg_e_illegal_expression);
  954. { specify that we don't use the value returned by the call }
  955. { Question : can this be also improtant
  956. for inlinen ??
  957. it is used for :
  958. - dispose of temp stack space
  959. - dispose on FPU stack }
  960. if p^.treetype=calln then
  961. p^.return_value_used:=false;
  962. code:=p;
  963. end;
  964. end;
  965. ready:
  966. if assigned(code) then
  967. set_tree_filepos(code,filepos);
  968. statement:=code;
  969. end;
  970. function block(islibrary : boolean) : ptree;
  971. var
  972. funcretsym : pfuncretsym;
  973. begin
  974. if procinfo.retdef<>pdef(voiddef) then
  975. begin
  976. { if the current is a function aktprocsym is non nil }
  977. { and there is a local symtable set }
  978. funcretsym:=new(pfuncretsym,init(aktprocsym^.name,@procinfo));
  979. { insert in local symtable }
  980. symtablestack^.insert(funcretsym);
  981. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  982. procinfo.retoffset:=-funcretsym^.address;
  983. procinfo.funcretsym:=funcretsym;
  984. end;
  985. read_declarations(islibrary);
  986. { temporary space is set, while the BEGIN of the procedure }
  987. if (symtablestack^.symtabletype=localsymtable) then
  988. procinfo.firsttemp := -symtablestack^.datasize
  989. else procinfo.firsttemp := 0;
  990. { space for the return value }
  991. { !!!!! this means that we can not set the return value
  992. in a subfunction !!!!! }
  993. { because we don't know yet where the address is }
  994. if procinfo.retdef<>pdef(voiddef) then
  995. begin
  996. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  997. { if (procinfo.retdef^.deftype=orddef) or
  998. (procinfo.retdef^.deftype=pointerdef) or
  999. (procinfo.retdef^.deftype=enumdef) or
  1000. (procinfo.retdef^.deftype=procvardef) or
  1001. (procinfo.retdef^.deftype=floatdef) or
  1002. (
  1003. (procinfo.retdef^.deftype=setdef) and
  1004. (psetdef(procinfo.retdef)^.settype=smallset)
  1005. ) then }
  1006. begin
  1007. { the space has been set in the local symtable }
  1008. procinfo.retoffset:=-funcretsym^.address;
  1009. if (procinfo.flags and pi_operator)<>0 then
  1010. {opsym^.address:=procinfo.call_offset; is wrong PM }
  1011. opsym^.address:=-procinfo.retoffset;
  1012. { eax is modified by a function }
  1013. {$ifdef i386}
  1014. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1015. {$endif}
  1016. {$ifdef m68k}
  1017. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1018. {$endif}
  1019. end;
  1020. end;
  1021. {Unit initialization?.}
  1022. if (lexlevel=1) and (current_module^.is_unit) then
  1023. if (token=_END) then
  1024. begin
  1025. consume(_END);
  1026. block:=nil;
  1027. end
  1028. else
  1029. begin
  1030. if token=_INITIALIZATION then
  1031. begin
  1032. current_module^.flags:=current_module^.flags or uf_init;
  1033. block:=statement_block(_INITIALIZATION);
  1034. end
  1035. else if (token=_FINALIZATION) then
  1036. begin
  1037. if (current_module^.flags and uf_finalize)<>0 then
  1038. block:=statement_block(_FINALIZATION)
  1039. else
  1040. begin
  1041. block:=nil;
  1042. exit;
  1043. end;
  1044. end
  1045. else
  1046. begin
  1047. current_module^.flags:=current_module^.flags or uf_init;
  1048. block:=statement_block(_BEGIN);
  1049. end;
  1050. end
  1051. else
  1052. block:=statement_block(_BEGIN);
  1053. end;
  1054. function assembler_block : ptree;
  1055. begin
  1056. read_declarations(false);
  1057. { temporary space is set, while the BEGIN of the procedure }
  1058. if symtablestack^.symtabletype=localsymtable then
  1059. procinfo.firsttemp := -symtablestack^.datasize
  1060. else procinfo.firsttemp := 0;
  1061. { assembler code does not allocate }
  1062. { space for the return value }
  1063. if procinfo.retdef<>pdef(voiddef) then
  1064. begin
  1065. if ret_in_acc(procinfo.retdef) then
  1066. begin
  1067. { in assembler code the result should be directly in %eax
  1068. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1069. procinfo.firsttemp:=procinfo.retoffset; }
  1070. {$ifdef i386}
  1071. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1072. {$endif}
  1073. {$ifdef m68k}
  1074. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1075. {$endif}
  1076. end
  1077. else if not is_fpu(procinfo.retdef) then
  1078. { should we allow assembler functions of big elements ? }
  1079. Message(parser_e_asm_incomp_with_function_return);
  1080. end;
  1081. { set the framepointer to esp for assembler functions }
  1082. { but only if the are no local variables }
  1083. { added no parameter also (PM) }
  1084. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1085. (aktprocsym^.definition^.localst^.datasize=0) and
  1086. (aktprocsym^.definition^.parast^.datasize=0) then
  1087. begin
  1088. {$ifdef i386}
  1089. procinfo.framepointer:=R_ESP;
  1090. {$endif}
  1091. {$ifdef m68k}
  1092. procinfo.framepointer:=R_SP;
  1093. {$endif}
  1094. { set the right value for parameters }
  1095. dec(aktprocsym^.definition^.parast^.call_offset,sizeof(pointer));
  1096. dec(procinfo.call_offset,sizeof(pointer));
  1097. end;
  1098. assembler_block:=_asm_statement;
  1099. { becuase the END is already read we need to get the
  1100. last_endtoken_filepos here (PFV) }
  1101. last_endtoken_filepos:=tokenpos;
  1102. end;
  1103. end.
  1104. {
  1105. $Log$
  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. }