switches.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman
  3. This unit implements the parsing of the switches like $I-
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit switches;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. systems,globtype;
  22. procedure HandleSwitch(switch,state:char);
  23. function CheckSwitch(switch,state:char):boolean;
  24. procedure recordpendingverbosityswitch(sw: char; state: char);
  25. procedure recordpendingmessagestate(msg: longint; state: tmsgstate);
  26. procedure recordpendinglocalswitch(sw: tlocalswitch; state: char);
  27. procedure recordpendinglocalfullswitch(const switches: tlocalswitches);
  28. procedure recordpendingverbosityfullswitch(verbosity: longint);
  29. procedure recordpendingcallingswitch(const str: shortstring);
  30. procedure recordpendingalignmentfullswitch(const alignment : talignmentinfo);
  31. procedure flushpendingswitchesstate;
  32. implementation
  33. uses
  34. cpuinfo,
  35. {$ifdef llvm}
  36. { override optimizer switches }
  37. llvminfo,
  38. {$endif llvm}
  39. globals,verbose,comphook,dirparse,
  40. fmodule;
  41. {****************************************************************************
  42. Main Switches Parsing
  43. ****************************************************************************}
  44. type
  45. TSwitchType=(ignoredsw,localsw,modulesw,globalsw,illegalsw,unsupportedsw,alignsw,optimizersw,packenumsw,pentiumfdivsw,targetsw);
  46. SwitchRec=record
  47. typesw : TSwitchType;
  48. setsw : byte;
  49. end;
  50. SwitchRecTable = array['A'..'Z'] of SwitchRec;
  51. const
  52. turboSwitchTable: SwitchRecTable =(
  53. {A} (typesw:alignsw; setsw:ord(cs_localnone)),
  54. {B} (typesw:localsw; setsw:ord(cs_full_boolean_eval)),
  55. {C} (typesw:localsw; setsw:ord(cs_do_assertion)),
  56. {D} (typesw:modulesw; setsw:ord(cs_debuginfo)),
  57. {E} (typesw:modulesw; setsw:ord(cs_fp_emulation)),
  58. {$ifdef i8086}
  59. {F} (typesw:localsw; setsw:ord(cs_force_far_calls)),
  60. {$else i8086}
  61. {F} (typesw:ignoredsw; setsw:ord(cs_localnone)),
  62. {$endif i8086}
  63. {G} (typesw:localsw; setsw:ord(cs_imported_data)),
  64. {H} (typesw:localsw; setsw:ord(cs_refcountedstrings)),
  65. {I} (typesw:localsw; setsw:ord(cs_check_io)),
  66. {J} (typesw:localsw; setsw:ord(cs_typed_const_writable)),
  67. {$ifdef i8086}
  68. {K} (typesw:modulesw; setsw:ord(cs_win16_smartcallbacks)),
  69. {$else i8086}
  70. {K} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  71. {$endif i8086}
  72. {L} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  73. {M} (typesw:localsw; setsw:ord(cs_generate_rtti)),
  74. {N} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  75. {O} (typesw:optimizersw; setsw:ord(cs_opt_none)),
  76. {P} (typesw:modulesw; setsw:ord(cs_openstring)),
  77. {Q} (typesw:localsw; setsw:ord(cs_check_overflow)),
  78. {R} (typesw:localsw; setsw:ord(cs_check_range)),
  79. {S} (typesw:localsw; setsw:ord(cs_check_stack)),
  80. {T} (typesw:localsw; setsw:ord(cs_typed_addresses)),
  81. {U} (typesw:pentiumfdivsw; setsw:ord(cs_localnone)),
  82. {V} (typesw:localsw; setsw:ord(cs_strict_var_strings)),
  83. {$ifdef i8086}
  84. {W} (typesw:targetsw; setsw:ord(ts_x86_far_procs_push_odd_bp)),
  85. {$else i8086}
  86. {W} (typesw:localsw; setsw:ord(cs_generate_stackframes)),
  87. {$endif i8086}
  88. {X} (typesw:modulesw; setsw:ord(cs_extsyntax)),
  89. {Y} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  90. {Z} (typesw:packenumsw; setsw:ord(cs_localnone))
  91. );
  92. macSwitchTable: SwitchRecTable =(
  93. {A} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  94. {B} (typesw:localsw; setsw:ord(cs_full_boolean_eval)),
  95. {C} (typesw:localsw; setsw:ord(cs_do_assertion)),
  96. {D} (typesw:modulesw; setsw:ord(cs_debuginfo)),
  97. {E} (typesw:modulesw; setsw:ord(cs_fp_emulation)),
  98. {$ifdef i8086}
  99. {F} (typesw:localsw; setsw:ord(cs_force_far_calls)),
  100. {$else i8086}
  101. {F} (typesw:ignoredsw; setsw:ord(cs_localnone)),
  102. {$endif i8086}
  103. {G} (typesw:ignoredsw; setsw:ord(cs_localnone)),
  104. {H} (typesw:localsw; setsw:ord(cs_refcountedstrings)),
  105. {I} (typesw:localsw; setsw:ord(cs_check_io)),
  106. {J} (typesw:localsw; setsw:ord(cs_external_var)),
  107. {$ifdef i8086}
  108. {K} (typesw:modulesw; setsw:ord(cs_win16_smartcallbacks)),
  109. {$else i8086}
  110. {K} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  111. {$endif i8086}
  112. {L} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  113. {M} (typesw:localsw; setsw:ord(cs_generate_rtti)),
  114. {N} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  115. {O} (typesw:optimizersw; setsw:ord(cs_opt_none)),
  116. {P} (typesw:modulesw; setsw:ord(cs_openstring)),
  117. {Q} (typesw:localsw; setsw:ord(cs_check_overflow)),
  118. {R} (typesw:localsw; setsw:ord(cs_check_range)),
  119. {S} (typesw:localsw; setsw:ord(cs_check_stack)),
  120. {T} (typesw:localsw; setsw:ord(cs_typed_addresses)),
  121. {U} (typesw:illegalsw; setsw:ord(cs_localnone)),
  122. {V} (typesw:localsw; setsw:ord(cs_strict_var_strings)),
  123. {$ifdef i8086}
  124. {W} (typesw:targetsw; setsw:ord(ts_x86_far_procs_push_odd_bp)),
  125. {$else i8086}
  126. {W} (typesw:localsw; setsw:ord(cs_generate_stackframes)),
  127. {$endif i8086}
  128. {X} (typesw:modulesw; setsw:ord(cs_extsyntax)),
  129. {Y} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
  130. {Z} (typesw:localsw; setsw:ord(cs_externally_visible))
  131. );
  132. procedure HandleSwitch(switch,state:char);
  133. var
  134. switchTablePtr: ^SwitchRecTable;
  135. begin
  136. switch:=upcase(switch);
  137. { Is the Switch in the letters ? }
  138. if not ((switch in ['A'..'Z']) and (state in ['-','+'])) then
  139. begin
  140. Message(scan_w_illegal_switch);
  141. exit;
  142. end;
  143. { Select switch table }
  144. if m_mac in current_settings.modeswitches then
  145. switchTablePtr:= @macSwitchTable
  146. else
  147. switchTablePtr:= @turboSwitchTable;
  148. { Handle the switch }
  149. with switchTablePtr^[switch] do
  150. begin
  151. case typesw of
  152. alignsw:
  153. if state='+' then
  154. current_settings.packrecords:=4
  155. else
  156. current_settings.packrecords:=1;
  157. optimizersw :
  158. begin
  159. if state='+' then
  160. current_settings.optimizerswitches:=level2optimizerswitches
  161. else
  162. current_settings.optimizerswitches:=[];
  163. end;
  164. ignoredsw :
  165. Message1(scan_n_ignored_switch,'$'+switch);
  166. illegalsw :
  167. Message1(scan_w_illegal_switch,'$'+switch);
  168. unsupportedsw :
  169. Message1(scan_w_unsupported_switch,'$'+switch);
  170. localsw :
  171. recordpendinglocalswitch(tlocalswitch(setsw),state);
  172. modulesw :
  173. begin
  174. if current_module.in_global then
  175. begin
  176. {$ifndef cpufpemu}
  177. if tmoduleswitch(setsw)=cs_fp_emulation then
  178. begin
  179. Message1(scan_w_unsupported_switch_by_target,'$'+switch);
  180. end
  181. else
  182. {$endif cpufpemu}
  183. begin
  184. if state='+' then
  185. include(current_settings.moduleswitches,tmoduleswitch(setsw))
  186. else
  187. begin
  188. { Turning off debuginfo when lineinfo is requested
  189. is not possible }
  190. if not((cs_use_lineinfo in current_settings.globalswitches) and
  191. (tmoduleswitch(setsw)=cs_debuginfo)) then
  192. exclude(current_settings.moduleswitches,tmoduleswitch(setsw));
  193. end;
  194. end;
  195. end
  196. else
  197. Message(scan_w_switch_is_global);
  198. end;
  199. globalsw :
  200. begin
  201. if current_module.in_global and (current_module=main_module) then
  202. begin
  203. if state='+' then
  204. include(current_settings.globalswitches,tglobalswitch(setsw))
  205. else
  206. exclude(current_settings.globalswitches,tglobalswitch(setsw));
  207. end
  208. else
  209. Message(scan_w_switch_is_global);
  210. end;
  211. packenumsw:
  212. begin
  213. if state='-' then
  214. current_settings.packenum:=1
  215. else
  216. current_settings.packenum:=4;
  217. end;
  218. pentiumfdivsw:
  219. begin
  220. { Switch u- means pentium-safe fdiv off -> fpc default. We don't }
  221. { support u+ }
  222. if state='+' then
  223. Message1(scan_w_unsupported_switch,'$'+switch);
  224. end;
  225. targetsw:
  226. UpdateTargetSwitchStr(TargetSwitchStr[ttargetswitch(setsw)].name+state,current_settings.targetswitches,current_module.in_global);
  227. end;
  228. end;
  229. end;
  230. function CheckSwitch(switch,state:char):boolean;
  231. var
  232. found : boolean;
  233. switchTablePtr: ^SwitchRecTable;
  234. begin
  235. switch:=upcase(switch);
  236. { Is the Switch in the letters ? }
  237. if not ((switch in ['A'..'Z']) and (state in ['-','+'])) then
  238. begin
  239. Message(scan_w_illegal_switch);
  240. CheckSwitch:=false;
  241. exit;
  242. end;
  243. { Select switch table }
  244. if m_mac in current_settings.modeswitches then
  245. switchTablePtr:= @macSwitchTable
  246. else
  247. switchTablePtr:= @turboSwitchTable;
  248. { Check the switch }
  249. with switchTablePtr^[switch] do
  250. begin
  251. case typesw of
  252. localsw : found:=(tlocalswitch(setsw) in current_settings.localswitches);
  253. modulesw : found:=(tmoduleswitch(setsw) in current_settings.moduleswitches);
  254. globalsw : found:=(tglobalswitch(setsw) in current_settings.globalswitches);
  255. packenumsw : found := (current_settings.packenum = 4);
  256. else
  257. found:=false;
  258. end;
  259. if state='-' then
  260. found:=not found;
  261. CheckSwitch:=found;
  262. end;
  263. end;
  264. procedure recordpendingverbosityswitch(sw: char; state: char);
  265. begin
  266. pendingstate.nextverbositystr:=pendingstate.nextverbositystr+sw+state;
  267. end;
  268. procedure recordpendingmessagestate(msg: longint; state: tmsgstate);
  269. var
  270. pstate : pmessagestaterecord;
  271. begin
  272. new(pstate);
  273. pstate^.next:=pendingstate.nextmessagerecord;
  274. pstate^.value:=msg;
  275. pstate^.state:=state;
  276. pendingstate.nextmessagerecord:=pstate;
  277. end;
  278. procedure recordpendinglocalswitch(sw: tlocalswitch; state: char);
  279. begin
  280. if not pendingstate.localswitcheschanged then
  281. pendingstate.nextlocalswitches:=current_settings.localswitches;
  282. if state='-' then
  283. exclude(pendingstate.nextlocalswitches,sw)
  284. else if state='+' then
  285. include(pendingstate.nextlocalswitches,sw)
  286. else { state = '*' }
  287. begin
  288. if sw in init_settings.localswitches then
  289. include(pendingstate.nextlocalswitches,sw)
  290. else
  291. exclude(pendingstate.nextlocalswitches,sw);
  292. end;
  293. pendingstate.localswitcheschanged:=true;
  294. end;
  295. procedure recordpendingalignmentfullswitch(const alignment : talignmentinfo);
  296. begin
  297. pendingstate.nextalignment:=alignment;
  298. pendingstate.alignmentchanged:=true;
  299. end;
  300. procedure recordpendinglocalfullswitch(const switches: tlocalswitches);
  301. begin
  302. pendingstate.nextlocalswitches:=switches;
  303. pendingstate.localswitcheschanged:=true;
  304. end;
  305. procedure recordpendingverbosityfullswitch(verbosity: longint);
  306. begin
  307. pendingstate.nextverbositystr:='';
  308. pendingstate.nextverbosityfullswitch:=verbosity;
  309. pendingstate.verbosityfullswitched:=true;
  310. end;
  311. procedure recordpendingcallingswitch(const str: shortstring);
  312. begin
  313. pendingstate.nextcallingstr:=str;
  314. end;
  315. procedure flushpendingswitchesstate;
  316. var
  317. tmpproccal: tproccalloption;
  318. fstate, pstate : pmessagestaterecord;
  319. begin
  320. { process pending localswitches (range checking, etc) }
  321. if pendingstate.localswitcheschanged then
  322. begin
  323. current_settings.localswitches:=pendingstate.nextlocalswitches;
  324. pendingstate.localswitcheschanged:=false;
  325. end;
  326. { process pending verbosity changes (warnings on, etc) }
  327. if pendingstate.verbosityfullswitched then
  328. begin
  329. status.verbosity:=pendingstate.nextverbosityfullswitch;
  330. pendingstate.verbosityfullswitched:=false;
  331. end;
  332. if pendingstate.alignmentchanged then
  333. begin
  334. current_settings.alignment:=pendingstate.nextalignment;
  335. pendingstate.alignmentchanged:=false;
  336. end;
  337. { process pending verbosity changes (warnings on, etc) }
  338. if pendingstate.nextverbositystr<>'' then
  339. begin
  340. setverbosity(pendingstate.nextverbositystr);
  341. pendingstate.nextverbositystr:='';
  342. end;
  343. fstate:=pendingstate.nextmessagerecord;
  344. pstate:=pendingstate.nextmessagerecord;
  345. while assigned(pstate) do
  346. begin
  347. pendingstate.nextmessagerecord:=pstate^.next;
  348. SetMessageVerbosity(pstate^.value,pstate^.state);
  349. if not assigned(pstate^.next) then
  350. begin
  351. pstate^.next:=current_settings.pmessage;
  352. current_settings.pmessage:=fstate;
  353. pstate:=nil;
  354. end
  355. else
  356. pstate:=pstate^.next;
  357. pendingstate.nextmessagerecord:=nil;
  358. end;
  359. { process pending calling convention changes (calling x) }
  360. if pendingstate.nextcallingstr<>'' then
  361. begin
  362. if not SetAktProcCall(pendingstate.nextcallingstr,tmpproccal) then
  363. Message1(parser_w_unknown_proc_directive_ignored,pendingstate.nextcallingstr)
  364. else if not(tmpproccal in supported_calling_conventions) then
  365. Message1(parser_e_illegal_calling_convention,pendingstate.nextcallingstr)
  366. else
  367. current_settings.defproccall:=tmpproccal;
  368. pendingstate.nextcallingstr:='';
  369. end;
  370. end;
  371. end.