home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
turbopas
/
rnf-pas.lbr
/
RNF.PQS
/
RNF.PAS
Wrap
Pascal/Delphi Source File
|
1986-07-16
|
15KB
|
481 lines
PROGRAM RNF(INPUT, OUTPUT , INFILE, OUTFILE);
{ RNF: Text formatter for document prepartation. }
{ Originally written for Cyber by Bob Foster at U. of Illinois. This
version derives from Software Consulting Services production RNF
18-Dec-84 running on VAX VMS ver 4. Enhancements to VAX version by
John McGrath. This is a well-written program, easy to maintain,
adapt, and enhance; unfortunately there are few comments. }
{ Adapted to Turbo Pascal and Prospero Pro Pascal (only minor changes
required) by Willett Kempton, May 1985 and May 1986. }
{ Very few compiler or operating system dependencies are used, and this
program can easily be ported to most Pascal systems on most computers. }
{ Normally RNF is run directly to the printer; there has not been a serious
attempt at speed optimization since the printer limits run speed. If
it is frequently used to write to files, it can be sped up by using
MOVE in place of DO loops in DOJUST and ADDWORD. }
CONST
version = ' 7 June 86 ';
VPAGE = 1;
VCH = 2;
VHL = 3;
VLIST = 9;
(* NEXT IS 20 *)
VLM = 20;
VRM = 21;
VSP = 22;
VNMP = 23;
VOLNO = 24;
vcr = 25;
VANSI = 26;
NextVariable = 27;
(* NEXT IS 27 *)
VARMAX = 140;
MACCHR = '.';
VARCHR = '$';
CMDCHR = '.';
NOPAGE = FALSE; { set true to make WRITELNs, not PAGE, do page eject }
TABMAX = 16;
LINLEN = 160;
MAXENP = 20;
HLMAX = 5;
CHRMOD = 128;
LowerCaseConvert = -32 (* ord('A') - ord('a') *);
FIGMAX = 10;
MaxParms = 8;
VHLMAX = 5;
MaxErrors = 63;
maxhash = 82;
AlfaBlanks = ' ';
AlfaLen = 10;
StackMax = 20;
StgTblSize = 10000; { this may need to be smaller on CP/M-80 }
paocBUG = true; { true if "write(paoc:len);" does not work according to ISO }
{ false for Cyber, VMS, Prospero, true for Turbo and UCSD }
TYPE
alfa = PACKED ARRAY [1 .. AlfaLen] OF CHAR;
StgRange = 1 .. StgTblSize;
VARTYP = (VITEM, VARRAY);
RELOPR = (EQ, GT, LT, NE, GE, LE, BADRELOP);
ENRANGE = 0 .. MAXENP;
SIGN = (PLUS, MINUS, UNSIGNED, INVALID);
SYMTYP = (WORD, COMMAND, VARS, NONE);
LLEN = 0 .. LINLEN;
LALEN = 1 .. LINLEN;
LineFlags = packed array [llen] of boolean;
JUSLIN = RECORD
NDX: LLEN;
POS: ARRAY [LALEN] OF INTEGER
END;
ALINE = PACKED ARRAY [LALEN] OF CHAR;
LINE = RECORD
LEN: LLEN;
LIN,
OverLin: ALINE;
CENTER,
BBAR: BOOLEAN;
HasOverPrinting,
HasBoldPrinting,
HasUnderscore: boolean;
USflag,
BoldFlag: LineFlags;
END;
CMDTYP = (CBLANK, cinclude, CCR, CBREAK, CRESPAG, CRES, CESCCHR,
CCENTER, CJUST, CUL, CLMAR, CRMAR, CFILL, CSIG, CPAGE,
CSUP, CSTD, CPS, CSAV, CP, CPP, CAP, CI, CSP, CS, CTP,
CCH, CHL, CNMP, CPNO, CTITLE, CST, CATITLE, CLIST,
CLE, CELIST, CFIG, CBAR, CBB, CEB, CU, CT, CTAB,
CTABS, CRT, CRIGHT, CLINES, CMACRO, CX, CVAR, CINC,
CASIS, CDEC, (* END OF CMDTYP SET *) CFLAG, CBOLD,
CCASEFLAG, CFLAGCAPS, CFLAGOVER, CFLAGSIG, CLOWER, CUPPER,
CPERIOD, CSAVPAG, CFRCPAGE, CTOP, CMID, CBOT, CARRAY,
CFMT, CIF, CDOT, CREM, CUPP, CUSB, NOTCMD);
CharType = (UpArrow, ucLetter, lcLetter, LeftAngle, EndSentence,
UnderScore, NumberSign, BackSlash, MiscChar, ArithChar,
OtherChar);
CharRange = char; { Prospero limits char to 0..127, thus to use }
{ full 8-bit set need ChrRange = '00' .. 'FF' }
ENVIRON = RECORD
J,
F,
PR,
SG,
UN,
Bl: BOOLEAN;
PM,
SP: INTEGER;
LM,
RM,
PS,
PT: LLEN;
TB: PACKED ARRAY [1 .. TABMAX] OF LLEN
END;
MACTYP = (HEADER, PARM);
PMAC = ^ MAC;
StringLocation = -1 .. StgTblSize;
StgDescription = record
ActiveMacro: pmac;
StgPosition,
StgBegin,
StgEnd: StringLocation;
end;
MAC = RECORD
ON: BOOLEAN;
NM: alfa;
MT: MACTYP;
NP: 0 .. MaxParms;
MacroBegin,
MacroEnd: StringLocation;
MA: PMAC;
END;
{}{VAX} { string80 = packed array [1..80] of char;}
{}{Turbo, Prospero } string80 = string[80];
OutflType = text;
VAR
INFILE,
inclfile: text;
OUTFILE: OutFlType;
{} InputName,
{} inclname: string80;
SYMTYPE: SYMTYP;
TopOfStack: integer;
StgStack: array [0 .. StackMax] of StgDescription;
StgMarker: integer (* free space pointer from end *);
FreeStgIndx: integer (* free space pointer from beginning *);
StgTable: packed array [StgRange] of char;
SYL,
OTL,
TMPL,
ADDSYL: LINE;
FREEMACP: PMAC;
CMDS: ARRAY [CMDTYP] OF alfa;
CMDTYPE: CMDTYP;
perfect: array [0 .. maxhash] of cmdtyp;
letperfect: array ['A' .. 'Z'] of integer;
InitialPageEject,
HandFeed,
AP,
asis,
ATITLE,
BAR,
BB,
bold,
DoInclFl,
ESCCHR,
FILL,
FLAG,
FLAGCAPS,
FLAGOVER,
FLAGSIG,
HOLDBB,
JUSTIT,
LOWER,
PARA,
PERIOD,
PQEND,
PREL,
RIGHT,
SIGBL,
SUP,
UL,
UNDL,
USB,
XTRABL,
YES: Boolean;
ILNO,
INCLNO,
OETXT,
OVETXT,
OEPAG,
OVBTXT,
PMAR: INTEGER;
JUST: JUSLIN;
ENSTK: ARRAY [ENRANGE] OF ENVIRON;
ENP: ENRANGE;
PARSPACE,
PARTEST,
SPACING: INTEGER;
PAGENV: ENVIRON;
DEFRB: INTEGER;
FORCE,
FIRSTCH: BOOLEAN;
FIGP: 0 .. FIGMAX;
FIGN: ARRAY [1 .. FIGMAX] OF INTEGER;
RIGHTSPACE: 0 .. 136;
TABS: ARRAY [1 .. TABMAX] OF LLEN;
RT,
T,
DOT: BOOLEAN;
BREAKSET,
OPTBRKSET,
CRSET: SET OF CBLANK .. CDEC;
EMPTY: BOOLEAN;
MACLSTP,
DefrFrcPgMacP,
FrcPgMacP,
ParagMacP,
CarRtnMacP,
MidMacP,
TTLMACP,
STLMACP,
ChapterMacP,
CHTMACP: PMAC;
NOTMACRO: BOOLEAN;
LASTCUP: integer;
XTEND: BOOLEAN;
LASTLEN,
LASTSLEN: LLEN;
VID: ARRAY [1 .. VARMAX] OF ALFA;
VAL: ARRAY [1 .. VARMAX] OF INTEGER;
VTY: ARRAY [1 .. VARMAX] OF VARTYP;
VUP: ARRAY [1 .. VARMAX] OF 1 .. VARMAX;
VARNDX,
TV: 1 .. VARMAX;
PUSHED: BOOLEAN;
PAGSAV: LINE;
PAGOTL: BOOLEAN;
ARELOPR: ARRAY [RELOPR] OF ALFA;
DangerPoint: integer;
EXPRERR,
SHOWEXPR: BOOLEAN;
ITEMSET,
TERMSET: SET OF ' ' .. '_';
RomanChars: packed array [1 .. 26] of char;
RomanValue: array [1 .. 13] of integer;
ROMLC: BOOLEAN;
EOFINPUT: BOOLEAN;
ErrorsOnLine: integer;
ErrorSet: set of 0 .. MaxErrors;
StartToken: integer;
VarName: alfa;
ERRORCOUNT: INTEGER;
LineCount: integer;
MakeUpper,
MakeLower: packed array [CharRange] of char;
CharCategory: array [CharRange] of CharType;
EmptyFlags: LineFlags;
{}{Turbo} { Page must be manually declared on Turbo Pascal }
{ use chr(12) or the page eject code for your printer, or set NOPAGE true }
procedure page(var f:text);
begin
writeln(f,chr(12))
end;
{}{Prospero} { Halt must be manually declared in Prospero Pro Pascal }
{ procedure halt;
procedure ExitProg(retcode:integer); external;
begin ExitProg(1); end;
}
procedure WritePAOC ( var L: ALINE; width: integer);
{ Write a Packed Array Of Char, with a field width. This procedure is }
{ necessary only because some Pascal compilers ignore field width on PAOCs. }
var i : integer;
begin
if not paocBUG
THEN write(outfile,L:width) { ISO standard: VAX, Prospero, UNIX etc. }
ELSE for i:= 1 to width do write(outfile, L[i]); { Turbo, MT+, UCSD }
end (* WritePAOC *);
function FileExists (filename:string80) : boolean;
{ Return true if file is available. Highly compiler-specific }
var
fl : text;
begin
{}{VMS}{ open (File_Variable:=Fl,File_Name:=filename, }
{}{VMS}{ History := old,error:=continue); FileExists := (Status(fl) = 0); }
(*$I-*)
{}{Turbo} assign(fl,filename); reset(fl); FileExists:= IOResult=0; close(fl);
(*$I+*)
{}{Prospero} { FileExists := fstat(filename); }
end (* fileexists *);
function BoolOrd(BoolExp: boolean): integer;
forward;
function ForceUpperCase(achar: char): char;
forward;
procedure StackToMacro(StartAt: integer;
var StartMacro, FinishMacro: StringLocation);
forward;
procedure Error(ErrNum: integer);
forward;
function TestOk(BoolExp: Boolean; ErrNum: integer): Boolean;
forward;
PROCEDURE CLRTAB;
forward;
PROCEDURE SAVENV(VAR E: ENVIRON);
forward;
procedure PushText(p: pmac);
forward;
PROCEDURE CLRLINE;
forward;
PROCEDURE SETSTD;
forward;
PROCEDURE RESENV(VAR E: ENVIRON);
forward;
{ VAX segment %include 'RNF0.pas' }
{ overlay } { CP/M-80 requires overlay }
(*$IRNF0.pas *)
{ VAX segment %include 'RNF1.pas' }
{ overlay } { CP/M-80 requires overlay }
(*$IRNF1.pas *)
{ VAX segment }
{ overlay } { CP/M-80 requires overlay }
procedure ProcessLine;
var
LastTop: integer;
LineIndex,
CurLinIndx: integer;
{VAX} { %include 'RNF2.PAS' %include 'RNF3.PAS' }
(*$IRNF2.pas *)
(*$IRNF3.pas *)
begin (* ProcessLine *)
if EofInput then
fin
else
with StgStack[TopOfStack] do
if asis and (TopOfStack = 0) then
begin
if StgTable[StgBegin] = '!' then
begin
StgPosition := StgEnd;
asis := false
end
else
BEGIN
with otl do
begin
LineIndex := VAL[VLM];
for CurLinIndx := StgBegin to StgEnd do
begin
LIN[LineIndex] := StgTable[CurLinIndx];
LineIndex := LineIndex + 1;
end;
LIN[LineIndex] := ' ';
len := LineIndex;
while ((LineIndex > 1) and (LIN[LineIndex] = ' ')) do
LineIndex := LineIndex - 1;
if LineIndex > val[vrm] + 1 then
begin
StartToken := val[vrm] + 1;
Error(54) (* Error - Asis text past right margin *);
end;
end;
StgPosition := StgEnd;
EMPTY := FALSE;
PUTLINE;
END;
end
else
begin
if ap and (StgTable[StgBegin] = ' ') and (StgPosition = StgBegin)
THEN PushText(ParagMacP);
GETSYM;
IF SYMTYPE = NONE THEN BLANKLINE
ELSE
repeat
CASE SYMTYPE OF
WORD: PUTWORD;
VARS: PUTVAR;
COMMAND:
begin
LastTop := TopOfStack;
if CMDTYPE in OPTBRKSET then BREAK;
if CMDTYPE in CRSET then CR;
(* the above break may force (stack) a page eject.
Do it first *)
if (LastTop <> TopOfStack) and (TopOfStack < StackMax)
then
begin
StgStack[TopOfStack + 1] := StgStack[TopOfStack];
TopOfStack := TopOfStack - 1;
(* put the current symbol under the top of stack *)
PushSyl(syl);
(* and push both down *)
TopOfStack := TopOfStack + 2;
end
else
DoCommand(CMDTYPE)
end
END;
GETSYM;
until symtype = none;
ENDLINE;
end;
end;
{VMS %include 'RNF4.PAS'}
(*$IRNF4.pas *)
BEGIN (*RNF*)
WRITELN(' RNF Text Formatter. ', version);
INI;
LineCount := 0;
repeat
ErrorsOnLine := 0;
ErrorSet := [];
getcur;
ProcessLine;
if ErrorSet <> [] then
WriteErrorMessages;
until eofinput;
writeln;
writeln(' Lines read: ', LineCount - 1: 1, '.');
if ErrorCount = 0 then
writeln(' No Errors detected.')
else
WRITELN( ' Errors detected: ', ErrorCount);
WRITELN( ' Last page processed: ', VAL[VPAGE]);
{}CLOSE(OUTFILE);
END (*RNF*).