v21i003: A text formatter with some nroff-like capabilities, Part01/03

Rich Salz rsalz at uunet.uu.net
Wed Feb 7 06:51:31 AEST 1990


Submitted-by: tcamp at dukeac.UUCP (Ted A. Campbell)
Posting-number: Volume 21, Issue 3
Archive-name: ro/part01

ro is a text formatter with many of the capabilities of nroff.  It is
based on a long line of CP/M and MSDOS formatters, going back to the ROFF
formatter described in Kernigan and Plauger's <Software Tools.>  Makefiles
are included for DOS and Unix.   Freeware.

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--  1 tcamp   users      2644 Nov 24 13:07 README
# -rw-r--r--  1 tcamp   users     14206 Nov 24 12:50 ro.h
# -rw-r--r--  1 tcamp   users     15015 Nov 24 12:49 ro.c
# -rw-r--r--  1 tcamp   users      7405 Nov 24 12:50 ro_proc.c
# -rw-r--r--  1 tcamp   users     11762 Nov 24 12:50 ro_macr.c
#
echo 'x - README'
if test -f README; then echo 'shar: not overwriting README'; else
sed 's/^X//' << '________This_Is_The_END________' > README
Xro version 1.00 -- Release of Source Code
X-----------------------------------------
X
X
XDescription:
X-----------
X
X"ro" is a text formatter with some of the capabilities 
Xof the Unix (tm, AT&T) "nroff" text formatter.  It is 
Xbased on an honorable tradition of CP/M and DOS formatters
Xwhich go back to the ROFF formatter described in Kernigan 
Xand Plauger's <Software Tools>.  It is copyrighted and 
Xdistributed as "freeware," i.e., you can use it for any 
Xpurpose as long as you don't make money off of it, or 
Xtry to claim that you wrote it.  
X
XThe "ro.qrf" file will give an overview of the capabilities 
Xof the formatter.  
X
XThe sourcecode has been compiled on an XT clone using 
Xthe Microsoft QuickC (tm) compiler, and on the AT&T 
XUnix PC and 3B15 computers using the stock Unix C 
Xcompilers.  
X
X
XFiles:
X-----
X
X	ro.h		general include file
X	ro.c		main program module
X	ro_proc.c	various procedures
X	ro_macr.c	macro procedures
X	ro_dive.c	diversion procedures
X	ro_word.c	word-handling procedures
X	ro_text.c	text-handling procedures
X	ro_setp.c	parameter setting procedures
X	ro_outp.c	output procedures
X
X	Makefile	Unix makefile
X	ro.mak		QuickC makefile
X
X	term.h		include file for filters
X	termnull.c	null filter -- strips out all printer codes
X	termansi.c	ANSI filter -- sets printer codes for ANSI terminal
X	termnx10.c	NX10 filter -- sets printer codes for NX 10 printer
X
X	ro.doc		primary documentation in "ro" format
X	ro.qrf		quick reference guide
X	tmac.m		a macro package
X	test.doc	test document showing use of end-note macros
X	README		this document
X
X
XReading and printing the manual:
X-------------------------------
X
XThe manual (file "ro.doc") is in "ro" format, and must be read
Xusing "ro" and a filter program.  If you have the Unix or DOS 
Xpager "more" installed in your path, you can read it page-by-
Xpage with the command
X
X	ro ro.doc | termnull | more
X
XIf your DOS computer has ANSI.SYS installed, or your Unix terminal
Xsupports ANSI escape sequences, the following command will show 
Xbold as bold and italics as underline:
X
X	ro ro.doc | termansi | more
X
XThe manual can br printed to any printer with the command(s):
X
X	ro ro.doc | termnull | lp		(Unix)
X	ro ro.doc | termnull >prn		(DOS)
X
XWith the Star Micronics NX10 printer, you may substitute 
X"termnx10" for "termnull" in the above command lines.  Instructions
Xfor creating filters for other printers are included in "ro.doc".  
X
XBinaries:
X-----------
X
XPC-compatible binaries have been posted to comp.binaries.ibm.pc.
X
X
XCommunications:
X--------------
X
XTed A. Campbell
XBywater Software 
XBox 4023 
XDuke Station
XDurham, NC  27706
X
XInternet:  	tcamp at dukeac.ac.duke.edu
XGENIE:		T.CAMPBELL1
________This_Is_The_END________
if test `wc -l < README` -ne 95; then
	echo 'shar: README was damaged during transit (should have been 95 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ro.h'
