!@GENERAL
!The commands available within CLEAN are as follows.
!(Commands may be abbreviated to their first letter).
!   <cr>        Move on to the next file in the directory.
!   HELP <cmd>  Generate more information about any particular command.
!   DELETE      Mark a file for deletion when the program stops.
!   SAVE        Unmark a file.  (To prevent the program deleting it).
!   COPY <n>    Copy the first <n> lines of the file to the console.
!   FILE <fn>   The file called <fn> becomes the current file.
!   RENAME <fn> The name of the file is changed to <fn>
!   ANALYSE     Display information about the size of the file etc.
!   PERMIT <ap> The access permissions on the file are changed to <ap>
!   TOP         Move back to the top of the directory
!   UP or LAST  Move back up to the previous file.
!   NEXT        Equivalent to <cr>
!   STOP        Stops the program.
!   QUIT        Equivalent to STOP.
!   EXIT        Identical to QUIT and STOP.
!Note that the directory is circular: moving past the end brings the
!current file up to the top of the directory and moving up past the
!top takes the current file down to the bottom.
!@FILE
!Format:       FILE  <filename>
!Effect:
!  <Filename> immediately becomes the current file, without having
!to step one by one through the files in the directory.
!@HELP
!
!   The basic command information can be printed by typing
!
!               HELP
!
!The second form is used to ask for more information about a
!particular command:
!
!               HELP  command-name
!
!Examples:
!               HELP
!               HELP  QUIT
!               HELP  DELETE
!
!@DELETE
!Format:        DELETE
!Effect:
!The current file is "marked for deletion" and the next file becomes the
!current file.  When CLEAN stops, the file will be physically deleted.
!(This is so that a file mistakenly DELETED my be rescued.  See HELP SAVE).
!   To indicate which files a user has asked to have deleted,
!when CLEAN prompts for a marked file, it prints a '>' character
!before the filename.  E.g.
!
!               Command:clean
!                       JIM.EXE:d
!                       JIM.IMP:
!                      SORT.EXE:top
!                               *TOP*
!               >       JIM.EXE:
!                       JIM.IMP:
!                      SORT.EXE:quit
!               Command:
!
!@SAVE
!Format:     SAVE
!Effect:
!   If the current file has been marked for deletion, it is unmarked
!and will not be deleted, otherwise the command has no effect.
!Any change in the status of a file (marked/unmarked) is indicated
!by the presence or absence respectively of the '>' marker beside
!the filename prompt for marked files.
!
!@PERMIT
!Format:     PERMIT new-permissions
!
!where "new-permissions" are any of:
!
!            ALL
!            NONE
!            list of letters in the range A to H
!Effect:
!   The access permissions on the current file are changed to
!the "new-permissions".  ALL is equivalent to ABCDEFGH and allows
!any user to access the file.  NONE is equivalent to an empty list
!of permissions and prevents all users but its owner from accessing
!the file (and event the owner may not delete the file without first
!altering the permissions on the file to include 'D' access).
!Users in groups 'A', 'B', 'C' etc. may be independently granted
!or withheld access to the file by using the third form.
!
!Examples:   PERMIT ABH                   access for A,B and H users only
!            PERMIT ALL                   access for everybody
!            P NONE                       no one else may access the file
!            PERMIT D                     allow deletion of the file
!
!@COPY
!Format:     COPY <n>
!Effect:
!   The first <n> lines of the file are copied onto the console.
!<n> defaults to the entire file.
!   The listing may be interrupted at any time, and the user
!returned to the CLEAN prompt level, by typing the <esc> <esc>
!sequence ("Int:!").
!
!Examples:
!            COPY                         list all of the current file
!            COPY 10                      list the first 10 lines
!            C22                          copy the first 22 lines
!
!@TOP
!Format:
!           TOP
!Effect:
!  The first file in the directory becomes the current file.
!
!@NEXT
!Format:     NEXT
!Effect:
!   The current file becomes the next file in the directory. If
!the current file is the last file in the directory and the NEXT
!(or <cr>) command is given, the current file position wraps round
!to the top of the directory again.
!
!@UP
!Format:
!            LAST
!Effect:
!   The current file becomes the previous current file.  (I.e.
!moves back up one position in the directory).  Moving back up past
!the top of the directory causes the current file position to
!'wrap around' to the bottom again.  (C.f. the NEXT command).
!
!@RENAME
!Format:     RENAME <filename>
!  where     <filename> is a valid MOUSES filename.  I.e. FILE.EXT.
!            Any UNIT_ or USER: parts will be ignored.
!Effect:
!   The current file is renamed immediately as <filename>.
!
!@ANALYSE
!Format:
!            ANALYSE
!Effect:
!   The following information about the current file is displayed.
!
!BLOCKS:  The number of disc blocks (512 bytes each) presently
!         occupied by the file.
!EXTENTS: The number of distinct contiguous groups of blocks
!         making up the file.  (Max 126).  This is a measure
!         of how fragmented the file is.
!CREATED: The date the file was created in the form dd-mmm-yy.
!
!If the program was invoked using the CLEAN! form the disc address
!of the file's spine block is also displayed
!
!@QUIT
!Stop the program.
!
!@EXIT
!Stops the program.
!$
!$
!Program for fiddling MOUSES directories
!Alan Culloch,    August 1980

