[comp.os.vms] Program Query: RUNOFF to TeX utility

vanroose@kulmath.uucp (Peter Vanroose) (07/01/88)

In article <8806211224.AA01268@ucbvax.Berkeley.EDU>, 
ACSCCRA@UBVMSC.CC.BUFFALO.EDU (Curtis R. Anderson) writes: (about RUNOFF-->TeX)
> Does such a product exist in anybody's archives?  If so, how would I go
> about obtaining one?

I wrote a Pascal program that does the RUNOFF to LaTeX transformation.
It is not too difficult to write down a program mapping the controls 
of RUNOFF to the controls of TeX.
There are however some caveats that should be mentioned:
1) From a RUNOFF text, it is not clear when "Math Mode" of TeX (enclosed 
   in "$"'s) is to be entered.  So my program leaves this to the user.
2) TeX has much more formatting possibilities than RUNOFF has; so the 
   output of my program will only give a rough idea of what LaTeX file
   could be made.  This optimization is also left to the user.
   It is important that the user is aware of this!
3) There are still some bugs in the program, but it worked on all our
   .RNO files that do not end with a blank line.
4) Not all RUNOFF controls are implemented (only the most commonly used ones).
   Others can be added in procedure COMMANDOLIJN.
   The non-implemented controls are just ignored.

I attach a listing of the program, for all people interested.
Please let me know any remarks or improvements.

+----------------------------------------------+
| Peter Vanroose (VANROOSE@kulmath.UUCP)       |
| Department of Mathematics, K.U.Leuven        |
| Celestijnenlaan 200 B, 3030 Leuven (Belgium) |
| Tel +32-16/200656 ext. 3053                  |
+----------------------------------------------+


