psub.pas 71 KB

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