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 (part02/05) Summary: new version Keywords: nroff conditionals ms man Message-ID: <104587@convex.convex.com> Date: 3 Aug 90 04:20:39 GMT Sender: news@convex.com Organization: Convex Computer Corporation; Richardson, TX Lines: 2975 --- part 2 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 2 (of 5)." # # Contents: # command.c config.h escape.c # # Wrapped by rosenkra%c1yankee@convex.com on Thu Aug 2 13:40:07 1990 # PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f command.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"command.c\" else echo shar: Extracting \"command.c\" \(30522 characters\) sed "s/^X//" >command.c <<'END_OF_command.c' X/* X * command.c - command input parser/processor for nroff text 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#define iscond(x) ((x)=='>'||(x)=='<'||(x)=='=') X#define isoper(x) ((x)=='+'||(x)=='-'||(x)=='*'||(x)=='/'||(x)=='%') X X/*------------------------------*/ X/* comand */ X/*------------------------------*/ Xcomand (p) Xregister char *p; X{ X X/* X * main command processor X */ X X static int in_if_cond = 0; X X register int i; X register int ct; X register int val; X register int indx; X int newval; X int spval; X int not_cond; X char argtyp; X char name[MAXLINE]; X char macexp[MXMLEN]; X int tmp; X char *pfs; X char fs[20]; X char c; X char *ps1; X char *ps2; X X X if (debugging) X fprintf (err_stream, X "***%s.comand: enter, p=|%s|\n",myname,p); X X /* X * get command code X */ X ct = comtyp (p, macexp); X X /* X * error? X */ X if (ct == UNKNOWN) X { X fprintf (err_stream, X "***%s: unrecognized command %s\n", myname, p); X return; X } X X /* X * ignore comments X */ X if (ct == COMMENT) X return; X X X /* X * do escape expansion on command line args X */ X expesc (p, name); X X X /* X * get value of command X */ X/* val = getval (p, &argtyp);*/ X X X /* X * do the command X */ X switch (ct) X { X /* set (¶m, val, type, defval, minval, maxval) */ X case FC: X /* X * field delim/pad chars X * X * .fc [delim] [pad] X */ X fprintf (err_stream, "***%s: .fc not available\n", myname); X break; X case TR: X /* X * translate X * X * .tr ab... X */ X fprintf (err_stream, "***%s: .tr not available\n", myname); X break; X X X X X case AD: X /* X * adjust X * X * .ad [mode] X */ X val = getval (p, &argtyp); X p = skipwd (p); X p = skipbl (p); X X switch (*p) X { X case 'l': X dc.adjval = ADJ_LEFT; X dc.juval = YES; X break; X case 'r': X dc.adjval = ADJ_RIGHT; X dc.juval = YES; X break; X case 'c': X dc.adjval = ADJ_CENTER; X dc.juval = YES; X break; X case 'b': X case 'n': X dc.adjval = ADJ_BOTH; X dc.juval = YES; X break; X default: X break; X } X break; X case AF: X /* X * assign format to number reg X * X * .af R {1,a,A,i,I,0...1} X */ X val = getval (p, &argtyp); X p = skipwd (p); X p = skipbl (p); X if (!isalpha (*p)) X { X fprintf (err_stream, X "***%s: invalid or missing number register name\n", X myname); X } X else X { X /* X * number register format is 1,a,A,i,I,0...1 X * default is 1. for 0001 format, store num dig X * or'ed with 0x80, up to 8 digits. X */ X indx = tolower (*p) - 'a'; X p = skipwd (p); X p = skipbl (p); X if (*p == '1') X dc.nrfmt[indx] = '1'; X else if (*p == 'a') X dc.nrfmt[indx] = 'a'; X else if (*p == 'A') X dc.nrfmt[indx] = 'A'; X else if (*p == 'i') X dc.nrfmt[indx] = 'i'; X else if (*p == 'I') X dc.nrfmt[indx] = 'I'; X else if (*p == '0') X { X for (i = 0; isdigit (p[i]); i++) X ; X dc.nrfmt[indx] = (char) (i); X if (dc.nrfmt[indx] <= 0) X dc.nrfmt[indx] = '1'; X else if (dc.nrfmt[indx] > 8) X { X dc.nrfmt[indx] = 8; X dc.nrfmt[indx] |= 0x80; X } X else X dc.nrfmt[indx] |= 0x80; X X } X else X dc.nrfmt[indx] = '1'; X } X break; X case BD: X /* X * embolden font (IGNORED) X * X * .bd [S] F N X */ X break; X case BO: X /* X * bold face X * X * .bo [N] X */ X val = getval (p, &argtyp); X set (&dc.boval, val, argtyp, 1, 0, HUGE); X dc.cuval = dc.ulval = 0; X break; X case BP: X /* X * begin page X * X * .bp [+/-N] X */ X val = getval (p, &argtyp); X if (pg.lineno > 0) X space (HUGE); X set (&pg.curpag, val, argtyp, pg.curpag + 1, -HUGE, HUGE); X pg.newpag = pg.curpag; X set_ireg ("%", pg.newpag, 0); X break; X case BR: X /* X * break (page) X * X * .br X */ X robrk (); X break; X case BS: X /* X * backspc in output X * X * .bs [N] X */ X val = getval (p, &argtyp); X set (&dc.bsflg, val, argtyp, 1, 0, 1); X break; X case C2: X /* X * nobreak char X * X * .c2 [c='] X */ X val = getval (p, &argtyp); X if (argtyp == '\r' || argtyp == '\n') X dc.nobrchr = '\''; X else X dc.nobrchr = argtyp; X break; X case CC: X /* X * command character X * X * .cc [c=.] X */ X val = getval (p, &argtyp); X if (argtyp == '\r' || argtyp == '\n') X dc.cmdchr = '.'; X else X dc.cmdchr = argtyp; X break; X case CE: X /* X * center X * X * .ce [N] X */ X val = getval (p, &argtyp); X robrk (); X set (&dc.ceval, val, argtyp, 1, 0, HUGE); X break; X case CS: X /* X * constant space char (IGNORED) X * X * .cs F N M X */ X break; X case CU: X /* X * continuous underline X * X * .cu [N] X */ X val = getval (p, &argtyp); X set (&dc.cuval, val, argtyp, 1, 0, HUGE); X dc.ulval = dc.boval = 0; X break; X case DE: X /* X * define macro X * X * .de name [end] X */ X val = getval (p, &argtyp); X ignoring = FALSE; X defmac (p, sofile[dc.flevel]); X break; X case DS: X /* X * define string X * X * .ds name string X */ X val = getval (p, &argtyp); X defstr (p); X break; X case EC: X /* X * escape char X * X * .ec [c=\] X */ X val = getval (p, &argtyp); X if (argtyp == '\r' || argtyp == '\n') X dc.escchr = '\\'; X else X dc.escchr = argtyp; X dc.escon = YES; X break; X case EF: X /* X * even footer X * X * .ef "a" "b" "c" X */ X val = getval (p, &argtyp); X gettl (p, pg.efoot, &pg.eflim[0]); X break; X case EH: X /* X * even header X * X * .eh "a" "b" "c" X */ X val = getval (p, &argtyp); X gettl (p, pg.ehead, &pg.ehlim[0]); X break; X case EN: X /* X * end macro def (should not get one here...) X * X * .en or .. X */ X fprintf (err_stream, "***%s: missing .de command\n", myname); X break; X case EO: X /* X * escape off X * X * .eo X */ X dc.escon = NO; X break; X case EX: X /* X * exit X * X * .ex X */ X if (sofile[0] != stdin) X fclose (sofile[0]); X for (i = 1; i <= Nfiles; i++) X { X if (sofile[i] != NULL_FPTR) X fclose (sofile[i]); X } X err_exit (0); X break; X case FI: X /* X * fill X * X * .fi X */ X robrk (); X dc.fill = YES; X break; X case FL: X /* X * flush NOW X * X * .fl X */ X fflush (out_stream); X break; X case FO: X /* X * footer X * X * .fo "a" "b" "c" X */ X val = getval (p, &argtyp); X gettl (p, pg.efoot, &pg.eflim[0]); X gettl (p, pg.ofoot, &pg.oflim[0]); X break; X case FT: X /* X * font change X * X * .ft {R,I,B,S,P} X * X * the way it's implemented here, it causes a break X * rather than be environmental... X */ X val = getval (p, &argtyp); X p = skipwd (p); X p = skipbl (p); X if (!isalpha (*p)) X { X fprintf (err_stream, X "***%s: invalid or missing font name\n", X myname); X } X else X { X pfs = &fs[0]; X X fontchange (*p, pfs); X X robrk (); X fflush (out_stream); X fprintf (out_stream, "%s", pfs); X fflush (out_stream); X } X break; X case TL: X case HE: X /* X * header (both are currently identical. .he is -me) X * X * .tl "a" "b" "c" X * .he "a" "b" "c" X */ X val = getval (p, &argtyp); X gettl (p, pg.ehead, &pg.ehlim[0]); X gettl (p, pg.ohead, &pg.ohlim[0]); X break; X case IE: X /* X * if of if/else conditional X * X * .ie condition anything X * .el anything X * X * .ie condition \{\ X * ... X * ... \} X * .el \{\ X * ... X * ... \} X */ X fprintf (err_stream, "***%s: .ie not available\n", myname); X break; X case EL: X /* X * else of if/else conditional X * X * .ie condition anything X * .el anything X * X * .ie condition \{\ X * ... X * ... \} X * .el \{\ X * ... X * ... \} X */ X fprintf (err_stream, "***%s: .el not available\n", myname); X break; X case IF: X /* X * conditional X * X * .if c command [c=n(roff),t(roff),e(ven),o(dd)] X * .if !c command X * .if 's1's2' command [s1 == s2] X * .if !'s1's2' command [s1 != s2] X * .if N command [N > 0] X * .if !N command [N <= 0] X * X * .if cond \{\ X * command X * ... \} X */ X p = skipwd (p); X p = skipbl (p); X not_cond = 0; X if (*p == '!') X { X p++; X not_cond = 1; X } X if (islower (*p) && isspace (*(p+1))) X { X /* X * single char: n=nroff,t=troff,e=evenpage,o=oddpage X */ X c = *p; X switch (c) X { X case 'n': /* if nroff... (always T) */ X p = skipwd (p); X p = skipbl (p); X X if (debugging) X fprintf (err_stream, X "***%s.comand: p=|%s|\n",myname, p); X X if (*p != EOS && not_cond == 0) X { X if (*p == '\\' && *(p+1) == '{') X { X read_if (); X } X else X { X if (*p == dc.cmdchr) X comand (p); X else X { X if (*p == '\"') X p++; X if (*p == ' ') X robrk (); X text (p); X } X } X } X break; X case 't': /* if troff... (always F) */ X p = skipwd (p); X p = skipbl (p); X X if (debugging) X fprintf (err_stream, X "***%s.comand: p=|%s|\n",myname, p); X X if (*p != EOS && not_cond != 0) X { X if (*p == '\\' && *(p+1) == '{') X { X read_if (); X } X else X { X if (*p == dc.cmdchr) X comand (p); X else X { X if (*p == '\"') X p++; X if (*p == ' ') X robrk (); X text (p); X } X } X } X break; X case 'e': /* if even page... */ X p = skipwd (p); X p = skipbl (p); X X if (debugging) X fprintf (err_stream, X "***%s.comand: p=|%s|\n",myname, p); X X X if (((pg.curpag % 2) == 0 && not_cond == 0) X || ((pg.curpag % 2) != 0 && not_cond != 0)) X { /* could be newpag, too */ X if (*p == '\\' && *(p+1) == '{') X { X read_if (); X } X else X { X if (*p == dc.cmdchr) X comand (p); X else X { X if (*p == '\"') X p++; X if (*p == ' ') X robrk (); X text (p); X } X } X } X break; X case 'o': /* if odd page... */ X p = skipwd (p); X p = skipbl (p); X X if (debugging) X fprintf (err_stream, X "***%s.comand: p=|%s|\n",myname, p); X X X if (((pg.curpag % 2) == 1 && not_cond == 0) X || ((pg.curpag % 2) != 1 && not_cond != 0)) X { X if (*p == '\\' && *(p+1) == '{') X { X read_if (); X } X else X { X if (*p == dc.cmdchr) X comand (p); X else X { X if (*p == '\"') X p++; X if (*p == ' ') X robrk (); X text (p); X } X } X } X break; X } X } X else if (*p == '\'' || *p == '/' || *p == '\"') X { X /* X * compare strings. we need to interpolate here X */ X c = *p; X ps1 = ++p; X while (*p != EOS && *p != c) X p++; X *p = EOS; X ps2 = ++p; X while (*p != EOS && *p != c) X p++; X *p = EOS; X X if (debugging) X fprintf (err_stream, X "***%s.comand: strcmp (ps1=|%s|,ps2=|%s|)\n", X myname, ps1, ps2); X X if ((!strcmp (ps1, ps2) && not_cond == 0) X || ( strcmp (ps1, ps2) && not_cond != 0)) X { X p++; X p = skipbl (p); X X if (*p == '\\' && *(p+1) == '{') X { X read_if (); X } X else X { X if (*p == dc.cmdchr) X comand (p); X else X { X if (*p == '\"') X p++; X if (*p == ' ') X robrk (); X text (p); X } X } X } X } X else X { X /* X * number X */ X X if (debugging) X fprintf (err_stream, X "***%s.comand: p=|%s|\n",myname, p); X X val = getnumeric (p); X if ((val > 0 && not_cond == 0) X || (val <= 0 && not_cond != 0)) X { X p = skipwd (p); X p = skipbl (p); X X if (*p == '\\' && *(p+1) == '{') X { X read_if (); X } X else X { X if (*p == dc.cmdchr) X comand (p); X else X { X if (*p == '\"') X p++; X if (*p == ' ') X robrk (); X text (p); X } X } X } X } X break; X case IG: X /* X * ignore input lines X * X * .ig name X */ X val = getval (p, &argtyp); X ignoring = TRUE; X defmac (p, sofile[dc.flevel]); X break; X case IN: X /* X * indenting X * X * .in [+/-N] X */ X val = getval (p, &argtyp); X set (&dc.inval, val, argtyp, 0, 0, dc.rmval - 1); X set_ireg (".i", dc.inval, 0); X dc.tival = dc.inval; X break; X case JU: X /* X * justify X * X * .ju X */ X dc.juval = YES; X break; X case LG: X /* X * ligature (IGNORED) X * X * .lg [N] X */ X break; X case LL: X /* X * line length X * X * .ll [+/-N] X * .rm [+/-N] X */ X val = getval (p, &argtyp); X set (&dc.rmval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE); X set (&dc.llval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE); X set_ireg (".l", dc.llval, 0); X break; X case LS: X /* X * line spacing X * X * .ls [+/-N=+1] X */ X val = getval (p, &argtyp); X set (&dc.lsval, val, argtyp, 1, 1, HUGE); X set_ireg (".v", dc.lsval, 0); X break; X case LT: X /* X * title length X * X * .lt N X */ X val = getval (p, &argtyp); X set (&dc.ltval, val, argtyp, PAGEWIDTH, 0, HUGE); X pg.ehlim[RIGHT] = dc.ltval; X pg.ohlim[RIGHT] = dc.ltval; X break; X case M1: X /* X * topmost margin X * X * .m1 N X */ X val = getval (p, &argtyp); X set (&pg.m1val, val, argtyp, 2, 0, HUGE); X break; X case M2: X /* X * second top margin X * X * .m2 N X */ X val = getval (p, &argtyp); X set (&pg.m2val, val, argtyp, 2, 0, HUGE); X break; X case M3: X /* X * 1st bottom margin X * X * .m3 N X */ X val = getval (p, &argtyp); X set (&pg.m3val, val, argtyp, 2, 0, HUGE); X pg.bottom = pg.plval - pg.m4val - pg.m3val; X break; X case M4: X /* X * bottom-most marg X * X * .m4 N X */ X val = getval (p, &argtyp); X set (&pg.m4val, val, argtyp, 2, 0, HUGE); X pg.bottom = pg.plval - pg.m4val - pg.m3val; X break; X case MACRO: X /* X * macro expansion X * X * (internal) X */ X maceval (p, macexp); X break; X case MC: X /* X * margin character (change bars) X * X * .mc [c [N]] X * X * right margin only, default 0.2i X */ X val = getval (p, &argtyp); X if (argtyp == '\r' || argtyp == '\n') X mc_ing = FALSE; /* turn off... */ X else X { X mc_ing = TRUE; /* turn on... */ X mc_space = 2; /* force these for now... */ X mc_char = argtyp; /* single char only!!! */ X X p = skipwd (p); X p = skipbl (p); X X val = getval (p, &argtyp); X set (&mc_space, val, argtyp, 2, 0, dc.llval); X } X break; X case NA: X /* X * no adjust X * X * .na X */ X dc.adjval = ADJ_OFF; X dc.juval = NO; X break; X case NE: X /* X * need n lines X * X * .ne N X */ X val = getval (p, &argtyp); X robrk (); X if ((pg.bottom - pg.lineno + 1) < (val * dc.lsval)) X { X space (HUGE); X } X break; X case NF: X /* X * no fill X * X * .nf X */ X robrk (); X dc.fill = NO; X break; X case NJ: X /* X * no justify X * X * .nj X */ X dc.juval = NO; X break; X case NR: X /* X * set number reg X * X * .nr R +/-N M X */ X val = getval (p, &argtyp); X p = skipwd (p); X p = skipbl (p); X if (!isalpha (*p)) X { X fprintf (err_stream, X "***%s: invalid or missing number register name\n", X myname); X } X else X { X /* X * indx is the register, R, and val is the final X * value (default = 0). getval does skipwd,skipbl X */ X indx = tolower (*p) - 'a'; X val = getval (p, &argtyp); X set (&dc.nr[indx], val, argtyp, 0, -INFINITE, INFINITE); X X /* X * now get autoincrement M, if any (default = 1). X * getval does skipwd,skipbl X */ X p = skipwd (p); X p = skipbl (p); X val = getval (p, &argtyp); X set (&dc.nrauto[indx], val, '1', 1, -INFINITE, INFINITE); X } X break; X case OF: X /* X * odd footer X * X * .of "a" "b" "c" X */ X val = getval (p, &argtyp); X gettl (p, pg.ofoot, &pg.oflim[0]); X break; X case OH: X /* X * odd header X * X * .oh "a" "b" "c" X */ X val = getval (p, &argtyp); X gettl (p, pg.ohead, &pg.ohlim[0]); X break; X case PC: X /* X * page number char X * X * .pc [c=NULL] X */ X val = getval (p, &argtyp); X if (argtyp == '\r' || argtyp == '\n') X dc.pgchr = EOS; X else X dc.pgchr = argtyp; X break; X case PL: X /* X * page length X * X * .pl N X */ X val = getval (p, &argtyp); X set (&pg.plval, X val, X argtyp, X PAGELEN, 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 break; X case PM: X /* X * print macro names and sizes X * X * .pm [t] X */ X val = getval (p, &argtyp); X if (argtyp == '\r' || argtyp == '\n') X printmac (0); X else if (argtyp == 't') X printmac (1); X else if (argtyp == 'T') X printmac (2); X else X printmac (0); X break; X case PN: X /* X * page number X * X * .pn N X */ X val = getval (p, &argtyp); X tmp = pg.curpag; X set (&pg.curpag, val - 1, argtyp, tmp, -HUGE, HUGE); X pg.newpag = pg.curpag + 1; X set_ireg ("%", pg.newpag, 0); X break; X case PO: X /* X * page offset X * X * .po N X */ X val = getval (p, &argtyp); X set (&pg.offset, val, argtyp, 0, 0, HUGE); X set_ireg (".o", pg.offset, 0); X break; X case PS: X /* X * point size (IGNORED) X * X * .ps +/-N X */ X break; X case RR: X /* X * unset number reg X * X * .rr R X */ X val = getval (p, &argtyp); X p = skipwd (p); X p = skipbl (p); X if (!isalpha (*p)) X { X fprintf (err_stream, X "***%s: invalid or missing number register name\n", X myname); X } X else X { X indx = tolower (*p) - 'a'; X val = 0; X set (&dc.nr[indx], val, argtyp, 0, -HUGE, HUGE); X } X break; X case SO: X /* X * source file X * X * .so name X */ X val = getval (p, &argtyp); X p = skipwd (p); X p = skipbl (p); X if (getwrd (p, name) == 0) X break; X if (dc.flevel + 1 >= Nfiles) X { X fprintf (err_stream, X "***%s: .so commands nested too deeply\n", X myname); X err_exit (-1); X } X if ((sofile[dc.flevel + 1] = fopen (name, "r")) == NULL_FPTR) X { X fprintf (err_stream, X "***%s: unable to open %s\n", myname, name); X err_exit (-1); X } X dc.flevel += 1; X break; X case SP: X /* X * space X * X * .sp [N=1] X */ X val = getval (p, &argtyp); X set (&spval, val, argtyp, 1, 0, HUGE); X space (spval); X break; X case SS: X /* X * space char size (IGNORED) X * X * .ss N X */ X break; X case TI: X /* X * temporary indent X * X * .ti [+/-N] X */ X val = getval (p, &argtyp); X robrk (); X set (&dc.tival, val, argtyp, 0, 0, dc.rmval); X break; X case UL: X /* X * underline X * X * .ul [N] X */ X val = getval (p, &argtyp); X set (&dc.ulval, val, argtyp, 0, 1, HUGE); X dc.cuval = dc.boval = 0; X break; X } X} X X X X X X/*------------------------------*/ X/* comtyp */ X/*------------------------------*/ Xcomtyp (p, m) Xregister char *p; Xchar *m; X{ X X/* X * decodes nro command and returns its associated value. X * ptr "p" is incremented (and returned) X */ X X register char c1; X register char c2; X char *s; X char macnam[MNLEN]; X X /* X * quick check: if null, ignore X */ X if (*p == EOS) X return (COMMENT); X X /* X * skip past dot and any whitespace X */ X p++; X while (*p && (*p == ' ' || *p == '\t')) X p++; X if (*p == '\0') X return (COMMENT); X X /* X * First check to see if the command is a macro. If it is, X * truncate to two characters and return expansion in m X * (i.e. the text of the macro). Note that upper and lower X * case characters are handled differently. X */ X getwrd (p, macnam); X macnam[2] = EOS; X if ((s = getmac (macnam)) != NULL_CPTR) X { X strcpy (m, s); X return (MACRO); X } X c1 = *p++; X c2 = *p; X if (c1 == '\\' && c2 == '\"') return (COMMENT); X if (c1 == 'a' && c2 == 'd') return (AD); X if (c1 == 'a' && c2 == 'f') return (AF); X if (c1 == 'b' && c2 == 'd') return (BD); X if (c1 == 'b' && c2 == 'o') return (BO); X if (c1 == 'b' && c2 == 'p') return (BP); X if (c1 == 'b' && c2 == 'r') return (BR); X if (c1 == 'b' && c2 == 's') return (BS); X if (c1 == 'c' && c2 == '2') return (C2); X if (c1 == 'c' && c2 == 'c') return (CC); X if (c1 == 'c' && c2 == 'e') return (CE); X if (c1 == 'c' && c2 == 's') return (CS); X if (c1 == 'c' && c2 == 'u') return (CU); X if (c1 == 'd' && c2 == 'e') return (DE); X if (c1 == 'd' && c2 == 's') return (DS); X if (c1 == 'e' && c2 == 'c') return (EC); X if (c1 == 'e' && c2 == 'f') return (EF); X if (c1 == 'e' && c2 == 'h') return (EH); X if (c1 == 'e' && c2 == 'n') return (EN); X if (c1 == '.') return (EN); X if (c1 == 'e' && c2 == 'o') return (EO); X if (c1 == 'e' && c2 == 'x') return (EX); X if (c1 == 'f' && c2 == 'i') return (FI); X if (c1 == 'f' && c2 == 'l') return (FL); X if (c1 == 'f' && c2 == 'o') return (FO); X if (c1 == 'f' && c2 == 't') return (FT); X if (c1 == 'h' && c2 == 'e') return (HE); X if (c1 == 'i' && c2 == 'f') return (IF); X/* if (c1 == 'i' && c2 == 'e') return (IE);*/ X/* if (c1 == 'e' && c2 == 'l') return (EL);*/ X if (c1 == 'i' && c2 == 'g') return (IG); X if (c1 == 'i' && c2 == 'n') return (IN); X if (c1 == 'j' && c2 == 'u') return (JU); X if (c1 == 'l' && c2 == 'g') return (LG); X if (c1 == 'l' && c2 == 'l') return (LL); X if (c1 == 'l' && c2 == 's') return (LS); X if (c1 == 'l' && c2 == 't') return (LT); X if (c1 == 'm' && c2 == '1') return (M1); X if (c1 == 'm' && c2 == '2') return (M2); X if (c1 == 'm' && c2 == '3') return (M3); X if (c1 == 'm' && c2 == '4') return (M4); X if (c1 == 'm' && c2 == 'c') return (MC); X if (c1 == 'n' && c2 == 'a') return (NA); X if (c1 == 'n' && c2 == 'e') return (NE); X if (c1 == 'n' && c2 == 'f') return (NF); X if (c1 == 'n' && c2 == 'j') return (NJ); X if (c1 == 'n' && c2 == 'r') return (NR); X if (c1 == 'o' && c2 == 'f') return (OF); X if (c1 == 'o' && c2 == 'h') return (OH); X if (c1 == 'p' && c2 == 'c') return (PC); X if (c1 == 'p' && c2 == 'l') return (PL); X if (c1 == 'p' && c2 == 'm') return (PM); X if (c1 == 'p' && c2 == 'n') return (PN); X if (c1 == 'p' && c2 == 'o') return (PO); X if (c1 == 'p' && c2 == 's') return (PS); X if (c1 == 'r' && c2 == 'm') return (RM); X if (c1 == 'r' && c2 == 'r') return (RR); X if (c1 == 's' && c2 == 'o') return (SO); X if (c1 == 's' && c2 == 'p') return (SP); X if (c1 == 's' && c2 == 's') return (SS); X if (c1 == 't' && c2 == 'i') return (TI); X if (c1 == 't' && c2 == 'l') return (TL); X if (c1 == 'u' && c2 == 'l') return (UL); X X if (c1 == 't' && c2 == 'r') return (TR); X if (c1 == 'f' && c2 == 'c') return (FC); X X return (UNKNOWN); X} X X X X X X/*------------------------------*/ X/* gettl */ X/*------------------------------*/ Xgettl (p, q, limit) Xregister char *p; Xregister char *q; Xint *limit; X{ X X/* X * get header or footer title X */ X X /* X * skip forward a word... X */ X p = skipwd (p); X p = skipbl (p); X X /* X * copy and set limits X */ X strcpy (q, p); X limit[LEFT] = dc.inval; X limit[RIGHT] = dc.rmval; X} X X X X X X/*------------------------------*/ X/* getval */ X/*------------------------------*/ Xgetval (p, p_argtyp) Xregister char *p; Xregister char *p_argtyp; X{ X X/* X * retrieves optional argument following command. X * returns positive integer value with sign (if any) X * saved in character addressed by p_argt. X */ X X p = skipwd (p); X p = skipbl (p); X *p_argtyp = *p; X if ((*p == '+') || (*p == '-')) X ++p; X return (ctod (p)); X} X X X X X X/*------------------------------*/ X/* getnumeric */ X/*------------------------------*/ X X#define N_ADD 0 X#define N_SUB 1 X#define N_MUL 2 X#define N_DIV 3 X#define N_MOD 4 X#define N_LT 5 X#define N_GT 6 X#define N_LE 7 X#define N_GE 8 X#define N_EQ 9 X#define N_AND 10 X#define N_OR 11 X X Xgetnumeric (p) Xregister char *p; X{ X X/* X * retrieves numeric argument. will parse for number registers, X * constants, operations, and logical comparisons. no imbeded spaces! X * start at p (don't skip) X */ X X char name[10]; X int val; X int thisval; X int autoinc; X char buf[256]; X char *pbuf; X int next_op; X int nreg; X X val = 0; X next_op = N_ADD; X while (*p != EOS && !isspace (*p)) X { X if (!strncmp (p, "\\n", 2)) X { X if (debugging) X fprintf (err_stream, X "***%s.getnumeric: found number reg...\n",myname); X /* X * number register X */ X autoinc = 0; X p += 2; X if (*p == '+') X { X autoinc = 1; X p++; X } X else if (*p == '-') X { X autoinc = -1; X p++; X } X if (isalpha (*p)) X { X /* X * \nx form. find reg (a-z) X */ X nreg = tolower (*p) - 'a'; X p++; X X /* X * was this \n+x or \n-x? if so, do the X * auto incr X */ X if (autoinc > 0) X dc.nr[nreg] += dc.nrauto[nreg]; X else if (autoinc < 0) X dc.nr[nreg] -= dc.nrauto[nreg]; X X X val = do_oper (val, next_op, dc.nr[nreg]); X } X else if (*p == '%') X { X /* X * \n% form. find index into reg struct X */ X nreg = findreg ("%"); X p++; X if (nreg < 0) X { X fprintf (err_stream, X "***%s: no register match\n", X myname); X err_exit (-1); X } X X /* X * was this \n+% or \n-%? if so, do the X * auto incr X */ X if (autoinc > 0) X rg[nreg].rval += rg[nreg].rauto; X else if (autoinc < 0) X rg[nreg].rval -= rg[nreg].rauto; X X X val = do_oper (val, next_op, rg[nreg].rval); X } X else if (*p == '(') X { X /* X * \n(xx form. find index into reg struct X */ X p++; X name[0] = *p++; X name[1] = *p++; X if (name[1] == ' ' || name[1] == '\t' X || name[1] == '\n' || name[1] == '\r') X name[1] = '\0'; X name[2] = '\0'; X nreg = findreg (name); X if (nreg < 0) X { X fprintf (err_stream, X "***%s: no register match\n", X myname); X err_exit (-1); X } X X X /* X * was this \n+(xx or \n-(xx? if so, do the X * auto incr X */ X if (rg[nreg].rflag & RF_WRITE) X { X if (autoinc > 0) X rg[nreg].rval += rg[nreg].rauto; X else if (autoinc < 0) X rg[nreg].rval -= rg[nreg].rauto; X } X X val = do_oper (val, next_op, rg[nreg].rval); X } X } X else if (isdigit (*p)) X { X pbuf = buf; X while (1) X { X if (*p == EOS || isspace (*p)) X break; X if (*p == '\\') X break; X if (iscond (*p)) X break; X if (isoper (*p)) X break; X X *pbuf++ = *p++; X } X *pbuf = EOS; X X if (debugging) X fprintf (err_stream, X "***%s.getnumeric: buf:|%s| next_op:%d val:%d\n", X myname,buf,next_op,val); X X thisval = ctod (buf); X val = do_oper (val, next_op, thisval); X if (debugging) X fprintf (err_stream, X "***%s.getnumeric: thisval:%d val:%d\n", X myname,thisval,val); X } X X /* X * p should now be at the next thing, either a X * space, a null, or an operator X */ X if (*p == EOS || isspace (*p)) X break; X switch (*p) X { X case '+': X next_op = N_ADD; X p++; X break; X case '-': X next_op = N_SUB; X p++; X break; X case '*': X next_op = N_MUL; X p++; X break; X case '/': X next_op = N_DIV; X p++; X break; X case '%': X next_op = N_MOD; X p++; X break; X case '&': X next_op = N_AND; X p++; X break; X case ':': X next_op = N_OR; X p++; X break; X case '<': X p++; X if (*p == '=') X { X p++; X next_op = N_LE; X } X else X next_op = N_LT; X break; X case '>': X p++; X if (*p == '=') X { X p++; X next_op = N_GE; X } X else X next_op = N_GT; X break; X case '=': X p++; X if (*p == '=') X p++; X next_op = N_EQ; X break; X } X } X return (val); X} X X X X X X/*------------------------------*/ X/* do_oper */ X/*------------------------------*/ Xdo_oper (first, oper, second) Xint first; Xint oper; Xint second; X{ X int val; X X if (debugging) X fprintf (err_stream, X "***%s.do_oper: first:%d op:%d second:%d\n", X myname, first, oper, second); X X switch (oper) X { X case N_ADD: X val = first + second; X break; X case N_SUB: X val = first - second; X break; X case N_MUL: X val = first * second; X break; X case N_DIV: X val = first / second; X break; X case N_MOD: X val = first % second; X break; X case N_LT: X val = ((first < second) ? 1 : 0); X break; X case N_GT: X val = ((first > second) ? 1 : 0); X break; X case N_LE: X val = ((first <= second) ? 1 : 0); X break; X case N_GE: X val = ((first >= second) ? 1 : 0); X break; X case N_EQ: X val = ((first == second) ? 1 : 0); X break; X case N_AND: X val = ((first && second) ? 1 : 0); X break; X case N_OR: X val = ((first || second) ? 1 : 0); X break; X } X X return (val); X} X X X X X X/*------------------------------*/ X/* set */ X/*------------------------------*/ Xset (param, val, type, defval, minval, maxval) Xregister int *param; Xregister int val; Xregister char type; Xregister int defval; Xregister int minval; Xregister int maxval; X{ X X/* X * set parameter and check range. this is for basically all commands X * which take interger args X * X * no param (i.e. \r or \n) means reset default X * + means param += val (increment) X * - means param -= val (decrement) X * anything else makes an assignment within the defined numerical limits X * X * examples: X * X * .nr a 14 set register 'a' to 14 X * .nr a +1 increment register 'a' by 1 X * .nr a reset register 'a' to default value (0) X */ X X switch (type) X { X case '\r': X case '\n': X *param = defval; X break; X case '+': X *param += val; X break; X case '-': X *param -= val; X break; X default: X *param = val; X break; X } X *param = min (*param, maxval); X *param = max (*param, minval); X} X X X X X X/*------------------------------*/ X/* set_ireg */ X/*------------------------------*/ Xset_ireg (name, val, opt) Xregister char *name; Xregister int val; Xregister int opt; /* 0=internal, 1=user set */ X{ X X/* X * set internal register "name" to val. ret 0 if ok, else -1 if reg not X * found or 1 if read only X */ X X register int nreg; X X nreg = findreg (name); X if (nreg < 0) X return (-1); X X if ((rg[nreg].rflag & RF_WRITE) || (opt == 0)) X { X rg[nreg].rval = val; X X return (0); X } X X return (1); X} X X X X X X/*------------------------------*/ X/* read_if */ X/*------------------------------*/ Xread_if () X{ X X/* X * read input while in if statement. stop when a line starts with \} X */ X X char ibuf[MAXLINE]; X char *pp; X X while (getlin (ibuf, sofile[dc.flevel]) != EOF) X { X if (debugging) X fprintf (err_stream, X "***%s.read_if: ibuf=|%s|\n",myname,ibuf); X X pp = skipbl (ibuf); X if (*pp == '\\' && *(pp+1) == '}') X return; 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 pp = ibuf; X while (*pp != EOS) X { X if (*pp == '\\' && *(pp+1) == '}') X return; X } X } X} END_OF_command.c if test 30522 -ne `wc -c config.h <<'END_OF_config.h' X#ifndef CONFIG_H X#define CONFIG_H X X/* X * for diffent os, define tos, unix, or minix. for gemdos, pick X * a compiler (alcyon, mwc, etc). see makefile for VERSFLAGS. X * X * for atari TOS, do: cc -Dtos -Dalcyon ... X * X * for minix, do: cc -D_MINIX -D_ST ... (ST minix) X * cc -D_MINIX ... (PC minix) X * X * for unix, do: cc -Dunix ... (generic) X * cc -Dunix -DBSD... (BSD) X * X * note: so far there is no specific ST minix version. -D_ST is ignored. X * X * nroff uses index/rindex. you may need -Dindex=strchr -Drindex=strrchr X * as well. this file is included in "nroff.h" which gets included in all X * sources so any definitions you need should be added here. X * X * all os-dependent code is #ifdef'ed with GEMDOS, MINIX_ST, MINIX_PC, X * MINIX, or UNIX. most of the differences deal with i/o only. X */ X#ifdef ALCYON X# ifndef tos X# define tos X# endif X# ifndef alcyon X# define alcyon X# endif X#endif X X#ifdef tos X# define GEMDOS X# undef minix X# undef unix X# undef MINIX X# undef MINIX_ST X# undef MINIX_PC X# undef UNIX X/*#define register*/ X#endif X X#ifdef alcyon X# ifndef ALCYON X# define ALCYON /* for gemdos version, alcyon C */ X# endif X# ifndef GEMDOS X# define GEMDOS X# endif X#endif X X#ifdef minix X# ifndef _MINIX X# define _MINIX X# endif X#endif X X#ifdef _MINIX X# define MINIX X# undef tos X# undef unix X# undef GEMDOS X# undef MINIX_ST X# undef MINIX_PC X# undef UNIX X# ifdef _ST X# ifndef atariST X# define atariST X# endif X# endif X# ifdef atariST X# define MINIX_ST X# else X# define MINIX_PC X# endif X#endif X X#ifdef unix X/* just in case does not define it (slightly different anyway) */ X#define tolower(x) (isupper(x)?((x)-'A'+'a'):(x)) X# undef tos X# undef minix X# undef _MINIX X# undef GEMDOS X# undef _ST X# undef MINIX_ST X# undef MINIX_PC X# ifndef UNIX X# define UNIX X# endif X#endif X X#endif /*CONFIG_H*/ X END_OF_config.h if test 1819 -ne `wc -c escape.c <<'END_OF_escape.c' X/* X * escape.c - Escape and special character input processing portion of X * 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/* expesc */ X/*------------------------------*/ Xexpesc (p, q) Xchar *p; Xchar *q; X{ X X/* X * Expand escape sequences X */ X X register char *s; X register char *t; X register char *pstr; X register int i; X register int val; X register int autoinc; X char c; X char fs[5]; /* for font change */ X char nrstr[20]; X char fmt[20]; X char name[10]; X int nreg; X char *pfs; X int inc; X int tmp; X char delim; X X X s = p; X t = q; X X X /* X * if escape parsing is not on, just copy string X */ X if (dc.escon == NO) X { X while (*s != EOS) X { X *t++ = *s++; X } X *t = EOS; X strcpy (p, q); X X return; X } X X X /* X * do it... X */ X while (*s != EOS) X { X if (*s != dc.escchr) X { X /* X * not esc, continue... X */ X *t++ = *s++; X } X X X else if (*(s + 1) == dc.escchr) X { X /* X * \\ escape escape X */ X *t++ = *s++; X ++s; X } X X X else if (*(s + 1) == 'n') X { X /* X * \nx, \n(xx register X * X * first check for \n+... or \n-... (either form) X */ X s += 2; X autoinc = 0; X if (*s == '+') X { X autoinc = 1; X s += 1; X } X if (*s == '-') X { X autoinc = -1; X s += 1; X } X X X X /* X * was this \nx or \n(xx form? X */ X if (isalpha (*s)) X { X /* X * \nx form. find reg (a-z) X */ X nreg = tolower (*s) - 'a'; X X X /* X * was this \n+x or \n-x? if so, do the X * auto incr X */ X if (autoinc > 0) X dc.nr[nreg] += dc.nrauto[nreg]; X else if (autoinc < 0) X dc.nr[nreg] -= dc.nrauto[nreg]; X X /* X * display format X */ X if (dc.nrfmt[nreg] == '1') X { X /* X * normal decimal digits X */ X t += itoda (dc.nr[nreg], t, 6) - 1; X } X else if (dc.nrfmt[nreg] == 'i') X { X /* X * lower roman X */ X t += itoroman (dc.nr[nreg], t, 24) - 1; X } X else if (dc.nrfmt[nreg] == 'I') X { X /* X * upper roman X */ X t += itoROMAN (dc.nr[nreg], t, 24) - 1; X } X else if (dc.nrfmt[nreg] == 'a') X { X /* X * lower letters X */ X t += itoletter (dc.nr[nreg], t, 12) - 1; X } X else if (dc.nrfmt[nreg] == 'A') X { X /* X * upper letters X */ X t += itoLETTER (dc.nr[nreg], t, 12) - 1; X } X else if (dc.nrfmt[nreg] & 0x80) X { X /* X * zero-filled decimal X */ X sprintf (fmt, "%%0%dld", X (int)(dc.nrfmt[nreg] & 0x7F)); X fmt[5] = '\0'; X sprintf (nrstr, fmt, (long) dc.nr[nreg]); X tmp = dc.nrfmt[nreg] & 0x7F; X nrstr[tmp] = '\0'; X X strcpy (t, nrstr); X t += strlen (nrstr); X } X else X { X /* X * normal (default) X */ X t += itoda (dc.nr[nreg], t, 6) - 1; X } X ++s; X } X else if (*s == '%') X { X /* X * \n% form. find index into reg struct X */ X nreg = findreg ("%"); X if (nreg < 0) X { X fprintf (err_stream, X "***%s: no register match\n", X myname); X err_exit (-1); X } X X X /* X * was this \n+% or \n-%? if so, do the X * auto incr X */ X if (autoinc > 0) X rg[nreg].rval += rg[nreg].rauto; X else if (autoinc < 0) X rg[nreg].rval -= rg[nreg].rauto; X X X /* X * display format X */ X if (rg[nreg].rfmt == '1') X { X /* X * normal decimal digits X */ X t += itoda (rg[nreg].rval, t, 6) - 1; X } X else if (rg[nreg].rfmt == 'i') X { X /* X * lower roman X */ X t += itoroman (rg[nreg].rval, t, 24) - 1; X } X else if (rg[nreg].rfmt == 'I') X { X /* X * upper roman X */ X t += itoROMAN (rg[nreg].rval, t, 24) - 1; X } X else if (rg[nreg].rfmt == 'a') X { X /* X * lower letters X */ X t += itoletter (rg[nreg].rval, t, 12) - 1; X } X else if (rg[nreg].rfmt == 'A') X { X /* X * upper letters X */ X t += itoLETTER (rg[nreg].rval, t, 12) - 1; X } X else if (rg[nreg].rfmt & 0x80) X { X /* X * zero-filled decimal X */ X sprintf (fmt, "%%0%dld", X (int)(rg[nreg].rfmt & 0x7F)); X fmt[5] = '\0'; X sprintf (nrstr, fmt, (long) rg[nreg].rval); X tmp = rg[nreg].rfmt & 0x7F; X nrstr[tmp] = '\0'; X X strcpy (t, nrstr); X t += strlen (nrstr); X } X else X { X /* X * normal (default) X */ X t += itoda (rg[nreg].rval, t, 6) - 1; X } X s += 1; X } X else if (*s == '(') X { X /* X * \n(xx form. find index into reg struct X */ X s += 1; X name[0] = *s; X name[1] = *(s + 1); X if (name[1] == ' ' || name[1] == '\t' X || name[1] == '\n' || name[1] == '\r') X name[1] = '\0'; X name[2] = '\0'; X nreg = findreg (name); X if (nreg < 0) X { X fprintf (err_stream, X "***%s: no register match\n", X myname); X err_exit (-1); X } X X X /* X * was this \n+(xx or \n-(xx? if so, do the X * auto incr X */ X if (rg[nreg].rflag & RF_WRITE) X { X if (autoinc > 0) X rg[nreg].rval += rg[nreg].rauto; X else if (autoinc < 0) X rg[nreg].rval -= rg[nreg].rauto; X } X X X /* X * display format X */ X if (rg[nreg].rfmt == '1') X { X /* X * normal decimal digits X */ X t += itoda (rg[nreg].rval, t, 6) - 1; X } X else if (rg[nreg].rfmt == 'i') X { X /* X * lower roman X */ X t += itoroman (rg[nreg].rval, t, 24) - 1; X } X else if (rg[nreg].rfmt == 'I') X { X /* X * upper roman X */ X t += itoROMAN (rg[nreg].rval, t, 24) - 1; X } X else if (rg[nreg].rfmt == 'a') X { X /* X * lower letters X */ X t += itoletter (rg[nreg].rval, t, 12) - 1; X } X else if (rg[nreg].rfmt == 'A') X { X /* X * upper letters X */ X t += itoLETTER (rg[nreg].rval, t, 12) - 1; X } X else if (rg[nreg].rfmt & 0x80) X { X /* X * zero-filled decimal X */ X sprintf (fmt, "%%0%dld", X (int)(rg[nreg].rfmt & 0x7F)); X fmt[5] = '\0'; X sprintf (nrstr, fmt, (long) rg[nreg].rval); X tmp = rg[nreg].rfmt & 0x7F; X nrstr[tmp] = '\0'; X X strcpy (t, nrstr); X t += strlen (nrstr); X } X else X { X /* X * normal (default) X */ X t += itoda (rg[nreg].rval, t, 6) - 1; X } X s += 2; X } X } X X X else if (*(s + 1) == '\"') X { X /* X * \" comment X */ X *s = EOS; X *t = *s; X X return; X } X X X else if (*(s + 1) == '*') X { X /* X * \*x, \*(xx string X */ X s += 2; X if (*s == '(') X { X /* X * \*(xx form X */ X s += 1; X name[0] = *s; X name[1] = *(s + 1); X name[2] = '\0'; X pstr = getstr (name); X if (!pstr) X { X fprintf (err_stream, X "***%s: string not found\n", X myname); X err_exit (-1); X } X while (*pstr) X *t++ = *pstr++; X s += 2; X } X else X { X /* X * \*x form X */ X name[0] = *s; X name[1] = '\0'; X pstr = getstr (name); X if (!pstr) X { X fprintf (err_stream, X "***%s: string not found\n", X myname); X err_exit (-1); X } X while (*pstr) X *t++ = *pstr++; X s += 1; X } X } X X X else if (*(s + 1) == 'f') X { X /* X * \fx font X */ X s += 2; X pfs = fs; /* set up ret string */ X fs[0] = '\0'; X X /* X * it parses 1-2 char of s and returns esc seq for X * \fB and \fR (\fI is same as \fB) X */ X fontchange (*s, pfs); X X /* X * imbed the atari (vt52) escape seq X */ X while (*pfs) X *t++ = *pfs++; X ++s; /* skip B,I,R,S,P */ X } X X X else if (*(s + 1) == '(') X { X /* X * \(xx special char X */ X s += 2; X X /* X * it returns num char to skip and sets c to X * the ascii value of the char X */ X inc = specialchar (s, &c); X X /* X * skip proper num char in s and add c to target X */ X if (inc) X { X s += inc; X *t++ = c; X } X } X X X else if (*(s + 1) == 'e') X { X /* X * \e printable version of escape X */ X *t++ = dc.escchr; X s += 2; X } X X X else if (*(s + 1) == '`') X { X /* X * \` grave, like \(ga X */ X *t++ = 0x60; X s += 2; X } X X X else if (*(s + 1) == '\'') X { X /* X * \' accute, like \(aa X */ X s += 2; X *t++ = 0xBA; X } X X X else if (*(s + 1) == '-') X { X /* X * \- minus X */ X s += 2; X *t++ = 0x2D; X } X X X else if (*(s + 1) == '.') X { X /* X * \. period X */ X s += 2; X *t++ = 0x2E; X } X X X else if (*(s + 1) == ' ') X { X /* X * \(space) space X */ X s += 2; X *t++ = 0x20; X } X X X else if (*(s + 1) == '0') X { X /* X * \0 digital width space X */ X s += 2; X *t++ = 0x20; X } X X X else if (*(s + 1) == '|') X { X /* X * \| narrow width char (0 in nroff) X */ X s += 2; X } X X X else if (*(s + 1) == '^') X { X /* X * \^ narrow width char (0 in nroff) X */ X s += 2; X } X X X else if (*(s + 1) == '&') X { X /* X * \& non-printing zero width X */ X s += 2; X } X X X else if (*(s + 1) == '!') X { X /* X * \! transparent copy line X */ X s += 2; X } X X X else if (*(s + 1) == '$') X { X /* X * \$N interpolate arg 1<=N<=9 X */ X s += 2; X } X X X else if (*(s + 1) == '%') X { X /* X * \% hyphen X */ X s += 2; X *t++ = 0x2D; X *t++ = 0x2D; X } X X X else if (*(s + 1) == 'a') X { X /* X * \a X */ X s += 2; X } X X X else if (*(s + 1) == 'b') X { X /* X * \b'abc...' X */ X s += 2; X } X X X else if (*(s + 1) == 'c') X { X /* X * \c X */ X s += 2; X } X X X else if (*(s + 1) == 'd') X { X /* X * \d X */ X s += 2; X } X X X else if (*(s + 1) == 'h') X { X /* X * \h'N' horiz motion X */ X s += 2; X delim = *s++; X val = atoi (s); X for (i = 0; i < val; i++) X *t++ = ' '; X while (*s != delim) X { X if (*s == 0) X break; X s++; X } X if (*s) X s++; X X } X X X else if (*(s + 1) == 'k') X { X /* X * \kx X */ X s += 2; X } X X X else if (*(s + 1) == 'l') X { X /* X * \l'Nc' X */ X s += 2; X } X X X else if (*(s + 1) == 'L') X { X /* X * \L'Nc' X */ X s += 2; X } X X X else if (*(s + 1) == 'o') X { X /* X * \o'abc...' overstrike X */ X s += 2; X delim = *s++; X while (*s != EOS && *s != delim) X { X *t++ = *s++; X *t++ = 0x08; X } X s++; X } X X X else if (*(s + 1) == 'p') X { X /* X * \p X */ X s += 2; X } X X X else if (*(s + 1) == 'r') X { X /* X * \r X */ X s += 2; X } X X X else if (*(s + 1) == 's') X { X /* X * \sN,\s+-N X */ X s += 2; X } X X X else if (*(s + 1) == 't') X { X /* X * \t horizontal tab X */ X s += 2; X *t++ = 0x09; X } X X X else if (*(s + 1) == 'u') X { X /* X * \u X */ X s += 2; X } X X X else if (*(s + 1) == 'v') X { X /* X * \v'N' vert tab X */ X s += 2; X delim = *s++; X val = atoi (s); X for (i = 0; i < val; i++) X *t++ = 0x0A; X while (*s != delim) X { X if (*s == 0) X break; X s++; X } X if (*s) X s++; X } X X X else if (*(s + 1) == 'w') X { X /* X * \w'str' X */ X s += 2; X } X X X else if (*(s + 1) == 'x') X { X /* X * \x'N' X */ X s += 2; X } X X X else if (*(s + 1) == 'z') X { X /* X * \zc print c w/o spacing X */ X s += 2; X *t++ = *s++; X *t++ = 0x08; X } X X X else if (*(s + 1) == '{') X { X /* X * \{ X */ X s += 2; X } X X X else if (*(s + 1) == '}') X { X /* X * \} X */ X s += 2; X } X X X else if (*(s + 1) == '\n' || *(s + 1) == '\r') X { X /* X * \(newline) ignore newline X */ X s += 2; X } X X X else X { X /* X * \X any other character not above X */ X s += 1; X *t++ = *s++; X } X X } X X /* X * end the string and return it in original buf X */ X *t = EOS; X strcpy (p, q); X} X X X X X/*------------------------------*/ X/* specialchar */ X/*------------------------------*/ Xspecialchar (s, c) Xregister char *s; Xregister char *c; X{ X X/* X * handles \(xx escape sequences for special characters (atari-specific) X */ X X register char c1; X register char c2; X X c1 = *s; X c2 = *(s+1); X X /* X * symbols (std font) X */ X if (c1 == 'e' && c2 == 'm') {*c = 0x2D; return (2);} /* dash */ X if (c1 == 'h' && c2 == 'y') {*c = 0x2D; return (2);} /* hyphen */ X if (c1 == 'b' && c2 == 'u') {*c = 0xF9; return (2);} /* bullet */ X if (c1 == 's' && c2 == 'q') {*c = 0xF9; return (2);} /* square */ X if (c1 == 'r' && c2 == 'u') {*c = 0x5F; return (2);} /* rule */ X if (c1 == '1' && c2 == '2') {*c = 0xAB; return (2);} /* 1/2 */ X if (c1 == '1' && c2 == '4') {*c = 0xAC; return (2);} /* 1/4 */ X if (c1 == 'd' && c2 == 'e') {*c = 0xF8; return (2);} /* degree */ X if (c1 == 'd' && c2 == 'g') {*c = 0xBB; return (2);} /* dagger */ X if (c1 == 'f' && c2 == 'm') {*c = 0xBA; return (2);} /* dagger */ X if (c1 == 'c' && c2 == 't') {*c = 0x9B; return (2);} /* cent */ X if (c1 == 'c' && c2 == 'o') {*c = 0xBD; return (2);} /* copyrite */ X if (c1 == 'r' && c2 == 'g') {*c = 0xBE; return (2);} /* registered */ X if (c1 == 't' && c2 == 'm') {*c = 0xBF; return (2);} /* trademark */ X X if (c1 == 'p' && c2 == '2') {*c = 0xFD; return (2);} /* ^2 */ X if (c1 == 'p' && c2 == '3') {*c = 0xFE; return (2);} /* ^3 */ X if (c1 == 'p' && c2 == 'n') {*c = 0xFC; return (2);} /* ^n */ X if (c1 == 'a' && c2 == 'a') {*c = 0xBA; return (2);} /* acute */ X if (c1 == 'g' && c2 == 'a') {*c = 0x60; return (2);} /* grave */ X if (c1 == 'd' && c2 == 't') {*c = 0xFA; return (2);} /* dot */ X if (c1 == 'p' && c2 == 'p') {*c = 0xBC; return (2);} /* paragraph */ X if (c1 == '^' && c2 == 'g') {*c = 0x07; return (2);} /* ring bell */ X if (c1 == 'u' && c2 == 'a') {*c = 0x01; return (2);} /* up arrow */ X if (c1 == 'd' && c2 == 'a') {*c = 0x02; return (2);} /* dn arrow */ X if (c1 == '-' && c2 == '>') {*c = 0x03; return (2);} /* rt arrow */ X if (c1 == '<' && c2 == '-') {*c = 0x04; return (2);} /* lf arrow */ X if (c1 == 'd' && c2 == 'i') {*c = 0xF6; return (2);} /* divide */ X if (c1 == 's' && c2 == 'r') {*c = 0xFB; return (2);} /* sq root */ X if (c1 == '=' && c2 == '=') {*c = 0xF0; return (2);} /* == */ X if (c1 == '>' && c2 == '=') {*c = 0xF2; return (2);} /* >= */ X if (c1 == '<' && c2 == '=') {*c = 0xF3; return (2);} /* <= */ X if (c1 == '+' && c2 == '-') {*c = 0xF1; return (2);} /* +- */ X if (c1 == '~' && c2 == '=') {*c = 0xF7; return (2);} /* ~= */ X if (c1 == 'a' && c2 == 'p') {*c = 0x7E; return (2);} /* approx */ X if (c1 == 'n' && c2 == 'o') {*c = 0xAA; return (2);} /* not */ X if (c1 == 'm' && c2 == 'o') {*c = 0xEE; return (2);} /* member */ X if (c1 == 'c' && c2 == 'a') {*c = 0xEF; return (2);} /* intersect */ X if (c1 == 'c' && c2 == 'u') {*c = 0x55; return (2);} /* union */ X if (c1 == 'i' && c2 == '1') {*c = 0xF4; return (2);} /* integral1 */ X if (c1 == 'i' && c2 == '2') {*c = 0xF5; return (2);} /* integral2 */ X X if (c1 == 'b' && c2 == 'r') {*c = 0x7C; return (2);} /* box v rule */ X if (c1 == 'b' && c2 == 'v') {*c = 0x7C; return (2);} /* bold vert */ X if (c1 == 'p' && c2 == 'l') {*c = 0x2B; return (2);} /* math plus */ X if (c1 == 'm' && c2 == 'i') {*c = 0x2D; return (2);} /* math minus */ X if (c1 == 'e' && c2 == 'q') {*c = 0x3D; return (2);} /* math equal */ X if (c1 == '*' && c2 == '*') {*c = 0x2A; return (2);} /* math star */ X if (c1 == 's' && c2 == 'l') {*c = 0x2F; return (2);} /* slash */ X if (c1 == 'u' && c2 == 'l') {*c = 0x5F; return (2);} /* underrule */ X if (c1 == 's' && c2 == 'c') {*c = 0xDD; return (2);} /* section */ X X X /* X * greek X */ X if (c1 == '*' && c2 == 'a') {*c = 0xE0; return (2);} /* alpha */ X if (c1 == '*' && c2 == 'b') {*c = 0xE1; return (2);} /* beta */ X if (c1 == '*' && c2 == 'g') {*c = 0xE2; return (2);} /* gamma */ X if (c1 == '*' && c2 == 'd') {*c = 0x7F; return (2);} /* delta */ X if (c1 == '*' && c2 == 's') {*c = 0xE4; return (2);} /* sigma */ X if (c1 == '*' && c2 == 'p') {*c = 0xE3; return (2);} /* pi */ X if (c1 == '*' && c2 == 'm') {*c = 0xE6; return (2);} /* mu */ X X *c = ' '; X return (0); X} X X X X X/*------------------------------*/ X/* fontchange */ X/*------------------------------*/ Xfontchange (fnt, s) Xchar fnt; Xchar *s; X{ X X/* X * handles \fx font change escapes for R,B,I,S,P (atari-specific) X * resets current and last font in dc struct (last used for .ft X * with no args) X */ X X int tmp; X X *s = '\0'; X switch (fnt) X { X case 'R': /* Times Roman */ X if (dc.dofnt == YES) X strcpy (s, e_standout); X dc.lastfnt = dc.thisfnt; X dc.thisfnt = 1; X break; X case 'I': /* Times italic */ X if (dc.dofnt == YES) X strcpy (s, s_standout); X dc.lastfnt = dc.thisfnt; X dc.thisfnt = 2; X break; X case 'B': /* Times bold */ X if (dc.dofnt == YES) X strcpy (s, s_standout); X dc.lastfnt = dc.thisfnt; X dc.thisfnt = 3; X break; X case 'S': /* math/special */ X *s = '\0'; X dc.lastfnt = dc.thisfnt; X dc.thisfnt = 4; X break; X case 'P': /* previous (exchange) */ X if (dc.dofnt == YES) X { X if (dc.lastfnt == 1) X strcpy (s, e_standout); /* to R */ X else if (dc.lastfnt == 2) X strcpy (s, s_standout); /* to I */ X else if (dc.lastfnt == 3) X strcpy (s, s_standout); /* to B */ X else X *s = '\0'; /* nothing */ X } X X tmp = dc.thisfnt; /* swap this/last */ X dc.thisfnt = dc.lastfnt; X dc.lastfnt = tmp; X break; X default: X *s = '\0'; X break; X } X X set_ireg (".f", dc.thisfnt, 0); X} X X X X X X/*------------------------------*/ X/* findreg */ X/*------------------------------*/ Xfindreg (name) Xregister char *name; X{ X X/* X * find register named 'name' in pool. return index into array or -1 X * if not found. X */ X X register int i; X register char *prname; X X for (i = 0; i < MAXREGS; i++) X { X prname = rg[i].rname; X if (*prname == *name && *(prname + 1) == *(name + 1)) X break; X } X X return ((i < MAXREGS) ? i : -1); X} X X X X END_OF_escape.c if test 18010 -ne `wc -c