pstatmnt.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588
  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. globtype,systems,tokens,
  31. strings,cobjects,globals,files,verbose,
  32. symtable,aasm,pass_1,types,scanner,hcodegen,ppu
  33. ,pbase,pexpr,pdecl
  34. {$ifdef i386}
  35. {$ifdef Ag386Bin}
  36. ,i386base,i386asm
  37. {$else}
  38. ,i386
  39. {$endif}
  40. ,tgeni386
  41. {$ifndef NoRa386Int}
  42. ,ra386int
  43. {$endif NoRa386Int}
  44. {$ifndef NoRa386Att}
  45. ,ra386att
  46. {$endif NoRa386Att}
  47. {$ifndef NoRa386Dir}
  48. ,ra386dir
  49. {$endif NoRa386Dir}
  50. {$endif i386}
  51. {$ifdef m68k}
  52. ,m68k,tgen68k
  53. {$ifndef NoRa68kMot}
  54. ,ra68kmot
  55. {$endif NoRa68kMot}
  56. {$endif m68k}
  57. ;
  58. const
  59. statement_level : longint = 0;
  60. function statement : ptree;forward;
  61. function if_statement : ptree;
  62. var
  63. ex,if_a,else_a : ptree;
  64. begin
  65. consume(_IF);
  66. ex:=comp_expr(true);
  67. consume(_THEN);
  68. if token<>_ELSE then
  69. if_a:=statement
  70. else
  71. if_a:=nil;
  72. if token=_ELSE then
  73. begin
  74. consume(_ELSE);
  75. else_a:=statement;
  76. end
  77. else
  78. else_a:=nil;
  79. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  80. end;
  81. { creates a block (list) of statements, til the next END token }
  82. function statements_til_end : ptree;
  83. var
  84. first,last : ptree;
  85. begin
  86. first:=nil;
  87. while token<>_END do
  88. begin
  89. if first=nil then
  90. begin
  91. last:=gennode(statementn,nil,statement);
  92. first:=last;
  93. end
  94. else
  95. begin
  96. last^.left:=gennode(statementn,nil,statement);
  97. last:=last^.left;
  98. end;
  99. if token<>SEMICOLON then
  100. break
  101. else
  102. consume(SEMICOLON);
  103. while token=SEMICOLON do
  104. consume(SEMICOLON);
  105. end;
  106. consume(_END);
  107. statements_til_end:=gensinglenode(blockn,first);
  108. end;
  109. function case_statement : ptree;
  110. var
  111. { contains the label number of currently parsed case block }
  112. aktcaselabel : plabel;
  113. firstlabel : boolean;
  114. root : pcaserecord;
  115. { the typ of the case expression }
  116. casedef : pdef;
  117. procedure newcaselabel(l,h : longint;first:boolean);
  118. var
  119. hcaselabel : pcaserecord;
  120. procedure insertlabel(var p : pcaserecord);
  121. begin
  122. if p=nil then p:=hcaselabel
  123. else
  124. if (p^._low>hcaselabel^._low) and
  125. (p^._low>hcaselabel^._high) then
  126. if (hcaselabel^.statement = p^.statement) and
  127. (p^._low = hcaselabel^._high + 1) then
  128. begin
  129. p^._low := hcaselabel^._low;
  130. freelabel(hcaselabel^._at);
  131. dispose(hcaselabel);
  132. end
  133. else
  134. insertlabel(p^.less)
  135. else
  136. if (p^._high<hcaselabel^._low) and
  137. (p^._high<hcaselabel^._high) then
  138. if (hcaselabel^.statement = p^.statement) and
  139. (p^._high+1 = hcaselabel^._low) then
  140. begin
  141. p^._high := hcaselabel^._high;
  142. freelabel(hcaselabel^._at);
  143. dispose(hcaselabel);
  144. end
  145. else
  146. insertlabel(p^.greater)
  147. else Message(parser_e_double_caselabel);
  148. end;
  149. begin
  150. new(hcaselabel);
  151. hcaselabel^.less:=nil;
  152. hcaselabel^.greater:=nil;
  153. hcaselabel^.statement:=aktcaselabel;
  154. hcaselabel^.firstlabel:=first;
  155. getlabel(hcaselabel^._at);
  156. hcaselabel^._low:=l;
  157. hcaselabel^._high:=h;
  158. insertlabel(root);
  159. end;
  160. var
  161. code,caseexpr,p,instruc,elseblock : ptree;
  162. hl1,hl2 : longint;
  163. begin
  164. consume(_CASE);
  165. caseexpr:=comp_expr(true);
  166. { determines result type }
  167. cleartempgen;
  168. do_firstpass(caseexpr);
  169. casedef:=caseexpr^.resulttype;
  170. if not(is_ordinal(casedef)) then
  171. Message(type_e_ordinal_expr_expected);
  172. consume(_OF);
  173. inc(statement_level);
  174. root:=nil;
  175. instruc:=nil;
  176. repeat
  177. getlabel(aktcaselabel);
  178. firstlabel:=true;
  179. { may be an instruction has more case labels }
  180. repeat
  181. p:=expr;
  182. cleartempgen;
  183. do_firstpass(p);
  184. if (p^.treetype=rangen) then
  185. begin
  186. { type checking for case statements }
  187. if not is_subequal(casedef, p^.left^.resulttype) then
  188. Message(parser_e_case_mismatch);
  189. { type checking for case statements }
  190. if not is_subequal(casedef, p^.right^.resulttype) then
  191. Message(parser_e_case_mismatch);
  192. hl1:=get_ordinal_value(p^.left);
  193. hl2:=get_ordinal_value(p^.right);
  194. testrange(casedef,hl1);
  195. testrange(casedef,hl2);
  196. if hl1>hl2 then
  197. Message(parser_e_case_lower_less_than_upper_bound);
  198. newcaselabel(hl1,hl2,firstlabel);
  199. end
  200. else
  201. begin
  202. { type checking for case statements }
  203. if not is_subequal(casedef, p^.resulttype) then
  204. Message(parser_e_case_mismatch);
  205. hl1:=get_ordinal_value(p);
  206. testrange(casedef,hl1);
  207. newcaselabel(hl1,hl1,firstlabel);
  208. end;
  209. disposetree(p);
  210. if token=COMMA then
  211. consume(COMMA)
  212. else
  213. break;
  214. firstlabel:=false;
  215. until false;
  216. consume(COLON);
  217. { handles instruction block }
  218. p:=gensinglenode(labeln,statement);
  219. p^.labelnr:=aktcaselabel;
  220. { concats instruction }
  221. instruc:=gennode(statementn,instruc,p);
  222. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  223. consume(SEMICOLON);
  224. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  225. if (token=_ELSE) or (token=_OTHERWISE) then
  226. begin
  227. if token=_ELSE then consume(_ELSE)
  228. else consume(_OTHERWISE);
  229. elseblock:=statements_til_end;
  230. end
  231. else
  232. begin
  233. elseblock:=nil;
  234. consume(_END);
  235. end;
  236. dec(statement_level);
  237. code:=gencasenode(caseexpr,instruc,root);
  238. code^.elseblock:=elseblock;
  239. case_statement:=code;
  240. end;
  241. function repeat_statement : ptree;
  242. var
  243. first,last,p_e : ptree;
  244. begin
  245. consume(_REPEAT);
  246. first:=nil;
  247. inc(statement_level);
  248. while token<>_UNTIL do
  249. begin
  250. if first=nil then
  251. begin
  252. last:=gennode(statementn,nil,statement);
  253. first:=last;
  254. end
  255. else
  256. begin
  257. last^.left:=gennode(statementn,nil,statement);
  258. last:=last^.left;
  259. end;
  260. if token<>SEMICOLON then
  261. break;
  262. consume(SEMICOLON);
  263. while token=SEMICOLON do
  264. consume(SEMICOLON);
  265. end;
  266. consume(_UNTIL);
  267. dec(statement_level);
  268. first:=gensinglenode(blockn,first);
  269. p_e:=comp_expr(true);
  270. repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  271. end;
  272. function while_statement : ptree;
  273. var
  274. p_e,p_a : ptree;
  275. begin
  276. consume(_WHILE);
  277. p_e:=comp_expr(true);
  278. consume(_DO);
  279. p_a:=statement;
  280. while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  281. end;
  282. function for_statement : ptree;
  283. var
  284. p_e,tovalue,p_a : ptree;
  285. backward : boolean;
  286. begin
  287. { parse loop header }
  288. consume(_FOR);
  289. p_e:=expr;
  290. if token=_DOWNTO then
  291. begin
  292. consume(_DOWNTO);
  293. backward:=true;
  294. end
  295. else
  296. begin
  297. consume(_TO);
  298. backward:=false;
  299. end;
  300. tovalue:=comp_expr(true);
  301. consume(_DO);
  302. { ... now the instruction }
  303. p_a:=statement;
  304. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  305. end;
  306. function _with_statement : ptree;
  307. var
  308. right,hp,p : ptree;
  309. i,levelcount : longint;
  310. withsymtable,symtab : psymtable;
  311. obj : pobjectdef;
  312. begin
  313. Must_be_valid:=false;
  314. p:=comp_expr(true);
  315. do_firstpass(p);
  316. right:=nil;
  317. if (not codegenerror) and
  318. (p^.resulttype^.deftype in [objectdef,recorddef]) then
  319. begin
  320. case p^.resulttype^.deftype of
  321. objectdef : begin
  322. obj:=pobjectdef(p^.resulttype);
  323. withsymtable:=new(pwithsymtable,init);
  324. withsymtable^.searchroot:=obj^.publicsyms^.searchroot;
  325. withsymtable^.defowner:=obj;
  326. symtab:=withsymtable;
  327. {$ifndef NODIRECTWITH}
  328. if (p^.treetype=loadn) and
  329. (p^.symtable=aktprocsym^.definition^.localst) then
  330. pwithsymtable(symtab)^.direct_with:=true;
  331. {symtab^.withnode:=p; not yet allocated !! }
  332. pwithsymtable(symtab)^.withrefnode:=p;
  333. {$endif ndef NODIRECTWITH}
  334. levelcount:=1;
  335. obj:=obj^.childof;
  336. while assigned(obj) do
  337. begin
  338. symtab^.next:=new(pwithsymtable,init);
  339. symtab:=symtab^.next;
  340. symtab^.searchroot:=obj^.publicsyms^.searchroot;
  341. {$ifndef NODIRECTWITH}
  342. if (p^.treetype=loadn) and
  343. (p^.symtable=aktprocsym^.definition^.localst) then
  344. pwithsymtable(symtab)^.direct_with:=true;
  345. {symtab^.withnode:=p; not yet allocated !! }
  346. pwithsymtable(symtab)^.withrefnode:=p;
  347. {$endif ndef NODIRECTWITH}
  348. symtab^.defowner:=obj;
  349. obj:=obj^.childof;
  350. inc(levelcount);
  351. end;
  352. symtab^.next:=symtablestack;
  353. symtablestack:=withsymtable;
  354. end;
  355. recorddef : begin
  356. symtab:=precdef(p^.resulttype)^.symtable;
  357. levelcount:=1;
  358. withsymtable:=new(pwithsymtable,init);
  359. withsymtable^.searchroot:=symtab^.searchroot;
  360. withsymtable^.next:=symtablestack;
  361. {$ifndef NODIRECTWITH}
  362. if (p^.treetype=loadn) and
  363. (p^.symtable=aktprocsym^.definition^.localst) then
  364. pwithsymtable(withsymtable)^.direct_with:=true;
  365. {symtab^.withnode:=p; not yet allocated !! }
  366. pwithsymtable(withsymtable)^.withrefnode:=p;
  367. {$endif ndef NODIRECTWITH}
  368. withsymtable^.defowner:=obj;
  369. symtablestack:=withsymtable;
  370. end;
  371. end;
  372. if token=COMMA then
  373. begin
  374. consume(COMMA);
  375. {$ifdef tp}
  376. right:=_with_statement;
  377. {$else}
  378. right:=_with_statement();
  379. {$endif}
  380. end
  381. else
  382. begin
  383. consume(_DO);
  384. if token<>SEMICOLON then
  385. right:=statement
  386. else
  387. right:=nil;
  388. end;
  389. for i:=1 to levelcount do
  390. symtablestack:=symtablestack^.next;
  391. _with_statement:=genwithnode(pwithsymtable(withsymtable),p,right,levelcount);
  392. end
  393. else
  394. begin
  395. Message(parser_e_false_with_expr);
  396. { try to recover from error }
  397. if token=COMMA then
  398. begin
  399. consume(COMMA);
  400. {$ifdef tp}
  401. hp:=_with_statement;
  402. {$else}
  403. hp:=_with_statement();
  404. {$endif}
  405. end
  406. else
  407. begin
  408. consume(_DO);
  409. { ignore all }
  410. if token<>SEMICOLON then
  411. statement;
  412. end;
  413. _with_statement:=nil;
  414. end;
  415. end;
  416. function with_statement : ptree;
  417. begin
  418. consume(_WITH);
  419. with_statement:=_with_statement;
  420. end;
  421. function raise_statement : ptree;
  422. var
  423. p1,p2 : ptree;
  424. begin
  425. p1:=nil;
  426. p2:=nil;
  427. consume(_RAISE);
  428. if token<>SEMICOLON then
  429. begin
  430. p1:=comp_expr(true);
  431. if (idtoken=_AT) then
  432. begin
  433. consume(ID);
  434. p2:=comp_expr(true);
  435. end;
  436. end
  437. else
  438. begin
  439. if not(in_except_block) then
  440. Message(parser_e_no_reraise_possible);
  441. end;
  442. raise_statement:=gennode(raisen,p1,p2);
  443. end;
  444. function try_statement : ptree;
  445. var
  446. p_try_block,p_finally_block,first,last,
  447. p_default,p_specific,hp : ptree;
  448. ot : pobjectdef;
  449. sym : pvarsym;
  450. old_in_except_block : boolean;
  451. exceptsymtable : psymtable;
  452. objname : stringid;
  453. begin
  454. procinfo.flags:=procinfo.flags or
  455. pi_uses_exceptions;
  456. p_default:=nil;
  457. p_specific:=nil;
  458. { read statements to try }
  459. consume(_TRY);
  460. first:=nil;
  461. inc(statement_level);
  462. while (token<>_FINALLY) and (token<>_EXCEPT) do
  463. begin
  464. if first=nil then
  465. begin
  466. last:=gennode(statementn,nil,statement);
  467. first:=last;
  468. end
  469. else
  470. begin
  471. last^.left:=gennode(statementn,nil,statement);
  472. last:=last^.left;
  473. end;
  474. if token<>SEMICOLON then
  475. break;
  476. consume(SEMICOLON);
  477. emptystats;
  478. end;
  479. p_try_block:=gensinglenode(blockn,first);
  480. if token=_FINALLY then
  481. begin
  482. consume(_FINALLY);
  483. p_finally_block:=statements_til_end;
  484. try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  485. dec(statement_level);
  486. end
  487. else
  488. begin
  489. consume(_EXCEPT);
  490. old_in_except_block:=in_except_block;
  491. in_except_block:=true;
  492. p_specific:=nil;
  493. if token=_ON then
  494. { catch specific exceptions }
  495. begin
  496. repeat
  497. consume(_ON);
  498. if token=ID then
  499. begin
  500. getsym(pattern,false);
  501. objname:=pattern;
  502. consume(ID);
  503. { is a explicit name for the exception given ? }
  504. if token=COLON then
  505. begin
  506. consume(COLON);
  507. getsym(pattern,true);
  508. consume(ID);
  509. if srsym^.typ=unitsym then
  510. begin
  511. consume(POINT);
  512. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  513. consume(ID);
  514. end;
  515. if (srsym^.typ=typesym) and
  516. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  517. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  518. ot:=pobjectdef(ptypesym(srsym)^.definition)
  519. else
  520. begin
  521. message(type_e_class_type_expected);
  522. ot:=pobjectdef(generrordef);
  523. end;
  524. sym:=new(pvarsym,init(objname,ot));
  525. exceptsymtable:=new(psymtable,init(stt_exceptsymtable));
  526. exceptsymtable^.insert(sym);
  527. { insert the exception symtable stack }
  528. exceptsymtable^.next:=symtablestack;
  529. symtablestack:=exceptsymtable;
  530. end
  531. else
  532. begin
  533. { only exception type }
  534. if srsym^.typ=unitsym then
  535. begin
  536. consume(POINT);
  537. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  538. consume(ID);
  539. end;
  540. if (srsym^.typ=typesym) and
  541. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  542. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  543. ot:=pobjectdef(ptypesym(srsym)^.definition)
  544. else
  545. begin
  546. message(type_e_class_type_expected);
  547. ot:=pobjectdef(generrordef);
  548. end;
  549. exceptsymtable:=nil;
  550. end;
  551. end
  552. else
  553. consume(ID);
  554. consume(_DO);
  555. hp:=gennode(onn,nil,statement);
  556. if ot^.deftype=errordef then
  557. begin
  558. disposetree(hp);
  559. hp:=genzeronode(errorn);
  560. end;
  561. if p_specific=nil then
  562. begin
  563. last:=hp;
  564. p_specific:=last;
  565. end
  566. else
  567. begin
  568. last^.left:=hp;
  569. last:=last^.left;
  570. end;
  571. { set the informations }
  572. last^.excepttype:=ot;
  573. last^.exceptsymtable:=exceptsymtable;
  574. last^.disposetyp:=dt_onn;
  575. { remove exception symtable }
  576. if assigned(exceptsymtable) then
  577. dellexlevel;
  578. if token<>SEMICOLON then
  579. break;
  580. consume(SEMICOLON);
  581. emptystats;
  582. until (token=_END) or(token=_ELSE);
  583. if token=_ELSE then
  584. { catch the other exceptions }
  585. begin
  586. consume(_ELSE);
  587. p_default:=statements_til_end;
  588. end
  589. else
  590. consume(_END);
  591. end
  592. else
  593. { catch all exceptions }
  594. begin
  595. p_default:=statements_til_end;
  596. end;
  597. dec(statement_level);
  598. in_except_block:=old_in_except_block;
  599. try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  600. end;
  601. end;
  602. function exit_statement : ptree;
  603. var
  604. p : ptree;
  605. begin
  606. consume(_EXIT);
  607. if token=LKLAMMER then
  608. begin
  609. consume(LKLAMMER);
  610. p:=comp_expr(true);
  611. consume(RKLAMMER);
  612. if procinfo.retdef=pdef(voiddef) then
  613. Message(parser_e_void_function)
  614. else
  615. procinfo.funcret_is_valid:=true;
  616. end
  617. else
  618. p:=nil;
  619. p:=gensinglenode(exitn,p);
  620. p^.resulttype:=procinfo.retdef;
  621. exit_statement:=p;
  622. end;
  623. function _asm_statement : ptree;
  624. var
  625. asmstat : ptree;
  626. Marker : Pai;
  627. begin
  628. Inside_asm_statement:=true;
  629. case aktasmmode of
  630. {$ifdef i386}
  631. {$ifndef NoRA386Att}
  632. asmmode_i386_att:
  633. asmstat:=ra386att.assemble;
  634. {$endif NoRA386Att}
  635. {$ifndef NoRA386Int}
  636. asmmode_i386_intel:
  637. asmstat:=ra386int.assemble;
  638. {$endif NoRA386Int}
  639. {$ifndef NoRA386Dir}
  640. asmmode_i386_direct:
  641. begin
  642. if (aktprocsym^.definition^.options and poinline)<>0 then
  643. Begin
  644. Message1(parser_w_not_supported_for_inline,'direct asm');
  645. Message(parser_w_inlining_disabled);
  646. aktprocsym^.definition^.options:= aktprocsym^.definition^.options and not poinline;
  647. End;
  648. asmstat:=ra386dir.assemble;
  649. end;
  650. {$endif NoRA386Dir}
  651. {$endif}
  652. {$ifdef m68k}
  653. {$ifndef NoRA68kMot}
  654. asmmode_m68k_mot:
  655. asmstat:=ra68kmot.assemble;
  656. {$endif NoRA68kMot}
  657. {$endif}
  658. else
  659. Message(parser_f_assembler_reader_not_supported);
  660. end;
  661. { Read first the _ASM statement }
  662. consume(_ASM);
  663. { END is read }
  664. if token=LECKKLAMMER then
  665. begin
  666. { it's possible to specify the modified registers }
  667. consume(LECKKLAMMER);
  668. asmstat^.object_preserved:=true;
  669. if token<>RECKKLAMMER then
  670. repeat
  671. { uppercase, because it's a CSTRING }
  672. uppervar(pattern);
  673. {$ifdef i386}
  674. if pattern='EAX' then
  675. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  676. else if pattern='EBX' then
  677. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  678. else if pattern='ECX' then
  679. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  680. else if pattern='EDX' then
  681. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  682. else if pattern='ESI' then
  683. begin
  684. usedinproc:=usedinproc or ($80 shr byte(R_ESI));
  685. asmstat^.object_preserved:=false;
  686. end
  687. else if pattern='EDI' then
  688. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  689. {$endif i386}
  690. {$ifdef m68k}
  691. if pattern='D0' then
  692. usedinproc:=usedinproc or ($800 shr word(R_D0))
  693. else if pattern='D1' then
  694. usedinproc:=usedinproc or ($800 shr word(R_D1))
  695. else if pattern='D6' then
  696. usedinproc:=usedinproc or ($800 shr word(R_D6))
  697. else if pattern='A0' then
  698. usedinproc:=usedinproc or ($800 shr word(R_A0))
  699. else if pattern='A1' then
  700. usedinproc:=usedinproc or ($800 shr word(R_A1))
  701. {$endif m68k}
  702. else consume(RECKKLAMMER);
  703. consume(CSTRING);
  704. if token=COMMA then consume(COMMA)
  705. else break;
  706. until false;
  707. consume(RECKKLAMMER);
  708. end
  709. else usedinproc:=$ff;
  710. { mark the start and the end of the assembler block for the optimizer }
  711. If Assigned(AsmStat^.p_asm) Then
  712. Begin
  713. Marker := New(Pai_Marker, Init(AsmBlockStart));
  714. AsmStat^.p_asm^.Insert(Marker);
  715. Marker := New(Pai_Marker, Init(AsmBlockEnd));
  716. AsmStat^.p_asm^.Concat(Marker);
  717. End;
  718. Inside_asm_statement:=false;
  719. _asm_statement:=asmstat;
  720. end;
  721. function new_dispose_statement : ptree;
  722. var
  723. p,p2 : ptree;
  724. ht : ttoken;
  725. store_allow : boolean;
  726. again : boolean; { dummy for do_proc_call }
  727. destrukname : stringid;
  728. sym : psym;
  729. classh : pobjectdef;
  730. pd,pd2 : pdef;
  731. store_valid : boolean;
  732. tt : ttreetyp;
  733. begin
  734. ht:=token;
  735. if token=_NEW then consume(_NEW)
  736. else consume(_DISPOSE);
  737. if ht=_NEW then
  738. tt:=hnewn
  739. else
  740. tt:=hdisposen;
  741. consume(LKLAMMER);
  742. p:=comp_expr(true);
  743. { calc return type }
  744. cleartempgen;
  745. Store_valid := Must_be_valid;
  746. Must_be_valid := False;
  747. do_firstpass(p);
  748. Must_be_valid := Store_valid;
  749. {var o:Pobject;
  750. begin
  751. new(o,init); (*Also a valid new statement*)
  752. end;}
  753. if token=COMMA then
  754. begin
  755. { extended syntax of new and dispose }
  756. { function styled new is handled in factor }
  757. consume(COMMA);
  758. { destructors have no parameters }
  759. destrukname:=pattern;
  760. consume(ID);
  761. pd:=p^.resulttype;
  762. pd2:=pd;
  763. if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  764. begin
  765. Message(type_e_pointer_type_expected);
  766. p:=factor(false);
  767. consume(RKLAMMER);
  768. new_dispose_statement:=genzeronode(errorn);
  769. exit;
  770. end;
  771. { first parameter must be an object or class }
  772. if ppointerdef(pd)^.definition^.deftype<>objectdef then
  773. begin
  774. Message(parser_e_pointer_to_class_expected);
  775. new_dispose_statement:=factor(false);
  776. consume_all_until(RKLAMMER);
  777. consume(RKLAMMER);
  778. exit;
  779. end;
  780. { check, if the first parameter is a pointer to a _class_ }
  781. classh:=pobjectdef(ppointerdef(pd)^.definition);
  782. if (classh^.options and oo_is_class)<>0 then
  783. begin
  784. Message(parser_e_no_new_or_dispose_for_classes);
  785. new_dispose_statement:=factor(false);
  786. { while token<>RKLAMMER do
  787. consume(token); }
  788. consume_all_until(RKLAMMER);
  789. consume(RKLAMMER);
  790. exit;
  791. end;
  792. { search cons-/destructor, also in parent classes }
  793. sym:=nil;
  794. while assigned(classh) do
  795. begin
  796. store_allow:=allow_only_static;
  797. allow_only_static:=false;
  798. sym:=classh^.publicsyms^.search(pattern);
  799. allow_only_static:=store_allow;
  800. srsymtable:=classh^.publicsyms;
  801. if assigned(sym) then
  802. break;
  803. classh:=classh^.childof;
  804. end;
  805. { the second parameter of new/dispose must be a call }
  806. { to a cons-/destructor }
  807. if (not assigned(sym)) or (sym^.typ<>procsym) then
  808. begin
  809. Message(parser_e_expr_have_to_be_destructor_call);
  810. new_dispose_statement:=genzeronode(errorn);
  811. end
  812. else
  813. begin
  814. p2:=gensinglenode(tt,p);
  815. if ht=_NEW then
  816. begin
  817. { Constructors can take parameters.}
  818. p2^.resulttype:=ppointerdef(pd)^.definition;
  819. do_member_read(false,sym,p2,pd,again);
  820. end
  821. else
  822. { destructors can't.}
  823. p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  824. { we need the real called method }
  825. cleartempgen;
  826. do_firstpass(p2);
  827. if not codegenerror then
  828. begin
  829. if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  830. Message(parser_e_expr_have_to_be_constructor_call);
  831. if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  832. Message(parser_e_expr_have_to_be_destructor_call);
  833. if ht=_NEW then
  834. begin
  835. p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  836. p2^.right^.resulttype:=pd2;
  837. end;
  838. end;
  839. new_dispose_statement:=p2;
  840. end;
  841. end
  842. else
  843. begin
  844. if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  845. Begin
  846. Message(type_e_pointer_type_expected);
  847. new_dispose_statement:=genzeronode(errorn);
  848. end
  849. else
  850. begin
  851. if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) and
  852. ((pobjectdef(ppointerdef(p^.resulttype)^.definition)^.options and oo_hasvmt) <> 0) then
  853. Message(parser_w_use_extended_syntax_for_objects);
  854. case ht of
  855. _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  856. _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  857. end;
  858. end;
  859. end;
  860. consume(RKLAMMER);
  861. end;
  862. function statement_block(starttoken : ttoken) : ptree;
  863. var
  864. first,last : ptree;
  865. filepos : tfileposinfo;
  866. begin
  867. first:=nil;
  868. filepos:=tokenpos;
  869. consume(starttoken);
  870. inc(statement_level);
  871. while not(token in [_END,_FINALIZATION]) do
  872. begin
  873. if first=nil then
  874. begin
  875. last:=gennode(statementn,nil,statement);
  876. first:=last;
  877. end
  878. else
  879. begin
  880. last^.left:=gennode(statementn,nil,statement);
  881. last:=last^.left;
  882. end;
  883. if (token in [_END,_FINALIZATION]) then
  884. break
  885. else
  886. begin
  887. { if no semicolon, then error and go on }
  888. if token<>SEMICOLON then
  889. begin
  890. consume(SEMICOLON);
  891. consume_all_until(SEMICOLON);
  892. end;
  893. consume(SEMICOLON);
  894. end;
  895. emptystats;
  896. end;
  897. { don't consume the finalization token, it is consumed when
  898. reading the finalization block, but allow it only after
  899. an initalization ! }
  900. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  901. consume(_END);
  902. dec(statement_level);
  903. last:=gensinglenode(blockn,first);
  904. set_tree_filepos(last,filepos);
  905. statement_block:=last;
  906. end;
  907. function statement : ptree;
  908. var
  909. p : ptree;
  910. code : ptree;
  911. labelnr : plabel;
  912. filepos : tfileposinfo;
  913. label
  914. ready;
  915. begin
  916. filepos:=tokenpos;
  917. case token of
  918. _GOTO : begin
  919. if not(cs_support_goto in aktmoduleswitches)then
  920. Message(sym_e_goto_and_label_not_supported);
  921. consume(_GOTO);
  922. if (token<>INTCONST) and (token<>ID) then
  923. begin
  924. Message(sym_e_label_not_found);
  925. code:=genzeronode(errorn);
  926. end
  927. else
  928. begin
  929. getsym(pattern,true);
  930. consume(token);
  931. if srsym^.typ<>labelsym then
  932. begin
  933. Message(sym_e_id_is_no_label_id);
  934. code:=genzeronode(errorn);
  935. end
  936. else
  937. code:=genlabelnode(goton,
  938. plabelsym(srsym)^.number);
  939. end;
  940. end;
  941. _BEGIN : code:=statement_block(_BEGIN);
  942. _IF : code:=if_statement;
  943. _CASE : code:=case_statement;
  944. _REPEAT : code:=repeat_statement;
  945. _WHILE : code:=while_statement;
  946. _FOR : code:=for_statement;
  947. _NEW,_DISPOSE : code:=new_dispose_statement;
  948. _WITH : code:=with_statement;
  949. _TRY : code:=try_statement;
  950. _RAISE : code:=raise_statement;
  951. { semicolons,else until and end are ignored }
  952. SEMICOLON,
  953. _ELSE,
  954. _UNTIL,
  955. _END:
  956. code:=genzeronode(niln);
  957. _FAIL : begin
  958. { internalerror(100); }
  959. if (aktprocsym^.definition^.options and poconstructor)=0 then
  960. Message(parser_e_fail_only_in_constructor);
  961. consume(_FAIL);
  962. code:=genzeronode(failn);
  963. end;
  964. _EXIT : code:=exit_statement;
  965. _ASM : begin
  966. code:=_asm_statement;
  967. end;
  968. _EOF : begin
  969. Message(scan_f_end_of_file);
  970. end;
  971. else
  972. begin
  973. if (token=INTCONST) or
  974. ((token=ID) and not((m_result in aktmodeswitches) and (idtoken=_RESULT))) then
  975. begin
  976. getsym(pattern,true);
  977. lastsymknown:=true;
  978. lastsrsym:=srsym;
  979. { it is NOT necessarily the owner
  980. it can be a withsymtable !!! }
  981. lastsrsymtable:=srsymtable;
  982. if assigned(srsym) and (srsym^.typ=labelsym) then
  983. begin
  984. consume(token);
  985. consume(COLON);
  986. if plabelsym(srsym)^.defined then
  987. Message(sym_e_label_already_defined);
  988. plabelsym(srsym)^.defined:=true;
  989. { statement modifies srsym }
  990. labelnr:=plabelsym(srsym)^.number;
  991. lastsymknown:=false;
  992. { the pointer to the following instruction }
  993. { isn't a very clean way }
  994. {$ifdef tp}
  995. code:=gensinglenode(labeln,statement);
  996. {$else}
  997. code:=gensinglenode(labeln,statement());
  998. {$endif}
  999. code^.labelnr:=labelnr;
  1000. { sorry, but there is a jump the easiest way }
  1001. goto ready;
  1002. end;
  1003. end;
  1004. p:=expr;
  1005. if not(p^.treetype in [calln,assignn,breakn,inlinen,
  1006. continuen]) then
  1007. Message(cg_e_illegal_expression);
  1008. { specify that we don't use the value returned by the call }
  1009. { Question : can this be also improtant
  1010. for inlinen ??
  1011. it is used for :
  1012. - dispose of temp stack space
  1013. - dispose on FPU stack }
  1014. if p^.treetype=calln then
  1015. p^.return_value_used:=false;
  1016. code:=p;
  1017. end;
  1018. end;
  1019. ready:
  1020. if assigned(code) then
  1021. set_tree_filepos(code,filepos);
  1022. statement:=code;
  1023. end;
  1024. function block(islibrary : boolean) : ptree;
  1025. var
  1026. funcretsym : pfuncretsym;
  1027. begin
  1028. if procinfo.retdef<>pdef(voiddef) then
  1029. begin
  1030. { if the current is a function aktprocsym is non nil }
  1031. { and there is a local symtable set }
  1032. funcretsym:=new(pfuncretsym,init(aktprocsym^.name,@procinfo));
  1033. { insert in local symtable }
  1034. symtablestack^.insert(funcretsym);
  1035. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  1036. procinfo.retoffset:=-funcretsym^.address;
  1037. procinfo.funcretsym:=funcretsym;
  1038. end;
  1039. read_declarations(islibrary);
  1040. { temporary space is set, while the BEGIN of the procedure }
  1041. if (symtablestack^.symtabletype=localsymtable) then
  1042. procinfo.firsttemp := -symtablestack^.datasize
  1043. else procinfo.firsttemp := 0;
  1044. { space for the return value }
  1045. { !!!!! this means that we can not set the return value
  1046. in a subfunction !!!!! }
  1047. { because we don't know yet where the address is }
  1048. if procinfo.retdef<>pdef(voiddef) then
  1049. begin
  1050. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  1051. { if (procinfo.retdef^.deftype=orddef) or
  1052. (procinfo.retdef^.deftype=pointerdef) or
  1053. (procinfo.retdef^.deftype=enumdef) or
  1054. (procinfo.retdef^.deftype=procvardef) or
  1055. (procinfo.retdef^.deftype=floatdef) or
  1056. (
  1057. (procinfo.retdef^.deftype=setdef) and
  1058. (psetdef(procinfo.retdef)^.settype=smallset)
  1059. ) then }
  1060. begin
  1061. { the space has been set in the local symtable }
  1062. procinfo.retoffset:=-funcretsym^.address;
  1063. if (procinfo.flags and pi_operator)<>0 then
  1064. {opsym^.address:=procinfo.call_offset; is wrong PM }
  1065. opsym^.address:=-procinfo.retoffset;
  1066. { eax is modified by a function }
  1067. {$ifdef i386}
  1068. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  1069. if is_64bitint(procinfo.retdef) then
  1070. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  1071. {$endif}
  1072. {$ifdef m68k}
  1073. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1074. if is_64bitint(procinfo.retdef) then
  1075. usedinproc:=usedinproc or ($800 shr byte(R_D1))
  1076. {$endif}
  1077. end;
  1078. end;
  1079. {Unit initialization?.}
  1080. if (lexlevel=unit_init_level) and (current_module^.is_unit) then
  1081. if (token=_END) then
  1082. begin
  1083. consume(_END);
  1084. block:=nil;
  1085. end
  1086. else
  1087. begin
  1088. if token=_INITIALIZATION then
  1089. begin
  1090. current_module^.flags:=current_module^.flags or uf_init;
  1091. block:=statement_block(_INITIALIZATION);
  1092. end
  1093. else if (token=_FINALIZATION) then
  1094. begin
  1095. if (current_module^.flags and uf_finalize)<>0 then
  1096. block:=statement_block(_FINALIZATION)
  1097. else
  1098. begin
  1099. block:=nil;
  1100. exit;
  1101. end;
  1102. end
  1103. else
  1104. begin
  1105. current_module^.flags:=current_module^.flags or uf_init;
  1106. block:=statement_block(_BEGIN);
  1107. end;
  1108. end
  1109. else
  1110. block:=statement_block(_BEGIN);
  1111. end;
  1112. function assembler_block : ptree;
  1113. begin
  1114. read_declarations(false);
  1115. { temporary space is set, while the BEGIN of the procedure }
  1116. if symtablestack^.symtabletype=localsymtable then
  1117. procinfo.firsttemp := -symtablestack^.datasize
  1118. else
  1119. procinfo.firsttemp := 0;
  1120. { assembler code does not allocate }
  1121. { space for the return value }
  1122. if procinfo.retdef<>pdef(voiddef) then
  1123. begin
  1124. if ret_in_acc(procinfo.retdef) then
  1125. begin
  1126. { in assembler code the result should be directly in %eax
  1127. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1128. procinfo.firsttemp:=procinfo.retoffset; }
  1129. {$ifdef i386}
  1130. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1131. {$endif}
  1132. {$ifdef m68k}
  1133. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1134. {$endif}
  1135. end
  1136. {
  1137. else if not is_fpu(procinfo.retdef) then
  1138. should we allow assembler functions of big elements ?
  1139. YES (FK)!!
  1140. Message(parser_e_asm_incomp_with_function_return);
  1141. }
  1142. end;
  1143. { set the framepointer to esp for assembler functions }
  1144. { but only if the are no local variables }
  1145. { added no parameter also (PM) }
  1146. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1147. (aktprocsym^.definition^.localst^.datasize=0) and
  1148. (aktprocsym^.definition^.parast^.datasize=0) and
  1149. not(ret_in_param(aktprocsym^.definition^.retdef)) then
  1150. begin
  1151. procinfo.framepointer:=stack_pointer;
  1152. { set the right value for parameters }
  1153. dec(aktprocsym^.definition^.parast^.address_fixup,target_os.size_of_pointer);
  1154. dec(procinfo.call_offset,target_os.size_of_pointer);
  1155. end;
  1156. { force the asm statement }
  1157. if token<>_ASM then
  1158. consume(_ASM);
  1159. Procinfo.Flags := ProcInfo.Flags Or pi_is_assembler;
  1160. assembler_block:=_asm_statement;
  1161. { becuase the END is already read we need to get the
  1162. last_endtoken_filepos here (PFV) }
  1163. last_endtoken_filepos:=tokenpos;
  1164. end;
  1165. end.
  1166. {
  1167. $Log$
  1168. Revision 1.75 1999-04-14 09:14:53 peter
  1169. * first things to store the symbol/def number in the ppu
  1170. Revision 1.74 1999/04/09 12:22:06 pierre
  1171. * bug found by Peter for DirectWith code fixed
  1172. Revision 1.73 1999/04/06 11:21:57 peter
  1173. * more use of ttoken
  1174. Revision 1.72 1999/03/31 13:55:15 peter
  1175. * assembler inlining working for ag386bin
  1176. Revision 1.71 1999/03/10 11:23:29 pierre
  1177. * typecheck for exit(value) : resulttype was not set
  1178. Revision 1.70 1999/03/04 13:55:45 pierre
  1179. * some m68k fixes (still not compilable !)
  1180. * new(tobj) does not give warning if tobj has no VMT !
  1181. Revision 1.69 1999/03/02 02:56:15 peter
  1182. + stabs support for binary writers
  1183. * more fixes and missing updates from the previous commit :(
  1184. Revision 1.68 1999/02/26 00:48:23 peter
  1185. * assembler writers fixed for ag386bin
  1186. Revision 1.67 1999/02/22 13:07:01 pierre
  1187. + -b and -bl options work !
  1188. + cs_local_browser ($L+) is disabled if cs_browser ($Y+)
  1189. is not enabled when quitting global section
  1190. * local vars and procedures are not yet stored into PPU
  1191. Revision 1.66 1999/02/22 02:15:31 peter
  1192. * updates for ag386bin
  1193. Revision 1.65 1999/02/15 13:13:15 pierre
  1194. * fix for bug0216
  1195. Revision 1.64 1999/02/11 09:46:26 pierre
  1196. * fix for normal method calls inside static methods :
  1197. WARNING there were both parser and codegen errors !!
  1198. added static_call boolean to calln tree
  1199. Revision 1.63 1999/02/09 15:45:47 florian
  1200. + complex results for assembler functions, fixes bug0155
  1201. Revision 1.62 1999/01/27 13:06:57 pierre
  1202. * memory leak in case optimization fixed
  1203. Revision 1.61 1999/01/25 22:49:09 peter
  1204. * more fixes for the on bug with unknown id
  1205. Revision 1.60 1999/01/23 23:29:38 florian
  1206. * first running version of the new code generator
  1207. * when compiling exceptions under Linux fixed
  1208. Revision 1.59 1999/01/21 16:41:02 pierre
  1209. * fix for constructor inside with statements
  1210. Revision 1.58 1999/01/05 08:20:07 florian
  1211. * mainly problem with invalid case ranges fixed (reported by Jonas)
  1212. Revision 1.57 1998/12/29 18:48:15 jonas
  1213. + optimize pascal code surrounding assembler blocks
  1214. Revision 1.56 1998/12/23 22:52:56 peter
  1215. * fixed new(x) crash if x contains an error
  1216. Revision 1.55 1998/12/16 12:30:59 jonas
  1217. * released CaseRange
  1218. Revision 1.54 1998/12/15 22:32:24 jonas
  1219. + convert consecutive case labels to a single range (-dCaseRange)
  1220. Revision 1.53 1998/12/15 11:52:18 peter
  1221. * fixed dup release of statement label in case
  1222. Revision 1.52 1998/12/11 00:03:37 peter
  1223. + globtype,tokens,version unit splitted from globals
  1224. Revision 1.51 1998/12/10 09:47:24 florian
  1225. + basic operations with int64/qord (compiler with -dint64)
  1226. + rtti of enumerations extended: names are now written
  1227. Revision 1.50 1998/11/13 15:40:25 pierre
  1228. + added -Se in Makefile cvstest target
  1229. + lexlevel cleanup
  1230. normal_function_level main_program_level and unit_init_level defined
  1231. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  1232. (test added in code !)
  1233. * -Un option was wrong
  1234. * _FAIL and _SELF only keyword inside
  1235. constructors and methods respectively
  1236. Revision 1.49 1998/11/12 12:55:17 pierre
  1237. * fix for bug0176 and bug0177
  1238. Revision 1.48 1998/11/05 23:43:24 peter
  1239. * fixed assembler directive and then not an ASM statement
  1240. Revision 1.47 1998/10/30 16:20:22 peter
  1241. * fixed dispose(destructor) crash when destructor didn't exists
  1242. Revision 1.46 1998/10/20 08:06:53 pierre
  1243. * several memory corruptions due to double freemem solved
  1244. => never use p^.loc.location:=p^.left^.loc.location;
  1245. + finally I added now by default
  1246. that ra386dir translates global and unit symbols
  1247. + added a first field in tsymtable and
  1248. a nextsym field in tsym
  1249. (this allows to obtain ordered type info for
  1250. records and objects in gdb !)
  1251. Revision 1.45 1998/10/19 08:55:01 pierre
  1252. * wrong stabs info corrected once again !!
  1253. + variable vmt offset with vmt field only if required
  1254. implemented now !!!
  1255. Revision 1.44 1998/10/13 13:10:27 peter
  1256. * new style for m68k/i386 infos and enums
  1257. Revision 1.43 1998/10/08 13:46:22 peter
  1258. * added eof message
  1259. * fixed unit init section parsing with finalize
  1260. Revision 1.42 1998/09/26 17:45:38 peter
  1261. + idtoken and only one token table
  1262. Revision 1.41 1998/09/24 23:49:15 peter
  1263. + aktmodeswitches
  1264. Revision 1.40 1998/09/23 21:53:04 florian
  1265. * the following doesn't work: on texception do, was a parser error, fixed
  1266. Revision 1.39 1998/09/21 10:26:07 peter
  1267. * merged fix
  1268. Revision 1.38.2.1 1998/09/21 10:24:43 peter
  1269. * fixed error recovery with with
  1270. Revision 1.38 1998/09/04 08:42:04 peter
  1271. * updated some error messages
  1272. Revision 1.37 1998/08/21 14:08:52 pierre
  1273. + TEST_FUNCRET now default (old code removed)
  1274. works also for m68k (at least compiles)
  1275. Revision 1.36 1998/08/20 21:36:41 peter
  1276. * fixed 'with object do' bug
  1277. Revision 1.35 1998/08/20 09:26:42 pierre
  1278. + funcret setting in underproc testing
  1279. compile with _dTEST_FUNCRET
  1280. Revision 1.34 1998/08/17 10:10:09 peter
  1281. - removed OLDPPU
  1282. Revision 1.33 1998/08/12 19:39:30 peter
  1283. * fixed some crashes
  1284. Revision 1.32 1998/08/10 14:50:17 peter
  1285. + localswitches, moduleswitches, globalswitches splitting
  1286. Revision 1.31 1998/08/02 16:41:59 florian
  1287. * on o : tobject do should also work now, the exceptsymtable shouldn't be
  1288. disposed by dellexlevel
  1289. Revision 1.30 1998/07/30 16:07:10 florian
  1290. * try ... expect <statement> end; works now
  1291. Revision 1.29 1998/07/30 13:30:37 florian
  1292. * final implemenation of exception support, maybe it needs
  1293. some fixes :)
  1294. Revision 1.28 1998/07/30 11:18:18 florian
  1295. + first implementation of try ... except on .. do end;
  1296. * limitiation of 65535 bytes parameters for cdecl removed
  1297. Revision 1.27 1998/07/28 21:52:55 florian
  1298. + implementation of raise and try..finally
  1299. + some misc. exception stuff
  1300. Revision 1.26 1998/07/27 21:57:14 florian
  1301. * fix to allow tv like stream registration:
  1302. @tmenu.load doesn't work if load had parameters or if load was only
  1303. declared in an anchestor class of tmenu
  1304. Revision 1.25 1998/07/14 21:46:53 peter
  1305. * updated messages file
  1306. Revision 1.24 1998/07/10 10:48:42 peter
  1307. * fixed realnumber scanning
  1308. * [] after asmblock was not uppercased anymore
  1309. Revision 1.23 1998/06/25 08:48:18 florian
  1310. * first version of rtti support
  1311. Revision 1.22 1998/06/24 14:48:36 peter
  1312. * ifdef newppu -> ifndef oldppu
  1313. Revision 1.21 1998/06/24 14:06:34 peter
  1314. * fixed the name changes
  1315. Revision 1.20 1998/06/23 14:00:16 peter
  1316. * renamed RA* units
  1317. Revision 1.19 1998/06/08 22:59:50 peter
  1318. * smartlinking works for win32
  1319. * some defines to exclude some compiler parts
  1320. Revision 1.18 1998/06/05 14:37:35 pierre
  1321. * fixes for inline for operators
  1322. * inline procedure more correctly restricted
  1323. Revision 1.17 1998/06/04 09:55:43 pierre
  1324. * demangled name of procsym reworked to become independant of the mangling scheme
  1325. Revision 1.16 1998/06/02 17:03:04 pierre
  1326. * with node corrected for objects
  1327. * small bugs for SUPPORT_MMX fixed
  1328. Revision 1.15 1998/05/30 14:31:06 peter
  1329. + $ASMMODE
  1330. Revision 1.14 1998/05/29 09:58:14 pierre
  1331. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  1332. (probably a merging problem)
  1333. * errors at start of line were lost
  1334. Revision 1.13 1998/05/28 17:26:50 peter
  1335. * fixed -R switch, it didn't work after my previous akt/init patch
  1336. * fixed bugs 110,130,136
  1337. Revision 1.12 1998/05/21 19:33:33 peter
  1338. + better procedure directive handling and only one table
  1339. Revision 1.11 1998/05/20 09:42:35 pierre
  1340. + UseTokenInfo now default
  1341. * unit in interface uses and implementation uses gives error now
  1342. * only one error for unknown symbol (uses lastsymknown boolean)
  1343. the problem came from the label code !
  1344. + first inlined procedures and function work
  1345. (warning there might be allowed cases were the result is still wrong !!)
  1346. * UseBrower updated gives a global list of all position of all used symbols
  1347. with switch -gb
  1348. Revision 1.10 1998/05/11 13:07:56 peter
  1349. + $ifdef NEWPPU for the new ppuformat
  1350. + $define GDB not longer required
  1351. * removed all warnings and stripped some log comments
  1352. * no findfirst/findnext anymore to remove smartlink *.o files
  1353. Revision 1.9 1998/05/06 08:38:46 pierre
  1354. * better position info with UseTokenInfo
  1355. UseTokenInfo greatly simplified
  1356. + added check for changed tree after first time firstpass
  1357. (if we could remove all the cases were it happen
  1358. we could skip all firstpass if firstpasscount > 1)
  1359. Only with ExtDebug
  1360. Revision 1.8 1998/05/05 12:05:42 florian
  1361. * problems with properties fixed
  1362. * crash fixed: i:=l when i and l are undefined, was a problem with
  1363. implementation of private/protected
  1364. Revision 1.7 1998/05/01 16:38:46 florian
  1365. * handling of private and protected fixed
  1366. + change_keywords_to_tp implemented to remove
  1367. keywords which aren't supported by tp
  1368. * break and continue are now symbols of the system unit
  1369. + widestring, longstring and ansistring type released
  1370. Revision 1.6 1998/04/30 15:59:42 pierre
  1371. * GDB works again better :
  1372. correct type info in one pass
  1373. + UseTokenInfo for better source position
  1374. * fixed one remaining bug in scanner for line counts
  1375. * several little fixes
  1376. Revision 1.5 1998/04/29 10:33:59 pierre
  1377. + added some code for ansistring (not complete nor working yet)
  1378. * corrected operator overloading
  1379. * corrected nasm output
  1380. + started inline procedures
  1381. + added starstarn : use ** for exponentiation (^ gave problems)
  1382. + started UseTokenInfo cond to get accurate positions
  1383. Revision 1.4 1998/04/08 16:58:05 pierre
  1384. * several bugfixes
  1385. ADD ADC and AND are also sign extended
  1386. nasm output OK (program still crashes at end
  1387. and creates wrong assembler files !!)
  1388. procsym types sym in tdef removed !!
  1389. }