pstatmnt.pas 50 KB

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