globals.pas 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. {
  2. $Id$
  3. Copyright (C) 1993-98 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. {$ifdef tp}
  19. {$E+,N+}
  20. {$endif}
  21. unit globals;
  22. interface
  23. uses
  24. {$ifdef Delphi4}
  25. dmisc,
  26. sysutils,
  27. {$else}
  28. strings,dos,
  29. {$endif}
  30. {$ifdef linux}
  31. {$ifdef TP}
  32. objects,
  33. {$endif}
  34. linux,
  35. {$endif}
  36. globtype,version,tokens,systems,cobjects;
  37. const
  38. {$ifdef linux}
  39. DirSep = '/';
  40. {$else}
  41. {$ifdef amiga}
  42. DirSep = '/';
  43. {$else}
  44. DirSep = '\';
  45. {$endif}
  46. {$endif}
  47. {$ifdef Splitheap}
  48. testsplit : boolean = false;
  49. {$endif Splitheap}
  50. delphimodeswitches : tmodeswitches=
  51. [m_delphi,m_tp,m_all,m_class,m_objpas,m_result,m_string_pchar,
  52. m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal];
  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];
  59. tpmodeswitches : tmodeswitches=
  60. [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. { directory where the utils can be found (options -FD) }
  83. utilsdirectory : dirstr;
  84. { some flags for global compiler switches }
  85. do_build,
  86. do_make : boolean;
  87. not_unit_proc : boolean;
  88. { path for searching units, different paths can be seperated by ; }
  89. exepath : dirstr; { Path to ppc }
  90. librarysearchpath,
  91. unitsearchpath,
  92. objectsearchpath,
  93. includesearchpath : TSearchPathList;
  94. { deffile }
  95. usewindowapi : boolean;
  96. description : string;
  97. { current position }
  98. token, { current token being parsed }
  99. idtoken : ttoken; { holds the token if the pattern is a known word }
  100. tokenpos, { last postion of the read 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. compile_level : word;
  110. make_ref : boolean;
  111. resolving_forward : boolean; { used to add forward reference as second ref }
  112. use_esp_stackframe : boolean; { to test for call with ESP as stack frame }
  113. {$ifdef TP}
  114. use_big : boolean;
  115. {$endif}
  116. { commandline values }
  117. initdefines : tlinkedlist;
  118. initglobalswitches : tglobalswitches;
  119. initmoduleswitches : tmoduleswitches;
  120. initlocalswitches : tlocalswitches;
  121. initmodeswitches : tmodeswitches;
  122. initpackenum : longint;
  123. initpackrecords : tpackrecords;
  124. initoutputformat : tasm;
  125. initoptprocessor : tprocessors;
  126. initasmmode : tasmmode;
  127. { current state values }
  128. aktglobalswitches : tglobalswitches;
  129. aktmoduleswitches : tmoduleswitches;
  130. aktlocalswitches : tlocalswitches;
  131. aktmodeswitches : tmodeswitches;
  132. aktpackenum : longint;
  133. aktpackrecords : tpackrecords;
  134. aktoutputformat : tasm;
  135. aktoptprocessor : tprocessors;
  136. aktasmmode : tasmmode;
  137. { Memory sizes }
  138. heapsize,
  139. maxheapsize,
  140. stacksize : longint;
  141. {$Ifdef EXTDEBUG}
  142. total_of_firstpass,
  143. firstpass_several : longint;
  144. {$ifdef FPC}
  145. EntryMemUsed : longint;
  146. {$endif FPC}
  147. { parameter switches }
  148. debugstop,
  149. only_one_pass : boolean;
  150. {$EndIf EXTDEBUG}
  151. { windows application type }
  152. apptype : tapptype;
  153. const
  154. RelocSection : boolean = true;
  155. DLLsource : boolean = false;
  156. DLLImageBase : pstring = nil;
  157. { used to set all registers used for each global function
  158. this should dramatically decrease the number of
  159. recompilations needed PM }
  160. simplify_ppu : boolean = false;
  161. { should we allow non static members ? }
  162. allow_only_static : boolean = false;
  163. Inside_asm_statement : boolean = false;
  164. { for error info in pp.pas }
  165. const
  166. parser_current_file : string = '';
  167. {$ifdef debug}
  168. { if the pointer don't point to the heap then write an error }
  169. function assigned(p : pointer) : boolean;
  170. {$endif}
  171. function min(a,b : longint) : longint;
  172. function max(a,b : longint) : longint;
  173. function align(i,a:longint):longint;
  174. procedure Replace(var s:string;s1:string;const s2:string);
  175. procedure ReplaceCase(var s:string;const s1,s2:string);
  176. function upper(const s : string) : string;
  177. function lower(const s : string) : string;
  178. function trimspace(const s:string):string;
  179. {$ifdef FPC}
  180. function tostru(i:cardinal) : string;
  181. {$else}
  182. function tostru(i:longint) : string;
  183. {$endif}
  184. procedure uppervar(var s : string);
  185. function tostr(i : longint) : string;
  186. function tostr_with_plus(i : longint) : string;
  187. procedure valint(S : string;var V : longint;var code : integer);
  188. function is_number(const s : string) : boolean;
  189. function ispowerof2(value : longint;var power : longint) : boolean;
  190. { enable ansistring comparison }
  191. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  192. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  193. function bstoslash(const s : string) : string;
  194. procedure abstract;
  195. function getdatestr:string;
  196. function gettimestr:string;
  197. function filetimestring( t : longint) : string;
  198. procedure DefaultReplacements(var s:string);
  199. function path_absolute(const s : string) : boolean;
  200. Function FileExists ( Const F : String) : Boolean;
  201. Function RemoveFile(const f:string):boolean;
  202. Function RemoveDir(d:string):boolean;
  203. Function GetFileTime ( Var F : File) : Longint;
  204. Function GetNamedFileTime ( Const F : String) : Longint;
  205. Function SplitFileName(const s:string):string;
  206. Function SplitName(const s:string):string;
  207. Function SplitExtension(Const HStr:String):String;
  208. Function AddExtension(Const HStr,ext:String):String;
  209. Function ForceExtension(Const HStr,ext:String):String;
  210. Function FixPath(s:string;allowdot:boolean):string;
  211. function FixFileName(const s:string):string;
  212. procedure SplitBinCmd(const s:string;var bstr,cstr:string);
  213. procedure SynchronizeFileTime(const fn1,fn2:string);
  214. function FindFile(const f : string;path : string;var b : boolean) : string;
  215. function FindExe(bin:string;var found:boolean):string;
  216. Procedure Shell(const command:string);
  217. procedure InitGlobals;
  218. procedure DoneGlobals;
  219. procedure strdispose(var p : pchar);
  220. implementation
  221. uses
  222. comphook;
  223. procedure strdispose(var p : pchar);
  224. begin
  225. if assigned(p) then
  226. begin
  227. freemem(p,strlen(p)+1);
  228. p:=nil;
  229. end;
  230. end;
  231. function ngraphsearchvalue(const s1,s2 : string) : double;
  232. const
  233. n = 3;
  234. var
  235. equals,i,j : longint;
  236. hs : string;
  237. begin
  238. equals:=0;
  239. { is the string long enough ? }
  240. if min(length(s1),length(s2))-n+1<1 then
  241. begin
  242. ngraphsearchvalue:=0.0;
  243. exit;
  244. end;
  245. for i:=1 to length(s1)-n+1 do
  246. begin
  247. hs:=copy(s1,i,n);
  248. for j:=1 to length(s2)-n+1 do
  249. if hs=copy(s2,j,n) then
  250. inc(equals);
  251. end;
  252. {$ifdef fpc}
  253. ngraphsearchvalue:=equals/double(max(length(s1),length(s2))-n+1);
  254. {$else}
  255. ngraphsearchvalue:=equals/(max(length(s1),length(s2))-n+1);
  256. {$endif}
  257. end;
  258. function bstoslash(const s : string) : string;
  259. {
  260. return string s with all \ changed into /
  261. }
  262. var
  263. i : longint;
  264. begin
  265. for i:=1to length(s) do
  266. if s[i]='\' then
  267. bstoslash[i]:='/'
  268. else
  269. bstoslash[i]:=s[i];
  270. {$ifndef TP}
  271. {$ifopt H+}
  272. setlength(bstoslash,length(s));
  273. {$else}
  274. bstoslash[0]:=s[0];
  275. {$endif}
  276. {$else}
  277. bstoslash[0]:=s[0];
  278. {$endif}
  279. end;
  280. {$ifdef debug}
  281. function assigned(p : pointer) : boolean;
  282. type
  283. ptrrec = record
  284. ofs,seg : word;
  285. end;
  286. {$ifndef FPC}
  287. {$ifndef DPMI}
  288. var
  289. lp : longint;
  290. {$endif DPMI}
  291. {$endif FPC}
  292. begin
  293. {$ifdef FPC}
  294. { Assigned is used for procvar and
  295. stack stored temp records !! PM }
  296. (* if (p<>nil) {and
  297. ((p<heaporg) or
  298. (p>heapptr))} then
  299. do_internalerror(230); *)
  300. {$else}
  301. {$ifdef DPMI}
  302. assigned:=(p<>nil);
  303. exit;
  304. {$else DPMI}
  305. if p=nil then
  306. lp:=0
  307. else
  308. lp:=longint(ptrrec(p).seg)*16+longint(ptrrec(p).ofs);
  309. if (lp<>0) and
  310. ((lp<longint(seg(heaporg^))*16+longint(ofs(heaporg^))) or
  311. (lp>longint(seg(heapptr^))*16+longint(ofs(heapptr^)))) then
  312. do_internalerror(230);
  313. {$endif DPMI}
  314. {$endif FPC}
  315. assigned:=(p<>nil);
  316. end;
  317. {$endif}
  318. function min(a,b : longint) : longint;
  319. {
  320. return the minimal of a and b
  321. }
  322. begin
  323. if a>b then
  324. min:=b
  325. else
  326. min:=a;
  327. end;
  328. function max(a,b : longint) : longint;
  329. {
  330. return the maximum of a and b
  331. }
  332. begin
  333. if a<b then
  334. max:=b
  335. else
  336. max:=a;
  337. end;
  338. function align(i,a:longint):longint;
  339. {
  340. return value <i> aligned <a> boundary
  341. }
  342. begin
  343. align:=(i+a-1) and not(a-1);
  344. end;
  345. procedure Replace(var s:string;s1:string;const s2:string);
  346. var
  347. last,
  348. i : longint;
  349. begin
  350. s1:=upper(s1);
  351. last:=0;
  352. repeat
  353. i:=pos(s1,upper(s));
  354. if i=last then
  355. i:=0;
  356. if (i>0) then
  357. begin
  358. Delete(s,i,length(s1));
  359. Insert(s2,s,i);
  360. last:=i;
  361. end;
  362. until (i=0);
  363. end;
  364. procedure ReplaceCase(var s:string;const s1,s2:string);
  365. var
  366. last,
  367. i : longint;
  368. begin
  369. last:=0;
  370. repeat
  371. i:=pos(s1,s);
  372. if i=last then
  373. i:=0;
  374. if (i>0) then
  375. begin
  376. Delete(s,i,length(s1));
  377. Insert(s2,s,i);
  378. last:=i;
  379. end;
  380. until (i=0);
  381. end;
  382. function upper(const s : string) : string;
  383. {
  384. return uppercased string of s
  385. }
  386. var
  387. i : longint;
  388. begin
  389. for i:=1 to length(s) do
  390. if s[i] in ['a'..'z'] then
  391. upper[i]:=char(byte(s[i])-32)
  392. else
  393. upper[i]:=s[i];
  394. {$ifdef FPC}
  395. {$ifopt H+}
  396. setlength(upper,length(s));
  397. {$else}
  398. upper[0]:=s[0];
  399. {$endif}
  400. {$else}
  401. upper[0]:=s[0];
  402. {$endif}
  403. end;
  404. function lower(const s : string) : string;
  405. {
  406. return lowercased string of s
  407. }
  408. var
  409. i : longint;
  410. begin
  411. for i:=1 to length(s) do
  412. if s[i] in ['A'..'Z'] then
  413. lower[i]:=char(byte(s[i])+32)
  414. else
  415. lower[i]:=s[i];
  416. {$ifndef TP}
  417. {$ifopt H+}
  418. setlength(lower,length(s));
  419. {$else}
  420. lower[0]:=s[0];
  421. {$endif}
  422. {$else}
  423. lower[0]:=s[0];
  424. {$endif}
  425. end;
  426. procedure uppervar(var s : string);
  427. {
  428. uppercase string s
  429. }
  430. var
  431. i : longint;
  432. begin
  433. for i:=1 to length(s) do
  434. if s[i] in ['a'..'z'] then
  435. s[i]:=char(byte(s[i])-32);
  436. end;
  437. {$ifdef FPC}
  438. function tostru(i:cardinal):string;
  439. {
  440. return string of value i, but for cardinals
  441. }
  442. var hs:string;
  443. begin
  444. str(i,hs);
  445. tostru:=hs;
  446. end;
  447. {$else FPC}
  448. function tostru(i:longint):string;
  449. begin
  450. tostru:=tostr(i);
  451. end;
  452. {$endif FPC}
  453. function trimspace(const s:string):string;
  454. {
  455. return s with all leading and ending spaces and tabs removed
  456. }
  457. var
  458. i,j : longint;
  459. begin
  460. i:=length(s);
  461. while (i>0) and (s[i] in [#9,' ']) do
  462. dec(i);
  463. j:=1;
  464. while (j<i) and (s[j] in [#9,' ']) do
  465. inc(j);
  466. trimspace:=Copy(s,j,i-j+1);
  467. end;
  468. function tostr(i : longint) : string;
  469. {
  470. return string of value i
  471. }
  472. var
  473. hs : string;
  474. begin
  475. str(i,hs);
  476. tostr:=hs;
  477. end;
  478. function tostr_with_plus(i : longint) : string;
  479. {
  480. return string of value i, but always include a + when i>=0
  481. }
  482. var
  483. hs : string;
  484. begin
  485. str(i,hs);
  486. if i>=0 then
  487. tostr_with_plus:='+'+hs
  488. else
  489. tostr_with_plus:=hs;
  490. end;
  491. procedure valint(S : string;var V : longint;var code : integer);
  492. {
  493. val() with support for octal, which is not supported under tp7
  494. }
  495. {$ifndef FPC}
  496. var
  497. vs : longint;
  498. c : byte;
  499. begin
  500. if s[1]='%' then
  501. begin
  502. vs:=0;
  503. longint(v):=0;
  504. for c:=2 to length(s) do
  505. begin
  506. if s[c]='0' then
  507. vs:=vs shl 1
  508. else
  509. if s[c]='1' then
  510. vs:=vs shl 1+1
  511. else
  512. begin
  513. code:=c;
  514. exit;
  515. end;
  516. end;
  517. code:=0;
  518. longint(v):=vs;
  519. end
  520. else
  521. system.val(S,V,code);
  522. end;
  523. {$else not FPC}
  524. begin
  525. system.val(S,V,code);
  526. end;
  527. {$endif not FPC}
  528. function is_number(const s : string) : boolean;
  529. {
  530. is string a correct number ?
  531. }
  532. var
  533. w : integer;
  534. l : longint;
  535. begin
  536. valint(s,l,w);
  537. is_number:=(w=0);
  538. end;
  539. function ispowerof2(value : longint;var power : longint) : boolean;
  540. {
  541. return if value is a power of 2. And if correct return the power
  542. }
  543. var
  544. hl : longint;
  545. i : longint;
  546. begin
  547. hl:=1;
  548. ispowerof2:=true;
  549. for i:=0 to 31 do
  550. begin
  551. if hl=value then
  552. begin
  553. power:=i;
  554. exit;
  555. end;
  556. hl:=hl shl 1;
  557. end;
  558. ispowerof2:=false;
  559. end;
  560. { enable ansistring comparison }
  561. { 0 means equal }
  562. { 1 means p1 > p2 }
  563. { -1 means p1 < p2 }
  564. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  565. var
  566. i,j : longint;
  567. begin
  568. compareansistrings:=0;
  569. j:=min(length1,length2);
  570. i:=0;
  571. while (i<j) do
  572. begin
  573. if p1[i]>p2[i] then
  574. begin
  575. compareansistrings:=1;
  576. exit;
  577. end
  578. else
  579. if p1[i]<p2[i] then
  580. begin
  581. compareansistrings:=-1;
  582. exit;
  583. end;
  584. inc(i);
  585. end;
  586. if length1>length2 then
  587. compareansistrings:=1
  588. else
  589. if length1<length2 then
  590. compareansistrings:=-1;
  591. end;
  592. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  593. var
  594. p : pchar;
  595. begin
  596. getmem(p,length1+length2+1);
  597. move(p1[0],p[0],length1);
  598. move(p2[0],p[length1],length2+1);
  599. concatansistrings:=p;
  600. end;
  601. {****************************************************************************
  602. Time Handling
  603. ****************************************************************************}
  604. Function L0(l:longint):string;
  605. {
  606. return the string of value l, if l<10 then insert a zero, so
  607. the string is always at least 2 chars '01','02',etc
  608. }
  609. var
  610. s : string;
  611. begin
  612. Str(l,s);
  613. if l<10 then
  614. s:='0'+s;
  615. L0:=s;
  616. end;
  617. function gettimestr:string;
  618. {
  619. get the current time in a string HH:MM:SS
  620. }
  621. var
  622. hour,min,sec,hsec : word;
  623. begin
  624. {$ifdef delphi}
  625. dmisc.gettime(hour,min,sec,hsec);
  626. {$else delphi}
  627. dos.gettime(hour,min,sec,hsec);
  628. {$endif delphi}
  629. gettimestr:=L0(Hour)+':'+L0(min)+':'+L0(sec);
  630. end;
  631. function getdatestr:string;
  632. {
  633. get the current date in a string YY/MM/DD
  634. }
  635. var
  636. Year,Month,Day,Wday : Word;
  637. begin
  638. {$ifdef delphi}
  639. dmisc.getdate(year,month,day,wday);
  640. {$else}
  641. dos.getdate(year,month,day,wday);
  642. {$endif}
  643. getdatestr:=L0(Year)+'/'+L0(Month)+'/'+L0(Day);
  644. end;
  645. function filetimestring( t : longint) : string;
  646. {
  647. convert dos datetime t to a string YY/MM/DD HH:MM:SS
  648. }
  649. var
  650. {$ifndef linux}
  651. DT : DateTime;
  652. {$endif}
  653. Year,Month,Day,Hour,Min,Sec : Word;
  654. begin
  655. if t=-1 then
  656. begin
  657. FileTimeString:='Not Found';
  658. exit;
  659. end;
  660. {$ifndef linux}
  661. unpacktime(t,DT);
  662. Year:=dT.year;month:=dt.month;day:=dt.day;
  663. Hour:=dt.hour;min:=dt.min;sec:=dt.sec;
  664. {$else}
  665. EpochToLocal (t,year,month,day,hour,min,sec);
  666. {$endif}
  667. filetimestring:=L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
  668. end;
  669. {****************************************************************************
  670. Default Macro Handling
  671. ****************************************************************************}
  672. procedure DefaultReplacements(var s:string);
  673. begin
  674. { Replace some macro's }
  675. Replace(s,'$FPCVER',full_version_string);
  676. Replace(s,'$FPCDATE',date_string);
  677. Replace(s,'$FPCTARGET',target_cpu_string);
  678. Replace(s,'$FPCCPU',target_cpu_string);
  679. Replace(s,'$TARGET',target_path);
  680. Replace(s,'$FPCOS',target_path);
  681. end;
  682. {****************************************************************************
  683. File Handling
  684. ****************************************************************************}
  685. function path_absolute(const s : string) : boolean;
  686. {
  687. is path s an absolute path?
  688. }
  689. begin
  690. path_absolute:=false;
  691. {$ifdef linux}
  692. if (length(s)>0) and (s[1]='/') then
  693. path_absolute:=true;
  694. {$else linux}
  695. {$ifdef amiga}
  696. if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or (Pos(':',s) = length(s)) then
  697. path_absolute:=true;
  698. {$else}
  699. if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or
  700. ((length(s)>2) and (s[2]=':') and ((s[3]='\') or (s[3]='/'))) then
  701. path_absolute:=true;
  702. {$endif amiga}
  703. {$endif linux}
  704. end;
  705. {$ifndef FPC}
  706. Procedure FindClose(var Info : SearchRec);
  707. Begin
  708. End;
  709. {$endif not FPC}
  710. {$ifdef delphi}
  711. Function FileExists ( Const F : String) : Boolean;
  712. begin
  713. FileExists:=sysutils.FileExists(f);
  714. end;
  715. {$else}
  716. Function FileExists ( Const F : String) : Boolean;
  717. Var
  718. {$ifdef linux}
  719. Info : Stat;
  720. {$else}
  721. Info : SearchRec;
  722. {$endif}
  723. begin
  724. {$ifdef linux}
  725. FileExists:=FStat(F,info);
  726. {$else}
  727. findfirst(F,readonly+archive+hidden,info);
  728. FileExists:=(doserror=0);
  729. findclose(Info);
  730. {$endif}
  731. end;
  732. {$endif}
  733. Function RemoveFile(const f:string):boolean;
  734. var
  735. g : file;
  736. begin
  737. assign(g,f);
  738. {$I-}
  739. erase(g);
  740. {$I+}
  741. RemoveFile:=(ioresult=0);
  742. end;
  743. Function RemoveDir(d:string):boolean;
  744. begin
  745. if d[length(d)]=DirSep then
  746. Delete(d,length(d),1);
  747. {$I-}
  748. rmdir(d);
  749. {$I+}
  750. RemoveDir:=(ioresult=0);
  751. end;
  752. Function SplitFileName(const s:string):string;
  753. var
  754. p : dirstr;
  755. n : namestr;
  756. e : extstr;
  757. begin
  758. FSplit(s,p,n,e);
  759. SplitFileName:=n+e;
  760. end;
  761. Function SplitName(const s:string):string;
  762. var
  763. i,j : longint;
  764. begin
  765. i:=Length(s);
  766. j:=Length(s);
  767. while (i>0) and not(s[i] in ['/','\']) do
  768. dec(i);
  769. while (j>0) and (s[j]<>'.') do
  770. dec(j);
  771. if j<=i then
  772. j:=255;
  773. SplitName:=Copy(s,i+1,j-(i+1));
  774. end;
  775. Function SplitExtension(Const HStr:String):String;
  776. var
  777. j : longint;
  778. begin
  779. j:=length(Hstr);
  780. while (j>0) and (Hstr[j]<>'.') do
  781. begin
  782. if hstr[j]=DirSep then
  783. j:=0
  784. else
  785. dec(j);
  786. end;
  787. if j=0 then
  788. j:=254;
  789. SplitExtension:=Copy(Hstr,j,255);
  790. end;
  791. Function AddExtension(Const HStr,ext:String):String;
  792. begin
  793. if (Ext<>'') and (SplitExtension(HStr)='') then
  794. AddExtension:=Hstr+Ext
  795. else
  796. AddExtension:=Hstr;
  797. end;
  798. Function ForceExtension(Const HStr,ext:String):String;
  799. var
  800. j : longint;
  801. begin
  802. j:=length(Hstr);
  803. while (j>0) and (Hstr[j]<>'.') do
  804. dec(j);
  805. if j=0 then
  806. j:=255;
  807. ForceExtension:=Copy(Hstr,1,j-1)+Ext;
  808. end;
  809. Function FixPath(s:string;allowdot:boolean):string;
  810. var
  811. i : longint;
  812. begin
  813. { Fix separator }
  814. for i:=1 to length(s) do
  815. if s[i] in ['/','\'] then
  816. s[i]:=DirSep;
  817. { Fix ending / }
  818. if (length(s)>0) and (s[length(s)]<>DirSep) and
  819. (s[length(s)]<>':') then
  820. s:=s+DirSep;
  821. { Remove ./ }
  822. if (not allowdot) and (s='.'+DirSep) then
  823. s:='';
  824. { return }
  825. FixPath:=s;
  826. end;
  827. function FixFileName(const s:string):string;
  828. var
  829. i : longint;
  830. NoPath : boolean;
  831. begin
  832. NoPath:=true;
  833. for i:=length(s) downto 1 do
  834. begin
  835. case s[i] of
  836. {$ifdef Linux}
  837. '/','\' : begin
  838. FixFileName[i]:='/';
  839. NoPath:=false; {Skip lowercasing path: 'X11'<>'x11' }
  840. end;
  841. 'A'..'Z' : if NoPath then
  842. FixFileName[i]:=char(byte(s[i])+32)
  843. else
  844. FixFileName[i]:=s[i];
  845. {$else}
  846. '/' : FixFileName[i]:='\';
  847. 'A'..'Z' : FixFileName[i]:=char(byte(s[i])+32);
  848. {$endif}
  849. else
  850. FixFileName[i]:=s[i];
  851. end;
  852. end;
  853. {$ifndef TP}
  854. {$ifopt H+}
  855. SetLength(FixFileName,length(s));
  856. {$else}
  857. FixFileName[0]:=s[0];
  858. {$endif}
  859. {$else}
  860. FixFileName[0]:=s[0];
  861. {$endif}
  862. end;
  863. procedure SplitBinCmd(const s:string;var bstr,cstr:string);
  864. var
  865. i : longint;
  866. begin
  867. i:=pos(' ',s);
  868. if i>0 then
  869. begin
  870. bstr:=Copy(s,1,i-1);
  871. cstr:=Copy(s,i+1,length(s)-i);
  872. end
  873. else
  874. begin
  875. bstr:='';
  876. cstr:='';
  877. end;
  878. end;
  879. procedure TSearchPathList.AddPath(s:string;addfirst:boolean);
  880. var
  881. j : longint;
  882. CurrentDir,
  883. CurrPath : string;
  884. hp : PStringQueueItem;
  885. begin
  886. if s='' then
  887. exit;
  888. { Support default macro's }
  889. DefaultReplacements(s);
  890. { get current dir }
  891. GetDir(0,CurrentDir);
  892. CurrentDir:=FixPath(CurrentDir,false);
  893. repeat
  894. j:=Pos(';',s);
  895. if j=0 then
  896. j:=255;
  897. {Get Pathname}
  898. CurrPath:=FixPath(Copy(s,1,j-1),false);
  899. if CurrPath='' then
  900. CurrPath:='.'+DirSep
  901. else
  902. begin
  903. CurrPath:=FixPath(FExpand(CurrPath),false);
  904. if (Copy(CurrPath,1,length(CurrentDir))=CurrentDir) then
  905. CurrPath:='.'+DirSep+Copy(CurrPath,length(CurrentDir)+1,255);
  906. end;
  907. System.Delete(s,1,j);
  908. if addfirst then
  909. begin
  910. Delete(currPath);
  911. Insert(currPath);
  912. end
  913. else
  914. begin
  915. { Check if already in path, then we don't add it }
  916. hp:=Find(currPath);
  917. if not assigned(hp) then
  918. Concat(currPath);
  919. end;
  920. until (s='');
  921. end;
  922. procedure TSearchPathList.AddList(list:TSearchPathList;addfirst:boolean);
  923. var
  924. s : string;
  925. hl : TSearchPathList;
  926. hp,hp2 : PStringQueueItem;
  927. begin
  928. if list.empty then
  929. exit;
  930. { create temp and reverse the list }
  931. if addfirst then
  932. begin
  933. hl.Init;
  934. hp:=list.first;
  935. while assigned(hp) do
  936. begin
  937. hl.insert(hp^.data^);
  938. hp:=hp^.next;
  939. end;
  940. while not hl.empty do
  941. begin
  942. s:=hl.Get;
  943. Delete(s);
  944. Insert(s);
  945. end;
  946. hl.done;
  947. end
  948. else
  949. begin
  950. hp:=list.first;
  951. while assigned(hp) do
  952. begin
  953. hp2:=Find(hp^.data^);
  954. { Check if already in path, then we don't add it }
  955. if not assigned(hp2) then
  956. Concat(hp^.data^);
  957. hp:=hp^.next;
  958. end;
  959. end;
  960. end;
  961. function TSearchPathList.FindFile(const f : string;var b : boolean) : string;
  962. Var
  963. p : PStringQueueItem;
  964. begin
  965. FindFile:='';
  966. b:=false;
  967. p:=first;
  968. while assigned(p) do
  969. begin
  970. If FileExists(p^.data^+f) then
  971. begin
  972. FindFile:=p^.data^;
  973. b:=true;
  974. exit;
  975. end;
  976. p:=p^.next;
  977. end;
  978. end;
  979. Function GetFileTime ( Var F : File) : Longint;
  980. Var
  981. {$ifdef linux}
  982. Info : Stat;
  983. {$endif}
  984. L : longint;
  985. begin
  986. {$ifdef linux}
  987. FStat (F,Info);
  988. L:=Info.Mtime;
  989. {$else}
  990. GetFTime(f,l);
  991. {$endif}
  992. GetFileTime:=L;
  993. end;
  994. Function GetNamedFileTime (Const F : String) : Longint;
  995. var
  996. L : Longint;
  997. {$ifndef linux}
  998. info : SearchRec;
  999. {$else}
  1000. info : stat;
  1001. {$endif}
  1002. begin
  1003. l:=-1;
  1004. {$ifdef linux}
  1005. if FStat (F,Info) then
  1006. L:=info.mtime;
  1007. {$else}
  1008. {$ifdef delphi}
  1009. dmisc.FindFirst (F,archive+readonly+hidden,info);
  1010. {$else delphi}
  1011. FindFirst (F,archive+readonly+hidden,info);
  1012. {$endif delphi}
  1013. if DosError=0 then
  1014. l:=info.time;
  1015. {$ifdef Linux}
  1016. FindClose(info);
  1017. {$endif}
  1018. {$ifdef Win32}
  1019. FindClose(info);
  1020. {$endif}
  1021. {$endif}
  1022. GetNamedFileTime:=l;
  1023. end;
  1024. {Touch Assembler and object time to ppu time is there is a ppufilename}
  1025. procedure SynchronizeFileTime(const fn1,fn2:string);
  1026. var
  1027. f : file;
  1028. l : longint;
  1029. begin
  1030. Assign(f,fn1);
  1031. {$I-}
  1032. reset(f,1);
  1033. {$I+}
  1034. if ioresult=0 then
  1035. begin
  1036. getftime(f,l);
  1037. close(f);
  1038. assign(f,fn2);
  1039. {$I-}
  1040. reset(f,1);
  1041. {$I+}
  1042. if ioresult=0 then
  1043. begin
  1044. setftime(f,l);
  1045. close(f);
  1046. end;
  1047. end;
  1048. end;
  1049. function FindFile(const f : string;path : string;var b : boolean) : string;
  1050. Var
  1051. singlepathstring : string;
  1052. i : longint;
  1053. begin
  1054. {$ifdef linux}
  1055. for i:=1 to length(path) do
  1056. if path[i]=':' then
  1057. path[i]:=';';
  1058. {$endif}
  1059. b:=false;
  1060. FindFile:='';
  1061. repeat
  1062. i:=pos(';',path);
  1063. if i=0 then
  1064. i:=255;
  1065. singlepathstring:=FixPath(copy(path,1,i-1),false);
  1066. delete(path,1,i);
  1067. If FileExists (singlepathstring+f) then
  1068. begin
  1069. FindFile:=singlepathstring;
  1070. b:=true;
  1071. exit;
  1072. end;
  1073. until path='';
  1074. end;
  1075. function FindExe(bin:string;var found:boolean):string;
  1076. begin
  1077. bin:=FixFileName(bin)+source_os.exeext;
  1078. {$ifdef delphi}
  1079. FindExe:=FindFile(bin,'.;'+exepath+';'+dmisc.getenv('PATH'),found)+bin;
  1080. {$else delphi}
  1081. FindExe:=FindFile(bin,'.;'+exepath+';'+dos.getenv('PATH'),found)+bin;
  1082. {$endif delphi}
  1083. end;
  1084. procedure abstract;
  1085. begin
  1086. do_internalerror(255);
  1087. end;
  1088. Procedure Shell(const command:string);
  1089. { This is already defined in the linux.ppu for linux, need for the *
  1090. expansion under linux }
  1091. {$ifdef linux}
  1092. begin
  1093. Linux.Shell(command);
  1094. end;
  1095. {$else}
  1096. var
  1097. comspec : string;
  1098. begin
  1099. comspec:=getenv('COMSPEC');
  1100. Exec(comspec,' /C '+command);
  1101. end;
  1102. {$endif}
  1103. {****************************************************************************
  1104. Init
  1105. ****************************************************************************}
  1106. procedure get_exepath;
  1107. var
  1108. hs1 : namestr;
  1109. hs2 : extstr;
  1110. begin
  1111. {$ifdef delphi}
  1112. exepath:=dmisc.getenv('PPC_EXEC_PATH');
  1113. {$else delphi}
  1114. exepath:=dos.getenv('PPC_EXEC_PATH');
  1115. {$endif delphi}
  1116. if exepath='' then
  1117. fsplit(FixFileName(paramstr(0)),exepath,hs1,hs2);
  1118. {$ifdef linux}
  1119. if exepath='' then
  1120. fsearch(hs1,dos.getenv('PATH'));
  1121. {$endif}
  1122. exepath:=FixPath(exepath,false);
  1123. end;
  1124. procedure DoneGlobals;
  1125. begin
  1126. initdefines.done;
  1127. if assigned(DLLImageBase) then
  1128. StringDispose(DLLImageBase);
  1129. librarysearchpath.Done;
  1130. unitsearchpath.Done;
  1131. objectsearchpath.Done;
  1132. includesearchpath.Done;
  1133. end;
  1134. procedure InitGlobals;
  1135. begin
  1136. { set global switches }
  1137. do_build:=false;
  1138. do_make:=true;
  1139. {$ifdef tp}
  1140. use_big:=false;
  1141. {$endif tp}
  1142. { Output }
  1143. OutputFile:='';
  1144. OutputExeDir:='';
  1145. OutputUnitDir:='';
  1146. { Utils directory }
  1147. utilsdirectory:='';
  1148. { Search Paths }
  1149. librarysearchpath.Init;
  1150. unitsearchpath.Init;
  1151. includesearchpath.Init;
  1152. objectsearchpath.Init;
  1153. { Def file }
  1154. usewindowapi:=false;
  1155. description:='Compiled by FPC '+version_string+' - '+target_cpu_string;
  1156. { Init values }
  1157. initmodeswitches:=fpcmodeswitches;
  1158. initlocalswitches:=[cs_check_io];
  1159. initmoduleswitches:=[cs_extsyntax,cs_browser];
  1160. initglobalswitches:=[cs_check_unit_name,cs_link_static];
  1161. {$ifdef i386}
  1162. initoptprocessor:=Class386;
  1163. initpackenum:=4;
  1164. initpackrecords:=packrecord_2;
  1165. initoutputformat:=target_asm.id;
  1166. initasmmode:=asmmode_i386_att;
  1167. {$else not i386}
  1168. {$ifdef m68k}
  1169. initoptprocessor:=MC68000;
  1170. include(initmoduleswitches,cs_fp_emulation);
  1171. initpackenum:=4;
  1172. initpackrecords:=packrecord_2;
  1173. initoutputformat:=as_m68k_as;
  1174. initasmmode:=asmmode_m68k_mot;
  1175. {$endif m68k}
  1176. {$endif i386}
  1177. initdefines.init;
  1178. { memory sizes, will be overriden by parameter or default for target
  1179. in options or init_parser }
  1180. stacksize:=0;
  1181. heapsize:=0;
  1182. maxheapsize:=0;
  1183. { compile state }
  1184. in_args:=false;
  1185. must_be_valid:=true;
  1186. not_unit_proc:=true;
  1187. apptype:=at_cui;
  1188. end;
  1189. begin
  1190. get_exepath;
  1191. {$ifdef EXTDEBUG}
  1192. {$ifdef FPC}
  1193. EntryMemUsed:=system.HeapSize-MemAvail;
  1194. {$endif FPC}
  1195. {$endif}
  1196. end.
  1197. {
  1198. $Log$
  1199. Revision 1.33 1999-11-12 11:03:50 peter
  1200. * searchpaths changed to stringqueue object
  1201. Revision 1.32 1999/11/09 23:34:46 pierre
  1202. + resolving_forward boolean used for references
  1203. Revision 1.31 1999/11/09 13:00:38 peter
  1204. * define FPC_DELPHI,FPC_OBJFPC,FPC_TP,FPC_GPC
  1205. * initial support for ansistring default with modes
  1206. Revision 1.30 1999/11/08 16:27:20 pierre
  1207. + Reset AnsiStrings to clean up memory
  1208. Revision 1.29 1999/11/06 14:34:20 peter
  1209. * truncated log to 20 revs
  1210. Revision 1.28 1999/11/04 10:55:31 peter
  1211. * TSearchPathList for the string type of the searchpaths, which is
  1212. ansistring under FPC/Delphi
  1213. Revision 1.27 1999/10/26 12:30:41 peter
  1214. * const parameter is now checked
  1215. * better and generic check if a node can be used for assigning
  1216. * export fixes
  1217. * procvar equal works now (it never had worked at least from 0.99.8)
  1218. * defcoll changed to linkedlist with pparaitem so it can easily be
  1219. walked both directions
  1220. Revision 1.26 1999/10/21 14:29:34 peter
  1221. * redesigned linker object
  1222. + library support for linux (only procedures can be exported)
  1223. Revision 1.25 1999/09/10 18:48:02 florian
  1224. * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
  1225. * most things for stored properties fixed
  1226. Revision 1.24 1999/09/08 16:05:31 peter
  1227. * pointer add/sub is now as expected and the same results as inc/dec
  1228. Revision 1.23 1999/09/07 15:11:00 pierre
  1229. * use do_internalerror insetead of runerror
  1230. Revision 1.22 1999/08/30 10:17:56 peter
  1231. * fixed crash in psub
  1232. * ansistringcompare fixed
  1233. * support for #$0b8
  1234. Revision 1.21 1999/08/27 10:45:00 pierre
  1235. options -Ca sets simply_ppu to true
  1236. Revision 1.20 1999/08/19 13:02:12 pierre
  1237. + label faillabel added for _FAIL support
  1238. Revision 1.19 1999/08/16 15:35:21 pierre
  1239. * fix for DLL relocation problems
  1240. * external bss vars had wrong stabs for pecoff
  1241. + -WB11000000 to specify default image base, allows to
  1242. load several DLLs with debugging info included
  1243. (relocatable DLL are stripped because the relocation
  1244. of the .Stab section is misplaced by ldw)
  1245. Revision 1.18 1999/08/11 17:26:32 peter
  1246. * tlinker object is now inherited for win32 and dos
  1247. * postprocessexecutable is now a method of tlinker
  1248. Revision 1.17 1999/08/10 12:51:14 pierre
  1249. * bind_win32_dll removed (Relocsection used instead)
  1250. * now relocsection is true by default ! (needs dlltool
  1251. for DLL generation)
  1252. Revision 1.16 1999/08/05 20:54:19 daniel
  1253. * Changes for new symtable.
  1254. Revision 1.15 1999/08/03 17:09:35 florian
  1255. * the alpha compiler can be compiled now
  1256. Revision 1.14 1999/07/23 16:05:19 peter
  1257. * alignment is now saved in the symtable
  1258. * C alignment added for records
  1259. * PPU version increased to solve .12 <-> .13 probs
  1260. Revision 1.13 1999/07/18 10:19:52 florian
  1261. * made it compilable with Dlephi 4 again
  1262. + fixed problem with large stack allocations on win32
  1263. Revision 1.12 1999/07/13 19:14:44 michael
  1264. + Defaultreplacemens now more logical
  1265. Revision 1.11 1999/07/10 10:26:18 peter
  1266. * merged
  1267. Revision 1.8.2.2 1999/07/10 10:03:04 peter
  1268. * fixed initialization/finalization in fpc mode
  1269. * allow $TARGET also in search paths
  1270. Revision 1.8.2.1 1999/07/07 07:53:21 michael
  1271. + Merged patches from florian
  1272. }