pstatmnt.pas 49 KB

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