if test -f ro.h; then echo 'shar: not overwriting ro.h'; else
sed 's/^X//' << '________This_Is_The_END________' > ro.h
X/********************************************************/
X/*							*/
X/*	ro.h		General header file for ro	*/
X/*							*/
X/*	ro version 1.00					*/
X/*							*/
X/*	Portions copyright (c) 1989 by Ted A. Campbell	*/
X/*		Bywater Software			*/
X/*		P. O. Box 4023				*/
X/*		Duke Station				*/
X/*		Durham, NC  27706			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.60	*/
X/*      (c) 1983, 4 by Ernest E. Bergmann               */
X/*		Physics, Building #16			*/
X/*		Lehigh University			*/
X/*		Bethlehem, Pa. 18015			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.61	*/
X/*      (c) 1985 by Konrad Kwok                         */
X/*		20 3rd Street, Section M		*/
X/*		Fariview Park,				*/
X/*		Hong Kong				*/
X/*							*/
X/*	ro and its predecessor ROFF4 are based on 	*/
X/*	the ROFF text processor described in Kernigan	*/
X/*	and Plauger's now-classic text <Software Tools> */
X/*							*/
X/* Permission is hereby granted for all commercial and	*/
X/* non-commercial reproduction and distribution of this */
X/* material provided this notice is included.		*/
X/*							*/
X/********************************************************/
X
X/************* INCLUDE FILES ****************************/
X
X#include "stdio.h"
X#include "ctype.h"
X#include "time.h"
X
X#ifdef __STDC__
X#include "stdlib.h"
X#include "malloc.h"
X#else
X#define size_t  int
X#define time_t  long
X#endif
X
X/****** PROGRAM DEFINITIONS *****************************/
X
X/***	User-Definable Options ***/
X
X#define NONROFF			/* allow non-nroff-standard features */
X
X/***	End of User-Definable Options ***/
X
X#define	ro_	X		/* shorten names for limited compilers */
X
X#define MAXLINE 255
X#define TRUE 1
X#define FALSE 0
X#define ERROR (-1)
X#define OK 0
X
X#define	TBUFSIZE	4096	/* Size of temporary holding buffer */
X#define BACKSIZE        4096    /* Size of backup buffer */
X#define STKSIZ          4
X#define DEBUG           ( debug != 0 )
X#define HUGE            135     /* generally large number */
X#define LSZ             511     /* line buffer size*/
X#define COMMAND         '.'     /* all commands starts with this */
X
X#define UNKNOWN         -1      /* returned if doesn't recg. command */
X#define NO_VAL          -32760  /* returned when no argument w/commad */
X#define WE_HAVE_A_WORD   1       /* returned by getwrd func. */
X#define NO              0
X#define YES             1
X#define UNDERLINE       '\137'
X
X/***	Character Definitions */
X
X#define CR              0x0D
X#define BACKSPACE       '\b'
X#define BELL    	'\007'
X#define NUMSIGN         '#'     /* for title strings */
X#define NEWLINE         '\n'
X#define TAB             '\t'
X#define BLANK           ' '
X#define FORMF           0x0C    /* formfeed for printer */
X#define	ESCAPE		0x1b	/* escape character */
X#define SQUOTE          0x27    /* single quote */
X#define DQUOTE          0x22    /* double quote */
X#define	BACKSLASH	0x5c	/* backslash */
X#define	PASSBACK	0xeee	/* a random large number to pass a literal 
X				   backslash back into the input stream */
X
X/**	Single-character printer code designations ***/
X
X#define	ROMAN		'R'	/* Restore "roman" or "regular" font */
X				/* Should turn off Bold and Italic */
X#define	ITALIC		'I'	/* Switch to italics or underline */
X#define	BOLD		'B'	/* Switch to bold */
X#define	HALFUP		'u'	/* Half-line up */
X#define	HALFDOWN	'd'	/* Half-line down */
X
X#define TRANSLATE 	2     /* May 23, 1983*/
X#define BLACK 		1
X#define WHITE 		0
X#define CONTROL 	-1
X#define SENTINEL 	-2
X#define HTAB    	-3
X#define OTHERS 		-4
X#define XCHAR 		'-'
X#define UCHAR 		'_'
X
X/* defaults for global parameters */
X
X#define FI_DEF          1
X#define LS_DEF          1
X#define IN_DEF          0
X#define RM_DEF          70
X#define TI_DEF          0
X#define CE_DEF          1
X#define UL_DEF          -1
X#define M1_DEF          2
X#define M2_DEF          2
X#define M3_DEF          2
X#define M4_DEF          2
X#define PL_DEF          66
X#define FF_DEF          YES     /* .ff defaults to "on" */
X#define FF_INI          NO      /* initial setting*/
X#define SC_INI          BLANK
X#define TS_DEF          8       /*standard tabsize*/
X#define TC_DEF          '~'     /*translation flag default*/
X#define CF_DEF          '^'     /*Dec 4*/
X#define IC_DEF          '\\'
X#define CW_DEF          12      /* 12/120" */
X#define JU_INI          YES     /* right adjust (justification) */
X#define	PO_DEF		0	/* page offset */
X#define REGDEF          0       /*default for register var.*/
X                                /*when .rg has no numeric arg*/
X
X#define REVSCROLL       FALSE
X#define CANBS           FALSE
X
X#define FMAX            8       /* # of additional files open*/
X
X/* defaults for global parameters */
X
X#define FI_DEF          1
X#define LS_DEF          1
X#define IN_DEF          0
X#define RM_DEF          70
X#define TI_DEF          0
X#define CE_DEF          1
X#define UL_DEF          -1
X#define M1_DEF          2
X#define M2_DEF          2
X#define M3_DEF          2
X#define M4_DEF          2
X#define PL_DEF          66
X#define FF_DEF          YES     /* .ff defaults to "on" */
X#define FF_INI          NO      /* initial setting*/
X#define SC_INI          BLANK
X#define TS_DEF          8       /*standard tabsize*/
X#define TC_DEF          '~'     /*translation flag default*/
X#define CF_DEF          '^'     /*Dec 4*/
X#define IC_DEF          '\\'
X#define CW_DEF          12      /* 12/120" */
X#define JU_INI          YES     /*right justification*/
X#define REGDEF          0       /*default for register var.*/
X                                /*when .rg has no numeric arg*/
X
X#define REVSCROLL       FALSE
X#define CANBS           FALSE
X
X#define FMAX            8       /* # of additional files open*/
X
X#define FI              1       /* fill lines */
X#define TI              2       /* temporary indent */
X#define BP              3       /* begin page  */
X#define BR              4       /* causes break */
X#define CE              5       /* center line(s) */
X#define IN              7       /* left indent */
X#define LS              8       /* line spacing */
X#define NF              9       /* no fill */
X#define PL              10      /* set page length */
X#define LL              11      /* set line length (right margin) */
X#define SP              12      /* add blank line(s) */
X#define ST              13      /* stop(pause) at page start?*/
X#define FO              14      /* footer title */
X#define HE              15      /* header title */
X#define M1              16      /* top margin */
X#define M2              17      /* second top margin */
X#define M3              18      /* first bottom margin */
X#define M4              19      /* bottom-most margin       */
X#define IG              20      /* "ignore";comments,Nov 6,82*/
X#define NE              21      /* "need";Nov 7,82*/
X#define FF              22      /* "formfeed";Nov 10*/
X#define SC              23      /* "space character";Nov13*/
X#define TA              25      /* "tabsize";Nov 13*/
X#define EH              26      /* "even headers";Nov 14*/
X#define OH              27      /* "odd headers"*/
X#define EF              28      /* "even footers"*/
X#define OF              29      /* "odd footers"*/
X#define EX              30      /* exit ("abort") */
X#define DB              31      /* "debug"*/
X#define TC              32      /* "translation flag char"*/
X#define TR              33      /* "def translation string"*/
X#define CF              34      /* Dec 4:control flag char*/
X#define IC              35      /* insert character */
X#define AD              37      /* adjust (justify) output lines */
X#define NA              38      /* no adjust of output lines */
X#define WH              39      /* whole line spacing code */
X#define FR              40      /* fractional spacing,code */
X#define DS              41      /* define string*/
X#define DE              42      /* define macro*/
X#define EM              43      /* end macro*/
X#define NR              44      /* register variable*/
X#define DI              45      /* diversion*/
X#define SO              47      /* "source", include*/
X#define PC              48      /* printer control definition*/
X#define TM              49      /* send inline msg to terminal */
X#define BJ              50      /* break with right justification
X                                   of current line */
X#define	PM		51	/* print macro names */
X#define	FT		52	/* set font */
X#define	PO		53	/* page offset */
X#define SS              54      /* show strings */
X#define SR              55      /* show registers */
X
X/****** GLOBAL VARIABLES ********************************/
X
XFILE 	*_dobuf, *instream;	/* i/o buffer used for direction  */
Xint 	debug;			/* Boolean:  debug mode on/off */
Xint	ro_verbose;		/* Boolean:  verbose mode on/off */
Xint 	ro_pagestop;
Xint 	ro_adjust;
Xint 	ro_useff;
Xint 	ro_firstpage, ro_lastpage;	/* for selectively printing output*/
Xint 	ro_suppress;		/* if true,no output is passed by putchar()*/
Xint 	ro_tival;      /* temporary indent -> default  0 */
Xint 	ro_ceval;      /* set equal to number of lines to be centered  */
Xint 	ro_spval;      /* blank lines to be spaced down */
Xint 	ro_curpag;     /* current output page number; init = 0 */
Xint 	ro_newpag;     /* next output page number; init = 1 */
Xint 	ro_vlineno;    /* virtual (intended) line advances on page,
X                        see vadv()*/
Xint 	ro_vflineno;   /* + line fraction */
Xint 	ro_plineno;    /* printer's actual line advances on page,
X                        see padv()*/
Xint 	ro_pflineno;   /* + line fraction */
Xint 	ro_bottom;     /* end of text area in lines;start of M3+M4 */
Xint 	ro_sentence;   /* Nov 20*/
Xint	ro_poval;	/* page offset */
X
X/***	Stack variables
X
X	The following variables are assigned to a stack and when 
X	a new value is assigned, it is "pushed" onto the stack, 
X	and when read, "popped" off.  The stack is read from 
X	the bottom.  						***/
X
Xint 	ro_fill[STKSIZ];       /* set to YES or NO  */
Xint 	ro_lsval[STKSIZ];      /* line spacing value -> default will be 1  */
Xint 	ro_inval[STKSIZ];      /* left indent -> default  0  */
Xint 	ro_rmval[STKSIZ];      /* right margin -> default  PAGEWIDTH  */
Xint 	ro_tcval[STKSIZ];      /* translation flag char  */
Xint 	ro_plval[STKSIZ];      /* page length in lines  */
Xint 	ro_m1val[STKSIZ];      /* margin before& including header in lines */
Xint 	ro_m2val[STKSIZ];      /* margin after header in lines */
Xint 	ro_m3val[STKSIZ];      /* margin after last text line in lines */
Xint 	ro_m4val[STKSIZ];      /* bottom margin, including footer in lines */
Xint 	ro_scval[STKSIZ];      /* space character  */
Xint 	ro_tabsiz[STKSIZ];     /* spacing of tabstops  */
Xint 	ro_cfval[STKSIZ];      /* Dec 4:control flag character value  */
Xint 	ro_icval[STKSIZ];      /* insert character */
X
Xchar 	ro_curline[ LSZ ];       /*input line buffer, Nov 26 */
Xchar 	ro_ehead[ LSZ ], ro_eh2[ LSZ ], ro_eh3[ LSZ ];    /* even header title  */
Xchar 	ro_ohead[ LSZ ], ro_oh2[ LSZ ], ro_oh3[ LSZ ];    /* odd header title  */
Xchar 	ro_efoot[ LSZ ], ro_ef2[ LSZ ], ro_ef3[ LSZ ];    /* even footer title  */
Xchar 	ro_ofoot[ LSZ ], ro_of2[ LSZ ], ro_of3[ LSZ ];    /* even footer title  */
X
Xstruct divfd		/* diversion file descriptor	 */
X	{
X	char nm[ 36 ];	/* name  */
X	char fn[ 64 ];	/* name of diversion file (not source file) */
X        int cs;		/* character count  */
X        int ls;		/* line count  */
X	int val;	/* value for register  */
X	char *mstr;	/* pointer to macro character string  */
X	FILE *bf;	/* to instream if open, FALSE otherwise  */
X	struct divfd *prev;
X	};
X
Xchar 	tbuf[ TBUFSIZE ];	/* a temporary buffer */
Xint 	ro_dir;        /* for "spreading" of lines     */
Xint 	ro_outwrds;    /* no. words in ro_outbuf; init = 0  */
Xchar 	ro_outbuf[ LSZ ];     /*lines to be filled collected here  */
Xint 	ro_outw;       /*current display width of ro_outbuf */
Xint 	ro_outpos;     /* =strlen(ro_outbuf)  */
Xint 	ro_wtop, ro_ltop, ro_outtop;   /*zero|negative;levels of subscripts */
Xint 	ro_wbot, ro_lbot, ro_outbot;   /*zero|positive;levels of subscripts */
Xint 	ro_oldln;              /*position of previous main line */
Xint 	ro_oldbot;             /*ro_outbot for previous line;reset
X                        each page */
Xint 	ro_frq, ro_frval;  /* fractional line?, what fraction size */
Xchar 	*ro_frstring; /* ^ to code for fractional spacing */
Xchar 	*ro_whstring; /* ^ to code for whole line spacing */
Xchar 	*ro_cptr[128-' '];    /*pointer table for print control */
Xchar 	*ro_tptr[128-' '];    /*pointer table for translation strings
X                          for char; initialize to null  */
X
Xstruct 	divfd *dlink;	/* points to head of diversion list  */
Xstruct 	divfd *rlink;	/* points to head of register variable list  */
Xstruct 	divfd *slink;	/* points to head of linked string list  */
Xstruct 	divfd *mlink;	/* points to head of linked macro list  */
X
X/*following added for buffered and formatted output:   */
X
Xchar 	ro_out2buf[LSZ];      /*for line to be output in fancy fmt */
Xint 	ro_bpos, ro_cp, ro_pp;         /*buffer,column,printer positions */
Xchar 	ro_xbuf[LSZ];         /*strikout buffer */
Xint 	ro_xf, ro_xcol;            /* " flag and column  */
Xchar 	ro_ubuf[LSZ];         /*underline buffer */
Xint 	ro_uf, ro_ucol;            /* " flag and column  */
Xint 	ro_first;              /*flag for first pass */
Xchar 	ro_dbuf[LSZ];         /*double strike buffer */
Xint 	ro_dpos;
Xint 	ro_ocnt;
Xint 	ro_mcnt;
Xint 	ro_blkcnt;
X
Xint 	ro_newxf, ro_newuf, ro_newmcnt; /* 3rd Mar,85 ; Conrad Kwok  */
Xchar 	ro_lastch;    /* 5th Mar,85  ;  Conrad Kwok  */
X
Xchar 	ro_backbuf[BACKSIZE];                 /* Backup buffer  */
Xint 	ro_binp;                               /* Position in above;init to 0  */
Xchar 	ro_keybd;             /*boolean & prompt for keyboard input */
Xchar 	ro_kline[MAXLINE];    /*keyboard line input buffer */
Xchar 	*ro_kptr;             /*pointer for above */
X
Xint     	ro_fptr;
XFILE 	*ro_fstack[FMAX];
Xint	ro_tflag;/*added for start(), complete() */
Xint 	ro_xf2, ro_uf2, ro_mcnt2;
X
X/****** DECLARATIONS FOR EXTERNAL FUNCTIONS ************ */
X
X/*      Declarations of externals
X *
X *
X */
X
X#ifndef __STDC__
Xextern  char *malloc();
X#endif
Xextern  char *macq();
Xextern 	struct divfd * find2();
Xextern  char ro_getch();
X
X/******** END OF FILE ***********************************/
X
X
________This_Is_The_END________
if test `wc -l < ro.h` -ne 365; then
	echo 'shar: ro.h was damaged during transit (should have been 365 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ro.c'
