Path: utzoo!attcan!uunet!convex!convex1.convex.com!rosenkra From: rosenkra@convex1.convex.com (William Rosencranz) Newsgroups: comp.os.minix Subject: Re: nroff v1.10p3 (part03/05) Summary: new version Keywords: nroff conditionals ms man Message-ID: <104588@convex.convex.com> Date: 3 Aug 90 04:21:59 GMT Sender: news@convex.com Organization: Convex Computer Corporation; Richardson, TX Lines: 2927 --- part 3 of 5 shar files #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # If this archive is complete, you will see the following message at the end: # "End of archive 3 (of 5)." # # Contents: # io.c low.c macros.c main.c # # Wrapped by rosenkra%c1yankee@convex.com on Thu Aug 2 13:40:46 1990 # PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f io.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"io.c\" else echo shar: Extracting \"io.c\" \(4007 characters\) sed "s/^X//" >io.c <<'END_OF_io.c' X/* X * io.c - low level I/O processing portion of nroff word processor X * X * adapted for atariST/TOS by Bill Rosenkranz 11/89 X * net: rosenkra@hall.cray.com X * CIS: 71460,17 X * GENIE: W.ROSENKRANZ X * X * original author: X * X * Stephen L. Browning X * 5723 North Parker Avenue X * Indianapolis, Indiana 46220 X * X * history: X * X * - Originally written in BDS C; X * - Adapted for standard C by W. N. Paul X * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz X */ X X#undef NRO_MAIN /* extern globals */ X X#include X#include "nroff.h" X X/*------------------------------*/ X/* getlin */ X/*------------------------------*/ Xgetlin (p, in_buf) Xchar *p; XFILE *in_buf; X{ X X/* X * retrieve one line of input text X */ X X register char *q; X register int i; X int c; X int nreg; X X q = p; X for (i = 0; i < MAXLINE - 1; ++i) X { X c = ngetc (in_buf); X if (c == EOF) X { X *q = EOS; X c = strlen (p); X return (c == 0 ? EOF : c); X } X *q++ = c; X if (c == '\n') X break; X } X *q = EOS; X X nreg = findreg (".c"); X if (nreg > 0) X set_ireg (".c", rg[nreg].rval + 1, 0); X X return (strlen (p)); X} X X X X X X X/*------------------------------*/ X/* ngetc */ X/*------------------------------*/ Xngetc (infp) XFILE *infp; X{ X X/* X * get character from input file or push back buffer X */ X X register int c; X X if (mac.ppb >= &mac.pbb[0]) X c = *mac.ppb--; X else X c = getc (infp); X X return (c); X} X X X X/*------------------------------*/ X/* pbstr */ X/*------------------------------*/ Xpbstr (p) Xchar *p; X{ X X/* X * Push back string into input stream X */ X X register int i; X X /* X * if string is null, we do nothing X */ X if (p == NULL_CPTR) X return; X if (p[0] == EOS) X return; X for (i = strlen (p) - 1; i >= 0; --i) X { X putbak (p[i]); X } X} X X X X X X/*------------------------------*/ X/* putbak */ X/*------------------------------*/ Xputbak (c) Xchar c; X{ X X/* X * Push character back into input stream. we use the push-back buffer X * stored with macros. X */ X X if (mac.ppb < &(mac.pbb[0])) X { X mac.ppb = &(mac.pbb[0]); X *mac.ppb = c; X } X else X { X if (mac.ppb >= &mac.pbb[MAXPBB - 1]) X { X fprintf (err_stream, X "***%s: push back buffer overflow\n", myname); X err_exit (-1); X } X *++(mac.ppb) = c; X } X} X X X X/*------------------------------*/ X/* prchar */ X/*------------------------------*/ Xprchar (c, fp) Xchar c; XFILE *fp; X{ X X/* X * print character with test for printer X */ X X/* this really slows things down. it should be fixed. for now, ignore X line printer... X X if (fp == stdout) X putc (c, fp); X else X putc_lpr (c, fp); X*/ X putc (c, fp); X} X X X X X X X/*------------------------------*/ X/* put */ X/*------------------------------*/ Xput (p) Xchar *p; X{ X X/* X * put out line with proper spacing and indenting X */ X X register int j; X char os[MAXLINE]; X X if (pg.lineno == 0 || pg.lineno > pg.bottom) X { X phead (); X } X if (dc.prflg == TRUE) X { X if (!dc.bsflg) X { X if (strkovr (p, os) == TRUE) X { X for (j = 0; j < pg.offset; ++j) X prchar (' ', out_stream); X for (j = 0; j < dc.tival; ++j) X prchar (' ', out_stream); X putlin (os, out_stream); X } X } X for (j = 0; j < pg.offset; ++j) X prchar (' ', out_stream); X for (j = 0; j < dc.tival; ++j) X prchar (' ', out_stream); X putlin (p, out_stream); X } X dc.tival = dc.inval; X skip (min (dc.lsval - 1, pg.bottom - pg.lineno)); X pg.lineno = pg.lineno + dc.lsval; X set_ireg ("ln", pg.lineno, 0); X if (pg.lineno > pg.bottom) X { X pfoot (); X if (stepping) X wait_for_char (); X } X} X X X X X/*------------------------------*/ X/* putlin */ X/*------------------------------*/ Xputlin (p, pbuf) Xregister char *p; XFILE *pbuf; X{ X X/* X * output a null terminated string to the file X * specified by pbuf. X */ X X while (*p != EOS) X prchar (*p++, pbuf); X} X X X X X/*------------------------------*/ X/* putc_lpr */ X/*------------------------------*/ X#ifdef GEMDOS X#include X#endif X Xputc_lpr (c, fp) Xchar c; XFILE *fp; X{ X X/* X * write char to printer X */ X X#ifdef GEMDOS X Bconout (0, (int) c & 0x00FF); X#else X putc (c, fp); X#endif X} END_OF_io.c if test 4007 -ne `wc -c low.c <<'END_OF_low.c' X/* X * low.c - misc low-level functions for nroff word processor X * X * adapted for atariST/TOS by Bill Rosenkranz 11/89 X * net: rosenkra@hall.cray.com X * CIS: 71460,17 X * GENIE: W.ROSENKRANZ X * X * original author: X * X * Stephen L. Browning X * 5723 North Parker Avenue X * Indianapolis, Indiana 46220 X * X * history: X * X * - Originally written in BDS C; X * - Adapted for standard C by W. N. Paul X * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz X */ X X#undef NRO_MAIN /* extern globals */ X X#include X#include "nroff.h" X X X X/*------------------------------*/ X/* atod */ X/*------------------------------*/ Xatod (c) Xchar c; X{ X X/* X * convert ascii character to decimal. X */ X X return (((c < '0') || (c > '9')) ? -1 : c - '0'); X} X X X X X X/*------------------------------*/ X/* robrk */ X/*------------------------------*/ Xrobrk () X{ X X/* X * end current filled line X */ X X if (co.outp > 0) X { X /* X * handle margin char (change bar) here for all filled lines X */ X co.outbuf[co.outp] = '\r'; X co.outbuf[co.outp+1] = '\n'; X co.outbuf[co.outp+2] = EOS; X X do_mc (co.outbuf); X X put (co.outbuf); X } X co.outp = 0; X co.outw = 0; X co.outwds = 0; X co.outesc = 0; X} X X X X X/*------------------------------*/ X/* ctod */ X/*------------------------------*/ Xctod (p) Xregister char *p; X{ X X/* X * convert string to decimal. processes only positive values. X * this takes a constant like "1", "1.0i", etc. X */ X X register long val; X register int d; X register char *pp = p; X register char *ptmp; X int rside = 0; X int lside = 0; X int has_rside = 0; X int has_lside = 0; X X if (*p == EOS) X return (0); X X ptmp = skipwd (pp); X pp = --ptmp; X X switch (*pp) X { X case 'i': X case 'c': X val = 0L; X while (*p != EOS && isdigit (*p)) X { X has_lside++; X lside = atod (*p); X p++; X if (lside == -1) X break; X val = 10L * val + (long) lside; X } X lside = (int) val; X if (*p == '.') X { X p++; X val = 0L; X while (*p != EOS && isdigit (*p)) X { X has_rside++; X rside = atod (*p); X p++; X if (rside == -1) X break; X val = 10L * val + (long) rside; X if (has_rside > 2) /* more than enough */ X break; X } X rside = (int) val; X } X X /* X * now put it together. 1.0i -> 240, 1.50i -> 360, etc. X */ X val = 0L; X if (has_lside) X { X val = (long) lside * BU_INCH; X } X switch (has_rside) X { X case 1: X val = val + ((long) rside * BU_INCH / 10L); X break; X case 2: X val = val + ((long) rside * BU_INCH / 100L); X break; X case 3: X val = val + ((long) rside * BU_INCH / 1000L); X break; X default: X break; X } X if (*pp == 'c') X val = (val * BU_CM) / BU_INCH; X X /* X * for now we convert to basic char size, 1 em... X */ X val = val / BU_EM; X X break; X X case 'P': X case 'm': X case 'n': X case 'p': X case 'u': X case 'v': X val = 0L; X while (*p != EOS) X { X d = atod (*p); X p++; X if (d == -1) X break; X val = 10L * val + (long) d; X } X switch (*pp) X { X case 'P': X val = val * BU_PICA; X break; X case 'p': X val = val * BU_POINT; X break; X case 'u': X val = val * BU_BU; X break; X case 'm': X val = val * BU_EM; X break; X case 'n': X val = val * BU_EN; X break; X case 'v': X val = val * BU_EM; X break; X } X X /* X * for now we convert to basic char size, 1 em... X */ X val = val / BU_EM; X X break; X X default: X /* X * this is the default behavior. it SHOULD make things X * compatible with the old way... X */ X val = 0L; X while (*p != EOS) X { X d = atod (*p); X p++; X if (d == -1) X break; X val = 10L * val + (long) d; X } X break; X } X X return ((int) val); X} X X X X X/*------------------------------*/ X/* inptobu */ X/*------------------------------*/ Xinptobu (ps) Xchar *ps; X{ X X/* X * convert input units to b.u. X */ X X return; X} X X X X X/*------------------------------*/ X/* butochar */ X/*------------------------------*/ Xbutochar (ps) Xchar *ps; X{ X X/* X * convert b.u. to char spaces X */ X X return; X} X X X X X/*------------------------------*/ X/* skipbl */ X/*------------------------------*/ Xchar *skipbl (p) Xregister char *p; X{ X X/* X * skip blanks and tabs in character buffer. return ptr to first X * non-space or non-tab char. this could mean EOS or \r or \n. X * also increments the arg ptr (side effect). X */ X X while ((*p != EOS) && (*p == ' ' || *p == '\t')) X ++p; X return (p); X} X X X X X/*------------------------------*/ X/* skipwd */ X/*------------------------------*/ Xchar *skipwd (p) Xregister char *p; X{ X X/* X * skip over word and punctuation. anything but space,\t,\r,\n, and EOS X * is skipped. return ptr to the first of these found. also increments X * the arg ptr (side effect). X */ X X while (*p != EOS && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n') X ++p; X return (p); X} X X X X X X/*------------------------------*/ X/* space */ X/*------------------------------*/ Xspace (n) Xint n; X{ X X/* X * space vertically n lines. this does header and footer also. X */ X X robrk (); X if (pg.lineno > pg.bottom) X return; X if (pg.lineno == 0) X phead (); X skip (min (n, pg.bottom + 1 - pg.lineno)); X pg.lineno += n; X set_ireg ("ln", pg.lineno, 0); X if (pg.lineno > pg.bottom) X pfoot (); X} X X X X X/*------------------------------*/ X/* getfield */ X/*------------------------------*/ Xchar *getfield (p, q, delim) Xregister char *p; Xregister char *q; Xchar delim; X{ X X/* X * get field from title X */ X X while (*p != delim && *p != '\r' && *p != '\n' && *p != EOS) X { X *q++ = *p++; X } X *q = EOS; X if (*p == delim) X ++p; X return (p); X} X X X X X X/*------------------------------*/ X/* getwrd */ X/*------------------------------*/ Xgetwrd (p0, p1) Xregister char *p0; Xregister char *p1; X{ X X/* X * get non-blank word from p0 into p1. X * return number of characters processed. X */ X X register int i; X register char *p; X char c; X X /* X * init counter... X */ X i = 0; X X X /* X * skip leading whitespace X */ X while (*p0 && (*p0 == ' ' || *p0 == '\t')) X { X ++i; X ++p0; X } X X X /* X * set ptr and start to look for end of word X */ X p = p0; X while (*p0 != ' ' && *p0 != EOS && *p0 != '\t') X { X if (*p0 == '\n' || *p0 == '\r') X break; X *p1 = *p0++; X ++p1; X ++i; X } X X c = *(p1 - 1); X if (c == '"') X c = *(p1 - 2); X if (c == '?' || c == '!') X { X *p1++ = ' '; X ++i; X } X if (c == '.' && (*p0 == '\n' || *p0 == '\r' || islower (*p))) X { X *p1++ = ' '; X ++i; X } X *p1 = EOS; X X return (i); X} X X X X X/*------------------------------*/ X/* countesc */ X/*------------------------------*/ X X#define ESC 27 X Xcountesc (p) Xregister char *p; X{ X X/* X * count atari escape sequence characters in given null-terminated X * string X */ X X register char *pp; X register int num; X X pp = p; X num = 0; X X while (*pp != EOS) X { X if (*pp == ESC) X { X /* X * count escape char (atari-specific, vt52) X * generally only p,q,b,and c will show up... X */ X switch (*(pp+1)) X { X case 'A': /* ESC-a */ X case 'B': X case 'C': X case 'D': X case 'E': X case 'H': X case 'I': X case 'J': X case 'K': X case 'L': X case 'M': X case 'd': X case 'e': X case 'f': X case 'j': X case 'k': X case 'l': X case 'o': X case 'p': X case 'q': X case 'v': X case 'w': X num += 2; X break; X case 'b': /* ESC-a-b */ X case 'c': X num += 3; X break; X case 'Y': /* ESC-a-b-c */ X case '[': /* Esc [ 7 m */ X num += 4; X break; X default: X num += 1; X break; X } X } X pp++; X } X X return (num); X} X X X X X/*------------------------------*/ X/* itoda */ X/*------------------------------*/ Xitoda (value, p, size) Xint value; Xregister char *p; Xregister int size; X{ X X/* X * convert integer to decimal ascii string X */ X X register int i; X register int j; X register int k; X register int aval; X char c[20]; X X aval = abs (value); X c[0] = EOS; X i = 1; X do X { X c[i++] = (aval % 10) + '0'; X aval /= 10; X X } while (aval > 0 && i <= size); X X if (value < 0 && i <= size) X c[i++] = '-'; X for (j = 0; j < i; ++j) X *p++ = c[i - j - 1]; X X return (i); X} X X X X X/*------------------------------*/ X/* itoROMAN */ X/*------------------------------*/ XitoROMAN (value, p, size) Xint value; Xregister char *p; Xregister int size; X{ X X/* X * convert integer to upper roman. must be positive X */ X X register int i; X register int j; X register int k; X register int aval; X char c[100]; X int rem; X X aval = abs (value); X c[0] = EOS; X i = 1; X X /* X * trivial case: X */ X if (aval == 0) X { X c[i++] = '0'; X goto done_100; X } X X /* X * temporarily mod 100... X */ X aval = aval % 100; X X if (aval > 0) X { X /* X * build backward X * X * | I| 1 X * | II| 2 X * | III| 3 X * | VI| 4 X * | V| 5 X * | IV| 6 X * | IIV| 7 X * | IIIV| 8 X * | XI| 9 X * | X| 0 X * | IX| 11 X * | IIX| 12 X */ X if ((aval % 5 == 0) && (aval % 10 != 0))/* 5 */ X c[i++] = 'V'; X else X { X rem = aval % 10; X if (rem == 9) /* 9 */ X { X c[i++] = 'X'; X c[i++] = 'I'; X } X else if (rem == 8) /* 8 */ X { X c[i++] = 'I'; X c[i++] = 'I'; X c[i++] = 'I'; X c[i++] = 'V'; X } X else if (rem == 7) /* 7 */ X { X c[i++] = 'I'; X c[i++] = 'I'; X c[i++] = 'V'; X } X else if (rem == 6) /* 6 */ X { X c[i++] = 'I'; X c[i++] = 'V'; X } X else if (rem == 4) /* 4 */ X { X c[i++] = 'V'; X c[i++] = 'I'; X } X else /* 3,2,1 */ X { X for (j = 0; j < rem; j++) X c[i++] = 'I'; X } X } X X aval /= 10; X if (aval == 0) X goto done_100; X X rem = aval % 10; X if (rem == 4) X { X c[i++] = 'L'; X c[i++] = 'X'; X } X else if (rem == 5) X { X c[i++] = 'L'; X } X else if (rem < 4) X { X for (j = 0; j < rem; j++) X c[i++] = 'X'; X } X else X { X for (j = 0; j < rem - 5; j++) X c[i++] = 'X'; X c[i++] = 'L'; X } X } X X Xdone_100: X /* X * divide by 100 (they are done) and temp mod by another 10 X */ X aval = abs (value); X aval /= 100; X X if (aval > 0) X { X rem = aval % 10; X if (rem == 4) X { X c[i++] = 'D'; X c[i++] = 'C'; X } X if (rem == 5) X { X c[i++] = 'D'; X } X else if (rem < 4) X { X for (j = 0; j < rem; j++) X c[i++] = 'C'; X } X else if (rem == 9) X { X c[i++] = 'M'; X c[i++] = 'C'; X } X else if (rem < 9) X { X for (j = 0; j < rem - 5; j++) X c[i++] = 'C'; X c[i++] = 'D'; X } X } X X X aval /= 10; X X if (aval > 0) X { X rem = aval % 10; X if (rem < 4) X { X for (j = 0; j < rem; j++) X c[i++] = 'M'; X } X } X X X if (value < 0) X c[i++] = '-'; X X for (j = 0; j < i; ++j) X *p++ = c[i - j - 1]; X X return (i); X} X X X X X/*------------------------------*/ X/* itoroman */ X/*------------------------------*/ Xitoroman (value, p, size) Xint value; Xchar *p; Xint size; X{ X X/* X * convert integer to lower roman X */ X X register int i; X register int len; X register int aval; X char c[100]; X X c[0] = EOS; X len = itoROMAN (value, c, size); X X for (i = 0; i < len; i++) X { X p[i] = c[i]; X if (isalpha (p[i])) X p[i] = tolower (c[i]); X } X X return (len); X} X X X X X/*------------------------------*/ X/* itoLETTER */ X/*------------------------------*/ XitoLETTER (value, p, size) Xint value; Xregister char *p; Xregister int size; X{ X X/* X * convert integer to upper letter value: 0,A,B,C,...,AA,AB,AC,... X */ X X register int i; X register int j; X register int k; X register int aval; X int rem; X char c[20]; X X aval = abs (value); X c[0] = EOS; X i = 1; X X /* X * 1 based: X * X * 0 0 X * 1 A X * 25 Z X * 26 AA X * 51 AZ X * 52 AAA X * ... X */ X if (aval == 0) X c[i++] = '0'; X else if (aval < 27) X { X c[i++] = aval - 1 + 'A'; X } X else X { X do X { X c[i++] = ((aval - 1) % 26) + 'A'; X aval = (aval - 1) / 26; X X } while (aval > 0 && i <= size); X } X X if (value < 0 && i <= size) X c[i++] = '-'; X X for (j = 0; j < i; ++j) X *p++ = c[i - j - 1]; X X return (i); X} X X X X/*------------------------------*/ X/* itoletter */ X/*------------------------------*/ Xitoletter (value, p, size) Xint value; Xregister char *p; Xregister int size; X{ X X/* X * convert integer to upper letter value: 0,a,b,c,...,aa,ab,ac,... X */ X X register int i; X register int j; X register int k; X register int aval; X char c[20]; X int rem; X X aval = abs (value); X c[0] = EOS; X i = 1; X X /* X * 1 based: X * X * 0 0 X * 1 A X * 25 Z X * 26 AA X * 51 AZ X * 52 AAA X * ... X */ X if (aval == 0) X c[i++] = '0'; X else if (aval < 27) X { X c[i++] = aval - 1 + 'a'; X } X else X { X do X { X c[i++] = ((aval - 1) % 26) + 'a'; X aval = (aval - 1) / 26; X X } while (aval > 0 && i <= size); X } X X if (value < 0 && i <= size) X c[i++] = '-'; X X for (j = 0; j < i; ++j) X *p++ = c[i - j - 1]; X X return (i); X} X X X X/*------------------------------*/ X/* min */ X/*------------------------------*/ X X#ifdef min X#undef min X#endif X Xmin (v1, v2) Xregister int v1; Xregister int v2; X{ X X/* X * find minimum of two integer ONLY X */ X X return ((v1 < v2) ? v1 : v2); X} X X X X X X/*------------------------------*/ X/* max */ X/*------------------------------*/ X X#ifdef max X#undef max X#endif X Xmax (v1, v2) Xregister int v1; Xregister int v2; X{ X X/* X * find maximum of two integers ONLY X */ X X return ((v1 > v2) ? v1 : v2); X} X X X X X X/*------------------------------*/ X/* err_exit */ X/*------------------------------*/ Xerr_exit (code) X{ X X/* X * exit cleanly on fatal error (close files, etc). also handles normal X * exit. X */ X X if (err_stream != stderr && err_stream != (FILE *) 0) X { X /* X * not going to stderr (-o file) X */ X fflush (err_stream); X fclose (err_stream); X } X if (debugging && dbg_stream != stderr && dbg_stream != (FILE *) 0) X { X fflush (dbg_stream); X fclose (dbg_stream); X } X if (out_stream != stdout && out_stream != (FILE *) 0) X { X /* X * not going to stdout (-l) X */ X fflush (out_stream); X fclose (out_stream); X } X X if (hold_screen) X { X wait_for_char (); X } X X exit (code); X} X X X X/*------------------------------*/ X/* wait_for_char */ X/*------------------------------*/ X#ifdef GEMDOS X#include X#endif X Xwait_for_char () X{ X#ifdef GEMDOS X printf ("enter any key..."); fflush (stdout); X Cconin (); X#endif X} X X X END_OF_low.c if test 13787 -ne `wc -c macros.c <<'END_OF_macros.c' X/* X * macros.c - macro input/output processing for nroff word processor X * X * adapted for atariST/TOS by Bill Rosenkranz 11/89 X * net: rosenkra@hall.cray.com X * CIS: 71460,17 X * GENIE: W.ROSENKRANZ X * X * original author: X * X * Stephen L. Browning X * 5723 North Parker Avenue X * Indianapolis, Indiana 46220 X * X * history: X * X * - Originally written in BDS C; X * - Adapted for standard C by W. N. Paul X * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz X */ X X#undef NRO_MAIN /* extern globals */ X X#include X#include "nroff.h" X X X X/*------------------------------*/ X/* defmac */ X/*------------------------------*/ Xdefmac (p, infp) Xregister char *p; XFILE *infp; X{ X X/* X * Define a macro. top level, read from stream. X * X * we should read macro without interpretation EXCEPT: X * X * 1) number registers are interpolated X * 2) strings indicated by \* are interpolated X * 3) arguments indicated by \$ are interpolated X * 4) concealed newlines indicated by \(newline) are eliminated X * 5) comments indicated by \" are eliminated X * 6) \t and \a are interpreted as ASCII h tab and SOH. X * 7) \\ is interpreted as backslash and \. is interpreted as a period. X * X * currently, we do only 3. a good place to do it would be here before X * putmac, after colmac... X */ X X register char *q; X register int i; X char name[MNLEN]; X char defn[MXMLEN]; X char newend[10]; X X X /* X * skip the .de and get to the name... X */ X q = skipwd (p); X q = skipbl (q); X X /* X * ok, name now holds the name. make sure it is valid (i.e. first X * char is alpha...). getwrd returns the length of the word. X */ X i = getwrd (q, name); X if (!isprint (*name)) X { X fprintf (err_stream, X "***%s: missing or illegal macro definition name\n", X myname); X err_exit (-1); X } X X /* X * truncate to 2 char max name. X */ X if (i > 2) X name[2] = EOS; X X X /* X * skip the name and see if we have a new end defined... X */ X q = skipwd (p); X q = skipbl (q); X for (i = 0; i < 10; i++) X newend[i] = EOS; X X for (i = 0; (i < 10) && ( isalpha (q[i]) || isdigit (q[i]) ); i++) X { X newend[i] = q[i]; X } X X X X /* X * read a line from input stream until we get the end of macro X * command (.en or ..). actually. we should have read the next X * field just above here to get the .de NA . or .de NA en string X * to be new end of macro. X */ X i = 0; X while (getlin (p, infp) != EOF) X { X if (p[0] == dc.cmdchr && p[1] == '\\' && p[2] == '\"') X { X /* X * comment, ignore it X */ X continue; X } X if (p[0] == dc.cmdchr && newend[0] != EOS X && p[1] == newend[0] && p[2] == newend[1]) X { X /* X * replacement end found X */ X break; X } X if (p[0] == dc.cmdchr && p[1] == 'e' && p[2] == 'n') X { X /* X * .en found X */ X break; X } X if (p[0] == dc.cmdchr && p[1] == dc.cmdchr) X { X /* X * .. found X */ X break; X } X X X /* X * collect macro from the line we just read. all this does X * is put it in the string defn. X */ X if ((i = colmac (p, defn, i)) == ERR) X { X fprintf (err_stream, X "***%s: macro definition too long\n", myname); X err_exit (-1); X } X } X X X /* X * store the macro X */ X if (!ignoring) X { X if (putmac (name, defn) == ERR) X { X fprintf (err_stream, X "***%s: macro definition table full\n", myname); X err_exit (-1); X } X } X} X X X X X X/*------------------------------*/ X/* colmac */ X/*------------------------------*/ Xcolmac (p, d, i) Xregister char *p; Xchar *d; Xregister int i; X{ X X/* X * Collect macro definition from input stream X */ X X char *pstart = p; X int istart = i; X X while (*p != EOS) X { X /* X * are we over the length limit for a single macro? X */ X if (i >= MXMLEN - 1) X { X d[i - 1] = EOS; X return (ERR); X } X X /* X * "i break for comments..." X */ X if (*p == '\\' && *(p+1) == '\"') X { X /* X * first back over any whitespace between comment X * start and last character in line. remember to X * decrement counter i, too... X */ X p--; X while (isspace (*p) && p > pstart && i > istart) X { X p--; X i--; X } X X /* X * now skip over the comment until we reach the X * trailing newline X */ X while (*p != EOS) X { X if (*p == '\n' || *p == '\r') X break; X p++; X } X } X X /* X * skip quoted things X */ X if (*p == '\\' && *(p+1) == '\\') X p++; X X /* X * copy it X */ X d[i++] = *p++; X } X d[i] = EOS; X return (i); X} X X X X X X/*------------------------------*/ X/* putmac */ X/*------------------------------*/ Xputmac (name, p) Xchar *name; Xchar *p; X{ X X/* X * Put macro definition into table X * X * NOTE: any expansions of things like number registers SHOULD X * have been done already. X */ X X X /* X * any room left? (did we exceed max number of possible macros) X */ X if (mac.lastp >= MXMDEF) X return (ERR); X X /* X * will new one fit in big buffer? X */ X if (mac.emb + strlen (name) + strlen (p) + 1 > &mac.mb[MACBUF]) X { X return (ERR); X } X X X /* X * add it... X * X * bump counter, set ptr to name, copy name, copy def. X * finally increment end of macro buffer ptr (emb). X * X * macro looks like this in mb: X * X * mac.mb[MACBUF] size of total buf X * lastp < MXMDEF number of macros possible X * *mnames[MXMDEF] -> names, each max length X * ..._____________________________...____________________... X * / / /|X|X|0|macro definition |0| / / / / / / / X * .../_/_/_|_|_|_|________________...___|_|/_/_/_/_/_/_/_... X * ^ X * | X * \----- mac.mnames[mac.lastp] points here X * X * both the 2 char name (XX) and the descripton are null term and X * follow one after the other. X */ X ++mac.lastp; X mac.mnames[mac.lastp] = mac.emb; X strcpy (mac.emb, name); X strcpy (mac.emb + strlen (name) + 1, p); X mac.emb += strlen (name) + strlen (p) + 2; X X return (OK); X} X X X X X X X/*------------------------------*/ X/* getmac */ X/*------------------------------*/ Xchar *getmac (name) Xregister char *name; X{ X X/* X * Get (lookup) macro definition from namespace X */ X X register int i; X X /* X * loop for all macros, starting with last one X */ X for (i = mac.lastp; i >= 0; --i) X { X /* X * is this REALLY a macro? X */ X if (mac.mnames[i]) X { X /* X * if it compares, return a ptr to it X */ X if (!strcmp (name, mac.mnames[i])) X { X/*!!!debug puts (mac.mnames[i]);*/ X X if (mac.mnames[i][1] == EOS) X return (mac.mnames[i] + 2); X else X return (mac.mnames[i] + 3); X } X } X } X X /* X * none found, return null X */ X return (NULL_CPTR); X} X X X X X X X/*------------------------------*/ X/* maceval */ X/*------------------------------*/ Xmaceval (p, m) Xregister char *p; Xchar *m; X{ X X/* X * Evaluate macro expansion X */ X X register int i; X register int j; X char *argp[15]; X char c; X int xc; X X X X /* X * replace command char with EOS X */ X *p++ = EOS; X X X /* X * initialize argp array to substitute command X * string for any undefined argument X * X * NO!!! this is fixed... X */ X/* for (i = 0; i < 10; ++i) X argp[i] = p; X*/ X /* X * skip the command name X */ X p = skipwd (p); X *p++ = EOS; X X X /* X * loop for all $n variables... X */ X for (i = 0; i < 10; ++i) X { X /* X * get to substituted param and if no more, reset remaining X * args to NULL and stop. using "i" here IS ok... X */ X p = skipbl (p); X if (*p == '\r' || *p == '\n' || *p == EOS) X { X if (debugging) X fprintf (err_stream, X "***%s.maceval: set_ireg(.$, %d, 0)\n", X myname,i); X X set_ireg (".$", i, 0); X for ( ; i < 10; i++) X { X argp[i] = NULL_CPTR; X } X break; X } X X X /* X * ...otherwise, see if this param is quoted. if it is, X * it is all one parameter, even with blanks (but not X * newlines...). look for another "c" (which is the quote). X * X * if no quote, just read the arg as a single word and null X * terminate it. X */ X if (*p == '\'' || *p == '"') X { X c = *p++; X argp[i] = p; X while (*p != c && *p != '\r' && *p != '\n' && *p != EOS) X ++p; X *p++ = EOS; X } X else X { X argp[i] = p; X p = skipwd (p); X *p++ = EOS; X } X } X X X /* X * m contains text of the macro. p contained the input line. X * here we start at the end of the macro def and see if there X * are any $n thingies. go backwards. X */ X for (i = strlen (m) - 1; i >= 0; --i) X { X /* X * found a $. X */ X if (i > 0 && m[i - 1] == '$') X { X if (!isdigit (m[i])) X { X /* X * it wasn't a numeric replacement arg so X * push this char back onto input stream X */ X putbak (m[i]); X } X else X { X /* X * it WAS a numeric replacement arg. so we X * want to push back the appropriate macro X * invocation arg. m[i]-'0' is the numerical X * value of the $1 thru $9. if the arg is X * not there, argp[n] will be (char *) 0 X * and pbstr will do nothing. X */ X xc = m[i] - '1'; X if (argp[xc]) X pbstr (argp[xc]); X --i; X } X } X else X { X /* X * no $ so push back the char... X */ X putbak (m[i]); X } X } X X /* X * at this point, the iobuf will hold the new macro command, full X * expanded for $n things. the return gets us right back to the X * main loop in main() and we parse the (new) command just as if X * it were read from a file. X */ X X} X X X X X X/*------------------------------*/ X/* printmac */ X/*------------------------------*/ Xprintmac (opt) Xint opt; /* 0=name&size,1=total size,2=full */ X{ X X/* X * print all macros and strings and tabulate sizes X */ X X register int i; /* was long, minix needs int */ X register long space; X register long totalspace; X register char *pname; X register char *pdef; X X X space = 0L; X totalspace = 0L; X X fflush (out_stream); X fflush (err_stream); X X for (i = mac.lastp; i >= 0; --i) X { X /* X * is this REALLY a macro? X */ X if (mac.mnames[i]) X { X pname = (char *) (mac.mnames[i]); X pdef = pname + 3; X if (*(pname + 1) == '\0') X pdef = pname + 2; X X space = (long) strlen (pdef); X totalspace += space; X X switch (opt) X { X case 0: X fprintf (err_stream, "%s %ld\n", pname, space); X break; X case 2: X fprintf (err_stream, "%s %ld\n", pname, space); X fprintf (err_stream, "%s\n", pdef); X break; X case 1: X default: X break; X } X } X } X fprintf (err_stream, "Total space: %ld\n", totalspace); X X} X END_OF_macros.c if test 10226 -ne `wc -c main.c <<'END_OF_main.c' X#include "config.h" X X/* X * main.c - main for nroff word processor X * X * similar to Unix(tm) nroff or RSX-11M RNO. adaptation of text processor X * given in "Software Tools", Kernighan and Plauger. X * X * adapted for atariST/TOS by Bill Rosenkranz 11/89 X * net: rosenkra@hall.cray.com X * CIS: 71460,17 X * GENIE: W.ROSENKRANZ X * X * original author: X * X * Stephen L. Browning X * 5723 North Parker Avenue X * Indianapolis, Indiana 46220 X * X * history: X * X * - Originally written in BDS C; X * - Adapted for standard C by W. N. Paul X * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz X */ X X#define NRO_MAIN /* to define globals in nro.h */ X X#include X#ifdef GEMDOS X#include X#include X#else X#include X#include X#endif X#include "nroff.h" X X Xmain (argc, argv) Xint argc; Xchar *argv[]; X{ X register int i; X int swflg; X int ifp = 0; X char *ptmp; X#ifndef GEMDOS X char *pterm; X char capability[100]; X char *pcap; X char *ps; X#endif X X X X /* X * set up initial flags and file descriptors X */ X swflg = FALSE; X ignoring = FALSE; X hold_screen = FALSE; X debugging = FALSE; X stepping = FALSE; X mc_ing = FALSE; X out_stream = stdout; X err_stream = stderr; X dbg_stream = stderr; X X X /* X * this is for tmp files, if ever needed. it SHOULD start X * out without the trailing slash. if not in env, use default X */ X if (ptmp = getenv ("TMPDIR")) X strcpy (tmpdir, ptmp); X else X strcpy (tmpdir, "."); X X X /* X * handle terminal for \fB, \fI X */ X#ifdef GEMDOS X strcpy (s_standout, "\33p"); /* atari/TOS is easy... */ X strcpy (e_standout, "\33q"); X strcpy (s_bold, "\33p"); /* atari/TOS is easy... */ X strcpy (e_bold, "\33q"); X strcpy (s_italic, "\33p"); X strcpy (e_italic, "\33q"); X#else X s_standout[0] = '\0'; X e_standout[0] = '\0'; X s_bold[0] = '\0'; X e_bold[0] = '\0'; X s_italic[0] = '\0'; X e_italic[0] = '\0'; X if ((pterm = getenv ("TERM")) /* it must exist first... */ X && (tgetent (termcap, pterm) == 1)) /* ...so we fill buffer */ X { X /* X * we currently use standout mode for all weirdness X * lile BOLD, italic, etc. X */ X pcap = capability; X if (ps = tgetstr ("so", &pcap)) X { X /* X * sun has padding in here. this is NOT portable. X * better to use tputs() to strip it... X */ X while (*ps && *ps != 0x1b) ps++; X strcpy (s_standout, ps); X strcpy (s_bold, ps); X strcpy (s_italic, ps); X } X if (ps = tgetstr ("se", &pcap)) X { X while (*ps && *ps != 0x1b) ps++; X strcpy (e_standout, ps); X strcpy (e_bold, ps); X strcpy (e_italic, ps); X } X } X#endif X X X X /* X * initialize structures (defaults) X */ X init (); X X X /* X * parse cmdline flags X */ X for (i = 1; i < argc; ++i) X { X if (*argv[i] == '-' || *argv[i] == '+') X { X if (pswitch (argv[i], &swflg) == ERR) X err_exit (-1); X } X } X X X /* X * loop on files X */ X for (i = 1; i < argc; ++i) X { X if (*argv[i] != '-' && *argv[i] != '+') X { X /* X * open this file... X */ X if ((sofile[0] = fopen (argv[i], "r")) == NULL_FPTR) X { X fprintf (err_stream, X "***%s: unable to open file %s\n", X myname, argv[i]); X err_exit (-1); X } X else X { X /* X * do it for this file... X */ X ifp = 1; X profile (); X fclose (sofile[0]); X } X } X else if (*argv[i] == '-' && *(argv[i]+1) == 0) X { X /* X * - means read stdin (anywhere in file list) X */ X sofile[0] = stdin; X ifp = 1; X profile (); X } X X } X X X /* X * if no files, usage (should really use stdin...) X */ X if ((ifp == 0 && swflg == FALSE) || argc <= 1) X { X usage (); X X err_exit (-1); X } X X X /* X * normal exit. this will fflush/fclose streams... X */ X err_exit (0); X} X X X X X/*------------------------------*/ X/* usage */ X/*------------------------------*/ Xusage () X{ X /* X * note: -l may not work correctly X */ X fprintf (stderr, "Usage: %s [options] file [...]\n", myname); X fprintf (stderr, "Options: -a no font changes\n"); X fprintf (stderr, " -b backspace\n"); X fprintf (stderr, " -d debug mode (file: nroff.dbg)\n"); X#ifdef GEMDOS X fprintf (stderr, " -h hold screen before desktop\n"); X#endif X/*!!! fprintf (stderr, " -l output to printer\n");*/ X fprintf (stderr, " -m macro file (e.g. -man)\n"); X fprintf (stderr, " -o error log file (stderr is default)\n"); X fprintf (stderr, " -po page offset\n"); X fprintf (stderr, " -pn initial page number\n"); X fprintf (stderr, " -pl page length\n"); X fprintf (stderr, " -s step through pages\n"); X fprintf (stderr, " -v print version only\n"); X fprintf (stderr, " + first page to do\n"); X fprintf (stderr, " - last page to do\n"); X fprintf (stderr, " - use stdin (in file list)\n"); X} X X X X X/*------------------------------*/ X/* init */ X/*------------------------------*/ Xinit () X{ X X/* X * initialize parameters for nro word processor X */ X X extern long time (); X X#ifdef MINIX X register int i; X#else X register long i; X#endif X time_t tval; X char *ctim; X X /* X * misc global flags, etc... X */ X mc_space = 2; X mc_char = '|'; X tval = time (0L); X ctim = ctime (&tval); X X /* X * basic document controls... X */ X dc.fill = YES; X dc.dofnt = YES; X dc.lsval = 1; X dc.inval = 0; X dc.rmval = PAGEWIDTH - 1; X dc.llval = PAGEWIDTH - 1; X dc.ltval = PAGEWIDTH - 1; X dc.tival = 0; X dc.ceval = 0; X dc.ulval = 0; X dc.cuval = 0; X dc.juval = YES; X dc.adjval = ADJ_BOTH; X dc.boval = 0; X dc.bsflg = FALSE; X dc.prflg = TRUE; X dc.sprdir = 0; X dc.flevel = 0; X dc.lastfnt = 1; X dc.thisfnt = 1; X dc.escon = YES; X dc.pgchr = '%'; X dc.cmdchr = '.'; X dc.escchr = '\\'; X dc.nobrchr = '\''; X for (i = 0; i < 26; ++i) X dc.nr[i] = 0; X for (i = 0; i < 26; ++i) X dc.nrauto[i] = 1; X for (i = 0; i < 26; ++i) X dc.nrfmt[i] = '1'; X X X /* X * initialize internal regs. first zero out... X */ X for (i = 0; i < MAXREGS; i++) X { X rg[i].rname[0] = EOS; X rg[i].rname[1] = EOS; X rg[i].rname[2] = EOS; X rg[i].rname[3] = EOS; X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X } X X X /* X * predefined regs. these are read/write: X */ X i = 0; X X strcpy (rg[i].rname, "%"); /* current page */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "ct"); /* character type */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "dl"); /* width of last complete di */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "dn"); /* height of last complete di */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "dw"); /* day of week (1-7) */ X rg[i].rval = 0; X if (!strncmp (&ctim[0], "Sun", 3)) X rg[i].rval = 1; X else if (!strncmp (&ctim[0], "Mon", 3)) X rg[i].rval = 2; X else if (!strncmp (&ctim[0], "Tue", 3)) X rg[i].rval = 3; X else if (!strncmp (&ctim[0], "Wed", 3)) X rg[i].rval = 4; X else if (!strncmp (&ctim[0], "Thu", 3)) X rg[i].rval = 5; X else if (!strncmp (&ctim[0], "Fri", 3)) X rg[i].rval = 6; X else if (!strncmp (&ctim[0], "Sat", 3)) X rg[i].rval = 7; X rg[i].rauto = 1; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "dy"); /* day of month (1-31) */ X rg[i].rauto = 1; X rg[i].rval = atoi (&ctim[8]); X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "hp"); /* current h pos on input */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "ln"); /* output line num */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "mo"); /* current month (1-12) */ X rg[i].rval = 0; X if (!strncmp (&ctim[4], "Jan", 3)) X rg[i].rval = 1; X else if (!strncmp (&ctim[4], "Feb", 3)) X rg[i].rval = 2; X else if (!strncmp (&ctim[4], "Mar", 3)) X rg[i].rval = 3; X else if (!strncmp (&ctim[4], "Apr", 3)) X rg[i].rval = 4; X else if (!strncmp (&ctim[4], "May", 3)) X rg[i].rval = 5; X else if (!strncmp (&ctim[4], "Jun", 3)) X rg[i].rval = 6; X else if (!strncmp (&ctim[4], "Jul", 3)) X rg[i].rval = 7; X else if (!strncmp (&ctim[4], "Aug", 3)) X rg[i].rval = 8; X else if (!strncmp (&ctim[4], "Sep", 3)) X rg[i].rval = 9; X else if (!strncmp (&ctim[4], "Oct", 3)) X rg[i].rval = 10; X else if (!strncmp (&ctim[4], "Nov", 3)) X rg[i].rval = 11; X else if (!strncmp (&ctim[4], "Dec", 3)) X rg[i].rval = 12; X rg[i].rauto = 1; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "nl"); /* v pos of last base-line */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "sb"); /* depth of str below base */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "st"); /* height of str above base */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "yr"); /* last 2 dig of current year*/ X rg[i].rauto = 1; X rg[i].rval = atoi (&ctim[22]); X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, "hh"); /* current hour (0-23) */ X rg[i].rauto = 1; X rg[i].rval = atoi (&ctim[11]); X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = 2 | 0x80; X i++; X X strcpy (rg[i].rname, "mm"); /* current minute (0-59) */ X rg[i].rauto = 1; X rg[i].rval = atoi (&ctim[14]); X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = 2 | 0x80; X i++; X X strcpy (rg[i].rname, "ss"); /* current second (0-59) */ X rg[i].rauto = 1; X rg[i].rval = atoi (&ctim[17]); X rg[i].rflag = RF_READ | RF_WRITE; X rg[i].rfmt = 2 | 0x80; X i++; X X X /* X * these are read only (by user): X */ X strcpy (rg[i].rname, ".$"); /* num args at current macro*/ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".A"); /* 1 for nroff */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".H"); /* hor resolution */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".T"); /* 1 for troff */ X rg[i].rauto = 0; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".V"); /* vert resolution */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".a"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".c"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".d"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".f"); /* current font (1-4) */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".h"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".i"); /* current indent */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".l"); /* current line length */ X rg[i].rauto = 1; X rg[i].rval = PAGEWIDTH - 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".n"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".o"); /* current offset */ X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".p"); /* current page len */ X rg[i].rauto = 1; X rg[i].rval = PAGELEN; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".s"); /* current point size */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".t"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".u"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".v"); /* current v line spacing */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".w"); /* width of prev char */ X rg[i].rauto = 1; X rg[i].rval = 1; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".x"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".y"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X i++; X X strcpy (rg[i].rname, ".z"); X rg[i].rauto = 1; X rg[i].rval = 0; X rg[i].rflag = RF_READ; X rg[i].rfmt = '1'; X X /* X * page controls... X */ X pg.curpag = 0; X pg.newpag = 1; X pg.lineno = 0; X pg.plval = PAGELEN; X pg.m1val = 2; X pg.m2val = 2; X pg.m3val = 2; X pg.m4val = 2; X pg.bottom = pg.plval - pg.m4val - pg.m3val; X pg.offset = 0; X pg.frstpg = 0; X pg.lastpg = 30000; X pg.ehead[0] = pg.ohead[0] = '\n'; X pg.efoot[0] = pg.ofoot[0] = '\n'; X for (i = 1; i < MAXLINE; ++i) X { X pg.ehead[i] = pg.ohead[i] = EOS; X pg.efoot[i] = pg.ofoot[i] = EOS; X } X pg.ehlim[LEFT] = pg.ohlim[LEFT] = dc.inval; X pg.eflim[LEFT] = pg.oflim[LEFT] = dc.inval; X pg.ehlim[RIGHT] = pg.ohlim[RIGHT] = dc.rmval; X pg.eflim[RIGHT] = pg.oflim[RIGHT] = dc.rmval; X X /* X * output buffer controls... X */ X co.outp = 0; X co.outw = 0; X co.outwds = 0; X co.lpr = FALSE; X co.outesc = 0; X for (i = 0; i < MAXLINE; ++i) X co.outbuf[i] = EOS; X X /* X * macros... X */ X for (i = 0; i < MXMDEF; ++i) X mac.mnames[i] = NULL_CPTR; X for (i = 0; i < MACBUF; ++i) X mac.mb[i] = EOS; X for (i = 0; i < MAXPBB; ++i) X mac.pbb[i] = EOS; X mac.lastp = 0; X mac.emb = &mac.mb[0]; X mac.ppb = NULL_CPTR; X X /* X * file descriptors (for sourced files) X */ X for (i = 0; i < Nfiles+1; ++i) X sofile[i] = NULL_FPTR; X} X X X X X/*------------------------------*/ X/* pswitch */ X/*------------------------------*/ Xpswitch (p, q) Xregister char *p; Xregister int *q; X{ X X/* X * process switch values from command line X */ X X int swgood; X char mfile[256]; X char *ptmac; X int indx; X int val; X X swgood = TRUE; X if (*p == '-') X { X /* X * since is STILL use the goofy atari/dri xmain code, i X * look for both upper and lower case. if you use dLibs X * (and if its startup code does not ucase the cmd line), X * you can probably look for just lower case. gulam and X * other shells typically don't change case of cmd line. X */ X switch (*++p) X { X case 0: /* stdin */ X break; X X case 'a': /* font changes */ X case 'A': X dc.dofnt = NO; X break; X X case 'b': /* backspace */ X case 'B': X dc.bsflg = TRUE; X break; X X case 'd': /* debug mode */ X case 'D': X dbg_stream = fopen (dbgfile, "w"); X debugging = TRUE; X if (dbg_stream == NULL_FPTR) X { X fprintf (err_stream, X "***%s: unable to open debug file %s\n", X myname, dbgfile); X X dbg_stream = stderr; X } X break; X X case 'h': /* hold screen */ X case 'H': X hold_screen = TRUE; X break; X X case 'l': /* to lpr (was P) */ X case 'L': X#ifdef GEMDOS X out_stream = (FILE *) 0; X#else X out_stream = fopen (printer, "w"); X#endif X co.lpr = TRUE; X break; X X case 'm': /* macro file */ X case 'M': X /* X * build macro file name. start with lib X * X * put c:\lib\tmac in environment so we can X * read it here. else use default. if you want X * file from cwd, "setenv TMACDIR ." from shell. X * X * we want file names like "tmac.an" (for -man) X */ X if (ptmac = getenv ("TMACDIR")) X { X /* X * this is the lib path (e.g. "c:\lib\tmac") X */ X strcpy (mfile, ptmac); X X /* X * this is the prefix (i.e. "\tmac.") X */ X strcat (mfile, TMACPRE); X } X else X /* X * use default lib/prefix (i.e. X * "c:\lib\tmac\tmac.") X */ X strcpy (mfile, TMACFULL); X X /* X * finally, add extension (e.g. "an") X */ X strcat (mfile, ++p); X X /* X * open file and read it X */ X if ((sofile[0] = fopen (mfile, "r")) == NULL_FPTR) X { X fprintf (stderr, X "***%s: unable to open macro file %s\n", X myname, mfile); X err_exit (-1); X } X profile (); X fclose (sofile[0]); X break; X X case 'o': /* output error log */ X case 'O': X if (!*(p+1)) X { X fprintf (stderr, X "***%s: no error file specified\n", X myname); X err_exit (-1); X } X if ((err_stream = fopen (p+1, "w")) == NULL_FPTR) X { X fprintf (stderr, X "***%s: unable to open error file %s\n", X myname, p+1); X err_exit (-1); X } X break; X X case 'p': /* .po, .pn */ X case 'P': X if (*(p+1) == 'o' || *(p+1) == 'O') /* -po___ */ X { X p += 2; X set (&pg.offset, ctod (p), '1', 0, 0, HUGE); X set_ireg (".o", pg.offset, 0); X } X else if (*(p+1) == 'n' || *(p+1) == 'N')/* -pn___ */ X { X p += 2; X set (&pg.curpag, ctod (p) - 1, '1', 0, -HUGE, HUGE); X pg.newpag = pg.curpag + 1; X set_ireg ("%", pg.newpag, 0); X } X else if (*(p+1) == 'l' || *(p+1) == 'L')/* -pl___ */ X { X p += 2; X set (&pg.plval, ctod (p) - 1, '1', 0, X pg.m1val + pg.m2val + pg.m3val + pg.m4val + 1, X HUGE); X set_ireg (".p", pg.plval, 0); X pg.bottom = pg.plval - pg.m3val - pg.m4val; X } X else /* -p___ */ X { X p++; X set (&pg.offset, ctod (p), '1', 0, 0, HUGE); X set_ireg (".o", pg.offset, 0); X } X break; X X case 'r': /* set number reg */ X case 'R': X if (!isalpha (*(p+1))) X { X fprintf (stderr, X "***%s: invalid number register name (%c)\n", X myname, (int) *(p+1)); X } X else X { X /* X * indx is the user num register and val X * is the final value. X */ X indx = tolower (*(p+1)) - 'a'; X val = atoi (p+2); X set (&dc.nr[indx], val, '1', 0, -INFINITE, INFINITE); X } X break; X X case 's': /* page step mode */ X case 'S': X stepping = TRUE; X break; X X case 'v': /* version */ X case 'V': X printf ("%s\n", version); X *q = TRUE; X break; X X case '0': /* last page */ X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X pg.lastpg = ctod (p); X break; X X default: /* illegal */ X swgood = FALSE; X break; X } X } X else if (*p == '+') /* first page */ X { X pg.frstpg = ctod (++p); X } X else /* illegal */ X { X swgood = FALSE; X } X X X if (swgood == FALSE) X { X fprintf (stderr, "***%s: illegal switch %s\n", myname, p); X return (ERR); X } X X return (OK); X} X X X X X/*------------------------------*/ X/* profile */ X/*------------------------------*/ Xprofile () X{ X X/* X * process input files from command line X */ X X char ibuf[MAXLINE]; X X /* X * handle nesting of includes (.so). note that .so causes dc.flevel X * to be increased... X */ X for (dc.flevel = 0; dc.flevel >= 0; dc.flevel -= 1) X { X while (getlin (ibuf, sofile[dc.flevel]) != EOF) X { X /* X * if line is a command or text X */ X if (ibuf[0] == dc.cmdchr) X { X comand (ibuf); X } X else X { X /* X * this is a text line. first see if X * first char is space. if it is, break X * line. X */ X if (ibuf[0] == ' ') X robrk (); X text (ibuf); X } X } X X /* X * close included file X */ X if (dc.flevel > 0) X fclose (sofile[dc.flevel]); X } X if (pg.lineno > 0) X space (HUGE); X} X X X X X END_OF_main.c if test 19776 -ne `wc -c