mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-12-27 16:31:19 +00:00
1006 lines
22 KiB
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;
|
|
}
|