if test -f ro.c; then echo 'shar: not overwriting ro.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ro.c
X/********************************************************/
X/*							*/
X/*	ro.c		main program file for ro	*/
X/*							*/
X/*	ro version 1.00					*/
X/*							*/
X/*	Portions copyright (c) 1989 by Ted A. Campbell	*/
X/*		Bywater Software			*/
X/*		P. O. Box 4023				*/
X/*		Duke Station				*/
X/*		Durham, NC  27706			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.60	*/
X/*      (c) 1983, 4 by Ernest E. Bergmann               */
X/*		Physics, Building #16			*/
X/*		Lehigh University			*/
X/*		Bethlehem, Pa. 18015			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.61	*/
X/*      (c) 1985 by Konrad Kwok                         */
X/*		20 3rd Street, Section M		*/
X/*		Fariview Park,				*/
X/*		Hong Kong				*/
X/*							*/
X/*	ro and its predecessor ROFF4 are based on 	*/
X/*	the ROFF text processor described in Kernigan	*/
X/*	and Plauger's now-classic text <Software Tools> */
X/*							*/
X/* Permission is hereby granted for all commercial and	*/
X/* non-commercial reproduction and distribution of this */
X/* material provided this notice is included.		*/
X/*							*/
X/********************************************************/
X
X#include "ro.h"
X
Xextern  char *ro_gets();
X
Xint ro_iline = 0;
Xint ro_deno = 0;
X
X/*****************MAIN************MAIN*********/
X
Xmain( argc, argv )
X	int argc;
X	char **argv;
X	{
X	register int n;
X	int fs;
X	char option, *pc;
X	char filename[20];
X	struct divfd *pd;
X
X	ro_lastch = NULL;
X	debug = FALSE;
X	ro_verbose = FALSE;
X
X	init_defaults();
X
X	/***    First process any flags         ***/
X
X	for ( n = 1; n < argc; ++n )
X		{ 
X		strcpy( filename, argv[ n ] );
X
X		if ( filename[0] == '-' )
X			{
X			option = filename[1];
X			if      ( option == 's' ) ro_pagestop = TRUE;
X			else if ( option == 'o' ) range( &filename[2] );
X			else if ( option == 'f' ) ro_useff = TRUE;
X			else if ( option == 'x' ) 
X				{
X				debug = TRUE;
X				ro_verbose = TRUE;
X				}
X			else if ( option == 'v' ) ro_verbose = TRUE;
X			continue;
X			}
X		}
X
X	if ( ro_verbose == TRUE )
X		{
X		fprintf( stderr, "ro, version 1.00 \n" );
X		}
X
X	if DEBUG
X		{
X		fprintf( stderr, "DEBUG:  initial .ls setting is %d. \n",
X			ro_lsval[0] );
X		}
X
X	/* Now process all files named */
X
X	fs = 0;
X
X	for ( n = 1; n < argc; ++n )
X		{ 
X		strcpy( filename, argv[ n ] );
X		if ( filename[0] != '-' )
X			{
X
X			if( pd = find2( filename, dlink ))
X				{
X				dclose( pd );
X				}
X
X			if (( instream = fopen( filename, "r" )) == NULL )
X				{
X				fprintf( stderr, "Can't open <%s> for input.\n", filename );
X 				}
X			else
X				{
X				++fs;		/* inc. number of files */
X				if ( ro_verbose == TRUE )
X					{
X					fprintf( stderr, "Processing <%s>\n", filename );
X					}
X				dolns();
X				}
X			}
X		}
X
X	/* No files opened; take input from stdin */
X
X	if ( fs == 0 )
X		{
X		if ( ro_verbose && ro_pagestop )
X			{
X			fprintf( stderr, "ERROR:  one cannot use -s (page stop) with standard input. \n" );
X			}
X		ro_pagestop = FALSE;	/* Cannot use page stop if stdin */
X		instream = stdin;
X		dolns();
X		}
X
X	ro_brk();
X	ro_vlineno = ro_plval[ 0 ];
X	padv();
X	if ( ro_useff ) putchar( FORMF );
X	dsclose();                      /* Close all diversions */
X	}				/* end main()		 */
X
X/****************************************/
X/* do processing of lines 		*/
X/****************************************/
X
Xdolns() 
X	{
X	char *pc;
X	struct divfd *sptr;
X	static char name[ 12 ];
X	ro_binp = 0;
X
X	while ( !feof( instream ) | ro_fptr | ro_binp )
X		{
X		ro_gets( ro_curline );
X		++ro_iline;
X
X		if DEBUG
X			{
X			fprintf( stderr, "DEBUG:  input line # %d <%s> \n",
X				ro_iline, ro_curline );
X			fprintf( stderr, "DEBUG:  ro_curline[0] is <%c> (0x%x)\n", 
X				ro_curline[0], ro_curline[0] );
X			}
X
X		if ( ro_curline[ 0 ] == COMMAND )
X			{
X			name[ 0 ] = ro_curline[ 1 ];
X			if ( class( ro_curline[ 2 ] ) == BLACK )
X				{
X				name[ 1 ] = ro_curline[ 2 ];
X				name[ 2 ] = '\0';
X				}
X			else
X				{
X				name[ 1 ] = '\0';
X				}
X			if ( ( pc = macq( ro_curline )) != NULL )
X				{
X				pbmac( pc, ro_curline );
X				}
X			else if ( ( sptr = find2( name, dlink )) != NULL )
X				{
X				read_div( sptr );
X				}
X			else
X				{
X				command( ro_curline );
X				}
X			}
X		else
X			{
X			text( ro_curline );
X			}
X		if ( feof( instream) )
X			{
X			endso();
X			}
X		}
X	}
X
Xchar *
Xro_gets( line )
X	char *line;
X	{
X	char *l;
X
X	l = line;
X	do
X		{
X		*l = ro_getch();
X		++l;
X		}
X	while( *(l - 1) != '\n' );
X
X	*( l - 1 ) = '\0';
X
X	if DEBUG
X		{
X		fprintf( stderr, "DEBUG:  ro_gets() <%s> \n", line );
X		}
X
X	return line;
X	}
X
Xchar
Xro_getch()
X	{
X	register int c;
X	static int bflag = FALSE;	/* was last character BACKSLASH? */
X
X	while ( TRUE )
X		{
X		if ( ro_binp == 0 )
X			{
X			if ( feof( instream ))
X				{
X				return '\n';
X				}
X			c = fgetc( instream );
X			}
X		else
X			{
X			c = ro_backbuf[ ro_binp-- ];
X			}
X		switch ( c )
X			{
X			case EOF:
X				bflag = FALSE;
X				return '\n';
X				break;
X			case '\r':
X				bflag = FALSE;
X				break;
X			case BACKSLASH:
X				if ( !bflag )
X					{
X					bflag = TRUE;
X					if ( ro_expand() == PASSBACK )
X						{
X						return BACKSLASH;
X						}
X					else
X						{
X						return ro_getch();
X						}
X					}
X				else
X					{
X					bflag = FALSE;
X					return c;
X					}
X				break;
X			default:
X				bflag = FALSE;
X				return c;
X				break;
X			}
X		}
X	}
X
X/**************************************************************
Xinitializes the global variables governing the execution of the
X format commands.
X**************************************************************/
X
Xinit_defaults()
X	{
X	static time_t now;
X	struct tm *ltime;
X
X	initsk( ro_fill,  FI_DEF);	/* yes we want filled lines */
X	initsk( ro_lsval, LS_DEF);	/* line spacing = 1 */
X	initsk( ro_inval, IN_DEF);	/* left margin indent	0 */
X	initsk( ro_rmval, RM_DEF);	/* right margin = page width	*/
X	initsk( ro_tcval, TC_DEF);
X	initsk( ro_plval, PL_DEF);
X	initsk( ro_m1val, M1_DEF);
X	initsk( ro_m2val, M2_DEF);
X	initsk( ro_m3val, M3_DEF);
X	initsk( ro_m4val, M4_DEF);
X	initsk( ro_scval, SC_INI);
X	initsk( ro_tabsiz, TS_DEF);
X	initsk( ro_cfval, CF_DEF);
X	initsk( ro_icval, IC_DEF);
X
X	ro_tival = IN_DEF; 	/* left margin temporary indent	0 */
X	ro_ceval = 0;		/* next n lines to be centered - 0 */
X	ro_pagestop = FALSE;
X	ro_useff = FF_INI;
X	ro_firstpage = 1;
X	ro_lastpage = 30000;	/*infinite*/
X	ro_adjust = JU_INI;
X	ro_poval = PO_DEF;
X
X	ro_curpag = 0;
X	ro_newpag = 1;
X	ro_frq = 0;
X	ro_frstring = ro_whstring = NULL;
X	ro_frval = 1;
X	ro_vflineno = ro_pflineno = ro_plineno = 0;
X	ro_vlineno = -1;
X	ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
X	ro_outw = ro_outpos = ro_outtop = ro_outbot = ro_oldln = ro_oldbot = ro_outwrds = 0;
X	ro_outbuf [0] = '\0';
X	ro_dir = 0;
X	ro_eh2[0] = ro_eh3[0] = ro_ehead[0] = '\0';
X	ro_oh2[0] = ro_oh3[0] = ro_ohead[0] = '\0';
X	ro_ef2[0] = ro_ef3[0] = ro_efoot[0] = '\0';
X	ro_of2[0] = ro_of3[0] = ro_ofoot[0] = '\0';
X	memfill( ro_cptr, 2*(128-' '), 0);
X	memfill( ro_tptr, 2*(128-' '), 0);
X
X	ro_out2buf[ 0 ] = ro_bpos = 0;
X	initxu();		/* Initialize overstrike and other variables */
X	ro_mcnt=1;
X	ro_uf = ro_xf = FALSE;
X	memfill( ro_dbuf, LSZ, FALSE);
X	ro_dpos = -1;
X	ro_fptr = 0;			 
X	mlink = dlink = rlink = slink = NULL;
X	ro_kptr = ro_kline;
X	*ro_kline=0;
X	ro_keybd=FALSE;
X
X	/***	now set up some pre-defined registers ***/ 
X
X	time( &now );
X	ltime = localtime( &now );
X	preregister( "dy", ltime->tm_mday );
X	preregister( "mo", ltime->tm_mon );
X	preregister( "yr", ltime->tm_year );
X	preregister( "%", ro_curpag );
X	}
X
X/**************************************************************
Xperforms the formatting command returned by comtyp -sets global
X	variables ( indenting, underlining, etc. )
X**************************************************************/
X
Xcommand( line )
X	char *line;
X	{
X	int c_type;	/* command type	*/
X	int arg_val;	/* argument value, if any */
X	static int arg_typ;    /* relative (+ or -) or absolute */
X	char wbuf[20], *l;
X	register int i;
X
X	c_type = comtyp (line);
X
X	if DEBUG
X		{
X		fprintf( stderr, "DEBUG:  command is %d \n", c_type );
X		}
X
X	if ( c_type == UNKNOWN )
X		{
X		if ( ro_verbose )
X			fprintf( stderr, "%s: unknown command \n", line);
X		return;
X		}
X	arg_val = get_val( line, &arg_typ );
X
X	if DEBUG
X		{
X		fprintf( stderr, "DEBUG:  get_val returned arg_val = %d, arg_typ = %c\n",
X			arg_val, arg_typ );
X		fprintf( stderr, "DEBUG:  c_type is now %d \n", c_type );
X		}
X
X	switch ( c_type )
X		{
X		case EM :
X		case IG : 
X			break;		/* ignore remark */
X
X		case FI :	 	/* filled lines	*/
X			ro_brk();
X			ro_fill[0] = YES;
X			break;
X
X		case NF:               /* non-filled lines */
X			ro_brk();
X			ro_fill[0] = NO;
X			break;
X
X		case AD :	 	/* adjusted (justified) lines	*/
X			ro_adjust = TRUE;
X			break;
X
X		case NA :		/* non-adjusted lines 	*/
X			ro_adjust = FALSE;
X			break;
X
X		case BR :	 	/* just cause a break */
X			ro_brk();
X			break;
X
X		case LS :	 	/* set line spacing value */
X			setS( ro_lsval, arg_val, arg_typ, LS_DEF, 1, HUGE );
X			break;
X
X		case TI :	 	/* set temporary left indent */
X			ro_brk();
X			set( &ro_tival, arg_val, arg_typ, TI_DEF, 0, ro_rmval );
X			break;
X
X		case IN :	 	/* set left indent */
X			setS( ro_inval, arg_val, arg_typ, IN_DEF, 0, ro_rmval-1 );
X			ro_tival = ro_inval[0];
X			break;
X
X		case LL :		/* set line length (right margin) */
X			setS( ro_rmval, arg_val, arg_typ, RM_DEF, ro_tival+1, 256 );
X			break;
X
X		case CE :	 /* center next arg_val lines */
X			ro_brk();
X			set( &ro_ceval, arg_val, arg_typ, CE_DEF, 0, HUGE);
X			break;
X
X		case SP :	 /* space down arg_val blank lines */
X			set( &ro_spval, arg_val, arg_typ, 1, 0, HUGE);
X			do_space ( ro_spval );
X			break;
X
X		case BP :	 /* set pageno arg_val - begin page */
X			ro_brk();
X			if(((ro_vlineno<=0)||(ro_vlineno>=ro_bottom))&&
X				(arg_val==NO_VAL)) 
X				{
X				break;
X				}
X			if ( ro_vlineno > 0 )
X				{
X				do_space (HUGE);
X				}
X			set( &ro_curpag, arg_val, arg_typ, ro_curpag+1, 0, 9999);
X			ro_newpag = ro_curpag;
X			break;
X
X		case NE :	 /*"need"*/
X			if ( arg_val == NO_VAL ) 
X				{
X				arg_val = 2;	/*default*/
X				}
X			need( arg_val );
X			break;
X
X		case PL :	 /* set page length */
X			setS( ro_plval, arg_val, arg_typ, PL_DEF,
X				ro_m1val[0]+ro_m2val[0]+ro_m3val[0]+ro_m4val[0]+1, HUGE);
X			ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
X			break;
X
X		case TA :	 /*tabsize*/
X			setS( ro_tabsiz, arg_val, '0', TS_DEF, 1, HUGE);
X			break;
X
X		case TC :	 /* tab character */
X			if ( arg_typ ) 
X				{
X				arg_val=arg_typ;
X				}
X			setS( ro_tcval, arg_val, '0', TC_DEF, BLANK+1, 127);
X			break;
X
X		case FT :	/* Set font */
X			switch( arg_typ )
X				{
X				case 'R':
X					putback( '\n' );
X					putback( ROMAN );
X					putback( ESCAPE );
X					break;
X				case 'I':
X					putback( '\n' );
X					putback( ITALIC );
X					putback( ESCAPE );
X					break;
X				case 'B':
X					putback( '\n' );
X					putback( BOLD );
X					putback( ESCAPE );
X					break;
X				default: 
X					if ( ro_verbose )
X						{
X						fprintf( stderr, 
X							"ft:  unrecognized font name \"%c\". \n", 
X							arg_typ );
X						}
X				}
X			break;
X
X		case TR :	 /*translation string defined here*/
X			gettr(); 
X			break;
X
X		case DS :	 /*define string*/
X			insert(); 
X			break;
X
X		case DE :	 /*define macro*/
X			++ro_deno;
X			if DEBUG
X				{
X				fprintf( stderr, "DEBUG:  .de number %d \n",
X					ro_deno );
X				}
X			minsert();
X			break;
X
X		case NR :        /*register variable*/
X			dovar(); 
X			break;
X
X		case DI :	 /*diversion to file*/
X			dodiv(); 
X			break;
X
X		case SO :	 /*source from file*/
X			source(); 
X			break;
X
X		case PM :	/* print macro definitions */
X			showm();
X			break;
X
X		case PO :	/* page offset */
X			set( &ro_poval, arg_val, arg_typ, 1, 0, HUGE );
X			break;
X
X		case TM :	 /* send message to terminal */
X			getwrd(ro_curline, wbuf);	/*skip command*/
X			skip_blanks(ro_curline);
X			trunc_bl(ro_curline);
X			fprintf( stderr, "<%s>\n", ro_curline);
X			break;
X
X#ifdef	NONROFF
X
X		case M1:		/* set topmost margin */
X			setS( ro_m1val, arg_val, arg_typ, M1_DEF, 0, HUGE);
X			break;
X
X		case M2:		/* set second top margin */
X			setS( ro_m2val, arg_val, arg_typ, M2_DEF, 0, HUGE);
X			break;
X
X		case M3:		/* set first bottom margin */
X			setS( ro_m3val, arg_val, arg_typ, M3_DEF, 0, HUGE);
X			ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
X			break;
X
X		case M4:		/* set bottom-most margin */
X			setS( ro_m4val, arg_val, arg_typ, M4_DEF, 0, HUGE);
X			ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
X			break;
X
X		case HE :	 /* get header title for pages */
X			gettl3 ( line, ro_ehead, ro_eh2, ro_eh3 );
X			gettl3 ( line, ro_ohead, ro_oh2, ro_oh3 );
X			break;
X
X		case OH :	 /*get odd header title*/
X			gettl3 ( line, ro_ohead, ro_oh2, ro_oh3 );
X			break;
X
X		case EH :	 /*get even header title*/
X			gettl3 ( line, ro_ehead, ro_eh2, ro_eh3 );
X			break;
X
X		case FO :	 /* get footer title for pages */
X			gettl3 ( line, ro_efoot, ro_ef2, ro_ef3 );
X			gettl3 ( line, ro_ofoot, ro_of2, ro_of3 );
X			break;
X
X		case OF :	 /* get odd page footer title*/
X			gettl3 ( line, ro_ofoot, ro_of2, ro_of3 );
X			break;
X
X		case EF :	 /* get even page footer title*/
X			gettl3 ( line, ro_efoot, ro_ef2, ro_ef3 );
X			break;
X
X		case ST :	 /* stop(pause) at each page?*/
X			set( &ro_pagestop, arg_val, '0', YES, NO, YES);
X			break;
X
X		case BJ :	 /*break with right justification*/
X			if(ro_fill)/*not applicable otherwise*/
X				{
X				spread(ro_outbuf,
X				ro_min(ro_rmval-ro_tival, MAXLINE-1)-ro_outw+1,
X				ro_outwrds);
X				ro_brk();
X				}
X			break;
X
X		case FF :	 /*formfeed*/
X			set( &ro_useff, arg_val, '0', FF_DEF, NO, YES);
X			break;
X
X		case SC :	 /*space character*/
X			if ( arg_typ ) 
X				{
X				arg_val=arg_typ;
X				}
X			setS( ro_scval, arg_val, '0', SC_INI, BLANK, 127);
X			break;
X
X		case EX :	 /* exit (abort) */
X			if ( ro_verbose )
X				fprintf( stderr, ".ex:  user abort.  \n");
X			exit(-1);		 /* tac */
X
X		case CF :	 /*translate character flag*/
X			if ( arg_typ ) 
X				{
X				arg_val=arg_typ;
X				}
X			setS( ro_cfval, arg_val, '0', CF_DEF, BLANK+1, 127);
X			break;
X
X		case IC :	 /* insert character for macro replace */
X			if ( arg_typ ) 
X				{
X				arg_val = arg_typ;
X				}
X			setS( ro_icval, arg_val, '0', IC_DEF, BLANK+1, 127 );
X			break;
X
X		case SR :       /* print register definitions */
X			showr();
X			break;
X
X		case SS :       /* print string definitions */
X			showit();
X			break;
X
X		case DB :	 /* debug */
X			set( &debug, arg_val, '0', NO, NO, YES);
X			if DEBUG 
X				{
X				fprintf( stderr, "Debug on...\n");
X				}
X			else 
X				{
X				fprintf( stderr, "...end of debug. \n");
X				}
X			break;
X#endif
X
X		default :
X			if ( ro_verbose )
X				{
X				fprintf( stderr, "Command %d not found.\n", c_type );
X				fprintf( stderr, "        line: <%s> \n", line );
X				}
X			break;
X		}
X	}
X
Xrange( s )
X	char *s;
X	{ 
X	int num;
X	num=0;
X	while(isdigit(*s)) num=num*10+(*(s++)-'0');
X	if(num) ro_firstpage=num;
X	if(*s=='-')
X		{
X		s++; 
X		num=0;
X		while(isdigit(*s)) num=num*10+(*(s++)-'0');
X		if(num) ro_lastpage=num;
X		}
X	else	ro_lastpage = ro_firstpage;
X	}
X
Xro_min( n1, n2 )
X	int n1, n2;
X	{
X	if ( n1 > n2 )
X		{
X		return n2;
X		}
X	else
X		{
X		return n1;
X		}
X	}
X
Xro_max( n1, n2 )
X	int n1, n2;
X	{
X	if ( n1 < n2 )
X		{
X		return n2;
X		}
X	else
X		{
X		return n1;
X		}
X	}
X
Xmemfill( b, n, c )
X	char *b;
X	int n;
X	char c;
X	{
X	register int x;
X	char *y;
X
X	y = b;
X	for ( x = 0; x < n; ++x )
X		{
X		*y = c;
X		}
X	}
X
________This_Is_The_END________
if test `wc -l < ro.c` -ne 745; then
	echo 'shar: ro.c was damaged during transit (should have been 745 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ro_proc.c'
