psub.pas 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl, Daniel Mantione
  4. Does the parsing of the procedures/functions
  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 psub;
  19. interface
  20. uses
  21. cobjects,
  22. symconst,tokens,symtable;
  23. const
  24. pd_global = $1; { directive must be global }
  25. pd_body = $2; { directive needs a body }
  26. pd_implemen = $4; { directive can be used implementation section }
  27. pd_interface = $8; { directive can be used interface section }
  28. pd_object = $10; { directive can be used object declaration }
  29. pd_procvar = $20; { directive can be used procvar declaration }
  30. pd_notobject = $40;{ directive can not be used object declaration }
  31. procedure compile_proc_body(const proc_names:Tstringcontainer;
  32. make_global,parent_has_class:boolean);
  33. procedure parse_proc_head(options:tproctypeoption);
  34. procedure parse_proc_dec;
  35. function is_proc_directive(tok:ttoken):boolean;
  36. procedure parse_var_proc_directives(var sym : psym);
  37. procedure parse_object_proc_directives(var sym : pprocsym);
  38. procedure read_proc;
  39. implementation
  40. uses
  41. globtype,systems,
  42. strings,globals,verbose,files,
  43. scanner,aasm,tree,types,
  44. import,gendef,
  45. {$ifdef newcg}
  46. cgbase,
  47. {$else newcg}
  48. hcodegen,temp_gen,
  49. {$endif newcg}
  50. pass_1,cpubase,cpuasm
  51. {$ifndef NOPASS2}
  52. ,pass_2
  53. {$endif}
  54. {$ifdef GDB}
  55. ,gdb
  56. {$endif GDB}
  57. {$ifdef newcg}
  58. {$ifndef NOOPT}
  59. ,aopt
  60. {$endif}
  61. {$else}
  62. {$ifdef i386}
  63. ,tgeni386
  64. ,cgai386
  65. {$ifndef NOOPT}
  66. ,aopt386
  67. {$endif}
  68. {$endif}
  69. {$ifdef m68k}
  70. ,tgen68k,cga68k
  71. {$endif}
  72. {$endif newcg}
  73. { parser specific stuff }
  74. ,pbase,ptype,pdecl,pexpr,pstatmnt
  75. {$ifdef newcg}
  76. ,tgcpu,convtree,cgobj,tgeni386 { for the new code generator tgeni386 is only a dummy }
  77. {$endif newcg}
  78. ;
  79. var
  80. realname:string; { contains the real name of a procedure as it's typed }
  81. procedure parse_proc_head(options:tproctypeoption);
  82. var sp:stringid;
  83. pd:Pprocdef;
  84. paramoffset:longint;
  85. sym:Psym;
  86. hs:string;
  87. st : psymtable;
  88. overloaded_level:word;
  89. storepos,procstartfilepos : tfileposinfo;
  90. begin
  91. { Save the position where this procedure really starts and set col to 1 which
  92. looks nicer }
  93. procstartfilepos:=tokenpos;
  94. { procstartfilepos.column:=1; I do not agree here !!
  95. lets keep excat position PM }
  96. if (options=potype_operator) then
  97. begin
  98. sp:=overloaded_names[optoken];
  99. realname:=sp;
  100. end
  101. else
  102. begin
  103. sp:=pattern;
  104. realname:=orgpattern;
  105. consume(_ID);
  106. end;
  107. { method ? }
  108. if not(parse_only) and try_to_consume(_POINT) then
  109. begin
  110. storepos:=tokenpos;
  111. tokenpos:=procstartfilepos;
  112. getsym(sp,true);
  113. sym:=srsym;
  114. tokenpos:=storepos;
  115. { load proc name }
  116. sp:=pattern;
  117. realname:=orgpattern;
  118. procstartfilepos:=tokenpos;
  119. { qualifier is class name ? }
  120. if (sym^.typ<>typesym) or
  121. (ptypesym(sym)^.restype.def^.deftype<>objectdef) then
  122. begin
  123. Message(parser_e_class_id_expected);
  124. aktprocsym:=nil;
  125. consume(_ID);
  126. end
  127. else
  128. begin
  129. { used to allow private syms to be seen }
  130. aktobjectdef:=pobjectdef(ptypesym(sym)^.restype.def);
  131. procinfo^._class:=pobjectdef(ptypesym(sym)^.restype.def);
  132. aktprocsym:=pprocsym(procinfo^._class^.symtable^.search(sp));
  133. consume(_ID);
  134. {The procedure has been found. So it is
  135. a global one. Set the flags to mark this.}
  136. procinfo^.flags:=procinfo^.flags or pi_is_global;
  137. aktobjectdef:=nil;
  138. { we solve this below }
  139. if not(assigned(aktprocsym)) then
  140. Message(parser_e_methode_id_expected);
  141. end;
  142. end
  143. else
  144. begin
  145. { check for constructor/destructor which is not allowed here }
  146. if (not parse_only) and
  147. (options in [potype_constructor,potype_destructor]) then
  148. Message(parser_e_constructors_always_objects);
  149. tokenpos:=procstartfilepos;
  150. aktprocsym:=pprocsym(symtablestack^.search(sp));
  151. if not(parse_only) then
  152. begin
  153. {The procedure we prepare for is in the implementation
  154. part of the unit we compile. It is also possible that we
  155. are compiling a program, which is also some kind of
  156. implementaion part.
  157. We need to find out if the procedure is global. If it is
  158. global, it is in the global symtable.}
  159. if not assigned(aktprocsym) and
  160. (symtablestack^.symtabletype=staticsymtable) then
  161. begin
  162. {Search the procedure in the global symtable.}
  163. aktprocsym:=Pprocsym(search_a_symtable(sp,globalsymtable));
  164. if assigned(aktprocsym) then
  165. begin
  166. {Check if it is a procedure.}
  167. if aktprocsym^.typ<>procsym then
  168. DuplicateSym(aktprocsym);
  169. {The procedure has been found. So it is
  170. a global one. Set the flags to mark this.}
  171. procinfo^.flags:=procinfo^.flags or pi_is_global;
  172. end;
  173. end;
  174. end;
  175. end;
  176. { Create the mangledname }
  177. {$ifndef UseNiceNames}
  178. if assigned(procinfo^._class) then
  179. begin
  180. if (pos('_$$_',procprefix)=0) then
  181. hs:=procprefix+'_$$_'+procinfo^._class^.objname^+'_$$_'+sp
  182. else
  183. hs:=procprefix+'_$'+sp;
  184. end
  185. else
  186. begin
  187. if lexlevel=normal_function_level then
  188. hs:=procprefix+'_'+sp
  189. else
  190. hs:=procprefix+'_$'+sp;
  191. end;
  192. {$else UseNiceNames}
  193. if assigned(procinfo^._class) then
  194. begin
  195. if (pos('_5Class_',procprefix)=0) then
  196. hs:=procprefix+'_5Class_'+procinfo^._class^.name^+'_'+tostr(length(sp))+sp
  197. else
  198. hs:=procprefix+'_'+tostr(length(sp))+sp;
  199. end
  200. else
  201. begin
  202. if lexlevel=normal_function_level then
  203. hs:=procprefix+'_'+tostr(length(sp))+sp
  204. else
  205. hs:=lowercase(procprefix)+'_'+tostr(length(sp))+sp;
  206. end;
  207. {$endif UseNiceNames}
  208. if assigned(aktprocsym) then
  209. begin
  210. { Check if overloading is enabled }
  211. if not(m_fpc in aktmodeswitches) then
  212. begin
  213. if aktprocsym^.typ<>procsym then
  214. begin
  215. DuplicateSym(aktprocsym);
  216. { try to recover by creating a new aktprocsym }
  217. tokenpos:=procstartfilepos;
  218. aktprocsym:=new(pprocsym,init(sp));
  219. end
  220. else
  221. begin
  222. if not(aktprocsym^.definition^.forwarddef) then
  223. Message(parser_e_procedure_overloading_is_off);
  224. end;
  225. end
  226. else
  227. begin
  228. { Check if the overloaded sym is realy a procsym }
  229. if aktprocsym^.typ<>procsym then
  230. begin
  231. Message1(parser_e_overloaded_no_procedure,aktprocsym^.name);
  232. { try to recover by creating a new aktprocsym }
  233. tokenpos:=procstartfilepos;
  234. aktprocsym:=new(pprocsym,init(sp));
  235. end;
  236. end;
  237. end
  238. else
  239. begin
  240. { create a new procsym and set the real filepos }
  241. tokenpos:=procstartfilepos;
  242. aktprocsym:=new(pprocsym,init(sp));
  243. { for operator we have only one definition for each overloaded
  244. operation }
  245. if (options=potype_operator) then
  246. begin
  247. { the only problem is that nextoverloaded might not be in a unit
  248. known for the unit itself }
  249. if assigned(overloaded_operators[optoken]) then
  250. aktprocsym^.definition:=overloaded_operators[optoken]^.definition;
  251. end;
  252. symtablestack^.insert(aktprocsym);
  253. end;
  254. st:=symtablestack;
  255. pd:=new(pprocdef,init);
  256. pd^.symtablelevel:=symtablestack^.symtablelevel;
  257. if assigned(procinfo^._class) then
  258. pd^._class := procinfo^._class;
  259. { set the options from the caller (podestructor or poconstructor) }
  260. pd^.proctypeoption:=options;
  261. { calculate the offset of the parameters }
  262. paramoffset:=8;
  263. { calculate frame pointer offset }
  264. if lexlevel>normal_function_level then
  265. begin
  266. procinfo^.framepointer_offset:=paramoffset;
  267. inc(paramoffset,target_os.size_of_pointer);
  268. { this is needed to get correct framepointer push for local
  269. forward functions !! }
  270. pd^.parast^.symtablelevel:=lexlevel;
  271. end;
  272. if assigned (procinfo^._Class) and
  273. not(procinfo^._Class^.is_class) and
  274. (pd^.proctypeoption in [potype_constructor,potype_destructor]) then
  275. inc(paramoffset,target_os.size_of_pointer);
  276. { self pointer offset }
  277. { self isn't pushed in nested procedure of methods }
  278. if assigned(procinfo^._class) and (lexlevel=normal_function_level) then
  279. begin
  280. procinfo^.selfpointer_offset:=paramoffset;
  281. if assigned(aktprocsym^.definition) and
  282. not(po_containsself in aktprocsym^.definition^.procoptions) then
  283. inc(paramoffset,target_os.size_of_pointer);
  284. end;
  285. { con/-destructor flag ? }
  286. if assigned (procinfo^._Class) and
  287. procinfo^._class^.is_class and
  288. (pd^.proctypeoption in [potype_destructor,potype_constructor]) then
  289. inc(paramoffset,target_os.size_of_pointer);
  290. procinfo^.para_offset:=paramoffset;
  291. pd^.parast^.datasize:=0;
  292. pd^.nextoverloaded:=aktprocsym^.definition;
  293. aktprocsym^.definition:=pd;
  294. { this is probably obsolete now PM }
  295. aktprocsym^.definition^.fileinfo:=procstartfilepos;
  296. aktprocsym^.definition^.setmangledname(hs);
  297. aktprocsym^.definition^.procsym:=aktprocsym;
  298. if not parse_only then
  299. begin
  300. overloaded_level:=0;
  301. { we need another procprefix !!! }
  302. { count, but only those in the same unit !!}
  303. while assigned(pd) and
  304. (pd^.owner^.symtabletype in [globalsymtable,staticsymtable]) do
  305. begin
  306. { only count already implemented functions }
  307. if not(pd^.forwarddef) then
  308. inc(overloaded_level);
  309. pd:=pd^.nextoverloaded;
  310. end;
  311. if overloaded_level>0 then
  312. procprefix:=hs+'$'+tostr(overloaded_level)+'$'
  313. else
  314. procprefix:=hs+'$';
  315. end;
  316. { this must also be inserted in the right symtable !! PM }
  317. { otherwise we get subbtle problems with
  318. definitions of args defs in staticsymtable for
  319. implementation of a global method }
  320. if token=_LKLAMMER then
  321. parameter_dec(aktprocsym^.definition);
  322. { so we only restore the symtable now }
  323. symtablestack:=st;
  324. if (options=potype_operator) then
  325. overloaded_operators[optoken]:=aktprocsym;
  326. end;
  327. procedure parse_proc_dec;
  328. var
  329. hs : string;
  330. isclassmethod : boolean;
  331. begin
  332. inc(lexlevel);
  333. { read class method }
  334. if token=_CLASS then
  335. begin
  336. consume(_CLASS);
  337. isclassmethod:=true;
  338. end
  339. else
  340. isclassmethod:=false;
  341. case token of
  342. _FUNCTION : begin
  343. consume(_FUNCTION);
  344. parse_proc_head(potype_none);
  345. if token<>_COLON then
  346. begin
  347. if not(aktprocsym^.definition^.forwarddef) or
  348. (m_repeat_forward in aktmodeswitches) then
  349. begin
  350. consume(_COLON);
  351. consume_all_until(_SEMICOLON);
  352. end;
  353. end
  354. else
  355. begin
  356. consume(_COLON);
  357. inc(testcurobject);
  358. single_type(aktprocsym^.definition^.rettype,hs,false);
  359. aktprocsym^.definition^.test_if_fpu_result;
  360. dec(testcurobject);
  361. end;
  362. end;
  363. _PROCEDURE : begin
  364. consume(_PROCEDURE);
  365. parse_proc_head(potype_none);
  366. aktprocsym^.definition^.rettype.def:=voiddef;
  367. end;
  368. _CONSTRUCTOR : begin
  369. consume(_CONSTRUCTOR);
  370. parse_proc_head(potype_constructor);
  371. if assigned(procinfo^._class) and
  372. procinfo^._class^.is_class then
  373. begin
  374. { CLASS constructors return the created instance }
  375. aktprocsym^.definition^.rettype.def:=procinfo^._class;
  376. end
  377. else
  378. begin
  379. { OBJECT constructors return a boolean }
  380. {$IfDef GDB}
  381. { GDB doesn't like unnamed types !}
  382. aktprocsym^.definition^.rettype.def:=globaldef('boolean');
  383. {$else GDB}
  384. aktprocsym^.definition^.rettype.def:=new(porddef,init(bool8bit,0,1));
  385. {$Endif GDB}
  386. end;
  387. end;
  388. _DESTRUCTOR : begin
  389. consume(_DESTRUCTOR);
  390. parse_proc_head(potype_destructor);
  391. aktprocsym^.definition^.rettype.def:=voiddef;
  392. end;
  393. _OPERATOR : begin
  394. if lexlevel>normal_function_level then
  395. Message(parser_e_no_local_operator);
  396. consume(_OPERATOR);
  397. if not(token in [_PLUS..last_overloaded]) then
  398. Message(parser_e_overload_operator_failed);
  399. optoken:=token;
  400. consume(Token);
  401. procinfo^.flags:=procinfo^.flags or pi_operator;
  402. parse_proc_head(potype_operator);
  403. if token<>_ID then
  404. begin
  405. opsym:=nil;
  406. if not(m_result in aktmodeswitches) then
  407. consume(_ID);
  408. end
  409. else
  410. begin
  411. opsym:=new(pvarsym,initdef(pattern,voiddef));
  412. consume(_ID);
  413. end;
  414. if not try_to_consume(_COLON) then
  415. begin
  416. consume(_COLON);
  417. aktprocsym^.definition^.rettype.def:=generrordef;
  418. consume_all_until(_SEMICOLON);
  419. end
  420. else
  421. begin
  422. single_type(aktprocsym^.definition^.rettype,hs,false);
  423. aktprocsym^.definition^.test_if_fpu_result;
  424. if (optoken in [_EQUAL,_GT,_LT,_GTE,_LTE]) and
  425. ((aktprocsym^.definition^.rettype.def^.deftype<>
  426. orddef) or (porddef(aktprocsym^.definition^.
  427. rettype.def)^.typ<>bool8bit)) then
  428. Message(parser_e_comparative_operator_return_boolean);
  429. if assigned(opsym) then
  430. opsym^.vartype.def:=aktprocsym^.definition^.rettype.def;
  431. { We need to add the return type in the mangledname
  432. to allow overloading with just different results !! (PM) }
  433. aktprocsym^.definition^.setmangledname(
  434. aktprocsym^.definition^.mangledname+'$$'+hs);
  435. if (optoken=_ASSIGNMENT) and
  436. is_equal(aktprocsym^.definition^.rettype.def,
  437. pvarsym(aktprocsym^.definition^.parast^.symindex^.first)^.vartype.def) then
  438. message(parser_e_no_such_assignment);
  439. end;
  440. end;
  441. end;
  442. if isclassmethod and
  443. assigned(aktprocsym) then
  444. {$ifdef INCLUDEOK}
  445. include(aktprocsym^.definition^.procoptions,po_classmethod);
  446. {$else}
  447. aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_classmethod];
  448. {$endif}
  449. consume(_SEMICOLON);
  450. dec(lexlevel);
  451. end;
  452. {****************************************************************************
  453. Procedure directive handlers
  454. ****************************************************************************}
  455. {$ifdef tp}
  456. {$F+}
  457. {$endif}
  458. procedure pd_far(const procnames:Tstringcontainer);
  459. begin
  460. Message(parser_w_proc_far_ignored);
  461. end;
  462. procedure pd_near(const procnames:Tstringcontainer);
  463. begin
  464. Message(parser_w_proc_near_ignored);
  465. end;
  466. procedure pd_export(const procnames:Tstringcontainer);
  467. begin
  468. if assigned(procinfo^._class) then
  469. Message(parser_e_methods_dont_be_export);
  470. if lexlevel<>normal_function_level then
  471. Message(parser_e_dont_nest_export);
  472. { only os/2 needs this }
  473. if target_info.target=target_i386_os2 then
  474. begin
  475. procnames.insert(realname);
  476. procinfo^.exported:=true;
  477. if cs_link_deffile in aktglobalswitches then
  478. deffile.AddExport(aktprocsym^.definition^.mangledname);
  479. end;
  480. end;
  481. procedure pd_inline(const procnames:Tstringcontainer);
  482. begin
  483. if not(cs_support_inline in aktmoduleswitches) then
  484. Message(parser_e_proc_inline_not_supported);
  485. end;
  486. procedure pd_forward(const procnames:Tstringcontainer);
  487. begin
  488. aktprocsym^.definition^.forwarddef:=true;
  489. end;
  490. procedure pd_stdcall(const procnames:Tstringcontainer);
  491. begin
  492. end;
  493. procedure pd_safecall(const procnames:Tstringcontainer);
  494. begin
  495. end;
  496. procedure pd_alias(const procnames:Tstringcontainer);
  497. begin
  498. consume(_COLON);
  499. procnames.insert(get_stringconst);
  500. end;
  501. procedure pd_asmname(const procnames:Tstringcontainer);
  502. begin
  503. aktprocsym^.definition^.setmangledname(target_os.Cprefix+pattern);
  504. if token=_CCHAR then
  505. consume(_CCHAR)
  506. else
  507. consume(_CSTRING);
  508. { we don't need anything else }
  509. aktprocsym^.definition^.forwarddef:=false;
  510. end;
  511. procedure pd_intern(const procnames:Tstringcontainer);
  512. begin
  513. consume(_COLON);
  514. aktprocsym^.definition^.extnumber:=get_intconst;
  515. end;
  516. procedure pd_system(const procnames:Tstringcontainer);
  517. begin
  518. aktprocsym^.definition^.setmangledname(realname);
  519. end;
  520. procedure pd_abstract(const procnames:Tstringcontainer);
  521. begin
  522. if (po_virtualmethod in aktprocsym^.definition^.procoptions) then
  523. {$ifdef INCLUDEOK}
  524. include(aktprocsym^.definition^.procoptions,po_abstractmethod)
  525. {$else}
  526. aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_abstractmethod]
  527. {$endif}
  528. else
  529. Message(parser_e_only_virtual_methods_abstract);
  530. { the method is defined }
  531. aktprocsym^.definition^.forwarddef:=false;
  532. end;
  533. procedure pd_virtual(const procnames:Tstringcontainer);
  534. {$ifdef WITHDMT}
  535. var
  536. pt : ptree;
  537. {$endif WITHDMT}
  538. begin
  539. if (aktprocsym^.definition^.proctypeoption=potype_constructor) and
  540. not(aktprocsym^.definition^._class^.is_class) then
  541. Message(parser_e_constructor_cannot_be_not_virtual);
  542. {$ifdef WITHDMT}
  543. if not(aktprocsym^.definition^._class^.is_class) and
  544. (token<>_SEMICOLON) then
  545. begin
  546. { any type of parameter is allowed here! }
  547. pt:=comp_expr(true);
  548. do_firstpass(pt);
  549. if is_constintnode(pt) then
  550. begin
  551. include(aktprocsym^.definition^.procoptions,po_msgint);
  552. aktprocsym^.definition^.messageinf.i:=pt^.value;
  553. end
  554. else
  555. Message(parser_e_ill_msg_expr);
  556. disposetree(pt);
  557. end;
  558. {$endif WITHDMT}
  559. end;
  560. procedure pd_static(const procnames:Tstringcontainer);
  561. begin
  562. if (cs_static_keyword in aktmoduleswitches) then
  563. begin
  564. {$ifdef INCLUDEOK}
  565. include(aktprocsym^.symoptions,sp_static);
  566. include(aktprocsym^.definition^.procoptions,po_staticmethod);
  567. {$else}
  568. aktprocsym^.symoptions:=aktprocsym^.symoptions+[sp_static];
  569. aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_staticmethod];
  570. {$endif}
  571. end;
  572. end;
  573. procedure pd_override(const procnames:Tstringcontainer);
  574. begin
  575. if not(aktprocsym^.definition^._class^.is_class) then
  576. Message(parser_e_no_object_override);
  577. end;
  578. procedure pd_message(const procnames:Tstringcontainer);
  579. var
  580. pt : ptree;
  581. begin
  582. { check parameter type }
  583. if not(po_containsself in aktprocsym^.definition^.procoptions) and
  584. ((aktprocsym^.definition^.para^.count<>1) or
  585. (pparaitem(aktprocsym^.definition^.para^.first)^.paratyp<>vs_var)) then
  586. Message(parser_e_ill_msg_param);
  587. pt:=comp_expr(true);
  588. do_firstpass(pt);
  589. if pt^.treetype=stringconstn then
  590. begin
  591. {$ifdef INCLUDEOK}
  592. include(aktprocsym^.definition^.procoptions,po_msgstr);
  593. {$else}
  594. aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_msgstr];
  595. {$endif}
  596. aktprocsym^.definition^.messageinf.str:=strnew(pt^.value_str);
  597. end
  598. else
  599. if is_constintnode(pt) then
  600. begin
  601. {$ifdef INCLUDEOK}
  602. include(aktprocsym^.definition^.procoptions,po_msgint);
  603. {$else}
  604. aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_msgint];
  605. {$endif}
  606. aktprocsym^.definition^.messageinf.i:=pt^.value;
  607. end
  608. else
  609. Message(parser_e_ill_msg_expr);
  610. disposetree(pt);
  611. end;
  612. procedure pd_cdecl(const procnames:Tstringcontainer);
  613. begin
  614. if aktprocsym^.definition^.deftype<>procvardef then
  615. aktprocsym^.definition^.setmangledname(target_os.Cprefix+realname);
  616. end;
  617. procedure pd_pascal(const procnames:Tstringcontainer);
  618. var st,parast : psymtable;
  619. lastps,ps : psym;
  620. begin
  621. new(st,init(parasymtable));
  622. parast:=aktprocsym^.definition^.parast;
  623. lastps:=nil;
  624. while assigned(parast^.symindex^.first) and (lastps<>psym(parast^.symindex^.first)) do
  625. begin
  626. ps:=psym(parast^.symindex^.first);
  627. while assigned(ps^.next) and (psym(ps^.next)<>lastps) do
  628. ps:=psym(ps^.next);
  629. ps^.owner:=st;
  630. { recalculate the corrected offset }
  631. { the really_insert_in_data procedure
  632. for parasymtable should only calculateoffset PM }
  633. ps^.insert_in_data;
  634. { reset the owner correctly }
  635. ps^.owner:=parast;
  636. lastps:=ps;
  637. end;
  638. end;
  639. procedure pd_register(const procnames:Tstringcontainer);
  640. begin
  641. Message(parser_w_proc_register_ignored);
  642. end;
  643. procedure pd_syscall(const procnames:Tstringcontainer);
  644. begin
  645. aktprocsym^.definition^.forwarddef:=false;
  646. aktprocsym^.definition^.extnumber:=get_intconst;
  647. end;
  648. procedure pd_external(const procnames:Tstringcontainer);
  649. {
  650. If import_dll=nil the procedure is assumed to be in another
  651. object file. In that object file it should have the name to
  652. which import_name is pointing to. Otherwise, the procedure is
  653. assumed to be in the DLL to which import_dll is pointing to. In
  654. that case either import_nr<>0 or import_name<>nil is true, so
  655. the procedure is either imported by number or by name. (DM)
  656. }
  657. var
  658. import_dll,
  659. import_name : string;
  660. import_nr : word;
  661. begin
  662. aktprocsym^.definition^.forwarddef:=false;
  663. { If the procedure should be imported from a DLL, a constant string follows.
  664. This isn't really correct, an contant string expression follows
  665. so we check if an semicolon follows, else a string constant have to
  666. follow (FK) }
  667. import_nr:=0;
  668. import_name:='';
  669. if not(token=_SEMICOLON) and not(idtoken=_NAME) then
  670. begin
  671. import_dll:=get_stringconst;
  672. if (idtoken=_NAME) then
  673. begin
  674. consume(_NAME);
  675. import_name:=get_stringconst;
  676. end;
  677. if (idtoken=_INDEX) then
  678. begin
  679. {After the word index follows the index number in the DLL.}
  680. consume(_INDEX);
  681. import_nr:=get_intconst;
  682. end;
  683. if (import_nr=0) and (import_name='') then
  684. {if (aktprocsym^.definition^.options and pocdecl)<>0 then
  685. import_name:=aktprocsym^.definition^.mangledname
  686. else
  687. Message(parser_w_empty_import_name);}
  688. { this should work both for win32 and Linux !! PM }
  689. import_name:=realname;
  690. if not(current_module^.uses_imports) then
  691. begin
  692. current_module^.uses_imports:=true;
  693. importlib^.preparelib(current_module^.modulename^);
  694. end;
  695. if not(m_repeat_forward in aktmodeswitches) then
  696. begin
  697. { we can only have one overloaded here ! }
  698. if assigned(aktprocsym^.definition^.nextoverloaded) then
  699. importlib^.importprocedure(aktprocsym^.definition^.nextoverloaded^.mangledname,
  700. import_dll,import_nr,import_name)
  701. else
  702. importlib^.importprocedure(aktprocsym^.mangledname,import_dll,import_nr,import_name);
  703. end
  704. else
  705. importlib^.importprocedure(aktprocsym^.mangledname,import_dll,import_nr,import_name);
  706. end
  707. else
  708. begin
  709. if (idtoken=_NAME) then
  710. begin
  711. consume(_NAME);
  712. import_name:=get_stringconst;
  713. aktprocsym^.definition^.setmangledname(import_name);
  714. end
  715. else
  716. begin
  717. { external shouldn't override the cdecl/system name }
  718. if not (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
  719. aktprocsym^.definition^.setmangledname(aktprocsym^.name);
  720. end;
  721. end;
  722. end;
  723. {$ifdef TP}
  724. {$F-}
  725. {$endif}
  726. {const
  727. namelength=15;}
  728. type
  729. pd_handler=procedure(const procnames:Tstringcontainer);
  730. proc_dir_rec=record
  731. idtok : ttoken;
  732. pd_flags : longint;
  733. handler : pd_handler;
  734. pocall : tproccalloptions;
  735. pooption : tprocoptions;
  736. mutexclpocall : tproccalloptions;
  737. mutexclpotype : tproctypeoptions;
  738. mutexclpo : tprocoptions;
  739. end;
  740. const
  741. {Should contain the number of procedure directives we support.}
  742. num_proc_directives=29;
  743. proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
  744. (
  745. (
  746. idtok:_ABSTRACT;
  747. pd_flags : pd_interface+pd_object;
  748. handler : {$ifndef TP}@{$endif}pd_abstract;
  749. pocall : [];
  750. pooption : [po_abstractmethod];
  751. mutexclpocall : [pocall_internproc,pocall_inline];
  752. mutexclpotype : [potype_constructor,potype_destructor];
  753. mutexclpo : [po_exports,po_interrupt,po_external]
  754. ),(
  755. idtok:_ALIAS;
  756. pd_flags : pd_implemen+pd_body;
  757. handler : {$ifndef TP}@{$endif}pd_alias;
  758. pocall : [];
  759. pooption : [];
  760. mutexclpocall : [pocall_inline];
  761. mutexclpotype : [];
  762. mutexclpo : [po_external]
  763. ),(
  764. idtok:_ASMNAME;
  765. pd_flags : pd_interface+pd_implemen;
  766. handler : {$ifndef TP}@{$endif}pd_asmname;
  767. pocall : [pocall_cdecl,pocall_clearstack];
  768. pooption : [po_external];
  769. mutexclpocall : [pocall_internproc];
  770. mutexclpotype : [];
  771. mutexclpo : [po_external]
  772. ),(
  773. idtok:_ASSEMBLER;
  774. pd_flags : pd_implemen+pd_body;
  775. handler : nil;
  776. pocall : [];
  777. pooption : [po_assembler];
  778. mutexclpocall : [];
  779. mutexclpotype : [];
  780. mutexclpo : [po_external]
  781. ),(
  782. idtok:_CDECL;
  783. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  784. handler : {$ifndef TP}@{$endif}pd_cdecl;
  785. pocall : [pocall_cdecl,pocall_clearstack];
  786. pooption : [po_savestdregs];
  787. mutexclpocall : [pocall_internproc,pocall_leftright,pocall_inline];
  788. mutexclpotype : [];
  789. mutexclpo : [po_assembler,po_external]
  790. ),(
  791. idtok:_DYNAMIC;
  792. pd_flags : pd_interface+pd_object;
  793. handler : {$ifndef TP}@{$endif}pd_virtual;
  794. pocall : [];
  795. pooption : [po_virtualmethod];
  796. mutexclpocall : [pocall_internproc,pocall_inline];
  797. mutexclpotype : [];
  798. mutexclpo : [po_exports,po_interrupt,po_external]
  799. ),(
  800. idtok:_EXPORT;
  801. pd_flags : pd_body+pd_global+pd_interface+pd_implemen{??};
  802. handler : {$ifndef TP}@{$endif}pd_export;
  803. pocall : [];
  804. pooption : [po_exports];
  805. mutexclpocall : [pocall_internproc,pocall_inline];
  806. mutexclpotype : [];
  807. mutexclpo : [po_external,po_interrupt]
  808. ),(
  809. idtok:_EXTERNAL;
  810. pd_flags : pd_implemen+pd_interface;
  811. handler : {$ifndef TP}@{$endif}pd_external;
  812. pocall : [];
  813. pooption : [po_external];
  814. mutexclpocall : [pocall_internproc,pocall_inline,pocall_palmossyscall];
  815. mutexclpotype : [];
  816. mutexclpo : [po_exports,po_interrupt,po_assembler]
  817. ),(
  818. idtok:_FAR;
  819. pd_flags : pd_implemen+pd_body+pd_interface+pd_procvar;
  820. handler : {$ifndef TP}@{$endif}pd_far;
  821. pocall : [];
  822. pooption : [];
  823. mutexclpocall : [pocall_internproc,pocall_inline];
  824. mutexclpotype : [];
  825. mutexclpo : []
  826. ),(
  827. idtok:_FORWARD;
  828. pd_flags : pd_implemen;
  829. handler : {$ifndef TP}@{$endif}pd_forward;
  830. pocall : [];
  831. pooption : [];
  832. mutexclpocall : [pocall_internproc,pocall_inline];
  833. mutexclpotype : [];
  834. mutexclpo : [po_external]
  835. ),(
  836. idtok:_INLINE;
  837. pd_flags : pd_implemen+pd_body;
  838. handler : {$ifndef TP}@{$endif}pd_inline;
  839. pocall : [pocall_inline];
  840. pooption : [];
  841. mutexclpocall : [pocall_internproc];
  842. mutexclpotype : [potype_constructor,potype_destructor];
  843. mutexclpo : [po_exports,po_external,po_interrupt]
  844. ),(
  845. idtok:_INTERNCONST;
  846. pd_flags : pd_implemen+pd_body;
  847. handler : {$ifndef TP}@{$endif}pd_intern;
  848. pocall : [pocall_internconst];
  849. pooption : [];
  850. mutexclpocall : [];
  851. mutexclpotype : [potype_operator];
  852. mutexclpo : []
  853. ),(
  854. idtok:_INTERNPROC;
  855. pd_flags : pd_implemen;
  856. handler : {$ifndef TP}@{$endif}pd_intern;
  857. pocall : [pocall_internproc];
  858. pooption : [];
  859. mutexclpocall : [pocall_inline,pocall_clearstack,pocall_leftright,pocall_cdecl];
  860. mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
  861. mutexclpo : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck]
  862. ),(
  863. idtok:_INTERRUPT;
  864. pd_flags : pd_implemen+pd_body;
  865. handler : nil;
  866. pocall : [];
  867. pooption : [po_interrupt];
  868. mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_clearstack,pocall_leftright,pocall_inline];
  869. mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
  870. mutexclpo : [po_external]
  871. ),(
  872. idtok:_IOCHECK;
  873. pd_flags : pd_implemen+pd_body;
  874. handler : nil;
  875. pocall : [];
  876. pooption : [po_iocheck];
  877. mutexclpocall : [pocall_internproc];
  878. mutexclpotype : [];
  879. mutexclpo : [po_external]
  880. ),(
  881. idtok:_MESSAGE;
  882. pd_flags : pd_interface+pd_object;
  883. handler : {$ifndef TP}@{$endif}pd_message;
  884. pocall : [];
  885. pooption : []; { can be po_msgstr or po_msgint }
  886. mutexclpocall : [pocall_inline,pocall_internproc];
  887. mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
  888. mutexclpo : [po_interrupt,po_external]
  889. ),(
  890. idtok:_NEAR;
  891. pd_flags : pd_implemen+pd_body+pd_procvar;
  892. handler : {$ifndef TP}@{$endif}pd_near;
  893. pocall : [];
  894. pooption : [];
  895. mutexclpocall : [pocall_internproc];
  896. mutexclpotype : [];
  897. mutexclpo : []
  898. ),(
  899. idtok:_OVERRIDE;
  900. pd_flags : pd_interface+pd_object;
  901. handler : {$ifndef TP}@{$endif}pd_override;
  902. pocall : [];
  903. pooption : [po_overridingmethod,po_virtualmethod];
  904. mutexclpocall : [pocall_inline,pocall_internproc];
  905. mutexclpotype : [];
  906. mutexclpo : [po_exports,po_external,po_interrupt]
  907. ),(
  908. idtok:_PASCAL;
  909. pd_flags : pd_implemen+pd_body+pd_procvar;
  910. handler : {$ifndef TP}@{$endif}pd_pascal;
  911. pocall : [pocall_leftright];
  912. pooption : [];
  913. mutexclpocall : [pocall_internproc];
  914. mutexclpotype : [];
  915. mutexclpo : [po_external]
  916. ),(
  917. idtok:_POPSTACK;
  918. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  919. handler : nil;
  920. pocall : [pocall_clearstack];
  921. pooption : [];
  922. mutexclpocall : [pocall_inline,pocall_internproc];
  923. mutexclpotype : [];
  924. mutexclpo : [po_assembler,po_external]
  925. ),(
  926. idtok:_PUBLIC;
  927. pd_flags : pd_implemen+pd_body+pd_global+pd_notobject;
  928. handler : nil;
  929. pocall : [];
  930. pooption : [];
  931. mutexclpocall : [pocall_internproc,pocall_inline];
  932. mutexclpotype : [];
  933. mutexclpo : [po_external]
  934. ),(
  935. idtok:_REGISTER;
  936. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  937. handler : {$ifndef TP}@{$endif}pd_register;
  938. pocall : [pocall_register];
  939. pooption : [];
  940. mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_internproc];
  941. mutexclpotype : [];
  942. mutexclpo : [po_external]
  943. ),(
  944. idtok:_SAFECALL;
  945. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  946. handler : {$ifndef TP}@{$endif}pd_safecall;
  947. pocall : [pocall_safecall];
  948. pooption : [po_savestdregs];
  949. mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_internproc,pocall_inline];
  950. mutexclpotype : [];
  951. mutexclpo : [po_external]
  952. ),(
  953. idtok:_SAVEREGISTERS;
  954. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  955. handler : nil;
  956. pocall : [];
  957. pooption : [po_saveregisters];
  958. mutexclpocall : [pocall_internproc];
  959. mutexclpotype : [];
  960. mutexclpo : [po_external]
  961. ),(
  962. idtok:_STATIC;
  963. pd_flags : pd_interface+pd_object;
  964. handler : {$ifndef TP}@{$endif}pd_static;
  965. pocall : [];
  966. pooption : [po_staticmethod];
  967. mutexclpocall : [pocall_inline,pocall_internproc];
  968. mutexclpotype : [potype_constructor,potype_destructor];
  969. mutexclpo : [po_external,po_interrupt,po_exports]
  970. ),(
  971. idtok:_STDCALL;
  972. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  973. handler : {$ifndef TP}@{$endif}pd_stdcall;
  974. pocall : [pocall_stdcall];
  975. pooption : [po_savestdregs];
  976. mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_inline,pocall_internproc];
  977. mutexclpotype : [];
  978. mutexclpo : [po_external]
  979. ),(
  980. idtok:_SYSCALL;
  981. pd_flags : pd_interface;
  982. handler : {$ifndef TP}@{$endif}pd_syscall;
  983. pocall : [pocall_palmossyscall];
  984. pooption : [];
  985. mutexclpocall : [pocall_cdecl,pocall_inline,pocall_internproc];
  986. mutexclpotype : [];
  987. mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
  988. ),(
  989. idtok:_SYSTEM;
  990. pd_flags : pd_implemen;
  991. handler : {$ifndef TP}@{$endif}pd_system;
  992. pocall : [pocall_clearstack];
  993. pooption : [];
  994. mutexclpocall : [pocall_leftright,pocall_inline,pocall_internproc];
  995. mutexclpotype : [];
  996. mutexclpo : [po_external,po_assembler,po_interrupt]
  997. ),(
  998. idtok:_VIRTUAL;
  999. pd_flags : pd_interface+pd_object;
  1000. handler : {$ifndef TP}@{$endif}pd_virtual;
  1001. pocall : [];
  1002. pooption : [po_virtualmethod];
  1003. mutexclpocall : [pocall_inline,pocall_internproc];
  1004. mutexclpotype : [];
  1005. mutexclpo : [po_external,po_interrupt,po_exports]
  1006. )
  1007. );
  1008. function is_proc_directive(tok:ttoken):boolean;
  1009. var
  1010. i : longint;
  1011. begin
  1012. is_proc_directive:=false;
  1013. for i:=1 to num_proc_directives do
  1014. if proc_direcdata[i].idtok=idtoken then
  1015. begin
  1016. is_proc_directive:=true;
  1017. exit;
  1018. end;
  1019. end;
  1020. function parse_proc_direc(const proc_names:Tstringcontainer;var pdflags:word):boolean;
  1021. {
  1022. Parse the procedure directive, returns true if a correct directive is found
  1023. }
  1024. var
  1025. p : longint;
  1026. found : boolean;
  1027. name : string;
  1028. begin
  1029. parse_proc_direc:=false;
  1030. name:=pattern;
  1031. found:=false;
  1032. for p:=1 to num_proc_directives do
  1033. if proc_direcdata[p].idtok=idtoken then
  1034. begin
  1035. found:=true;
  1036. break;
  1037. end;
  1038. { Check if the procedure directive is known }
  1039. if not found then
  1040. begin
  1041. { parsing a procvar type the name can be any
  1042. next variable !! }
  1043. if (pdflags and (pd_procvar or pd_object))=0 then
  1044. Message1(parser_w_unknown_proc_directive_ignored,name);
  1045. exit;
  1046. end;
  1047. { static needs a special treatment }
  1048. if (idtoken=_STATIC) and not (cs_static_keyword in aktmoduleswitches) then
  1049. exit;
  1050. { Conflicts between directives ? }
  1051. if (aktprocsym^.definition^.proctypeoption in proc_direcdata[p].mutexclpotype) or
  1052. ((aktprocsym^.definition^.proccalloptions*proc_direcdata[p].mutexclpocall)<>[]) or
  1053. ((aktprocsym^.definition^.procoptions*proc_direcdata[p].mutexclpo)<>[]) then
  1054. begin
  1055. Message1(parser_e_proc_dir_conflict,name);
  1056. exit;
  1057. end;
  1058. { Check if the directive is only for objects }
  1059. if ((proc_direcdata[p].pd_flags and pd_object)<>0) and
  1060. not assigned(aktprocsym^.definition^._class) then
  1061. begin
  1062. exit;
  1063. end;
  1064. { check if method and directive not for object public }
  1065. if ((proc_direcdata[p].pd_flags and pd_notobject)<>0) and
  1066. assigned(aktprocsym^.definition^._class) then
  1067. begin
  1068. exit;
  1069. end;
  1070. { consume directive, and turn flag on }
  1071. consume(token);
  1072. parse_proc_direc:=true;
  1073. { Check the pd_flags if the directive should be allowed }
  1074. if ((pdflags and pd_interface)<>0) and
  1075. ((proc_direcdata[p].pd_flags and pd_interface)=0) then
  1076. begin
  1077. Message1(parser_e_proc_dir_not_allowed_in_interface,name);
  1078. exit;
  1079. end;
  1080. if ((pdflags and pd_implemen)<>0) and
  1081. ((proc_direcdata[p].pd_flags and pd_implemen)=0) then
  1082. begin
  1083. Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
  1084. exit;
  1085. end;
  1086. if ((pdflags and pd_procvar)<>0) and
  1087. ((proc_direcdata[p].pd_flags and pd_procvar)=0) then
  1088. begin
  1089. Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
  1090. exit;
  1091. end;
  1092. { Return the new pd_flags }
  1093. if (proc_direcdata[p].pd_flags and pd_body)=0 then
  1094. pdflags:=pdflags and (not pd_body);
  1095. if (proc_direcdata[p].pd_flags and pd_global)<>0 then
  1096. pdflags:=pdflags or pd_global;
  1097. { Add the correct flag }
  1098. aktprocsym^.definition^.proccalloptions:=aktprocsym^.definition^.proccalloptions+proc_direcdata[p].pocall;
  1099. aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+proc_direcdata[p].pooption;
  1100. { Adjust positions of args for cdecl or stdcall }
  1101. if (aktprocsym^.definition^.deftype=procdef) and
  1102. (([pocall_cdecl,pocall_stdcall]*aktprocsym^.definition^.proccalloptions)<>[]) then
  1103. aktprocsym^.definition^.parast^.set_alignment(target_os.size_of_longint);
  1104. { Call the handler }
  1105. if pointer({$ifndef FPC}@{$endif}proc_direcdata[p].handler)<>nil then
  1106. proc_direcdata[p].handler(proc_names);
  1107. end;
  1108. {***************************************************************************}
  1109. function check_identical(var p : pprocdef) : boolean;
  1110. {
  1111. Search for idendical definitions,
  1112. if there is a forward, then kill this.
  1113. Returns the result of the forward check.
  1114. Removed from unter_dec to keep the source readable
  1115. }
  1116. var
  1117. hd,pd : Pprocdef;
  1118. storeparast : psymtable;
  1119. ad,fd : psym;
  1120. s : string;
  1121. begin
  1122. check_identical:=false;
  1123. p:=nil;
  1124. pd:=aktprocsym^.definition;
  1125. if assigned(pd) then
  1126. begin
  1127. { Is there an overload/forward ? }
  1128. if assigned(pd^.nextoverloaded) then
  1129. begin
  1130. { walk the procdef list }
  1131. while (assigned(pd)) and (assigned(pd^.nextoverloaded)) do
  1132. begin
  1133. if not(m_repeat_forward in aktmodeswitches) or
  1134. (equal_paras(aktprocsym^.definition^.para,pd^.nextoverloaded^.para,false) and
  1135. { for operators equal_paras is not enough !! }
  1136. ((aktprocsym^.definition^.proctypeoption<>potype_operator) or (optoken<>_ASSIGNMENT) or
  1137. is_equal(pd^.nextoverloaded^.rettype.def,aktprocsym^.definition^.rettype.def))) then
  1138. begin
  1139. if pd^.nextoverloaded^.forwarddef then
  1140. { remove the forward definition but don't delete it, }
  1141. { the symtable is the owner !! }
  1142. begin
  1143. hd:=pd^.nextoverloaded;
  1144. { Check if the procedure type and return type are correct }
  1145. if (hd^.proctypeoption<>aktprocsym^.definition^.proctypeoption) or
  1146. (not(is_equal(hd^.rettype.def,aktprocsym^.definition^.rettype.def)) and
  1147. (m_repeat_forward in aktmodeswitches)) then
  1148. begin
  1149. Message1(parser_e_header_dont_match_forward,aktprocsym^.demangledName);
  1150. exit;
  1151. end;
  1152. { Check calling convention, no check for internconst,internproc which
  1153. are only defined in interface or implementation }
  1154. if (hd^.proccalloptions-[pocall_internconst,pocall_internproc]<>
  1155. aktprocsym^.definition^.proccalloptions-[pocall_internconst,pocall_internproc]) then
  1156. begin
  1157. { only trigger an error, becuase it doesn't hurt }
  1158. Message(parser_e_call_convention_dont_match_forward);
  1159. { set the mangledname to the interface name so it doesn't trigger
  1160. the Note about different manglednames (PFV) }
  1161. aktprocsym^.definition^.setmangledname(hd^.mangledname);
  1162. end;
  1163. { manglednames are equal? }
  1164. hd^.count:=false;
  1165. if (m_repeat_forward in aktmodeswitches) or
  1166. aktprocsym^.definition^.haspara then
  1167. begin
  1168. if (hd^.mangledname<>aktprocsym^.definition^.mangledname) then
  1169. begin
  1170. { When overloading is not possible then we issue an error }
  1171. { This is not true, tp7/delphi don't give an error when a renamed
  1172. type is used in the other declaration (PFV)
  1173. if not(m_repeat_forward in aktmodeswitches) then
  1174. begin
  1175. Message1(parser_e_header_dont_match_forward,aktprocsym^.demangledName);
  1176. exit;
  1177. end; }
  1178. if not(po_external in aktprocsym^.definition^.procoptions) then
  1179. Message2(parser_n_interface_name_diff_implementation_name,hd^.mangledname,
  1180. aktprocsym^.definition^.mangledname);
  1181. { reset the mangledname of the interface part to be sure }
  1182. { this is wrong because the mangled name might have been used already !! }
  1183. if hd^.is_used then
  1184. renameasmsymbol(hd^.mangledname,aktprocsym^.definition^.mangledname);
  1185. hd^.setmangledname(aktprocsym^.definition^.mangledname);
  1186. { so we need to keep the name of interface !!
  1187. No!!!! The procedure directives can change the mangledname.
  1188. I fixed this by first calling check_identical and then doing
  1189. the proc directives, but this is not a good solution.(DM)}
  1190. { this is also wrong (PM)
  1191. aktprocsym^.definition^.setmangledname(hd^.mangledname);}
  1192. end
  1193. else
  1194. begin
  1195. { If mangled names are equal, therefore }
  1196. { they have the same number of parameters }
  1197. { Therefore we can check the name of these }
  1198. { parameters... }
  1199. if hd^.forwarddef and aktprocsym^.definition^.forwarddef then
  1200. begin
  1201. Message1(parser_e_function_already_declared_public_forward,aktprocsym^.demangledName);
  1202. Check_identical:=true;
  1203. { Remove other forward from the list to reduce errors }
  1204. pd^.nextoverloaded:=pd^.nextoverloaded^.nextoverloaded;
  1205. exit;
  1206. end;
  1207. ad:=psym(hd^.parast^.symindex^.first);
  1208. fd:=psym(aktprocsym^.definition^.parast^.symindex^.first);
  1209. if assigned(ad) and assigned(fd) then
  1210. begin
  1211. while assigned(ad) and assigned(fd) do
  1212. begin
  1213. s:=ad^.name;
  1214. if s<>fd^.name then
  1215. begin
  1216. Message3(parser_e_header_different_var_names,
  1217. aktprocsym^.name,s,fd^.name);
  1218. break;
  1219. end;
  1220. { it is impossible to have a nil pointer }
  1221. { for only one parameter - since they }
  1222. { have the same number of parameters. }
  1223. { Left = next parameter. }
  1224. ad:=psym(ad^.left);
  1225. fd:=psym(fd^.left);
  1226. end;
  1227. end;
  1228. end;
  1229. end;
  1230. { also the para_offset }
  1231. hd^.parast^.address_fixup:=aktprocsym^.definition^.parast^.address_fixup;
  1232. hd^.count:=true;
  1233. { remove pd^.nextoverloaded from the list }
  1234. { and add aktprocsym^.definition }
  1235. pd^.nextoverloaded:=pd^.nextoverloaded^.nextoverloaded;
  1236. hd^.nextoverloaded:=aktprocsym^.definition^.nextoverloaded;
  1237. { Alert! All fields of aktprocsym^.definition that are modified
  1238. by the procdir handlers must be copied here!.}
  1239. hd^.forwarddef:=false;
  1240. hd^.proccalloptions:=hd^.proccalloptions + aktprocsym^.definition^.proccalloptions;
  1241. hd^.procoptions:=hd^.procoptions + aktprocsym^.definition^.procoptions;
  1242. if aktprocsym^.definition^.extnumber=-1 then
  1243. aktprocsym^.definition^.extnumber:=hd^.extnumber
  1244. else
  1245. if hd^.extnumber=-1 then
  1246. hd^.extnumber:=aktprocsym^.definition^.extnumber;
  1247. { switch parast for warning in implementation PM }
  1248. if (m_repeat_forward in aktmodeswitches) or
  1249. aktprocsym^.definition^.haspara then
  1250. begin
  1251. storeparast:=hd^.parast;
  1252. hd^.parast:=aktprocsym^.definition^.parast;
  1253. aktprocsym^.definition^.parast:=storeparast;
  1254. end;
  1255. if pd=aktprocsym^.definition then
  1256. p:=nil
  1257. else
  1258. p:=pd;
  1259. aktprocsym^.definition:=hd;
  1260. check_identical:=true;
  1261. end
  1262. else
  1263. { abstract methods aren't forward defined, but this }
  1264. { needs another error message }
  1265. if not(po_abstractmethod in pd^.nextoverloaded^.procoptions) then
  1266. Message(parser_e_overloaded_have_same_parameters)
  1267. else
  1268. Message(parser_e_abstract_no_definition);
  1269. break;
  1270. end;
  1271. pd:=pd^.nextoverloaded;
  1272. end;
  1273. end
  1274. else
  1275. begin
  1276. { there is no overloaded, so its always identical with itself }
  1277. check_identical:=true;
  1278. end;
  1279. end;
  1280. { insert opsym only in the right symtable }
  1281. if ((procinfo^.flags and pi_operator)<>0) and assigned(opsym)
  1282. and not parse_only then
  1283. begin
  1284. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  1285. begin
  1286. pprocdef(aktprocsym^.definition)^.parast^.insert(opsym);
  1287. { this increases the data size }
  1288. { correct this to get the right ret $value }
  1289. dec(pprocdef(aktprocsym^.definition)^.parast^.datasize,opsym^.getpushsize);
  1290. { this allows to read the funcretoffset }
  1291. opsym^.address:=-4;
  1292. opsym^.varspez:=vs_var;
  1293. end
  1294. else
  1295. pprocdef(aktprocsym^.definition)^.localst^.insert(opsym);
  1296. end;
  1297. end;
  1298. procedure compile_proc_body(const proc_names:Tstringcontainer;
  1299. make_global,parent_has_class:boolean);
  1300. {
  1301. Compile the body of a procedure
  1302. }
  1303. var
  1304. oldexitlabel,oldexit2label : pasmlabel;
  1305. oldfaillabel,oldquickexitlabel:Pasmlabel;
  1306. _class,hp:Pobjectdef;
  1307. { switches can change inside the procedure }
  1308. entryswitches, exitswitches : tlocalswitches;
  1309. oldaktmaxfpuregisters,localmaxfpuregisters : longint;
  1310. { code for the subroutine as tree }
  1311. {$ifdef newcg}
  1312. code:ptree;
  1313. {$else newcg}
  1314. code:ptree;
  1315. {$endif newcg}
  1316. { size of the local strackframe }
  1317. stackframe:longint;
  1318. { true when no stackframe is required }
  1319. nostackframe:boolean;
  1320. { number of bytes which have to be cleared by RET }
  1321. parasize:longint;
  1322. { filepositions }
  1323. entrypos,
  1324. savepos,
  1325. exitpos : tfileposinfo;
  1326. begin
  1327. { calculate the lexical level }
  1328. inc(lexlevel);
  1329. if lexlevel>32 then
  1330. Message(parser_e_too_much_lexlevel);
  1331. { static is also important for local procedures !! }
  1332. if (po_staticmethod in aktprocsym^.definition^.procoptions) then
  1333. allow_only_static:=true
  1334. else if (lexlevel=normal_function_level) then
  1335. allow_only_static:=false;
  1336. { save old labels }
  1337. oldexitlabel:=aktexitlabel;
  1338. oldexit2label:=aktexit2label;
  1339. oldquickexitlabel:=quickexitlabel;
  1340. oldfaillabel:=faillabel;
  1341. { get new labels }
  1342. getlabel(aktexitlabel);
  1343. getlabel(aktexit2label);
  1344. { exit for fail in constructors }
  1345. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  1346. begin
  1347. getlabel(faillabel);
  1348. getlabel(quickexitlabel);
  1349. end;
  1350. { reset break and continue labels }
  1351. block_type:=bt_general;
  1352. aktbreaklabel:=nil;
  1353. aktcontinuelabel:=nil;
  1354. { insert symtables for the class, by only if it is no nested function }
  1355. if assigned(procinfo^._class) and not(parent_has_class) then
  1356. begin
  1357. { insert them in the reverse order ! }
  1358. hp:=nil;
  1359. repeat
  1360. _class:=procinfo^._class;
  1361. while _class^.childof<>hp do
  1362. _class:=_class^.childof;
  1363. hp:=_class;
  1364. _class^.symtable^.next:=symtablestack;
  1365. symtablestack:=_class^.symtable;
  1366. until hp=procinfo^._class;
  1367. end;
  1368. { insert parasymtable in symtablestack}
  1369. { only if lexlevel > 1 !!! global symtable should be right after staticsymtazble
  1370. for checking of same names used in interface and implementation !! }
  1371. if lexlevel>=normal_function_level then
  1372. begin
  1373. aktprocsym^.definition^.parast^.next:=symtablestack;
  1374. symtablestack:=aktprocsym^.definition^.parast;
  1375. symtablestack^.symtablelevel:=lexlevel;
  1376. end;
  1377. { insert localsymtable in symtablestack}
  1378. aktprocsym^.definition^.localst^.next:=symtablestack;
  1379. symtablestack:=aktprocsym^.definition^.localst;
  1380. symtablestack^.symtablelevel:=lexlevel;
  1381. { constant symbols are inserted in this symboltable }
  1382. constsymtable:=symtablestack;
  1383. { reset the temporary memory }
  1384. cleartempgen;
  1385. {$ifdef newcg}
  1386. tg.usedinproc:=[];
  1387. {$else newcg}
  1388. { no registers are used }
  1389. usedinproc:=0;
  1390. {$endif newcg}
  1391. { save entry info }
  1392. entrypos:=aktfilepos;
  1393. entryswitches:=aktlocalswitches;
  1394. localmaxfpuregisters:=aktmaxfpuregisters;
  1395. {$ifdef newcg}
  1396. {$ifdef dummy}
  1397. { parse the code ... }
  1398. if (po_assembler in aktprocsym^.definition^.procoptions) then
  1399. code:=convtree2node(assembler_block)
  1400. else
  1401. code:=convtree2node(block(current_module^.islibrary));
  1402. {$endif dummy}
  1403. { parse the code ... }
  1404. if (po_assembler in aktprocsym^.definition^.procoptions) then
  1405. code:=assembler_block
  1406. else
  1407. code:=block(current_module^.islibrary);
  1408. {$else newcg}
  1409. { parse the code ... }
  1410. if (po_assembler in aktprocsym^.definition^.procoptions) then
  1411. code:=assembler_block
  1412. else
  1413. code:=block(current_module^.islibrary);
  1414. {$endif newcg}
  1415. { get a better entry point }
  1416. if assigned(code) then
  1417. entrypos:=code^.fileinfo;
  1418. { save exit info }
  1419. exitswitches:=aktlocalswitches;
  1420. exitpos:=last_endtoken_filepos;
  1421. { save current filepos }
  1422. savepos:=aktfilepos;
  1423. {When we are called to compile the body of a unit, aktprocsym should
  1424. point to the unit initialization. If the unit has no initialization,
  1425. aktprocsym=nil. But in that case code=nil. hus we should check for
  1426. code=nil, when we use aktprocsym.}
  1427. { set the framepointer to esp for assembler functions }
  1428. { but only if the are no local variables }
  1429. { already done in assembler_block }
  1430. {$ifdef newcg}
  1431. tg.setfirsttemp(procinfo^.firsttemp_offset);
  1432. {$else newcg}
  1433. setfirsttemp(procinfo^.firsttemp_offset);
  1434. {$endif newcg}
  1435. { ... and generate assembler }
  1436. { but set the right switches for entry !! }
  1437. aktlocalswitches:=entryswitches;
  1438. oldaktmaxfpuregisters:=aktmaxfpuregisters;
  1439. aktmaxfpuregisters:=localmaxfpuregisters;
  1440. {$ifndef NOPASS2}
  1441. {$ifdef newcg}
  1442. if assigned(code) then
  1443. generatecode(code);
  1444. {$else newcg}
  1445. if assigned(code) then
  1446. generatecode(code);
  1447. {$endif newcg}
  1448. { set switches to status at end of procedure }
  1449. aktlocalswitches:=exitswitches;
  1450. if assigned(code) then
  1451. begin
  1452. aktprocsym^.definition^.code:=code;
  1453. { the procedure is now defined }
  1454. aktprocsym^.definition^.forwarddef:=false;
  1455. {$ifdef newcg}
  1456. aktprocsym^.definition^.usedregisters:=tg.usedinproc;
  1457. {$else newcg}
  1458. aktprocsym^.definition^.usedregisters:=usedinproc;
  1459. {$endif newcg}
  1460. end;
  1461. {$ifdef newcg}
  1462. stackframe:=tg.gettempsize;
  1463. {$else newcg}
  1464. stackframe:=gettempsize;
  1465. {$endif newcg}
  1466. { first generate entry code with the correct position and switches }
  1467. aktfilepos:=entrypos;
  1468. aktlocalswitches:=entryswitches;
  1469. {$ifdef newcg}
  1470. if assigned(code) then
  1471. cg^.g_entrycode(procinfo^.aktentrycode,proc_names,make_global,stackframe,parasize,nostackframe,false);
  1472. {$else newcg}
  1473. if assigned(code) then
  1474. genentrycode(procinfo^.aktentrycode,proc_names,make_global,stackframe,parasize,nostackframe,false);
  1475. {$endif newcg}
  1476. { now generate exit code with the correct position and switches }
  1477. aktfilepos:=exitpos;
  1478. aktlocalswitches:=exitswitches;
  1479. if assigned(code) then
  1480. begin
  1481. {$ifdef newcg}
  1482. cg^.g_exitcode(procinfo^.aktexitcode,parasize,nostackframe,false);
  1483. {$else newcg}
  1484. genexitcode(procinfo^.aktexitcode,parasize,nostackframe,false);
  1485. {$endif newcg}
  1486. procinfo^.aktproccode^.insertlist(procinfo^.aktentrycode);
  1487. procinfo^.aktproccode^.concatlist(procinfo^.aktexitcode);
  1488. {$ifdef i386}
  1489. {$ifndef NoOpt}
  1490. if (cs_optimize in aktglobalswitches) and
  1491. { do not optimize pure assembler procedures }
  1492. ((procinfo^.flags and pi_is_assembler)=0) then
  1493. Optimize(procinfo^.aktproccode);
  1494. {$endif NoOpt}
  1495. {$endif}
  1496. { save local data (casetable) also in the same file }
  1497. if assigned(procinfo^.aktlocaldata) and
  1498. (not procinfo^.aktlocaldata^.empty) then
  1499. begin
  1500. procinfo^.aktproccode^.concat(new(pai_section,init(sec_data)));
  1501. procinfo^.aktproccode^.concatlist(procinfo^.aktlocaldata);
  1502. procinfo^.aktproccode^.concat(new(pai_section,init(sec_code)));
  1503. end;
  1504. { now we can insert a cut }
  1505. if (cs_create_smart in aktmoduleswitches) then
  1506. codesegment^.concat(new(pai_cut,init));
  1507. { add the procedure to the codesegment }
  1508. codesegment^.concatlist(procinfo^.aktproccode);
  1509. end;
  1510. {$else}
  1511. if assigned(code) then
  1512. firstpass(code);
  1513. {$endif NOPASS2}
  1514. { ... remove symbol tables, for the browser leave the static table }
  1515. { if (cs_browser in aktmoduleswitches) and (symtablestack^.symtabletype=staticsymtable) then
  1516. symtablestack^.next:=symtablestack^.next^.next
  1517. else }
  1518. if lexlevel>=normal_function_level then
  1519. symtablestack:=symtablestack^.next^.next
  1520. else
  1521. symtablestack:=symtablestack^.next;
  1522. { ... check for unused symbols }
  1523. { but only if there is no asm block }
  1524. if assigned(code) then
  1525. begin
  1526. if (Errorcount=0) then
  1527. begin
  1528. aktprocsym^.definition^.localst^.check_forwards;
  1529. aktprocsym^.definition^.localst^.checklabels;
  1530. end;
  1531. if (procinfo^.flags and pi_uses_asm)=0 then
  1532. begin
  1533. { not for unit init, becuase the var can be used in finalize,
  1534. it will be done in proc_unit }
  1535. if not(aktprocsym^.definition^.proctypeoption
  1536. in [potype_proginit,potype_unitinit,potype_unitfinalize]) then
  1537. aktprocsym^.definition^.localst^.allsymbolsused;
  1538. aktprocsym^.definition^.parast^.allsymbolsused;
  1539. end;
  1540. end;
  1541. { the local symtables can be deleted, but the parast }
  1542. { doesn't, (checking definitons when calling a }
  1543. { function }
  1544. { not for a inline procedure !! (PM) }
  1545. { at lexlevel = 1 localst is the staticsymtable itself }
  1546. { so no dispose here !! }
  1547. if assigned(code) and
  1548. not(cs_browser in aktmoduleswitches) and
  1549. not(pocall_inline in aktprocsym^.definition^.proccalloptions) then
  1550. begin
  1551. if lexlevel>=normal_function_level then
  1552. dispose(aktprocsym^.definition^.localst,done);
  1553. aktprocsym^.definition^.localst:=nil;
  1554. end;
  1555. {$ifdef newcg}
  1556. { all registers can be used again }
  1557. tg.resetusableregisters;
  1558. { only now we can remove the temps }
  1559. tg.resettempgen;
  1560. {$else newcg}
  1561. { all registers can be used again }
  1562. resetusableregisters;
  1563. { only now we can remove the temps }
  1564. resettempgen;
  1565. {$endif newcg}
  1566. { remove code tree, if not inline procedure }
  1567. if assigned(code) and not(pocall_inline in aktprocsym^.definition^.proccalloptions) then
  1568. {$ifdef newcg}
  1569. {!!!!!!! dispose(code,done); }
  1570. disposetree(code);
  1571. {$else newcg}
  1572. disposetree(code);
  1573. {$endif newcg}
  1574. { remove class member symbol tables }
  1575. while symtablestack^.symtabletype=objectsymtable do
  1576. symtablestack:=symtablestack^.next;
  1577. aktmaxfpuregisters:=oldaktmaxfpuregisters;
  1578. { restore filepos, the switches are already set }
  1579. aktfilepos:=savepos;
  1580. { restore labels }
  1581. aktexitlabel:=oldexitlabel;
  1582. aktexit2label:=oldexit2label;
  1583. quickexitlabel:=oldquickexitlabel;
  1584. faillabel:=oldfaillabel;
  1585. { reset to normal non static function }
  1586. if (lexlevel=normal_function_level) then
  1587. allow_only_static:=false;
  1588. { previous lexlevel }
  1589. dec(lexlevel);
  1590. end;
  1591. procedure parse_proc_directives(Anames:Pstringcontainer;var pdflags:word);
  1592. {
  1593. Parse the procedure directives. It does not matter if procedure directives
  1594. are written using ;procdir; or ['procdir'] syntax.
  1595. }
  1596. var
  1597. res : boolean;
  1598. begin
  1599. while token in [_ID,_LECKKLAMMER] do
  1600. begin
  1601. if try_to_consume(_LECKKLAMMER) then
  1602. begin
  1603. repeat
  1604. parse_proc_direc(Anames^,pdflags);
  1605. until not try_to_consume(_COMMA);
  1606. consume(_RECKKLAMMER);
  1607. { we always expect at least '[];' }
  1608. res:=true;
  1609. end
  1610. else
  1611. res:=parse_proc_direc(Anames^,pdflags);
  1612. { A procedure directive normally followed by a semicolon, but in
  1613. a const section we should stop when _EQUAL is found }
  1614. if res then
  1615. begin
  1616. if (block_type=bt_const) and
  1617. (token=_EQUAL) then
  1618. break;
  1619. consume(_SEMICOLON);
  1620. end
  1621. else
  1622. break;
  1623. end;
  1624. end;
  1625. procedure parse_var_proc_directives(var sym : psym);
  1626. var
  1627. anames : pstringcontainer;
  1628. pdflags : word;
  1629. oldsym : pprocsym;
  1630. pd : pabstractprocdef;
  1631. begin
  1632. oldsym:=aktprocsym;
  1633. anames:=new(pstringcontainer,init);
  1634. pdflags:=pd_procvar;
  1635. { we create a temporary aktprocsym to read the directives }
  1636. aktprocsym:=new(pprocsym,init(sym^.name));
  1637. case sym^.typ of
  1638. varsym :
  1639. pd:=pabstractprocdef(pvarsym(sym)^.vartype.def);
  1640. typedconstsym :
  1641. pd:=pabstractprocdef(ptypedconstsym(sym)^.typedconsttype.def);
  1642. typesym :
  1643. pd:=pabstractprocdef(ptypesym(sym)^.restype.def);
  1644. else
  1645. internalerror(994932432);
  1646. end;
  1647. if pd^.deftype<>procvardef then
  1648. internalerror(994932433);
  1649. pabstractprocdef(aktprocsym^.definition):=pd;
  1650. { names should never be used anyway }
  1651. inc(lexlevel);
  1652. parse_proc_directives(anames,pdflags);
  1653. dec(lexlevel);
  1654. aktprocsym^.definition:=nil;
  1655. dispose(aktprocsym,done);
  1656. dispose(anames,done);
  1657. aktprocsym:=oldsym;
  1658. end;
  1659. procedure parse_object_proc_directives(var sym : pprocsym);
  1660. var
  1661. anames : pstringcontainer;
  1662. pdflags : word;
  1663. begin
  1664. pdflags:=pd_object;
  1665. anames:=new(pstringcontainer,init);
  1666. inc(lexlevel);
  1667. parse_proc_directives(anames,pdflags);
  1668. dec(lexlevel);
  1669. dispose(anames,done);
  1670. if (po_containsself in aktprocsym^.definition^.procoptions) and
  1671. (([po_msgstr,po_msgint]*aktprocsym^.definition^.procoptions)=[]) then
  1672. Message(parser_e_self_in_non_message_handler);
  1673. end;
  1674. procedure checkvaluepara(p:pnamedindexobject);{$ifndef FPC}far;{$endif}
  1675. var
  1676. vs : pvarsym;
  1677. s : string;
  1678. begin
  1679. with pvarsym(p)^ do
  1680. begin
  1681. if copy(name,1,3)='val' then
  1682. begin
  1683. s:=Copy(name,4,255);
  1684. if not(po_assembler in aktprocsym^.definition^.procoptions) then
  1685. begin
  1686. vs:=new(Pvarsym,initdef(s,vartype.def));
  1687. vs^.fileinfo:=fileinfo;
  1688. vs^.varspez:=varspez;
  1689. aktprocsym^.definition^.localst^.insert(vs);
  1690. {$ifdef INCLUDEOK}
  1691. include(vs^.varoptions,vo_is_local_copy);
  1692. {$else}
  1693. vs^.varoptions:=vs^.varoptions+[vo_is_local_copy];
  1694. {$endif}
  1695. vs^.varstate:=vs_assigned;
  1696. localvarsym:=vs;
  1697. inc(refs); { the para was used to set the local copy ! }
  1698. { warnings only on local copy ! }
  1699. varstate:=vs_used;
  1700. end
  1701. else
  1702. begin
  1703. aktprocsym^.definition^.parast^.rename(name,s);
  1704. end;
  1705. end;
  1706. end;
  1707. end;
  1708. procedure read_proc;
  1709. {
  1710. Parses the procedure directives, then parses the procedure body, then
  1711. generates the code for it
  1712. }
  1713. var
  1714. oldprefix : string;
  1715. oldprocsym : Pprocsym;
  1716. oldprocinfo : pprocinfo;
  1717. oldconstsymtable : Psymtable;
  1718. oldfilepos : tfileposinfo;
  1719. names : Pstringcontainer;
  1720. pdflags : word;
  1721. prevdef,stdef : pprocdef;
  1722. begin
  1723. { save old state }
  1724. oldprocsym:=aktprocsym;
  1725. oldprefix:=procprefix;
  1726. oldconstsymtable:=constsymtable;
  1727. oldprocinfo:=procinfo;
  1728. { create a new procedure }
  1729. new(names,init);
  1730. {$ifdef fixLeaksOnError}
  1731. strContStack.push(names);
  1732. {$endif fixLeaksOnError}
  1733. codegen_newprocedure;
  1734. with procinfo^ do
  1735. begin
  1736. parent:=oldprocinfo;
  1737. { clear flags }
  1738. flags:=0;
  1739. { standard frame pointer }
  1740. framepointer:=frame_pointer;
  1741. { funcret_is_valid:=false; }
  1742. funcret_state:=vs_declared;
  1743. { is this a nested function of a method ? }
  1744. if assigned(oldprocinfo) then
  1745. _class:=oldprocinfo^._class;
  1746. end;
  1747. parse_proc_dec;
  1748. procinfo^.sym:=aktprocsym;
  1749. procinfo^.def:=aktprocsym^.definition;
  1750. { set the default function options }
  1751. if parse_only then
  1752. begin
  1753. aktprocsym^.definition^.forwarddef:=true;
  1754. { set also the interface flag, for better error message when the
  1755. implementation doesn't much this header }
  1756. aktprocsym^.definition^.interfacedef:=true;
  1757. pdflags:=pd_interface;
  1758. end
  1759. else
  1760. begin
  1761. pdflags:=pd_body;
  1762. if current_module^.in_implementation then
  1763. pdflags:=pdflags or pd_implemen;
  1764. if (not current_module^.is_unit) or (cs_create_smart in aktmoduleswitches) then
  1765. pdflags:=pdflags or pd_global;
  1766. procinfo^.exported:=false;
  1767. aktprocsym^.definition^.forwarddef:=false;
  1768. end;
  1769. { parse the directives that may follow }
  1770. inc(lexlevel);
  1771. parse_proc_directives(names,pdflags);
  1772. dec(lexlevel);
  1773. { set aktfilepos to the beginning of the function declaration }
  1774. oldfilepos:=aktfilepos;
  1775. aktfilepos:=aktprocsym^.definition^.fileinfo;
  1776. { search for forward declarations }
  1777. if not check_identical(prevdef) then
  1778. begin
  1779. { A method must be forward defined (in the object declaration) }
  1780. if assigned(procinfo^._class) and (not assigned(oldprocinfo^._class)) then
  1781. Message(parser_e_header_dont_match_any_member);
  1782. { Give a better error if there is a forward def in the interface and only
  1783. a single implementation }
  1784. if (not aktprocsym^.definition^.forwarddef) and
  1785. assigned(aktprocsym^.definition^.nextoverloaded) and
  1786. aktprocsym^.definition^.nextoverloaded^.forwarddef and
  1787. aktprocsym^.definition^.nextoverloaded^.interfacedef and
  1788. not(assigned(aktprocsym^.definition^.nextoverloaded^.nextoverloaded)) then
  1789. Message1(parser_e_header_dont_match_forward,aktprocsym^.demangledName)
  1790. else
  1791. begin
  1792. { check the global flag }
  1793. if (procinfo^.flags and pi_is_global)<>0 then
  1794. Message(parser_e_overloaded_must_be_all_global);
  1795. end
  1796. end;
  1797. { set return type here, becuase the aktprocsym^.definition can be
  1798. changed by check_identical (PFV) }
  1799. procinfo^.returntype.def:=aktprocsym^.definition^.rettype.def;
  1800. { pointer to the return value ? }
  1801. if ret_in_param(procinfo^.returntype.def) then
  1802. begin
  1803. procinfo^.return_offset:=procinfo^.para_offset;
  1804. inc(procinfo^.para_offset,target_os.size_of_pointer);
  1805. end;
  1806. { allows to access the parameters of main functions in nested functions }
  1807. aktprocsym^.definition^.parast^.address_fixup:=procinfo^.para_offset;
  1808. { when it is a value para and it needs a local copy then rename
  1809. the parameter and insert a copy in the localst. This is not done
  1810. for assembler procedures }
  1811. if (not parse_only) and (not aktprocsym^.definition^.forwarddef) then
  1812. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}checkvaluepara);
  1813. { restore file pos }
  1814. aktfilepos:=oldfilepos;
  1815. { compile procedure when a body is needed }
  1816. if (pdflags and pd_body)<>0 then
  1817. begin
  1818. Message1(parser_p_procedure_start,aktprocsym^.demangledname);
  1819. names^.insert(aktprocsym^.definition^.mangledname);
  1820. { set _FAIL as keyword if constructor }
  1821. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  1822. tokeninfo^[_FAIL].keyword:=m_all;
  1823. if assigned(aktprocsym^.definition^._class) then
  1824. tokeninfo^[_SELF].keyword:=m_all;
  1825. compile_proc_body(names^,((pdflags and pd_global)<>0),assigned(oldprocinfo^._class));
  1826. { reset _FAIL as normal }
  1827. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  1828. tokeninfo^[_FAIL].keyword:=m_none;
  1829. if assigned(aktprocsym^.definition^._class) and (lexlevel=main_program_level) then
  1830. tokeninfo^[_SELF].keyword:=m_none;
  1831. consume(_SEMICOLON);
  1832. end;
  1833. { close }
  1834. {$ifdef fixLeaksOnError}
  1835. if names <> strContStack.pop then
  1836. writeln('problem with strContStack in psub!');
  1837. {$endif fixLeaksOnError}
  1838. dispose(names,done);
  1839. codegen_doneprocedure;
  1840. { Restore old state }
  1841. constsymtable:=oldconstsymtable;
  1842. { from now on all refernece to mangledname means
  1843. that the function is already used }
  1844. aktprocsym^.definition^.count:=true;
  1845. { restore the interface order to maintain CRC values PM }
  1846. if assigned(prevdef) and assigned(aktprocsym^.definition^.nextoverloaded) then
  1847. begin
  1848. stdef:=aktprocsym^.definition;
  1849. aktprocsym^.definition:=stdef^.nextoverloaded;
  1850. stdef^.nextoverloaded:=prevdef^.nextoverloaded;
  1851. prevdef^.nextoverloaded:=stdef;
  1852. end;
  1853. aktprocsym:=oldprocsym;
  1854. procprefix:=oldprefix;
  1855. procinfo:=oldprocinfo;
  1856. opsym:=nil;
  1857. end;
  1858. end.
  1859. {
  1860. $Log$
  1861. Revision 1.53 2000-03-16 16:41:13 pierre
  1862. * fix for bug 807
  1863. Revision 1.52 2000/03/15 23:10:00 pierre
  1864. * fix for bug 848 (that still genrated wrong code)
  1865. + better testing for variables used in assembler
  1866. (gives an error if variable is not directly reachable !)
  1867. Revision 1.51 2000/02/27 14:44:39 peter
  1868. * if calling convention doesn't match don't print note about
  1869. different manglednames
  1870. Revision 1.50 2000/02/20 20:49:45 florian
  1871. * newcg is compiling
  1872. * fixed the dup id problem reported by Paul Y.
  1873. Revision 1.49 2000/02/17 14:53:42 florian
  1874. * some updates for the newcg
  1875. Revision 1.48 2000/02/09 13:23:00 peter
  1876. * log truncated
  1877. Revision 1.47 2000/02/08 13:55:13 peter
  1878. * reset section back to code after localdata
  1879. Revision 1.46 2000/02/04 20:00:22 florian
  1880. * an exception in a construcor calls now the destructor (this applies only
  1881. to classes)
  1882. Revision 1.45 2000/02/04 14:54:17 jonas
  1883. * moved call to resetusableregs to compile_proc_body (put it right before the
  1884. reset of the temp generator) so the optimizer can know which registers are
  1885. regvars
  1886. Revision 1.44 2000/01/28 23:17:53 florian
  1887. * virtual XXXX; support for objects, only if -dWITHDMT is defined
  1888. Revision 1.43 2000/01/21 22:06:16 florian
  1889. * fixed for the fix of bug 793
  1890. * fpu variables modified by nested subroutines aren't regable anymore
  1891. * $maxfpuregisters doesn't modify anymore the behavior of a procedure before
  1892. Revision 1.42 2000/01/16 22:17:12 peter
  1893. * renamed call_offset to para_offset
  1894. Revision 1.41 2000/01/11 17:16:06 jonas
  1895. * removed a lot of memory leaks when an error is encountered (caused by
  1896. procinfo and pstringcontainers). There are still plenty left though :)
  1897. Revision 1.40 2000/01/07 01:14:31 peter
  1898. * updated copyright to 2000
  1899. Revision 1.39 1999/12/22 01:01:52 peter
  1900. - removed freelabel()
  1901. * added undefined label detection in internal assembler, this prevents
  1902. a lot of ld crashes and wrong .o files
  1903. * .o files aren't written anymore if errors have occured
  1904. * inlining of assembler labels is now correct
  1905. Revision 1.38 1999/12/06 18:17:09 peter
  1906. * newcg compiler compiles again
  1907. Revision 1.37 1999/11/30 10:40:48 peter
  1908. + ttype, tsymlist
  1909. Revision 1.36 1999/11/22 00:23:09 pierre
  1910. * also complain about unused functions in program
  1911. Revision 1.35 1999/11/17 17:05:02 pierre
  1912. * Notes/hints changes
  1913. Revision 1.34 1999/11/10 00:24:02 pierre
  1914. * more browser details
  1915. Revision 1.33 1999/11/09 23:43:08 pierre
  1916. * better browser info
  1917. Revision 1.32 1999/11/09 23:06:45 peter
  1918. * esi_offset -> selfpointer_offset to be newcg compatible
  1919. * hcogegen -> cgbase fixes for newcg
  1920. Revision 1.31 1999/11/06 14:34:23 peter
  1921. * truncated log to 20 revs
  1922. Revision 1.30 1999/10/26 12:30:44 peter
  1923. * const parameter is now checked
  1924. * better and generic check if a node can be used for assigning
  1925. * export fixes
  1926. * procvar equal works now (it never had worked at least from 0.99.8)
  1927. * defcoll changed to linkedlist with pparaitem so it can easily be
  1928. walked both directions
  1929. Revision 1.29 1999/10/22 10:39:35 peter
  1930. * split type reading from pdecl to ptype unit
  1931. * parameter_dec routine is now used for procedure and procvars
  1932. Revision 1.28 1999/10/13 10:37:36 peter
  1933. * moved mangledname creation of normal proc so it also handles a wrong
  1934. method proc
  1935. }