PROGRAM kformat;
{
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                 +
+ PROGRAM TITLE:               FORMAT                             +
+                                                                 +
+ WRITTEN BY:                  K & F.                             +
+                                                                 +
+  Translated from the "format" program in the book               +
+  "Software Tools" by Kernigan & Flager                          +
+                                                                 +
+ MODIFICATION RECORD:                                            +
+   MAR 81 - Pascal/Z v 3.3 and seperately compiled               +
+            modules by Raymond E. Penley, March 1981             +
+                                                                 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Zug Editor's comment: This is the MAIN module of a group of programs,
       the following programs are needed:
               KFORMAT.DOC
               KFORMAT.SUB
               KFORMAT.SYM
               KFORMAT.TYP
               STDIO.PAS
               DOCOMM.PAS
               DOTEXT.PAS
               GLOBALS.TOP
               STDFUNC.TOP
       Each PAS progrm gets compiled. The main program must be compiled
first because it makes the additional files *.sym and *typ. Each module
may be edited and recompiled at any time. However, if any changes are
made in the MAIN module then ALL modules MUST be compiled again. At link
time you should have:
       LINK KFORMAT,STDIO,DOTEXT,DOCOMM

}

{$iGLOBALS.TOP }

{$iSTDFUNC.TOP }


{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
{+++ ALL I/O PROCEDURES ARE IN EXTERNAL FILE: STDIO.PAS +++}
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

PROCEDURE STDOPEN;EXTERNAL;
PROCEDURE getc(var ch: char);EXTERNAL;
PROCEDURE putc(c:CHAR);EXTERNAL;
PROCEDURE puts(VAR LINE:BUFFER);EXTERNAL;
PROCEDURE gets(VAR LINE:BUFFER);EXTERNAL;


{
 Skip chars in string
}
PROCEDURE SKIPCHARS(VAR buf: BUFFER; VAR ppos: int);
begin
 WHILE ( (buf[ppos]<>BLANK)
     AND (buf[ppos]<>TAB)
     AND (buf[ppos]<>newline) ) do ppos := ppos + 1;
end;


{
 Skip blanks in string
}
PROCEDURE SKIPBL(VAR buf:BUFFER; VAR i: int);
BEGIN
 WHILE (buf[i]=BLANK) OR (buf[i]=TAB) DO i := i + 1;
END;


{$iIMINMAX.LIB }

{$iCTOITOC.LIB }


{
 Skip n blank lines
}
PROCEDURE SKIP(s: int);
VAR     i: int;
BEGIN
 FOR i := 1 to s DO PUTC(newline);
END;


PROCEDURE PUTDEC(number,width: int);
VAR     numstr  :DSTRING;
       i,nd    : int;
BEGIN
 numstr := STR(number);
 nd := length(numstr);
 FOR i := (nd+1) TO width DO PUTC(SPACE);
 FOR i := 1 to nd DO PUTC(numstr[i]);
END;


{
 put out title line with optional page number
}
PROCEDURE PUTTL(VAR ttl:BUFFER; pagno: int);
VAR     i: int;
BEGIN
 FOR i := 1 TO LENGTH(ttl) DO
   IF (ttl[i]=PAGENUM)THEN
     PUTDEC(pagno,1)
   ELSE
     PUTC(ttl[i]);
END;


{
       put out page header
}
PROCEDURE PUTHEAD;
BEGIN
 curpag := newpag;
 newpag := newpag + 1;
 IF (m1val > 0) THEN
   BEGIN
     SKIP(m1val-1);
     PUTTL(header,curpag)
   END;
 SKIP(m2val);
 lineno := m1val + m2val + 1;
END;


{
       put out page footer
}
PROCEDURE PUTFOOT;
BEGIN
 SKIP(m3val);
 IF (m4val > 0) THEN
   BEGIN
     PUTTL(footer,curpag);
     SKIP(m4val-1)
   END;
 lineno := 0;                          { *** 3-24-81 *** }
END;


{
       put out a line with proper spacing & indenting
}
PROCEDURE PUTTEXT(VAR ptline:BUFFER);
VAR     i: int;
BEGIN
 IF ((lineno=0) OR (lineno > bottom)) THEN PUTHEAD;
 FOR i := 1 to tival DO PUTC(SPACE);
 tival := inval;
 puts(ptline);
 SKIP(IMIN(lsval-1,bottom-lineno));
 lineno := lineno + lsval;
 IF (lineno > bottom) THEN PUTFOOT;
END;


PROCEDURE DOBREAK;
BEGIN
 IF ( outp > 0 ) THEN
   begin append(outbuf,newline);
         PUTTEXT(outbuf);
   end;
 outp := 0;
 outw := 0;
 outwds := 0;
 setlength(outbuf,0);          { * outbuf := ''; * }
END;


{++++++++++++++++++++++++++++++++++}
{$R-}{ RANGE CHECKING OFF          }
{$S-}{ STACK OVERFLOW CHECKING OFF }
{++++++++++++++++++++++++++++++++++}


PROCEDURE INITGLOBALS;
BEGIN
 EOS    := CHR(EOSVAL);
 newline := EOS;               { *** 3-81 *** }
 BACKSPACE := CHR(BACKSPVAL);
 BLANK  := ' ';
 TAB    := CHR(9);
 spacefill := FALSE;
 direction := FALSE;
 fill   := TRUE;
 lsval  := 1;
 inval  := 0;
 rmval  := PAGWIDDEF;
 tival  := 0;
 ceval  := 0;
 ulval  := 0;
 spval  := 0;
 curpag := 0;
 newpag := 1;
 lineno := 0;
 plval  := PAGLENDEF;
 m1val  := HEMARGDEF;
 m2val  := 2;
 m3val  := 2;
 m4val  := FOMARGDEF;
 bottom := plval - m3val - m4val;
 setlength(header,0);          { * header := ''; * }
 setlength(footer,0);          { * footer := ''; * }
 cmdlist[CMD0] := '  ';
 cmdlist[ fi ] := 'fi';
 cmdlist[ ce ] := 'ce';
 cmdlist[ ul ] := 'ul';
 cmdlist[ ls ] := 'ls';
 cmdlist[ bp ] := 'bp';
 cmdlist[ he ] := 'he';
 cmdlist[ fo ] := 'fo';
 cmdlist[ ind] := 'in'; { ind avoids conflict with keyword in }
 cmdlist[ rm ] := 'rm';
 cmdlist[ ti ] := 'ti';
 cmdlist[ nf ] := 'nf';
 cmdlist[ sp ] := 'sp';
 cmdlist[ pl ] := 'pl';
 cmdlist[ br ] := 'br';
 cmdlist[ sf ] := 'sf';
 cmdlist[UNKN] := 'zz';
 outp := 0;
 outw := 0;
 outwds := 0;
END;


PROCEDURE DOCOMMAND(cmdline:buffer); EXTERNAL;


PROCEDURE DOTEXT(textline:BUFFER); EXTERNAL;


{
       Main program kformat
}
BEGIN {$C+}{ allow control-c checking only in main program }
 STDOPEN;
 INITGLOBALS;
 WHILE not eof(stdin) and not xeof do
   BEGIN
     gets(inbuf);
     IF inbuf[1] = COMNDFLAG THEN
       DOCOMMAND(inbuf)
     ELSE
       DOTEXT(inbuf);
   END;
 IF ( lineno>0 ) THEN DOCOMMAND('.sp 32000  ');
END. {kformat}