| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 | {    This file is part of the Free Pascal run time library.    Copyright (c) 1999-2000 by the Free Pascal development team    <What does this file>    See the file COPYING.FPC, included in this distribution,    for details about the copyright.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************}unit unixutil;interfacevar  Tzseconds : Longint;Type  ComStr  = String[255];  PathStr = String[255];  DirStr  = String[255];  NameStr = String[255];  ExtStr  = String[255];Function Dirname(Const path:pathstr):pathstr;Function StringToPPChar(S: PChar;ReserveEntries:integer):ppchar;Function StringToPPChar(Var S:String;ReserveEntries:integer):ppchar;Function StringToPPChar(Var S:AnsiString;ReserveEntries:integer):ppchar;function ArrayStringToPPchar(const S:Array of AnsiString;reserveentries:Longint):ppchar; // const ?Function Basename(Const path:pathstr;Const suf:pathstr):pathstr;Function FNMatch(const Pattern,Name:string):Boolean;Function GetFS (var T:Text):longint;Function GetFS(Var F:File):longint;Procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);Function LocalToEpoch(year,month,day,hour,minute,second:Word):Longint;Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word);Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);Function GregorianToJulian(Year,Month,Day:Longint):LongInt;implementation{$I textrec.inc}{$i filerec.inc}function ArrayStringToPPchar(const S:Array of AnsiString;reserveentries:Longint):ppchar; // const ?// Extra allocate reserveentries pchar's at the beginning (default param=0 after 1.0.x ?)// Note: for internal use by skilled programmers only// if "s" goes out of scope in the parent procedure, the pointer is dangling.var p   : ppchar;    i   : LongInt;begin  if High(s)<Low(s) Then Exit(NIL);  Getmem(p,sizeof(pchar)*(high(s)-low(s)+ReserveEntries+2));  // one more for NIL, one more                                              // for cmd  if p=nil then    begin      {$ifdef xunix}      fpseterrno(ESysEnomem);      {$endif}      exit(NIL);    end;  for i:=low(s) to high(s) do     p[i+Reserveentries]:=pchar(s[i]);  p[high(s)+1+Reserveentries]:=nil;  ArrayStringToPPchar:=p;end;Procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);Var  DotPos,SlashPos,i : longint;Begin  SlashPos:=0;  DotPos:=256;  i:=Length(Path);  While (i>0) and (SlashPos=0) Do   Begin     If (DotPos=256) and (Path[i]='.') Then      begin        DotPos:=i;      end;     If (Path[i]='/') Then      SlashPos:=i;     Dec(i);   End;  Ext:=Copy(Path,DotPos,255);  Dir:=Copy(Path,1,SlashPos);  Name:=Copy(Path,SlashPos + 1,DotPos - SlashPos - 1);End;Function Dirname(Const path:pathstr):pathstr;{  This function returns the directory part of a complete path.  Unless the directory is root '/', The last character is not  a slash.}var  Dir  : PathStr;  Name : NameStr;  Ext  : ExtStr;begin  FSplit(Path,Dir,Name,Ext);  if length(Dir)>1 then   Delete(Dir,length(Dir),1);  DirName:=Dir;end;Function StringToPPChar(Var S:String;ReserveEntries:integer):ppchar;{  Create a PPChar to structure of pchars which are the arguments specified  in the string S. Especially usefull for creating an ArgV for Exec-calls  Note that the string S is destroyed by this call.}begin  S:=S+#0;  StringToPPChar:=StringToPPChar(pchar(@S[1]),ReserveEntries);end;Function StringToPPChar(Var S:AnsiString;ReserveEntries:integer):ppchar;{  Create a PPChar to structure of pchars which are the arguments specified  in the string S. Especially usefull for creating an ArgV for Exec-calls}begin  StringToPPChar:=StringToPPChar(PChar(S),ReserveEntries);end;Function StringToPPChar(S: PChar;ReserveEntries:integer):ppchar;var  i,nr  : longint;  Buf : ^char;  p   : ppchar;begin  buf:=s;  nr:=1;  while (buf^<>#0) do                   // count nr of args   begin     while (buf^ in [' ',#9,#10]) do    // Kill separators.      inc(buf);     inc(nr);     if buf^='"' Then                   // quotes argument?      begin        inc(buf);        while not (buf^ in [#0,'"']) do // then end of argument is end of string or next quote         inc(buf);        if buf^='"' then                // skip closing quote.          inc(buf);      end     else       begin                            // else std         while not (buf^ in [' ',#0,#9,#10]) do           inc(buf);       end;   end;  getmem(p,(ReserveEntries+nr)*sizeof(pchar));  StringToPPChar:=p;  if p=nil then   begin     {$ifdef xunix}     fpseterrno(ESysEnomem);     {$endif}     exit;   end;  for i:=1 to ReserveEntries do inc(p); // skip empty slots  buf:=s;  while (buf^<>#0) do   begin     while (buf^ in [' ',#9,#10]) do    // Kill separators.      begin       buf^:=#0;       inc(buf);      end;     if buf^='"' Then                   // quotes argument?      begin        inc(buf);        p^:=buf;        inc(p);        p^:=nil;        while not (buf^ in [#0,'"']) do // then end of argument is end of string or next quote         inc(buf);        if buf^='"' then                // skip closing quote.          begin            buf^:=#0;            inc(buf);          end;      end     else       begin        p^:=buf;        inc(p);        p^:=nil;         while not (buf^ in [' ',#0,#9,#10]) do           inc(buf);       end;   end;end;Function Basename(Const path:pathstr;Const suf:pathstr):pathstr;{  This function returns the filename part of a complete path. If suf is  supplied, it is cut off the filename.}var  Dir  : PathStr;  Name : NameStr;  Ext  : ExtStr;begin  FSplit(Path,Dir,Name,Ext);  if Suf<>Ext then   Name:=Name+Ext;  BaseName:=Name;end;Function FNMatch(const Pattern,Name:string):Boolean;Var  LenPat,LenName : longint;  Function DoFNMatch(i,j:longint):Boolean;  Var    Found : boolean;  Begin  Found:=true;  While Found and (i<=LenPat) Do   Begin     Case Pattern[i] of      '?' : Found:=(j<=LenName);      '*' : Begin            {find the next character in pattern, different of ? and *}              while Found do                begin                inc(i);                if i>LenPat then Break;                case Pattern[i] of                  '*' : ;                  '?' : begin                          if j>LenName then begin DoFNMatch:=false; Exit; end;                          inc(j);                        end;                else                  Found:=false;                end;               end;              Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));            {Now, find in name the character which i points to, if the * or ?             wasn't the last character in the pattern, else, use up all the             chars in name}              Found:=false;              if (i<=LenPat) then              begin                repeat                  {find a letter (not only first !) which maches pattern[i]}                  while (j<=LenName) and (name[j]<>pattern[i]) do                    inc (j);                  if (j<LenName) then                  begin                    if DoFnMatch(i+1,j+1) then                    begin                      i:=LenPat;                      j:=LenName;{we can stop}                      Found:=true;                      Break;                    end else                      inc(j);{We didn't find one, need to look further}                  end else                  if j=LenName then                  begin                    Found:=true;                    Break;                  end;                  { This 'until' condition must be j>LenName, not j>=LenName.                    That's because when we 'need to look further' and                    j = LenName then loop must not terminate. }                until (j>LenName);              end else              begin                j:=LenName;{we can stop}                Found:=true;              end;            end;     else {not a wildcard character in pattern}       Found:=(j<=LenName) and (pattern[i]=name[j]);     end;     inc(i);     inc(j);   end;  DoFnMatch:=Found and (j>LenName);  end;Begin {start FNMatch}  LenPat:=Length(Pattern);  LenName:=Length(Name);  FNMatch:=DoFNMatch(1,1);End;Function GetFS (var T:Text):longint;{  Get File Descriptor of a text file.}begin  if textrec(t).mode=fmclosed then   exit(-1)  else   GETFS:=textrec(t).Handleend;Function GetFS(Var F:File):longint;{  Get File Descriptor of an unTyped file.}begin  { Handle and mode are on the same place in textrec and filerec. }  if filerec(f).mode=fmclosed then   exit(-1)  else   GETFS:=filerec(f).Handleend;Const{Date Translation}  C1970=2440588;  D0   =   1461;  D1   = 146097;  D2   =1721119;Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);Var  YYear,XYear,Temp,TempMonth : LongInt;Begin  Temp:=((JulianDN-D2) shl 2)-1;  JulianDN:=Temp Div D1;  XYear:=(Temp Mod D1) or 3;  YYear:=(XYear Div D0);  Temp:=((((XYear mod D0)+4) shr 2)*5)-3;  Day:=((Temp Mod 153)+5) Div 5;  TempMonth:=Temp Div 153;  If TempMonth>=10 Then   Begin     inc(YYear);     dec(TempMonth,12);   End;  inc(TempMonth,3);  Month := TempMonth;  Year:=YYear+(JulianDN*100);end;Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word);{  Transforms Epoch time into local time (hour, minute,seconds)}Var  DateNum: LongInt;Begin  inc(Epoch,TZSeconds);  Datenum:=(Epoch Div 86400) + c1970;  JulianToGregorian(DateNum,Year,Month,day);  Epoch:=Abs(Epoch Mod 86400);  Hour:=Epoch Div 3600;  Epoch:=Epoch Mod 3600;  Minute:=Epoch Div 60;  Second:=Epoch Mod 60;End;Function LocalToEpoch(year,month,day,hour,minute,second:Word):Longint;{  Transforms local time (year,month,day,hour,minutes,second) to Epoch time   (seconds since 00:00, january 1 1970, corrected for local time zone)}Begin  LocalToEpoch:=((GregorianToJulian(Year,Month,Day)-c1970)*86400)+                (LongInt(Hour)*3600)+(Longint(Minute)*60)+Second-TZSeconds;End;Function GregorianToJulian(Year,Month,Day:Longint):LongInt;Var  Century,XYear: LongInt;Begin  If Month<=2 Then   Begin     Dec(Year);     Inc(Month,12);   End;  Dec(Month,3);  Century:=(longint(Year Div 100)*D1) shr 2;  XYear:=(longint(Year Mod 100)*D0) shr 2;  GregorianToJulian:=((((Month*153)+2) div 5)+Day)+D2+XYear+Century;End;end.
 |