globals.pas 36 KB

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