gno/usr.bin/nroff/nroff.c

1006 lines
22 KiB
C

/*
* main.c - main for nroff word processor
*
* similar to Unix(tm) nroff or RSX-11M RNO. adaptation of text processor
* given in "Software Tools", Kernighan and Plauger.
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: nroff.c,v 1.3 1997/10/30 04:04:35 gdr Exp $
*/
#ifdef __ORCAC__
segment "main______";
#pragma optimize 79
#endif
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#ifdef __GNO__
#include <err.h>
#include <termcap.h>
#include <gno/gno.h>
#else
#include "unix/err.h"
#include "unix/termcap.h"
#endif
#ifdef sparc
#include <memory.h>
#include "unix/sunos.h"
#endif
#include "nroff.h"
#include "macros.h"
#include "io.h"
static void init (void);
static void processFile (void);
static int pswitch (char *p, int *q);
static void usage (void);
/*************************************************************************
*
* Global variables block. Keep them in main.c so that the IIgs'
* debuggers can find them.
*/
struct docctl dc;
struct page pg;
struct macros_t mac;
struct regs rg[MAXREGS];
FILE *out_stream;
FILE *err_stream;
FILE *dbg_stream;
FILE *sofile[Nfiles+1];
int ignoring; /* .ig vs .de */
int hold_screen;
int debugging;
int stepping; /* paging */
int mc_ing = 0; /* turned off */
int mc_space = 2;
char mc_char = '|';
char tmpdir[256];
char s_standout[20];
char e_standout[20];
char s_bold[20];
char e_bold[20];
char s_italic[20];
char e_italic[20];
char *dbgfile = "nroff.dbg";
#ifdef GEMDOS
char *printer = "prn:"; /* this WON'T work!!! */
#else
char *printer = ".ttyb"; /* this probably won't */
#endif
static char termcap[1024]; /* _must_ be 1024 */
static char *progname;
static char *version = "(GNO) v1.2, 5 Mar 97 gdr";
/*
* End of global variable definitions.
*
*************************************************************************/
#ifdef __STACK_CHECK__
static void
printStack (void) {
fprintf(stderr, "stack usage: %d bytes\n", _endStackCheck());
}
#endif
int
main (int argc, char *argv[]) {
register int i;
int swflg;
int ifp = 0;
char *ptmp;
char *pterm;
char capability[100];
char *pcap;
char *ps;
#ifdef __GNO__
#ifdef __STACK_CHECK__
_beginStackCheck();
atexit(printStack);
#endif
if (argc > 0) {
progname = __prognameGS();
} else {
exit(1); /* not running from a shell? */
}
#else
if (argc > 0) {
progname = basename(argv[0]);
} else {
progname = "nroff";
}
#endif
/*
* set up initial flags and file descriptors
*/
swflg = FALSE;
ignoring = FALSE;
hold_screen = FALSE;
debugging = FALSE;
stepping = FALSE;
mc_ing = FALSE;
out_stream = stdout;
err_stream = stderr;
dbg_stream = stderr;
/*
* this is for tmp files, if ever needed. it SHOULD start
* out without the trailing slash. if not in env, use default
*/
if ((ptmp = getenv ("TMPDIR")) != NULL) {
strcpy (tmpdir, ptmp);
} else {
strcpy (tmpdir, ".");
}
/*
* handle terminal for \fB, \fI
*/
s_standout[0] = '\0';
e_standout[0] = '\0';
s_bold[0] = '\0';
e_bold[0] = '\0';
s_italic[0] = '\0';
e_italic[0] = '\0';
/*
* get termcap information
*/
if ((pterm = getenv("TERM")) == NULL) {
errx(1, "TERM environment variable not set");
}
switch (tgetent(termcap, pterm)) {
case -1:
errx(1, "couldn't open termcap database");
/*NOTREACHED*/
case 0:
errx(1, "terminal type %s not found in termcap database", pterm);
/*NOTREACHED*/
}
/*
* we currently use standout mode for all weirdness
* like BOLD, italic, etc.
*/
pcap = capability;
if ((ps = tgetstr ("so", &pcap)) != NULL) {
/*
* sun has padding in here. this is NOT portable.
* better to use tputs() to strip it...
*/
/* while (*ps && *ps != 0x1b) ps++; */
strcpy (s_standout, ps);
strcpy (s_bold, ps);
strcpy (s_italic, ps);
} else {
err(1, "couldn't get standout mode");
/*NOTREACHED*/
}
if ((ps = tgetstr ("se", &pcap)) != NULL) {
/* while (*ps && *ps != 0x1b) ps++; */
strcpy (e_standout, ps);
strcpy (e_bold, ps);
strcpy (e_italic, ps);
}
/*
* initialize structures (defaults)
*/
init ();
/*
* parse cmdline flags
*/
for (i = 1; i < argc; ++i) {
if (*argv[i] == '-' || *argv[i] == '+') {
if (pswitch (argv[i], &swflg) == ERR) {
err_exit (-1);
}
}
}
/*
* loop on files
*/
for (i = 1; i < argc; ++i) {
if (*argv[i] != '-' && *argv[i] != '+') {
/*
* open this file...
*/
if ((sofile[0] = fopen (argv[i], "r")) == NULL_FPTR) {
err(-1, "unable to open file %s", argv[i]);
} else {
/*
* do it for this file...
*/
ifp = 1;
processFile ();
fclose (sofile[0]);
}
} else if (*argv[i] == '-' && *(argv[i]+1) == 0) {
/*
* - means read stdin (anywhere in file list)
*/
sofile[0] = stdin;
ifp = 1;
sleep(1);
processFile ();
}
}
/*
* if no files, usage (should really use stdin...)
*/
if ((ifp == 0 && swflg == FALSE) || argc <= 1) {
usage ();
err_exit (-1);
}
/*
* normal exit. this will fflush/fclose streams...
*/
err_exit (0);
#if defined(__GNUC__) || defined(__INSIGHT__)
return 0;
#endif
}
/*------------------------------*/
/* usage */
/*------------------------------*/
static void
usage (void) {
/*
* note: -l may not work correctly
*/
fprintf(stderr, "Usage: %s [options] file [...]\n", progname);
fputs("\t-a\tno font changes\n", stderr);
fputs("\t-b\t\tbackspace\n", stderr);
fputs("\t-d\t\tdebug mode (file: nroff.dbg)\n", stderr);
#ifdef GEMDOS
fputs("\t-h\t\thold screen before desktop\n", stderr);
#endif
#if 0
fputs("\t-l\t\toutput to printer\n", stderr);
#endif
fputs("\t-m<name>\tmacro file (e.g. -man)\n", stderr);
fputs("\t-o<file>\terror log file (stderr is default)\n", stderr);
fputs("\t-po<n>\t\tpage offset\n", stderr);
fputs("\t-pn<n>\t\tinitial page number\n", stderr);
fputs("\t-pl<n>\t\tpage length\n", stderr);
fputs("\t-s\t\tstep through pages\n", stderr);
fputs("\t-v\t\tprint version only\n", stderr);
fputs("\t+<n>\t\tfirst page to do\n", stderr);
fputs("\t-<n>\t\tlast page to do\n", stderr);
fputs("\t-\t\tuse stdin (in file list)\n", stderr);
}
/*
* init
* initialize parameters for nro word processor
*/
static void
init (void) {
#ifdef MINIX
register int i;
#else
register long i;
#endif
time_t tval;
char *ctim;
/*
* misc global flags, etc...
*/
mc_space = 2;
mc_char = '|';
tval = time (0L);
ctim = ctime (&tval);
/*
* basic document controls...
*/
dc.fill = YES;
dc.dofnt = YES;
dc.lsval = 1;
dc.inval = 0;
dc.rmval = PAGEWIDTH - 1;
dc.llval = PAGEWIDTH - 1;
dc.ltval = PAGEWIDTH - 1;
dc.tival = 0;
dc.ceval = 0;
dc.ulval = 0;
dc.cuval = 0;
dc.juval = YES;
dc.adjval = ADJ_BOTH;
dc.boval = 0;
dc.bsflg = FALSE;
dc.prflg = TRUE;
dc.sprdir = 0;
dc.flevel = 0;
dc.lastfnt = 1;
dc.thisfnt = 1;
dc.escon = YES;
dc.pgchr = '%';
dc.cmdchr = '.';
dc.escchr = '\\';
dc.nobrchr = '\'';
for (i = 0; i < 26; ++i) {
dc.nr[i] = 0;
}
for (i = 0; i < 26; ++i) {
dc.nrauto[i] = 1;
}
for (i = 0; i < 26; ++i) {
dc.nrfmt[i] = '1';
}
/*
* initialize internal regs. first zero out...
*/
for (i = 0; i < MAXREGS; i++) {
rg[i].rname[0] = EOS;
rg[i].rname[1] = EOS;
rg[i].rname[2] = EOS;
rg[i].rname[3] = EOS;
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
}
/*
* predefined regs. these are read/write:
*/
i = 0;
strcpy (rg[i].rname, "%"); /* current page */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "ct"); /* character type */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dl"); /* width of last complete di */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dn"); /* height of last complete di */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dw"); /* day of week (1-7) */
rg[i].rval = 0;
if (!strncmp (&ctim[0], "Sun", 3)) rg[i].rval = 1;
else if (!strncmp (&ctim[0], "Mon", 3)) rg[i].rval = 2;
else if (!strncmp (&ctim[0], "Tue", 3)) rg[i].rval = 3;
else if (!strncmp (&ctim[0], "Wed", 3)) rg[i].rval = 4;
else if (!strncmp (&ctim[0], "Thu", 3)) rg[i].rval = 5;
else if (!strncmp (&ctim[0], "Fri", 3)) rg[i].rval = 6;
else if (!strncmp (&ctim[0], "Sat", 3)) rg[i].rval = 7;
rg[i].rauto = 1;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dy"); /* day of month (1-31) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[8]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "hp"); /* current h pos on input */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "ln"); /* output line num */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "mo"); /* current month (1-12) */
rg[i].rval = 0;
if (!strncmp (&ctim[4], "Jan", 3)) rg[i].rval = 1;
else if (!strncmp (&ctim[4], "Feb", 3)) rg[i].rval = 2;
else if (!strncmp (&ctim[4], "Mar", 3)) rg[i].rval = 3;
else if (!strncmp (&ctim[4], "Apr", 3)) rg[i].rval = 4;
else if (!strncmp (&ctim[4], "May", 3)) rg[i].rval = 5;
else if (!strncmp (&ctim[4], "Jun", 3)) rg[i].rval = 6;
else if (!strncmp (&ctim[4], "Jul", 3)) rg[i].rval = 7;
else if (!strncmp (&ctim[4], "Aug", 3)) rg[i].rval = 8;
else if (!strncmp (&ctim[4], "Sep", 3)) rg[i].rval = 9;
else if (!strncmp (&ctim[4], "Oct", 3)) rg[i].rval = 10;
else if (!strncmp (&ctim[4], "Nov", 3)) rg[i].rval = 11;
else if (!strncmp (&ctim[4], "Dec", 3)) rg[i].rval = 12;
rg[i].rauto = 1;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "nl"); /* v pos of last base-line */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "sb"); /* depth of str below base */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "st"); /* height of str above base */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "yr"); /* last 2 dig of current year*/
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[22]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "hh"); /* current hour (0-23) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[11]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = 2 | 0x80;
i++;
strcpy (rg[i].rname, "mm"); /* current minute (0-59) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[14]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = 2 | 0x80;
i++;
strcpy (rg[i].rname, "ss"); /* current second (0-59) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[17]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = 2 | 0x80;
i++;
/*
* these are read only (by user):
*/
strcpy (rg[i].rname, ".$"); /* num args at current macro*/
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".A"); /* 1 for nroff */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".H"); /* hor resolution */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".T"); /* 1 for troff */
rg[i].rauto = 0;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".V"); /* vert resolution */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".a");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".c");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".d");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".f"); /* current font (1-4) */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".h");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".i"); /* current indent */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".l"); /* current line length */
rg[i].rauto = 1;
rg[i].rval = PAGEWIDTH - 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".n");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".o"); /* current offset */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".p"); /* current page len */
rg[i].rauto = 1;
rg[i].rval = PAGELEN;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".s"); /* current point size */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".t");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".u");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".v"); /* current v line spacing */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".w"); /* width of prev char */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".x");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".y");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".z");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
/*
* page controls...
*/
pg.curpag = 0;
pg.newpag = 1;
pg.lineno = 0;
pg.plval = PAGELEN;
pg.m1val = 2;
pg.m2val = 2;
pg.m3val = 2;
pg.m4val = 2;
pg.bottom = pg.plval - pg.m4val - pg.m3val;
pg.offset = 0;
pg.frstpg = 0;
pg.lastpg = 30000;
pg.ehead[0] = pg.ohead[0] = '\n';
pg.efoot[0] = pg.ofoot[0] = '\n';
memset(pg.ehead + 1, EOS, MAXLINE -1);
memset(pg.ohead + 1, EOS, MAXLINE -1);
memset(pg.efoot + 1, EOS, MAXLINE -1);
memset(pg.ofoot + 1, EOS, MAXLINE -1);
#if 0
for (i = 1; i < MAXLINE; ++i) {
pg.ehead[i] = pg.ohead[i] = EOS;
pg.efoot[i] = pg.ofoot[i] = EOS;
}
#endif
pg.ehlim[LEFT] = pg.ohlim[LEFT] = dc.inval;
pg.eflim[LEFT] = pg.oflim[LEFT] = dc.inval;
pg.ehlim[RIGHT] = pg.ohlim[RIGHT] = dc.rmval;
pg.eflim[RIGHT] = pg.oflim[RIGHT] = dc.rmval;
/*
* output buffer controls...
*/
initOutbuf();
/*
* macros...
*/
initMacros();
/*
* file descriptors (for sourced files)
*/
for (i = 0; i < Nfiles+1; ++i) {
sofile[i] = NULL_FPTR;
}
}
/*
* pswitch
*
* process switch values from command line
*/
static int
pswitch (char *p, int *q) {
int swgood;
char mfile[256];
char *ptmac;
int indx;
int val;
swgood = TRUE;
if (*p == '-') {
/*
* since is STILL use the goofy atari/dri xmain code, i
* look for both upper and lower case. if you use dLibs
* (and if its startup code does not ucase the cmd line),
* you can probably look for just lower case. gulam and
* other shells typically don't change case of cmd line.
*/
switch (*++p) {
case 0: /* stdin */
break;
case 'a': /* font changes */
case 'A':
dc.dofnt = NO;
break;
case 'b': /* backspace */
case 'B':
dc.bsflg = TRUE;
break;
case 'd': /* debug mode */
case 'D':
if ((dbg_stream = fopen (dbgfile, "w")) == NULL) {
warn ("unable to open debug file %s, using stderr", dbgfile);
dbg_stream = stderr;
}
debugging = TRUE;
break;
case 'h': /* hold screen */
case 'H':
hold_screen = TRUE;
break;
case 'l': /* to lpr (was P) */
case 'L':
#ifdef GEMDOS
out_stream = (FILE *) 0;
#else
out_stream = fopen (printer, "w");
#endif
setPrinting(TRUE);
break;
case 'm': /* macro file */
case 'M':
/*
* build macro file name. start with lib
*
* put c:\lib\tmac in environment so we can
* read it here. else use default. if you want
* file from cwd, "setenv TMACDIR ." from shell.
*
* we want file names like "tmac.an" (for -man)
*/
if ((ptmac = getenv ("TMACDIR")) != NULL) {
/*
* this is the lib path (e.g. "c:\lib\tmac")
*/
strcpy (mfile, ptmac);
/*
* this is the prefix (i.e. "\tmac.")
*/
strcat (mfile, TMACPRE);
} else {
/*
* use default lib/prefix (i.e.
* "c:\lib\tmac\tmac.")
*/
strcpy (mfile, TMACFULL);
}
/*
* finally, add extension (e.g. "an")
*/
strcat (mfile, ++p);
/*
* open file and read it
*/
if ((sofile[0] = fopen (mfile, "r")) == NULL_FPTR) {
err(-1, "unable to open macro file %s", mfile);
/*NOTREACHED*/
}
processFile ();
fclose (sofile[0]);
break;
case 'o': /* output error log */
case 'O':
if (!*(p+1)) {
err(-1, "no error file specified");
/*NOTREACHED*/
}
if ((err_stream = fopen (p+1, "w")) == NULL) {
err(-1, "unable to open error file %s", p+1);
/*NOTREACHED*/
}
err_set_file(err_stream);
break;
case 'p': /* .po, .pn */
case 'P':
if (*(p+1) == 'o' || *(p+1) == 'O') { /* -po___ */
p += 2;
set (&pg.offset, ctod (p), '1', 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
} else if (*(p+1) == 'n' || *(p+1) == 'N') { /* -pn___ */
p += 2;
set (&pg.curpag, ctod (p) - 1, '1', 0, -HUGE, HUGE);
pg.newpag = pg.curpag + 1;
set_ireg ("%", pg.newpag, 0);
} else if (*(p+1) == 'l' || *(p+1) == 'L') { /* -pl___ */
p += 2;
set (&pg.plval, ctod (p) - 1, '1', 0,
pg.m1val + pg.m2val + pg.m3val + pg.m4val + 1,
HUGE);
set_ireg (".p", pg.plval, 0);
pg.bottom = pg.plval - pg.m3val - pg.m4val;
} else { /* -p___ */
p++;
set (&pg.offset, ctod (p), '1', 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
}
break;
case 'r': /* set number reg */
case 'R':
if (!isalpha (*(p+1))) {
warnx("invalid number register name (%c)", *(p+1));
} else {
/*
* indx is the user num register and val
* is the final value.
*/
indx = tolower (*(p+1)) - 'a';
val = atoi (p+2);
set (&dc.nr[indx], val, '1', 0, -INFINITE, INFINITE);
}
break;
case 's': /* page step mode */
case 'S':
stepping = TRUE;
break;
case 'v': /* version */
case 'V':
printf ("%s %s\n", progname, version);
*q = TRUE;
break;
case '0': /* last page */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
pg.lastpg = ctod (p);
break;
default: /* illegal */
swgood = FALSE;
break;
}
} else if (*p == '+') { /* first page */
pg.frstpg = ctod (++p);
} else { /* illegal */
swgood = FALSE;
}
if (swgood == FALSE) {
warnx("illegal option: %s", p);
return (ERR);
}
return (OK);
}
/*
* processFile
*
* process input files from command line
*/
static void
processFile (void) {
static char ibuf[MAXLINE];
int i;
/*
* handle nesting of includes (.so). note that .so causes dc.flevel
* to be increased...
*/
for (dc.flevel = 0; dc.flevel >= 0; dc.flevel -= 1) {
while ((i = getlin (ibuf, sofile[dc.flevel])) != EOF) {
/*
* if line is a command or text
*/
if (ibuf[0] == dc.cmdchr) {
comand (ibuf);
} else {
/*
* this is a text line. first see if
* first char is space. if it is, break
* line.
*/
if (ibuf[0] == ' ') {
robrk ();
}
text (ibuf);
}
}
/*
* close included file
*/
if (dc.flevel > 0) {
fclose (sofile[dc.flevel]);
}
}
if (pg.lineno > 0) {
nroffSpace (HUGE);
}
}
#pragma optimize 78
#pragma debug 0
void
debugMessage (const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
fprintf(err_stream, "%s: ", progname);
vfprintf(err_stream, fmt, ap);
va_end(ap);
return;
}