<> DIRECTORY AMEvents USING [CallDebugger], Atom USING [MakeAtom, GetProp, PutProp], CIFS USING [Error, Open, GetFC, read], ConvertUnsafe USING [AppendRope, ToRope], Directory USING [Lookup, GetProps, Error], File USING [Capability, nullCapability], FileIO USING [Open, OpenFailed], IO USING [CR, EndOf, EndOfStream, SyntaxError, Close, Flush, GetBlock, GetIndex, GetLength, int, GetCedarToken, PutChar, PutF, PutRope, ROPE, rope, RIS, SetIndex, SP, STREAM, TAB, GetToken, WhiteSpace, SkipOver, UserAborted], IOExtras USING [GetCedarScannerToken, FromTokenProc], Loader USING [Instantiate, Start, Error], PrincOps USING [ControlModule], Process USING [GetCurrent], Rope USING [Cat, Concat, Equal, Fetch, Find, IsEmpty, Length, Replace, Substr, Text], RopeInline USING [NewText], RTProcess USING [GetTotalPageFaults, StartWatchingFaults], SafeStorage USING [NWordsAllocated], ShowTime USING [GetMark, Microseconds, Show], System USING [GreenwichMeanTime], Time USING [Current], TiogaOps USING [AddLooks, CreateSimplePattern, FirstChild, GetRope, GoToPreviousCharacter, InsertChar, IsComment, Location, Next, NodeSearch, Paste, Pattern, Ref, SaveSpanForPaste, ViewerDoc, SelectPoint, LastLocWithin], TiogaExtraOps USING [GetFile], UserExec USING [HistoryEvent, ExecHandle, CheckForAbort, UserAbort, UserAborted, GetTheFile, GetStreams, ErrorThisEvent, GetDefaultExecHandle], UserExecExtras USING [CreateEvent, NewErrorThisEvent], UserExecPrivate USING [AcquireExec, EventFailed, ReleaseExec, Prompt, UpdateFrameCache, ExecPrivateRecord, StripComments, CreateSubEvent, methodList, MethodList, GetPrivateStuff, BlinkIcon, HistoryEventPrivateRecord], UserProfile USING [Boolean, CallWhenProfileChanges, ProfileChangedProc], ViewerClasses USING [Viewer], ViewerOps USING [FindViewer] ; UserExecMiscImpl: CEDAR PROGRAM IMPORTS AMEvents, Atom, CIFS, ConvertUnsafe, Directory, FileIO, IO, IOExtras, Loader, Rope, RopeInline, RTProcess, SafeStorage, ShowTime, Time, UserExec, Process, TiogaOps, TiogaExtraOps, UserExecExtras, UserExecPrivate, UserProfile, ViewerOps EXPORTS UserExec, UserExecExtras, UserExecPrivate = BEGIN OPEN IO; <> ExecHandle: TYPE = UserExec.ExecHandle; HistoryEvent: TYPE = UserExec.HistoryEvent ; <> ExecPrivateRecord: PUBLIC TYPE = UserExecPrivate.ExecPrivateRecord; <> HistoryEventPrivateRecord: PUBLIC TYPE = UserExecPrivate.HistoryEventPrivateRecord; <> DoIt: PUBLIC PROC [input: ROPE, exec: ExecHandle _ UserExec.GetDefaultExecHandle[], partOf: HistoryEvent _ NIL] = { private: REF UserExecPrivate.ExecPrivateRecord; execOwner: UNSAFE PROCESS; event, subEvent: HistoryEvent; privateEvent, privateSubEvent: REF UserExecPrivate.HistoryEventPrivateRecord; abortIfSubEventFails: BOOLEAN; start, current: INT _ 0; length: INT; mark: ShowTime.Microseconds _ 0; t0: System.GreenwichMeanTime; nWords: LONG CARDINAL _ 0; nFaults: INT _ 0; Release: PROC = TRUSTED { -- Process IF exec # NIL AND private.execState # destroyed AND UserExecPrivate.ReleaseExec[exec] THEN { IF private.process = Process.GetCurrent[] THEN ERROR; private.eventState _ readyForNext; IF private.execState = listening THEN UserExecPrivate.Prompt[private.eventNum, exec]; }; }; {ENABLE UNWIND => Release[]; ShowStats: PROC = { IF showStats AND exec # NIL AND NOT private.dontPrompt THEN { out: STREAM = UserExec.GetStreams[exec].out; nw: INT _ SafeStorage.NWordsAllocated[] - nWords; t: System.GreenwichMeanTime; seconds: LONG CARDINAL; nf: INT; Put: PROC [char: CHAR] RETURNS[BOOL _ FALSE] = {out.PutChar[char]}; out.PutF["*n {"]; TRUSTED {t _ Time.Current[]}; seconds _ t - t0; IF seconds > 60 THEN { out.PutF["%d minutes, %d seconds", int[seconds/60], int[seconds MOD 60]]; } ELSE { ShowTime.Show[from: mark, p: Put, places: 2]; out.PutRope[" seconds"]; }; IF nw > 0 AND nw < 10000000 THEN out.PutF[", %d words", int[nw]]; TRUSTED {nf _ RTProcess.GetTotalPageFaults[] - nFaults}; IF nf > 0 AND nf < 10000000 THEN out.PutF[", %d page faults", int[nf]]; out.PutChar['}]; }; }; IF exec # NIL THEN { private _ UserExecPrivate.GetPrivateStuff[exec]; execOwner _ private.execOwner; IF UserExecPrivate.AcquireExec[exec] THEN TRUSTED { -- Process IF private.process = Process.GetCurrent[] THEN ERROR; -- since Read Eval Print acquires exec first, this must be an event coming in from somewhere else. IF private.execState = notListening OR private.execState = dormant THEN { IF partOf # NIL THEN privateEvent _ partOf.privateStuff; UserExecPrivate.Prompt[ IF partOf # NIL THEN privateEvent.eventNum ELSE private.eventNum, -- if partof was specified, then use its eventNumber. exec]; } ELSE IF private.eventState = readyForNext THEN private.eventState _ running ELSE ERROR; UserExec.GetStreams[exec].out.PutRope[input]; }; }; event _ IF partOf # NIL THEN partOf ELSE UserExecExtras.CreateEvent[exec, input]; subEvent _ event; privateEvent _ event.privateStuff; privateSubEvent _ subEvent.privateStuff; length _ Rope.Length[input]; <> DO stream: STREAM; substr: ROPE _ NIL; whiteSpace: BOOLEAN _ TRUE; UserExec.CheckForAbort[exec]; IF current = length THEN EXIT; start _ current; WHILE current < length DO char: CHARACTER _ Rope.Fetch[input, current]; TerminatesAtCurrent: PROC RETURNS[BOOL] = { count: INT _ start; fromTokenProc: IOExtras.FromTokenProc = { count _ count + token.next; IF token.kind = tokenCOMMENT AND closure.proc[closure.data, token.next - 1] = '\n THEN count _ count - 1; -- cr is (incorrectly) included in comment. without this check, test would say that CR is not a legitimate terminator in this case }; stream _ RIS[input, stream]; IO.SetIndex[stream, start]; IF NOT Rope.Equal[IO.GetCedarToken[stream! IO.EndOfStream => GOTO Yes], "_"] THEN RETURN[TRUE]; IO.SetIndex[stream, start]; DO IOExtras.GetCedarScannerToken[stream, fromTokenProc ! IO.SyntaxError => CONTINUE ]; <<-- current is one beyond the character just read. We want to know if that character, e.g. CR could be the terminator. Therefore, we want to test and see if the scan stopped just before that character.>> IF count = current - 1 THEN GOTO Yes -- stopped just before the desired place. ELSE IF count >= current THEN GOTO No; ENDLOOP; EXITS No => RETURN[FALSE]; Yes => RETURN[TRUE]; }; current _ current + 1; SELECT char FROM SP => IF whiteSpace THEN start _ current; -- necessary (aesthetic) for compound events <<'' => current _ current + 1; -- from the standpoint of terminating the input, ignore next character. Whether ' or ^ is interpreted as special for command line will have to wait until we decide if this is a command or an expression.>> <<'^ =>>> <