if test -f ro_proc.c; then echo 'shar: not overwriting ro_proc.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ro_proc.c
X/********************************************************/
X/*							*/
X/*	ro_proc.c	various procedures for ro	*/
X/*							*/
X/*	ro version 1.00					*/
X/*							*/
X/*	Portions copyright (c) 1989 by Ted A. Campbell	*/
X/*		Bywater Software			*/
X/*		P. O. Box 4023				*/
X/*		Duke Station				*/
X/*		Durham, NC	27706			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.60	*/
X/*	(c) 1983, 4 by Ernest E. Bergmann		*/
X/*		Physics, Building #16			*/
X/*		Lehigh University			*/
X/*		Bethlehem, Pa. 18015			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.61	*/
X/*	(c) 1985 by Konrad Kwok				*/
X/*		20 3rd Street, Section M		*/
X/*		Fariview Park,				*/
X/*		Hong Kong				*/
X/*							*/
X/*	ro and its predecessor ROFF4 are based on 	*/
X/*	the ROFF text processor described in Kernigan	*/
X/*	and Plauger's now-classic text <Software Tools> */
X/*							*/
X/* Permission is hereby granted for all commercial and	*/
X/* non-commercial reproduction and distribution of this */
X/* material provided this notice is included.		*/
X/*							*/
X/********************************************************/
X
X#include "ro.h"
X
X/**********************************************************
XRemoves white-space characters at start of string.
X***********************************************************/
X
Xskip_blanks ( string )
X	char *string;	 /* cursor to original string */
X	{
X	char *p;	 /* cursor to 'final' string */
X	for(p=string;*string==BLANK||*string==TAB||*string==NEWLINE;
X		string++);
X		while(*(p++) = *(string++));
X	}
X
X/*************************************************************/
X
Xint comtyp (line)
X	char *line;
X	{
X	char let1, let2;
X	let1 = line[1];
X	let2 = line[2];
X
X	if ( let1==COMMAND )		return( EM ); /* end macro or comment */
X	if ( let1=='f' && let2=='i')	return( FI ); /* fill		      */
X	if ( let1=='t' && let2=='i')	return( TI ); /* temp. left indent    */
X	if ( let1=='b' && let2=='p')	return( BP ); /* break, page #	      */
X	if ( let1=='b' && let2=='r')	return( BR ); /* break		      */
X	if ( let1=='c' && let2=='e')	return( CE ); /* center line(s)	      */
X	if ( let1=='i' && let2=='n')	return( IN ); /* left indent	      */
X	if ( let1=='l' && let2=='l')	return( LL ); /* right margin	      */
X	if ( let1=='l' && let2=='s')	return( LS ); /* line spacing	      */
X	if ( let1=='n' && let2=='f')	return( NF ); /* no fill	      */
X	if ( let1=='p' && let2=='l')	return( PL ); /* page length	      */
X	if ( let1=='s' && let2=='p')	return( SP ); /* output blank lines   */
X	if ( let1=='n' && let2=='e')	return( NE ); /* need vertical spaces */
X	if ( let1=='t' && let2=='a')	return( TA ); /* tab size	      */
X	if ( let1=='t' && let2=='c')	return( TC ); /* tab character	      */
X	if ( let1=='t' && let2=='r')	return( TR ); /* translate chars      */
X	if ( let1=='a' && let2=='d')	return( AD ); /* adjust output lines  */
X	if ( let1=='n' && let2=='a')	return( NA ); /* no adjust output     */
X	if ( let1=='e' && let2=='m')	return( EM ); /* end macro	      */
X	if ( let1=='d' && let2=='e')	return( DE ); /* define macro	      */
X	if ( let1=='d' && let2=='s')	return( DS ); /* define string	      */
X	if ( let1=='n' && let2=='r')	return( NR ); /* number register      */
X	if ( let1=='d' && let2=='i')	return( DI ); /* divert output	      */
X	if ( let1=='s' && let2=='o')	return( SO ); /* source from file     */
X	if ( let1=='p' && let2=='m')	return( PM ); /* print macros         */
X	if ( let1=='e' && let2=='x')	return( EX ); /* exit (abort)	      */
X	if ( let1=='i' && let2=='g')	return( IG ); /* ignore -- comment    */
X	if ( let1=='t' && let2=='m')	return( TM ); /* message to terminal  */
X	if ( let1=='f' && let2=='t')	return( FT ); /* set font	      */
X	if ( let1=='p' && let2=='o')	return( PO ); /* page offset 	      */
X
X#ifdef	NOTYET
X	if ( let1=='w' && let2=='h')	return( WH ); /* set trap 	      */
X#endif
X
X#ifdef	NONROFF
X	if ( let1=='F' && let2=='O')	return( FO ); /* footer for title     */
X	if ( let1=='H' && let2=='E')	return( HE ); /* header for title     */
X	if ( let1=='S' && let2=='T')	return( ST ); /* stop between pages   */
X	if ( let1=='F' && let2=='F')	return( FF ); /* form feed	      */
X	if ( let1=='S' && let2=='C')	return( SC ); /* space character      */
X	if ( let1=='O' && let2=='H')	return( OH ); /* odd-page header      */
X	if ( let1=='O' && let2=='F')	return( OF ); /* odd-page footer      */
X	if ( let1=='E' && let2=='H')	return( EH ); /* even-page header     */
X	if ( let1=='E' && let2=='F')	return( EF ); /* even-page footer     */
X	if ( let1=='C' && let2=='F')	return( CF ); /* trans. char. flag    */
X	if ( let1=='I' && let2=='C')	return( IC ); /* insert character     */
X	if ( let1=='B' && let2=='J')	return( BJ ); /* break, justified     */
X	if ( let1=='S' && let2=='S')    return( SS ); /* show strings */
X	if ( let1=='S' && let2=='R')    return( SR ); /* show registers    */
X	if ( let1=='M')
X		{ 
X		if (let2=='1')		return( M1 );
X		if (let2=='2')		return( M2 );
X		if (let2=='3')		return( M3 );
X		if (let2=='4')		return( M4 );
X		}
X	if ( let1=='D' && let2=='B')	return( DB ); /* debug on			 */
X#endif
X
X	return( UNKNOWN );			/* no match */
X	}
X
X/*************************************************************
Xgets the number ( if any ) associated with any command 
X*************************************************************/
X
Xget_val( line, typ )
X	char *line;
X	int *typ;
X	{
X	int i;
X	char local[ MAXLINE ];
X	strcpy (local, line);	 /* local copy */
X
X	/* skip over the command line */
X	for(i=1; local[i]!=' '&&local[i]!='\t'&&local[i]!='\n'
X		&&local[i]!=0; i++);
X
X	skip_blanks (&local[i]);		/* find the number */
X	*typ = local[i];		/* relative or absolute */
X	if ( *typ=='+' || *typ=='-' )
X		{
X		i++;
X		}
X	else if ( !isdigit( *typ ) )
X		{
X		return( NO_VAL );
X		}
X	return ( atoi( &local[i] ));
X	}
X
X/*************************************************************
X sets a non-stacked global parameter like ro_spval, ro_pagestop, etc.
X Also checks that the new value is within the range of that 
X parameter.	Assigns the default for that parameter if no value
X is specified.
X*************************************************************/
X
Xset( param, val, arg_typ, defval, minval, maxval )
X	int *param, val, defval, minval, maxval;
X	int arg_typ;
X	{
X	if ( val == NO_VAL ) 
X		{
X		*param = defval;	 /* defaulted */
X		}
X	else if (arg_typ == '+') 
X		{
X		*param += val;	/* relative + */
X		}
X	else if ( arg_typ == '-' ) 
X		{
X		*param -= val;	/* relative - */
X		}
X	else	
X		{
X		*param = val;			 /* absolute */
X		}
X	*param = ro_min (*param, maxval);
X	*param = ro_max (*param, minval);
X
X	if DEBUG fprintf( stderr,"DEBUG:  set() *param = %d\n", *param);
X	}
X
X/*************************************************************
X		end current filled line 
X**************************************************************/
X
Xro_brk()
X	{
X	int l;
X	if DEBUG 
X		{
X		fprintf( stderr,"DEBUG:  ro_brk(): ro_outbuf=<%s>\n", ro_outbuf);
X		}
X
X	if (ro_outpos)
X		{
X		put( ro_outbuf );
X		}
X	ro_outw = ro_outpos = ro_outtop = ro_outbot = ro_outwrds = 0;
X	ro_outbuf[0] = '\0';
X	}
X
X/**************************************************/
X
Xinitxu()		/*initialize underline,overstrike variables*/
X	{	 
X	ro_xcol = ro_ucol = -1;
X	memfill(ro_xbuf,LSZ,' ');
X	memfill(ro_ubuf,LSZ,' ');
X	}
X
X/****************************************/
X
Xneed(n) /*test for space before footer*/
X	int n;	/*whole lines*/
X	{
X	if (( ro_vlineno >= (ro_bottom-n) ) && ( ro_bottom >= ro_vlineno ) )
X		{
X		do_space( HUGE );
X		ro_newpag = ++ro_curpag;
X		}
X	}
X
________This_Is_The_END________
if test `wc -l < ro_proc.c` -ne 224; then
	echo 'shar: ro_proc.c was damaged during transit (should have been 224 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ro_macr.c'
