unixutil.pp 9.3 KB

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