!System message block format

%recordformat parmfm(%short dsno, dact,
          (%short ssno, sact,(%integer p1,p2,p3,p4,p5,p6 %or
                              %string(23) text)          %or
           %short xsno, %string(25) fname))

!Magic numbers for system calls

%const %integer kill TTY IO = 6;         !svc# to throw away console output buf
%const %integer unpack date = 13;        !svc#
%const %integer to director = 20;        !svc# pass message to the file system
%const %integer pack filename = 17;      !svc#s to convert filename strings to
%const %integer unpack filename = 18;    !      and from the packed system form

!destination activity (DACT) values
!for file system (DIRECTOR) operations.

%const %integer delete = 14;             !delete <packed filename>
%const %integer rename = 15;             !<packed oldname> <packed newname>
%const %integer files  = 17;             !read dir blk <packed user> <buf addr>
%const %integer status = 18;             !of file: <blocks><extents><created>
%const %integer set file access = 22;    !alter protections on file
%const %integer become = 27;             !change hats: <packed new dir name>

!Directory format

%record %format filef     (%integer name1, name2,   {packed filename}
                           %short spine block,      {disc block number}
                           %short day)              {creation date + achive}
                                                    {info in the top 2 bits}
%record %format directoryf(%short files,            {No. of files in directory}
                           %byte access rights,     {of the directory's owner}
                           %byte check,             {always '?'}
                           %short spare, %byte spare1,
                           %byte permissions,       {required to access dir}
                           %record(filef) %array file(1:42))

%begin
   %include "Sysinc:command.inc"
   %externalstring(17)%spec Console int
   %externalstring(63)%fnspec ItoS(%integer N, P)
   %externalstring(8)%fnspec XtoS(%integer N, P)
   %const %string(31) program source = "Newsrc:CLEAN.IMP"
   %const %integer infinity = 16_7FFFFFFF
   %own %string(31) version = "(pre-release) vsn 0.00";   !%OWN shows in diags
   %const %integer non zero = 1


   !Events

   %const %integer input ended = 9;      !end-of-file on current input stream
   %const %integer fault = 11;           !user event, signalled on input errors
   %own %integer XEVENT = input ended
   %routine FAULTS
      Xevent = fault
      %signal fault
   %end

   %record(parm fm) %fn packed (%string(31) filename)
      %record(parm fm) P
      P_fname = filename;  SVC (pack filename,P)
      %result = P
   %end

   %routine report (%string(63) message)
      print string (message);  newline
   %end

   %routine say (%string(63) message)
      spaces (15);  print string (message);  newline
   %end

   %string(15) %fn access (%integer mask);  !translate access bits
      %string(15) s = ""
      %integer j
      mask = mask & 255
      %result = "*NONE*" %if mask = 0
      %result = "*ALL*" %if mask = 255
      %for j = 0,1,7 %cycle
         s = s . to string ('A'+j) %if mask & 1<<j # 0
      %repeat
      %result = s
   %end

   %string(15) %fn sys date (%integer packed form)
      %record(parm fm) P
      P_p1 = packed form
      SVC (unpack date,P)
      %result = P_text
   %end

   %integer %fn stoi (%string(15) s)
      %byte %name b
      %integer j = 0, k, sign = 1
      %result = 0 %if s = ""
      sign = -sign %if s -> ("-") . s
      %for k = 1,1,length(s) %cycle
         b == char no (s,k)
         report (s . "?") %and %signal fault %unless '0' <= b <= '9'
         j = 10*j + (b-'0')
      %repeat
      %result = sign*j
   %end

   %routine test (%string(63) context, %record(parm fm)%name P)
      !log a parameterised error message if the
      !director call failure parameter is set in P (P_P6).
      %return %if P_p6 = 0
      report ("*" . context . " -- " . P_text)
      %signal fault
   %end

   %integer %fn upper (%integer sym)
      %result = sym %unless 'a' <= sym <= 'z'
      %result = sym - 'a' + 'A'
   %end

   %routine get (%string(*)%name s)
      %integer sym
      skip symbol %while next symbol = ' '
      s = ""
      %cycle
         sym = next symbol
         %exit %if sym <= ' '
         s <- s . to string (sym)
         skip symbol
      %repeat
   %end

   %routine get alpha (%string(*)%name s)
      %integer sym
      skip symbol %while next symbol = ' '
      s = ""
      %cycle
         sym = upper (next symbol)
         %exit %unless 'A' <= sym <= 'Z'
         s <- s . to string (sym)
         skip symbol
      %repeat
   %end

   %routine drain input line
      %string(63) s = """"
      %if next symbol # NL %start
         %while next symbol # NL %cycle
            s <- s . to string (next symbol)
            skip symbol
         %repeat
         s <- s . """ ignored"
         report (s)
      %finish
      skip symbol;                       !past NL
   %end

   %string(15) %array unpacked (1:42)
   %byte %array pos (1:42);              !map n -> nth dir entry (sorted)
   %record(directoryf) D

   %routine sort dir;                    !set up POS and UNPACKED
      %integer j, k, flag, swap, no files = 0
      %record(parm fm) P
      %record(filef)%name f
      %for j = 1,1,42 %cycle;            !unpack directory entries
         pos(j) = j
         f == D_file(j)
         %if f_name2 = 0 %start
            unpacked(j) = ""
         %else
            no files = no files + 1
            P = 0;  P_p3 = f_name1;  P_p4 = f_name2
            SVC (unpack filename,P)
            unpacked(j) = P_fname
         %finish
      %repeat
      %if no files = 0 %start
         report ("No files")
         %stop
      %finish
      %for j = 1,1,42 %cycle;            !do the sort
         flag = 0
         %for k = 1,1,42-j %cycle
            %if unpacked(pos(k)) > unpacked(pos(k+1)) %start
               flag = non zero
               swap = pos(k);  pos(k) = pos(k+1);  pos(k+1) = swap
            %finish
         %repeat
      %repeat %until flag = 0
   %end

   %own %byte %array del(1:42) = 0(*);   !#0 => file#n is to be deleted
   %record(filef)%name f
   %string(63) s, fname, topic
   %integer j, k, m, sym, lines, flag
   %byte %name b
   %record(parm fm) P, Q

   %on %event input ended, fault %start
      %if EVENT_event = input ended %start
         !Kill all files which were marked for deletion
         %for j = 1,1,42 %cycle
            f == D_file(pos(j))
            %if del(j) # 0 %start
               P = 0
               P_dact = DELETE;  P_p3 = f_name1;  P_p4 = f_name2
               SVC (to director,P)
               s = unpacked (pos(j))
               %if P_p6 # 0 %start
                  s = "*cannot delete " . s . " -- " . P_text
               %else
                  s = s . " deleted"
               %finish
               report (s)
            %finish
         %repeat
         %if command_parameter # "" %start;           !return to home directory
            P = 0;  P_dact = BECOME
            SVC (to director,P);            !and we're ourselves again
            test ("Become fails",P);        !maybe
         %finish
         %stop
      %finish
      drain input line
      XEVENT = input ended; !again
      -> RECOVER
   %finish

   !Main program

   select input (0);  select output (0)

   %if command_parameter # "" %start;                 !CLEAN someone else's directory,
      command_parameter = command_parameter . ":";                 !syntax id CLEAN(UNIT_USER)
      P = packed (command_parameter);  P_dact = BECOME;  P_p6 = 0;!me
      SVC (to director,P)
      %if P_p6 # 0 %start
         report ("CLEAN fails -- " . P_text)
         %stop
      %finish
   %finish

   P_p1 = 0;  P_p2 = 0;                  !read current default directory block
   P_p6 = addr(D)
   P_dact = FILES;  SVC (to director,P)
   test ("CLEAN fails",P)
   %if command_modifier # 0 %start
      say ("Directory on unit " . itos(p_p1,0) . " block " . %c
           itos(p_p2,0) . " (X'" . xtos(p_p2,4) . "')")
   %finish
   j = 0;                                !index into directory
   sort dir

RECOVER:
   %cycle
      %if j < 0 %or j >= 42 %start
         j = 0
         say ("*TOP*")
      %finish
      j = j + 1;  f == D_file(pos(j))
      %continue %if f_name2 = 0;         !unused directory slot?
      !prompt user with filename
      P = 0;  P_p3 = f_name1;  P_p4 = f_name2; !unpack it first
      fname = unpacked (pos(j))
      s = fname;  s = " " . s %while length(s) < 14
      s = s . ":";  char no (s,1) = '>' %if del(j) # 0
      prompt (s)
      get alpha (s);                     !user gives command to act on file
      %if s # "" %or next symbol = '?' %start
         skip symbol %while next symbol = ' '
         skip symbol %and -> HELP %if next symbol = '?'
         -> STOP %if s = "STOP";         !one-off frigs
         P = 0;                          !set up P for all commands to use
         P_p3 = f_name1;  P_p4 = f_name2
         sym = char no (s,1);            !only 1st char of command significant

         %if sym = 'D' %start;           !mark file for deletion at the end
            del(j) = non zero
            say ("marked for deletion")
         %else %if sym = 'S';            !retain file previously marked
            del(j) = 0
            say ("saved!")
         %else %if sym = 'H';            !HELP
            get alpha (s);               !topic
HELP:       s = "GENERAL" %if s = ""
            j = j - 1
            open input (3,program source)
            select input (3)
            flag = 0
            %cycle
               skip symbol;              !past '!'
               %if next symbol = '$' %start
                  say ("Nothing about " . s) %if flag = 0
                  %exit
               %finish
               %if next symbol = '@' %start;   !start of new topic
                  skip symbol
                  get alpha (topic)
                  %exit %if flag # 0;          !end of one we wanted
                  flag = non zero %if char no(s,1) = char no (topic,1)
                  skip symbol;           !past nl
               %else
                  %while next symbol # NL %cycle
                     print symbol (next symbol) %if flag # 0
                     skip symbol
                  %repeat
                  newline %if flag # 0
                  skip symbol;           !past nl
               %finish
            %repeat
            close input
            select input (0)
         %else %if sym = 'C'; !COPY file on T:
            j = j - 1
            get (s);                     !only the 1st n lines
            lines = stoi (s);  lines = infinity %if lines <= 0
            open input (3,fname)
            select input (3)
            console int = ""
            %begin
               %on input ended %start
                  %return; !to enclosing block
               %finish
               %for k = 1,1,lines %cycle
                  %while next symbol # NL %cycle
                     %if console int # "" %start; !user has caused "Int:!"
                        P_p1 = 0;  P_p2 = non zero;  P_p3 = 0
                        SVC (kill TTY IO,P);   !chuck content of TT output buf
                        close input;  select input (0)
                        newline
                        FAULTS
                     %finish
                     print symbol (next symbol)
                     skip symbol
                  %repeat
                  newline;                  !in output
                  skip symbol;              !past NL
               %repeat
            %end
            close input
            select input (0)
         %else %if sym = 'P';            !set protection mask
            j = j - 1
            get alpha (s);               !new mask (ALL,NONE, or A..H)
            %if s = "ALL" %start
               k = 255
            %else %if s = "NONE"
               k = 0
            %else
               k = 0
               %for m = 1,1,length(s) %cycle
                  b == char no (s,m)
                  say (to string(b)."?") %and FAULTS %unless 'A' <= b <= 'H'
                  k = k ! 1<<(b-'A')
               %repeat
            %finish
            P_p6 = k;  P_dact = set file access
            SVC (to director,P)
            test ("Change access fails",P)
         %else %if sym = 'F';            !find <filename>
            get (s)
            say ("filename?") %and j = j - 1 %and FAULTS %if s = ""
            P = packed (s)
            %if P_p1 # 0 %or P_p2 < 0 %start;  !bad fname
               say (s . "?")
               j = j - 1
               FAULTS
            %finish
            SVC (unpack filename,P)
            s = P_fname
            %for k = 1,1,42 %cycle
               %if unpacked(pos(k)) = s %start
                  j = k
                  %exit
               %finish
               %if k = 42 %start
                  say (s . " not found")
                  j = j - 1
                  FAULTS
               %finish
            %repeat
            j = j - 1
         %else %if sym = 'R';            !rename <new name>
            get (s);  Q = packed (s)
            %if Q_p1 # 0 %or Q_p2 < 0 %start
               j = j - 1
               say (s . "?")
               FAULTS
            %finish
            P_p5 = Q_p3;  P_p6 = Q_p4
            P_dact = RENAME;  SVC (to director,P)
            test ("Rename fails",P)
            f_name1 = Q_p3;  f_name2 = Q_p4;   !make our copy of dir consistent
            SVC (unpack filename,Q);  unpacked (pos(j)) = Q_fname
            s = unpacked (pos(j))
            say (fname . " renamed " . s)
            j = j - 1
         %else %if sym = 'T';            !move to first file in directory
            j = -1
         %else %if sym = 'U' %or sym = 'L'; !move  back up to last file
            j = j - 1;                   !back 1 past this one
            j = j - 1 %while j > 0 %and D_file(pos(j))_name2 = 0; !find valid
            j = 42 %and say ("*END*") %if j = 0;            !wrap
            j = j - 1;                   !& back off one
         %else %if sym = 'N';            !move to NEXT file (for completeness)
         %else %if sym = 'A';            !analyse file
            j = j - 1
            P_dact = status;  SVC (to director,P)
            test ("analyse fails",P)
            s <- itos (P_p2,0) . " block";  s <- s . "s" %if P_p2 # 1
            s <- s . " "
            s <- s . itos (P_p3,0) ." extent"; s <- s . "s" %if P_p3 # 1
            s <- s . " "
            s <- s . " access " . access(P_p4) . ", created on "
            s <- s . sys date(P_p5&16_3FFF)
            say (s)
            %if command_modifier # 0 %start
               s <- "spine block at " . itos(f_spine block,0) . %c
                    " (X'" . xtos(f_spine block,4) . "')"
               say (s)
            %finish
         %else %if sym = 'Q' %or sym = 'E'
STOP:       xEVENT = input ended;         !!!TEMP
            %signal input ended
         %else
            report (s . "?  Try HELP")
         %finish
      %finish

DRAIN:
      drain input line
   %repeat

%end %of %program
, topic
   %integer j, k, m, sym, lines, flag
   %byte %name b
   %record(parm fm) P, Q

   %on %event input ended, fault %start
      %if EVENT_event = input ended %start
         !Kill all files which were marked for deletion
         %for j = 1,1,42 %cycle
            f == D_file(pos(j))
            %if del(j) # 0 %start
               P = 0
               P_dact = DELETE;  P_p3 = f_name1;  P_p4 = f_name2
               SVC (to director,P)
               s = unpacked (pos(j))
               %if P_p6 # 0 %start
                  s = "*cannot delete " . s . " -- " . P_text
               %else
                  s = s . " deleted"
               %finish
               report (s)
            %finish
         %repeat
         %if command_parameter # "" %start;           !return to home directory
            P = 0;  P_dact = BECOME
            SVC (to director,P);            !and we're ourselves again
            test ("Become fails",P);        !maybe
         %finish
         %stop
      %finish
      drain input line
      XEVENT = input ended; !again
      -> RECOVER
   %finish

   !Main program

   select input (0);  select output (0)

   %if command_parameter # "" %start;                 !CLEAN someone else's directory,
      command_parameter = command_parameter . ":";                 !syntax id CLEAN(UNIT_USER)
      P = packed (command_parameter);  P_dact = BECOME;  P_p6 = 0;!me
      SVC (to director,P)
      %if P_p6 # 0 %start
         report ("CLEAN fails -- " . P_text)
         %stop
      %finish
   %finish

   P_p1 = 0;  P_p2 = 0;                  !read current default directory block
   P_p6 = addr(D)
   P_dact = FILES;  SVC (to director,P)
   test ("CLEAN fails",P)
   %if command_modifier # 0 %start
      say ("Directory on unit " . itos(p_p1) . " block " . %c
           itos(p_p2) . " (X'" . xtos(p_p2,4) . "')")
   %finish
   j = 0;                                !index into directory
   sort dir

RECOVER:
   %cycle
      %if j < 0 %or j >= 42 %start
         j = 0
         say ("*TOP*")
      %finish
      j = j + 1;  f == D_file(pos(j))
      %continue %if f_name2 = 0;         !unused directory slot?
      !prompt user with filename
      P = 0;  P_p3 = f_name1;  P_p4 = f_name2; !unpack it first
      fname = unpacked (pos(j))
      s = fname;  s = " " . s %while length(s) < 14
      s = s . ":";  char no (s,1) = '>' %if del(j) # 0
      prompt (s)
      get alpha (s);                     !user gives command to act on file
      %if s # "" %or next symbol = '?' %start
         skip symbol %while next symbol = ' '
         skip symbol %and -> HELP %if next symbol = '?'
         -> STOP %if s = "STOP";         !one-off frigs
         P = 0;                          !set up P for all commands to use
         P_p3 = f_name1;  P_p4 = f_name2
         sym = char no (s,1);            !only 1st char of command significant

         %if sym = 'D' %start;           !mark file for deletion at the end
            del(j) = non zero
            say ("marked for deletion")
         %else %if sym = 'S';            !retain file previously marked
            del(j) = 0
            say ("saved!")
         %else %if sym = 'H';            !HELP
            get alpha (s);               !topic
HELP:       s = "GENERAL" %if s = ""
            j = j - 1
            open input (3,program source)
            select input (3)
            flag = 0
            %cycle
               skip symbol;              !past '!'
               %if next symbol = '$' %start
                  say ("Nothing about " . s) %if flag = 0
                  %exit
               %finish
               %if next symbol = '@' %start;   !start of new topic
                  skip symbol
                  get alpha (topic)
                  %exit %if flag # 0;          !end of one we wanted
                  flag = non zero %if char no(s,1) = char no (topic,1)
                  skip symbol;           !past nl
               %else
                  %while next symbol # NL %cycle
                     print symbol (next symbol) %if flag # 0
                     skip symbol
                  %repeat
                  newline %if flag # 0
                  skip symbol;           !past nl
               %finish
            %repeat
            close input
            select input (0)
         %else %if sym = 'C'; !COPY file on T:
            j = j - 1
            get (s);                     !only the 1st n lines
            lines = stoi (s);  lines = infinity %if lines <= 0
            open input (3,fname)
            select input (3)
            console int = ""
            %begin
               %on input ended %start
                  %return; !to enclosing block
               %finish
               %for k = 1,1,lines %cycle
                  %while next symbol # NL %cycle
                     %if console int # "" %start; !user has caused "Int:!"
                        P_p1 = 0;  P_p2 = non zero;  P_p3 = 0
                        SVC (kill TTY IO,P);   !chuck content of TT output buf
                        close input;  select input (0)
                        newline
                        FAULTS
                     %finish
                     print symbol (next symbol)
                     skip symbol
                  %repeat
                  newline;                  !in output
                  skip symbol;              !past NL
               %repeat
            %end
            close input
            select input (0)
         %else %if sym = 'P';            !set protection mask
            j = j - 1
            get alpha (s);               !new mask (ALL,NONE, or A..H)
            %if s = "ALL" %start
               k = 255
            %else %if s = "NONE"
               k = 0
            %else
               k = 0
               %for m = 1,1,length(s) %cycle
                  b == char no (s,m)
                  say (to string(b)."?") %and FAULTS %unless 'A' <= b <= 'H'
                  k = k ! 1<<(b-'A')
               %repeat
            %finish
            P_p6 = k;  P_dact = set file access
            SVC (to director,P)
            test ("Change access fails",P)
         %else %if sym = 'F';            !find <filename>
            get (s)
            say ("filename?") %and j = j - 1 %and FAULTS %if s = ""
            P = packed (s)
            %if P_p1 # 0 %or P_p2 < 0 %start;  !bad fname
               say (s . "?")
               j = j - 1
               FAULTS
            %finish
            SVC (unpack filename,P)
            s = P_fname
            %for k = 1,1,42 %cycle
               %if unpacked(pos(k)) = s %start
                  j = k
                  %exit
               %finish
               %if k = 42 %start
                  say (s . " not found")
                  j = j - 1
                  FAULTS
               %finish
            %repeat
            j = j - 1
         %else %if sym = 'R';            !rename <new name>
            get (s);  Q = packed (s)
            %if Q_p1 # 0 %or Q_p2 < 0 %start
               j = j - 1
               say (s . "?")
               FAULTS
            %finish
            P_p5 = Q_p3;  P_p6 = Q_p4
            P_dact = RENAME;  SVC (to director,P)
            test ("Rename fails",P)
            f_name1 = Q_p3;  f_name2 = Q_p4;   !make our copy of dir consistent
            SVC (unpack filename,Q);  unpacked (pos(j)) = Q_fname
            s = unpacked (pos(j))
            say (fname . " renamed " . s)
            j = j - 1
         %else %if sym = 'T';            !move to first file in directory
            j = -1
         %else %if sym = 'U' %or sym = 'L'; !move  back up to last file
            j = j - 1;                   !back 1 past this one
            j = j - 1 %while j > 0 %and D_file(pos(j))_name2 = 0; !find valid
            j = 42 %and say ("*END*") %if j = 0;            !wrap
            j = j - 1;                   !& back off one
         %else %if sym = 'N';            !move to NEXT file (for completeness)
         %else %if sym = 'A';            !analyse file
            j = j - 1
            P_dact = status;  SVC (to director,P)
            test ("analyse fails",P)
            s <- itos (P_p2) . " block";  s <- s . "s" %if P_p2 # 1
            s <- s . " "
            s <- s . itos (P_p3) ." extent"; s <- s . "s" %if P_p3 # 1
            s <- s . " "
            s <- s . " access " . access(P_p4) . ", created on "
            s <- s . sys date(P_p5&16_3FFF)
            say (s)
            %if command_modifier # 0 %start
               s <- "spine block at " . itos(f_spine block) . %c
                    " (X'" . xtos(f_spine block,4) . "')"
               say (s)
            %finish
         %else %if sym = 'Q' %or sym = 'E'
STOP:       xEVENT = input ended;         !!!TEMP
            %signal input ended
         %else
            report (s . "?  Try HELP")
         %finish
      %finish

DRAIN:
      drain input line
   %repeat


{just a dummy comment}
%endofprogram