if test -f ro_macr.c; then echo 'shar: not overwriting ro_macr.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ro_macr.c
X/********************************************************/
X/*							*/
X/*	ro_macr.c	macro and diversion routines	*/
X/*			for ro				*/
X/*							*/
X/*	ro version 1.00					*/
X/*							*/
X/*	Portions copyright (c) 1989 by Ted A. Campbell	*/
X/*		Bywater Software			*/
X/*		P. O. Box 4023				*/
X/*		Duke Station				*/
X/*		Durham, NC  27706			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.60	*/
X/*      (c) 1983, 4 by Ernest E. Bergmann               */
X/*		Physics, Building #16			*/
X/*		Lehigh University			*/
X/*		Bethlehem, Pa. 18015			*/
X/*							*/
X/*	Contains portions of ROFF4, Version 1.61	*/
X/*      (c) 1985 by Konrad Kwok                         */
X/*		20 3rd Street, Section M		*/
X/*		Fariview Park,				*/
X/*		Hong Kong				*/
X/*							*/
X/*	ro and its predecessor ROFF4 are based on 	*/
X/*	the ROFF text processor described in Kernigan	*/
X/*	and Plauger's now-classic text <Software Tools> */
X/*							*/
X/* Permission is hereby granted for all commercial and	*/
X/* non-commercial reproduction and distribution of this */
X/* material provided this notice is included.		*/
X/*							*/
X/********************************************************/
X
X#include "ro.h"
X
X/********************************************/
X/* insert()  -- process .ds command	    */
X/* takes a command line in ro_curline and adds its
Xentry to the table */
X
Xinsert()
X	{
X	static char name[ LSZ ];
X	register int n;
X	char c, *l;
X	struct divfd *sptr;
X
X	 /*pass over command*/
X
X	 l = ro_curline;
X	 for ( c = *l; c != ' ' && c != '\n' && c != '\t'; l++ )
X		{
X		c = *l;
X		}
X
X	 /*advance to first non-blank */
X
X	 for ( ; c == ' ' || c == '\t'; l++ )
X		{
X		c = *l;
X		}
X	 if ( c == '\n' )
X		{
X		if ( ro_verbose == TRUE )
X			{
X			fprintf( stderr, ".ds:  no arguments \n" );
X			}
X		return -1;
X		}
X
X	/* get the name of the macro into the buffer */
X
X	n = 0;
X	--l;
X	do
X		{
X		name[ n ] = *l;
X		++l;
X		++n;
X		}
X	while( *l != ' ' && *l != '\t' && *l != '\n' );
X	name[ n ] = '\0';		/* terminate name with \0 */
X
X	if ( strlen( name ) > 2 ) 
X		{
X		name[ 2 ] = '\0';
X		if ( ro_verbose == TRUE )
X			{
X			fprintf( stderr, ".ds:  string name over two characters, shortened to <%s>. \n", 
X				name );
X			}
X		}
X
X 	 /*advance to first non-blank */
X
X	 c = *l;
X	 for ( ; c == ' ' || c == '\t'; l++ )
X		{
X		c = *l;
X		}
X	 if ( c == '\n' )
X		{
X		if ( ro_verbose == TRUE )
X			{
X			fprintf( stderr, ".ds:  no string argument \n" );
X			}
X		return -1;
X		}
X
X	/* now get the string itself into the tbuf buffer */
X
X	if ( c == '\"' )
X		{
X		n = 0;
X		do
X			{
X			tbuf[ n ] = *l;
X			++l;
X			++n;
X			}
X		while( *l != c );
X		tbuf[ n ] = '\0';		/* terminate name with \0 */
X		}
X	else
X		{
X		n = 0;
X		do
X			{
X			tbuf[ n ] = *l;
X			++l;
X			++n;
X			}
X		while( *l != ' ' && *l != '\t' && *l != '\n' );
X		tbuf[ n ] = '\0';		/* terminate name with \0 */
X		}
X
X	/* see if it is already defined	  */
X
X	if( ( sptr = find2( name, slink )) != NULL )	
X		{
X		if ( ro_verbose == TRUE )
X			{
X			fprintf( stderr, "%cWarning: <%s> was defined to be <%s>\n",
X				BELL, name, sptr->mstr );
X			fprintf( stderr, "...now it is defined to be <%s>\n", tbuf );
X			}
X		}
X
X	else 
X		{
X		if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
X			{
X			fprintf( stderr, "Fatal error: cannot allocate memory for insertion structure.  \n" ); 
X			exit ( -1 );
X			}
X
X		/* allocation succeeded, set up links */
X
X		sptr->prev = slink;		/* save previous link	*/
X		slink = sptr;			/* reset link		*/
X		strcpy( sptr->nm, name );
X		sptr->mstr = NULL;
X		}
X
X	/* allocate memory for the new string if it is longer 
X	   than the current string */ 
X
X	if ( strlen( tbuf ) > strlen( sptr->mstr ) )
X		{
X		if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
X			{
X			fprintf( stderr, "Fatal error:  failed to allocate memory for string. \n" );
X			exit( -1 );
X			}
X		}
X
X	/* copy the string to the new memory */
X
X	strcpy( sptr->mstr, tbuf );
X
X	}
X
X/****************************************/
X
Xshowit()		/* displays the list of entries in the string
X			substitution table pointed to by HEAD. */
X	{
X	struct divfd *pw;
X	fprintf( stderr, "Strings defined:\n");
X	dashes();
X	pw = slink;
X	while( pw != NULL )
X		{
X		fprintf( stderr, "%s:\t<%s> \n", pw->nm, pw->mstr );
X		pw = pw->prev;
X		}
X	dashes();
X	}
X
X/****************************************/
X
Xputback( c )	/*cf K & P, p256*/
X	char c;
X	{
X	if ( ++ro_binp >= BACKSIZE )
X		{
X		fprintf( stderr, "Fatal error:  too many characters pushed back\n");
X		exit( -1 );
X		}
X	ro_backbuf[ ro_binp ] = c;
X	}
X
X/** add by Conrad Kwok. 9th Sept.,84 ****/
X
Xpbmac( s, sl )			/* s = pointer to macro text 	*/
X	char s[], sl[];		/* sl = current line 		*/
X	{
X	static char *parms[10], dupln[LSZ];
X	register int i;
X
X	strcpy( dupln, sl );		/* get a copy of the current line */
X	setparm( dupln, parms );
X	for ( i = strlen(s)-1; i >= 0; )
X		{
X		if ( isdigit( s[i] ))
X			{
X			if ( i > 0 && s[ i - 1 ] == '$' )
X				{ 
X				pbstr( parms[ s[i--] & 0x0f ]); 
X				--i;
X				}
X			else
X				{
X				putback( s[i--] );
X				}
X			}
X		else
X			{
X			putback( s[i--] );
X			}
X		}
X	}
X
Xsetparm( sl, parms)
X	char *sl, *parms[];
X	{ 
X	char a,c;
X	int nuparm;
X	for ( c = *sl; c != ' ' && c != '\n' && c != '\t'; )
X		{
X		c = *++sl;
X		}
X
X	while ( c == ' ' || c == '\t' )
X		{
X		c = *++sl;
X		}
X
X	for ( nuparm = 0; nuparm < 10; ) 
X		{
X		if (!(isalnum(c) || (c=='+') || (c=='-')))
X			{
X			sl++;
X			}
X		else
X			{
X			c = ' ';
X			}
X		parms[ nuparm++ ] = sl;
X
X		for ( a = *sl; a != c && a != '\n' && a != '\0'; )
X			{
X			if ( c == ' ' && a == '\t' ) 
X				{
X				break;
X				}
X
X			else 
X				{
X				a = *++sl;
X				}
X			}
X		*sl = '\0';
X		c = a;
X		if ( a != '\0' && a != '\n') 
X			{
X			while ( c == ' ' || c == '\t') 
X				{
X				c = *++sl;
X				}
X			}
X		}
X	}
X
X/****************************************/
X
Xpbstr( s )		/*put back string on input; cf K&P,p257*/
X	char s[LSZ];
X	{
X	int i;
X	for ( i = strlen(s); i > 0; ) 
X		{
X		putback( s[--i] );
X		}
X	}
X
Xro_expand()
X	{
X	char c, d, name[ 36 ];
X	register int n;
X	struct divfd *sptr;
X
X	c = ro_getch();
X	switch( c )
X		{
X		case BACKSLASH:
X			return PASSBACK;
X			break;
X		case '*':		/* expand defined string */
X			d = ro_getch();
X			if ( d == '(' )	/* two-letter name */
X				{
X				name[ 0 ] = ro_getch();
X				name[ 1 ] = ro_getch();
X				name[ 2 ] = '\0';
X				}
X			else		/* one-character name */
X				{
X				name[ 0 ] = d;
X				name[ 1 ] = '\0';
X				}
X			if ( ( sptr = find2( name, slink )) == NULL )
X				{
X				if ( ro_verbose == TRUE )
X					{
X					fprintf( stderr, "ro:  failed to find string name <%s> \n", 
X						name );
X					}
X				}
X			else
X				{
X				n = strlen( sptr->mstr ) - 1;
X				while( n >= 0 )
X					{
X					putback( sptr->mstr[ n ] );
X					--n;
X					}
X				}
X			break;
X		case 'n':		/* expand number register */
X			d = ro_getch();
X			if ( d == '(' )	/* two-letter name */
X				{
X				name[ 0 ] = ro_getch();
X				name[ 1 ] = ro_getch();
X				name[ 2 ] = '\0';
X				}
X			else		/* one-character name */
X				{
X				name[ 0 ] = d;
X				name[ 1 ] = '\0';
X				}
X			if ( ( sptr = find2( name, rlink )) == NULL )
X				{
X				if ( ro_verbose == TRUE )
X					{
X					fprintf( stderr, "ro:  failed to find register name <%s> \n", 
X						name );
X					}
X				}
X			else
X				{
X				sprintf( tbuf, "%d", sptr->val );
X				n = strlen( tbuf ) - 1;
X				while( n >= 0 )
X					{
X					putback( tbuf[ n ] );
X					--n;
X					}
X				}
X			break;
X		case 'u':		/* Half-line up */
X			putback( HALFUP );
X			putback( ESCAPE );
X			break;
X		case 'd':		/* Half-line down */
X			putback( HALFDOWN );
X			putback( ESCAPE );
X			break;
X		case 'f':		/* switch font */
X			d = ro_getch();
X			switch( d )
X				{
X				case 'R':
X					putback( ROMAN );
X					putback( ESCAPE );
X					break;
X				case 'I':
X					putback( ITALIC );
X					putback( ESCAPE );
X					break;
X				case 'B':
X					putback( BOLD );
X					putback( ESCAPE );
X					break;
X				default: 
X					if ( ro_verbose == TRUE )
X						{
X						fprintf( stderr, 
X							"ro:  unrecognized font name \"%c\" in input stream. \n", 
X							d );
X						}
X				}
X			break;
X		default:
X			putback( c );
X			break;
X		}
X	return TRUE;
X	}
X
X/****************************************/
X/* takes a .de and following lines and places
Xthe information in the table;	no macro
Xdefinition nesting permitted */
X
Xminsert()
X	{
X	register int n;
X	static char c, *src, *dst;
X	int keepon;
X	struct divfd *sptr;
X
X	if DEBUG
X		{
X		fprintf( stderr, "DEBUG:  enter minsert() \n" );
X		}
X
X	/* pass over command and following white space */
X
X	for ( src = ro_curline, c = *src; (c != ' ' ) && (c!='\n') && (c!='\t'); src++ )
X		{
X		c = *src;
X		}
X	for ( ; (c == ' ') || (c == '\t'); src++ ) 
X		{
X		c = *src;
X		}
X
X	/* Check to see if there is a name for the macro */
X
X	if ( ( c == '\n' ) || ( c == '\0' ))
X		{
X		if ( ro_verbose )
X			{
X			fprintf( stderr, "ERROR:  .de:  no name given. \n");
X			}
X		return -1;
X		}
X
X	/* Name detected, proceed to store the name */
X
X	else
X		{
X		if DEBUG
X			{
X			fprintf( stderr, "DEBUG:  macro name found; prepare to allocate memory. \n" );
X			}
X
X		if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
X			{
X			fprintf( stderr, "FATAL ERROR: cannot allocate memory for macro definition structure.  \n" );
X			exit ( -1 );
X			}
X
X		if DEBUG
X			{
X			fprintf( stderr, "DEBUG:  memory allocated for macro.\n" );
X			}
X
X		sptr->prev = mlink;             /* save previous link   */
X		mlink = sptr;			/* set mlink to this	*/
X		n = 0;
X		while( class( c ) == BLACK )	/* Store each character */
X			{			/* of the macro name    */
X			sptr->nm[ n++ ] = c;
X			c = *( src++ );
X			}
X		sptr->nm[ n ] = '\0';
X
X		if DEBUG
X			{
X			fprintf( stderr, "DEBUG:  new macro name is <%s> \n",
X				sptr->nm );
X			}
X
X		}
X
X	/* Now read from instream until end of macro or EOF */
X
X	dst = tbuf;
X	keepon = 1;
X	while( keepon == 1 )
X		{
X		ro_gets( ro_curline );
X		src = ro_curline;
X
X		/* Check for end of macro */
X
X		if (( ro_curline[0] == COMMAND) && ( comtyp( ro_curline ) == EM ))
X			{
X			keepon = 0;
X			}
X		else			/* Not end; transfer to buffer	*/
X			{
X			transfer( &src, &dst, (char) '\0' );
X			*(dst - 1) = '\n';	/* put a LF at the end 	*/
X			*dst = 0;		/* and a temp. delimiter */
X			}
X
X		if DEBUG
X			{
X			fprintf( stderr, "DEBUG:  minsert() current line <%s> \n", 
X				tbuf );
X			}
X
X		}
X	*( dst ) = '\0';                /* Terminate with \0            */
X
X	if DEBUG
X		{
X		fprintf( stderr, "DEBUG:  text of new macro is <%s> \n", tbuf );
X		}
X
X	/* allocate memory for this macro string and transfer the string to
X		the new location */ 
X
X	if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
X		{
X		fprintf( stderr, "Fatal error:  failed to allocate memory for macro string. \n" );
X		exit( -1 );
X		}
X	strcpy( sptr->mstr, tbuf );
X
X	}
X
X/****************************************/
X
Xshowm() /*lists macro definitions*/
X	{
X	struct divfd *pw;
X	char *pc;
X	fprintf( stderr, "MACROS DEFINED:\n");
X	pw = mlink;
X	while ( pw != NULL )
X		{
X		fprintf( stderr, "\t.%s\t<%s>\n", pw->nm, pw->mstr );
X		pw = pw->prev;
X		}
X	dashes();
X	}
X
X/****************************************/
X
Xchar *macq( line )              /*looks up name to see if it is a macro
X				definition.	If it is, returns the
X				corresponding string, else returns
X				FALSE.
X				*/
X	char *line;
X	{
X	char c, *pc, wb[ LSZ ];
X	struct divfd *pstr;
X
X	pc = wb;
X	while ( class( c = *( ++line )) == BLACK )
X		{
X		*( pc++ ) = c;
X		}
X	*pc='\0';
X
X	pstr = find2( wb, mlink );
X	if ( pstr == NULL )
X		{
X		return NULL;
X		}
X	else
X		{
X		return ( pstr->mstr );
X		}
X	}
X
X/****************************************/
X
Xstruct divfd *
Xfind2( s, link)	 	/* finds or doesn't find s in table
X			    of substitutions pointed to by link */
X	char *s;
X	struct divfd *link;
X	{
X	struct divfd *l;
X	char *pc;
X
X	l = link;
X	while ( l != NULL )
X		{
X		if ( !strcmp( s, l->nm ) )
X			{
X			return( l );    /* return structure pointer     */
X			}
X		l = l->prev;
X		}
X
X	return( NULL );				/* failed		*/
X	}
X
X/****************************************/
X
________This_Is_The_END________
if test `wc -l < ro_macr.c` -ne 620; then
	echo 'shar: ro_macr.c was damaged during transit (should have been 620 bytes)'
fi
fi		; : end of overwriting check
exit 0


-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list