%
% This program makes some systematic edits, and some that are clearly
% ad hoc. The syematic changes include expanding tabs and cleaning up
% trailing whitespace, plus processing of some escapes that "info" format
% uses. The ad hoc ones appear to relate to "words" that have embedded
% apostrophes.
%
% It replaces a sequence of Unix-specific commands, which included use of
% expand to dispose of tabs and several uses of sed to perform the other
% transformations.
% It transforms from redhelp.x into redhelp.y
% It will also be MUCH slower than direct use of Unix utilities, in part
% because it has been coded here with simplicity, portability and clarity
% as objectives above speed. After all the help file is not re-created
% by end-users and not altered very often anyway.
%
%                                        A C Norman.        December 1995

symbolic;
on comp;

fluid '(edits n_edits);

edits := for each p in '(
   ("Euler's"            . "Euler")
   ("EULER'S"            . "EULER")
   ("Euler constant can" . "Euler's constant can")
   ("Catalan's"          . "Catalan")
   ("CATALAN'S"          . "CATALAN")
   ("Khinchin's"         . "Khinchin")
   ("KHINCHIN'S"         . "KHINCHIN")
   ("Khinchin book"      . "Khinchin's book")
   ("Jacobi's"           . "Jacobi")
   ("@$"                 . "$")
   ("@key"               . "(Key)")
   ("@%"                 . "%")
   ("@_"                 . "_")
         ) collect (explode2 car p . explode2 cdr p);



symbolic procedure matches(x, p);
   if null p then list x
   else if null x then nil
   else if car x eq car p then matches(cdr x, cdr p)
   else nil;

symbolic procedure make_edits();
  begin
    scalar fi, fo, c, line, n, p, w, t0, n_edits,
           !*echo, !*raise, !*lower;
    t0 := time();
    fi := open("redhelp.x", 'input);
    if null fi then error(0, "Input file not available");
    fo := open("redhelp.y", 'output);
    if null fo then error(0, "Output file not available");
    fi := rds fi;
    fo := wrs fo;
    linelength 1000; % Output must never wrap.
    n_edits := 0;
    c := !$eol!$;
    while not (c = !$eof!$) do <<
       line := nil;
       n := 0;
% While reading a line in I will process tabs, counting a tab as at least
% one blank and then enough to pad out to the next multiple of 8.
       while not ((c := readch()) = !$eol!$ or c = !$eof!$) do <<
          if c = tab!* then <<
             repeat << line := '!  . line;
                       n := n + 1 >> until zerop remainder(n, 8) >>
          else << line := c . line; n := n + 1 >> >>;
% Next I act on 's/  *$//g', which discards trailing blanks.
       while eqcar(line, '!  ) do line := cdr line;
       line := reversip line;
       while line do <<
          for each p in edits do
             if (w := matches(line, car p)) then <<
                 n_edits := n_edits + 1;
                 line := append(cdr p, car w) >>;
          prin2 car line;
          line := cdr line >>;
       terpri() >>;
    rds fi;
    wrs fo;
    close fi;
    close fo;
    prin2 n_edits; prin2t " edits performed";
    return (time() - t0)/1000.0
  end;

make_edits();

quit;


