unixutil.pp 11 KB

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