psub.pas 69 KB

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