unixutil.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. <What does this file>
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit unixutil;
  13. interface
  14. var
  15. Tzseconds : Longint;
  16. Type
  17. ComStr = String[255];
  18. PathStr = String[255];
  19. DirStr = String[255];
  20. NameStr = String[255];
  21. ExtStr = String[255];
  22. Function Dirname(Const path:pathstr):pathstr;
  23. Function StringToPPChar(S: PChar;ReserveEntries:integer):ppchar;
  24. Function StringToPPChar(Var S:String;ReserveEntries:integer):ppchar;
  25. Function StringToPPChar(Var S:AnsiString;ReserveEntries:integer):ppchar;
  26. function ArrayStringToPPchar(const S:Array of AnsiString;reserveentries:Longint):ppchar; // const ?
  27. Function Basename(Const path:pathstr;Const suf:pathstr):pathstr;
  28. Function FNMatch(const Pattern,Name:string):Boolean;
  29. Function GetFS (var T:Text):longint;
  30. Function GetFS(Var F:File):longint;
  31. Procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);
  32. Function LocalToEpoch(year,month,day,hour,minute,second:Word):Longint;
  33. Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word);
  34. Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);
  35. Function GregorianToJulian(Year,Month,Day:Longint):LongInt;
  36. implementation
  37. {$I textrec.inc}
  38. {$i filerec.inc}
  39. function ArrayStringToPPchar(const S:Array of AnsiString;reserveentries:Longint):ppchar; // const ?
  40. // Extra allocate reserveentries pchar's at the beginning (default param=0 after 1.0.x ?)
  41. // Note: for internal use by skilled programmers only
  42. // if "s" goes out of scope in the parent procedure, the pointer is dangling.
  43. var p : ppchar;
  44. i : LongInt;
  45. begin
  46. if High(s)<Low(s) Then Exit(NIL);
  47. Getmem(p,sizeof(pchar)*(high(s)-low(s)+ReserveEntries+2)); // one more for NIL, one more
  48. // for cmd
  49. if p=nil then
  50. begin
  51. {$ifdef xunix}
  52. fpseterrno(ESysEnomem);
  53. {$endif}
  54. exit(NIL);
  55. end;
  56. for i:=low(s) to high(s) do
  57. p[i+Reserveentries]:=pchar(s[i]);
  58. p[high(s)+1+Reserveentries]:=nil;
  59. ArrayStringToPPchar:=p;
  60. end;
  61. Procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);
  62. Var
  63. DotPos,SlashPos,i : longint;
  64. Begin
  65. SlashPos:=0;
  66. DotPos:=256;
  67. i:=Length(Path);
  68. While (i>0) and (SlashPos=0) Do
  69. Begin
  70. If (DotPos=256) and (Path[i]='.') Then
  71. begin
  72. DotPos:=i;
  73. end;
  74. If (Path[i]='/') Then
  75. SlashPos:=i;
  76. Dec(i);
  77. End;
  78. Ext:=Copy(Path,DotPos,255);
  79. Dir:=Copy(Path,1,SlashPos);
  80. Name:=Copy(Path,SlashPos + 1,DotPos - SlashPos - 1);
  81. End;
  82. Function Dirname(Const path:pathstr):pathstr;
  83. {
  84. This function returns the directory part of a complete path.
  85. Unless the directory is root '/', The last character is not
  86. a slash.
  87. }
  88. var
  89. Dir : PathStr;
  90. Name : NameStr;
  91. Ext : ExtStr;
  92. begin
  93. FSplit(Path,Dir,Name,Ext);
  94. if length(Dir)>1 then
  95. Delete(Dir,length(Dir),1);
  96. DirName:=Dir;
  97. end;
  98. Function StringToPPChar(Var S:String;ReserveEntries:integer):ppchar;
  99. {
  100. Create a PPChar to structure of pchars which are the arguments specified
  101. in the string S. Especially usefull for creating an ArgV for Exec-calls
  102. Note that the string S is destroyed by this call.
  103. }
  104. begin
  105. S:=S+#0;
  106. StringToPPChar:=StringToPPChar(pchar(@S[1]),ReserveEntries);
  107. end;
  108. Function StringToPPChar(Var S:AnsiString;ReserveEntries:integer):ppchar;
  109. {
  110. Create a PPChar to structure of pchars which are the arguments specified
  111. in the string S. Especially usefull for creating an ArgV for Exec-calls
  112. }
  113. begin
  114. StringToPPChar:=StringToPPChar(PChar(S),ReserveEntries);
  115. end;
  116. Function StringToPPChar(S: PChar;ReserveEntries:integer):ppchar;
  117. var
  118. i,nr : longint;
  119. Buf : ^char;
  120. p : ppchar;
  121. begin
  122. buf:=s;
  123. nr:=1;
  124. while (buf^<>#0) do // count nr of args
  125. begin
  126. while (buf^ in [' ',#9,#10]) do // Kill separators.
  127. inc(buf);
  128. inc(nr);
  129. if buf^='"' Then // quotes argument?
  130. begin
  131. inc(buf);
  132. while not (buf^ in [#0,'"']) do // then end of argument is end of string or next quote
  133. inc(buf);
  134. if buf^='"' then // skip closing quote.
  135. inc(buf);
  136. end
  137. else
  138. begin // else std
  139. while not (buf^ in [' ',#0,#9,#10]) do
  140. inc(buf);
  141. end;
  142. end;
  143. getmem(p,(ReserveEntries+nr)*sizeof(pchar));
  144. StringToPPChar:=p;
  145. if p=nil then
  146. begin
  147. {$ifdef xunix}
  148. fpseterrno(ESysEnomem);
  149. {$endif}
  150. exit;
  151. end;
  152. for i:=1 to ReserveEntries do inc(p); // skip empty slots
  153. buf:=s;
  154. while (buf^<>#0) do
  155. begin
  156. while (buf^ in [' ',#9,#10]) do // Kill separators.
  157. begin
  158. buf^:=#0;
  159. inc(buf);
  160. end;
  161. if buf^='"' Then // quotes argument?
  162. begin
  163. inc(buf);
  164. p^:=buf;
  165. inc(p);
  166. p^:=nil;
  167. while not (buf^ in [#0,'"']) do // then end of argument is end of string or next quote
  168. inc(buf);
  169. if buf^='"' then // skip closing quote.
  170. begin
  171. buf^:=#0;
  172. inc(buf);
  173. end;
  174. end
  175. else
  176. begin
  177. p^:=buf;
  178. inc(p);
  179. p^:=nil;
  180. while not (buf^ in [' ',#0,#9,#10]) do
  181. inc(buf);
  182. end;
  183. end;
  184. end;
  185. Function Basename(Const path:pathstr;Const suf:pathstr):pathstr;
  186. {
  187. This function returns the filename part of a complete path. If suf is
  188. supplied, it is cut off the filename.
  189. }
  190. var
  191. Dir : PathStr;
  192. Name : NameStr;
  193. Ext : ExtStr;
  194. begin
  195. FSplit(Path,Dir,Name,Ext);
  196. if Suf<>Ext then
  197. Name:=Name+Ext;
  198. BaseName:=Name;
  199. end;
  200. Function FNMatch(const Pattern,Name:string):Boolean;
  201. Var
  202. LenPat,LenName : longint;
  203. Function DoFNMatch(i,j:longint):Boolean;
  204. Var
  205. Found : boolean;
  206. Begin
  207. Found:=true;
  208. While Found and (i<=LenPat) Do
  209. Begin
  210. Case Pattern[i] of
  211. '?' : Found:=(j<=LenName);
  212. '*' : Begin
  213. {find the next character in pattern, different of ? and *}
  214. while Found do
  215. begin
  216. inc(i);
  217. if i>LenPat then Break;
  218. case Pattern[i] of
  219. '*' : ;
  220. '?' : begin
  221. if j>LenName then begin DoFNMatch:=false; Exit; end;
  222. inc(j);
  223. end;
  224. else
  225. Found:=false;
  226. end;
  227. end;
  228. Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
  229. {Now, find in name the character which i points to, if the * or ?
  230. wasn't the last character in the pattern, else, use up all the
  231. chars in name}
  232. Found:=false;
  233. if (i<=LenPat) then
  234. begin
  235. repeat
  236. {find a letter (not only first !) which maches pattern[i]}
  237. while (j<=LenName) and (name[j]<>pattern[i]) do
  238. inc (j);
  239. if (j<LenName) then
  240. begin
  241. if DoFnMatch(i+1,j+1) then
  242. begin
  243. i:=LenPat;
  244. j:=LenName;{we can stop}
  245. Found:=true;
  246. Break;
  247. end else
  248. inc(j);{We didn't find one, need to look further}
  249. end else
  250. if j=LenName then
  251. begin
  252. Found:=true;
  253. Break;
  254. end;
  255. { This 'until' condition must be j>LenName, not j>=LenName.
  256. That's because when we 'need to look further' and
  257. j = LenName then loop must not terminate. }
  258. until (j>LenName);
  259. end else
  260. begin
  261. j:=LenName;{we can stop}
  262. Found:=true;
  263. end;
  264. end;
  265. else {not a wildcard character in pattern}
  266. Found:=(j<=LenName) and (pattern[i]=name[j]);
  267. end;
  268. inc(i);
  269. inc(j);
  270. end;
  271. DoFnMatch:=Found and (j>LenName);
  272. end;
  273. Begin {start FNMatch}
  274. LenPat:=Length(Pattern);
  275. LenName:=Length(Name);
  276. FNMatch:=DoFNMatch(1,1);
  277. End;
  278. Function GetFS (var T:Text):longint;
  279. {
  280. Get File Descriptor of a text file.
  281. }
  282. begin
  283. if textrec(t).mode=fmclosed then
  284. exit(-1)
  285. else
  286. GETFS:=textrec(t).Handle
  287. end;
  288. Function GetFS(Var F:File):longint;
  289. {
  290. Get File Descriptor of an unTyped file.
  291. }
  292. begin
  293. { Handle and mode are on the same place in textrec and filerec. }
  294. if filerec(f).mode=fmclosed then
  295. exit(-1)
  296. else
  297. GETFS:=filerec(f).Handle
  298. end;
  299. Const
  300. {Date Translation}
  301. C1970=2440588;
  302. D0 = 1461;
  303. D1 = 146097;
  304. D2 =1721119;
  305. Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);
  306. Var
  307. YYear,XYear,Temp,TempMonth : LongInt;
  308. Begin
  309. Temp:=((JulianDN-D2) shl 2)-1;
  310. JulianDN:=Temp Div D1;
  311. XYear:=(Temp Mod D1) or 3;
  312. YYear:=(XYear Div D0);
  313. Temp:=((((XYear mod D0)+4) shr 2)*5)-3;
  314. Day:=((Temp Mod 153)+5) Div 5;
  315. TempMonth:=Temp Div 153;
  316. If TempMonth>=10 Then
  317. Begin
  318. inc(YYear);
  319. dec(TempMonth,12);
  320. End;
  321. inc(TempMonth,3);
  322. Month := TempMonth;
  323. Year:=YYear+(JulianDN*100);
  324. end;
  325. Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word);
  326. {
  327. Transforms Epoch time into local time (hour, minute,seconds)
  328. }
  329. Var
  330. DateNum: LongInt;
  331. Begin
  332. inc(Epoch,TZSeconds);
  333. Datenum:=(Epoch Div 86400) + c1970;
  334. JulianToGregorian(DateNum,Year,Month,day);
  335. Epoch:=Abs(Epoch Mod 86400);
  336. Hour:=Epoch Div 3600;
  337. Epoch:=Epoch Mod 3600;
  338. Minute:=Epoch Div 60;
  339. Second:=Epoch Mod 60;
  340. End;
  341. Function LocalToEpoch(year,month,day,hour,minute,second:Word):Longint;
  342. {
  343. Transforms local time (year,month,day,hour,minutes,second) to Epoch time
  344. (seconds since 00:00, january 1 1970, corrected for local time zone)
  345. }
  346. Begin
  347. LocalToEpoch:=((GregorianToJulian(Year,Month,Day)-c1970)*86400)+
  348. (LongInt(Hour)*3600)+(Longint(Minute)*60)+Second-TZSeconds;
  349. End;
  350. Function GregorianToJulian(Year,Month,Day:Longint):LongInt;
  351. Var
  352. Century,XYear: LongInt;
  353. Begin
  354. If Month<=2 Then
  355. Begin
  356. Dec(Year);
  357. Inc(Month,12);
  358. End;
  359. Dec(Month,3);
  360. Century:=(longint(Year Div 100)*D1) shr 2;
  361. XYear:=(longint(Year Mod 100)*D0) shr 2;
  362. GregorianToJulian:=((((Month*153)+2) div 5)+Day)+D2+XYear+Century;
  363. End;
  364. end.
  365. {
  366. $Log$
  367. Revision 1.8 2005-03-25 22:53:39 jonas
  368. * fixed several warnings and notes about unused variables (mainly) or
  369. uninitialised use of variables/function results (a few)
  370. Revision 1.7 2005/02/14 17:13:31 peter
  371. * truncate log
  372. }