home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 9 Archive
/
09-Archive.zip
/
lxlt121s.zip
/
lxLite_src
/
common
/
SysLib.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-08-17
|
24KB
|
821 lines
{$A-,B-,D+,E-,F-,G-,I-,L+,N-,O-,P+,Q-,R-,S-,T-,V-,X+,Y+}
{&AlignCode-,AlignData-,AlignRec-,Asm-,Cdecl-,Delphi+,W-,Frame-,G3+}
{&LocInfo+,Optimise+,OrgName-,SmartLink+,Speed-,Z-,ZD-}
Unit SysLib;
Interface uses use32, Dos, miscUtil, Collect
{$ifDef OS2}, os2def {$endIf};
const
fMaskDelim1 = ':'; {fileMask delimiter char}
fMaskDelim2 = '/'; {fileMask delimiter char}
type
{$ifDef OS2}
pFileMatch = ^tFileMatch;
tFileMatch = object(tObject)
matchStrings : pZTstrCollection;
constructor Create(const fMasks : string);
procedure AddMask(const fMasks : string);
function Matches(const fName : string) : boolean;
destructor Destroy; virtual;
end;
pEAcollection = ^tEAcollection;
tEAcollection = object(tCollection)
constructor Fetch(const fName : string);
function Attach(const fName : string) : boolean;
procedure FreeItem(Item: Pointer); virtual;
end;
{ Fast MUTEX semaphore type }
tMutexSem = record
Next : Pointer; { Next thread ID requesting ownership }
Owner : TID; { Current semaphore owner; bit 31 = semaphore in use }
Count : Longint; { For recursive semaphore requests }
end;
{$endIf}
pCommandLineParser = ^tCommandLineParser;
tCommandLineParser = object(tObject)
procedure Parse(var S : string);
procedure ParseCommandLine;
function GetWord(var ParmStr : string; StartChar : Word; var DestStr : string) : Word;
function GetOpt(const parmStr : string; StartChar : Word; const OptChars : string;
OptFlags : array of Longint; var Option : Longint) : Word;
function ParmHandler(var ParmStr : string) : Word; virtual;
function NameHandler(var ParmStr : string) : Word; virtual;
procedure PreProcess(var ParmStr : string); virtual;
procedure PostProcess; virtual;
end;
{Return TRUE if file exists; FALSE otherwise}
Function fileExist(const fName : string) : Boolean;
{Try to rename file sName into dName. Returns TRUE if succesful}
Function fileRename(const sName,dName : string) : Boolean;
{Try to erase file fName and returns TRUE if succesful}
Function fileErase(const fName : string) : Boolean;
{Returns file length in bytes or -1 if no such file}
Function fileLength(const fName : string) : Longint;
{Copy file srcName into dstName; return TRUE if o.k.}
Function fileCopy(const sName,dName : string) : boolean;
{Create an entire directory tree structure}
Function makeDirTree(const dirName : string) : boolean;
{Create an unique temporary filename by given filemask: replace '?' by}
{unique characters; if no path is given uses TEMP or TMP environment var}
Function tempFileName(const fName : string) : string;
{Return a string containing executable`s source path including last '\' or '/'}
Function SourcePath : string;
{An replacement for standard fSplit which handles correctly forvard slashes}
procedure fSplit(const Path : PathStr; var Dir : DirStr; var Name : NameStr;
var Ext : ExtStr);
{$ifDef OS2 ---------}
{ Open an [F]ast [M]utex [S]emaphore }
Function fmsInit(var Sem : tMutexSem) : boolean;
{ Request a semaphore; wait until semaphore is available }
Function fmsRequest(var Sem : tMutexSem) : boolean;
{ Release semaphore; return TRUE if o.k.; FALSE if caller is not owner }
Function fmsRelease(var Sem : tMutexSem) : boolean;
{ Check if semaphore is owned; DO NOT RELY ON THIS! }
Function fmsCheck(var Sem : tMutexSem) : boolean;
{ Unlock a executable module if it is already in use }
Function unlockModule(const fName : string) : boolean;
{ Return an string from resourse (from string table) }
Function GetResourceString(ID : Longint) : string;
{$endIf}
Implementation uses strOp, Streams, strings
{$ifDef OS2}, os2base {$endIf};
{$ifDef OS2}
constructor tFileMatch.Create;
begin
New(matchStrings, Create(4, 4));
AddMask(fMasks);
end;
procedure tFileMatch.AddMask;
var
I,oPos,
Pos1,Pos2 : Word;
iDone : boolean;
nP : pChar;
begin
oPos := 1; I := 1; iDone := FALSE;
repeat
Pos1 := ScanFwd(fMaskDelim1, fMasks, I);
Pos2 := ScanFwd(fMaskDelim2, fMasks, I);
if (Pos2 > 0)
then if Pos1 = 0
then Pos1 := Pos2
else Pos1 := MinI(Pos1, Pos2);
Inc(I);
if (Pos1 = 0)
then begin
Pos1 := succ(length(fMasks));
iDone := TRUE;
end;
if Pos1 > oPos
then begin
GetMem(nP, succ(Pos1 - oPos));
strUpper(strPcopy(nP, copy(fMasks, oPos, Pos1 - oPos)));
if matchStrings^.IndexOf(nP) >= 0
then FreeMem(nP, succ(Pos1 - oPos))
else matchStrings^.Insert(nP);
end;
oPos := succ(Pos1);
until iDone;
end;
function tFileMatch.Matches;
var I : Integer;
Source,
Target : array[0..255] of Char;
begin
Matches := TRUE;
StrUpper(StrPcopy(Source, fName));
For I := 0 to pred(matchStrings^.Count) do
if (DosEditName(1, Source, matchStrings^.At(I), Target, sizeOf(Target)) = 0) and
(StrComp(Source, Target) = 0)
then exit;
Matches := FALSE;
end;
destructor tFileMatch.Destroy;
begin
Dispose(matchStrings, Destroy);
inherited Destroy;
end;
constructor tEAcollection.Fetch;
const
eaNameBfSz = 1024;
secureSize = 256; {F$#%^k! Bug in DosEnumAttribute}
var
fN : array[0..255] of char;
sV,oV,
I,eaCn : Longint;
Buff : pByteArray;
eaN : pStringCollection;
pS : pString;
pEA,nEA : pFea2;
eaBuf : EAop2;
fStat : FileStatus4;
procedure resFree;
begin
if eaBuf.fpFEA2List <> nil
then FreeMem(eaBuf.fpFEA2List, fStat.cbList);
if eaN <> nil
then Dispose(eaN, Destroy);
if Buff <> nil then FreeMem(Buff, eaNameBfSz + secureSize);
end;
begin
inherited Create(8, 8);
GetMem(Buff, eaNameBfSz + secureSize);
New(eaN, Create(8, 8));
fillChar(fStat, sizeOf(fStat), 0);
fillChar(eaBuf, sizeOf(eaBuf), 0);
if (Buff = nil) or (eaN = nil)
then begin resFree; Fail; end;
StrPCopy(@fN, fName);
sV := 1;
repeat
eaCn := -1; FillChar(Buff^, eaNameBfSz, 0); {F&^#$@%&k! Really not needed}
if DosEnumAttribute(EnumEA_RefType_Path, @fN, sV, Buff^, eaNameBfSz, eaCn, EnumEA_Level_No_Value) <> 0
then begin resFree; Fail; end;
if eaCn = 0 then break;
pEA := @Buff^;
For I := 1 to eaCn do
begin
eaN^.Insert(NewStr(StrPas(@pEA^.szName)));
Inc(Longint(pEA), pEA^.oNextEntryOffset);
Inc(sV);
end;
until FALSE;
if DosQueryPathInfo(@fN, Fil_QueryEAsize, fStat, sizeOf(fStat)) <> 0
then begin resFree; Fail; end;
I := 0;
GetMem(eaBuf.fpFEA2List, fStat.cbList);
eaBuf.fpGEA2List := @Buff^;
While I < eaN^.Count do
begin
sV := 4; oV := 4;
repeat
pS := eaN^.At(I);
if sV + 4 + succ(length(pS^)) > pred(eaNameBfSz) then break;
pLong(@Buff^[oV])^ := sV - oV;
pLong(@Buff^[sV])^ := 0; oV := sV;
Move(pS^, Buff^[sV + 4], succ(length(pS^)));
Inc(sV, 4 + succ(length(pS^)));
Buff^[sV] := 0; sV := (sV + 4) and $FFFFFFFC;
Inc(I);
until I >= eaN^.Count;
pLong(@Buff^[0])^ := sV;
eaBuf.fpFEA2List^.cbList := fStat.cbList;
if DosQueryPathInfo(@fN, Fil_QueryEAsFromList, eaBuf, sizeOf(eaBuf)) = 0
then begin
pEA := @eaBuf.fpFEA2List^.list;
While longint(pEA) - longint(@eaBuf.fpFEA2List^.list) <= eaBuf.fpFEA2List^.cbList do
begin
GetMem(nEA, sizeOf(Fea2) + pEA^.cbName + pEA^.cbValue);
Move(pEA^, nEA^, sizeOf(Fea2) + pEA^.cbName + pEA^.cbValue);
Insert(nEA);
if pEA^.oNextEntryOffset = 0 then break;
Inc(longint(pEA), pEA^.oNextEntryOffset);
end;
end;
end;
resFree;
end;
Function tEAcollection.Attach;
label
locEx;
const
eaNameBfSz = 300;
var
fN : array[0..255] of Char;
oldAttr,
I,fT,maxEA : Longint;
eaBuf : EAop2;
Buff,OneEA : pByteArray;
fInfo : FileStatus3;
begin
if (Count = 0) then begin Attach := TRUE; exit; end;
Attach := FALSE;
GetMem(Buff, eaNameBfSz);
maxEA := 0;
if (Buff = nil) then goto locEx;
if DosQueryPathInfo(StrPCopy(@fN, fName), fil_Standard, fInfo, SizeOf(fInfo)) <> 0
then goto locEx;
{temporary remove hidden/readonly attributes}
oldAttr := fInfo.attrFile;
fInfo.attrFile := fInfo.attrFile and not (file_ReadOnly + file_System + file_Hidden);
DosSetPathInfo(@fN, fil_Standard, fInfo, SizeOf(fInfo), 0);
fInfo.attrFile := oldAttr;
For I := 0 to pred(Count) do
with pFea2(At(I))^ do
if sizeOf(Fea2) + cbName + cbValue > maxEA
then maxEA := sizeOf(Fea2) + cbName + cbValue;
Inc(maxEA, 4);
GetMem(oneEA, maxEA);
pLong(oneEA)^ := maxEA;
eaBuf.fpGEA2List := @Buff^;
eaBuf.fpFEA2list := @oneEA^;
For I := 0 to pred(Count) do
with pFea2(At(I))^ do
begin
oNextEntryOffset := 0;
pLong(@Buff^[0])^ := 4 + 4 + 1 + 1 + cbName;
pLong(@Buff^[4])^ := 0;
Buff^[8] := cbName;
Move(szName, Buff^[9], cbName);
Buff^[9 + cbName] := 0;
Move(oNextEntryOffset, oneEA^[4], sizeOf(Fea2) + cbName + cbValue);
DosSetPathInfo(@fN, fil_QueryEAsize, eaBuf, sizeOf(eaBuf), 0);
end;
Attach := DosSetPathInfo(@fN, fil_Standard, fInfo, SizeOf(fInfo), 0) = 0;
locEx:
FreeMem(oneEA, maxEA);
if Buff <> nil then FreeMem(Buff, eaNameBfSz);
end;
procedure tEAcollection.FreeItem;
begin
if Item <> nil
then with pFea2(Item)^ do
FreeMem(Item, sizeOf(Fea2) + cbName + cbValue);
end;
{$endIf}
Function fileExist;
var
sr : SearchRec;
begin
Dos.FindFirst(fName, AnyFile, sr);
fileExist := Dos.DosError = 0;
{$ifDef OS2}
Dos.FindClose(sr);
{$endIf}
end;
Function fileRename;
var F : File;
begin
Assign(F, sName); Rename(F, dName);
fileRename := ioResult = 0;
end;
Function fileErase;
var F : File;
begin
Assign(F, FName); SetFAttr(F, Archive);
Erase(F); fileErase := ioResult = 0;
end;
Function fileLength;
var F : File;
I : Longint;
begin
I := fileMode; fileMode := $40; { open_access_ReadOnly + open_share_DenyNone };
Assign(F, fName); Reset(F, 1);
fileMode := I;
if ioResult <> 0
then fileLength := -1
else begin
fileLength := fileSize(F);
Close(F);
end;
end;
Function fileCopy;
{$ifDef OS2}
var
sn,dn : pChar;
begin
GetMem(sn, succ(length(sName)));
GetMem(dn, succ(length(dName)));
StrPCopy(sn, sName);
StrPCopy(dn, dName);
fileCopy := DosCopy(sn, dn, dcpy_Existing) = 0;
FreeMem(sn, succ(length(sName)));
FreeMem(dn, succ(length(dName)));
end;
{$else}
var
IS,OS : pFileStream;
At : Word;
FT : Longint;
begin
fileCopy := FALSE;
New(IS, Create(sName, stmReadOnly));
if (IS = nil) or (IS^.Error <> steOK)
then begin
if IS <> nil then Dispose(IS, Destroy);
exit;
end;
New(OS, Create(dName, stmWriteOnly));
FT := IS^.GetTime; At := IS^.GetAttr;
if (OS = nil) or (OS^.Error <> steOK)
then begin
Dispose(IS, Destroy);
if OS <> nil then Dispose(OS, Destroy);
exit;
end;
if IS^.Size <> OS^.CopyFrom(IS^, -1)
then begin
Dispose(OS, Erase);
fileCopy := FALSE;
end
else begin
OS^.SetAttr(At);
OS^.SetTime(FT);
Dispose(OS, Destroy);
fileCopy := TRUE;
end;
Dispose(IS, Destroy);
end;
{$endIf}
Function makeDirTree(const dirName : string) : boolean;
var
L,SC : Integer;
S : string;
begin
makeDirTree := FALSE;
L := 0; SC := 0;
While L <= length(dirName) do
begin
repeat
Inc(L);
until (L > length(dirName)) or (dirName[L] in ['/','\',':']);
if (L <= length(dirName)) and (dirName[L] = ':') then SC := 2;
if SC > 0 then begin Dec(SC); Continue; end;
S := copy(dirName, 1, pred(L));
while (S <> '') and (S[length(S)] in ['/','\']) do Dec(byte(S[0]));
if (S <> '') and (not fileExist(S)) then mkDir(S);
if ioResult <> 0 then exit;
end;
makeDirTree := TRUE;
end;
Function tempFileName;
var
D,N,R : string;
Count : Integer;
{$ifDef OS2}
sz : array[0..255] of Char;
Action: Longint;
Handle: hFile;
{$endif}
begin
D := extractDir(fName);
N := Copy(fName, succ(length(D)), 255);
if D = '' then D := GetEnv('TEMP');
if D = '' then D := GetEnv('TMP');
if not (D[length(D)] in ['/', '\']) then D := D + '\';
Count := 1000;
repeat
R := D + N; Dec(Count);
While First('?', R) <> 0 do R[First('?', R)] := char(Random(10) + byte('0'));
{$ifDef OS2}
if DosOpen(strPCopy(@sz, R), Handle, Action, 0, 0,
open_action_Create_If_New + open_action_Fail_If_Exists,
open_flags_Fail_On_Error + open_Share_DenyReadWrite +
open_access_ReadOnly, nil) = 0
then begin
DosClose(Handle);
break;
end;
{$else}
if (not fileExist(R)) then break;
{$endIf}
until (Count = 0);
if Count = 0
then tempFileName := ''
else tempFileName := R;
end;
Function SourcePath; assembler {&uses esi,edi};
{$ifDef OS2}
asm mov edi,Environment
mov al,0
mov ecx,-1
@@cont: repne scasb
scasb
jnz @@cont
mov esi,edi
repne scasb
@@searchSlash: cmp byte ptr [edi-1],':'
je @@done
dec edi
cmp edi,esi
jbe @@done
cmp byte ptr [edi],'/'
je @@done
cmp byte ptr [edi],'\'
jne @@searchSlash
@@done: sub edi,esi
mov eax,edi
inc eax
mov ecx,eax
mov edi,@result
stosb
rep movsb
end;
{$else}
asm push ds
mov es,PrefixSeg
mov ds,es:[02Ch]
push ds
pop es
mov al,0
mov cx,-1
xor di,di
@@cont: repne scasb
scasb
jnz @@cont
scasw
mov si,di
repne scasb
@@searchSlash: cmp byte ptr [di-1],':'
je @@done
dec di
cmp di,si
jbe @@done
cmp byte ptr [di],'/'
je @@done
cmp byte ptr [di],'\'
jne @@searchSlash
@@done: sub di,si
mov ax,di
inc ax
mov cx,ax
les di,@result
stosb
rep movsb
pop ds
end;
{$endIf}
procedure fSplit;
var
I,J : Integer;
begin
I := length(Path);
While (I > 1) and (Path[I] <> '.') and (not (Path[I] in ['/','\',':'])) do Dec(I);
if (I <= 1)
then begin
Dir := ''; Name := Path; Ext := '';
exit;
end;
if (Path[I] = '.')
then if (Path[I - 1] in ['/','\',':'])
then begin
Dir := Copy(Path, 1, I - 1);
Name := Copy(Path, I, 255);
Ext := '';
exit;
end
else begin
Ext := Copy(Path, I, 255); J := I;
While (J > 1) and (not (Path[J] in ['/','\',':'])) do Dec(J);
if (Path[J] in ['/','\',':'])
then begin
Name := Copy(Path, J + 1, I - J - 1);
Dir := Copy(Path, 1, J);
end
else begin
Name := Copy(Path, J, I - J);
Dir := '';
end;
exit;
end
else begin
Ext := '';
Name := Copy(Path, I, 255);
Dir := Copy(Path, 1, I - 1);
end;
end;
{$ifDef OS2}
function fmsInit; assembler {&uses none};
asm mov ecx,Sem
lock bts [ecx].tMutexSem.Owner,31 {Lock semaphore updates}
jnc @@ok
mov al,0
ret 4
@@ok: xor eax,eax
mov [ecx].tMutexSem.Next,eax
lock xchg [ecx].tMutexSem.Owner,eax
mov al,1
end;
function fmsRequest; assembler {&uses none};
asm mov eax,fs:[12] {Get ^Thread Information Block}
push dword ptr [eax] {Owner : Longint}
push eax {Next : Pointer}
@@testSem: mov ecx,Sem[4+4] {+4+4 since &frame-}
lock bts [ecx].tMutexSem.Owner,31
jnc @@semFree
push 1 {There is no hurry since semaphore is busy}
call DosSleep {Go to sleep for a while...}
pop eax
jmp @@testSem
@@semFree: mov edx,[ecx].tMutexSem.Owner {Get semaphore owner}
btr edx,31 {Reset `semaphor busy` bit}
cmp edx,[esp+4] {Owner = current TID?}
jne @@notOur
inc [ecx].tMutexSem.Count
lock btr [ecx].tMutexSem.Owner,31 {Release semaphore}
add esp,4+4
mov al,1
ret 4
@@notOur: mov eax,esp
xchg eax,[ecx].tMutexSem.Next
test edx,edx {Owner = 0?}
jz @@notBusy
mov [esp],eax {Save ^nextTID}
lock btr [ecx].tMutexSem.Owner,31 {Release semaphore}
push dword ptr [esp+4] {Our TID}
call SuspendThread {Sleep until wakeup}
add esp,4+4
mov al,1
ret 4
@@notBusy: xchg eax,[ecx].tMutexSem.Next
inc edx
mov [ecx].tMutexSem.Count,edx {Request count = 1}
pop eax {Skip ^nextTID}
pop eax
lock xchg [ecx].tMutexSem.Owner,eax {Set owner&unlock semaphore}
mov al,1
end;
function fmsRelease; assembler {&uses none};
asm
@@testSem: mov ecx,Sem
lock bts [ecx].tMutexSem.Owner,31 {Lock semaphore updates}
jnc @@semFree
push 1
call DosSleep
pop eax
jmp @@testSem
@@semFree: mov eax,fs:[12]
mov eax,[eax]
bts eax,31 {Set bit 31 in EAX for comparison}
cmp eax,[ecx].tMutexSem.Owner
je @@isOur
lock btr [ecx].tMutexSem.Owner,31 {Release semaphore}
mov al,0
ret 4
@@isOur: dec [ecx].tMutexSem.Count {Request count = 1?}
jz @@scanChain
lock btr [ecx].tMutexSem.Owner,31 {Release semaphore}
mov al,1
ret 4
@@scanChain: mov edx,eax
mov eax,ecx
mov ecx,[ecx].tMutexSem.Next {^nextTID}
test ecx,ecx
jnz @@scanChain
mov ecx,Sem
cmp eax,ecx
je @@onlyOwner {Thread is only in chain}
mov [edx].tMutexSem.Next,0 {Remove thread from chain}
mov [ecx].tMutexSem.Count,1 {Set request count to 1}
mov eax,[eax].tMutexSem.Owner
push eax
@@resumeIt: push eax {ResumeThread(TID = EAX)}
lock xchg [ecx].tMutexSem.Owner,eax{Make thread semaphore owner}
call ResumeThread {Wake up thread}
cmp eax,error_Not_Frozen
jne @@resumeOK
push 1
call DosSleep
pop eax
pop eax
jmp @@resumeIt
@@resumeOK: pop eax
mov al,1
ret 4
@@onlyOwner: xor eax,eax
lock xchg eax,[ecx].tMutexSem.Owner
mov al,1
end;
function fmsCheck; assembler {&uses none};
asm mov eax,Sem
mov eax,[eax].tMutexSem.Owner
and eax,7FFFFFFFh
setz al
end;
function GetResourceString(ID : Longint) : string;
var
pS : pByte;
I : Integer;
S : string;
begin
if DosGetResource(nullHandle, rt_String, ID div 16 + 1, Pointer(pS)) <> 0
then begin
GetResourceString := '';
exit;
end;
Inc(pS, sizeOf(Word16)); {skip codepage}
For I := 1 to ID and $0F do Inc(pS, succ(pS^));
Move(pS^, S, pS^);
Dec(byte(S[0]));
DosFreeResource(pS);
GetResourceString := S;
end;
Function unlockModule(const fName : string) : boolean;
var
tmp : array[0..256] of Char;
begin
unlockModule := DosReplaceModule(strPCopy(tmp, fName), nil, nil) = 0;
end;
{$endIf}
procedure tCommandLineParser.Parse;
begin
PreProcess(S);
While S <> '' do
begin
While (S <> '') and ((S[1] = ' ') or (S[1] = #9)) do
Delete(S, 1, 1);
if S <> ''
then if (S[1] in ['/','-'])
then begin
Delete(S, 1, 1);
if (S <> '') then Delete(S, 1, ParmHandler(S));
end
else Delete(S, 1, NameHandler(S));
end;
end;
procedure tCommandLineParser.ParseCommandLine;
var
ParmStr : string;
begin
{$ifDef OS2}
if CmdLine = nil
then ParmStr := ''
else ParmStr := StrPas(GetASCIIZptr(CmdLine^, 2));
{$else}
Move(mem[PrefixSeg:$80], ParmStr, succ(mem[PrefixSeg:$80]));
{$endIf}
Parse(ParmStr);
end;
Function tCommandLineParser.GetWord;
var
I,J : Word;
fCh : Char;
begin
I := StartChar;
if (I <= length(ParmStr)) and (not (ParmStr[I] in [#9,' ','/','-']))
then begin
J := I;
if ParmStr[I] = '"'
then fCh := '"'
else fCh := ' ';
repeat
Inc(I);
until (I > length(ParmStr)) or (ParmStr[I] = fCh);
if fCh = '"'
then begin DestStr := Copy(ParmStr, succ(J), pred(I - J)); Inc(I); end
else DestStr := Copy(ParmStr, J, I - J);
end
else DestStr := '';
GetWord := I - StartChar;
end;
function tCommandLineParser.GetOpt;
var
I,J,K : Longint;
Ch : Char;
fCh : boolean;
begin
K := StartChar; I := 0;
fCh := TRUE;
repeat
if StartChar <= length(parmStr)
then Ch := UpCase(ParmStr[StartChar])
else Ch := ' ';
case Ch of
'-' : begin
if fCh then I := OptFlags[high(OptFlags)];
Option := Option and (not I);
I := 0;
end;
':',
'+' : begin
if fCh then I := OptFlags[high(OptFlags)];
Option := Option or I;
I := 0;
if Ch = ':' then break;
end;
else begin
J := First(Ch, OptChars);
if J = 0
then begin
if fCh then I := OptFlags[high(OptFlags)];
Option := Option or I;
break;
end
else I := I or OptFlags[pred(J) + low(OptFlags)];
end;
end;
fCh := FALSE;
Inc(StartChar);
until FALSE;
GetOpt := StartChar - K;
end;
function tCommandLineParser.ParmHandler;
var
I : Integer;
begin
I := 0; While (I < length(ParmStr)) and (ParmStr[succ(I)] <= ' ') do Inc(I);
ParmHandler := I;
end;
function tCommandLineParser.NameHandler;
begin
NameHandler := ParmHandler(ParmStr);
end;
procedure tCommandLineParser.PreProcess;
begin
end;
procedure tCommandLineParser.PostProcess;
begin
end;
end.