
SECTION "DecodeArgs"

GET "LibHdr"

STATIC {
   dummy = #x4e524556;
   version = 1*256+2 }

MANIFEST $(
   DeleteChar = 127 $);

LET RdArgs(keys, argv, size) = VALOF
$( LET w = argv;
   LET numbargs = ?;

   !w := 0;
   FOR p = 1 TO keys%0 DO
   $( LET kch = keys%p;
      IF kch='/' THEN $(
	 LET c = CapitalCh(keys%(p+1));
	 IF c='A' THEN !w := !w | 1;
	 IF c='K' THEN !w := !w | 2;
	 IF c='S' THEN !w := !w | 4;
	 LOOP $);
      IF kch=',' THEN $(
	 w := w+1;
	 !w := 0 $) $);
   w := w+1;
   numbargs := w-argv;

// At this stage, the argument elements of argv have been
// initialised to  0	-
//		   1   /A
//		   2   /K
//		   3   /A/K
//		   4   /S
//		   5   /S/A
//		   6   /S/K
//		   7   /S/A/K

   $( LET argno = -1;
      LET wsize = size+argv-w;

      SWITCHON RdItem(w, wsize) INTO
      $( DEFAULT:
err:	 $( LET ch = ?;
	    ch := RdCh() REPEATUNTIL ch='*N' | ch='*E' |
				     ch=EndStreamCh
	 $)
	 CASE -3:
	    result2 := 120;
	    RESULTIS 0

	 CASE 0:  // *N, EndStreamCh
	    FOR i = 0 TO numbargs-1 DO $(
	       LET a = argv!i;
	       IF 0<=a<=7 THEN
		  TEST (a&1)=0 THEN
		     argv!i := 0
		  ELSE
		     GOTO err $);
	    RdCh();
	    RESULTIS w

	 CASE 1:  // keyword name
	    argno := FindArg(keys, w);
	    TEST argno>=0 THEN
	       TEST 4<=argv!argno<=7 THEN $( // no value for key.
		  argv!argno := -1;
		  LOOP $)
	       ELSE $(
		  LET item = RdItem(w, wsize);
		  IF item=-2 THEN item := RdItem(w, wsize);
		  IF item<=0 THEN GOTO err $)
	    ELSE TEST RdCh()='*N' & FindArg("HELP,?", w)>=0 THEN $(
	       // help facility
	       WriteF("Arguments %S: ", keys);
	       ENDCASE $)
	    ELSE {
	       UnRdCh();
	       GOTO err }

	 CASE 2:  // quoted item (i.e. arg value)
	    IF argno<0 THEN
	       FOR i = 0 TO numbargs-1 DO SWITCHON argv!i INTO
	       $( CASE 0: CASE 1:
		    argno := i;
		    BREAK
		  CASE 2: CASE 3:
		    GOTO err
	       $);
	    IF argno<0 THEN GOTO err;
	    argv!argno := w;
	    w := w+w%0/BytesPerWord+1
      $)
   $) REPEAT
$)

// Read an item from command line
// returns -3	 escape
//	   -2	 "=" Symbol
//	   -1	 error
//	    0	 *N or EndStreamCh
//	    1	 keyword
//	    2	 nonkeyword (maybe quoted)

AND RdItem(v, size) = VALOF
$( LET p = 0;
   LET pmax = (size+1)*BytesPerWord-1;
   LET ch = ?;
   LET quoted, keyword = FALSE, FALSE;

   FOR i = 0 TO size DO v!i := 0;

   ch := RdCh() REPEATWHILE ch='*S';

   TEST ch='"' THEN $(
      quoted := TRUE;
      ch := RdCh() $)
   ELSE IF ch='-' THEN $(
      keyword := TRUE;
      ch := RdCh() $);

   UNTIL ch='*N' | ch=EndStreamCh DO
   $( IF ch='*E' THEN RESULTIS -3;  // escape has been pressed
      TEST quoted THEN $(
	 IF ch='"' THEN RESULTIS 2;
	 IF ch='**' THEN $(
	    ch := RdCh();
	    IF CapitalCh(ch)='E' THEN ch := '*E';
	    IF CapitalCh(ch)='N' THEN ch := '*N' $) $)
      ELSE IF ch=';' | ch='=' |
	      (ch='*S' & p>0 & v%1~='**') THEN
	 BREAK;
      IF p=pmax THEN RESULTIS -1;
      v%(p+1) := ch;
      p := (ch=DeleteChar -> (p=0 -> 0, p-1), p+1);
      v%0 := p;
      ch := RdCh() $);

   IF quoted THEN RESULTIS -1;
   UnRdCh();
   TEST p=0 THEN
      TEST ch='=' THEN $(
	 RdCh();
	 RESULTIS -2 $)
      ELSE
	 RESULTIS 0
   ELSE
      RESULTIS keyword -> 1, 2
$)

AND FindArg(keys, w) = VALOF  // =argno if found, =-1 otherwise
$( MANIFEST $( matching = 0; skipping = 1 $);
   LET state, wp, argno = matching, 0, 0;

   FOR i = 1 TO keys%0 DO $(
      LET kch = keys%i;
      IF state=matching THEN $(
	 IF (kch='=' | kch='/' | kch=',') & wp=w%0 THEN
	    RESULTIS argno;
	 wp := wp+1;
	 IF compch(kch,w%wp)~=0 THEN state := skipping $);
      IF kch=',' | kch='=' THEN state, wp := matching, 0;
      IF kch=',' THEN argno := argno+1$);
   IF state=matching & wp=w%0 THEN RESULTIS argno;
   RESULTIS -1
$)
