{$A-} PROGRAM TOOLS; {$I TOOLU.PAS} PROCEDURE INITCMD; { Initialize command line; modified for double quotes } { Pipes added -- Willett Kempton, 3 January 1985 } { Multiple processes (sequential) added -- WK, 5 January 1985 } CONST PIPE = BAR; SEQPRCS = SEMICOL; VAR FD,FDJUNK:FILEDESC; FNAME:XSTRING; FT:FILTYP; IDX:1..MAXSTR; JSKIP:INTEGER; PendingProcess, { local variable only } JUNK:BOOLEAN; i,DEBUG2: INTEGER; BEGIN CMDFIL[STDIN]:=STDIO; { make STDOUT and STDERR normal buffered files; this eliminates one layer of if checks and procedure calls } NAMESTR(FNAME,'CON:'); for FD := STDOUT to STDERR do begin CMDFIL[FD] := CLOSED; FDJUNK := MUSTOPEN(FNAME,IOWRITE); end; { CMDFIL[STDOUT]:=STDIO; CMDFIL[STDERR]:=STDIO; } FOR FD:=SUCC(STDERR) TO MAXOPEN DO CMDFIL[FD]:=CLOSED; KBDN:=0; if EntryFromHost then begin writeln('Software tools, version ',Version, ', type "help" for command list'); PendingProcess := FALSE; SetEntryFromHost(FALSE); end else PendingProcess := ActiveProcessQ; FromPipe := PendingProcess and (PipeCount > 0); if PendingProcess then begin SCOPY(ProcessQueue,1,CMDLIN,1); if Debug or ListProcess then PUTSTR(CMDLIN,STDERR); if FromPipe then begin XCLOSE(STDIN); GenPipeName(PipeCount,FNAME); FD := MUSTOPEN(FNAME,IOREAD); end; end else begin PipeCount := 0; write(ShellPrompt); ReadingShellCmd := true; { flag for GETKBD } if (not getline(cmdlin,STDIN,MAXSTR)) then begin writeln(' eof to shell'); ExitToHost; end; ReadingShellCmd := false; end; CMDARGS:=0; JSKIP:=0; { counts quotes already skipped } IDX:=1; WHILE (not (CMDLIN[IDX] in [ENDSTR,NEWLINE,PIPE,SEQPRCS])) DO BEGIN WHILE((CMDLIN[IDX]=BLANK)AND(JSKIP MOD 2 <>1))DO IDX:=IDX+1; IF NOT(CMDLIN[IDX] IN [NEWLINE,PIPE,SEQPRCS]) THEN BEGIN { next argument } CMDARGS:=CMDARGS+1; CMDIDX[CMDARGS]:=IDX-JSKIP; WHILE((CMDLIN[IDX]<>NEWLINE) AND (NOT(CMDLIN[IDX] IN [BLANK,PIPE,SEQPRCS])OR(ODD(JSKIP)))) DO BEGIN IF (CMDLIN[IDX]=DQUOTE) THEN JSKIP:=JSKIP+1 ELSE CMDLIN[IDX-JSKIP]:=CMDLIN[IDX]; IDX := IDX+1; END; if (CMDLIN[IDX] IN [PIPE,SEQPRCS]) then for i:= MAXSTR downto (IDX-JSKIP+1) do { don't overwrite } CMDLIN[i] := CMDLIN[i-1]; CMDLIN[IDX-JSKIP]:=ENDSTR; IDX:=IDX+1; { redirection } IF (CMDLIN[CMDIDX[CMDARGS]]=LESS) THEN BEGIN XCLOSE(STDIN); CMDIDX[CMDARGS]:=CMDIDX[CMDARGS]+1; JUNK:=GETARG(CMDARGS,FNAME,MAXSTR); FD:=MUSTOPEN(FNAME,IOREAD); CMDARGS:=CMDARGS-1; END ELSE IF (CMDLIN[CMDIDX[CMDARGS]]=GREATER) THEN BEGIN XCLOSE(STDOUT); CMDIDX[CMDARGS]:=CMDIDX[CMDARGS]+1; JUNK:=GETARG(CMDARGS,FNAME,MAXSTR); FD:=MUSTCREATE(FNAME,IOWRITE); CMDARGS:=CMDARGS-1; END ELSE IF Debug then BEGIN WRITE(' arg ',CMDARGS:1,' '); DEBUG2 := CMDIDX[CMDARGS]; WHILE CMDLIN[DEBUG2]<>ENDSTR DO BEGIN WRITE(CHR(CMDLIN[DEBUG2])); DEBUG2:=DEBUG2+1; END; WRITELN; END END END; ToPipe := CMDLIN[IDX] = PIPE; ActiveProcessQ := ToPipe or (CMDLIN[IDX]=SEQPRCS); if ActiveProcessQ then begin SCOPY(CMDLIN,(IDX+1),ProcessQueue,1);{ preserve remainder of command } if ToPipe then begin XCLOSE(STDOUT); PipeCount := PipeCount+1; GenPipeName(PipeCount,FNAME); FD := MUSTCREATE(FNAME,IOWRITE); end; end; END { INITCMD }; procedure Shell; { Chain to proper file } VAR CMDPTR:FILE; str:STRING80; COMMAND:XSTRING; DONE:BOOLEAN; I, Chapter, Position:INTEGER; CONST (* This is horribly non-standard (only Turbo), but saves memory *) AllCmds: array[0..8] of string [54] = (* must have blank before AND after each command *) (' quit help ', ' charcount copy linecount wordcount detab list shell ', ' entab overstrike compress expand echo translit ', ' compare include concat print makecopy archive ', ' sort unique kwic unrotate ', { ' rotate ' not supported } ' find change ', ' edit ', ' format ', ' define macro '); procedure GiveHelp; var ch: integer; begin writeln; writeln('Commands:'); for ch:= 1 to 8 do begin write(AllCmds[ch]); if ch in[1..3,6] then writeln end; writeln(AllCmds[0]); writeln; writeln('Symbols:'); write(' ''|'' pipe, '';'' next process,'); writeln(' redirection: ''>'' to file, ''<'' from file.'); write(' ''^Z'' (control-Z) terminate console input,'); writeln(' " " quote arguments.'); writeln; end { GiveHelp }; function LowCase(c:char):char; begin if c in ['A'..'Z'] then LowCase := char(ord(c)+32) else LowCase := c; end; PROCEDURE SETCHAIN(chapnum:char); var len : integer; tempstr:string80; BEGIN ASSIGN(CMDPTR,CONCAT(SystemDrive,'CHAPTER',chapnum,'.CHN')); (* put non-abbreviated form in global variable *) len := length(AllCmds[Chapter]); tempstr := copy(AllCmds[Chapter],(Position+1),(len-Position)); GlobalArg1 := copy( tempstr, 1, (pos(' ',tempstr)-1) ); (* strip commands after *) DONE:=TRUE END; BEGIN { Shell } DONE:=FALSE; repeat INITCMD; IF GETARG(1,COMMAND,MAXSTR) THEN BEGIN str:=' '; FOR I:=1 TO XLENGTH(COMMAND) DO str := CONCAT(str,LowCase(chr(COMMAND[I]))); if not Abbreviate then str := concat(str,' '); Chapter := -1; repeat Chapter := Chapter + 1; Position := Pos(str,AllCmds[Chapter]); { Turbo, nonstandard } until (Chapter=9) or (Position>0); if Chapter=0 then {pseudo-chapter "0"} begin if Position=1 then ExitToHost else GiveHelp end else if Position>0 then SETCHAIN(chr(Chapter+ord('0'))) { good command, real chapter } else { bad command } BEGIN WRITELN(str,'?');DONE:=FALSE END; END { IF GETARG }; until DONE; CHAIN(CMDPTR) { <-- if I/O Error 01, check configuration in TOOLU.PAS } END { Shell }; BEGIN Shell; END.