DEADSOFTWARE

remove generic parser from DswOpts
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 14 Feb 2020 19:55:59 +0000 (22:55 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 14 Feb 2020 19:55:59 +0000 (22:55 +0300)
src/generic/Dsw/Mod/Opts.cp

index 079bf616c69a57a91cfc14789097600104100a91..f4fc7d110d35ace6fab6b5603695e6ab660485a3 100644 (file)
@@ -1,17 +1,6 @@
 MODULE DswOpts;
 
-  IMPORT Kernel, Log;
-
-  CONST
-    (* symbol *)
-    null* = 0; opt* = 1; char* = 2; string* = 3; ident* = 4; eos* = 5; eof* = 6;
-
-    (* scanner options *)
-    options* = 0; strings* = 1; identifiers* = 2; chars* = 3; terminators* = 4;
-    emptystr* = 5; emptyident* = 6; invalid* = 7;
-
-    (* errors *)
-    ok* = 0; unkopt* = 1; missarg* = 2;
+  IMPORT Kernel;
 
   TYPE
     String* = POINTER TO ARRAY OF CHAR;
@@ -21,134 +10,58 @@ MODULE DswOpts;
     args: POINTER TO ARRAY OF String;
     argn-, argi-: INTEGER; 
     str-: String;
-    ch-: CHAR;
-    opts*: SET;
-
-  PROCEDURE Skip (n: INTEGER);
-  BEGIN
-    ASSERT(n >= 0, 20);
-    ASSERT(argn < LEN(args), 21);
-    ASSERT(argi + n <= LEN(args[argn]$), 22);
-    INC(argi, n)
-  END Skip;
 
   PROCEDURE IsOpt (ch: CHAR): BOOLEAN;
   BEGIN
-    RETURN (CAP(ch) >= "A") & (CAP(ch) <= "Z") OR (ch >= "0") & (ch <= "9") OR (ch = "-")
+    RETURN (CAP(ch) >= "A") & (CAP(ch) <= "Z") OR (ch >= "0") & (ch <= "9")
   END IsOpt;
 
-  PROCEDURE IsIdentStart (ch: CHAR): BOOLEAN;
-  BEGIN
-    RETURN (CAP(ch) >= "A") & (CAP(ch) <= "Z") OR (ch = "_")
-  END IsIdentStart;
-
-  PROCEDURE IsIdent (ch: CHAR): BOOLEAN;
+  PROCEDURE Reset*;
   BEGIN
-    RETURN (CAP(ch) >= "A") & (CAP(ch) <= "Z") OR (ch = "_") OR (ch >= "0") & (ch <= "9")
-  END IsIdent;
+    argn := 1; argi := 0; str := NIL; optMode := FALSE;
+  END Reset;
 
-  PROCEDURE Get* (VAR x: BYTE);
-    VAR i, j, len: INTEGER; sym: BYTE; c: CHAR;
+  PROCEDURE GetStr;
+    VAR ch: CHAR; i, beg, len: INTEGER;
   BEGIN
-    ch := 0X; str := NIL;
-    IF argn >= LEN(args) THEN
-      optMode := FALSE; sym := eof
-    ELSE
-      sym := null;
-      c := args[argn, argi];
-      IF c = 0X THEN
-        optMode := FALSE; INC(argn); argi := 0;
-        IF terminators IN opts THEN sym := eos; (* !!! *)
-        ELSIF argn >= LEN(args) THEN sym := eof (* !!! *)
-        ELSE c := args[argn, argi] (* continue parsing *)
-        END
+    str := NIL;
+    IF argn < LEN(args) THEN
+      beg := argi;
+      REPEAT ch := args[argn, argi]; INC(argi) UNTIL ch = 0X;
+      len := argi - beg;
+      NEW(str, len + 1);
+      FOR i := 0 TO len - 1 DO
+        str[i] := args[argn, beg + i] (* zero not copied *)
       END;
-      IF sym = null THEN
-        IF (options IN opts) & (optMode & IsOpt(c) OR (c = "-") & IsOpt(args[argn, argi + 1])) THEN
-          sym := opt;
-          IF optMode THEN
-            ch := c; optMode := TRUE; Skip(1)
-          ELSE
-            ch := args[argn, argi + 1]; optMode := TRUE; Skip(2)
-          END
-        ELSIF (identifiers IN opts) OR (strings IN opts) THEN
-          len := 0; i := argi; sym := null;
-          (* --- get length of identifier --- *)
-          IF (identifiers IN opts) & (IsIdentStart(args[argn, i]) OR (emptyident IN opts)) THEN
-            WHILE IsIdent(args[argn, i]) DO
-              INC(len);
-              INC(i)
-            END;
-            sym := ident
-          END;
-          (* --- get length of string --- *)
-          IF strings IN opts THEN
-            WHILE args[argn, i] # 0X DO
-              INC(len);
-              INC(i)
-            END;
-            sym := string
-          ELSIF (identifiers IN opts) & (args[argn, i] # 0X) & ~(invalid IN opts) THEN
-            WHILE args[argn, i] # 0X DO INC(i) END;
-            sym := null
-          END;
-          (* --- copy string --- *)
-          IF (sym # null) & ((len > 0) OR (sym = string) & (emptystr IN opts) OR (sym = ident) & (emptyident IN opts)) THEN
-            NEW(str, len + 1);
-            FOR j := 0 TO len - 1 DO
-              str[j] := args[argn, argi + j]
-            END;
-            str[len] := 0X
-          END;
-          optMode := FALSE;
-          Skip(i - argi)
-        ELSIF chars IN opts THEN
-          ch := c; optMode := FALSE; Skip(1)
-        ELSE
-          optMode := FALSE; sym := null; Skip(1)
-        END
-      END
-    END;
-    x := sym
-  END Get;
-
-  PROCEDURE Reset*;
-  BEGIN
-    argn := 1; argi := 0; ch := 0X; str := NIL; optMode := FALSE;
-    opts := {options, strings, emptystr}
-  END Reset;
+      INC(argn); argi := 0; optMode := FALSE
+    END
+  END GetStr;
 
   PROCEDURE GetOpt* (IN optstring: ARRAY OF CHAR): CHAR;
-    VAR save: SET; sym: BYTE; c: CHAR; i, mode: INTEGER;
+    VAR opt, ch: CHAR; i: INTEGER;
   BEGIN
-    save := opts; opts := {options, strings, emptystr}; c := 0X;
-    Get(sym);
-    IF sym = opt THEN
-      c := ch; i := 0;
-      WHILE (optstring[i] # 0X) & (optstring[i] # c) DO
-        INC(i);
-        WHILE optstring[i] = ":" DO
-          INC(i)
-        END
-      END;
-      IF optstring[i] = c THEN
-        opts := {strings, emptystr}; mode := 0; INC(i);
-        WHILE optstring[i] = ":" DO
-          INC(mode);
-          INC(i)
-        END;
-        IF mode # 0 THEN Get(sym);
-          IF (sym # string) & (mode = 1) THEN
-            NEW(str, 2); str[0] := c; c := ":"
-          END 
+    IF argn >= LEN(args) THEN
+      opt := 0X; optMode := FALSE (* eof *)
+    ELSIF optMode & IsOpt(args[argn, argi]) OR (args[argn, argi] = "-") & IsOpt(args[argn, argi + 1]) THEN
+      IF ~optMode THEN optMode := TRUE; INC(argi) END;
+      opt := args[argn, argi]; INC(argi); i := 0;
+      IF args[argn, argi] = 0X THEN INC(argn); argi := 0; optMode := FALSE END;
+      REPEAT
+        ch := optstring[i]; INC(i);
+        IF ch = ":" THEN ch := optstring[i]; INC(i) END
+      UNTIL (ch = opt) OR (ch = 0X);
+      IF ch = opt THEN
+        IF optstring[i] = ":" THEN
+          GetStr;
+          IF str = NIL THEN
+            NEW(str, 2); str[0] := opt; opt := ":" (* missing param *)
+          END
         END
-      ELSE NEW(str, 2); str[0] := c; c := "?"
+      ELSE NEW(str, 2); str[0] := opt; opt := "?" (* unknown option *)
       END
-    ELSIF sym = eof THEN c := 0X (* eof *)
-    ELSE c := "$" (* string *)
+    ELSE GetStr; opt := "$" (* string *)
     END;
-    opts := save;
-    RETURN c
+    RETURN opt
   END GetOpt;
 
   PROCEDURE Init;