globals.pas 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  1. {
  2. $Id$
  3. Copyright (C) 1998-2000 by Florian Klaempfl
  4. This unit implements some support functions and global variables
  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 globals;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. {$ifdef win32}
  23. windows,
  24. {$endif}
  25. {$ifdef unix}
  26. linux,
  27. {$endif}
  28. {$ifdef Delphi}
  29. sysutils,
  30. dmisc,
  31. {$else}
  32. strings,
  33. dos,
  34. {$endif}
  35. globtype,version,systems,cutils,cobjects;
  36. const
  37. {$ifdef unix}
  38. DirSep = '/';
  39. {$else}
  40. {$ifdef amiga}
  41. DirSep = '/';
  42. {$else}
  43. DirSep = '\';
  44. {$endif}
  45. {$endif}
  46. {$ifdef Splitheap}
  47. testsplit : boolean = false;
  48. {$endif Splitheap}
  49. delphimodeswitches : tmodeswitches=
  50. [m_delphi,m_tp,m_all,m_class,m_objpas,m_result,m_string_pchar,
  51. m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
  52. m_out,m_default_para];
  53. fpcmodeswitches : tmodeswitches=
  54. [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward,
  55. m_cvar_support,m_initfinal,m_add_pointer];
  56. objfpcmodeswitches : tmodeswitches=
  57. [m_objfpc,m_fpc,m_all,m_class,m_objpas,m_result,m_string_pchar,m_nested_comment,
  58. m_repeat_forward,m_cvar_support,m_initfinal,m_add_pointer,m_out,m_default_para];
  59. tpmodeswitches : tmodeswitches=
  60. [m_tp7,m_tp,m_all,m_tp_procvar];
  61. gpcmodeswitches : tmodeswitches=
  62. [m_gpc,m_all];
  63. type
  64. TSearchPathList = object(TStringQueue)
  65. procedure AddPath(s:string;addfirst:boolean);
  66. procedure AddList(list:TSearchPathList;addfirst:boolean);
  67. function FindFile(const f : string;var b : boolean) : string;
  68. end;
  69. var
  70. { specified inputfile }
  71. inputdir : dirstr;
  72. inputfile : namestr;
  73. inputextension : extstr;
  74. { specified outputfile with -o parameter }
  75. outputfile : namestr;
  76. { specified with -FE or -FU }
  77. outputexedir : dirstr;
  78. outputunitdir : dirstr;
  79. { things specified with parameters }
  80. paralinkoptions,
  81. paradynamiclinker : string;
  82. parapreprocess : boolean;
  83. { directory where the utils can be found (options -FD) }
  84. utilsdirectory : dirstr;
  85. { some flags for global compiler switches }
  86. do_build,
  87. do_make : boolean;
  88. not_unit_proc : boolean;
  89. { path for searching units, different paths can be seperated by ; }
  90. exepath : dirstr; { Path to ppc }
  91. librarysearchpath,
  92. unitsearchpath,
  93. objectsearchpath,
  94. includesearchpath : TSearchPathList;
  95. { deffile }
  96. usewindowapi : boolean;
  97. description : string;
  98. dllversion : string;
  99. dllmajor,dllminor,dllrevision : word; { revision only for netware }
  100. akttokenpos, { position of the last token }
  101. aktfilepos : tfileposinfo; { current position }
  102. { type of currently parsed block }
  103. { isn't full implemented (FK) }
  104. block_type : tblock_type;
  105. in_args : boolean; { arguments must be checked especially }
  106. parsing_para_level : longint; { parameter level, used to convert
  107. proc calls to proc loads in firstcalln }
  108. { Must_be_valid : boolean; should the variable already have a value
  109. obsolete replace by set_varstate function }
  110. compile_level : word;
  111. make_ref : boolean;
  112. resolving_forward : boolean; { used to add forward reference as second ref }
  113. use_esp_stackframe : boolean; { to test for call with ESP as stack frame }
  114. inlining_procedure : boolean; { are we inlining a procedure }
  115. { commandline values }
  116. initdefines : tlinkedlist;
  117. initglobalswitches : tglobalswitches;
  118. initmoduleswitches : tmoduleswitches;
  119. initlocalswitches : tlocalswitches;
  120. initmodeswitches : tmodeswitches;
  121. {$IFDEF testvarsets}
  122. Initsetalloc, {0=fixed, 1 =var}
  123. {$ENDIF}
  124. initpackenum : longint;
  125. initpackrecords : tpackrecords;
  126. initoutputformat : tasm;
  127. initoptprocessor,
  128. initspecificoptprocessor : tprocessors;
  129. initasmmode : tasmmode;
  130. initinterfacetype : tinterfacetypes;
  131. { current state values }
  132. aktglobalswitches : tglobalswitches;
  133. aktmoduleswitches : tmoduleswitches;
  134. aktlocalswitches : tlocalswitches;
  135. nextaktlocalswitches : tlocalswitches;
  136. localswitcheschanged : boolean;
  137. aktmodeswitches : tmodeswitches;
  138. {$IFDEF testvarsets}
  139. aktsetalloc,
  140. {$ENDIF}
  141. aktpackenum : longint;
  142. aktmaxfpuregisters: longint;
  143. aktpackrecords : tpackrecords;
  144. aktoutputformat : tasm;
  145. aktoptprocessor,
  146. aktspecificoptprocessor : tprocessors;
  147. aktasmmode : tasmmode;
  148. aktinterfacetype : tinterfacetypes;
  149. { Memory sizes }
  150. heapsize,
  151. maxheapsize,
  152. stacksize : longint;
  153. {$Ifdef EXTDEBUG}
  154. total_of_firstpass,
  155. firstpass_several : longint;
  156. {$ifdef FPC}
  157. EntryMemUsed : longint;
  158. {$endif FPC}
  159. { parameter switches }
  160. debugstop,
  161. only_one_pass : boolean;
  162. {$EndIf EXTDEBUG}
  163. { windows application type }
  164. apptype : tapptype;
  165. const
  166. RelocSection : boolean = true;
  167. RelocSectionSetExplicitly : boolean = false;
  168. LinkTypeSetExplicitly : boolean = false;
  169. IsExe : boolean = false;
  170. DLLsource : boolean = false;
  171. DLLImageBase : pstring = nil;
  172. UseDeffileForExport : boolean = true;
  173. ForceDeffileForExport : boolean = false;
  174. { used to set all registers used for each global function
  175. this should dramatically decrease the number of
  176. recompilations needed PM }
  177. simplify_ppu : boolean = false;
  178. { should we allow non static members ? }
  179. allow_only_static : boolean = false;
  180. Inside_asm_statement : boolean = false;
  181. global_unit_count : word = 0;
  182. { for error info in pp.pas }
  183. parser_current_file : string = '';
  184. procedure abstract;
  185. function bstoslash(const s : string) : string;
  186. function getdatestr:string;
  187. function gettimestr:string;
  188. function filetimestring( t : longint) : string;
  189. procedure DefaultReplacements(var s:string);
  190. function GetCurrentDir:string;
  191. function path_absolute(const s : string) : boolean;
  192. Function PathExists ( F : String) : Boolean;
  193. Function FileExists ( Const F : String) : Boolean;
  194. Function RemoveFile(const f:string):boolean;
  195. Function RemoveDir(d:string):boolean;
  196. Function GetFileTime ( Var F : File) : Longint;
  197. Function GetNamedFileTime ( Const F : String) : Longint;
  198. Function SplitPath(const s:string):string;
  199. Function SplitFileName(const s:string):string;
  200. Function SplitName(const s:string):string;
  201. Function SplitExtension(Const HStr:String):String;
  202. Function AddExtension(Const HStr,ext:String):String;
  203. Function ForceExtension(Const HStr,ext:String):String;
  204. Function FixPath(s:string;allowdot:boolean):string;
  205. function FixFileName(const s:string):string;
  206. procedure SplitBinCmd(const s:string;var bstr,cstr:string);
  207. procedure SynchronizeFileTime(const fn1,fn2:string);
  208. function FindFile(const f : string;path : string;var b : boolean) : string;
  209. function FindExe(bin:string;var found:boolean):string;
  210. function GetShortName(const n:string):string;
  211. Procedure Shell(const command:string);
  212. function GetEnvPChar(const envname:string):pchar;
  213. procedure FreeEnvPChar(p:pchar);
  214. Function SetCompileMode(const s:string; changeInit: boolean):boolean;
  215. procedure InitGlobals;
  216. procedure DoneGlobals;
  217. function string2guid(const s: string; var GUID: TGUID): boolean;
  218. function guid2string(const GUID: TGUID): string;
  219. implementation
  220. uses
  221. comphook;
  222. procedure abstract;
  223. begin
  224. do_internalerror(255);
  225. end;
  226. function ngraphsearchvalue(const s1,s2 : string) : double;
  227. const
  228. n = 3;
  229. var
  230. equals,i,j : longint;
  231. hs : string;
  232. begin
  233. equals:=0;
  234. { is the string long enough ? }
  235. if min(length(s1),length(s2))-n+1<1 then
  236. begin
  237. ngraphsearchvalue:=0.0;
  238. exit;
  239. end;
  240. for i:=1 to length(s1)-n+1 do
  241. begin
  242. hs:=copy(s1,i,n);
  243. for j:=1 to length(s2)-n+1 do
  244. if hs=copy(s2,j,n) then
  245. inc(equals);
  246. end;
  247. {$ifdef fpc}
  248. ngraphsearchvalue:=equals/double(max(length(s1),length(s2))-n+1);
  249. {$else}
  250. ngraphsearchvalue:=equals/(max(length(s1),length(s2))-n+1);
  251. {$endif}
  252. end;
  253. function bstoslash(const s : string) : string;
  254. {
  255. return string s with all \ changed into /
  256. }
  257. var
  258. i : longint;
  259. begin
  260. for i:=1to length(s) do
  261. if s[i]='\' then
  262. bstoslash[i]:='/'
  263. else
  264. bstoslash[i]:=s[i];
  265. bstoslash[0]:=s[0];
  266. end;
  267. {****************************************************************************
  268. Time Handling
  269. ****************************************************************************}
  270. Function L0(l:longint):string;
  271. {
  272. return the string of value l, if l<10 then insert a zero, so
  273. the string is always at least 2 chars '01','02',etc
  274. }
  275. var
  276. s : string;
  277. begin
  278. Str(l,s);
  279. if l<10 then
  280. s:='0'+s;
  281. L0:=s;
  282. end;
  283. function gettimestr:string;
  284. {
  285. get the current time in a string HH:MM:SS
  286. }
  287. var
  288. hour,min,sec,hsec : word;
  289. begin
  290. {$ifdef delphi}
  291. dmisc.gettime(hour,min,sec,hsec);
  292. {$else delphi}
  293. dos.gettime(hour,min,sec,hsec);
  294. {$endif delphi}
  295. gettimestr:=L0(Hour)+':'+L0(min)+':'+L0(sec);
  296. end;
  297. function getdatestr:string;
  298. {
  299. get the current date in a string YY/MM/DD
  300. }
  301. var
  302. Year,Month,Day,Wday : Word;
  303. begin
  304. {$ifdef delphi}
  305. dmisc.getdate(year,month,day,wday);
  306. {$else}
  307. dos.getdate(year,month,day,wday);
  308. {$endif}
  309. getdatestr:=L0(Year)+'/'+L0(Month)+'/'+L0(Day);
  310. end;
  311. function filetimestring( t : longint) : string;
  312. {
  313. convert dos datetime t to a string YY/MM/DD HH:MM:SS
  314. }
  315. var
  316. {$ifndef unix}
  317. DT : DateTime;
  318. {$endif}
  319. Year,Month,Day,Hour,Min,Sec : Word;
  320. begin
  321. if t=-1 then
  322. begin
  323. FileTimeString:='Not Found';
  324. exit;
  325. end;
  326. {$ifndef unix}
  327. unpacktime(t,DT);
  328. Year:=dT.year;month:=dt.month;day:=dt.day;
  329. Hour:=dt.hour;min:=dt.min;sec:=dt.sec;
  330. {$else}
  331. EpochToLocal (t,year,month,day,hour,min,sec);
  332. {$endif}
  333. filetimestring:=L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
  334. end;
  335. {****************************************************************************
  336. Default Macro Handling
  337. ****************************************************************************}
  338. procedure DefaultReplacements(var s:string);
  339. begin
  340. { Replace some macro's }
  341. Replace(s,'$FPCVER',version_string);
  342. Replace(s,'$VERSION',version_string);
  343. Replace(s,'$FULLVERSION',full_version_string);
  344. Replace(s,'$FPCDATE',date_string);
  345. Replace(s,'$FPCTARGET',target_cpu_string);
  346. Replace(s,'$FPCCPU',target_cpu_string);
  347. Replace(s,'$TARGET',target_path);
  348. Replace(s,'$FPCOS',target_path);
  349. end;
  350. {****************************************************************************
  351. File Handling
  352. ****************************************************************************}
  353. function GetCurrentDir:string;
  354. var
  355. CurrentDir : string;
  356. begin
  357. GetDir(0,CurrentDir);
  358. GetCurrentDir:=FixPath(CurrentDir,false);
  359. end;
  360. function path_absolute(const s : string) : boolean;
  361. {
  362. is path s an absolute path?
  363. }
  364. begin
  365. path_absolute:=false;
  366. {$ifdef unix}
  367. if (length(s)>0) and (s[1]='/') then
  368. path_absolute:=true;
  369. {$else unix}
  370. {$ifdef amiga}
  371. if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or (Pos(':',s) = length(s)) then
  372. path_absolute:=true;
  373. {$else}
  374. if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or
  375. ((length(s)>2) and (s[2]=':') and ((s[3]='\') or (s[3]='/'))) then
  376. path_absolute:=true;
  377. {$endif amiga}
  378. {$endif unix}
  379. end;
  380. {$ifndef FPC}
  381. Procedure FindClose(var Info : SearchRec);
  382. Begin
  383. End;
  384. {$endif not FPC}
  385. Function FileExists ( Const F : String) : Boolean;
  386. {$ifndef delphi}
  387. Var
  388. Info : SearchRec;
  389. {$endif}
  390. begin
  391. {$ifdef delphi}
  392. FileExists:=sysutils.FileExists(f);
  393. {$else}
  394. findfirst(F,readonly+archive+hidden,info);
  395. FileExists:=(doserror=0);
  396. findclose(Info);
  397. {$endif delphi}
  398. end;
  399. Function PathExists ( F : String) : Boolean;
  400. Var
  401. Info : SearchRec;
  402. begin
  403. if F[Length(f)] in ['/','\'] then
  404. Delete(f,length(f),1);
  405. findfirst(F,readonly+archive+hidden+directory,info);
  406. PathExists:=(doserror=0) and ((info.attr and directory)=directory);
  407. findclose(Info);
  408. end;
  409. Function RemoveFile(const f:string):boolean;
  410. var
  411. g : file;
  412. begin
  413. assign(g,f);
  414. {$I-}
  415. erase(g);
  416. {$I+}
  417. RemoveFile:=(ioresult=0);
  418. end;
  419. Function RemoveDir(d:string):boolean;
  420. begin
  421. if d[length(d)]=DirSep then
  422. Delete(d,length(d),1);
  423. {$I-}
  424. rmdir(d);
  425. {$I+}
  426. RemoveDir:=(ioresult=0);
  427. end;
  428. Function SplitPath(const s:string):string;
  429. var
  430. i : longint;
  431. begin
  432. i:=Length(s);
  433. while (i>0) and not(s[i] in ['/','\']) do
  434. dec(i);
  435. SplitPath:=Copy(s,1,i);
  436. end;
  437. Function SplitFileName(const s:string):string;
  438. var
  439. p : dirstr;
  440. n : namestr;
  441. e : extstr;
  442. begin
  443. FSplit(s,p,n,e);
  444. SplitFileName:=n+e;
  445. end;
  446. Function SplitName(const s:string):string;
  447. var
  448. i,j : longint;
  449. begin
  450. i:=Length(s);
  451. j:=Length(s);
  452. while (i>0) and not(s[i] in ['/','\']) do
  453. dec(i);
  454. while (j>0) and (s[j]<>'.') do
  455. dec(j);
  456. if j<=i then
  457. j:=255;
  458. SplitName:=Copy(s,i+1,j-(i+1));
  459. end;
  460. Function SplitExtension(Const HStr:String):String;
  461. var
  462. j : longint;
  463. begin
  464. j:=length(Hstr);
  465. while (j>0) and (Hstr[j]<>'.') do
  466. begin
  467. if hstr[j]=DirSep then
  468. j:=0
  469. else
  470. dec(j);
  471. end;
  472. if j=0 then
  473. j:=254;
  474. SplitExtension:=Copy(Hstr,j,255);
  475. end;
  476. Function AddExtension(Const HStr,ext:String):String;
  477. begin
  478. if (Ext<>'') and (SplitExtension(HStr)='') then
  479. AddExtension:=Hstr+Ext
  480. else
  481. AddExtension:=Hstr;
  482. end;
  483. Function ForceExtension(Const HStr,ext:String):String;
  484. var
  485. j : longint;
  486. begin
  487. j:=length(Hstr);
  488. while (j>0) and (Hstr[j]<>'.') do
  489. dec(j);
  490. if j=0 then
  491. j:=255;
  492. ForceExtension:=Copy(Hstr,1,j-1)+Ext;
  493. end;
  494. Function FixPath(s:string;allowdot:boolean):string;
  495. var
  496. i : longint;
  497. begin
  498. { Fix separator }
  499. for i:=1 to length(s) do
  500. if s[i] in ['/','\'] then
  501. s[i]:=DirSep;
  502. { Fix ending / }
  503. if (length(s)>0) and (s[length(s)]<>DirSep) and
  504. (s[length(s)]<>':') then
  505. s:=s+DirSep;
  506. { Remove ./ }
  507. if (not allowdot) and (s='.'+DirSep) then
  508. s:='';
  509. { return }
  510. {$ifdef unix}
  511. FixPath:=s;
  512. {$else}
  513. FixPath:=Lower(s);
  514. {$endif}
  515. end;
  516. function FixFileName(const s:string):string;
  517. var
  518. i : longint;
  519. {$ifdef Linux}
  520. NoPath : boolean;
  521. {$endif Linux}
  522. begin
  523. {$ifdef Linux}
  524. NoPath:=true;
  525. {$endif Linux}
  526. for i:=length(s) downto 1 do
  527. begin
  528. case s[i] of
  529. {$ifdef Linux}
  530. '/','\' : begin
  531. FixFileName[i]:='/';
  532. NoPath:=false; {Skip lowercasing path: 'X11'<>'x11' }
  533. end;
  534. 'A'..'Z' : if NoPath then
  535. FixFileName[i]:=char(byte(s[i])+32)
  536. else
  537. FixFileName[i]:=s[i];
  538. {$else}
  539. '/' : FixFileName[i]:='\';
  540. 'A'..'Z' : FixFileName[i]:=char(byte(s[i])+32);
  541. {$endif}
  542. else
  543. FixFileName[i]:=s[i];
  544. end;
  545. end;
  546. FixFileName[0]:=s[0];
  547. end;
  548. procedure SplitBinCmd(const s:string;var bstr,cstr:string);
  549. var
  550. i : longint;
  551. begin
  552. i:=pos(' ',s);
  553. if i>0 then
  554. begin
  555. bstr:=Copy(s,1,i-1);
  556. cstr:=Copy(s,i+1,length(s)-i);
  557. end
  558. else
  559. begin
  560. bstr:='';
  561. cstr:='';
  562. end;
  563. end;
  564. procedure TSearchPathList.AddPath(s:string;addfirst:boolean);
  565. var
  566. j : longint;
  567. hs,hsd,
  568. CurrentDir,
  569. CurrPath : string;
  570. dir : searchrec;
  571. hp : PStringQueueItem;
  572. procedure addcurrpath;
  573. begin
  574. if addfirst then
  575. begin
  576. Delete(currPath);
  577. Insert(currPath);
  578. end
  579. else
  580. begin
  581. { Check if already in path, then we don't add it }
  582. hp:=Find(currPath);
  583. if not assigned(hp) then
  584. Concat(currPath);
  585. end;
  586. end;
  587. begin
  588. if s='' then
  589. exit;
  590. { Support default macro's }
  591. DefaultReplacements(s);
  592. { get current dir }
  593. CurrentDir:=GetCurrentDir;
  594. repeat
  595. { get currpath }
  596. if addfirst then
  597. begin
  598. j:=length(s);
  599. while (j>0) and (s[j]<>';') do
  600. dec(j);
  601. CurrPath:=FixPath(Copy(s,j+1,length(s)-j),false);
  602. if j=0 then
  603. s:=''
  604. else
  605. System.Delete(s,j,length(s)-j+1);
  606. end
  607. else
  608. begin
  609. j:=Pos(';',s);
  610. if j=0 then
  611. j:=255;
  612. CurrPath:=FixPath(Copy(s,1,j-1),false);
  613. System.Delete(s,1,j);
  614. end;
  615. { fix pathname }
  616. if CurrPath='' then
  617. CurrPath:='.'+DirSep
  618. else
  619. begin
  620. CurrPath:=FixPath(FExpand(CurrPath),false);
  621. if (CurrentDir<>'') and (Copy(CurrPath,1,length(CurrentDir))=CurrentDir) then
  622. CurrPath:='.'+DirSep+Copy(CurrPath,length(CurrentDir)+1,255);
  623. end;
  624. { wildcard adding ? }
  625. if pos('*',currpath)>0 then
  626. begin
  627. if currpath[length(currpath)]=dirsep then
  628. hs:=Copy(currpath,1,length(CurrPath)-1)
  629. else
  630. hs:=currpath;
  631. hsd:=SplitPath(hs);
  632. findfirst(hs,directory,dir);
  633. while doserror=0 do
  634. begin
  635. if (dir.name<>'.') and
  636. (dir.name<>'..') and
  637. ((dir.attr and directory)<>0) then
  638. begin
  639. currpath:=hsd+dir.name+dirsep;
  640. hp:=Find(currPath);
  641. if not assigned(hp) then
  642. AddCurrPath;
  643. end;
  644. findnext(dir);
  645. end;
  646. FindClose(dir);
  647. end
  648. else
  649. begin
  650. if PathExists(currpath) then
  651. addcurrpath;
  652. end;
  653. until (s='');
  654. end;
  655. procedure TSearchPathList.AddList(list:TSearchPathList;addfirst:boolean);
  656. var
  657. s : string;
  658. hl : TSearchPathList;
  659. hp,hp2 : PStringQueueItem;
  660. begin
  661. if list.empty then
  662. exit;
  663. { create temp and reverse the list }
  664. if addfirst then
  665. begin
  666. hl.Init;
  667. hp:=list.first;
  668. while assigned(hp) do
  669. begin
  670. hl.insert(hp^.data^);
  671. hp:=hp^.next;
  672. end;
  673. while not hl.empty do
  674. begin
  675. s:=hl.Get;
  676. Delete(s);
  677. Insert(s);
  678. end;
  679. hl.done;
  680. end
  681. else
  682. begin
  683. hp:=list.first;
  684. while assigned(hp) do
  685. begin
  686. hp2:=Find(hp^.data^);
  687. { Check if already in path, then we don't add it }
  688. if not assigned(hp2) then
  689. Concat(hp^.data^);
  690. hp:=hp^.next;
  691. end;
  692. end;
  693. end;
  694. function TSearchPathList.FindFile(const f : string;var b : boolean) : string;
  695. Var
  696. p : PStringQueueItem;
  697. begin
  698. FindFile:='';
  699. b:=false;
  700. p:=first;
  701. while assigned(p) do
  702. begin
  703. If FileExists(p^.data^+f) then
  704. begin
  705. FindFile:=p^.data^;
  706. b:=true;
  707. exit;
  708. end;
  709. p:=p^.next;
  710. end;
  711. end;
  712. Function GetFileTime ( Var F : File) : Longint;
  713. Var
  714. {$ifdef unix}
  715. Info : Stat;
  716. {$endif}
  717. L : longint;
  718. begin
  719. {$ifdef unix}
  720. FStat (F,Info);
  721. L:=Info.Mtime;
  722. {$else}
  723. GetFTime(f,l);
  724. {$endif}
  725. GetFileTime:=L;
  726. end;
  727. Function GetNamedFileTime (Const F : String) : Longint;
  728. begin
  729. GetNamedFileTime:=do_getnamedfiletime(F);
  730. end;
  731. {Touch Assembler and object time to ppu time is there is a ppufilename}
  732. procedure SynchronizeFileTime(const fn1,fn2:string);
  733. var
  734. f : file;
  735. l : longint;
  736. begin
  737. Assign(f,fn1);
  738. {$I-}
  739. reset(f,1);
  740. {$I+}
  741. if ioresult=0 then
  742. begin
  743. getftime(f,l);
  744. { just to be sure in case there are rounding errors }
  745. setftime(f,l);
  746. close(f);
  747. assign(f,fn2);
  748. {$I-}
  749. reset(f,1);
  750. {$I+}
  751. if ioresult=0 then
  752. begin
  753. setftime(f,l);
  754. close(f);
  755. end;
  756. end;
  757. end;
  758. function FindFile(const f : string;path : string;var b : boolean) : string;
  759. Var
  760. singlepathstring : string;
  761. i : longint;
  762. begin
  763. {$ifdef unix}
  764. for i:=1 to length(path) do
  765. if path[i]=':' then
  766. path[i]:=';';
  767. {$endif}
  768. b:=false;
  769. FindFile:='';
  770. repeat
  771. i:=pos(';',path);
  772. if i=0 then
  773. i:=256;
  774. singlepathstring:=FixPath(copy(path,1,i-1),false);
  775. delete(path,1,i);
  776. If FileExists (singlepathstring+f) then
  777. begin
  778. FindFile:=singlepathstring;
  779. b:=true;
  780. exit;
  781. end;
  782. until path='';
  783. end;
  784. function FindExe(bin:string;var found:boolean):string;
  785. begin
  786. bin:=FixFileName(bin)+source_os.exeext;
  787. {$ifdef delphi}
  788. FindExe:=FindFile(bin,'.;'+exepath+';'+dmisc.getenv('PATH'),found)+bin;
  789. {$else delphi}
  790. FindExe:=FindFile(bin,'.;'+exepath+';'+dos.getenv('PATH'),found)+bin;
  791. {$endif delphi}
  792. end;
  793. function GetShortName(const n:string):string;
  794. {$ifdef win32}
  795. var
  796. hs,hs2 : string;
  797. i : longint;
  798. {$endif}
  799. {$ifdef go32v2}
  800. var
  801. hs : string;
  802. {$endif}
  803. begin
  804. GetShortName:=n;
  805. {$ifdef win32}
  806. hs:=n+#0;
  807. i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));
  808. if (i>0) and (i<=high(hs2)) then
  809. begin
  810. hs2[0]:=chr(strlen(@hs2[1]));
  811. GetShortName:=hs2;
  812. end;
  813. {$endif}
  814. {$ifdef go32v2}
  815. hs:=n;
  816. if Dos.GetShortName(hs) then
  817. GetShortName:=hs;
  818. {$endif}
  819. end;
  820. {****************************************************************************
  821. OS Dependent things
  822. ****************************************************************************}
  823. function GetEnvPChar(const envname:string):pchar;
  824. {$ifdef win32}
  825. var
  826. s : string;
  827. i,len : longint;
  828. hp,p,p2 : pchar;
  829. {$endif}
  830. begin
  831. {$ifdef unix}
  832. GetEnvPchar:=Linux.Getenv(envname);
  833. {$define GETENVOK}
  834. {$endif}
  835. {$ifdef win32}
  836. GetEnvPchar:=nil;
  837. p:=GetEnvironmentStrings;
  838. hp:=p;
  839. while hp^<>#0 do
  840. begin
  841. s:=strpas(hp);
  842. i:=pos('=',s);
  843. len:=strlen(hp);
  844. if upper(copy(s,1,i-1))=upper(envname) then
  845. begin
  846. GetMem(p2,len-length(envname));
  847. Move(hp[i],p2^,len-length(envname));
  848. GetEnvPchar:=p2;
  849. break;
  850. end;
  851. { next string entry}
  852. hp:=hp+len+1;
  853. end;
  854. FreeEnvironmentStrings(p);
  855. {$define GETENVOK}
  856. {$endif}
  857. {$ifdef GETENVOK}
  858. {$undef GETENVOK}
  859. {$else}
  860. GetEnvPchar:=StrPNew(Dos.Getenv(envname));
  861. {$endif}
  862. end;
  863. procedure FreeEnvPChar(p:pchar);
  864. begin
  865. {$ifndef unix}
  866. StrDispose(p);
  867. {$endif}
  868. end;
  869. Procedure Shell(const command:string);
  870. { This is already defined in the linux.ppu for linux, need for the *
  871. expansion under linux }
  872. {$ifdef unix}
  873. begin
  874. Linux.Shell(command);
  875. end;
  876. {$else}
  877. var
  878. comspec : string;
  879. begin
  880. comspec:=getenv('COMSPEC');
  881. Exec(comspec,' /C '+command);
  882. end;
  883. {$endif}
  884. Function SetCompileMode(const s:string; changeInit: boolean):boolean;
  885. var
  886. b : boolean;
  887. begin
  888. b:=true;
  889. if s='DEFAULT' then
  890. aktmodeswitches:=initmodeswitches
  891. else
  892. if s='DELPHI' then
  893. aktmodeswitches:=delphimodeswitches
  894. else
  895. if s='TP' then
  896. aktmodeswitches:=tpmodeswitches
  897. else
  898. if s='FPC' then
  899. aktmodeswitches:=fpcmodeswitches
  900. else
  901. if s='OBJFPC' then
  902. aktmodeswitches:=objfpcmodeswitches
  903. else
  904. if s='GPC' then
  905. aktmodeswitches:=gpcmodeswitches
  906. else
  907. b:=false;
  908. if b and changeInit then
  909. initmodeswitches := aktmodeswitches;
  910. if b then
  911. begin
  912. { turn ansistrings on by default ? }
  913. if (m_default_ansistring in aktmodeswitches) then
  914. begin
  915. include(aktlocalswitches,cs_ansistrings);
  916. if changeinit then
  917. include(initlocalswitches,cs_ansistrings);
  918. end
  919. else
  920. begin
  921. exclude(aktlocalswitches,cs_ansistrings);
  922. if changeinit then
  923. exclude(initlocalswitches,cs_ansistrings);
  924. end;
  925. end;
  926. SetCompileMode:=b;
  927. end;
  928. { '('D1:'00000000-'D2:'0000-'D3:'0000-'D4:'0000-000000000000)' }
  929. function string2guid(const s: string; var GUID: TGUID): boolean;
  930. function ishexstr(const hs: string): boolean;
  931. var
  932. i: integer;
  933. begin
  934. ishexstr:=false;
  935. for i:=1 to Length(hs) do begin
  936. if not (hs[i] in ['0'..'9','A'..'F','a'..'f']) then
  937. exit;
  938. end;
  939. ishexstr:=true;
  940. end;
  941. function hexstr2longint(const hexs: string): longint;
  942. var
  943. i: integer;
  944. rl: longint;
  945. begin
  946. rl:=0;
  947. for i:=1 to length(hexs) do begin
  948. rl:=rl shl 4;
  949. case hexs[i] of
  950. '0'..'9' : inc(rl,ord(hexs[i])-ord('0'));
  951. 'A'..'F' : inc(rl,ord(hexs[i])-ord('A')+10);
  952. 'a'..'f' : inc(rl,ord(hexs[i])-ord('a')+10);
  953. end
  954. end;
  955. hexstr2longint:=rl;
  956. end;
  957. var
  958. i: integer;
  959. begin
  960. if (Length(s)=38) and (s[1]='{') and (s[38]='}') and
  961. (s[10]='-') and (s[15]='-') and (s[20]='-') and (s[25]='-') and
  962. ishexstr(copy(s,2,8)) and ishexstr(copy(s,11,4)) and
  963. ishexstr(copy(s,16,4)) and ishexstr(copy(s,21,4)) and
  964. ishexstr(copy(s,26,12)) then begin
  965. GUID.D1:=hexstr2longint(copy(s,2,8));
  966. GUID.D2:=hexstr2longint(copy(s,11,4));
  967. GUID.D3:=hexstr2longint(copy(s,16,4));
  968. for i:=0 to 1 do
  969. GUID.D4[i]:=hexstr2longint(copy(s,21+i*2,2));
  970. for i:=2 to 7 do
  971. GUID.D4[i]:=hexstr2longint(copy(s,22+i*2,2));
  972. string2guid:=true;
  973. end
  974. else
  975. string2guid:=false;
  976. end;
  977. function guid2string(const GUID: TGUID): string;
  978. function long2hex(l, len: longint): string;
  979. const
  980. hextbl: array[0..15] of char = '0123456789ABCDEF';
  981. var
  982. rs: string;
  983. i: integer;
  984. begin
  985. rs[0]:=chr(len);
  986. for i:=len downto 1 do begin
  987. rs[i]:=hextbl[l and $F];
  988. l:=l shr 4;
  989. end;
  990. long2hex:=rs;
  991. end;
  992. begin
  993. guid2string:=
  994. '{'+long2hex(GUID.D1,8)+
  995. '-'+long2hex(GUID.D2,4)+
  996. '-'+long2hex(GUID.D3,4)+
  997. '-'+long2hex(GUID.D4[0],2)+long2hex(GUID.D4[1],2)+
  998. '-'+long2hex(GUID.D4[2],2)+long2hex(GUID.D4[3],2)+
  999. long2hex(GUID.D4[4],2)+long2hex(GUID.D4[5],2)+
  1000. long2hex(GUID.D4[6],2)+long2hex(GUID.D4[7],2)+
  1001. '}';
  1002. end;
  1003. {****************************************************************************
  1004. Init
  1005. ****************************************************************************}
  1006. {$ifdef unix}
  1007. {$define need_path_search}
  1008. {$endif unix}
  1009. {$ifdef os2}
  1010. {$define need_path_search}
  1011. {$endif os2}
  1012. procedure get_exepath;
  1013. var
  1014. hs1 : namestr;
  1015. hs2 : extstr;
  1016. {$ifdef need_path_search}
  1017. b : boolean;
  1018. {$endif}
  1019. begin
  1020. {$ifdef delphi}
  1021. exepath:=dmisc.getenv('PPC_EXEC_PATH');
  1022. {$else delphi}
  1023. exepath:=dos.getenv('PPC_EXEC_PATH');
  1024. {$endif delphi}
  1025. if exepath='' then
  1026. fsplit(FixFileName(paramstr(0)),exepath,hs1,hs2);
  1027. {$ifdef need_path_search}
  1028. if exepath='' then
  1029. begin
  1030. if pos(source_os.exeext,hs1) <>
  1031. (length(hs1) - length(source_os.exeext)+1) then
  1032. hs1 := hs1 + source_os.exeext;
  1033. {$ifdef delphi}
  1034. exepath := findfile(hs1,dmisc.getenv('PATH'),b);
  1035. {$else delphi}
  1036. exepath := findfile(hs1,dos.getenv('PATH'),b);
  1037. {$endif delphi}
  1038. end;
  1039. {$endif need_path_search}
  1040. exepath:=FixPath(exepath,false);
  1041. end;
  1042. procedure DoneGlobals;
  1043. begin
  1044. initdefines.done;
  1045. if assigned(DLLImageBase) then
  1046. StringDispose(DLLImageBase);
  1047. RelocSection:=true;
  1048. RelocSectionSetExplicitly:=false;
  1049. UseDeffileForExport:=true;
  1050. librarysearchpath.Done;
  1051. unitsearchpath.Done;
  1052. objectsearchpath.Done;
  1053. includesearchpath.Done;
  1054. end;
  1055. procedure InitGlobals;
  1056. begin
  1057. { set global switches }
  1058. do_build:=false;
  1059. do_make:=true;
  1060. compile_level:=0;
  1061. { these two should not be cleared in
  1062. DoneGlobals as the IDE might need their value }
  1063. IsExe:=false;
  1064. DLLsource:=false;
  1065. { Output }
  1066. OutputFile:='';
  1067. OutputExeDir:='';
  1068. OutputUnitDir:='';
  1069. { Utils directory }
  1070. utilsdirectory:='';
  1071. { Search Paths }
  1072. librarysearchpath.Init;
  1073. unitsearchpath.Init;
  1074. includesearchpath.Init;
  1075. objectsearchpath.Init;
  1076. { Def file }
  1077. usewindowapi:=false;
  1078. description:='Compiled by FPC '+version_string+' - '+target_cpu_string;
  1079. dllversion:='';
  1080. { Init values }
  1081. initmodeswitches:=fpcmodeswitches;
  1082. initlocalswitches:=[cs_check_io];
  1083. initmoduleswitches:=[cs_extsyntax,cs_browser];
  1084. initglobalswitches:=[cs_check_unit_name,cs_link_static];
  1085. {$ifdef i386}
  1086. initoptprocessor:=Class386;
  1087. initspecificoptprocessor:=Class386;
  1088. initpackenum:=4;
  1089. {$IFDEF testvarsets}
  1090. initsetalloc:=0;
  1091. {$ENDIF}
  1092. initpackrecords:=packrecord_2;
  1093. initoutputformat:=target_asm.id;
  1094. initasmmode:=asmmode_i386_att;
  1095. {$else not i386}
  1096. {$ifdef m68k}
  1097. initoptprocessor:=MC68000;
  1098. include(initmoduleswitches,cs_fp_emulation);
  1099. initpackenum:=4;
  1100. {$IFDEF testvarsets}
  1101. initsetalloc:=0;
  1102. {$ENDIF}
  1103. initpackrecords:=packrecord_2;
  1104. initoutputformat:=as_m68k_as;
  1105. initasmmode:=asmmode_m68k_mot;
  1106. {$endif m68k}
  1107. {$endif i386}
  1108. initinterfacetype:=it_interfacecom;
  1109. initdefines.init;
  1110. { memory sizes, will be overriden by parameter or default for target
  1111. in options or init_parser }
  1112. stacksize:=0;
  1113. heapsize:=0;
  1114. maxheapsize:=0;
  1115. { compile state }
  1116. in_args:=false;
  1117. { must_be_valid:=true; obsolete PM }
  1118. not_unit_proc:=true;
  1119. apptype:=app_cui;
  1120. end;
  1121. begin
  1122. get_exepath;
  1123. {$ifdef EXTDEBUG}
  1124. {$ifdef FPC}
  1125. EntryMemUsed:=system.HeapSize-MemAvail;
  1126. {$endif FPC}
  1127. {$endif}
  1128. end.
  1129. {
  1130. $Log$
  1131. Revision 1.20 2000-11-13 15:26:12 marco
  1132. * Renamefest
  1133. Revision 1.19 2000/11/12 22:20:37 peter
  1134. * create generic toutputsection for binary writers
  1135. Revision 1.18 2000/11/04 14:25:19 florian
  1136. + merged Attila's changes for interfaces, not tested yet
  1137. Revision 1.17 2000/10/31 22:02:46 peter
  1138. * symtable splitted, no real code changes
  1139. Revision 1.16 2000/10/04 14:51:08 pierre
  1140. * IsExe restored
  1141. Revision 1.15 2000/09/27 21:20:56 peter
  1142. * also set initlocalswitches in setcompilemode (merged)
  1143. Revision 1.14 2000/09/26 10:50:41 jonas
  1144. * initmodeswitches is changed is you change the compiler mode from the
  1145. command line (the -S<x> switches didn't work anymore for changing the
  1146. compiler mode) (merged from fixes branch)
  1147. Revision 1.13 2000/09/24 21:33:46 peter
  1148. * message updates merges
  1149. Revision 1.12 2000/09/24 21:19:50 peter
  1150. * delphi compile fixes
  1151. Revision 1.11 2000/09/24 15:12:40 peter
  1152. * fixed typo
  1153. Revision 1.10 2000/09/24 15:06:16 peter
  1154. * use defines.inc
  1155. Revision 1.9 2000/09/24 10:33:07 peter
  1156. * searching of exe in path also for OS/2
  1157. * fixed searching of exe in path.
  1158. Revision 1.8 2000/09/11 17:00:22 florian
  1159. + first implementation of Netware Module support, thanks to
  1160. Armin Diehl ([email protected]) for providing the patches
  1161. Revision 1.7 2000/08/27 16:11:51 peter
  1162. * moved some util functions from globals,cobjects to cutils
  1163. * splitted files into finput,fmodule
  1164. Revision 1.6 2000/08/12 19:14:58 peter
  1165. * ELF writer works now also with -g
  1166. * ELF writer is default again for linux
  1167. Revision 1.5 2000/08/12 15:30:44 peter
  1168. * IDE patch for stream reading (merged)
  1169. Revision 1.4 2000/08/02 19:49:59 peter
  1170. * first things for default parameters
  1171. Revision 1.3 2000/07/13 12:08:25 michael
  1172. + patched to 1.1.0 with former 1.09patch from peter
  1173. Revision 1.2 2000/07/13 11:32:41 michael
  1174. + removed logs
  1175. }