summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d41744a)
raw | patch | inline | side by side (parent: d41744a)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Fri, 14 Feb 2020 19:55:59 +0000 (22:55 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Fri, 14 Feb 2020 19:55:59 +0000 (22:55 +0300) |
src/generic/Dsw/Mod/Opts.cp | patch | blob | history |
index 079bf616c69a57a91cfc14789097600104100a91..f4fc7d110d35ace6fab6b5603695e6ab660485a3 100644 (file)
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;
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;