globals.pas 36 KB

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