koreth@panarthea.ebay.sun.com (Steven Grimm) (11/15/89)
Submitted-by: rosenkra@hall.cray.com (Bill Rosenkranz) Posting-number: Volume 3, Issue 9 Archive-name: nroff/part02 part02/03 -bill rosenkra@hall.cray.com ------------cut here----------------cut here--------------------------------- #!/bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by hall!rosenkra on Sun Nov 12 16:35:33 CST 1989 # Contents: main.c command.c text.c io.c echo x - main.c sed 's/^@//' > "main.c" <<'@//E*O*F main.c//' /* * main.c - main for nroff word processor * * similar to Unix(tm) nroff or RSX-11M RNO. adaptation of text processor * given in "Software Tools", Kernighan and Plauger. * * adapted for atariST/TOS by Bill Rosenkranz 11/89 * net: rosenkra@hall.cray.com * CIS: 71460,17 * GENIE: W.ROSENKRANZ * * original author: * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * history: * * - Originally written in BDS C; * - Adapted for standard C by W. N. Paul * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz */ #define NRO_MAIN /* to define globals in nro.h */ #include <stdio.h> #ifdef ATARIST #include <sys\types.h> #include <sys\time.h> #else #include <sys/types.h> #include <sys/time.h> #endif #include "nroff.h" main (argc, argv) int argc; char *argv[]; { register int i; int swflg; int ifp = 0; swflg = FALSE; hold_screen = FALSE; debugging = FALSE; pout = stdout; err_stream = stderr; dbg_stream = stderr; /* * initialize structures (defaults) */ init (); /* * parse cmdline flags */ for (i = 1; i < argc; ++i) { if (*argv[i] == '-' || *argv[i] == '+') { if (pswitch (argv[i], argv[i+1], &swflg) == ERR) err_exit (-1); } } /* * loop on files */ for (i = 1; i < argc; ++i) { if (*argv[i] != '-' && *argv[i] != '+') { /* * open this file... */ if ((sofile[0] = fopen (argv[i], "r")) == NULL) { fprintf (err_stream, "***%s: unable to open file %s\n", myname, argv[i]); err_exit (-1); } else { /* * do it for this file... */ ifp = 1; profile (); fclose (sofile[0]); } } else if (*argv[i] == '-' && *(argv[i]+1) == 0) { /* * - means read stdin */ sofile[0] = stdin; ifp = 1; profile (); } } /* * if no files, usage */ if ((ifp == 0 && swflg == FALSE) || argc <= 1) { usage (); err_exit (-1); } /* * if not going to stdout (-l) */ if (pout != stdout) { fflush (pout); fclose (pout); } err_exit (0); } /*------------------------------*/ /* usage */ /*------------------------------*/ usage () { /* * note: -l not documented */ fprintf (stderr, "Usage: %s [options] file [...]\n", myname); fprintf (stderr, "Options:\n"); fprintf (stderr, "-a font changes\n"); fprintf (stderr, "-b backspace\n"); fprintf (stderr, "-h hold screen\n"); /* fprintf (stderr, "-l output to printer\n");*/ fprintf (stderr, "-m<name> macro file (e.g. -man)\n"); fprintf (stderr, "-o file error log file\n"); fprintf (stderr, "-po<n> page offset\n"); fprintf (stderr, "-pn<n> initial page number\n"); fprintf (stderr, "-v version\n"); fprintf (stderr, "+<n> first page to do\n"); fprintf (stderr, "-<n> last page to do\n"); fprintf (stderr, "- use stdin\n"); } /*------------------------------*/ /* init */ /*------------------------------*/ init () { /* * initialize parameters for nro word processor */ register long i; #ifdef ALCYON time_t dum = 0; #else extern long time (); time_t dum = time (0); #endif char *ctim; dc.fill = YES; dc.dofnt = YES; dc.lsval = 1; dc.inval = 0; dc.rmval = PAGEWIDTH - 1; dc.llval = PAGEWIDTH - 1; dc.ltval = PAGEWIDTH - 1; dc.tival = 0; dc.ceval = 0; dc.ulval = 0; dc.cuval = 0; dc.juval = YES; dc.adjval = ADJ_BOTH; dc.boval = 0; dc.bsflg = FALSE; dc.prflg = TRUE; dc.sprdir = 0; dc.flevel = 0; dc.lastfnt = 1; dc.thisfnt = 1; dc.escon = YES; dc.pgchr = '%'; dc.cmdchr = '.'; dc.escchr = '\\'; dc.nobrchr = '\''; for (i = 0; i < 26; ++i) dc.nr[i] = 0; for (i = 0; i < 26; ++i) dc.nrauto[i] = 1; for (i = 0; i < 26; ++i) dc.nrfmt[i] = '1'; /* * initialize internal regs. first zero out... */ for (i = 0; i < MAXREGS; i++) { rg[i].rname[0] = rg[i].rname[1] = rg[i].rname[2] = rg[i].rname[3] = '\0'; rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; } /* * this should be checked... */ ctim = ctime (&dum); /* * predefined regs. these are read/write: */ i = 0; strcpy (rg[i].rname, "%"); /* current page */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "ct"); /* character type */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "dl"); /* width of last complete di */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "dn"); /* height of last complete di */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "dw"); /* day of week (1-7) */ rg[i].rval = 0; if (!strncmp (&ctim[0], "Sun", 3)) rg[i].rval = 1; else if (!strncmp (&ctim[0], "Mon", 3)) rg[i].rval = 2; else if (!strncmp (&ctim[0], "Tue", 3)) rg[i].rval = 3; else if (!strncmp (&ctim[0], "Wed", 3)) rg[i].rval = 4; else if (!strncmp (&ctim[0], "Thu", 3)) rg[i].rval = 5; else if (!strncmp (&ctim[0], "Fri", 3)) rg[i].rval = 6; else if (!strncmp (&ctim[0], "Sat", 3)) rg[i].rval = 7; rg[i].rauto = 1; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "dy"); /* day of month (1-31) */ rg[i].rauto = 1; rg[i].rval = atoi (&ctim[8]); rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "hp"); /* current h pos on input */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "ln"); /* output line num */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "mo"); /* current month (1-12) */ rg[i].rval = 0; if (!strncmp (&ctim[4], "Jan", 3)) rg[i].rval = 1; else if (!strncmp (&ctim[4], "Feb", 3)) rg[i].rval = 2; else if (!strncmp (&ctim[4], "Mar", 3)) rg[i].rval = 3; else if (!strncmp (&ctim[4], "Apr", 3)) rg[i].rval = 4; else if (!strncmp (&ctim[4], "May", 3)) rg[i].rval = 5; else if (!strncmp (&ctim[4], "Jun", 3)) rg[i].rval = 6; else if (!strncmp (&ctim[4], "Jul", 3)) rg[i].rval = 7; else if (!strncmp (&ctim[4], "Aug", 3)) rg[i].rval = 8; else if (!strncmp (&ctim[4], "Sep", 3)) rg[i].rval = 9; else if (!strncmp (&ctim[4], "Oct", 3)) rg[i].rval = 10; else if (!strncmp (&ctim[4], "Nov", 3)) rg[i].rval = 11; else if (!strncmp (&ctim[4], "Dec", 3)) rg[i].rval = 12; rg[i].rauto = 1; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "nl"); /* v pos of last base-line */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "sb"); /* depth of str below base */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "st"); /* height of str above base */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, "yr"); /* last 2 dig of current year*/ rg[i].rauto = 1; rg[i].rval = atoi (&ctim[22]); rg[i].rflag = RF_READ | RF_WRITE; rg[i].rfmt = '1'; i++; /* * these are read only: */ strcpy (rg[i].rname, ".$"); /* num of args at current macro*/ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".A"); /* 1 for nroff */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".H"); /* hor resolution */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".T"); /* 1 for troff */ rg[i].rauto = 0; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".V"); /* vert resolution */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".a"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".c"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".d"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".f"); /* current font (1-4) */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".h"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".i"); /* current indent */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".l"); /* current line length */ rg[i].rauto = 1; rg[i].rval = PAGEWIDTH - 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".n"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".o"); /* current offset */ rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".p"); /* current page len */ rg[i].rauto = 1; rg[i].rval = PAGELEN; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".s"); /* current point size */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".t"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".u"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".v"); /* current v line spacing */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".w"); /* width of prev char */ rg[i].rauto = 1; rg[i].rval = 1; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".x"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".y"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; i++; strcpy (rg[i].rname, ".z"); rg[i].rauto = 1; rg[i].rval = 0; rg[i].rflag = RF_READ; rg[i].rfmt = '1'; pg.curpag = 0; pg.newpag = 1; pg.lineno = 0; pg.plval = PAGELEN; pg.m1val = 2; pg.m2val = 2; pg.m3val = 2; pg.m4val = 2; pg.bottom = pg.plval - pg.m4val - pg.m3val; pg.offset = 0; pg.frstpg = 0; pg.lastpg = 30000; pg.ehead[0] = pg.ohead[0] = '\n'; pg.efoot[0] = pg.ofoot[0] = '\n'; for (i = 1; i < MAXLINE; ++i) { pg.ehead[i] = pg.ohead[i] = EOS; pg.efoot[i] = pg.ofoot[i] = EOS; } pg.ehlim[LEFT] = pg.ohlim[LEFT] = dc.inval; pg.eflim[LEFT] = pg.oflim[LEFT] = dc.inval; pg.ehlim[RIGHT] = pg.ohlim[RIGHT] = dc.rmval; pg.eflim[RIGHT] = pg.oflim[RIGHT] = dc.rmval; co.outp = 0; co.outw = 0; co.outwds = 0; co.lpr = FALSE; for (i = 0; i < MAXLINE; ++i) co.outbuf[i] = EOS; for (i = 0; i < MXMDEF; ++i) mac.mnames[i] = NULL; for (i = 0; i < MACBUF; ++i) mac.mb[i] = '\0'; for (i = 0; i < MAXLINE; ++i) mac.pbb[i] = '\0'; mac.lastp = 0; mac.emb = &mac.mb[0]; mac.ppb = NULL; } /*------------------------------*/ /* pswitch */ /*------------------------------*/ pswitch (p, p2, q) register char *p; register char *p2; register int *q; { /* * process switch values from command line */ int swgood; char mfile[128]; char *ptmac; swgood = TRUE; if (*p == '-') { /* * since is STILL use the goofy atari/dri xmain code, i * look for both upper and lower case. if you use dLibs * (and if its startup code does not ucase the cmd line), * you can probably look for just lower case. gulam and * other shells typically don't change case of cmd line. */ switch (*++p) { case 0: /* stdin */ break; case 'a': /* font changes */ case 'A': dc.dofnt = NO; break; case 'b': /* backspace */ case 'B': dc.bsflg = TRUE; break; case 'd': /* debug mode */ case 'D': dbg_stream = fopen (dbgfile, "w"); debugging = TRUE; break; case 'h': /* hold screen */ case 'H': hold_screen = TRUE; break; case 'l': /* to lpr (was P) */ case 'L': pout = fopen (printer, "w"); co.lpr = TRUE; break; case 'm': /* macro file */ case 'M': /* * build macro file name. start with lib * * put c:\lib\tmac in environment so we can * read it here. else use default. if you want * file from cwd, "setenv TMACDIR ." from shell. * * we want file names like "tmac.an" (for -man) */ if (ptmac = getenv ("TMACDIR")) { /* * this is the lib path (e.g. "c:\lib\tmac") */ strcpy (mfile, ptmac); /* * this is the prefix (i.e. "\tmac.") */ strcat (mfile, TMACPRE); } else /* * use default lib/prefix (i.e. * "c:\lib\tmac\tmac.") */ strcpy (mfile, TMACFULL); /* * finally, add extension (e.g. "an") */ strcat (mfile, ++p); /* * open file and read it */ if ((sofile[0] = fopen (mfile, "r")) == NULL) { fprintf (stderr, "***%s: unable to open macro file %s\n", myname, mfile); err_exit (-1); } profile (); fclose (sofile[0]); break; case 'o': /* output error log */ case 'O': if (!p2) { fprintf (stderr, "***%s: no error file specified\n", myname); err_exit (-1); } if ((err_stream = fopen (p2, "w")) == NULL) { fprintf (stderr, "***%s: unable to open error file %s\n", myname, p2); err_exit (-1); } break; case 'p': /* .po, .pn */ case 'P': if (*(p+1) == 'o' || *(p+1) == 'O') /* -po___ */ { p += 2; set (&pg.offset, ctod (p), '1', 0, 0, HUGE); set_ireg (".o", pg.offset, 0); } else if (*(p+1) == 'n' || *(p+1) == 'N')/* -pn___ */ { p += 2; set (&pg.curpag, ctod (p) - 1, '1', 0, -HUGE, HUGE); pg.newpag = pg.curpag + 1; set_ireg ("%", pg.newpag, 0); } else /* -p___ */ { set (&pg.offset, ctod (++p), '1', 0, 0, HUGE); set_ireg (".o", pg.offset, 0); } break; case 'v': /* version */ case 'V': printf ("%s\n", version); *q = TRUE; break; case '0': /* last page */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pg.lastpg = ctod (p); break; default: /* illegal */ swgood = FALSE; break; } } else if (*p == '+') /* first page */ { pg.frstpg = ctod (++p); } else /* illegal */ { swgood = FALSE; } if (swgood == FALSE) { fprintf (stderr, "***%s: illegal switch %s\n", myname, p); return (ERR); } return (OK); } /*------------------------------*/ /* profile */ /*------------------------------*/ profile () { /* * process input files from command line */ char ibuf[MAXLINE]; /* * handle nesting of includes (.so) */ for (dc.flevel = 0; dc.flevel >= 0; dc.flevel -= 1) { while (getlin (ibuf, sofile[dc.flevel]) != EOF) { /* * if line is a command or text */ if (ibuf[0] == dc.cmdchr) { comand (ibuf); } else { /* * this is a text line. first see if * first char is space. if it is, break * line. */ if (ibuf[0] == ' ') robrk (); text (ibuf); } } /* * close included file */ if (dc.flevel > 0) fclose (sofile[dc.flevel]); } if (pg.lineno > 0) space (HUGE); } @//E*O*F main.c// chmod u=rw,g=r,o=r main.c echo x - command.c sed 's/^@//' > "command.c" <<'@//E*O*F command.c//' /* * command.c - command input parser/processor for nroff text processor * * adapted for atariST/TOS by Bill Rosenkranz 11/89 * net: rosenkra@hall.cray.com * CIS: 71460,17 * GENIE: W.ROSENKRANZ * * original author: * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * history: * * - Originally written in BDS C; * - Adapted for standard C by W. N. Paul * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz */ #undef NRO_MAIN /* extern globals */ #include <stdio.h> #include "nroff.h" /*------------------------------*/ /* comand */ /*------------------------------*/ comand (p) register char *p; { /* * main command processor */ register int i; register int ct; register int val; register int indx; int newval; int spval; char argtyp; char name[MAXLINE]; char macexp[MXMLEN]; int tmp; char *pfs; char fs[20]; /* * get command code */ ct = comtyp (p, macexp); /* * error? */ if (ct == UNKNOWN) { fprintf (err_stream, "***%s: unrecognized command %s\n", myname, p); return; } /* * ignore comments */ if (ct == COMMENT) return; /* * do escape expansion on command line args */ expesc (p, name); /* * get value of command */ val = getval (p, &argtyp); /* * do the command */ switch (ct) { /* set (¶m, val, type, defval, minval, maxval) */ case FC: /* * field delim/pad chars * * .fc [delim] [pad] */ fprintf (err_stream, "***%s: .fc not available\n", myname); break; case TR: /* * translate * * .tr ab... */ fprintf (err_stream, "***%s: .tr not available\n", myname); break; case AD: /* * adjust * * .ad [mode] */ p = skipwd (p); p = skipbl (p); switch (*p) { case 'l': dc.adjval = ADJ_LEFT; dc.juval = YES; break; case 'r': dc.adjval = ADJ_RIGHT; dc.juval = YES; break; case 'c': dc.adjval = ADJ_CENTER; dc.juval = YES; break; case 'b': case 'n': dc.adjval = ADJ_BOTH; dc.juval = YES; break; default: break; } break; case AF: /* * assign format to number reg * * .af R {1,a,A,i,I,0...1} */ p = skipwd (p); p = skipbl (p); if (!isalpha (*p)) { fprintf (err_stream, "***%s: invalid or missing number register name\n", myname); } else { /* * number register format is 1,a,A,i,I,0...1 * default is 1. for 0001 format, store num dig * or'ed with 0x80, up to 8 digits. */ indx = tolower (*p) - 'a'; p = skipwd (p); p = skipbl (p); if (*p == '1') dc.nrfmt[indx] = '1'; else if (*p == 'a') dc.nrfmt[indx] = 'a'; else if (*p == 'A') dc.nrfmt[indx] = 'A'; else if (*p == 'i') dc.nrfmt[indx] = 'i'; else if (*p == 'I') dc.nrfmt[indx] = 'I'; else if (*p == '0') { for (i = 0; isdigit (p[i]); i++) ; dc.nrfmt[indx] = (char) (i); if (dc.nrfmt[indx] <= 0) dc.nrfmt[indx] = '1'; else if (dc.nrfmt[indx] > 8) { dc.nrfmt[indx] = 8; dc.nrfmt[indx] |= 0x80; } else dc.nrfmt[indx] |= 0x80; } else dc.nrfmt[indx] = '1'; } break; case BO: /* * bold face * * .bo [N] */ set (&dc.boval, val, argtyp, 1, 0, HUGE); dc.cuval = dc.ulval = 0; break; case BP: /* * begin page * * .bp [+/-N] */ if (pg.lineno > 0) space (HUGE); set (&pg.curpag, val, argtyp, pg.curpag + 1, -HUGE, HUGE); pg.newpag = pg.curpag; set_ireg ("%", pg.newpag, 0); break; case BR: /* * break (page) * * .br */ robrk (); break; case BS: /* * backspc in output * * .bs [N] */ set (&dc.bsflg, val, argtyp, 1, 0, 1); break; case C2: /* * nobreak char * * .c2 [c='] */ if (argtyp == '\r' || argtyp == '\n') dc.nobrchr = '\''; else dc.nobrchr = argtyp; break; case CC: /* * command character * * .cc [c=.] */ if (argtyp == '\r' || argtyp == '\n') dc.cmdchr = '.'; else dc.cmdchr = argtyp; break; case CE: /* * center * * .ce [N] */ robrk (); set (&dc.ceval, val, argtyp, 1, 0, HUGE); break; case CU: /* * continuous underline * * .cu [N] */ set (&dc.cuval, val, argtyp, 1, 0, HUGE); dc.ulval = dc.boval = 0; break; case DE: /* * define macro * * .de name [end] */ defmac (p, sofile[dc.flevel]); break; case DS: /* * define string * * .ds name string */ defstr (p); break; case EC: /* * escape char * * .ec [c=\] */ if (argtyp == '\r' || argtyp == '\n') dc.escchr = '\\'; else dc.escchr = argtyp; dc.escon = YES; break; case EF: /* * even footer * * .ef "a" "b" "c" */ gettl (p, pg.efoot, &pg.eflim[0]); break; case EH: /* * even header * * .eh "a" "b" "c" */ gettl (p, pg.ehead, &pg.ehlim[0]); break; case EN: /* * end macro def (should not get one here...) * * .en or .. */ fprintf (err_stream, "***%s: missing .de command\n", myname); break; case EO: /* * escape off * * .eo */ dc.escon = NO; break; case FI: /* * fill * * .fi */ robrk (); dc.fill = YES; break; case FL: /* * flush NOW * * .fl */ fflush (pout); break; case FO: /* * footer * * .fo "a" "b" "c" */ gettl (p, pg.efoot, &pg.eflim[0]); gettl (p, pg.ofoot, &pg.oflim[0]); break; case FT: /* * font change * * .ft {R,I,B,S,P} * * the way it's implemented here, it causes a break * rather than be environmental... */ p = skipwd (p); p = skipbl (p); if (!isalpha (*p)) { fprintf (err_stream, "***%s: invalid or missing font name\n", myname); } else { pfs = &fs[0]; fontchange (*p, pfs); robrk (); fflush (pout); fprintf (pout, "%s", pfs); fflush (pout); } break; case TL: case HE: /* * header (both are currently identical. .he is -me) * * .tl "a" "b" "c" * .he "a" "b" "c" */ gettl (p, pg.ehead, &pg.ehlim[0]); gettl (p, pg.ohead, &pg.ohlim[0]); break; case IN: /* * indenting * * .in [+/-N] */ set (&dc.inval, val, argtyp, 0, 0, dc.rmval - 1); set_ireg (".i", dc.inval, 0); dc.tival = dc.inval; break; case JU: /* * justify * * .ju */ dc.juval = YES; break; case LL: /* * line length * * .ll [+/-N] * .rm [+/-N] */ set (&dc.rmval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE); set (&dc.llval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE); set_ireg (".l", dc.llval, 0); break; case LS: /* * line spacing * * .ls [+/-N=+1] */ set (&dc.lsval, val, argtyp, 1, 1, HUGE); set_ireg (".v", dc.lsval, 0); break; case LT: /* * title length * * .lt N */ set (&dc.ltval, val, argtyp, PAGEWIDTH, 0, HUGE); pg.ehlim[RIGHT] = dc.ltval; pg.ohlim[RIGHT] = dc.ltval; break; case M1: /* * topmost margin * * .m1 N */ set (&pg.m1val, val, argtyp, 2, 0, HUGE); break; case M2: /* * second top margin * * .m2 N */ set (&pg.m2val, val, argtyp, 2, 0, HUGE); break; case M3: /* * 1st bottom margin * * .m3 N */ set (&pg.m3val, val, argtyp, 2, 0, HUGE); pg.bottom = pg.plval - pg.m4val - pg.m3val; break; case M4: /* * bottom-most marg * * .m4 N */ set (&pg.m4val, val, argtyp, 2, 0, HUGE); pg.bottom = pg.plval - pg.m4val - pg.m3val; break; case MACRO: /* * macro expansion * * (internal) */ maceval (p, macexp); break; case NA: /* * no adjust * * .na */ dc.adjval = ADJ_OFF; dc.juval = NO; break; case NE: /* * need n lines * * .ne N */ robrk (); if ((pg.bottom - pg.lineno + 1) < (val * dc.lsval)) { space (HUGE); } break; case NF: /* * no fill * * .nf */ robrk (); dc.fill = NO; break; case NJ: /* * no justify * * .nj */ dc.juval = NO; break; case NR: /* * set number reg * * .nr R +/-N M */ p = skipwd (p); p = skipbl (p); if (!isalpha (*p)) { fprintf (err_stream, "***%s: invalid or missing number register name\n", myname); } else { /* * indx is the register, R, and val is the final * value (default = 0). getval does skipwd,skipbl */ indx = tolower (*p) - 'a'; val = getval (p, &argtyp); set (&dc.nr[indx], val, argtyp, 0, -INFINITE, INFINITE); /* * now get autoincrement M, if any (default = 1). * getval does skipwd,skipbl */ p = skipwd (p); p = skipbl (p); val = getval (p, &argtyp); set (&dc.nrauto[indx], val, '1', 1, -INFINITE, INFINITE); } break; case OF: /* * odd footer * * .of "a" "b" "c" */ gettl (p, pg.ofoot, &pg.oflim[0]); break; case OH: /* * odd header * * .oh "a" "b" "c" */ gettl (p, pg.ohead, &pg.ohlim[0]); break; case PC: /* * page number char * * .pc [c=NULL] */ if (argtyp == '\r' || argtyp == '\n') dc.pgchr = EOS; else dc.pgchr = argtyp; break; case PL: /* * page length * * .pl N */ set (&pg.plval, val, argtyp, PAGELEN, pg.m1val + pg.m2val + pg.m3val + pg.m4val + 1, HUGE); set_ireg (".p", pg.plval, 0); pg.bottom = pg.plval - pg.m3val - pg.m4val; break; case PM: /* * print macro names and sizes * * .pm [t] */ if (argtyp == '\r' || argtyp == '\n') printmac (0); else if (argtyp == 't') printmac (1); else if (argtyp == 'T') printmac (2); else printmac (0); break; case PN: /* * page number * * .pn N */ tmp = pg.curpag; set (&pg.curpag, val - 1, argtyp, tmp, -HUGE, HUGE); pg.newpag = pg.curpag + 1; set_ireg ("%", pg.newpag, 0); break; case PO: /* * page offset * * .po N */ set (&pg.offset, val, argtyp, 0, 0, HUGE); set_ireg (".o", pg.offset, 0); break; case RR: /* * unset number reg * * .rr R */ p = skipwd (p); p = skipbl (p); if (!isalpha (*p)) { fprintf (err_stream, "***%s: invalid or missing number register name\n", myname); } else { indx = tolower (*p) - 'a'; val = 0; set (&dc.nr[indx], val, argtyp, 0, -HUGE, HUGE); } break; case SO: /* * source file * * .so name */ p = skipwd (p); p = skipbl (p); if (getwrd (p, name) == 0) break; if (dc.flevel + 1 >= Nfiles) { fprintf (err_stream, "***%s: .so commands nested too deeply\n", myname); err_exit (-1); } if ((sofile[dc.flevel + 1] = fopen (name, "r")) == NULL) { fprintf (err_stream, "***%s: unable to open %s\n", myname, name); err_exit (-1); } dc.flevel += 1; break; case SP: /* * space * * .sp [N=1] */ set (&spval, val, argtyp, 1, 0, HUGE); space (spval); break; case TI: /* * temporary indent * * .ti [+/-N] */ robrk (); set (&dc.tival, val, argtyp, 0, 0, dc.rmval); break; case UL: /* * underline * * .ul [N] */ set (&dc.ulval, val, argtyp, 0, 1, HUGE); dc.cuval = dc.boval = 0; break; } } /*------------------------------*/ /* comtyp */ /*------------------------------*/ comtyp (p, m) register char *p; char *m; { /* * decodes nro command and returns its associated * value. */ register char c1; register char c2; char *s; char macnam[MNLEN]; /* * skip past dot and any whitespace */ p++; while (*p && (*p == ' ' || *p == '\t')) p++; if (*p == '\0') return (COMMENT); /* * First check to see if the command is a macro. * If it is, truncate to two characters and return * expansion in m. Note that upper and lower case * characters are handled differently. */ getwrd (p, macnam); macnam[2] = EOS; if ((s = getmac (macnam)) != NULL) { strcpy (m, s); return (MACRO); } c1 = *p++; c2 = *p; if (c1 == '\\' && c2 == '\"') return (COMMENT); if (c1 == 'a' && c2 == 'f') return (AF); if (c1 == 'a' && c2 == 'd') return (AD); if (c1 == 'b' && c2 == 'o') return (BO); if (c1 == 'b' && c2 == 'p') return (BP); if (c1 == 'b' && c2 == 'r') return (BR); if (c1 == 'b' && c2 == 's') return (BS); if (c1 == 'c' && c2 == 'c') return (CC); if (c1 == 'c' && c2 == 'e') return (CE); if (c1 == 'c' && c2 == 'u') return (CU); if (c1 == 'd' && c2 == 'e') return (DE); if (c1 == 'd' && c2 == 's') return (DS); if (c1 == 'e' && c2 == 'f') return (EF); if (c1 == 'e' && c2 == 'c') return (EC); if (c1 == 'e' && c2 == 'h') return (EH); if (c1 == 'e' && c2 == 'n') return (EN); if (c1 == '.') return (EN); if (c1 == 'e' && c2 == 'o') return (EO); if (c1 == 'f' && c2 == 'i') return (FI); if (c1 == 'f' && c2 == 'l') return (FL); if (c1 == 'f' && c2 == 'o') return (FO); if (c1 == 'f' && c2 == 't') return (FT); if (c1 == 'h' && c2 == 'e') return (HE); if (c1 == 'i' && c2 == 'n') return (IN); if (c1 == 'j' && c2 == 'u') return (JU); if (c1 == 'l' && c2 == 'l') return (LL); if (c1 == 'l' && c2 == 's') return (LS); if (c1 == 'm' && c2 == '1') return (M1); if (c1 == 'm' && c2 == '2') return (M2); if (c1 == 'm' && c2 == '3') return (M3); if (c1 == 'm' && c2 == '4') return (M4); if (c1 == 'n' && c2 == 'a') return (NA); if (c1 == 'n' && c2 == 'e') return (NE); if (c1 == 'n' && c2 == 'f') return (NF); if (c1 == 'n' && c2 == 'j') return (NJ); if (c1 == 'n' && c2 == 'r') return (NR); if (c1 == 'o' && c2 == 'f') return (OF); if (c1 == 'o' && c2 == 'h') return (OH); if (c1 == 'p' && c2 == 'c') return (PC); if (c1 == 'p' && c2 == 'l') return (PL); if (c1 == 'p' && c2 == 'm') return (PM); if (c1 == 'p' && c2 == 'o') return (PO); if (c1 == 'r' && c2 == 'm') return (RM); if (c1 == 'r' && c2 == 'r') return (RR); if (c1 == 's' && c2 == 'o') return (SO); if (c1 == 's' && c2 == 'p') return (SP); if (c1 == 't' && c2 == 'i') return (TI); if (c1 == 't' && c2 == 'l') return (TL); if (c1 == 'u' && c2 == 'l') return (UL); if (c1 == 'p' && c2 == 'n') return (PN); if (c1 == 'r' && c2 == 'r') return (RR); if (c1 == 'c' && c2 == '2') return (C2); if (c1 == 't' && c2 == 'r') return (TR); if (c1 == 'l' && c2 == 't') return (LT); if (c1 == 'f' && c2 == 'c') return (FC); return (UNKNOWN); } /*------------------------------*/ /* gettl */ /*------------------------------*/ gettl (p, q, limit) register char *p; register char *q; int limit[]; { /* * get header or footer title */ /* * skip forward a word... */ p = skipwd (p); p = skipbl (p); /* * copy and set limits */ strcpy (q, p); limit[LEFT] = dc.inval; limit[RIGHT] = dc.rmval; } /*------------------------------*/ /* getval */ /*------------------------------*/ getval (p, p_argt) register char *p; register char *p_argt; { /* * retrieves optional argument following nro command. * returns positive integer value with sign (if any) * saved in character addressed by p_argt. */ p = skipwd (p); p = skipbl (p); *p_argt = *p; if ((*p == '+') || (*p == '-')) ++p; return (ctod (p)); } /*------------------------------*/ /* set */ /*------------------------------*/ set (param, val, type, defval, minval, maxval) register int *param; register int val; register char type; register int defval; register int minval; register int maxval; { /* * set parameter and check range. this is for basically all commands * which take interger args * * no param (i.e. \r or \n) means reset default * + means param += val (increment) * - means param -= val (decrement) * anything else makes an assignment within the defined numerical limits * * examples: * * .nr a 14 set register 'a' to 14 * .nr a +1 increment register 'a' by 1 * .nr a reset register 'a' to default value (0) */ switch (type) { case '\r': case '\n': *param = defval; break; case '+': *param += val; break; case '-': *param -= val; break; default: *param = val; break; } *param = min (*param, maxval); *param = max (*param, minval); } /*------------------------------*/ /* set_ireg */ /*------------------------------*/ set_ireg (name, val, opt) register char *name; register int val; register int opt; /* 0=internal, 1=user set */ { /* * set internal register "name" to val. ret 0 if ok, else -1 if reg not * found or 1 if read only */ register int nreg; nreg = findreg (name); if (nreg < 0) return (-1); if ((rg[nreg].rflag & RF_WRITE) || (opt == 0)) { rg[nreg].rval = val; return (0); } return (1); } @//E*O*F command.c// chmod u=rw,g=r,o=r command.c echo x - text.c sed 's/^@//' > "text.c" <<'@//E*O*F text.c//' /* * text.c - text output processing portion of nroff word processor * * adapted for atariST/TOS by Bill Rosenkranz 11/89 * net: rosenkra@hall.cray.com * CIS: 71460,17 * GENIE: W.ROSENKRANZ * * original author: * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * history: * * - Originally written in BDS C; * - Adapted for standard C by W. N. Paul * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz */ #undef NRO_MAIN /* extern globals */ #include <stdio.h> #include "nroff.h" /*------------------------------*/ /* text */ /*------------------------------*/ text (p) register char *p; { /* * main text processing */ register int i; char wrdbuf[MAXLINE]; /* * skip over leading blanks if in fill mode. we indent later. * since leadbl does a robrk, do it if in .nf mode */ if (dc.fill == YES) { if (*p == ' ' || *p == '\n' || *p == '\r') leadbl (p); } else robrk (); /* * expand escape sequences */ expesc (p, wrdbuf); /* * test for how to output */ if (dc.ulval > 0) { /* * underline (.ul) * * Because of the way underlining is handled, * MAXLINE should be declared to be three times * larger than the longest expected input line * for underlining. Since many of the character * buffers use this parameter, a lot of memory * can be allocated when it may not really be * needed. A MAXLINE of 180 would allow about * 60 characters in the output line to be * underlined (remember that only alphanumerics * get underlined - no spaces or punctuation). */ underl (p, wrdbuf, MAXLINE); --dc.ulval; } if (dc.cuval > 0) { /* * continuous underline (.cu) */ underl (p, wrdbuf, MAXLINE); --dc.cuval; } if (dc.boval > 0) { /* * bold (.bo) */ bold (p, wrdbuf, MAXLINE); --dc.boval; } if (dc.ceval > 0) { /* * centered (.ce) */ center (p); put (p); --dc.ceval; } else if ((*p == '\r' || *p == '\n') && dc.fill == NO) { /* * all blank line */ put (p); } else if (dc.fill == NO) { /* * unfilled (.nf) */ put (p); } else { /* * anything else... * * init escape char counter for this line... */ co.outesc = 0; /* * get a word and put it out. increment ptr to the next * word. */ while ((i = getwrd (p, wrdbuf)) > 0) { co.outesc += countesc (wrdbuf); putwrd (wrdbuf); p += i; } } } /*------------------------------*/ /* bold */ /*------------------------------*/ bold (p0, p1, size) register char *p0; register char *p1; int size; { /* * insert bold face text (by overstriking) */ register int i; register int j; j = 0; for (i = 0; (p0[i] != '\n') && (j < size - 1); ++i) { if (isalpha (p0[i]) || isdigit (p0[i])) { p1[j++] = p0[i]; p1[j++] = '\b'; } p1[j++] = p0[i]; } p1[j++] = '\n'; p1[j] = EOS; while (*p1 != EOS) *p0++ = *p1++; *p0 = EOS; } /*------------------------------*/ /* center */ /*------------------------------*/ center (p) register char *p; { /* * center a line by setting tival */ dc.tival = max ((dc.rmval + dc.tival - width (p)) >> 1, 0); } /*------------------------------*/ /* expand */ /*------------------------------*/ expand (p0, c, s) register char *p0; char c; register char *s; { /* * expand title buffer to include character string */ register char *p; register char *q; register char *r; char tmp[MAXLINE]; p = p0; q = tmp; while (*p != EOS) { if (*p == c) { r = s; while (*r != EOS) *q++ = *r++; } else *q++ = *p; ++p; } *q = EOS; strcpy (p0, tmp); /* copy it back */ } /*------------------------------*/ /* justcntr */ /*------------------------------*/ justcntr (p, q, limit) register char *p; char *q; int limit[]; { /* * center title text into print buffer */ register int len; len = width (p); q = &q[(limit[RIGHT] + limit[LEFT] - len) >> 1]; while (*p != EOS) *q++ = *p++; } /*------------------------------*/ /* justleft */ /*------------------------------*/ justleft (p, q, limit) register char *p; char *q; int limit; { /* * left justify title text into print buffer */ q = &q[limit]; while (*p != EOS) *q++ = *p++; } /*------------------------------*/ /* justrite */ /*------------------------------*/ justrite (p, q, limit) register char *p; char *q; int limit; { /* * right justify title text into print buffer */ register int len; len = width (p); q = &q[limit - len]; while (*p != EOS) *q++ = *p++; } /*------------------------------*/ /* leadbl */ /*------------------------------*/ leadbl (p) register char *p; { /* * delete leading blanks, set tival */ register int i; register int j; /* * end current line and reset co struct */ robrk (); /* * skip spaces */ for (i = 0; p[i] == ' ' || p[i] == '\t'; ++i) ; /* * if not end of line, reset current temp indent */ if (p[i] != '\n' && p[i] != '\r') dc.tival = i; /* * shift string */ for (j = 0; p[i] != EOS; ++j) p[j] = p[i++]; p[j] = EOS; } /*------------------------------*/ /* pfoot */ /*------------------------------*/ pfoot () { /* * put out page footer */ if (dc.prflg == TRUE) { skip (pg.m3val); if (pg.m4val > 0) { if ((pg.curpag % 2) == 0) { puttl (pg.efoot, pg.eflim, pg.curpag); } else { puttl (pg.ofoot, pg.oflim, pg.curpag); } skip (pg.m4val - 1); } } } /*------------------------------*/ /* phead */ /*------------------------------*/ phead () { /* * put out page header */ pg.curpag = pg.newpag; if (pg.curpag >= pg.frstpg && pg.curpag <= pg.lastpg) { dc.prflg = TRUE; } else { dc.prflg = FALSE; } ++pg.newpag; set_ireg ("%", pg.newpag, 0); if (dc.prflg == TRUE) { if (pg.m1val > 0) { skip (pg.m1val - 1); if ((pg.curpag % 2) == 0) { puttl (pg.ehead, pg.ehlim, pg.curpag); } else { puttl (pg.ohead, pg.ohlim, pg.curpag); } } skip (pg.m2val); } /* * initialize lineno for the next page */ pg.lineno = pg.m1val + pg.m2val + 1; set_ireg ("ln", pg.lineno, 0); } /*------------------------------*/ /* puttl */ /*------------------------------*/ puttl (p, lim, pgno) register char *p; int lim[]; int pgno; { /* * put out title or footer */ register int i; char pn[8]; char t[MAXLINE]; char h[MAXLINE]; char delim; itoda (pgno, pn, 6); for (i = 0; i < MAXLINE; ++i) h[i] = ' '; delim = *p++; p = getfield (p, t, delim); expand (t, dc.pgchr, pn); justleft (t, h, lim[LEFT]); p = getfield (p, t, delim); expand (t, dc.pgchr, pn); justcntr (t, h, lim); p = getfield (p, t, delim); expand (t, dc.pgchr, pn); justrite (t, h, lim[RIGHT]); for (i = MAXLINE - 4; h[i] == ' '; --i) h[i] = EOS; h[++i] = '\n'; h[++i] = '\r'; h[++i] = EOS; if (strlen (h) > 2) { for (i = 0; i < pg.offset; ++i) prchar (' ', pout); } putlin (h, pout); } /*------------------------------*/ /* putwrd */ /*------------------------------*/ putwrd (wrdbuf) register char *wrdbuf; { /* * put word in output buffer */ register char *p0; register char *p1; int w; int last; int llval; int nextra; /* * check if this word puts us over the limit */ w = width (wrdbuf); last = strlen (wrdbuf) + co.outp; llval = dc.rmval - dc.tival; if (((co.outp > 0) && ((co.outw + w) > llval)) || (last > MAXLINE)) { /* * last word exceeds limit so prepare to break line, print * it, and reset outbuf. */ last -= co.outp; if (dc.juval == YES) { nextra = llval - co.outw + 1; /* * Check whether last word was end of * sentence and modify counts so that * it is right justified. */ if (co.outbuf[co.outp - 2] == ' ') { --co.outp; ++nextra; } spread (co.outbuf, co.outp - 1, nextra, co.outwds, co.outesc); if ((nextra > 0) && (co.outwds > 1)) { co.outp += (nextra - 1); } /* if (co.outesc > 0) { co.outp += co.outesc; } */ } /* * break line, output it, and reset all co members. reset * esc count. */ robrk (); co.outesc = countesc (wrdbuf); } /* * copy the current word to the out buffer which may have been * reset */ p0 = wrdbuf; p1 = co.outbuf + co.outp; while (*p0 != EOS) *p1++ = *p0++; co.outp = last; co.outbuf[co.outp++] = ' '; co.outw += w + 1; co.outwds += 1; } /*------------------------------*/ /* skip */ /*------------------------------*/ skip (n) register int n; { /* * skips the number of lines specified by n. */ register int i; if (dc.prflg == TRUE && n > 0) { for (i = 0; i < n; ++i) { prchar ('\n', pout); } prchar ('\r', pout); } } /*------------------------------*/ /* spread */ /*------------------------------*/ spread (p, outp, nextra, outwds, escapes) register char *p; int outp; int nextra; int outwds; int escapes; { /* * spread words to justify right margin */ register int i; register int j; register int nb; register int ne; register int nholes; int jmin; /* * quick sanity check... */ if ((nextra <= 0) || (outwds <= 1)) return; /*fflush (pout); fprintf (err_stream, "in spread: escapes = %d\n", escapes); fflush (err_stream);*/ /* * set up for the spread and do it... */ dc.sprdir = ~dc.sprdir; ne = nextra; nholes = outwds - 1; /* holes between words */ i = outp - 1; /* last non-blank character */ j = min (MAXLINE - 3, i + ne); /* leave room for CR,LF,EOS */ /* j += escapes; if (p[i-1] == 27) j += 2; j = min (j, MAXLINE - 3); */ while (i < j) { p[j] = p[i]; if (p[i] == ' ') { if (dc.sprdir == 0) nb = (ne - 1) / nholes + 1; else nb = ne / nholes; ne -= nb; --nholes; for (; nb > 0; --nb) { --j; p[j] = ' '; } } --i; --j; } } /*------------------------------*/ /* strkovr */ /*------------------------------*/ strkovr (p, q) register char *p; register char *q; { /* * split overstrikes (backspaces) into seperate buffer */ register char *pp; int bsflg; bsflg = FALSE; pp = p; while (*p != EOS) { *q = ' '; *pp = *p; ++p; if (*p == '\b') { if (*pp >= ' ' && *pp <= '~') { bsflg = TRUE; *q = *pp; ++p; *pp = *p; ++p; } } ++q; ++pp; } *q++ = '\r'; *q = *pp = EOS; return (bsflg); } /*------------------------------*/ /* underl */ /*------------------------------*/ underl (p0, p1, size) register char *p0; register char *p1; int size; { /* * underline a line */ register int i; register int j; j = 0; for (i = 0; (p0[i] != '\n') && (j < size - 1); ++i) { if (p0[i] >= ' ' && p0[i] <= '~') { if (isalpha (p0[i]) || isdigit (p0[i]) || dc.cuval > 0) { p1[j++] = '_'; p1[j++] = '\b'; } } p1[j++] = p0[i]; } p1[j++] = '\n'; p1[j] = EOS; while (*p1 != EOS) *p0++ = *p1++; *p0 = EOS; } /*------------------------------*/ /* width */ /*------------------------------*/ width (s) register char *s; { /* * compute width of character string */ register int w; w = 0; while (*s != EOS) { if (*s == '\b') --w; else if (*s != '\n' && *s != '\r') ++w; ++s; } return (w); } @//E*O*F text.c// chmod u=rw,g=r,o=r text.c echo x - io.c sed 's/^@//' > "io.c" <<'@//E*O*F io.c//' /* * io.c - low level I/O processing portion of nroff word processor * * adapted for atariST/TOS by Bill Rosenkranz 11/89 * net: rosenkra@hall.cray.com * CIS: 71460,17 * GENIE: W.ROSENKRANZ * * original author: * * Stephen L. Browning * 5723 North Parker Avenue * Indianapolis, Indiana 46220 * * history: * * - Originally written in BDS C; * - Adapted for standard C by W. N. Paul * - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz */ #undef NRO_MAIN /* extern globals */ #include <stdio.h> #include "nroff.h" /*------------------------------*/ /* getlin */ /*------------------------------*/ getlin (p, in_buf) char *p; FILE *in_buf; { /* * retrieve one line of input text */ register char *q; register int i; int c; int nreg; q = p; for (i = 0; i < MAXLINE - 1; ++i) { c = ngetc (in_buf); if (c == EOF) { *q = EOS; c = strlen (p); return (c == 0 ? EOF : c); } *q++ = c; if (c == '\n') break; } *q = EOS; nreg = findreg (".c"); if (nreg > 0) set_ireg (".c", rg[nreg].rval + 1, 0); return (strlen (p)); } /*------------------------------*/ /* ngetc */ /*------------------------------*/ ngetc (infp) FILE *infp; { /* * get character from input file or push back buffer */ register int c; if (mac.ppb >= &mac.pbb[0]) c = *mac.ppb--; else c = getc (infp); return (c); } /*------------------------------*/ /* pbstr */ /*------------------------------*/ pbstr (p) char p[]; { /* * Push back string into input stream */ register int i; /* * if string is null, we do nothing */ for (i = strlen (p) - 1; i >= 0; --i) { putbak (p[i]); } } /*------------------------------*/ /* putbak */ /*------------------------------*/ putbak (c) char c; { /* * Push character back into input stream. we use the push-back buffer * stored with macros. */ if (mac.ppb < &(mac.pbb[0])) { mac.ppb = &(mac.pbb[0]); *mac.ppb = c; } else { if (mac.ppb >= &mac.pbb[MAXLINE - 1]) { fprintf (err_stream, "***%s: push back buffer overflow\n", myname); err_exit (-1); } *++(mac.ppb) = c; } } /*------------------------------*/ /* prchar */ /*------------------------------*/ prchar (c, fp) char c; FILE *fp; { /* * print character with test for printer */ putc (c, fp); } /*------------------------------*/ /* put */ /*------------------------------*/ put (p) char *p; { /* * put out line with proper spacing and indenting */ register int j; char os[MAXLINE]; if (pg.lineno == 0 || pg.lineno > pg.bottom) { phead (); } if (dc.prflg == TRUE) { if (!dc.bsflg) { if (strkovr (p, os) == TRUE) { for (j = 0; j < pg.offset; ++j) prchar (' ', pout); for (j = 0; j < dc.tival; ++j) prchar (' ', pout); putlin (os, pout); } } for (j = 0; j < pg.offset; ++j) prchar (' ', pout); for (j = 0; j < dc.tival; ++j) prchar (' ', pout); putlin (p, pout); } dc.tival = dc.inval; skip (min (dc.lsval - 1, pg.bottom - pg.lineno)); pg.lineno = pg.lineno + dc.lsval; set_ireg ("ln", pg.lineno, 0); if (pg.lineno > pg.bottom) pfoot (); } /*------------------------------*/ /* putlin */ /*------------------------------*/ putlin (p, pbuf) register char *p; FILE *pbuf; { /* * output a null terminated string to the file * specified by pbuf. */ while (*p != EOS) prchar (*p++, pbuf); } @//E*O*F io.c// chmod u=rw,g=r,o=r io.c exit 0