globals.pas 35 KB

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