home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / INDENT.ZIP / INDENT.PAS
Encoding:
Pascal/Delphi Source File  |  1985-09-20  |  35.1 KB  |  1,293 lines

  1.  (* this is on p 171 of Pascal with Style *)
  2.  (* by Henry F. Ledgard, Paul A. Lagin, and *)
  3.  (* John F. Hueras.  Typed in by Jim Shaw, *)
  4.  (* 7021 N. Park Ave. Indianapolis, IN 46220 *)
  5.  (* Runs properly under Pascal/M, trademark *)
  6.  (* Sorcim. *)
  7.   (* The program is by Jon F. Hueras and Henry  *)
  8.   (* F. Ledgard.  Permission for the Z Users Group  *)
  9.   (* granted for non-commercial use by Mike Violano *)
  10.   (* of the Hayden Book Company on 3/15/82.  *)
  11.  
  12.  
  13. (* Transported to Compaq by Jim Shaw *)
  14. (* 7/22/84 *)
  15. (* Runs properly under Turbo Pascal *)
  16.  
  17. (*$C-,R-,V-,U-,K-*)
  18.  
  19. program pretty ( (* from *) inputfile,
  20. (* to   *)      outputfile );
  21.  
  22. const
  23.       maxsymbolsize = 200;
  24.       maxstacksize  = 100;
  25.       maxkeylnth    =  10;
  26.       maxlinesize   = 120;
  27.       sfail1        =  60;
  28.       sfail2        =  80;
  29.       indent1       =   4;
  30.       indent2       =   2;
  31.       space         = ' ';
  32.  
  33. (* this is on p 172 *)
  34.  
  35. type
  36.      keysymbol = ( progsym,    funcsym,     procsym,
  37.                   labelsym,   constsym,    typesym,
  38.                   varsym,     beginsym,    repeatsym,
  39.                   recordsym,  casesym,     casevarsym,
  40.                   ofsym,      forsym,      whilesym,
  41.                   withsym,    dosym,       ifsym,
  42.                   thensym,    elsesym,     endsym,
  43.                   untilsym,   becomes,     opencomment,
  44.                   closecomment,            semicolon,
  45.                   colon,      equals,      openparen,
  46.                   closeparen, period,      endoffile,
  47.                   othersym );
  48.  
  49.      option = ( crsuppress,
  50.                crbefore,
  51.                blanklinebefore,
  52.                dindentonkeys,
  53.                dindent,
  54.                spacebefore,
  55.                spaceafter,
  56.                gobblesymbols,
  57.                indentbytab,
  58.                indenttoclp,
  59.                crafter );
  60.  
  61.      optionset = set of option;
  62.  
  63.      keysymset = set of keysymbol;
  64.  
  65.      tableentry = record
  66.                    optionsselected   : optionset;
  67.                    dindentsymbols    : keysymset;
  68.                    gobbleterminators : keysymset;
  69.                   end ;
  70.  
  71.      optiontable = array [ keysymbol ] of tableentry;
  72.  
  73. (* page 173 *)
  74.  
  75.      key = packed array [ 1 .. maxkeylnth ] of char;
  76.  
  77.      keywordtable = array [ progsym..untilsym ] of key;
  78.  
  79.      specialchar = packed array [ 1..2 ] of char;
  80.  
  81.      dblchrset = set of becomes..opencomment;
  82.  
  83.      dblchartable = array [ becomes..opencomment ] of
  84.                     specialchar;
  85.      sglchartable = array [ semicolon..period ] of char;
  86.  
  87. (* the book calls for a type STRING which pascal/m
  88. has as a predefined type.  The bandaid is to
  89. call the book's type STRING the name STRINGC. *)
  90.  
  91.      stringc = array [ 1..maxsymbolsize ] of char;
  92.  
  93.      symbol = record
  94.                 name         : keysymbol;
  95.                 value        : stringc;
  96.                 lnth       : integer;
  97.                 spacesbefore : integer;
  98.                 crsbefore    : integer;
  99.               end ;
  100.  
  101.      symbolinfo = ^symbol;
  102.  
  103.      charname = ( letter,     digit,      blank,
  104.                  quote,      endofline,  filemark,
  105.                  otherchar );
  106.  
  107.      charinfo = record
  108.                  name  : charname;
  109.                  value : char
  110.                 end ;
  111.  
  112.      stackentry = record
  113.                    indentsymbol : keysymbol;
  114.                    prevmargin   : integer
  115.                   end ;
  116.  
  117.      symbolstack = array [ 1..maxstacksize ] of stackentry;
  118.  
  119.      workstring = string[80];
  120.  
  121.  
  122. (* page 174 *)
  123.  
  124. var
  125.  
  126.     inputfile,
  127.     outputfile : text;
  128.  
  129.     inname : workstring;
  130.     outname : workstring;
  131.  
  132.     ok,
  133.     recordseen : boolean;
  134.  
  135.     currchar,
  136.     nextchar : charinfo;
  137.  
  138.     currsym,
  139.     nextsym : symbolinfo;
  140.  
  141.     crpending : boolean;
  142.  
  143.     ppoption : optiontable;
  144.  
  145.     keyword : keywordtable;
  146.  
  147.     dblchars : dblchrset;
  148.  
  149.     dblchar : dblchartable;
  150.     sglchar : sglchartable;
  151.  
  152.     stack : symbolstack;
  153.     top   : integer;
  154.  
  155.     currlinepos,
  156.     currmargin : integer;
  157.  
  158.     file1,file2 : Workstring;
  159. (* part of initalize from page 187 *)
  160.  
  161.  
  162. procedure init2( var ppoption : optiontable);
  163. begin
  164.  
  165.  
  166. (* page 187 *)
  167.  
  168.   with ppoption [ progsym ] do
  169.     begin
  170.       optionsselected := [ blanklinebefore,
  171.                          spaceafter ];
  172.       dindentsymbols  := [];
  173.       gobbleterminators := []
  174.     end ;
  175.   with ppoption [ funcsym ] do
  176.     begin
  177.       optionsselected   := [ blanklinebefore,
  178.                            dindentonkeys,spaceafter ];
  179.       dindentsymbols    := [ labelsym,constsym,
  180.                            typesym,varsym ];
  181.       gobbleterminators := []
  182.     end ;
  183.   with ppoption [ procsym ] do
  184.     begin
  185.       optionsselected   := [ blanklinebefore,
  186.                            dindentonkeys,spaceafter ];
  187.       dindentsymbols    := [ labelsym,constsym,
  188.                            typesym,varsym ];
  189.       gobbleterminators := []
  190.     end ;
  191.   with ppoption [ labelsym ] do
  192.     begin
  193.       optionsselected   := [ blanklinebefore,
  194.                            spaceafter, indenttoclp ];
  195.       dindentsymbols    := [];
  196.       gobbleterminators := []
  197.     end ;
  198.   with ppoption [ constsym ] do
  199.     begin
  200.       optionsselected   := [ blanklinebefore,
  201.                            dindentonkeys,spaceafter,indenttoclp
  202.                            ];
  203.       dindentsymbols    := [ labelsym,constsym,typesym,varsym ];
  204.       gobbleterminators := []
  205.     end ;
  206.   with ppoption [ typesym ] do
  207.     begin
  208.       optionsselected   := [ blanklinebefore,
  209.                            dindentonkeys,spaceafter,indenttoclp
  210.                            ];
  211.       dindentsymbols    := [ labelsym,constsym,typesym,varsym ];
  212.       gobbleterminators := []
  213.     end ;
  214.  
  215. (* page 188 *)
  216.  
  217.   with ppoption [ varsym ] do
  218.     begin
  219.       optionsselected   := [ blanklinebefore,
  220.                            dindentonkeys,spaceafter,indenttoclp
  221.                            ];
  222.       dindentsymbols    := [ labelsym,constsym,
  223.                            typesym,varsym ];
  224.       gobbleterminators := []
  225.     end ;
  226.   with ppoption [ beginsym ] do
  227.     begin
  228.       optionsselected   := [ crbefore,dindentonkeys,
  229.                              indentbytab,crafter ];
  230.       dindentsymbols    := [ labelsym,constsym,
  231.                            typesym,varsym ] ;
  232.       gobbleterminators := []
  233.     end ;
  234.   with ppoption [ repeatsym ] do
  235.     begin
  236.       optionsselected   := [ indentbytab,crafter];
  237.       dindentsymbols    := [];
  238.       gobbleterminators := []
  239.     end ;
  240.   with ppoption [ recordsym ] do
  241.     begin
  242.       optionsselected   := [ indentbytab,crafter ];
  243.       dindentsymbols    := [];
  244.       gobbleterminators := []
  245.     end ;
  246.   with ppoption [ casesym ] do
  247.     begin
  248.       optionsselected   := [ spaceafter,indentbytab,
  249.                            gobblesymbols,crafter ];
  250.       dindentsymbols    := [];
  251.       gobbleterminators := [ ofsym ]
  252.     end ;
  253.   with ppoption [ casevarsym ] do
  254.     begin
  255.       optionsselected   := [ spaceafter,indentbytab,
  256.                            gobblesymbols,crafter ];
  257.       dindentsymbols    := [];
  258.       gobbleterminators := [ ofsym ]
  259.     end ;
  260.  
  261. (* page 189 *)
  262.  
  263.   with ppoption [ ofsym ] do
  264.     begin
  265.       optionsselected   := [ crsuppress,spacebefore ];
  266.       dindentsymbols    := [];
  267.       gobbleterminators := [];
  268.     end ;
  269.   with ppoption [ forsym ] do
  270.     begin
  271.       optionsselected   := [ spaceafter,indentbytab,
  272.                            gobblesymbols,crafter ];
  273.       dindentsymbols    := [];
  274.       gobbleterminators := [ dosym ];
  275.     end ;
  276.   with ppoption [ whilesym ] do
  277.     begin
  278.       optionsselected   := [ spaceafter,indentbytab,
  279.                            gobblesymbols,crafter ];
  280.       dindentsymbols    := [];
  281.       gobbleterminators := [ dosym ]
  282.     end ;
  283.   with ppoption [ withsym ] do
  284.     begin
  285.       optionsselected   := [ spaceafter,indentbytab,
  286.                            gobblesymbols,crafter ];
  287.       dindentsymbols    := [];
  288.       gobbleterminators := [ dosym ]
  289.     end ;
  290.   with ppoption [ dosym ] do
  291.     begin
  292.       optionsselected   := [ crsuppress,spacebefore];
  293.       dindentsymbols    := [];
  294.       gobbleterminators := []
  295.     end ;
  296.   with ppoption [ ifsym ] do
  297.     begin
  298.       optionsselected   := [ spaceafter,
  299.                            gobblesymbols ];
  300.       dindentsymbols    := [];
  301.       gobbleterminators := [ thensym ]
  302.     end ;
  303. end ;(* init2 *)
  304.  
  305. (* some more init of ppoption *)
  306.  
  307.  
  308. procedure init3 (var ppoption : optiontable);
  309. begin
  310.  
  311. (* page 190 *)
  312.  
  313.   with ppoption [ thensym ] do
  314.     begin
  315.       optionsselected   := [indentbytab,crafter ];
  316.       dindentsymbols    := [];
  317.       gobbleterminators := []
  318.     end ;
  319.   with ppoption [ elsesym ] do
  320.     begin
  321.       optionsselected   := [ crbefore,dindentonkeys,
  322.                            dindent,indentbytab,crafter ];
  323.       dindentsymbols    := [ ifsym,elsesym ];
  324.       gobbleterminators := []
  325.     end ;
  326.   with ppoption [ endsym ] do
  327.     begin
  328.       optionsselected   := [ crbefore,dindentonkeys,
  329.                            dindent,crafter ];
  330.       dindentsymbols    := [ ifsym,thensym,elsesym,
  331.                            whilesym,withsym,casevarsym,
  332.                            forsym,colon,equals ];
  333.       gobbleterminators := []
  334.     end ;
  335.   with ppoption [ untilsym ] do
  336.     begin
  337.       optionsselected   := [ crbefore,dindentonkeys,
  338.                            dindent,spaceafter,gobblesymbols,
  339.                            crafter ];
  340.       dindentsymbols    := [ ifsym,thensym,elsesym,
  341.                            forsym,whilesym,withsym,colon,equals
  342.                            ];
  343.       gobbleterminators := [ endsym,untilsym,elsesym,
  344.                            semicolon ]
  345.     end ;
  346.  
  347. (* page 191 *)
  348.  
  349.   with ppoption [ becomes ] do
  350.     begin
  351.       optionsselected   := [ spacebefore,spaceafter
  352.                            ,gobblesymbols];
  353.       dindentsymbols    := [];
  354.       gobbleterminators := [ endsym,untilsym,elsesym,
  355.                            semicolon ]
  356.     end ;
  357.   with ppoption [ opencomment ] do
  358.     begin
  359.       optionsselected   := [ crsuppress ];
  360.       dindentsymbols    := [];
  361.       gobbleterminators := []
  362.     end ;
  363.   with ppoption [ closecomment ] do
  364.     begin
  365.       optionsselected   := [ crsuppress ];
  366.       dindentsymbols    := [];
  367.       gobbleterminators := []
  368.     end ;
  369.   with ppoption [ semicolon ] do
  370.     begin
  371.       optionsselected   := [ crsuppress,dindentonkeys,
  372.                            crafter ];
  373.       dindentsymbols   := [ifsym,thensym,elsesym,
  374.                           forsym,whilesym,withsym,colon,equals ]
  375.       ;
  376.       gobbleterminators := []
  377.     end ;
  378.   with ppoption [ colon ] do
  379.     begin
  380.       optionsselected   := [ spaceafter,indenttoclp ];
  381.       dindentsymbols    := [];
  382.       gobbleterminators := []
  383.     end ;
  384.  
  385. (* page 192 *)
  386.  
  387.   with ppoption [ equals ] do
  388.     begin
  389.       optionsselected   := [ spacebefore,spaceafter,
  390.                            indenttoclp ];
  391.       dindentsymbols    := [];
  392.       gobbleterminators := []
  393.     end ;
  394.   with ppoption [ openparen ] do
  395.     begin
  396.       optionsselected   := [ gobblesymbols ];
  397.       dindentsymbols    := [];
  398.       gobbleterminators := [ closeparen ]
  399.     end ;
  400.   with ppoption [ closeparen ] do
  401.     begin
  402.       optionsselected   := [];
  403.       dindentsymbols    := [];
  404.       gobbleterminators := []
  405.     end ;
  406.   with ppoption [ period ] do
  407.     begin
  408.       optionsselected   := [ crsuppress ];
  409.       dindentsymbols    := [];
  410.       gobbleterminators := []
  411.     end ;
  412.   with ppoption [ endoffile ] do
  413.     begin
  414.       optionsselected   := [];
  415.       dindentsymbols    := [];
  416.       gobbleterminators := [];
  417.     end ;
  418.   with ppoption [ othersym ] do
  419.     begin
  420.       optionsselected   := [];
  421.       dindentsymbols    := [];
  422.       gobbleterminators := []
  423.     end ;
  424. end ; (* init2 *)
  425.  
  426. procedure commandline (var f1,f2: workstring);
  427.  
  428. type 
  429.      CommandString  = string[127];
  430.  
  431. var 
  432.     buffer         : CommandString;
  433.     CL             : CommandString absolute cseg: $80;
  434. begin
  435.   Buffer := Copy(cl,2,127);
  436.   if (Pos(' ',buffer) <> 0)
  437.     then
  438.       begin
  439.         File1 := Copy(buffer,1,Pos(' ',buffer)-1);
  440.         File2 := buffer;
  441.         Delete(file2,1,Pos(' ',file2));
  442.       end
  443.     else
  444.       begin
  445.         File1 := Copy(buffer,1,14);
  446.         File2 := '';
  447.       end;
  448. end; (* end commandline *)
  449.  
  450. function openout : boolean;
  451.  
  452.  (* returns TRUE for successfull open *)
  453.  
  454. var
  455.     result : integer;
  456.     escape : boolean;
  457.  
  458.  
  459. begin (* openout *)
  460.   OutName := file2;
  461.   repeat (* begin repeat *)
  462.     if (length(file2) = 0)
  463.       then
  464.         begin
  465.           writeln ;
  466.           write ('Type output file name, or CR to quit ');
  467.           readln (OutName);
  468.         end;
  469.     if (Length (OutName) > 0)
  470.       then
  471.         begin
  472.           escape := false;
  473.           assign (OutputFile, OutName);
  474.           {$I-} Rewrite (OutputFile) {$I+};
  475.           result := IOResult;
  476.           if (result <> 0)
  477.            then
  478.             writeln ('Cannot open ',OutName,'code ', result);
  479.         end
  480.       else (* just typed CR *)
  481.         begin
  482.           result := 0;
  483.           escape := true;
  484.         end;
  485.   until (result = 0);
  486.   openout := NOT escape;
  487. end; (* openout *)
  488.  
  489.  
  490. (********************************************************************)
  491.  
  492. function openin : boolean;
  493.  
  494.   (* Return True for successfull open *)
  495.  
  496. var
  497.     result : integer;
  498.     escape : boolean;
  499. (*    cmdline1,cmdline2 : string[80]; *)
  500. begin (* OpenIn *)
  501.  
  502.   InName := file1;
  503.   repeat
  504.     if (Length(file1) = 0)
  505.       then
  506.         begin
  507.           Writeln ;
  508.           Write ('Type input file name, or CR to quit ');
  509.           Readln (InName);
  510.         end;
  511.     if (Length (InName) > 0)
  512.       then
  513.         begin
  514.           Assign (InputFile,InName);
  515.           {$I-} Reset (InputFile) {$I+};
  516.           result := IOResult;
  517.           escape := false;
  518.           if (result <> 0)
  519.            then
  520.             begin
  521.             writeln ('Cannot find ',InName);
  522.             file1:='';
  523.             end;
  524.         end
  525.       else (* just typed CR *)
  526.         begin
  527.           result := 0;
  528.           escape := true;
  529.         end;
  530.   until (result = 0);
  531.   openin := NOT escape;
  532. end; (* openin *)
  533.  
  534. (* page 175 *)
  535.  
  536. procedure getchar (var inputfile : text;
  537.                    var nextchar  : charinfo;
  538.                    var currchar  : charinfo );
  539.  
  540. var ch : char;
  541.  
  542. begin (* getchar *)
  543.   currchar := nextchar;
  544.   with nextchar do
  545.     begin
  546.       if eof ( inputfile )
  547.         then
  548.           name := filemark
  549.         else
  550.           if eoln ( inputfile )
  551.             then
  552.               name := endofline
  553.             else
  554.              begin (* check of name type *)
  555.               read (inputfile,ch);
  556.               if ch in ['A'..'Z']
  557.                 then
  558.                  name := letter
  559.                 else
  560.                  if ch in ['a'..'z']
  561.                   then
  562.                    name := letter
  563.                   else
  564.                    if ch in ['0'..'9']
  565.                     then
  566.                      name := digit
  567.                     else
  568.                      if ch = ''''
  569.                       then
  570.                        name := quote
  571.                       else
  572.                        if ch = space
  573.                         then
  574.                          name := blank
  575.                         else
  576.                          name := otherchar;
  577.              end; (* check of name type *)
  578.       if name in [ filemark, endofline ]
  579.         then
  580.           value := space
  581.         else
  582.           value := ch ;
  583.       if name = endofline
  584.         then
  585.           readln (inputfile);
  586.     end; (* with *)
  587. end ; (* getchar *)
  588.  
  589. (* page 176 *)
  590.  
  591. procedure storenextchar ( var inputfile : text;
  592.                          var lnth    : integer;
  593.                          var currchar,
  594.                          nextchar  : charinfo;
  595.                          var value     : stringc );
  596.  
  597. begin (* storenextchar *)
  598.   getchar ( inputfile, nextchar, currchar );
  599.   if lnth < maxsymbolsize
  600.     then
  601.       begin
  602.         lnth := lnth+1;
  603.         value [lnth] := currchar.value
  604.       end
  605. end ; (* storechar *)
  606.  
  607.  
  608. procedure skipspaces ( var inputfile    : text;
  609.                       var currchar,
  610.                       nextchar     : charinfo;
  611.                       var spacesbefore,
  612.                       crsbefore    : integer );
  613. begin (* skipspaces *)
  614.   crsbefore := 0;
  615.   spacesbefore := 0;
  616.   while nextchar.name in [ blank,endofline ] do
  617.     begin
  618.       getchar (inputfile,nextchar,currchar );
  619.       case currchar.name of
  620.         blank     : spacesbefore := spacesbefore+1;
  621.         endofline : begin
  622.                      crsbefore    := crsbefore+1;
  623.                      spacesbefore := 0
  624.                     end
  625.       end; (* case *)
  626.     end; (* begin of while *)
  627. end ; (* skipspaces *)
  628.  
  629.  
  630. (* page 177 *)
  631.  
  632. procedure getcomment (
  633. (* form *)            var inputfile : text;
  634. (* updating *)        var currchar,
  635.                       nextchar  : charinfo;
  636.                       var name      : keysymbol;
  637.                       var value     : stringc;
  638.                       var lnth    : integer    );
  639. begin (* getcomment *)
  640.   name := opencomment;
  641.   while not ( ((currchar.value = '*') and
  642.         (nextchar.value = ')') )
  643.         or (nextchar.name = endofline )
  644.         or (nextchar.name = filemark )
  645.         ) do
  646.     storenextchar (inputfile,lnth,currchar,nextchar,
  647.                    value);
  648.   if (currchar.value = '*') and (nextchar.value=')')
  649.     then
  650.       begin
  651.         storenextchar (inputfile,lnth,currchar,nextchar,
  652.                        value );
  653.         name := closecomment
  654.       end
  655. end ; (* getcomment *)
  656.  
  657. (* page 178 *)
  658.  
  659. function idtype (value  : stringc;
  660.                  lnth : integer )
  661. : keysymbol;
  662.  
  663. var 
  664.     i: integer;
  665.     keyvalue : key;
  666.     hit      : boolean;
  667.     thiskey  : keysymbol;
  668.  
  669. begin (* idtype *)
  670.   idtype := othersym;
  671.   if lnth <= maxkeylnth
  672.     then
  673.       begin
  674.         for i := 1 to lnth do
  675.           keyvalue [i] := value [i];
  676.         for i := lnth+1 to maxkeylnth do
  677.           keyvalue [i] := space;
  678.         thiskey := progsym;
  679.         hit := false;
  680.         while not(hit or (pred(thiskey) = untilsym)) do
  681.           if keyvalue = keyword [thiskey]
  682.             then
  683.               hit := true
  684.             else
  685.               thiskey := succ(thiskey);
  686.         if hit
  687.           then
  688.             idtype := thiskey
  689.       end ;
  690. end ; (* idtype *)
  691.  
  692. (* page 179 *)
  693.  
  694. procedure getidentifier (
  695.                          var inputfile : text;
  696.                          var currchar,nextchar : charinfo;
  697.                          var name      : keysymbol;
  698.                          var value     : stringc;
  699.                          var lnth    : integer );
  700.  
  701. begin (* getidentifier *)
  702.   while nextchar.name in [ letter,digit ] do
  703.     storenextchar(inputfile,lnth,currchar,nextchar,value);
  704.   name := idtype ((* of *) value, (* using *) lnth);
  705.   if name in [ recordsym, casesym, endsym ]
  706.     then
  707.       case name of
  708.         recordsym : recordseen := true;
  709.         casesym   : if recordseen
  710.                      then
  711.                       name := casevarsym;
  712.         endsym    : recordseen := false
  713.       end (* case *)
  714. end ; (* getindentifier *)
  715.  
  716. procedure getnumber (
  717.                      var inputfile : text ;
  718.                      var currchar,nextchar : charinfo;
  719.                      var name   : keysymbol;
  720.                      var value  : stringc;
  721.                      var lnth : integer );
  722. begin (* getnumber *)
  723.   while nextchar.name = digit do
  724.     storenextchar (inputfile,lnth,currchar,nextchar,
  725.                    value );
  726.   name := othersym
  727. end ; (* getnumber *)
  728.  
  729. (* page 180 *)
  730.  
  731. procedure getcharliteral (
  732.                           var inputfile : text;
  733.                           var currchar,nextchar : charinfo ;
  734.                           var name   : keysymbol;
  735.                           var value  : stringc;
  736.                           var lnth : integer    );
  737. begin (* getcharliteral *)
  738.   while nextchar.name = quote do
  739.     begin (* while *)
  740.       storenextchar (inputfile,lnth,currchar,nextchar,
  741.                      value );
  742.       while not(nextchar.name in [quote,endofline,filemark]) 
  743.         do
  744.         storenextchar (inputfile,lnth,currchar,
  745.                        nextchar,value);
  746.       if nextchar.name = quote
  747.         then
  748.           storenextchar (inputfile,lnth,currchar,
  749.                          nextchar,value)
  750.     end ; (* while *)
  751.   name := othersym
  752. end ; (* getcharliteral *)
  753.  
  754. (* page 181 *)
  755.  
  756. function chartype (currchar,nextchar : charinfo )
  757. : keysymbol ;
  758.  
  759. var 
  760.     nexttwochars : specialchar;
  761.     hit : boolean;
  762.     thischar : keysymbol;
  763. begin (* chartype *)
  764.   nexttwochars[1] := currchar.value;
  765.   nexttwochars[2] := nextchar.value;
  766.   thischar := becomes;
  767.   hit      := false;
  768.   while not(hit or (thischar = closecomment)) do
  769.     if nexttwochars = dblchar [thischar]
  770.       then
  771.         hit := true
  772.       else
  773.         thischar := succ(thischar);
  774.   if not hit
  775.     then
  776.       begin
  777.         thischar := semicolon;
  778.         while not(hit or (pred(thischar)=period)) do
  779.           if currchar.value = sglchar[thischar]
  780.             then
  781.               hit := true
  782.             else
  783.               thischar := succ(thischar)
  784.       end ; (* begin after else *)
  785.   if hit
  786.     then
  787.       chartype := thischar
  788.     else
  789.       chartype := othersym
  790. end ; (* chartype *)
  791.  
  792. (* page 182 *)
  793.  
  794. procedure getspecialchar (
  795.                           var inputfile : text;
  796.                           var currchar,nextchar : charinfo;
  797.                           var name : keysymbol;
  798.                           var value : stringc;
  799.                           var lnth : integer    );
  800. begin (* getspecialchar *)
  801.   storenextchar ( inputfile,lnth,currchar,
  802.                  nextchar,value );
  803.   name := chartype ( currchar,nextchar );
  804.   if name in dblchars
  805.     then
  806.       storenextchar ( inputfile,lnth,currchar,
  807.                      nextchar,value )
  808. end ; (* getspecialchar *)
  809.  
  810. (* page 183 *)
  811.  
  812. procedure getnextsymbol (
  813.                          var inputfile : text;
  814.                          var currchar,nextchar : charinfo;
  815.                          var name : keysymbol;
  816.                          var value : stringc;
  817.                          var lnth : integer  );
  818. begin (* getnextsymbol *)
  819.   case nextchar.name of
  820.     letter : getidentifier(inputfile,currchar,nextchar,
  821.                            name,value,lnth );
  822.     digit : getnumber (inputfile,currchar,nextchar,
  823.                        name,value,lnth );
  824.     quote : getcharliteral(inputfile,currchar,nextchar,
  825.                            name,value,lnth );
  826.     otherchar : 
  827.                 begin
  828.                  getspecialchar (inputfile,currchar,nextchar
  829.                                  ,
  830.                                  name,value,lnth );
  831.                  if name = opencomment
  832.                   then
  833.                    getcomment (inputfile,currchar,
  834.                                nextchar,
  835.                                name,value,lnth )
  836.                 end ; (* begin otherchar case *)
  837.     filemark : name := endoffile
  838.   end (* case *)
  839. end ; (* getnextsymbol *)
  840.  
  841. (* page 184 *)
  842.  
  843. procedure getsymbol (
  844.                      var inputfile : text;
  845.                      var nextsym : symbolinfo;
  846.                      var currsym : symbolinfo );
  847.  
  848. var 
  849.     dummy : symbolinfo;
  850. begin (* getsymbol *)
  851.   dummy := currsym;
  852.   currsym := nextsym;
  853.   nextsym := dummy;
  854.   with nextsym^ do
  855.     begin
  856.       skipspaces (inputfile,currchar,nextchar,
  857.                   spacesbefore,crsbefore );
  858.       lnth := 0;
  859.       if currsym^.name = opencomment
  860.         then
  861.           getcomment (inputfile,currchar,nextchar,
  862.                       name,value,lnth )
  863.         else
  864.           getnextsymbol (inputfile,currchar,nextchar,
  865.                          name,value,lnth );
  866.     end; (* with *)
  867. end ; (* getsymbol *)
  868.  
  869. (* page 185 *)
  870.  
  871. procedure initalize (
  872.                      var inputfile,outputfile : text;
  873.                      var topofstack : integer;
  874.                      var currlinepos,currmargin : integer;
  875.                      var keyword : keywordtable;
  876.                      var dblchars : dblchrset;
  877.                      var dblchar : dblchartable;
  878.                      var sglchar : sglchartable;
  879.                      var recordseen : boolean;
  880.                      var currchar,nextchar : charinfo;
  881.                      var currsym,nextsym : symbolinfo );
  882.  
  883. var i : integer;
  884. (* page 186 *)
  885.  
  886. begin (* initalize *)
  887.   topofstack := 0;
  888.   currlinepos := 0;
  889.   currmargin := 0;
  890.   keyword [ progsym    ] := 'PROGRAM   ';
  891.   keyword [ funcsym    ] := 'FUNCTION  ';
  892.   keyword [ procsym    ] := 'PROCEDURE ';
  893.   keyword [ labelsym   ] := 'LABEL     ';
  894.   keyword [ constsym   ] := 'CONST     ';
  895.   keyword [ typesym    ] := 'TYPE      ';
  896.   keyword [ varsym     ] := 'VAR       ';
  897.   keyword [ beginsym   ] := 'BEGIN     ';
  898.   keyword [ repeatsym  ] := 'REPEAT    ';
  899.   keyword [ recordsym  ] := 'RECORD    ';
  900.   keyword [ casesym    ] := 'CASE      ';
  901.   keyword [ casevarsym ] := 'CASE      ';
  902.   keyword [ ofsym      ] := 'OF        ';
  903.   keyword [ forsym     ] := 'FOR       ';
  904.   keyword [ whilesym   ] := 'WHILE     ';
  905.   keyword [ withsym    ] := 'WITH      ';
  906.   keyword [ dosym      ] := 'DO        ';
  907.   keyword [ ifsym      ] := 'IF        ';
  908.   keyword [ thensym    ] := 'THEN      ';
  909.   keyword [ elsesym    ] := 'ELSE      ';
  910.   keyword [ endsym     ] := 'END       ';
  911.   keyword [ untilsym   ] := 'UNTIL     ';
  912.  
  913.   dblchars := [ becomes, opencomment ];
  914.   dblchar [ becomes      ] := ':=' ;
  915.   dblchar [ opencomment  ] := '(*' ;
  916.   sglchar [ semicolon  ] := ';' ;
  917.   sglchar [ colon      ] := ':' ;
  918.   sglchar [ equals     ] := '=' ;
  919.   sglchar [ openparen  ] := '(' ;
  920.   sglchar [ closeparen ] := ')' ;
  921.   sglchar [ period     ] := '.' ;
  922.   recordseen := false;
  923.   nextchar.name := blank;
  924.   nextchar.value := space;
  925.   new(currsym);
  926.   new(nextsym);
  927.   with nextsym^ do
  928.     begin
  929.       name := othersym;
  930.       for i := 1 to maxsymbolsize do
  931.         value[i] := space;
  932.       lnth := 1;
  933.       spacesbefore := 0;
  934.       crsbefore := 0;
  935.     end ; (* with *)
  936.  
  937.   getchar (inputfile,nextchar,currchar);
  938.   getsymbol(inputfile,nextsym,currsym );
  939. end ; (* initalize *)
  940. (* page 193 *)
  941.  
  942. function stackempty : boolean;
  943. begin (* stackempty *)
  944.   if top = 0
  945.     then
  946.       stackempty := true
  947.     else
  948.       stackempty := false
  949. end ; (* stackempty *)
  950.  
  951. function stackfull : boolean;
  952. begin (* stackfull *)
  953.   if top = maxstacksize
  954.     then
  955.       stackfull := true
  956.     else
  957.       stackfull := false
  958. end ; (* stackfull *)
  959.  
  960. (* page 194 *)
  961.  
  962. procedure popstack( var indentsymbol : keysymbol;
  963.                    var prevmargin : integer );
  964. begin (* popstack *)
  965.   if not stackempty
  966.     then
  967.       begin
  968.         indentsymbol := stack[top].indentsymbol;
  969.         prevmargin := stack[top].prevmargin;
  970.         top := top-1;
  971.       end
  972.     else
  973.       begin
  974.         indentsymbol := othersym;
  975.         prevmargin := 0;
  976.       end ;
  977. end ; (* popstack *)
  978.  
  979. procedure pushstack ( indentsymbol : keysymbol;
  980.                      prevmargin : integer );
  981. begin (* pushstack *)
  982.   top := top+1;
  983.   stack[top].indentsymbol := indentsymbol;
  984.   stack[top].prevmargin := prevmargin;
  985. end ; (* pushstack *)
  986.  
  987. (* page 195 *)
  988.  
  989. procedure writecrs( numberofcrs : integer;
  990.                    var currlinepos : integer;
  991.                    var outputfile : text );
  992.  
  993. var
  994.     i : integer;
  995. begin
  996.   if numberofcrs > 0
  997.     then
  998.       begin
  999.         for i := 1 to numberofcrs do
  1000.           writeln(outputfile);
  1001.         currlinepos := 0;
  1002.       end ;
  1003. end ; (* writecrs *)
  1004.  
  1005. procedure insertcr ( var currsym : symbolinfo;
  1006.                     var outputfile : text );
  1007.  
  1008. const 
  1009.       once = 1;
  1010. begin
  1011.   if currsym^.crsbefore = 0
  1012.     then
  1013.       begin
  1014.         writecrs(once,currlinepos,outputfile);
  1015.         currsym^.spacesbefore := 0;
  1016.       end ;
  1017. end ; (* insertcr *)
  1018.  
  1019. (* page 196 *)
  1020.  
  1021. procedure insertblankline ( var currsym : symbolinfo;
  1022.                            var outputfile : text );
  1023.  
  1024. const 
  1025.       once = 1;
  1026.       twice = 2;
  1027. begin
  1028.   if currsym^.crsbefore = 0
  1029.     then
  1030.       begin
  1031.         if currlinepos = 0
  1032.           then
  1033.             writecrs(once,currlinepos,outputfile)
  1034.           else
  1035.             writecrs(twice,currlinepos,outputfile);
  1036.         currsym^.spacesbefore := 0
  1037.       end
  1038.     else
  1039.       if currsym^.crsbefore = 1
  1040.         then
  1041.           if currlinepos > 0
  1042.             then
  1043.               writecrs (once,currlinepos,outputfile);
  1044. end ; (* insertblankline *)
  1045.  
  1046. (* page 197 *)
  1047.  
  1048. procedure lshifton ( dindentsymbols : keysymset );
  1049.  
  1050. var 
  1051.     indentsymbol : keysymbol;
  1052.     prevmargin   : integer;
  1053. begin (* lshifton *)
  1054.   if not stackempty
  1055.     then
  1056.       begin
  1057.         repeat
  1058.           popstack(indentsymbol,prevmargin );
  1059.           if indentsymbol in dindentsymbols
  1060.             then
  1061.               currmargin := prevmargin
  1062.         until (not(indentsymbol in dindentsymbols))
  1063.               or (stackempty);
  1064.         if not (indentsymbol in dindentsymbols)
  1065.           then
  1066.             pushstack(indentsymbol,prevmargin );
  1067.       end ;
  1068. end ; (* lshifton *)
  1069.  
  1070. procedure lshift;
  1071.  
  1072. var 
  1073.     indentsymbol : keysymbol;
  1074.     prevmargin   : integer;
  1075. begin
  1076.   if not stackempty
  1077.     then
  1078.       begin
  1079.         popstack (indentsymbol,prevmargin );
  1080.         currmargin := prevmargin;
  1081.       end ;
  1082. end ; (* lshift *)
  1083.  
  1084. (* page 198 *)
  1085.  
  1086. procedure insertspace ( var symbol : symbolinfo;
  1087.                        var outputfile : text );
  1088. begin (* insertspace *)
  1089.   if currlinepos < maxlinesize
  1090.     then
  1091.       begin
  1092.         write(outputfile, space);
  1093.         currlinepos := currlinepos +1;
  1094.         with symbol^ do
  1095.           if (crsbefore =0)and(spacesbefore > 0 )
  1096.             then
  1097.               spacesbefore := spacesbefore-1
  1098.       end ;
  1099. end ; (* insertspace *)
  1100.  
  1101. procedure movelinepos ( newlinepos : integer;
  1102.                        var currlinepos : integer;
  1103.                        var outputfile : text );
  1104.  
  1105. var 
  1106.     i : integer;
  1107. begin (* movelinepos *)
  1108.   for i := currlinepos+1 to newlinepos do
  1109.     write(outputfile,' ');
  1110.   currlinepos := newlinepos;
  1111. end ; (* movelinepos *)
  1112.  
  1113. (* page 199 *)
  1114.  
  1115. procedure printsymbol ( currsym : symbolinfo;
  1116.                        var currlinepos : integer;
  1117.                        var outputfile : text );
  1118.  
  1119. var 
  1120.     i : integer;
  1121. begin (* printsymbol *)
  1122.   with currsym^ do
  1123.     begin
  1124.       for i := 1 to lnth do
  1125.         write (outputfile,value[i]);
  1126.       currlinepos := currlinepos + lnth;
  1127.     end (* with *)
  1128. end ; (* printsymbol *)
  1129.  
  1130. (* page 200 *)
  1131.  
  1132. procedure ppsymbol ( currsym : symbolinfo;
  1133.                     var outputfile : text );
  1134.  
  1135. const 
  1136.       once = 1;
  1137.  
  1138. var 
  1139.     newlinepos : integer;
  1140. begin (* ppsymbol *)
  1141.   with currsym^ do
  1142.     begin
  1143.       writecrs(crsbefore,currlinepos,outputfile);
  1144.       if (currlinepos + spacesbefore > currmargin)
  1145.          or(name in [opencomment,closecomment])
  1146.         then
  1147.           newlinepos := currlinepos + spacesbefore
  1148.         else
  1149.           newlinepos := currmargin;
  1150.       if newlinepos + lnth > maxlinesize
  1151.         then
  1152.           begin
  1153.             writecrs(once,currlinepos,outputfile);
  1154.             if currmargin + lnth <= maxlinesize
  1155.               then
  1156.                 newlinepos := currmargin
  1157.               else
  1158.                 if lnth < maxlinesize
  1159.                  then
  1160.                   newlinepos := maxlinesize - lnth
  1161.                  else
  1162.                   newlinepos := 0
  1163.           end ;
  1164.       movelinepos(newlinepos,currlinepos,outputfile);
  1165.       printsymbol(currsym,currlinepos,outputfile);
  1166.     end ; (* with *)
  1167. end ; (* ppsymbol *)
  1168.  
  1169. (* page 201 *)
  1170.  
  1171. procedure rshifttoclp(currsym : keysymbol );
  1172. forward;
  1173.  
  1174. procedure gobble(var inputfile : text;
  1175.                  terminators : keysymset;
  1176.                  var currsym,nextsym : symbolinfo ;
  1177.                  var outputfile : text );
  1178. begin (* gobble *)
  1179.   rshifttoclp (currsym^.name);
  1180.   while not(nextsym^.name in (terminators+[endoffile])) do
  1181.     begin
  1182.       getsymbol(inputfile,nextsym,currsym );
  1183.       ppsymbol (currsym,outputfile );
  1184.     end ; (* while *)
  1185.   lshift;
  1186. end ; (* gobble *)
  1187.  
  1188. (* page 202 *)
  1189.  
  1190. procedure rshift( currsym : keysymbol);
  1191. begin
  1192. (* rshift *)
  1193.   if not stackfull
  1194.     then
  1195.       pushstack (currsym,currmargin);
  1196.   if currmargin < sfail1
  1197.     then
  1198.       currmargin := currmargin + indent1
  1199.     else
  1200.       if currmargin < sfail2
  1201.         then
  1202.           currmargin := currmargin + indent2
  1203. end ; (* rshift *)
  1204.  
  1205. procedure rshifttoclp;
  1206. begin (* rshifttoclp *)
  1207.   if not stackfull
  1208.     then
  1209.       pushstack(currsym,currmargin);
  1210.   currmargin := currlinepos
  1211. end ; (* rshifttoclp *)
  1212.  
  1213. (* page 203 *)
  1214.  
  1215.  
  1216. (* ************** *)
  1217.  
  1218. begin (* prettyprint *)
  1219.   commandline(file1,file2);
  1220.   writeln;
  1221.   writeln ('Program to prettyprint Pascal source code.');
  1222.   ok := openin;
  1223.   if ok
  1224.     then
  1225.       ok := ok and openout;
  1226.   if ok
  1227.     then (* the files were opened correctly *)
  1228.       begin (* so do the main part *)
  1229.         initalize ( inputfile,  outputfile, top,
  1230.                    currlinepos,  currmargin, keyword, dblchars,
  1231.                    dblchar, sglchar, recordseen, currchar, nextchar,
  1232.                    currsym, nextsym );
  1233.         init2 (ppoption);
  1234.         init3 (ppoption); (* it takes 3 procs to init *)
  1235.         crpending := false;
  1236.         while (nextsym^.name <> endoffile) do
  1237.           begin
  1238.            getsymbol(inputfile,nextsym,currsym);
  1239.            with ppoption [currsym^.name] do
  1240.             begin
  1241.              if ((crpending and not
  1242.                 (crsuppress in optionsselected))
  1243.                 or(crbefore in optionsselected))
  1244.               then
  1245.                begin
  1246.                 insertcr(currsym,outputfile);
  1247.                 crpending := false;
  1248.                end ;
  1249.              if blanklinebefore in optionsselected
  1250.               then
  1251.                begin
  1252.                 insertblankline(currsym,outputfile);
  1253.                 crpending := false;
  1254.                end ;
  1255.              if dindentonkeys in optionsselected
  1256.               then
  1257.                lshifton(dindentsymbols);
  1258.              if dindent in optionsselected
  1259.               then
  1260.                lshift;
  1261.              if spacebefore in optionsselected
  1262.               then
  1263.                insertspace(currsym,outputfile);
  1264.              ppsymbol(currsym,outputfile);
  1265.              if spaceafter in optionsselected
  1266.               then
  1267.                insertspace(nextsym,outputfile);
  1268.              if indentbytab in optionsselected
  1269.               then
  1270.                rshift(currsym^.name);
  1271.              if indenttoclp in optionsselected
  1272.               then
  1273.                rshifttoclp(currsym^.name );
  1274.              if gobblesymbols in optionsselected
  1275.               then
  1276.                gobble ( inputfile,gobbleterminators,
  1277.                        currsym,nextsym,outputfile);
  1278.              if crafter in optionsselected
  1279.               then
  1280.                crpending := true;
  1281.             end (* with *)
  1282.           end ; (* while *)
  1283.         if crpending
  1284.           then
  1285.            writeln(outputfile);
  1286.         close (outputfile);
  1287.         close (inputfile);
  1288.         writeln ('Prettyprint successful.');
  1289.       end (* begin by ok *)
  1290.     else
  1291.       writeln ('Prettyprint stopped.');
  1292. end.
  1293.