program RNOtoTEX (input,output);
{ PASCAL program transforming RUNOFF input to LaTeX output. }
{ Written by Peter Vanroose, Leuven (Belgium), 18-Dec-1987. }
{ VANROOSE@kulmath.UUCP }
CONST specials = 
      ['_','\','$','&','%','#','~','^','{','}',''(8),'|','=','+','<','*'];
TYPE string = VARYING [80] of CHAR;
VAR i,j,lengte:     INTEGER;
    c:              CHAR;
    symb:           string;
    lijn:           ARRAY [1..255] of CHAR;
    rnospec:        SET of CHAR;

PROCEDURE schrijf(a: string);
begin
  write(symb); symb:=a
end;

PROCEDURE leeslijn;
begin
  lengte:=0;
  WHILE lengte=0 DO begin
    WHILE not eoln DO begin lengte:=lengte+1; read(lijn[lengte]) end;
    readln; lijn[lengte+1]:=' ' end;
  j:=1
end;

PROCEDURE schrijfcommentlijn;
begin
  write(' % '); FOR i:=1 TO lengte DO write(lijn[i]);
end;

PROCEDURE overstrike; { CASE "%" of PROCEDURE omzetting }
begin
  i:=i+1;
  CASE lijn[i] OF
  '/': symb:='\not '+symb;
  '_': symb:='{\em '+symb+'}';
  OTHERWISE symb:=symb+lijn[i]
  end{CASE}
end;

PROCEDURE omzetting;
begin
  IF lijn[i] IN rnospec THEN
    CASE lijn[i] OF
    '_': begin
         i:=i+1;
         IF not (lijn[i] IN specials) or (lijn[i+1]='%') THEN schrijf(lijn[i])
         ELSE IF lijn[i] IN ['_','$','&','%','#',' '] THEN schrijf('\'+lijn[i])
              ELSE begin IF lijn[i]='\' THEN schrijf('\setminus ');
                         IF lijn[i]='~' THEN schrijf('\sim ');
                         IF lijn[i]='^' THEN schrijf('\wedge ') end end;
    '*': begin
         i:=i+1;
         IF not (lijn[i] IN specials) THEN schrijf('{\bf '+lijn[i]+'}')
         ELSE IF (lijn[i+1]<>'%') or not ('%' IN rnospec) THEN
                 IF lijn[i] IN ['_','$','&','%','#',' '] 
                 THEN schrijf('{\bf\'+lijn[i]+'}')
                 ELSE begin IF lijn[i]='\' THEN schrijf('{\bf\setminus}');
                            IF lijn[i]='~' THEN schrijf('{\bf\sim}');
                            IF lijn[i]='^' THEN schrijf('{\bf\wedge}') end end;
    '&': begin
         i:=i+1;
         IF not (lijn[i] IN specials) THEN schrijf('{\em '+lijn[i]+'}')
         ELSE IF (lijn[i+1]<>'%') or not ('%' IN rnospec) THEN
                 IF lijn[i] IN ['_','$','&','%','#',' '] 
                 THEN schrijf('{\em\'+lijn[i]+'}')
                 ELSE begin IF lijn[i]='\' THEN schrijf('{\em\setminus}');
                            IF lijn[i]='~' THEN schrijf('{\em\sim}');
                            IF lijn[i]='^' THEN schrijf('{\em\wedge}') end end;
    '^': begin
         IF (lijn[i+1]='&') and ('&' IN rnospec) 
            THEN begin i:=i+1; schrijf('{\em ') end;
         IF (lijn[i+1]='*') and ('*' IN rnospec) 
            THEN begin i:=i+1; schrijf('{\bf ') end;
         IF lijn[i+1] IN ['^','\','<'] 
            THEN       i:=i+1                   end;
    '\': begin
         IF (lijn[i+1]='&') and ('&' IN rnospec) 
            THEN begin i:=i+1; schrijf('}') end;
         IF (lijn[i+1]='*') and ('*' IN rnospec) 
            THEN begin i:=i+1; schrijf('}') end;
         IF lijn[i+1] IN ['^','\','<'] 
            THEN       i:=i+1               end;
    '|','<','+': {empty};
    '=': schrijf('\-');
    '%': overstrike;
    '#': schrijf('\ ');
    ''(8): begin
         IF (lijn[i+1]=' ') or ((lijn[i+1]='#') and ('#' IN rnospec)) 
            THEN i:=i+1
            ELSE IF (lijn[i+2]='%') and ('%' IN rnospec) THEN begin
              IF lijn[i+3]='e' THEN
                IF lijn[i+1] IN [';',':','.','-','_'] 
                THEN begin symb:=greekmath[lijn[i+1]]+'{'+symb+'}'; i:=i+3 end;
              IF lijn[i+3]='y' THEN begin
                IF lijn[i+1] IN ['`','''','^','~','.'] 
                THEN begin symb:='\'+lijn[i+1]+'{'+symb+'}'; i:=i+3 end;
                IF lijn[i+1]='-' THEN begin symb:='\={'+symb+'}'; i:=i+3 end;
                IF lijn[i+1]='"' 
                THEN begin symb:='\H{'+symb+'}'; i:=i+3 end end;
              IF lijn[i+3]='g' THEN begin
                IF lijn[i+1]=',' THEN begin symb:='\c{'+symb+'}'; i:=i+3 end;
                IF lijn[i+1]='.' THEN begin symb:='\d{'+symb+'}'; i:=i+3 end;
                IF lijn[i+1]='-' THEN begin symb:='\b{'+symb+'}'; i:=i+3 end 
       end end end
    end{CASE}
  ELSE
    CASE lijn[i] OF
    '\': IF (lijn[i+1]='%') and ('%' IN rnospec) THEN schrijf(lijn[i])
         ELSE schrijf('\setminus ');
    '~': IF (lijn[i+1]='%') and ('%' IN rnospec) THEN schrijf(lijn[i])
         ELSE schrijf('\sim ');
    '^': IF (lijn[i+1]='%') and ('%' IN rnospec )THEN schrijf(lijn[i])
         ELSE schrijf('\wedge ');
    '_','$','&','%','#','{','}':
         IF (lijn[i+1]='%') and ('%' IN rnospec) THEN schrijf(lijn[i])
         ELSE schrijf('\'+lijn[i]);
    OTHERWISE schrijf(lijn[i]) end{CASE}
end;

PROCEDURE commandolijn; FORWARD;

PROCEDURE verwerklijn;
begin
  IF lijn[j]='.' THEN commandolijn
  ELSE begin
    IF lijn[1]=' ' THEN writeln;
    i:=j-1; symb:='';
    WHILE i<lengte DO begin
      i:=i+1;
      IF not (lijn[i] IN specials) THEN schrijf(lijn[i]) ELSE omzetting  end;
    write(symb) end
end;

PROCEDURE checkcolon; { look for ";" in a non-recognized command line}
begin
  WHILE (j<lengte) and (lijn[j]<>';') DO j:=j+1; j:=j+1;
  IF j<=lengte THEN verwerklijn; schrijfcommentlijn
end;

PROCEDURE flags;
begin
  symb:=''; i:=j+1;
  WHILE (i<lengte)  and (lijn[i]<>' ') DO i:=i+1;
  WHILE (i<lengte)  and (lijn[i] =' ') DO i:=i+1;
  WHILE (i<=lengte) and not (lijn[i] IN [';','.',' ']) DO begin
    IF lijn[i] IN ['A'..'Z'] THEN lijn[i]:=chr(32+ord(lijn[i]));
    symb:=symb+lijn[i]; i:=i+1 end;
  IF symb='accept'          THEN rnospec:=rnospec+['_']
  ELSE IF symb='overstrike' THEN rnospec:=rnospec+['%']
  ELSE IF symb='break'      THEN rnospec:=rnospec+['|']
  ELSE IF symb='hyphenate'  THEN rnospec:=rnospec+['=']
  ELSE IF symb='bold'       THEN rnospec:=rnospec+['*']
  ELSE IF symb='capitalize' THEN rnospec:=rnospec+['<']
  ELSE IF symb='period'     THEN rnospec:=rnospec+['+']
  ELSE IF symb='space'      THEN rnospec:=rnospec+['#']
  ELSE IF symb='underline'  THEN rnospec:=rnospec+['&']
  ELSE IF symb='lowercase'  THEN {empty}
  ELSE IF symb='uppercase'  THEN {empty}
  ELSE checkcolon;
  WHILE (i<lengte) and (lijn[i] =' ') DO i:=i+1;
  IF lijn[i]='.' THEN begin j:=i; commandolijn end
end;

PROCEDURE noflags;
begin
  symb:=''; i:=j+1;
  WHILE (i<lengte)  and (lijn[i]<>'F') and (lijn[i]<>'f') DO i:=i+1;
  WHILE (i<lengte)  and (lijn[i]<>' ') DO i:=i+1;
  WHILE (i<lengte)  and (lijn[i] =' ') DO i:=i+1;
  WHILE (i<=lengte) and not (lijn[i] IN [';','.',' ']) DO begin
    IF lijn[i] IN ['A'..'Z'] THEN lijn[i]:=chr(32+ord(lijn[i]));
    symb:=symb+lijn[i]; i:=i+1 end;
  IF symb='accept'          THEN rnospec:=rnospec-['_']
  ELSE IF symb='lowercase'  THEN {empty}
  ELSE IF symb='uppercase'  THEN {empty}
  ELSE IF symb='space'      THEN rnospec:=rnospec-['#']
  ELSE IF symb='capitalize' THEN rnospec:=rnospec-['<']
  ELSE IF symb='overstrike' THEN rnospec:=rnospec-['%']
  ELSE IF symb='break'      THEN rnospec:=rnospec-['|']
  ELSE IF symb='hyphenate'  THEN rnospec:=rnospec-['=']
  ELSE IF symb='bold'       THEN rnospec:=rnospec-['*']
  ELSE IF symb='underline'  THEN rnospec:=rnospec-['&']
  ELSE IF symb='period'     THEN rnospec:=rnospec-['+']
  ELSE checkcolon;
  WHILE (i<lengte) and (lijn[i] =' ') DO i:=i+1;
  IF lijn[i]='.' THEN begin j:=i; commandolijn end
end;

PROCEDURE commandolijn;
begin
  CASE lijn[j+1] OF
  'a','A': IF (lijn[j+2] IN ['x','X']) or 
              ((lijn[j+2] IN ['p','P']) and (lijn[j+3] IN ['p','P']))
           THEN write('\appendix ') ELSE checkcolon;

  'b','B': CASE lijn[j+2] OF
      'r','R': begin
           write('\mbox{}\\'); i:=j+3;
           WHILE (i<=lengte) and not (lijn[i] IN [';','.']) DO i:=i+1;
           IF i<=lengte THEN begin
             j:=i; 
             IF lijn[i]=';' THEN begin writeln; j:=j+1 end; 
             verwerklijn end end;
      ';','.',' ','1'..'9': begin
           write('\mbox{}\bigskip\\'); j:=j+2;
           WHILE (j<lengte) and not (lijn[j] IN [';','.']) DO j:=j+1;
           IF j<lengte THEN begin
             IF lijn[j]=';' THEN begin writeln; j:=j+1 end; 
             verwerklijn end end;
      OTHERWISE checkcolon
      end{CASE};

  'c','C': CASE lijn[j+2] OF
      ';',' ': begin
           writeln('\begin{center}'); j:=j+2;
           WHILE (j<lengte) and (lijn[j]<>';') DO j:=j+1; j:=j+1;
           IF j>lengte THEN leeslijn; verwerklijn; writeln;
           write('\end{center}') end;
      'h','H': begin WHILE lijn[j]<>' ' DO j:=j+1; j:=j+1;
               write('\chapter{'); verwerklijn; write('}') end;
      OTHERWISE checkcolon
      end{CASE};

  'f','F': flags;
  'n','N': noflags;

  'h','H': CASE lijn[j+2] OF
      'l','L': begin j:=j+3;
             WHILE lijn[j]=' ' DO j:=j+1;
             IF lijn[j] IN ['0'..'9'] THEN begin j:=j+1;
               IF lijn[j-1]='1' THEN write('\section{')
               ELSE IF lijn[j-1]='2' THEN write('\subsection{')
                    ELSE write('\subsubsection{') end
             ELSE write('\section{');
             verwerklijn; write('}') end;
      'e','E': IF lijn[j+7]=' ' THEN begin j:=j+7;
             WHILE lijn[j]=' ' DO j:=j+1;
             IF lijn[j] IN ['0'..'9'] THEN begin j:=j+1;
               IF lijn[j-1]='1' THEN write('\section{')
               ELSE IF lijn[j-1]='2' THEN write('\subsection{')
                    ELSE write('\subsubsection{') end
             ELSE write('\section{');
             verwerklijn; write('}') end
             ELSE checkcolon;
      'd','D': checkcolon end{CASE};
  'p','P': begin IF lijn[j+2]=' ' THEN writeln
           ELSE IF lijn[j+2] IN ['g','G'] THEN write('\newpage ')
           ELSE IF (lijn[j+3] IN ['g','G']) and (lengte<j+6) 
                THEN write('\newpage ') 
           ELSE IF lijn[j+3] IN ['r','R'] THEN writeln
           ELSE checkcolon end;
  OTHERWISE checkcolon
  end{CASE}
end;

BEGIN
  writeln('\documentstyle[12pt]{article}');
  writeln('\begin{document}');
  writeln('% RNOtoTEX output --- can possibly be optimized;');
  writeln('% ---warning--- no "$" signs inserted!');

  rnospec :=['_','\','&','#','^',''(8)];

  WHILE not eof DO begin leeslijn; verwerklijn; writeln end;

  writeln('\end{document}')
END.