{$A-}
PROGRAM CHAPTER7;
{$I TOOLU.PAS}
var cmdptr:file;
PROCEDURE FORMAT;
CONST
  CMD=PERIOD;
  PAGENUM=SHARP;
  PAGEWIDTH=60;
  PAGELEN=66;
  HUGE=10000;
TYPE
  CMDTYPE=(BP,BR,CE,FI,FO,HE,IND,LS,NF,PL,
    RM,SP,TI,UL,UNKNOWN);
VAR
  CURPAGE,NEWPAGE,LINENO:INTEGER;
  PLVAL,M1VAL,M2VAL,M3VAL,M4VAL:INTEGER;
  BOTTOM:INTEGER;
  HEADER,FOOTER:XSTRING;
  
  FILL:BOOLEAN;
  LSVAL,SPVAL,INVAL,RMVAL,TIVAL,CEVAL,ULVAL:INTEGER;

  OUTP,OUTW,OUTWDS:INTEGER;
  OUTBUF:XSTRING;
  DIR:0..1;
  INBUF:XSTRING;
  
PROCEDURE SKIPBL(VAR S:XSTRING;VAR I:INTEGER);
BEGIN
  WHILE(S[I]=BLANK) OR(S[I]=TAB)DO
    I:=I+1
  END;
  
FUNCTION GETVAL(VAR BUF:XSTRING;VAR ARGTYPE:INTEGER):INTEGER;
VAR
  I:INTEGER;
BEGIN
  I:=1;
  WHILE(NOT(BUF[I]IN[BLANK,TAB,NEWLINE]))DO
    I:=I+1;
  SKIPBL(BUF,I);
  ARGTYPE:=BUF[I];
  IF(ARGTYPE=PLUS) OR (ARGTYPE=MINUS) THEN
    I:=I+1;
  GETVAL:=CTOI(BUF,I)
END;

PROCEDURE SETPARAM(VAR PARAM:INTEGER;VAL,ARGTYPE,DEFVAL,MINVAL,MAXVAL:
  INTEGER);
BEGIN
  IF(ARGTYPE=NEWLINE)THEN
    PARAM:=DEFVAL
  ELSE IF (ARGTYPE=PLUS)THEN
    PARAM:=PARAM+VAL
  ELSE IF(ARGTYPE=MINUS) THEN
    PARAM:=PARAM-VAL
  ELSE PARAM:=VAL;
  PARAM:=MIN(PARAM,MAXVAL);
  PARAM:=MAX(PARAM,MINVAL)
END;

PROCEDURE SKIP(N:INTEGER);
VAR I:INTEGER;
BEGIN
  FOR I:=1 TO N DO
    PUTC(NEWLINE)
END;

PROCEDURE PUTTL(VAR BUF:XSTRING;PAGENO:INTEGER);
VAR I:INTEGER;
BEGIN
  FOR I:=1 TO XLENGTH(BUF) DO
    IF(BUF[I]=PAGENUM) THEN
      PUTDEC(PAGENO,1)
    ELSE
      PUTC(BUF[I])
END;

PROCEDURE PUTFOOT;
BEGIN
  SKIP(M3VAL);
  IF(M4VAL>0) THEN BEGIN
    PUTTL(FOOTER,CURPAGE);
    SKIP(M4VAL-1)
  END
END;

PROCEDURE PUTHEAD;
BEGIN
  CURPAGE:=NEWPAGE;
  NEWPAGE:=NEWPAGE+1;
  IF(M1VAL>0)THEN BEGIN
    SKIP(M1VAL-1);
    PUTTL(HEADER,CURPAGE)
  END;
  SKIP(M2VAL);
  LINENO:=M1VAL+M2VAL+1
END;

PROCEDURE PUT(VAR BUF:XSTRING);
VAR
  I:INTEGER;
BEGIN
  IF(LINENO<=0) OR(LINENO>BOTTOM) THEN
    PUTHEAD;
  FOR I:=1 TO INVAL+TIVAL DO
    PUTC(BLANK);
  TIVAL:ööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööER;
BEGIN
  IF(INBUF[1]=BLANK) OR (INBUF[1]=NEWLINE) THEN
    LEADBL(INBUF);
  IF(ULVAL>0) THEN BEGIN
    UNDERLN(INBUF,MAXSTR);
    ULVAL:=ULVAL-1
  END;
  IF(CEVAL>0)THEN BEGIN
    CENTER(INBUF);
    PUT(INBUF);
    CEVAL:=CEVAL-1
  END
  ELSE IF (INBUF[1]=NEWLINE)THEN
    PUT(INBUF)
  ELSE IF(NOT FILL) THEN
    PUT(INBUF)
  ELSE BEGIN
    I:=1;
    REPEAT
      I:=GETWORD(INBUF,I,WORDBUF);
      IF(I>0)THEN
        PUTWORD(WORDBUF)
      UNTIL(I=0)
    END
    
