psub.pas 71 KB

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