fpswitch.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998-2000 by Berczi Gabor
  4. Compiler switches routines for the IDE
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit FPSwitch;
  12. interface
  13. uses
  14. Objects,
  15. Systems,
  16. WUtils,
  17. FPConst;
  18. const
  19. MinMemSize = 1024; { min. local heap and stack size }
  20. MaxMemSize = 67107840; { max. local heap and stack size }
  21. type
  22. TParamID =
  23. (idNone,idAlign,idRangeChecks,idStackChecks,idIOChecks,
  24. idOverflowChecks,idAsmDirect,idAsmATT,idAsmIntel,idAsmMot,
  25. idSymInfNone,idSymInfGlobalOnly,idSymInfGlobalLocal,
  26. idStackSize,idHeapSize,idStrictVarStrings,idExtendedSyntax,
  27. idMMXOps,idTypedAddress,idPackRecords,idPackEnum,idStackFrames,
  28. idReferenceInfo,idDebugInfo,idBoolEval,
  29. idLongString,idTypeInfo);
  30. TSwitchMode = (om_Normal,om_Debug,om_Release);
  31. TSwitchItemTyp = (ot_Select,ot_Boolean,ot_String,ot_Longint);
  32. PSwitchItem = ^TSwitchItem;
  33. TSwitchItem = object(TObject)
  34. Typ : TSwitchItemTyp;
  35. Name : string[50];
  36. Param : string[10];
  37. ParamID : TParamID;
  38. constructor Init(const n,p:string; AID: TParamID);
  39. function NeedParam:boolean;virtual;
  40. function ParamValue:string;virtual;
  41. function ParamValueBool(SM: TSwitchMode):boolean;virtual;
  42. function GetSwitchStr(SM: TSwitchMode): string; virtual;
  43. function GetNumberStr(SM: TSwitchMode): string; virtual;
  44. function GetOptionStr(SM: TSwitchMode): string; virtual;
  45. procedure Reset;virtual;
  46. end;
  47. PSelectItem = ^TSelectItem;
  48. TSelectItem = object(TSwitchItem)
  49. IsDefault : boolean;
  50. constructor Init(const n,p:string; AID: TParamID);
  51. { Select to avoid anything in config file }
  52. constructor InitDefault(const n:string);
  53. end;
  54. PBooleanItem = ^TBooleanItem;
  55. TBooleanItem = object(TSwitchItem)
  56. IsSet : array[TSwitchMode] of boolean;
  57. constructor Init(const n,p:string; AID: TParamID);
  58. function NeedParam:boolean;virtual;
  59. procedure Reset;virtual;
  60. function GetSwitchStr(SM: TSwitchMode): string; virtual;
  61. function ParamValueBool(SM: TSwitchMode):boolean;virtual;
  62. end;
  63. PStringItem = ^TStringItem;
  64. TStringItem = object(TSwitchItem)
  65. Str : array[TSwitchMode] of string;
  66. multiple : boolean;
  67. SeparateSpaces : boolean;
  68. constructor Init(const n,p:string;AID: TParamID; mult,allowspaces:boolean);
  69. function NeedParam:boolean;virtual;
  70. function ParamValue:string;virtual;
  71. procedure Reset;virtual;
  72. end;
  73. PLongintItem = ^TLongintItem;
  74. TLongintItem = object(TSwitchItem)
  75. Val : array[TSwitchMode] of longint;
  76. constructor Init(const n,p:string; AID: TParamID);
  77. function NeedParam:boolean;virtual;
  78. function ParamValue:string;virtual;
  79. function GetNumberStr(SM: TSwitchMode): string; virtual;
  80. procedure Reset;virtual;
  81. end;
  82. PSwitches = ^TSwitches;
  83. TSwitches = object
  84. constructor Init(ch:char);
  85. constructor InitSelect(ch:char);
  86. destructor Done;
  87. { general items }
  88. function ItemCount:integer;
  89. function ItemName(index:integer):string;
  90. function ItemParam(index:integer):string;
  91. { type specific }
  92. procedure AddSelectItem(const name,param:string; AID: TParamID);
  93. procedure AddDefaultSelect(const name:string);
  94. procedure AddBooleanItem(const name,param:string; AID: TParamID);
  95. procedure AddLongintItem(const name,param:string; AID: TParamID);
  96. procedure AddStringItem(const name,param:string;AID: TParamID;mult,allowspaces:boolean);
  97. function GetCurrSel:integer;
  98. function GetCurrSelParam : String;
  99. function GetBooleanItem(index:integer):boolean;
  100. function GetLongintItem(index:integer):longint;
  101. function GetStringItem(index:integer):string;
  102. procedure SetCurrSel(index:integer);
  103. function SetCurrSelParam(const s : String) : boolean;
  104. procedure SetBooleanItem(index:integer;b:boolean);
  105. procedure SetLongintItem(index:integer;l:longint);
  106. procedure SetStringItem(index:integer;const s:string);
  107. { read / write to cfgfile which must be open }
  108. procedure WriteItemsCfg;
  109. function ReadItemsCfg(const s:string):boolean;
  110. private
  111. IsSel : boolean;
  112. Prefix : char;
  113. SelNr : array[TSwitchMode] of integer;
  114. Items : PCollection;
  115. end;
  116. const
  117. SwitchesMode : TSwitchMode = om_Normal;
  118. SwitchesModeName : array[TSwitchMode] of string[10]=
  119. ('~N~ormal','~D~ebug','~R~elease');
  120. SwitchesModeStr : array[TSwitchMode] of string[8]=
  121. ('NORMAL','DEBUG','RELEASE');
  122. CustomArg : array[TSwitchMode] of string{$ifndef FPC}[128]{$endif}=
  123. ('','','');
  124. var
  125. LibLinkerSwitches,
  126. OtherLinkerSwitches,
  127. DebugInfoSwitches,
  128. LinkAfterSwitches,
  129. ProfileInfoSwitches,
  130. {MemorySizeSwitches, doubled !! }
  131. SyntaxSwitches,
  132. VerboseSwitches,
  133. CodegenSwitches,
  134. OptimizationSwitches,
  135. OptimizingGoalSwitches,
  136. ProcessorSwitches,
  137. AsmReaderSwitches,
  138. AsmInfoSwitches,
  139. AsmOutputSwitches,
  140. TargetSwitches,
  141. ConditionalSwitches,
  142. MemorySwitches,
  143. BrowserSwitches,
  144. DirectorySwitches : PSwitches;
  145. { write/read the Switches to fpc.cfg file }
  146. procedure WriteSwitches(const fn:string);
  147. procedure ReadSwitches(const fn:string);
  148. { initialize }
  149. procedure InitSwitches;
  150. procedure SetDefaultSwitches;
  151. procedure DoneSwitches;
  152. function GetSourceDirectories : string;
  153. procedure GetCompilerOptionLines(C: PUnsortedStringCollection);
  154. implementation
  155. uses
  156. Dos,
  157. GlobType,
  158. FPString,FPVars,FPUtils;
  159. var
  160. CfgFile : text;
  161. {*****************************************************************************
  162. TSwitchItem
  163. *****************************************************************************}
  164. constructor TSwitchItem.Init(const n,p:string; AID: TParamID);
  165. begin
  166. Inherited Init;
  167. Name:=n;
  168. Param:=p;
  169. ParamID:=AID;
  170. end;
  171. function TSwitchItem.NeedParam:boolean;
  172. begin
  173. NeedParam:=false;
  174. end;
  175. function TSwitchItem.ParamValue:string;
  176. begin
  177. ParamValue:='';
  178. end;
  179. function TSwitchItem.ParamValueBool(SM: TSwitchMode):boolean;
  180. begin
  181. Abstract;
  182. ParamValueBool:=false;
  183. end;
  184. function TSwitchItem.GetSwitchStr(SM: TSwitchMode): string;
  185. begin
  186. Abstract;
  187. GetSwitchStr:='';
  188. end;
  189. function TSwitchItem.GetNumberStr(SM: TSwitchMode): string;
  190. begin
  191. Abstract;
  192. GetNumberStr:='';
  193. end;
  194. function TSwitchItem.GetOptionStr(SM: TSwitchMode): string;
  195. begin
  196. Abstract;
  197. GetOptionStr:='';
  198. end;
  199. procedure TSwitchItem.Reset;
  200. begin
  201. end;
  202. {*****************************************************************************
  203. TSelectItem
  204. *****************************************************************************}
  205. constructor TSelectItem.Init(const n,p:string; AID: TParamID);
  206. begin
  207. Inherited Init(n,p,AID);
  208. Typ:=ot_Select;
  209. IsDefault:=false;
  210. end;
  211. constructor TSelectItem.InitDefault(const n:string);
  212. begin
  213. Inherited Init(n,'',idNone);
  214. Typ:=ot_Select;
  215. IsDefault:=true;
  216. end;
  217. {*****************************************************************************
  218. TBooleanItem
  219. *****************************************************************************}
  220. constructor TBooleanItem.Init(const n,p:string; AID: TParamID);
  221. begin
  222. Inherited Init(n,p,AID);
  223. Typ:=ot_Boolean;
  224. Reset;
  225. end;
  226. function TBooleanItem.NeedParam:boolean;
  227. begin
  228. NeedParam:=IsSet[SwitchesMode];
  229. end;
  230. procedure TBooleanItem.Reset;
  231. begin
  232. FillChar(IsSet,sizeof(IsSet),0);
  233. end;
  234. function TBooleanItem.ParamValueBool(SM: TSwitchMode):boolean;
  235. begin
  236. ParamValueBool:=IsSet[SM];
  237. end;
  238. function TBooleanItem.GetSwitchStr(SM: TSwitchMode): string;
  239. begin
  240. GetSwitchStr:=BoolToStr(IsSet[SM],'+','-');
  241. end;
  242. {*****************************************************************************
  243. TStringItem
  244. *****************************************************************************}
  245. constructor TStringItem.Init(const n,p:string; AID: TParamID; mult,allowspaces:boolean);
  246. begin
  247. Inherited Init(n,p,AID);
  248. Typ:=ot_String;
  249. Multiple:=mult;
  250. SeparateSpaces:=not allowspaces;
  251. Reset;
  252. end;
  253. function TStringItem.NeedParam:boolean;
  254. begin
  255. NeedParam:=(Str[SwitchesMode]<>'');
  256. end;
  257. function TStringItem.ParamValue:string;
  258. begin
  259. ParamValue:=Str[SwitchesMode];
  260. end;
  261. procedure TStringItem.Reset;
  262. begin
  263. FillChar(Str,sizeof(Str),0);
  264. end;
  265. {*****************************************************************************
  266. TLongintItem
  267. *****************************************************************************}
  268. constructor TLongintItem.Init(const n,p:string; AID: TParamID);
  269. begin
  270. Inherited Init(n,p,AID);
  271. Typ:=ot_Longint;
  272. Reset;
  273. end;
  274. function TLongintItem.NeedParam:boolean;
  275. begin
  276. NeedParam:=(Val[SwitchesMode]<>0);
  277. end;
  278. function TLongintItem.ParamValue:string;
  279. var
  280. s : string;
  281. begin
  282. Str(Val[SwitchesMode],s);
  283. ParamValue:=s;
  284. end;
  285. procedure TLongintItem.Reset;
  286. begin
  287. FillChar(Val,sizeof(Val),0);
  288. end;
  289. function TLongintItem.GetNumberStr(SM: TSwitchMode): string;
  290. begin
  291. GetNumberStr:=IntToStr(Val[SM]);
  292. end;
  293. {*****************************************************************************
  294. TSwitch
  295. *****************************************************************************}
  296. constructor TSwitches.Init(ch:char);
  297. begin
  298. new(Items,Init(10,5));
  299. Prefix:=ch;
  300. FillChar(SelNr,SizeOf(SelNr),#0);
  301. IsSel:=false;
  302. end;
  303. constructor TSwitches.InitSelect(ch:char);
  304. begin
  305. new(Items,Init(10,5));
  306. Prefix:=ch;
  307. FillChar(SelNr,SizeOf(SelNr),#0);
  308. IsSel:=true;
  309. end;
  310. destructor TSwitches.Done;
  311. begin
  312. dispose(Items,Done);
  313. end;
  314. procedure TSwitches.AddSelectItem(const name,param:string; AID: TParamID);
  315. begin
  316. Items^.Insert(New(PSelectItem,Init(name,Param,AID)));
  317. end;
  318. procedure TSwitches.AddDefaultSelect(const name:string);
  319. begin
  320. Items^.Insert(New(PSelectItem,InitDefault(name)));
  321. end;
  322. procedure TSwitches.AddBooleanItem(const name,param:string; AID: TParamID);
  323. begin
  324. Items^.Insert(New(PBooleanItem,Init(name,Param,AID)));
  325. end;
  326. procedure TSwitches.AddLongintItem(const name,param:string; AID: TParamID);
  327. begin
  328. Items^.Insert(New(PLongintItem,Init(name,Param,AID)));
  329. end;
  330. procedure TSwitches.AddStringItem(const name,param:string;AID: TParamID;mult,allowspaces:boolean);
  331. begin
  332. Items^.Insert(New(PStringItem,Init(name,Param,AID,mult,allowspaces)));
  333. end;
  334. function TSwitches.ItemCount:integer;
  335. begin
  336. ItemCount:=Items^.Count;
  337. end;
  338. function TSwitches.ItemName(index:integer):string;
  339. var
  340. P : PSwitchItem;
  341. begin
  342. if index<ItemCount then
  343. P:=Items^.At(Index)
  344. else
  345. P:=nil;
  346. if assigned(P) then
  347. ItemName:=P^.Name
  348. else
  349. ItemName:='';
  350. end;
  351. function TSwitches.ItemParam(index:integer):string;
  352. var
  353. P : PSwitchItem;
  354. begin
  355. if index<ItemCount then
  356. P:=Items^.At(Index)
  357. else
  358. P:=nil;
  359. if assigned(P) then
  360. ItemParam:='-'+Prefix+P^.Param
  361. else
  362. ItemParam:='';
  363. end;
  364. function TSwitches.GetBooleanItem(index:integer):boolean;
  365. var
  366. P : PBooleanItem;
  367. begin
  368. if index<ItemCount then
  369. P:=Items^.At(Index)
  370. else
  371. P:=nil;
  372. if assigned(P) and (P^.Typ=ot_boolean) then
  373. GetBooleanItem:=P^.IsSet[SwitchesMode]
  374. else
  375. GetBooleanItem:=false;
  376. end;
  377. function TSwitches.GetLongintItem(index:integer):longint;
  378. var
  379. P : PLongintItem;
  380. begin
  381. if index<ItemCount then
  382. P:=Items^.At(Index)
  383. else
  384. P:=nil;
  385. if assigned(P) and (P^.Typ=ot_longint) then
  386. GetLongintItem:=P^.Val[SwitchesMode]
  387. else
  388. GetLongintItem:=0;
  389. end;
  390. function TSwitches.GetStringItem(index:integer):string;
  391. var
  392. P : PStringItem;
  393. begin
  394. if index<ItemCount then
  395. P:=Items^.At(Index)
  396. else
  397. P:=nil;
  398. if assigned(P) and (P^.Typ=ot_string) then
  399. GetStringItem:=P^.Str[SwitchesMode]
  400. else
  401. GetStringItem:='';
  402. end;
  403. procedure TSwitches.SetBooleanItem(index:integer;b:boolean);
  404. var
  405. P : PBooleanItem;
  406. begin
  407. if index<ItemCount then
  408. P:=Items^.At(Index)
  409. else
  410. P:=nil;
  411. if assigned(P) and (P^.Typ=ot_boolean) then
  412. P^.IsSet[SwitchesMode]:=b;
  413. end;
  414. procedure TSwitches.SetLongintItem(index:integer;l:longint);
  415. var
  416. P : PLongintItem;
  417. begin
  418. if index<ItemCount then
  419. P:=Items^.At(Index)
  420. else
  421. P:=nil;
  422. if assigned(P) and (P^.Typ=ot_longint) then
  423. P^.Val[SwitchesMode]:=l;
  424. end;
  425. procedure TSwitches.SetStringItem(index:integer;const s:string);
  426. var
  427. P : PStringItem;
  428. begin
  429. if index<ItemCount then
  430. P:=Items^.At(Index)
  431. else
  432. P:=nil;
  433. if assigned(P) and (P^.Typ=ot_string) then
  434. P^.Str[SwitchesMode]:=s;
  435. end;
  436. function TSwitches.GetCurrSel:integer;
  437. begin
  438. if IsSel then
  439. GetCurrSel:=SelNr[SwitchesMode]
  440. else
  441. GetCurrSel:=-1;
  442. end;
  443. function TSwitches.GetCurrSelParam : String;
  444. begin
  445. if IsSel then
  446. GetCurrSelParam:=PSwitchItem(Items^.At(SelNr[SwitchesMode]))^.Param
  447. else
  448. GetCurrSelParam:='';
  449. end;
  450. procedure TSwitches.SetCurrSel(index:integer);
  451. begin
  452. if IsSel then
  453. SelNr[SwitchesMode]:=index;
  454. end;
  455. function TSwitches.SetCurrSelParam(const s : String) : boolean;
  456. function checkitem(P:PSwitchItem):boolean;{$ifndef FPC}far;{$endif}
  457. begin
  458. { empty items are not equivalent to others !! }
  459. CheckItem:=((S='') and (P^.Param='')) or
  460. ((Length(S)>0) and (P^.Param=s));
  461. end;
  462. var
  463. FoundP : PSwitchItem;
  464. begin
  465. FoundP:=Items^.FirstThat(@CheckItem);
  466. if Assigned(FoundP) then
  467. begin
  468. SetCurrSelParam:=true;
  469. SelNr[SwitchesMode]:=Items^.IndexOf(FoundP);
  470. end
  471. else
  472. SetCurrSelParam:=false;
  473. end;
  474. procedure TSwitches.WriteItemsCfg;
  475. var
  476. Pref : char;
  477. procedure writeitem(P:PSwitchItem);{$ifndef FPC}far;{$endif}
  478. var
  479. s,s1 : string;
  480. i,j : integer;
  481. begin
  482. if P^.NeedParam then
  483. begin
  484. if (P^.Typ=ot_string) and (PStringItem(P)^.Multiple) then
  485. begin
  486. s:=PStringItem(P)^.Str[SwitchesMode];
  487. repeat
  488. i:=pos(';',s);
  489. if PStringItem(P)^.SeparateSpaces then
  490. j:=pos(' ',s)
  491. else
  492. j:=0;
  493. if i=0 then
  494. i:=256;
  495. if (j>0) and (j<i) then
  496. i:=j;
  497. s1:=Copy(s,1,i-1);
  498. if s1<>'' then
  499. writeln(CfgFile,' -'+Pref+P^.Param+s1);
  500. Delete(s,1,i);
  501. until s='';
  502. end
  503. else
  504. if P^.Param<>'/' then
  505. Writeln(CfgFile,' -'+Pref+P^.Param+P^.ParamValue);
  506. end;
  507. end;
  508. var
  509. P : PSelectItem;
  510. begin
  511. Pref:=Prefix;
  512. if IsSel then
  513. begin
  514. { can be empty for some targets }
  515. If Items^.count>0 then
  516. begin
  517. P:=Items^.At(SelNr[SwitchesMode]);
  518. if not P^.IsDefault then
  519. writeln(CfgFile,' '+ItemParam(SelNr[SwitchesMode]));
  520. end;
  521. end
  522. else
  523. Items^.ForEach(@writeitem);
  524. end;
  525. procedure WriteCustom;
  526. var
  527. s : string;
  528. i : longint;
  529. begin
  530. s:=CustomArg[SwitchesMode];
  531. While s<>'' do
  532. begin
  533. i:=pos(' ',s);
  534. if i=0 then i:=256;
  535. writeln(CfgFile,' '+Copy(s,1,i-1));
  536. if i=256 then
  537. s:=''
  538. else
  539. s:=copy(s,i+1,255);
  540. end;
  541. end;
  542. function TSwitches.ReadItemsCfg(const s:string):boolean;
  543. function checkitem(P:PSwitchItem):boolean;{$ifndef FPC}far;{$endif}
  544. begin
  545. { empty items are not equivalent to others !! }
  546. { but -dGDB didn't work because of this PM }
  547. CheckItem:=((P^.Param='') and ((S='') or (P^.typ=ot_String))) or
  548. ((Length(P^.Param)>0) and (P^.Param=Copy(s,1,length(P^.Param))));
  549. end;
  550. var
  551. FoundP : PSwitchItem;
  552. code : integer;
  553. begin
  554. FoundP:=Items^.FirstThat(@checkitem);
  555. if assigned(FoundP) then
  556. begin
  557. case FoundP^.Typ of
  558. ot_Select : SelNr[SwitchesMode]:=Items^.IndexOf(FoundP);
  559. ot_Boolean : PBooleanItem(FoundP)^.IsSet[SwitchesMode]:=true;
  560. ot_String : begin
  561. if (PStringItem(FoundP)^.Multiple) and (PStringItem(FoundP)^.Str[SwitchesMode]<>'') then
  562. PStringItem(FoundP)^.Str[SwitchesMode]:=PStringItem(FoundP)^.Str[SwitchesMode]+';'+
  563. Copy(s,length(FoundP^.Param)+1,255)
  564. else
  565. PStringItem(FoundP)^.Str[SwitchesMode]:=Copy(s,length(FoundP^.Param)+1,255);
  566. end;
  567. ot_Longint : Val(Copy(s,length(FoundP^.Param)+1,255),PLongintItem(FoundP)^.Val[SwitchesMode],code);
  568. end;
  569. ReadItemsCfg:=true;
  570. end
  571. else
  572. ReadItemsCfg:=false;
  573. end;
  574. {*****************************************************************************
  575. Read / Write
  576. *****************************************************************************}
  577. procedure WriteSwitches(const fn:string);
  578. var
  579. OldSwitchesMode, SWM: TSwitchMode;
  580. begin
  581. { create the switches }
  582. assign(CfgFile,fn);
  583. {$I-}
  584. rewrite(CfgFile);
  585. {$I+}
  586. if ioresult<>0 then
  587. exit;
  588. writeln(CfgFile,'# '+msg_automaticallycreateddontedit);
  589. OldSwitchesMode:=SwitchesMode;
  590. for SWM:=low(TSwitchMode) to high(TSwitchMode) do
  591. begin
  592. SwitchesMode := SWM;
  593. Writeln(CfgFile,'#IFDEF '+SwitchesModeStr[SwitchesMode]);
  594. TargetSwitches^.WriteItemsCfg;
  595. VerboseSwitches^.WriteItemsCfg;
  596. SyntaxSwitches^.WriteItemsCfg;
  597. CodegenSwitches^.WriteItemsCfg;
  598. OptimizationSwitches^.WriteItemsCfg;
  599. OptimizingGoalSwitches^.WriteItemsCfg;
  600. ProcessorSwitches^.WriteItemsCfg;
  601. AsmReaderSwitches^.WriteItemsCfg;
  602. AsmInfoSwitches^.WriteItemsCfg;
  603. AsmOutputSwitches^.WriteItemsCfg;
  604. DirectorySwitches^.WriteItemsCfg;
  605. MemorySwitches^.WriteItemsCfg;
  606. ConditionalSwitches^.WriteItemsCfg;
  607. LibLinkerSwitches^.WriteItemsCfg;
  608. OtherLinkerSwitches^.WriteItemsCfg;
  609. DebugInfoSwitches^.WriteItemsCfg;
  610. ProfileInfoSwitches^.WriteItemsCfg;
  611. LinkAfterSwitches^.WriteItemsCfg;
  612. BrowserSwitches^.WriteItemsCfg;
  613. {MemorySizeSwitches^.WriteItemsCfg;}
  614. WriteCustom;
  615. Writeln(CfgFile,'#ENDIF');
  616. Writeln(CfgFile,'');
  617. end;
  618. close(CfgFile);
  619. SwitchesMode:=OldSwitchesMode;
  620. end;
  621. procedure ReadSwitches(const fn:string);
  622. var
  623. c : char;
  624. s : string;
  625. res : boolean;
  626. OldSwitchesMode,i : TSwitchMode;
  627. begin
  628. assign(CfgFile,fn);
  629. {$I-}
  630. reset(CfgFile);
  631. {$I+}
  632. if ioresult<>0 then
  633. begin
  634. SetDefaultSwitches;
  635. exit;
  636. end;
  637. OldSwitchesMode:=SwitchesMode;
  638. SwitchesMode:=om_Normal;
  639. while not eof(CfgFile) do
  640. begin
  641. readln(CfgFile,s);
  642. s:=LTrim(s);
  643. if (length(s)>=2) and (s[1]='-') then
  644. begin
  645. c:=s[2];
  646. res:=false;
  647. Delete(s,1,2);
  648. case c of
  649. 'a' : res:=AsmInfoSwitches^.ReadItemsCfg(s);
  650. 'A' : res:=AsmOutputSwitches^.ReadItemsCfg(s);
  651. 'b' : res:=BrowserSwitches^.ReadItemsCfg(s);
  652. 'C' : begin
  653. res:=CodegenSwitches^.ReadItemsCfg(s);
  654. if not res then
  655. res:=MemorySwitches^.ReadItemsCfg(s);
  656. end;
  657. 'd' : res:=ConditionalSwitches^.ReadItemsCfg(s);
  658. 'F' : res:=DirectorySwitches^.ReadItemsCfg(s);
  659. 'g' : res:=DebugInfoSwitches^.ReadItemsCfg(s);
  660. 'O' : begin
  661. res:=true;
  662. if not OptimizationSwitches^.ReadItemsCfg(s) then
  663. if not ProcessorSwitches^.ReadItemsCfg(s) then
  664. res:=OptimizingGoalSwitches^.ReadItemsCfg(s);
  665. end;
  666. 'p' : res:=ProfileInfoSwitches^.ReadItemsCfg(s);
  667. 's' : res:=LinkAfterSwitches^.ReadItemsCfg(s);
  668. 'R' : res:=AsmReaderSwitches^.ReadItemsCfg(s);
  669. 'S' : res:=SyntaxSwitches^.ReadItemsCfg(s);
  670. 'T' : res:=TargetSwitches^.ReadItemsCfg(s);
  671. 'v' : res:=VerboseSwitches^.ReadItemsCfg(s);
  672. 'X' : begin
  673. res:=LibLinkerSwitches^.ReadItemsCfg(s);
  674. if not res then
  675. res:=OtherLinkerSwitches^.ReadItemsCfg(s);
  676. end;
  677. end;
  678. { keep all others as a string }
  679. if not res then
  680. CustomArg[SwitchesMode]:=CustomArg[SwitchesMode]+' -'+c+s;
  681. end
  682. else
  683. if (Copy(s,1,7)='#IFDEF ') then
  684. begin
  685. Delete(s,1,7);
  686. for i:=low(TSwitchMode) to high(TSwitchMode) do
  687. if s=SwitchesModeStr[i] then
  688. begin
  689. SwitchesMode:=i;
  690. break;
  691. end;
  692. end
  693. else;
  694. end;
  695. close(CfgFile);
  696. SwitchesMode:=OldSwitchesMode;
  697. end;
  698. function GetSourceDirectories : string;
  699. var
  700. P : PStringItem;
  701. S : String;
  702. c : char;
  703. function checkitem(P:PSwitchItem):boolean;{$ifndef FPC}far;{$endif}
  704. begin
  705. CheckItem:=(P^.Typ=ot_string) and (P^.Param=c);
  706. end;
  707. begin
  708. GetSourceDirectories:='';
  709. c:='u';
  710. P:=DirectorySwitches^.Items^.FirstThat(@CheckItem);
  711. S:='';
  712. if assigned(P) then
  713. S:=P^.Str[SwitchesMode];
  714. c:='i';
  715. P:=DirectorySwitches^.Items^.FirstThat(@CheckItem);
  716. if assigned(P) then
  717. S:=P^.Str[SwitchesMode]+';'+S;
  718. if S='' then
  719. GetSourceDirectories:=SourceDirs+';'
  720. else
  721. GetSourceDirectories:=SourceDirs+';'+S+';';
  722. end;
  723. {*****************************************************************************
  724. Initialize
  725. *****************************************************************************}
  726. procedure InitSwitches;
  727. var
  728. t : tsystem;
  729. begin
  730. New(SyntaxSwitches,Init('S'));
  731. with SyntaxSwitches^ do
  732. begin
  733. AddBooleanItem(opt_objectpascal,'2',idNone);
  734. AddBooleanItem(opt_clikeoperators,'c',idNone);
  735. AddBooleanItem(opt_stopafterfirsterror,'e',idNone);
  736. AddBooleanItem(opt_allowlabelandgoto,'g',idNone);
  737. AddBooleanItem(opt_cplusplusstyledinline,'i',idNone);
  738. AddBooleanItem(opt_globalcmacros,'m',idNone);
  739. AddBooleanItem(opt_tp7compatibility,'o',idNone);
  740. AddBooleanItem(opt_delphicompatibility,'d',idNone);
  741. AddBooleanItem(opt_allowstaticinobjects,'s',idNone);
  742. { Useless as they are not passed to the compiler PM
  743. AddBooleanItem(opt_strictvarstrings,'/',idStrictVarStrings);
  744. AddBooleanItem(opt_extendedsyntax,'/',idExtendedSyntax);
  745. AddBooleanItem(opt_allowmmxoperations,'/',idMMXOps); }
  746. end;
  747. New(VerboseSwitches,Init('v'));
  748. with VerboseSwitches^ do
  749. begin
  750. AddBooleanItem(opt_warnings,'w',idNone);
  751. AddBooleanItem(opt_notes,'n',idNone);
  752. AddBooleanItem(opt_hints,'h',idNone);
  753. AddBooleanItem(opt_generalinfo,'i',idNone);
  754. AddBooleanItem(opt_usedtriedinfo,'ut',idNone);
  755. AddBooleanItem(opt_all,'a',idNone);
  756. AddBooleanItem(opt_showallprocsonerror,'b',idNone);
  757. end;
  758. New(CodegenSwitches,Init('C'));
  759. with CodegenSwitches^ do
  760. begin
  761. AddBooleanItem(opt_rangechecking,'r',idRangeChecks);
  762. AddBooleanItem(opt_stackchecking,'t',idStackChecks);
  763. AddBooleanItem(opt_iochecking,'i',idIOChecks);
  764. AddBooleanItem(opt_overflowchecking,'o',idOverflowChecks);
  765. end;
  766. New(OptimizingGoalSwitches,InitSelect('O'));
  767. with OptimizingGoalSwitches^ do
  768. begin
  769. AddSelectItem(opt_generatefastercode,'G',idNone);
  770. AddSelectItem(opt_generatesmallercode,'g',idNone);
  771. end;
  772. New(OptimizationSwitches,Init('O'));
  773. with OptimizationSwitches^ do
  774. begin
  775. {$ifdef I386}
  776. AddBooleanItem(opt_useregistervariables,'r',idNone);
  777. AddBooleanItem(opt_uncertainoptimizations,'u',idNone);
  778. AddBooleanItem(opt_level1optimizations,'1',idNone);
  779. AddBooleanItem(opt_level2optimizations,'2',idNone);
  780. {$else not I386}
  781. {$ifdef m68k}
  782. AddBooleanItem(opt_level1optimizations,'a',idNone);
  783. AddBooleanItem(opt_useregistervariables,'x',idNone);
  784. {$endif m68k}
  785. {$endif I386}
  786. end;
  787. New(ProcessorSwitches,InitSelect('O'));
  788. with ProcessorSwitches^ do
  789. begin
  790. {$ifdef I386}
  791. AddSelectItem(opt_i386486,'p1',idNone);
  792. AddSelectItem(opt_pentiumandmmx,'p2',idNone);
  793. AddSelectItem(opt_pentiumpro,'p3',idNone);
  794. AddSelectItem(opt_pentiumiv,'p4',idNone);
  795. {$else not I386}
  796. {$ifdef m68k}
  797. AddSelectItem(opt_m68000,'',idNone);
  798. AddSelectItem(opt_m68020,'2',idNone);
  799. {$endif m68k}
  800. {$endif not I386}
  801. end;
  802. New(TargetSwitches,InitSelect('T'));
  803. with TargetSwitches^ do
  804. begin
  805. { better, we've a correct target list without "tilded" names instead a wrong one }
  806. for t:=low(tsystem) to high(tsystem) do
  807. if assigned(targetinfos[t]) then
  808. AddSelectItem(targetinfos[t]^.name,targetinfos[t]^.shortname,idNone);
  809. end;
  810. New(AsmReaderSwitches,InitSelect('R'));
  811. with AsmReaderSwitches^ do
  812. begin
  813. {$ifdef I386}
  814. AddSelectItem(opt_directassembler,'direct',idAsmDirect);
  815. AddSelectItem(opt_attassembler,'att',idAsmATT);
  816. AddSelectItem(opt_intelassembler,'intel',idAsmIntel);
  817. {$endif I386}
  818. {$ifdef M68K}
  819. AddSelectItem(opt_motassembler,'mot',idAsmDirect);
  820. {$endif M68K}
  821. end;
  822. New(AsmInfoSwitches,Init('a'));
  823. with AsmInfoSwitches^ do
  824. begin
  825. AddBooleanItem(opt_listsource,'l',idNone);
  826. AddBooleanItem(opt_listregisterallocation,'r',idNone);
  827. AddBooleanItem(opt_listtempallocation,'t',idNone);
  828. end;
  829. New(AsmOutputSwitches,InitSelect('A'));
  830. with AsmOutputSwitches^ do
  831. begin
  832. AddDefaultSelect(opt_usedefaultas);
  833. {$ifdef I386}
  834. AddSelectItem(opt_usegnuas,'as',idNone);
  835. AddSelectItem(opt_usenasmcoff,'nasmcoff',idNone);
  836. AddSelectItem(opt_usenasmelf,'nasmelf',idNone);
  837. AddSelectItem(opt_usenasmobj,'nasmobj',idNone);
  838. AddSelectItem(opt_usemasm,'masm',idNone);
  839. AddSelectItem(opt_usetasm,'tasm',idNone);
  840. AddSelectItem(opt_usecoff,'coff',idNone);
  841. AddSelectItem(opt_usepecoff,'pecoff',idNone);
  842. {$endif I386}
  843. end;
  844. New(BrowserSwitches,InitSelect('b'));
  845. with BrowserSwitches^ do
  846. begin
  847. AddSelectItem(opt_nobrowser,'-',idSymInfNone);
  848. AddSelectItem(opt_globalonlybrowser,'+',idSymInfGlobalOnly);
  849. AddSelectItem(opt_localglobalbrowser,'l',idSymInfGlobalLocal);
  850. end;
  851. New(ConditionalSwitches,Init('d'));
  852. with ConditionalSwitches^ do
  853. begin
  854. AddStringItem(opt_conditionaldefines,'',idNone,true,false);
  855. end;
  856. New(MemorySwitches,Init('C'));
  857. with MemorySwitches^ do
  858. begin
  859. AddLongintItem(opt_stacksize,'s',idStackSize);
  860. AddLongintItem(opt_heapsize,'h',idHeapSize);
  861. end;
  862. New(DirectorySwitches,Init('F'));
  863. with DirectorySwitches^ do
  864. begin
  865. AddStringItem(opt_unitdirectories,'u',idNone,true,true);
  866. AddStringItem(opt_includedirectories,'i',idNone,true,true);
  867. AddStringItem(opt_librarydirectories,'l',idNone,true,true);
  868. AddStringItem(opt_objectdirectories,'o',idNone,true,true);
  869. AddStringItem(opt_exeppudirectories,'E',idNone,true,true);
  870. AddStringItem(opt_ppuoutputdirectory,'U',idNone,true,true);
  871. AddStringItem(opt_cross_tools_directory,'D',idNone,true,true);
  872. end;
  873. New(LibLinkerSwitches,InitSelect('X'));
  874. with LibLinkerSwitches^ do
  875. begin
  876. AddDefaultSelect(opt_librariesdefault);
  877. AddSelectItem(opt_dynamiclibraries,'D',idNone);
  878. AddSelectItem(opt_staticlibraries,'S',idNone);
  879. AddSelectItem(opt_smartlibraries,'X',idNone);
  880. end;
  881. New(OtherLinkerSwitches,Init('X'));
  882. with OtherLinkerSwitches^ do
  883. begin
  884. AddBooleanItem(opt_stripalldebugsymbols,'s',idNone);
  885. AddBooleanItem(opt_forcestaticlibs,'t',idNone);
  886. end;
  887. New(DebugInfoSwitches,InitSelect('g'));
  888. with DebugInfoSwitches^ do
  889. begin
  890. AddSelectItem(opt_nogendebugsymbolinfo,'-',idNone);
  891. AddSelectItem(opt_gendebugsymbolinfo,'',idNone);
  892. AddSelectItem(opt_gensymbolandbacktraceinfo,'l',idNone);
  893. AddSelectItem(opt_valgrindinfo,'v',idNone);
  894. { AddSelectItem('Generate ~d~bx symbol information','d');
  895. does not work anyhow (PM) }
  896. end;
  897. New(LinkAfterSwitches,Init('s'));
  898. LinkAfterSwitches^.AddBooleanItem(opt_linkafter,'',idNone);
  899. New(ProfileInfoSwitches,InitSelect('p'));
  900. with ProfileInfoSwitches^ do
  901. begin
  902. AddSelectItem(opt_noprofileinfo,'-',idNone);
  903. AddSelectItem(opt_gprofinfo,'g',idNone);
  904. end;
  905. {New(MemorySizeSwitches,Init('C'));
  906. with MemorySizeSwitches^ do
  907. begin
  908. AddLongIntItem('~S~tack size','s');
  909. AddLongIntItem('Local ~h~eap size','h');
  910. end;}
  911. SwitchesPath:=LocateFile(SwitchesName);
  912. if SwitchesPath='' then
  913. SwitchesPath:=SwitchesName;
  914. SwitchesPath:=FExpand(SwitchesPath);
  915. end;
  916. procedure SetDefaultSwitches;
  917. var
  918. i,OldSwitchesMode : TSwitchMode;
  919. begin
  920. { setup some useful defaults }
  921. OldSwitchesMode:=SwitchesMode;
  922. for i:=low(TSwitchMode) to high(TSwitchMode) do
  923. begin
  924. SwitchesMode:=i;
  925. {$ifdef i386}
  926. { default is Pentium }
  927. ProcessorSwitches^.SetCurrSel(1);
  928. { AT&T reader }
  929. AsmReaderSwitches^.SetCurrSel(1);
  930. {$endif i386}
  931. { 128k stack }
  932. MemorySwitches^.SetLongintItem(0,65536*2);
  933. { 2 MB heap }
  934. MemorySwitches^.SetLongintItem(1,1024*1024*2);
  935. { goto/lable allowed }
  936. SyntaxSwitches^.SetBooleanItem(3,true);
  937. case i of
  938. om_debug:
  939. begin
  940. { debugging info on }
  941. DebugInfoSwitches^.SetCurrSel(1);
  942. { range checking }
  943. CodegenSwitches^.SetBooleanItem(0,true);
  944. { io checking }
  945. CodegenSwitches^.SetBooleanItem(2,true);
  946. { overflow checking }
  947. CodegenSwitches^.SetBooleanItem(3,true);
  948. end;
  949. om_normal:
  950. begin
  951. OptimizationSwitches^.SetBooleanItem(2,true);
  952. end;
  953. om_release:
  954. begin
  955. OptimizationSwitches^.SetBooleanItem(2,true);
  956. OptimizationSwitches^.SetBooleanItem(3,true);
  957. end;
  958. end;
  959. { set appriopriate default target }
  960. TargetSwitches^.SetCurrSelParam(target_info.shortname);
  961. end;
  962. SwitchesMode:=OldSwitchesMode;
  963. end;
  964. procedure DoneSwitches;
  965. begin
  966. dispose(SyntaxSwitches,Done);
  967. dispose(VerboseSwitches,Done);
  968. dispose(CodegenSwitches,Done);
  969. dispose(OptimizationSwitches,Done);
  970. dispose(OptimizingGoalSwitches,Done);
  971. dispose(ProcessorSwitches,Done);
  972. dispose(BrowserSwitches,Done);
  973. dispose(TargetSwitches,Done);
  974. dispose(AsmReaderSwitches,Done);
  975. dispose(AsmOutputSwitches,Done);
  976. dispose(AsmInfoSwitches,Done);
  977. dispose(ConditionalSwitches,Done);
  978. dispose(MemorySwitches,Done);
  979. {dispose(MemorySizeSwitches,Done);}
  980. dispose(DirectorySwitches,Done);
  981. dispose(DebugInfoSwitches,Done);
  982. dispose(LibLinkerSwitches,Done);
  983. dispose(LinkAfterSwitches,Done);
  984. dispose(OtherLinkerSwitches,Done);
  985. dispose(ProfileInfoSwitches,Done);
  986. end;
  987. procedure GetCompilerOptionLines(C: PUnsortedStringCollection);
  988. procedure AddLine(const S: string);
  989. begin
  990. C^.Insert(NewStr(S));
  991. end;
  992. procedure ConstructSwitchModeDirectives(SM: TSwitchMode; const IfDefSym: string);
  993. var SwitchParams: PStringCollection;
  994. MiscParams : PStringCollection;
  995. procedure AddSwitch(const S: string);
  996. begin
  997. SwitchParams^.Insert(NewStr(S));
  998. end;
  999. procedure AddParam(const S: string);
  1000. begin
  1001. MiscParams^.Insert(NewStr(S));
  1002. end;
  1003. procedure EnumSwitches(P: PSwitches);
  1004. procedure HandleSwitch(P: PSwitchItem); {$ifndef FPC}far;{$endif}
  1005. begin
  1006. case P^.ParamID of
  1007. { idAlign :}
  1008. idRangeChecks : AddSwitch('R'+P^.GetSwitchStr(SM));
  1009. idStackChecks : AddSwitch('S'+P^.GetSwitchStr(SM));
  1010. idIOChecks : AddSwitch('I'+P^.GetSwitchStr(SM));
  1011. idOverflowChecks : AddSwitch('Q'+P^.GetSwitchStr(SM));
  1012. { idAsmDirect : if P^.GetParamValueBool[SM] then AddParam('ASMMODE DIRECT');
  1013. idAsmATT : if P^.GetParamValueBool[SM] then AddParam('ASMMODE ATT');
  1014. idAsmIntel : if P^.GetParamValueBool[SM] then AddParam('ASMMODE INTEL');
  1015. idAsmMot : if P^.GetParamValueBool[SM] then AddParam('ASMMODE MOT');}
  1016. { idSymInfNone : ;
  1017. idSymInfGlobalOnly:;
  1018. idSymInfGlobalLocal:if P^.ParamValueBool(SM) then AddSwitch('L+');}
  1019. { idStackSize
  1020. idHeapSize}
  1021. idStrictVarStrings: AddSwitch('V'+P^.GetSwitchStr(SM));
  1022. idExtendedSyntax : AddSwitch('X'+P^.GetSwitchStr(SM));
  1023. idMMXOps : if P^.ParamValueBool(SM) then AddParam('MMX');
  1024. idTypedAddress : AddSwitch('T'+P^.GetSwitchStr(SM));
  1025. { idPackRecords
  1026. idPackEnum}
  1027. idStackFrames : AddSwitch('W'+P^.GetSwitchStr(SM));
  1028. idReferenceInfo : AddSwitch('Y'+P^.GetSwitchStr(SM));
  1029. idDebugInfo : AddSwitch('D'+P^.GetSwitchStr(SM));
  1030. idBoolEval : AddSwitch('B'+P^.GetSwitchStr(SM));
  1031. idLongString : AddSwitch('H'+P^.GetSwitchStr(SM));
  1032. idTypeInfo : AddSwitch('M'+P^.GetSwitchStr(SM));
  1033. end;
  1034. end;
  1035. begin
  1036. P^.Items^.ForEach(@HandleSwitch);
  1037. end;
  1038. var I: integer;
  1039. S: string;
  1040. begin
  1041. AddLine('{$IFDEF '+IfDefSym+'}');
  1042. New(SwitchParams, Init(10,10));
  1043. New(MiscParams, Init(10,10));
  1044. EnumSwitches(LibLinkerSwitches);
  1045. EnumSwitches(OtherLinkerSwitches);
  1046. EnumSwitches(DebugInfoSwitches);
  1047. EnumSwitches(ProfileInfoSwitches);
  1048. EnumSwitches(SyntaxSwitches);
  1049. EnumSwitches(VerboseSwitches);
  1050. EnumSwitches(CodegenSwitches);
  1051. EnumSwitches(OptimizationSwitches);
  1052. EnumSwitches(OptimizingGoalSwitches);
  1053. EnumSwitches(ProcessorSwitches);
  1054. EnumSwitches(AsmReaderSwitches);
  1055. EnumSwitches(AsmInfoSwitches);
  1056. EnumSwitches(AsmOutputSwitches);
  1057. EnumSwitches(TargetSwitches);
  1058. EnumSwitches(ConditionalSwitches);
  1059. EnumSwitches(MemorySwitches);
  1060. EnumSwitches(BrowserSwitches);
  1061. EnumSwitches(DirectorySwitches);
  1062. S:='';
  1063. for I:=0 to SwitchParams^.Count-1 do
  1064. begin
  1065. if I=0 then S:='{$' else S:=S+',';
  1066. S:=S+PString(SwitchParams^.At(I))^;
  1067. end;
  1068. if S<>'' then S:=S+'}';
  1069. if S<>'' then AddLine(' '+S);
  1070. for I:=0 to MiscParams^.Count-1 do
  1071. AddLine(' {$'+PString(MiscParams^.At(I))^+'}');
  1072. Dispose(SwitchParams, Done); Dispose(MiscParams, Done);
  1073. AddLine('{$ENDIF '+IfDefSym+'}');
  1074. end;
  1075. var SM: TSwitchMode;
  1076. begin
  1077. for SM:=Low(TSwitchMode) to High(TSwitchMode) do
  1078. ConstructSwitchModeDirectives(SM,SwitchesModeStr[SM]);
  1079. end;
  1080. end.