瀏覽代碼

atari: implement ARGV protocol for runtime startup

Thorsten Otto 3 年之前
父節點
當前提交
fecb72fea3
共有 2 個文件被更改,包括 93 次插入34 次删除
  1. 92 33
      rtl/atari/syspara.inc
  2. 1 1
      rtl/atari/system.pp

+ 92 - 33
rtl/atari/syspara.inc

@@ -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;
 
+  { check ARGV usage indicator }
+  len := ord(P[0]);
+  if scan_argv then
+    exit;
+
   { Set argv[0] }
-  Temp := ParamStr(0);
-  AllocArg(0, Length(Temp));
-  Move(Temp[1], Argv[0]^, Length(Temp));
-  Argv[0][Length(Temp)] := #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;

+ 1 - 1
rtl/atari/system.pp

@@ -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;