pstatmnt.pas 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. {$i defines.inc}
  20. interface
  21. uses
  22. tokens,node;
  23. function statement_block(starttoken : ttoken) : tnode;
  24. { reads an assembler block }
  25. function assembler_block : tnode;
  26. implementation
  27. uses
  28. { common }
  29. cutils,
  30. { global }
  31. globtype,globals,verbose,
  32. systems,cpuinfo,cpuasm,
  33. { aasm }
  34. cpubase,aasm,
  35. { symtable }
  36. symconst,symbase,symtype,symdef,symsym,symtable,types,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,pexpr,
  43. { codegen }
  44. rgobj,cgbase
  45. {$ifdef i386}
  46. {$ifndef NoRa386Int}
  47. ,ra386int
  48. {$endif NoRa386Int}
  49. {$ifndef NoRa386Att}
  50. ,ra386att
  51. {$endif NoRa386Att}
  52. {$ifndef NoRa386Dir}
  53. ,ra386dir
  54. {$endif NoRa386Dir}
  55. {$endif i386}
  56. {$ifdef m68k}
  57. {$ifndef NoRa68kMot}
  58. ,ra68kmot
  59. {$endif NoRa68kMot}
  60. {$endif m68k}
  61. { codegen }
  62. {$ifdef newcg}
  63. ,cgbase
  64. {$endif newcg}
  65. ;
  66. function statement : tnode;forward;
  67. function if_statement : tnode;
  68. var
  69. ex,if_a,else_a : tnode;
  70. begin
  71. consume(_IF);
  72. ex:=comp_expr(true);
  73. consume(_THEN);
  74. if token<>_ELSE then
  75. if_a:=statement
  76. else
  77. if_a:=nil;
  78. if try_to_consume(_ELSE) then
  79. else_a:=statement
  80. else
  81. else_a:=nil;
  82. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  83. end;
  84. { creates a block (list) of statements, til the next END token }
  85. function statements_til_end : tnode;
  86. var
  87. first,last : tstatementnode;
  88. begin
  89. first:=nil;
  90. while token<>_END do
  91. begin
  92. if first=nil then
  93. begin
  94. last:=cstatementnode.create(nil,statement);
  95. first:=last;
  96. end
  97. else
  98. begin
  99. last.left:=cstatementnode.create(nil,statement);
  100. last:=tstatementnode(last.left);
  101. end;
  102. if not try_to_consume(_SEMICOLON) then
  103. break;
  104. consume_emptystats;
  105. end;
  106. consume(_END);
  107. statements_til_end:=cblocknode.create(first);
  108. end;
  109. function case_statement : tnode;
  110. var
  111. { contains the label number of currently parsed case block }
  112. aktcaselabel : tasmlabel;
  113. firstlabel : boolean;
  114. root : pcaserecord;
  115. { the typ of the case expression }
  116. casedef : tdef;
  117. procedure newcaselabel(l,h : TConstExprInt;first:boolean);
  118. var
  119. hcaselabel : pcaserecord;
  120. procedure insertlabel(var p : pcaserecord);
  121. begin
  122. if p=nil then p:=hcaselabel
  123. else
  124. if (p^._low>hcaselabel^._low) and
  125. (p^._low>hcaselabel^._high) then
  126. if (hcaselabel^.statement = p^.statement) and
  127. (p^._low = hcaselabel^._high + 1) then
  128. begin
  129. p^._low := hcaselabel^._low;
  130. dispose(hcaselabel);
  131. end
  132. else
  133. insertlabel(p^.less)
  134. else
  135. if (p^._high<hcaselabel^._low) and
  136. (p^._high<hcaselabel^._high) then
  137. if (hcaselabel^.statement = p^.statement) and
  138. (p^._high+1 = hcaselabel^._low) then
  139. begin
  140. p^._high := hcaselabel^._high;
  141. dispose(hcaselabel);
  142. end
  143. else
  144. insertlabel(p^.greater)
  145. else Message(parser_e_double_caselabel);
  146. end;
  147. begin
  148. new(hcaselabel);
  149. hcaselabel^.less:=nil;
  150. hcaselabel^.greater:=nil;
  151. hcaselabel^.statement:=aktcaselabel;
  152. hcaselabel^.firstlabel:=first;
  153. getlabel(hcaselabel^._at);
  154. hcaselabel^._low:=l;
  155. hcaselabel^._high:=h;
  156. insertlabel(root);
  157. end;
  158. var
  159. code,caseexpr,p,instruc,elseblock : tnode;
  160. hl1,hl2 : TConstExprInt;
  161. casedeferror : boolean;
  162. begin
  163. consume(_CASE);
  164. caseexpr:=comp_expr(true);
  165. { determines result type }
  166. rg.cleartempgen;
  167. do_resulttypepass(caseexpr);
  168. casedeferror:=false;
  169. casedef:=caseexpr.resulttype.def;
  170. if (not assigned(casedef)) or
  171. not(is_ordinal(casedef)) then
  172. begin
  173. CGMessage(type_e_ordinal_expr_expected);
  174. { create a correct tree }
  175. caseexpr.free;
  176. caseexpr:=cordconstnode.create(0,u32bittype);
  177. { set error flag so no rangechecks are done }
  178. casedeferror:=true;
  179. end;
  180. consume(_OF);
  181. inc(statement_level);
  182. root:=nil;
  183. instruc:=nil;
  184. repeat
  185. getlabel(aktcaselabel);
  186. firstlabel:=true;
  187. { maybe an instruction has more case labels }
  188. repeat
  189. p:=expr;
  190. if is_widechar(casedef) then
  191. begin
  192. if (p.nodetype=rangen) then
  193. begin
  194. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  195. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  196. do_resulttypepass(trangenode(p).left);
  197. do_resulttypepass(trangenode(p).right);
  198. end
  199. else
  200. begin
  201. p:=ctypeconvnode.create(p,cwidechartype);
  202. do_resulttypepass(p);
  203. end;
  204. end;
  205. hl1:=0;
  206. hl2:=0;
  207. if (p.nodetype=rangen) then
  208. begin
  209. { type checking for case statements }
  210. if is_subequal(casedef, trangenode(p).left.resulttype.def) and
  211. is_subequal(casedef, trangenode(p).right.resulttype.def) then
  212. begin
  213. hl1:=get_ordinal_value(trangenode(p).left);
  214. hl2:=get_ordinal_value(trangenode(p).right);
  215. if hl1>hl2 then
  216. CGMessage(parser_e_case_lower_less_than_upper_bound);
  217. if not casedeferror then
  218. begin
  219. testrange(casedef,hl1,false);
  220. testrange(casedef,hl2,false);
  221. end;
  222. end
  223. else
  224. CGMessage(parser_e_case_mismatch);
  225. newcaselabel(hl1,hl2,firstlabel);
  226. end
  227. else
  228. begin
  229. { type checking for case statements }
  230. if not is_subequal(casedef, p.resulttype.def) then
  231. CGMessage(parser_e_case_mismatch);
  232. hl1:=get_ordinal_value(p);
  233. if not casedeferror then
  234. testrange(casedef,hl1,false);
  235. newcaselabel(hl1,hl1,firstlabel);
  236. end;
  237. p.free;
  238. if token=_COMMA then
  239. consume(_COMMA)
  240. else
  241. break;
  242. firstlabel:=false;
  243. until false;
  244. consume(_COLON);
  245. { handles instruction block }
  246. p:=clabelnode.createcase(aktcaselabel,statement);
  247. { concats instruction }
  248. instruc:=cstatementnode.create(instruc,p);
  249. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  250. consume(_SEMICOLON);
  251. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  252. if (token=_ELSE) or (token=_OTHERWISE) then
  253. begin
  254. if not try_to_consume(_ELSE) then
  255. consume(_OTHERWISE);
  256. elseblock:=statements_til_end;
  257. end
  258. else
  259. begin
  260. elseblock:=nil;
  261. consume(_END);
  262. end;
  263. dec(statement_level);
  264. code:=ccasenode.create(caseexpr,instruc,root);
  265. tcasenode(code).elseblock:=elseblock;
  266. case_statement:=code;
  267. end;
  268. function repeat_statement : tnode;
  269. var
  270. first,last,p_e : tnode;
  271. begin
  272. consume(_REPEAT);
  273. first:=nil;
  274. inc(statement_level);
  275. while token<>_UNTIL do
  276. begin
  277. if first=nil then
  278. begin
  279. last:=cstatementnode.create(nil,statement);
  280. first:=last;
  281. end
  282. else
  283. begin
  284. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  285. last:=tstatementnode(last).left;
  286. end;
  287. if not try_to_consume(_SEMICOLON) then
  288. break;
  289. consume_emptystats;
  290. end;
  291. consume(_UNTIL);
  292. dec(statement_level);
  293. first:=cblocknode.create(first);
  294. p_e:=comp_expr(true);
  295. repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  296. end;
  297. function while_statement : tnode;
  298. var
  299. p_e,p_a : tnode;
  300. begin
  301. consume(_WHILE);
  302. p_e:=comp_expr(true);
  303. consume(_DO);
  304. p_a:=statement;
  305. while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  306. end;
  307. function for_statement : tnode;
  308. var
  309. p_e,tovalue,p_a : tnode;
  310. backward : boolean;
  311. begin
  312. { parse loop header }
  313. consume(_FOR);
  314. p_e:=expr;
  315. if token=_DOWNTO then
  316. begin
  317. consume(_DOWNTO);
  318. backward:=true;
  319. end
  320. else
  321. begin
  322. consume(_TO);
  323. backward:=false;
  324. end;
  325. tovalue:=comp_expr(true);
  326. consume(_DO);
  327. { ... now the instruction }
  328. p_a:=statement;
  329. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  330. end;
  331. function _with_statement : tnode;
  332. var
  333. right,p : tnode;
  334. i,levelcount : longint;
  335. withsymtable,symtab : tsymtable;
  336. obj : tobjectdef;
  337. hp : tnode;
  338. begin
  339. p:=comp_expr(true);
  340. do_resulttypepass(p);
  341. set_varstate(p,false);
  342. right:=nil;
  343. if (not codegenerror) and
  344. (p.resulttype.def.deftype in [objectdef,recorddef]) then
  345. begin
  346. case p.resulttype.def.deftype of
  347. objectdef : begin
  348. obj:=tobjectdef(p.resulttype.def);
  349. symtab:=twithsymtable.Create(obj,obj.symtable.symsearch);
  350. withsymtable:=symtab;
  351. if (p.nodetype=loadn) and
  352. (tloadnode(p).symtable=aktprocdef.localst) then
  353. twithsymtable(symtab).direct_with:=true;
  354. twithsymtable(symtab).withrefnode:=p;
  355. levelcount:=1;
  356. obj:=obj.childof;
  357. while assigned(obj) do
  358. begin
  359. symtab.next:=twithsymtable.create(obj,obj.symtable.symsearch);
  360. symtab:=symtab.next;
  361. if (p.nodetype=loadn) and
  362. (tloadnode(p).symtable=aktprocdef.localst) then
  363. twithsymtable(symtab).direct_with:=true;
  364. twithsymtable(symtab).withrefnode:=p;
  365. obj:=obj.childof;
  366. inc(levelcount);
  367. end;
  368. symtab.next:=symtablestack;
  369. symtablestack:=withsymtable;
  370. end;
  371. recorddef : begin
  372. symtab:=trecorddef(p.resulttype.def).symtable;
  373. levelcount:=1;
  374. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch);
  375. if (p.nodetype=loadn) and
  376. (tloadnode(p).symtable=aktprocdef.localst) then
  377. twithsymtable(withsymtable).direct_with:=true;
  378. twithsymtable(withsymtable).withrefnode:=p;
  379. withsymtable.next:=symtablestack;
  380. symtablestack:=withsymtable;
  381. end;
  382. end;
  383. if token=_COMMA then
  384. begin
  385. consume(_COMMA);
  386. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  387. end
  388. else
  389. begin
  390. consume(_DO);
  391. if token<>_SEMICOLON then
  392. right:=statement
  393. else
  394. right:=cerrornode.create;
  395. end;
  396. for i:=1 to levelcount do
  397. symtablestack:=symtablestack.next;
  398. _with_statement:=cwithnode.create(twithsymtable(withsymtable),p,right,levelcount);
  399. end
  400. else
  401. begin
  402. Message(parser_e_false_with_expr);
  403. { try to recover from error }
  404. if token=_COMMA then
  405. begin
  406. consume(_COMMA);
  407. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  408. if (hp=nil) then; { remove warning about unused }
  409. end
  410. else
  411. begin
  412. consume(_DO);
  413. { ignore all }
  414. if token<>_SEMICOLON then
  415. statement;
  416. end;
  417. _with_statement:=nil;
  418. end;
  419. end;
  420. function with_statement : tnode;
  421. begin
  422. consume(_WITH);
  423. with_statement:=_with_statement;
  424. end;
  425. function raise_statement : tnode;
  426. var
  427. p,pobj,paddr,pframe : tnode;
  428. begin
  429. pobj:=nil;
  430. paddr:=nil;
  431. pframe:=nil;
  432. consume(_RAISE);
  433. if not(token in [_SEMICOLON,_END]) then
  434. begin
  435. { object }
  436. pobj:=comp_expr(true);
  437. if try_to_consume(_AT) then
  438. begin
  439. paddr:=comp_expr(true);
  440. if try_to_consume(_COMMA) then
  441. pframe:=comp_expr(true);
  442. end;
  443. end
  444. else
  445. begin
  446. if (block_type<>bt_except) then
  447. Message(parser_e_no_reraise_possible);
  448. end;
  449. p:=craisenode.create(pobj,paddr,pframe);
  450. raise_statement:=p;
  451. end;
  452. function try_statement : tnode;
  453. var
  454. p_try_block,p_finally_block,first,last,
  455. p_default,p_specific,hp : tnode;
  456. ot : ttype;
  457. sym : tvarsym;
  458. old_block_type : tblock_type;
  459. exceptsymtable : tsymtable;
  460. objname,objrealname : stringid;
  461. srsym : tsym;
  462. srsymtable : tsymtable;
  463. oldaktexceptblock: integer;
  464. begin
  465. procinfo^.flags:=procinfo^.flags or pi_uses_exceptions;
  466. p_default:=nil;
  467. p_specific:=nil;
  468. { read statements to try }
  469. consume(_TRY);
  470. first:=nil;
  471. inc(exceptblockcounter);
  472. oldaktexceptblock := aktexceptblock;
  473. aktexceptblock := exceptblockcounter;
  474. inc(statement_level);
  475. while (token<>_FINALLY) and (token<>_EXCEPT) do
  476. begin
  477. if first=nil then
  478. begin
  479. last:=cstatementnode.create(nil,statement);
  480. first:=last;
  481. end
  482. else
  483. begin
  484. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  485. last:=tstatementnode(last).left;
  486. end;
  487. if not try_to_consume(_SEMICOLON) then
  488. break;
  489. consume_emptystats;
  490. end;
  491. p_try_block:=cblocknode.create(first);
  492. if try_to_consume(_FINALLY) then
  493. begin
  494. inc(exceptblockcounter);
  495. aktexceptblock := exceptblockcounter;
  496. p_finally_block:=statements_til_end;
  497. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  498. dec(statement_level);
  499. end
  500. else
  501. begin
  502. consume(_EXCEPT);
  503. old_block_type:=block_type;
  504. block_type:=bt_except;
  505. inc(exceptblockcounter);
  506. aktexceptblock := exceptblockcounter;
  507. ot:=generrortype;
  508. p_specific:=nil;
  509. if (idtoken=_ON) then
  510. { catch specific exceptions }
  511. begin
  512. repeat
  513. consume(_ID);
  514. if token=_ID then
  515. begin
  516. objname:=pattern;
  517. objrealname:=orgpattern;
  518. { can't use consume_sym here, because we need already
  519. to check for the colon }
  520. searchsym(objname,srsym,srsymtable);
  521. consume(_ID);
  522. { is a explicit name for the exception given ? }
  523. if try_to_consume(_COLON) then
  524. begin
  525. consume_sym(srsym,srsymtable);
  526. if (srsym.typ=typesym) and
  527. is_class(ttypesym(srsym).restype.def) then
  528. begin
  529. ot:=ttypesym(srsym).restype;
  530. sym:=tvarsym.create(objrealname,ot);
  531. end
  532. else
  533. begin
  534. sym:=tvarsym.create(objrealname,generrortype);
  535. if (srsym.typ=typesym) then
  536. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  537. else
  538. Message1(type_e_class_type_expected,ot.def.typename);
  539. end;
  540. exceptsymtable:=tstt_exceptsymtable.create;
  541. exceptsymtable.insert(sym);
  542. { insert the exception symtable stack }
  543. exceptsymtable.next:=symtablestack;
  544. symtablestack:=exceptsymtable;
  545. end
  546. else
  547. begin
  548. { check if type is valid, must be done here because
  549. with "e: Exception" the e is not necessary }
  550. if srsym=nil then
  551. begin
  552. identifier_not_found(objrealname);
  553. srsym:=generrorsym;
  554. end;
  555. { support unit.identifier }
  556. if srsym.typ=unitsym then
  557. begin
  558. consume(_POINT);
  559. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  560. if srsym=nil then
  561. begin
  562. identifier_not_found(orgpattern);
  563. srsym:=generrorsym;
  564. end;
  565. consume(_ID);
  566. end;
  567. { check if type is valid, must be done here because
  568. with "e: Exception" the e is not necessary }
  569. if (srsym.typ=typesym) and
  570. is_class(ttypesym(srsym).restype.def) then
  571. ot:=ttypesym(srsym).restype
  572. else
  573. begin
  574. ot:=generrortype;
  575. if (srsym.typ=typesym) then
  576. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  577. else
  578. Message1(type_e_class_type_expected,ot.def.typename);
  579. end;
  580. exceptsymtable:=nil;
  581. end;
  582. end
  583. else
  584. consume(_ID);
  585. consume(_DO);
  586. hp:=connode.create(nil,statement);
  587. if ot.def.deftype=errordef then
  588. begin
  589. hp.free;
  590. hp:=cerrornode.create;
  591. end;
  592. if p_specific=nil then
  593. begin
  594. last:=hp;
  595. p_specific:=last;
  596. end
  597. else
  598. begin
  599. tonnode(last).left:=hp;
  600. last:=tonnode(last).left;
  601. end;
  602. { set the informations }
  603. { only if the creation of the onnode was succesful, it's possible }
  604. { that last and hp are errornodes (JM) }
  605. if last.nodetype = onn then
  606. begin
  607. tonnode(last).excepttype:=tobjectdef(ot.def);
  608. tonnode(last).exceptsymtable:=exceptsymtable;
  609. end;
  610. { remove exception symtable }
  611. if assigned(exceptsymtable) then
  612. begin
  613. dellexlevel;
  614. if last.nodetype <> onn then
  615. exceptsymtable.free;
  616. end;
  617. if not try_to_consume(_SEMICOLON) then
  618. break;
  619. consume_emptystats;
  620. until (token=_END) or (token=_ELSE);
  621. if token=_ELSE then
  622. { catch the other exceptions }
  623. begin
  624. consume(_ELSE);
  625. p_default:=statements_til_end;
  626. end
  627. else
  628. consume(_END);
  629. end
  630. else
  631. { catch all exceptions }
  632. begin
  633. p_default:=statements_til_end;
  634. end;
  635. dec(statement_level);
  636. block_type:=old_block_type;
  637. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  638. end;
  639. aktexceptblock := oldaktexceptblock;
  640. end;
  641. function exit_statement : tnode;
  642. var
  643. p : tnode;
  644. begin
  645. consume(_EXIT);
  646. if try_to_consume(_LKLAMMER) then
  647. begin
  648. p:=comp_expr(true);
  649. consume(_RKLAMMER);
  650. if (block_type=bt_except) then
  651. Message(parser_e_exit_with_argument_not__possible);
  652. if is_void(aktprocdef.rettype.def) then
  653. Message(parser_e_void_function);
  654. end
  655. else
  656. p:=nil;
  657. p:=cexitnode.create(p);
  658. do_resulttypepass(p);
  659. exit_statement:=p;
  660. end;
  661. function _asm_statement : tnode;
  662. var
  663. asmstat : tasmnode;
  664. Marker : tai;
  665. begin
  666. Inside_asm_statement:=true;
  667. case aktasmmode of
  668. asmmode_none : ; { just be there to allow to a compile without
  669. any assembler readers }
  670. {$ifdef i386}
  671. {$ifndef NoRA386Att}
  672. asmmode_i386_att:
  673. asmstat:=tasmnode(ra386att.assemble);
  674. {$endif NoRA386Att}
  675. {$ifndef NoRA386Int}
  676. asmmode_i386_intel:
  677. asmstat:=tasmnode(ra386int.assemble);
  678. {$endif NoRA386Int}
  679. {$ifndef NoRA386Dir}
  680. asmmode_i386_direct:
  681. begin
  682. if not target_asm.allowdirect then
  683. Message(parser_f_direct_assembler_not_allowed);
  684. if (aktprocdef.proccalloption=pocall_inline) then
  685. Begin
  686. Message1(parser_w_not_supported_for_inline,'direct asm');
  687. Message(parser_w_inlining_disabled);
  688. aktprocdef.proccalloption:=pocall_fpccall;
  689. End;
  690. asmstat:=tasmnode(ra386dir.assemble);
  691. end;
  692. {$endif NoRA386Dir}
  693. {$endif}
  694. {$ifdef m68k}
  695. {$ifndef NoRA68kMot}
  696. asmmode_m68k_mot:
  697. asmstat:=tasmnode(ra68kmot.assemble);
  698. {$endif NoRA68kMot}
  699. {$endif}
  700. else
  701. Message(parser_f_assembler_reader_not_supported);
  702. end;
  703. { Read first the _ASM statement }
  704. consume(_ASM);
  705. { END is read }
  706. if try_to_consume(_LECKKLAMMER) then
  707. begin
  708. { it's possible to specify the modified registers }
  709. include(asmstat.flags,nf_object_preserved);
  710. if token<>_RECKKLAMMER then
  711. repeat
  712. { uppercase, because it's a CSTRING }
  713. uppervar(pattern);
  714. {$ifdef i386}
  715. if pattern='EAX' then
  716. include(rg.usedinproc,R_EAX)
  717. else if pattern='EBX' then
  718. include(rg.usedinproc,R_EBX)
  719. else if pattern='ECX' then
  720. include(rg.usedinproc,R_ECX)
  721. else if pattern='EDX' then
  722. include(rg.usedinproc,R_EDX)
  723. else if pattern='ESI' then
  724. begin
  725. include(rg.usedinproc,R_ESI);
  726. exclude(asmstat.flags,nf_object_preserved);
  727. end
  728. else if pattern='EDI' then
  729. include(rg.usedinproc,R_EDI)
  730. {$endif i386}
  731. {$ifdef m68k}
  732. if pattern='D0' then
  733. include(rg.usedinproc,R_D0)
  734. else if pattern='D1' then
  735. include(rg.usedinproc,R_D1)
  736. else if pattern='D2' then
  737. include(rg.usedinproc,R_D2)
  738. else if pattern='D3' then
  739. include(rg.usedinproc,R_D3)
  740. else if pattern='D4' then
  741. include(rg.usedinproc,R_D4)
  742. else if pattern='D5' then
  743. include(rg.usedinproc,R_D5)
  744. else if pattern='D6' then
  745. include(rg.usedinproc,R_D6)
  746. else if pattern='D7' then
  747. include(rg.usedinproc,R_D7)
  748. else if pattern='A0' then
  749. include(rg.usedinproc,R_A0)
  750. else if pattern='A1' then
  751. include(rg.usedinproc,R_A1)
  752. else if pattern='A2' then
  753. include(rg.usedinproc,R_A2)
  754. else if pattern='A3' then
  755. include(rg.usedinproc,R_A3)
  756. else if pattern='A4' then
  757. include(rg.usedinproc,R_A4)
  758. else if pattern='A5' then
  759. include(rg.usedinproc,R_A5)
  760. {$endif m68k}
  761. {$ifdef powerpc}
  762. if pattern<>'' then
  763. internalerror(200108251)
  764. {$endif powerpc}
  765. else consume(_RECKKLAMMER);
  766. consume(_CSTRING);
  767. if not try_to_consume(_COMMA) then
  768. break;
  769. until false;
  770. consume(_RECKKLAMMER);
  771. end
  772. else rg.usedinproc := ALL_REGISTERS;
  773. { mark the start and the end of the assembler block
  774. this is needed for the optimizer }
  775. If Assigned(AsmStat.p_asm) Then
  776. Begin
  777. Marker := Tai_Marker.Create(AsmBlockStart);
  778. AsmStat.p_asm.Insert(Marker);
  779. Marker := Tai_Marker.Create(AsmBlockEnd);
  780. AsmStat.p_asm.Concat(Marker);
  781. End;
  782. Inside_asm_statement:=false;
  783. _asm_statement:=asmstat;
  784. end;
  785. function statement : tnode;
  786. var
  787. p : tnode;
  788. code : tnode;
  789. filepos : tfileposinfo;
  790. srsym : tsym;
  791. srsymtable : tsymtable;
  792. s : stringid;
  793. begin
  794. filepos:=akttokenpos;
  795. case token of
  796. _GOTO :
  797. begin
  798. if not(cs_support_goto in aktmoduleswitches)then
  799. Message(sym_e_goto_and_label_not_supported);
  800. consume(_GOTO);
  801. if (token<>_INTCONST) and (token<>_ID) then
  802. begin
  803. Message(sym_e_label_not_found);
  804. code:=cerrornode.create;
  805. end
  806. else
  807. begin
  808. if token=_ID then
  809. consume_sym(srsym,srsymtable)
  810. else
  811. begin
  812. searchsym(pattern,srsym,srsymtable);
  813. if srsym=nil then
  814. begin
  815. identifier_not_found(pattern);
  816. srsym:=generrorsym;
  817. srsymtable:=nil;
  818. end;
  819. consume(token);
  820. end;
  821. if srsym.typ<>labelsym then
  822. begin
  823. Message(sym_e_id_is_no_label_id);
  824. code:=cerrornode.create;
  825. end
  826. else
  827. begin
  828. code:=cgotonode.create(tlabelsym(srsym));
  829. tgotonode(code).labsym:=tlabelsym(srsym);
  830. { set flag that this label is used }
  831. tlabelsym(srsym).used:=true;
  832. end;
  833. end;
  834. end;
  835. _BEGIN :
  836. code:=statement_block(_BEGIN);
  837. _IF :
  838. code:=if_statement;
  839. _CASE :
  840. code:=case_statement;
  841. _REPEAT :
  842. code:=repeat_statement;
  843. _WHILE :
  844. code:=while_statement;
  845. _FOR :
  846. code:=for_statement;
  847. _WITH :
  848. code:=with_statement;
  849. _TRY :
  850. code:=try_statement;
  851. _RAISE :
  852. code:=raise_statement;
  853. { semicolons,else until and end are ignored }
  854. _SEMICOLON,
  855. _ELSE,
  856. _UNTIL,
  857. _END:
  858. code:=cnothingnode.create;
  859. _FAIL :
  860. begin
  861. if (aktprocdef.proctypeoption<>potype_constructor) then
  862. Message(parser_e_fail_only_in_constructor);
  863. consume(_FAIL);
  864. code:=cfailnode.create;
  865. end;
  866. _EXIT :
  867. code:=exit_statement;
  868. _ASM :
  869. code:=_asm_statement;
  870. _EOF :
  871. Message(scan_f_end_of_file);
  872. else
  873. begin
  874. p:=expr;
  875. { When a colon follows a intconst then transform it into a label }
  876. if try_to_consume(_COLON) then
  877. begin
  878. s:=tostr(tordconstnode(p).value);
  879. p.free;
  880. searchsym(s,srsym,srsymtable);
  881. if assigned(srsym) then
  882. begin
  883. if tlabelsym(srsym).defined then
  884. Message(sym_e_label_already_defined);
  885. tlabelsym(srsym).defined:=true;
  886. p:=clabelnode.create(tlabelsym(srsym),nil);
  887. end
  888. else
  889. begin
  890. identifier_not_found(s);
  891. p:=cnothingnode.create;
  892. end;
  893. end;
  894. if p.nodetype=labeln then
  895. begin
  896. { the pointer to the following instruction }
  897. { isn't a very clean way }
  898. tlabelnode(p).left:=statement{$ifdef FPCPROCVAR}(){$endif};
  899. { be sure to have left also resulttypepass }
  900. resulttypepass(tlabelnode(p).left);
  901. end;
  902. { blockn support because a read/write is changed into a blocknode }
  903. { with a separate statement for each read/write operation (JM) }
  904. { the same is true for val() if the third parameter is not 32 bit }
  905. if not(p.nodetype in [nothingn,calln,assignn,breakn,inlinen,
  906. continuen,labeln,blockn]) then
  907. Message(cg_e_illegal_expression);
  908. { specify that we don't use the value returned by the call }
  909. { Question : can this be also improtant
  910. for inlinen ??
  911. it is used for :
  912. - dispose of temp stack space
  913. - dispose on FPU stack }
  914. if p.nodetype=calln then
  915. exclude(p.flags,nf_return_value_used);
  916. code:=p;
  917. end;
  918. end;
  919. if assigned(code) then
  920. code.set_tree_filepos(filepos);
  921. statement:=code;
  922. end;
  923. function statement_block(starttoken : ttoken) : tnode;
  924. var
  925. first,last : tnode;
  926. filepos : tfileposinfo;
  927. begin
  928. first:=nil;
  929. filepos:=akttokenpos;
  930. consume(starttoken);
  931. inc(statement_level);
  932. while not(token in [_END,_FINALIZATION]) do
  933. begin
  934. if first=nil then
  935. begin
  936. last:=cstatementnode.create(nil,statement);
  937. first:=last;
  938. end
  939. else
  940. begin
  941. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  942. last:=tstatementnode(last).left;
  943. end;
  944. if (token in [_END,_FINALIZATION]) then
  945. break
  946. else
  947. begin
  948. { if no semicolon, then error and go on }
  949. if token<>_SEMICOLON then
  950. begin
  951. consume(_SEMICOLON);
  952. consume_all_until(_SEMICOLON);
  953. end;
  954. consume(_SEMICOLON);
  955. end;
  956. consume_emptystats;
  957. end;
  958. { don't consume the finalization token, it is consumed when
  959. reading the finalization block, but allow it only after
  960. an initalization ! }
  961. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  962. consume(_END);
  963. dec(statement_level);
  964. last:=cblocknode.create(first);
  965. last.set_tree_filepos(filepos);
  966. statement_block:=last;
  967. end;
  968. function assembler_block : tnode;
  969. {# Optimize the assembler block by removing all references
  970. which are via the frame pointer by replacing them with
  971. references via the stack pointer.
  972. This is only available to certain cpu targets where
  973. the frame pointer saving must be done explicitly.
  974. }
  975. procedure OptimizeFramePointer(p:tasmnode);
  976. var
  977. hp : tai;
  978. parafixup,
  979. i : longint;
  980. begin
  981. { replace framepointer with stackpointer }
  982. procinfo^.framepointer:=STACK_POINTER_REG;
  983. { set the right value for parameters }
  984. dec(aktprocdef.parast.address_fixup,pointer_size);
  985. dec(procinfo^.para_offset,pointer_size);
  986. { replace all references to parameters in the instructions,
  987. the parameters can be identified by the parafixup option
  988. that is set. For normal user coded [ebp+4] this field is not
  989. set }
  990. parafixup:=aktprocdef.parast.address_fixup;
  991. hp:=tai(p.p_asm.first);
  992. while assigned(hp) do
  993. begin
  994. if hp.typ=ait_instruction then
  995. begin
  996. { fixup the references }
  997. for i:=1 to taicpu(hp).ops do
  998. begin
  999. with taicpu(hp).oper[i-1] do
  1000. if typ=top_ref then
  1001. begin
  1002. case ref^.options of
  1003. ref_parafixup :
  1004. begin
  1005. ref^.offsetfixup:=parafixup;
  1006. ref^.base:=STACK_POINTER_REG;
  1007. end;
  1008. end;
  1009. end;
  1010. end;
  1011. end;
  1012. hp:=tai(hp.next);
  1013. end;
  1014. end;
  1015. {$ifdef CHECKFORPUSH}
  1016. function UsesPush(p:tasmnode):boolean;
  1017. var
  1018. hp : tai;
  1019. begin
  1020. hp:=tai(p.p_asm.first);
  1021. while assigned(hp) do
  1022. begin
  1023. if (hp.typ=ait_instruction) and
  1024. (taicpu(hp).opcode=A_PUSH) then
  1025. begin
  1026. UsesPush:=true;
  1027. exit;
  1028. end;
  1029. hp:=tai(hp.next);
  1030. end;
  1031. UsesPush:=false;
  1032. end;
  1033. {$endif CHECKFORPUSH}
  1034. var
  1035. p : tnode;
  1036. haslocals,hasparas : boolean;
  1037. begin
  1038. { retrieve info about locals and paras before a result
  1039. is inserted in the symtable }
  1040. haslocals:=(aktprocdef.localst.datasize>0);
  1041. hasparas:=(aktprocdef.parast.datasize>0);
  1042. { temporary space is set, while the BEGIN of the procedure }
  1043. if symtablestack.symtabletype=localsymtable then
  1044. procinfo^.firsttemp_offset := -symtablestack.datasize
  1045. else
  1046. procinfo^.firsttemp_offset := 0;
  1047. { assembler code does not allocate }
  1048. { space for the return value }
  1049. if not is_void(aktprocdef.rettype.def) then
  1050. begin
  1051. aktprocdef.funcretsym:=tfuncretsym.create(aktprocsym.name,aktprocdef.rettype);
  1052. { insert in local symtable }
  1053. { but with another name, so that recursive calls are possible }
  1054. symtablestack.insert(aktprocdef.funcretsym);
  1055. symtablestack.rename(aktprocdef.funcretsym.name,'$result');
  1056. { update the symtablesize back to 0 if there were no locals }
  1057. if not haslocals then
  1058. symtablestack.datasize:=0;
  1059. { set the used flag for the return }
  1060. if ret_in_acc(aktprocdef.rettype.def) then
  1061. include(rg.usedinproc,accumulator);
  1062. end;
  1063. { force the asm statement }
  1064. if token<>_ASM then
  1065. consume(_ASM);
  1066. procinfo^.Flags := procinfo^.Flags Or pi_is_assembler;
  1067. p:=_asm_statement;
  1068. { set the framepointer to esp for assembler functions when the
  1069. following conditions are met:
  1070. - if the are no local variables
  1071. - no reference to the result variable (refcount<=1)
  1072. - result is not stored as parameter
  1073. - target processor has optional frame pointer save
  1074. (vm, i386, vm only currently)
  1075. }
  1076. if (po_assembler in aktprocdef.procoptions) and
  1077. (not haslocals) and
  1078. (not hasparas) and
  1079. (aktprocdef.owner.symtabletype<>objectsymtable) and
  1080. (not assigned(aktprocdef.funcretsym) or
  1081. (tfuncretsym(aktprocdef.funcretsym).refcount<=1)) and
  1082. not(ret_in_param(aktprocdef.rettype.def)) and
  1083. (target_cpu in [cpu_i386,cpu_m68k,cpu_vm])
  1084. {$ifdef CHECKFORPUSH}
  1085. and not(UsesPush(tasmnode(p)))
  1086. {$endif CHECKFORPUSH}
  1087. then
  1088. OptimizeFramePointer(tasmnode(p));
  1089. { Flag the result as assigned when it is returned in the
  1090. accumulator or on the fpu stack }
  1091. if assigned(aktprocdef.funcretsym) and
  1092. (is_fpu(aktprocdef.rettype.def) or
  1093. ret_in_acc(aktprocdef.rettype.def)) then
  1094. tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
  1095. { because the END is already read we need to get the
  1096. last_endtoken_filepos here (PFV) }
  1097. last_endtoken_filepos:=akttokenpos;
  1098. assembler_block:=p;
  1099. end;
  1100. end.
  1101. {
  1102. $Log$
  1103. Revision 1.54 2002-04-21 19:02:05 peter
  1104. * removed newn and disposen nodes, the code is now directly
  1105. inlined from pexpr
  1106. * -an option that will write the secondpass nodes to the .s file, this
  1107. requires EXTDEBUG define to actually write the info
  1108. * fixed various internal errors and crashes due recent code changes
  1109. Revision 1.53 2002/04/20 21:32:24 carl
  1110. + generic FPC_CHECKPOINTER
  1111. + first parameter offset in stack now portable
  1112. * rename some constants
  1113. + move some cpu stuff to other units
  1114. - remove unused constents
  1115. * fix stacksize for some targets
  1116. * fix generic size problems which depend now on EXTEND_SIZE constant
  1117. Revision 1.52 2002/04/16 16:11:17 peter
  1118. * using inherited; without a parent having the same function
  1119. will do nothing like delphi
  1120. Revision 1.51 2002/04/15 19:01:28 carl
  1121. + target_info.size_of_pointer -> pointer_Size
  1122. Revision 1.50 2002/04/14 16:53:54 carl
  1123. + asm statement uses ALL_REGISTERS
  1124. Revision 1.49 2002/03/31 20:26:36 jonas
  1125. + a_loadfpu_* and a_loadmm_* methods in tcg
  1126. * register allocation is now handled by a class and is mostly processor
  1127. independent (+rgobj.pas and i386/rgcpu.pas)
  1128. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1129. * some small improvements and fixes to the optimizer
  1130. * some register allocation fixes
  1131. * some fpuvaroffset fixes in the unary minus node
  1132. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1133. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1134. also better optimizable)
  1135. * fixed and optimized register saving/restoring for new/dispose nodes
  1136. * LOC_FPU locations now also require their "register" field to be set to
  1137. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1138. - list field removed of the tnode class because it's not used currently
  1139. and can cause hard-to-find bugs
  1140. Revision 1.48 2002/03/11 19:10:28 peter
  1141. * Regenerated with updated fpcmake
  1142. Revision 1.47 2002/03/04 17:54:59 peter
  1143. * allow oridinal labels again
  1144. Revision 1.46 2002/01/29 21:32:03 peter
  1145. * allow accessing locals in other lexlevel when the current assembler
  1146. routine doesn't have locals.
  1147. Revision 1.45 2002/01/24 18:25:49 peter
  1148. * implicit result variable generation for assembler routines
  1149. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1150. Revision 1.44 2001/11/09 10:06:56 jonas
  1151. * allow recursive calls again in assembler procedure
  1152. Revision 1.43 2001/11/02 22:58:05 peter
  1153. * procsym definition rewrite
  1154. Revision 1.42 2001/10/26 22:36:42 florian
  1155. * fixed ranges in case statements with widechars
  1156. Revision 1.41 2001/10/25 21:22:37 peter
  1157. * calling convention rewrite
  1158. Revision 1.40 2001/10/24 11:51:39 marco
  1159. * Make new/dispose system functions instead of keywords
  1160. Revision 1.39 2001/10/17 22:41:04 florian
  1161. * several widechar fixes, case works now
  1162. Revision 1.38 2001/10/16 15:10:35 jonas
  1163. * fixed goto/label/try bugs
  1164. Revision 1.37 2001/09/22 11:11:43 peter
  1165. * "fpc -P?" command to query for used ppcXXX compiler
  1166. Revision 1.36 2001/09/06 10:21:50 jonas
  1167. * fixed superfluous generation of stackframes for assembler procedures
  1168. with no local vars or para's (this broke the backtrace printing in case
  1169. of an rte)
  1170. Revision 1.35 2001/09/03 13:19:12 jonas
  1171. * set funcretsym for assembler procedures too (otherwise using __RESULT
  1172. in assembler procedures causes a crash)
  1173. Revision 1.34 2001/08/26 13:36:46 florian
  1174. * some cg reorganisation
  1175. * some PPC updates
  1176. Revision 1.33 2001/08/23 14:28:36 jonas
  1177. + tempcreate/ref/delete nodes (allows the use of temps in the
  1178. resulttype and first pass)
  1179. * made handling of read(ln)/write(ln) processor independent
  1180. * moved processor independent handling for str and reset/rewrite-typed
  1181. from firstpass to resulttype pass
  1182. * changed names of helpers in text.inc to be generic for use as
  1183. compilerprocs + added "iocheck" directive for most of them
  1184. * reading of ordinals is done by procedures instead of functions
  1185. because otherwise FPC_IOCHECK overwrote the result before it could
  1186. be stored elsewhere (range checking still works)
  1187. * compilerprocs can now be used in the system unit before they are
  1188. implemented
  1189. * added note to errore.msg that booleans can't be read using read/readln
  1190. Revision 1.32 2001/08/06 21:40:47 peter
  1191. * funcret moved from tprocinfo to tprocdef
  1192. Revision 1.31 2001/06/03 21:57:37 peter
  1193. + hint directive parsing support
  1194. Revision 1.30 2001/05/17 13:25:24 jonas
  1195. * fixed web bugs 1480 and 1481
  1196. Revision 1.29 2001/05/04 15:52:04 florian
  1197. * some Delphi incompatibilities fixed:
  1198. - out, dispose and new can be used as idenfiers now
  1199. - const p = apointerype(nil); is supported now
  1200. + support for const p = apointertype(pointer(1234)); added
  1201. Revision 1.28 2001/04/21 12:03:11 peter
  1202. * m68k updates merged from fixes branch
  1203. Revision 1.27 2001/04/18 22:01:57 peter
  1204. * registration of targets and assemblers
  1205. Revision 1.26 2001/04/15 09:48:30 peter
  1206. * fixed crash in labelnode
  1207. * easier detection of goto and label in try blocks
  1208. Revision 1.25 2001/04/14 14:07:11 peter
  1209. * moved more code from pass_1 to det_resulttype
  1210. Revision 1.24 2001/04/13 01:22:13 peter
  1211. * symtable change to classes
  1212. * range check generation and errors fixed, make cycle DEBUG=1 works
  1213. * memory leaks fixed
  1214. Revision 1.23 2001/04/04 22:43:52 peter
  1215. * remove unnecessary calls to firstpass
  1216. Revision 1.22 2001/04/02 21:20:34 peter
  1217. * resulttype rewrite
  1218. Revision 1.21 2001/03/22 22:35:42 florian
  1219. + support for type a = (a=1); in Delphi mode added
  1220. + procedure p(); in Delphi mode supported
  1221. + on isn't keyword anymore, it can be used as
  1222. id etc. now
  1223. Revision 1.20 2001/03/11 22:58:50 peter
  1224. * getsym redesign, removed the globals srsym,srsymtable
  1225. Revision 1.19 2000/12/25 00:07:27 peter
  1226. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1227. tlinkedlist objects)
  1228. Revision 1.18 2000/12/23 19:59:35 peter
  1229. * object to class for ow/og objects
  1230. * split objectdata from objectoutput
  1231. Revision 1.17 2000/12/16 22:45:55 jonas
  1232. * fixed case statements with int64 values
  1233. Revision 1.16 2000/11/29 00:30:37 florian
  1234. * unused units removed from uses clause
  1235. * some changes for widestrings
  1236. Revision 1.15 2000/11/27 15:47:19 jonas
  1237. * fix for web bug 1251 (example 1)
  1238. Revision 1.14 2000/11/22 22:43:34 peter
  1239. * fixed crash with exception without sysutils (merged)
  1240. Revision 1.13 2000/11/04 14:25:21 florian
  1241. + merged Attila's changes for interfaces, not tested yet
  1242. Revision 1.12 2000/10/31 22:02:50 peter
  1243. * symtable splitted, no real code changes
  1244. Revision 1.11 2000/10/14 21:52:56 peter
  1245. * fixed memory leaks
  1246. Revision 1.10 2000/10/14 10:14:52 peter
  1247. * moehrendorf oct 2000 rewrite
  1248. Revision 1.9 2000/10/01 19:48:25 peter
  1249. * lot of compile updates for cg11
  1250. Revision 1.8 2000/09/24 21:19:50 peter
  1251. * delphi compile fixes
  1252. Revision 1.7 2000/09/24 15:06:24 peter
  1253. * use defines.inc
  1254. Revision 1.6 2000/08/27 16:11:52 peter
  1255. * moved some util functions from globals,cobjects to cutils
  1256. * splitted files into finput,fmodule
  1257. Revision 1.5 2000/08/12 15:41:15 peter
  1258. * fixed bug 1096 (merged)
  1259. Revision 1.4 2000/08/12 06:46:06 florian
  1260. + case statement for int64/qword implemented
  1261. Revision 1.3 2000/07/13 12:08:27 michael
  1262. + patched to 1.1.0 with former 1.09patch from peter
  1263. Revision 1.2 2000/07/13 11:32:45 michael
  1264. + removed logs
  1265. }