END;
  

PROCEDURE INITFMT;
BEGIN
  FILL:=TRUE;
  DIR:=0;
  INVAL:=0;
  RMVAL:=PAGEWIDTH;
  TIVAL:=0;
  LSVAL:=1;
  SPVAL:=0;
  CEVAL:=0;
  ULVAL:=0;
  LINENO:=0;
  CURPAGE:=0;
  NEWPAGE:=1;
  PLVAL:=PAGELEN;
  M1VAL:=3;M2VAL:=2;M3VAL:=2;M4VAL:=3;
  BOTTOM:=PLVAL-M3VAL-M4VAL;
  HEADER[1]:=NEWLINE;
  HEADER[2]:=ENDSTR;
  FOOTER[1]:=NEWLINE;
  FOOTER[2]:=ENDSTR;
  OUTP:=0;
  OUTW:=0;
  OUTWDS:=0
END;

FUNCTION GETCMD(VAR BUF:XSTRING):CMDTYPE;
VAR
  CMD:PACKED ARRAY[1..2] OF CHAR;
BEGIN
  CMD[1]:=CHR(BUF[2]);
  CMD[2]:=CHR(BUF[3]);
  IF(CMD='fi')THEN GETCMD:=FI
  ELSE IF (CMD='nf')THEN GETCMD:=NF
  ELSE IF (CMD='br')THEN GETCMD:=BR
  ELSE IF (CMD='ls')THEN GETCMD:=LS
  ELSE IF (CMD='bp')THEN GETCMD:=BP
  ELSE IF (CMD='sp')THEN GETCMD:=SP
  ELSE IF (CMD='in')THEN GETCMD:=IND
  ELSE IF (CMD='rm')THEN GETCMD:=RM
  ELSE IF (CMD='ce')THEN GETCMD:=CE
  ELSE IF (CMD='ti')THEN GETCMD:=TI
  ELSE IF (CMD='ul')THEN GETCMD:=UL
  ELSE IF (CMD='he') THEN GETCMD:=HE
  ELSE IF (CMD='fo') THEN GETCMD:=FO
  ELSE IF (CMD='pl') THEN GETCMD:=PL
  ELSE GETCMD:=UNKNOWN
END;

PROCEDURE COMMAND(VAR BUF:XSTRING);
VAR CMD:CMDTYPE;
ARGTYPE,SPVAL,VAL:INTEGER;
BEGIN
  CMD:=GETCMD(BUF);
  IF(CMD<>UNKNOWN)THEN
    VAL:=GETVAL(BUF,ARGTYPE);
    CASE CMD OF
    FI:BEGIN
       BREAK;
       FILL:=TRUE END;
    NF:BEGIN BREAK;
       FILL:=FALSE END;
    BR:BREAK;
    LS:SETPARAM(LSVAL,VAL,ARGTYPE,1,1,HUGE);
    CE:BEGIN BREAK;
       SETPARAM(CEVAL,VAL,ARGTYPE,1,0,HUGE) END;
    UL:SETPARAM(ULVAL,VAL,ARGTYPE,1,0,HUGE);
    HE:GETTL(BUF,HEADER);
    FO:GETTL(BUF,FOOTER);
    BP:BEGIN PAGE;
       SETPARAM(CURPAGE,VAL,ARGTYPE,CURPAGE+1,-HUGE,HUGE);
       NEWPAGE:=CURPAGE END;
    SP:BEGIN
       SETPARAM(SPVAL,VAL,ARGTYPE,1,0,HUGE);
       space(spval)
       END;
    IND:SETPARAM(INVAL,VAL,ARGTYPE,0,0,RMVAL-1);
    RM:SETPARAM(INVAL,VAL,ARGTYPE,PAGEWIDTH,
        INVAL+TIVAL+1,HUGE);
    TI:BEGIN BREAK;
       SETPARAM(TIVAL,VAL,ARGTYPE,0,-HUGE,RMVAL) END;
    PL:BEGIN
       SETPARAM(PLVAL,VAL,ARGTYPE,PAGELEN,
        M1VAL+M2VAL+M3VAL+M4VAL+1,HUGE);
       BOTTOM:=PLVAL-M3VAL-M4VAL END;
    UNKNOWN:
    END
  END;

       
       

BEGIN
  
  INITFMT;
  WHILE(GETLINE(INBUF,STDIN,MAXSTR))DO
    IF(INBUF[1]=CMD) THEN
      COMMAND(INBUF)
    ELSE
      TEXT(INBUF);
    PAGE
END;

BEGIN
  FORMAT;
  ENDCMD;assign(cmdptr,'SHELL.COM');execute(cmdptr)
END.


