pstatmnt.pas 51 KB

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