psub.pas 72 KB

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