pstatmnt.pas 52 KB

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