pstatmnt.pas 47 KB

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