-- MTypeImpl.Mesa, last edit February 8, 1983 4:46 pm
-- Pilot 6.0/ Mesa 7.0
-- main program for the mesa type program
DIRECTORY
CWF: TYPE USING [SetWriteProcedure, WF0, WF1, WF2, WFCR],
IO: TYPE USING[Handle, PutChar, UserAbort],
Rope: TYPE USING[ROPE, Text],
RopeInline: TYPE USING[InlineFlatten],
UnsafeSTP: TYPE USING [Error],
STPSubr: TYPE USING [PatternGeneralOpen, RetrieveProcType, StopSTP],
String: TYPE USING [AppendChar, AppendString, UpperCase],
Subr: TYPE USING [AbortMyself, debugflg, errorflg, GetLine, MakeTTYProcs,
strcpy, TTYProcs],
UECP: TYPE USING[Argv, Parse],
UserExec: TYPE USING[AcquireResource, AskUser, CommandProc, GetStreams,
RegisterCommand, ReleaseResource];
MTypeImpl: PROGRAM
IMPORTS CWF, IO, RopeInline, STP: UnsafeSTP, STPSubr, String,
Subr, UECP, UserExec = {
-- MDS usage!!
stdout: IO.Handle;
-- end of mds
Main: UserExec.CommandProc = TRUSTED {
ENABLE UNWIND => [] ← UserExec.ReleaseResource[$MType];
h: Subr.TTYProcs;
in, out: IO.Handle;
[in, out] ← UserExec.GetStreams[exec];
[] ← UserExec.AcquireResource[$MType, "MType", exec];
h ← Subr.MakeTTYProcs[in, out, exec, MyConfirm];
MTypeUsingProcs[h, event.commandLine];
[] ← UserExec.ReleaseResource[$MType];
};
-- this is the procedure called by the Simple Executive
MTypeUsingProcs: PROC[h: Subr.TTYProcs, commandLine: Rope.ROPE] = {
ENABLE Subr.AbortMyself => {
CWF.WF0["Aborted.\n"L];
GOTO leave;
};
newpattern: STRING ← [100];
Subr.errorflg ← Subr.debugflg ← FALSE;
stdout ← h.out;
[] ← CWF.SetWriteProcedure[MyPutChar];
[] ← InitMain[newpattern, h, commandLine];
CWF.WF0["\n**** MType finished.\n"L];
EXITS
leave => NULL;
};
InitMain: PROC[newpattern: STRING, h: Subr.TTYProcs, commandLine: Rope.ROPE]
RETURNS[grepflag: BOOL] = {
token: STRING ← [100];
ignoreCaseFlag: BOOL ← FALSE ;
grepPattern: STRING ← [100] ;
flat: Rope.Text;
argv: UECP.Argv ← UECP.Parse[commandLine];
parm: CARDINAL;
listFilesOnlyFlag: BOOL ← FALSE;
LineWrite: STPSubr.RetrieveProcType = {
line: STRING ← [1000];
nlines: CARDINAL ← 0;
skipRest ← FALSE;
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
IF ~ listFilesOnlyFlag THEN CWF.WF1["**** File %s:\n"L, fileName];
WHILE Subr.GetLine[remoteStream, line] DO
IF ~ grepflag THEN CWF.WF1["%s\n"L, line]
ELSE IF Match[ grepPattern, line, ignoreCaseFlag ] THEN
IF listFilesOnlyFlag THEN {
CWF.WF1["%s "L, fileName];
EXIT;
}
ELSE
CWF.WF2["%4d: %s\n"L, @nlines, line];
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
nlines ← nlines + 1;
ENDLOOP;
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
IF ~grepflag THEN CWF.WFCR[];
};
{
ENABLE
STP.Error => {
CWF.WF0["FTP Error. "L];
IF error ~= NIL THEN CWF.WF1["message: %s\n"L,error];
GOTO leave;
};
typedPattern: BOOL←FALSE;
grepflag ← FALSE;
parm ← 1;
WHILE parm < argv.argc DO
flat ← RopeInline.InlineFlatten[argv[parm]];
Subr.strcpy[token, LOOPHOLE[flat]];
parm ← parm + 1;
IF token[0] = '- OR token[0] = '/ THEN {
FOR i: CARDINAL IN [1 .. token.length) DO
SELECT String.UpperCase[ token[i] ] FROM
'C => ignoreCaseFlag ← TRUE ;
'L => listFilesOnlyFlag ← TRUE;
'G => {
buffer: STRING ← [100] ;
grepflag ← TRUE ;
grepPattern.length ← 0;
String.AppendChar[ grepPattern, '* ] ;
flat ← RopeInline.InlineFlatten[argv[parm]];
Subr.strcpy[buffer, LOOPHOLE[flat]];
parm ← parm + 1;
IF newpattern.length = 0 THEN {
String.AppendString[ grepPattern, buffer ];
Subr.strcpy[newpattern, buffer];
}
ELSE String.AppendString[ grepPattern, newpattern ] ;
String.AppendChar[ grepPattern, '* ] ;
} ;
ENDCASE =>
CWF.WF1[ "?Unknown switch: %s.*N"L, token] ;
ENDLOOP ;
LOOP ;
} ;
IF grepflag AND ~(listFilesOnlyFlag AND typedPattern) THEN {
CWF.WF1[ "**** Pattern: %S, "L, grepPattern ];
typedPattern←TRUE;
};
IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself;
STPSubr.PatternGeneralOpen[filepattern: token, proc: LineWrite, h: h];
ENDLOOP;
STPSubr.StopSTP[];
EXITS
leave => NULL;
}};
--## Match matches a string against a pattern with the standard matching
--## characters: * and #.
Match: PROC[ pattern: STRING, str: STRING, ignoreCase: BOOL ]
RETURNS[ BOOL ] = BEGIN
RMatch: PROC[ p, s: CARDINAL ]
RETURNS[ b: BOOL ] = BEGIN
b ← FALSE ; --## get rid of Mesa warning
WHILE TRUE DO
IF p >= pattern.length THEN
RETURN[ s >= str.length ] ;
SELECT pattern[ p ] FROM
'# => {
IF s >= str.length THEN
RETURN[ FALSE ] ;
s ← s + 1 ;
p ← p + 1 ;
} ;
'* => {
IF p = pattern.length - 1 THEN
RETURN[ TRUE ] ;
WHILE TRUE DO
IF RMatch[ p + 1, s ] THEN
RETURN[ TRUE ] ;
IF (s ← s + 1) >= str.length THEN
RETURN[ FALSE ] ;
ENDLOOP ;
} ;
ENDCASE => {
IF s >= str.length THEN
RETURN[ FALSE ] ;
IF ignoreCase THEN
IF String.UpperCase[ pattern[ p ] ] #
String.UpperCase[ str[ s ] ] THEN
RETURN[ FALSE ]
ELSE NULL
ELSE IF pattern[ p ] # str[ s ] THEN
RETURN[ FALSE ] ;
s ← s + 1 ;
p ← p + 1 ;
} ;
ENDLOOP ;
END ; --## RMatch
--## main body of Match
RETURN[ RMatch[ 0, 0 ] ] ;
END ;
MyConfirm: PROC[in, out: IO.Handle, data: REF ANY, msg: Rope.ROPE, dch: CHAR]
RETURNS[CHAR] = {
value: ATOM;
value ← UserExec.AskUser[msg:msg, exec: NARROW[data],
keyList: LIST[$Yes, $No]]; -- order is important
SELECT value FROM
$No => RETURN['n];
$Yes => RETURN['y];
ENDCASE => ERROR;
};
MyPutChar: PROC[ch: CHAR] = {
stdout.PutChar[ch];
};
-- start code
UserExec.RegisterCommand["MType.~", Main];
}.