psub.pas 71 KB

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