MS-DOS/v2.0/bin/FILBP.PAS
2018-09-21 17:53:34 -07:00

167 lines
6.0 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{$title: 'Command Line Filename Parser' $linesize:79}
MODULE parse; {$debug- $stackck+}
{ command line filename parsing; Bob Wallace Microsoft 7/81 }
CONST maxfile = 32; {NOTE: must be set same as caller}
dfprf = 'PRF';
msprf = 'Profile filename [';
dfhst = 'HST';
mshst = 'Histogram filename [';
dfmap = 'MAP';
msmap = 'Map file [';
nuln = 'NUL ';
TYPE
filenam = lstring (maxfile); {filename parameter type}
setsw = ARRAY [wrd(0)..3] OF byte; {switches parameter type}
sets = set of 0..31; {caller's parameter type}
setc = set of chr(0)..chr(127); {set of characters}
cpmex = string (3); cpmnm = string (8);
cpmfn = RECORD
cfd [0]: string (2);
cfn [2]: cpmnm; cfp [10]: char; cfe [11]: cpmex;
END;
setbitt = ARRAY [wrd(0)..7] OF byte;
CONST setbit = setbitt (128, 64, 32, 16, 8, 4, 2, 1);
VAR idset:setc; VALUE idset:=setc ['A'..'Z','a'..'z','0'..'9',
'$', '&', '#', '@', '!', '%', '-', '_', '`', '''',
'(', ')', '<', '>', '{', '}', '\', '^', '~', '|'];
VAR drset:setc; VALUE drset:=setc ['A'..'O','a'..'o'];
PROCEDURE fillc (dst: adrmem; len: word; chc: char); extern;
PROCEDURE movel (prf: adrmem; dst: adrmem; len: word); extern;
PROCEDURE ptyuqq (len: word; prf: adsmem); extern;
PROCEDURE plyuqq; extern;
FUNCTION gtyuqq (len: word; dst: adsmem): word; extern;
PROCEDURE filbm
(VAR prffil,hstfil,mapfil: filenam; VAR oldsw: setsw);
(* sets the filenames for source, hstect, listing, and second
listing (hstect list or cross ref); also sets any switches,
allowing those in the oldsw set and returning them in oldsw *)
VAR prf, hst, map: cpmfn; {target filenames in CPM format}
newsw: setsw; {new switches, return in oldsw}
qq: lstring (128); iq: word; {command line, current index}
pqq: ads of lstring (128); {address CPM-type command line}
cesxqq [extern]: word; {segment val}
c: char; l: word; iscomma: boolean; i: word; {other stuff}
FUNCTION parchr (ch: char): boolean; {true iff CH found}
BEGIN
parchr := (iq <= qq.len) AND (qq [iq] = ch);
IF result (parchr) THEN iq := iq+1;
END;
FUNCTION upperc: char; {return current char, in upper case}
BEGIN
upperc := qq[iq];
IF result (upperc) >= 'a'
THEN upperc := chr (ord (result (upperc)) - 32);
END;
PROCEDURE blanks; {skip blanks and set any switches}
BEGIN
WHILE parchr (' ') DO {nothing};
IF parchr ('/') THEN
BEGIN
IF (iq <= qq.len)
AND THEN (ord (upperc) - 64) IN retype (sets, oldsw)
THEN
BEGIN
i := wrd (upperc) - 64; iq := iq + 1;
newsw[i DIV 8] := newsw[i DIV 8] OR setbit[i MOD 8];
blanks; {recurse for more}
END
ELSE iq := iq - 1; {put "/" back on line to get error}
END;
END;
FUNCTION parset (VAR dst: string; CONST chs: setc): boolean;
(* Move characters from qq to DST as long as they are in CHS
Deletes from qq, blanks DST, returns true if any moved *)
VAR i: word;
BEGIN
fillc (adr dst, wrd (upper (dst)), ' '); parset := false;
FOR i := 1 TO wrd (upper (dst)) DO
IF (iq > qq.len) OR ELSE NOT (qq [iq] IN chs)
THEN BREAK
ELSE
BEGIN
dst [i] := upperc; parset := true; iq := iq + 1;
END;
END;
FUNCTION filenm (CONST prompt: string; VAR nam: filenam;
VAR fcb: cpmfn; defext: cpmex): boolean;
(* Get a filename into the FCB, setting defaults as
appropriate; return true iff a filename found *)
VAR i: word; p: adrmem; defile: cpmnm;
BEGIN
blanks;
IF iscomma THEN defile := prf.cfn ELSE defile := nuln;
IF iq > qq.len THEN
BEGIN
ptyuqq (wrd (upper (prompt)), ads prompt);
FOR i := 1 TO 8 DO
IF defile [i] <> ' ' THEN ptyuqq (1, ads defile [i]);
ptyuqq (1, ads '.'); ptyuqq (3, ads defext);
ptyuqq (3, ads ']: ');
qq.len := gtyuqq (upper (qq), ads qq [1]); iq := 1;
END;
fcb.cfp := '.';
IF (iq < qq.len) AND (qq [iq+1] = ':')
AND THEN parset (c, drset)
THEN
BEGIN
fcb.cfd[1] := c; fcb.cfd[2] := ':'; iq := iq+1;
defile := prf.cfn; {default to source name now}
END
ELSE fcb.cfd := ' ';
filenm := parset (fcb.cfn, idset);
IF parchr (':')
THEN BEGIN fcb.cfe := ': '; fcb.cfp := ' '; END
ELSE
IF parchr ('.')
THEN [eval (parset (fcb.cfe, idset)); defile := prf.cfn]
ELSE fcb.cfe := defext;
IF NOT result (filenm) THEN fcb.cfn := defile;
blanks;
nam.len := 0; p := adr fcb;
FOR i := 0 TO 13 DO IF p^[i] <> wrd (' ')
THEN [nam.len := nam.len+1; nam[nam.len] := chr (p^[i])];
END;
FUNCTION conso (CONST fn: cpmnm): boolean;
BEGIN
conso := (fn = 'CON ') OR (fn = 'USER ');
END;
BEGIN
newsw := setsw (do 4 of 0);
pqq.r := 128; pqq.s := cesxqq;
FOR i := 0 TO pqq^.len+1 DO qq[i] := pqq^[i]; iq := 1;
REPEAT
iscomma := true; prf.cfn := ' ';
IF filenm (msprf, prffil, prf, dfprf)
THEN
BEGIN
eval (parchr (','));
eval (filenm (mshst, hstfil, hst, dfhst));
iscomma := parchr (',');
eval (filenm (msmap, mapfil, map, 'map'));
blanks; eval (parchr (';')); blanks;
IF hst.cfn <> nuln THEN newsw[3] := newsw[3] OR 8;
IF map.cfn <> nuln THEN newsw[3] := newsw[3] OR 04;
IF conso (map.cfn) THEN newsw[3] := newsw[3] OR 01;
IF iq > qq.len THEN [oldsw := newsw; return];
END;
ptyuqq (15, ads 'Line invalid: '''); i := qq.len - iq + 1;
IF i > 0 THEN ptyuqq (i, ads qq [iq]);
ptyuqq (15, ads ''', start again.'); plyuqq; iq := 256;
UNTIL FALSE;
END;
END.