-- 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]; }.