atari: implement ARGV protocol for runtime startup

This commit is contained in:
Thorsten Otto 2022-01-31 16:19:24 +01:00 committed by FPK
parent 41d4e181ea
commit fecb72fea3
2 changed files with 94 additions and 35 deletions

View File

@ -14,11 +14,23 @@
**********************************************************************}
(* define this symbol to get ARGV argument passing that's strictly
* compatible with the Atari standard. If it's not defined, then
* the startup code won't validate the ARGV= variable by checking
* the command byte for 127. Note that there are still some
* applications (gulam is a notable example) that implement only
* part of the standard and don't set the command byte to 127.
*)
{$IF 0}
{$DEFINE STRICTLY_COMPATIBLE_WITH_STANDARD }
{$ENDIF}
{ Generates correct argument array on startup }
procedure GenerateArgs;
var
ArgVLen: LongInt;
LocalIndex: Word;
len: Integer;
procedure AllocArg(Idx, Len: LongInt);
var
@ -35,69 +47,116 @@ var
ArgV[Idx] := SysAllocMem(Succ(Len));
end;
function scan_argv : boolean;
var
hp, start : pchar;
len: integer;
begin
hp:=basepage^.p_env;
result:=false;
if (hp=nil) then
exit;
LocalIndex := 0;
while hp^<>#0 do
begin
if (hp[0] = 'A') and (hp[1] = 'R') and (hp[2] = 'G') and (hp[3] = 'V') and (hp[4] = '=') then
begin
{ in any case, terminate environment here }
hp[0] := #0;
hp[1] := #0;
{ skip ARGV= string }
hp := hp + 5;
if (hp[0] = 'N') and (hp[1] = 'U') and (hp[2] = 'L') and (hp[3] = 'L') and (hp[4] = ':') then
begin
{ TODO: handle NULL arguments }
end;
{$ifdef STRICTLY_COMPATIBLE_WITH_STANDARD}
if (len <> 127) then
exit;
{$endif}
{ skip ARGV= value }
while hp^<>#0 do
inc(hp);
inc(hp);
{ get arguments }
while hp^<>#0 do
begin
start := hp;
while hp^<>#0 do
inc(hp);
len := hp - start;
allocarg(localindex,len);
move(start^,argv[localindex]^,len);
argv[localindex][len]:=#0;
inc(localindex);
inc(hp);
end;
argc:=localindex;
result := true;
exit;
end;
hp := hp + strlen(hp) + 1;
end;
end;
var
Count: Word;
Start: Word;
Ende: Word;
LocalIndex: Word;
i: Integer;
P : PChar;
Temp : AnsiString;
InQuotes: boolean;
begin
P := Args;
ArgVLen := 0;
{ Set argv[0] }
Temp := ParamStr(0);
AllocArg(0, Length(Temp));
Move(Temp[1], Argv[0]^, Length(Temp));
Argv[0][Length(Temp)] := #0;
{ check ARGV usage indicator }
len := ord(P[0]);
if scan_argv then
exit;
{ Set argv[0] }
AllocArg(0, 0);
Argv[0][0] := #0;
{ just in case; commandline cannot be longer }
if len > 127 then
begin
argc := 1;
exit;
end;
InQuotes := False;
{ Handle the other args }
Count := 0;
p[len + 1] := #0;
Count := 1;
{ first index is one }
LocalIndex := 1;
while (P[Count] <> #0) do
begin
while (p[count]=' ') or (p[count]=#9) or (p[count]=LineEnding) do
while (P[Count] <> #0) and (p[count]<=#32) do
Inc(count);
if p[count] = '"' then
begin
inQuotes := True;
Inc(Count);
end;
start := count;
if inQuotes then
begin
while (p[count]<>#0) and (p[count]<>'"') and (p[count]<>LineEnding) do
begin
Inc(Count)
end;
start := count;
while (p[count]<>#0) and (p[count]<>'"') and (p[count]>=#32) do
Inc(Count);
ende := count;
if (p[count] = '"') then
Inc(Count);
end else
begin
while (p[count]<>#0) and (p[count]<>' ') and (p[count]<>#9) and (p[count]<>LineEnding) do
start := count;
while (p[count]<>#0) and (p[count]>#32) do
inc(count);
ende := count;
end;
ende := count;
if not inQuotes then
begin
while (p[start]=' ') and (Start < Ende) do
Inc(Start)
end;
if (ende-start>0) then
if (ende>start) then
begin
allocarg(localindex,ende-start);
move(p[start],argv[localindex]^,ende-start);
argv[localindex][ende-start]:=#0;
if inQuotes and (argv[localindex][(ende-start) - 1] = '"') then
argv[localindex][(ende-start)-1] := #0;
inc(localindex);
end;
if inQuotes and (p[count] = '"') then
Inc(Count);
inQuotes := False;
end;
argc:=localindex;
end;
@ -119,6 +178,6 @@ var
s1: string;
begin
ParamStr := '';
if (l > 0) and (l + 1 <= argc) then
if (l >= 0) and (l < argc) then
ParamStr := StrPas(argv[l]);
end;

View File

@ -119,7 +119,7 @@ var
procedure SysInitParamsAndEnv;
begin
// [0] index contains the args length...
args:=@basepage^.p_cmdlin[1];
args:=@basepage^.p_cmdlin[0];
GenerateArgs;
end;