Annotation of coherent/d/bin/nroff/main.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * main.c
                      3:  * Nroff/Troff.
                      4:  * Main program and initialization.
                      5:  */
                      6: 
                      7: #include <ctype.h>
                      8: #if    MSDOS
                      9: #include <types.h>
                     10: #include <stat.h>
                     11: #else
                     12: #include <sys/types.h>
                     13: #include <sys/stat.h>
                     14: #endif
                     15: #include <time.h>
                     16: #include <path.h>
                     17: #include <string.h>
                     18: #include "roff.h"
                     19: 
                     20: extern char    *getenv();
                     21: extern char    *path();
                     22: extern time_t  time();
                     23: #ifdef GEMDOS
                     24: extern char    *tempnam();
                     25: #else
                     26: extern char    *mktemp();
                     27: #endif
                     28: 
                     29: #ifdef GEMDOS
                     30: unsigned long _stksize = 0x8000L;
                     31: #endif
                     32: 
                     33: static int     kflag;          /* keep tmp file for debug purposes     */
                     34: static char    template[sizeof(TMPLATE)+1] = TMPLATE;
                     35: static char    *tempname;      /* temp file name                       */
                     36: 
                     37: main(argc, argv) int argc; char *argv[];
                     38: {
                     39:        register int i, fileflag, iflag;
                     40:        register char *libpath, *cp;
                     41:        register REG *rp;
                     42:        char c, name[2];
                     43: 
                     44:        argv0 = (ntroff == NROFF) ? "nroff" : "troff";
                     45:        cp = getenv((ntroff == NROFF) ? "NROFF" : "TROFF");
                     46:        if (cp != NULL && *cp != '\0')
                     47:                addargs(cp, &argc, &argv);
                     48:        initialize(argc, argv);
                     49: 
                     50:        /*
                     51:         * Process specified input files.
                     52:         * initialize() already handled most options.
                     53:         */
                     54:        fileflag = iflag = 0;
                     55:        for (i = 1; i < argc; i++) {
                     56:                cp = argv[i];
                     57:                if (*cp != '-') {
                     58:                        /* Process non-option argument. */
                     59:                        fileflag = 1;
                     60:                        if (adsfile(cp) != 0)
                     61:                                process();
                     62:                        continue;
                     63:                }
                     64: 
                     65:                /* Process '-'-option argument. */
                     66:                c = *++cp;                      /* argv[i][1] */
                     67:                cp++;                           /* &argv[i][2] */
                     68:                if (c == 'i')
                     69:                        iflag = 1;              /* process stdin when done */
                     70:                else if (c == 'f')
                     71:                        ++i;                    /* ignore tempfile arg */
                     72:                else if (c == 'm') {
                     73:                        /* Process "-m" macro package argument. */
                     74:                        sprintf(miscbuf, TMACFMT, cp);
                     75:                        libpath = DEFLIBPATH;
                     76:                        if ((libpath = path(libpath, miscbuf, AREAD)) != NULL)
                     77:                                strcpy(miscbuf, libpath);
                     78: #if    (DDEBUG & DBGFILE)
                     79:                        printd(DBGFILE, "tmac file = %s\n", miscbuf);
                     80: #endif
                     81:                        adsfile(miscbuf);
                     82:                        process();
                     83:                } else if (c == 'n') {
                     84:                        /* Reset page number. */
                     85:                        pno = atoi(cp);
                     86:                        npn = pno + 1;
                     87:                } else if (c == 'r' && *cp != '\0') {
                     88:                        /* Reset register value. */
                     89:                        name[0] = *cp++;
                     90:                        if (isdigit(*cp))
                     91:                                name[1] = '\0';
                     92:                        else
                     93:                                name[1] = *cp++;
                     94:                        rp = getnreg(name);
                     95:                        rp->n_reg.r_nval = atoi(cp);
                     96:                        if (rp == nrpnreg)              /* Page # register */
                     97:                                npn = pno + 1;          /* Set next page # */
                     98:                }
                     99:        }
                    100:        if (fileflag == 0 || iflag != 0) {
                    101:                /* Process standard input. */
                    102:                adsunit(stdin);
                    103:                process();
                    104:        }
                    105:        if (iestackx != -1)
                    106:                printe(".ie without matching .el");
                    107:        leave(0);
                    108: }
                    109: 
                    110: /*
                    111:  * Open temp file, set up registers and general initialization.
                    112:  */
                    113: initialize(argc, argv) int argc; char *argv[];
                    114: {
                    115:        register REG *rp;
                    116:        register REQ *qp;
                    117:        register int i;
                    118:        int Dflag, tmparg;
                    119:        char *s;
                    120: 
                    121:        A_reg = ntroff==NROFF;
                    122: 
                    123:        /*
                    124:         * Pass over args, process those dealing with global initialization.
                    125:         * main() makes another pass over the arg list to process input files.
                    126:         */
                    127:        Dflag = tmparg = 0;
                    128:        for (i = 1; i < argc; i++) {
                    129:                if (argv[i][0] != '-')
                    130:                        continue;
                    131:                switch (argv[i][1]) {
                    132:                case 'a':
                    133:                        A_reg = 1;
                    134:                        continue;
                    135:                case 'd':
                    136: #if    DDEBUG
                    137:                        if (argv[i][2] != '\0') {
                    138:                                dbglvl = atoi(&argv[i][2]);
                    139:                                dbginit();
                    140:                        } else
                    141: #endif
                    142:                                dflag++;
                    143:                        continue;
                    144:                case 'D':
                    145:                        Dflag = 1;
                    146:                        continue;
                    147:                case 'f':
                    148:                        if (i < (argc-1))
                    149:                                tmparg = ++i;
                    150:                        else
                    151:                                panic("-f option requires file argument");
                    152:                        continue;
                    153:                case 'i':
                    154:                        continue;       /* handled in main() */
                    155:                case 'K':
                    156:                case 'k':
                    157:                        kflag++;
                    158:                        continue;
                    159:                case 'l':
                    160:                        lflag = 1;
                    161:                        continue;
                    162:                case 'm':
                    163:                        continue;       /* handled in main() */
                    164:                case 'n':
                    165:                        continue;       /* handled in main() */
                    166:                case 'p':
                    167:                        pflag = 1;
                    168:                        continue;
                    169:                case 'r':
                    170:                        continue;       /* handled in main() */
                    171: #ifndef GEMDOS
                    172:                case 'T':
                    173:                        if (ntroff == NROFF)
                    174:                                T_reg = 1;
                    175:                        continue;
                    176: #endif
                    177:                case 'x':
                    178:                        xflag++;
                    179:                        continue;
                    180:                case 'V':
                    181:                case 'v':
                    182:                        fprintf(stderr, "%s: V%s\n", argv0, VERSION);
                    183:                        continue;
                    184: #if    ZKLUDGE
                    185:                case 'Z':
                    186:                        if (argv[i][2] != '\0')
                    187:                                Zflag = atoi(&argv[i][2]);
                    188:                        else
                    189:                                Zflag = ZPAGES;
                    190:                        continue;
                    191: #endif
                    192:                default:
                    193:                        fprintf(stderr, "%s: illegal option: %s\n", argv0, argv[i]);
                    194:                        /* fall through... */
                    195:                case '?':
                    196:                        usage();
                    197:                }
                    198:        }
                    199: 
                    200:        /* Initialize tempfile. */
                    201: #ifdef GEMDOS
                    202:        tempname = (tmparg) ? argv[tmparg] : tempnam(0L, "nroff");
                    203: #else
                    204:        tempname = (tmparg) ? argv[tmparg] : mktemp(template);
                    205: #endif
                    206:        dprint2(DBGFILE, "temp file name = %s\n", tempname);
                    207:        if ((tmp=fopen(tempname, "wb")) == NULL)
                    208:                panic("cannot create temp file");
                    209:        else if (freopen(tempname, "rwb", tmp) == NULL)
                    210:                panic("cannot reopen temp file");
                    211:        tmpseek = ENVSIZE * sizeof (ENV);
                    212:        tmpseek = (tmpseek+DBFSIZE+DBFSIZE-1) & ~(DBFSIZE-1);
                    213: 
                    214: #ifdef GEMDOS
                    215:        /*
                    216:         * GEMDOS lseek does not produce sparse files;
                    217:         * this makes it necessary to write the beginning of nroff's work file.
                    218:         */
                    219:        memset(diskbuf, '\0', DBFSIZE);
                    220:        for (i = 0; i < tmpseek; i += DBFSIZE) {
                    221:                dprintd(DBGFILE, "initializing tempfile\n");
                    222:                if (write(fileno(tmp), diskbuf, DBFSIZE) != DBFSIZE)
                    223:                        panic("temp file write error");
                    224:        }
                    225: #endif
                    226: #ifdef COHERENT
                    227:        /*
                    228:         * Unlinking temp file immediately under COHERENT makes it
                    229:         * go away if program is interrupted with <Ctrl-C>;
                    230:         * under GEMDOS it would destroy the file immediately,
                    231:         * so it is done under leave() below.
                    232:         */
                    233:        if (kflag == 0)
                    234:                unlink(tempname);
                    235: #endif
                    236: 
                    237:        /* Copy .pre-file if it exists. */
                    238:        if (!Dflag) {
                    239:                s = (lflag) ? PRE_L : PRE_P;
                    240:                if (lib_file(s, 0) == 0 & ntroff == TROFF)
                    241:                        printe("file \"%s\" not found", s);
                    242:        }
                    243:        
                    244:        /* Initialize globals. */
                    245:        dev_init();             /* output writer-specific initialization */
                    246:        for (i = 0; i < NWIDTH; i++)
                    247:                trantab[i] = i;                         /* translation table */
                    248:        for (i = 0; i < RHTSIZE; i++)
                    249:                regt[i] = NULL;                         /* request hash table */
                    250:        for (qp = reqtab; qp->q_name[0]; qp++) {        /* built-in requests */
                    251:                rp = makereg(qp->q_name, RTEXT);
                    252:                rp->t_reg.r_macd.r_div.m_next = NULL;
                    253:                rp->t_reg.r_macd.r_div.m_type = MREQS;
                    254:                rp->t_reg.r_macd.r_div.m_func = qp->q_func;
                    255:        }
                    256: 
                    257:        /* Create built in registers. */
                    258:        /* UNDONE: "c.", same as ".c" */
                    259:        nrpnreg = getnreg("%");
                    260:        nrctreg = getnreg("ct");
                    261:        nrdlreg = getnreg("dl");
                    262:        nrdnreg = getnreg("dn");
                    263:        nrdwreg = getnreg("dw");
                    264:        nrdyreg = getnreg("dy");
                    265:        nrhpreg = getnreg("hp");
                    266:        nrlnreg = getnreg("ln");
                    267:        nrmoreg = getnreg("mo");
                    268:        nrnlreg = getnreg("nl");
                    269:        nrsbreg = getnreg("sb");
                    270:        nrstreg = getnreg("st");
                    271:        nryrreg = getnreg("yr");
                    272:        setnreg();
                    273: 
                    274:        /* Environment initialization. */
                    275:        envset();
                    276:        envinit[0] = 1;
                    277: 
                    278:        /* Etc. */
                    279:        iestackx = -1;
                    280:        cdivp = NULL;
                    281:        newdivn("\0\0");
                    282:        mdivp = cdivp;
                    283: #ifdef GEMDOS
                    284:        if (((long)mdivp) & 1L)
                    285:                panic("diversion buffer odd alignment");
                    286: #endif
                    287:        endtrap[0] = '\0';
                    288:        strp = NULL;
                    289:        pgl = (lflag) ? unit(17*SMINCH, 2*SDINCH) : unit(11*SMINCH, SDINCH);
                    290:        pno = 1;
                    291:        npn = 2;
                    292:        esc = '\\';
                    293: 
                    294:        /* Load default fonts for troff, initialize font numbers. */
                    295:        i = lib_file("fonts.r", 1);
                    296:        if (ntroff == TROFF && i == 0)
                    297:                panic("fonts.r not found");
                    298:        if (Dflag) {
                    299:                font_display();
                    300:                exit(0);
                    301:        }
                    302:        if (setfont("R", 1) == -1)
                    303:                leave(1);                       /* font R is mandatory */
                    304:        tfn = curfont;                          /* tab character font */
                    305:        if ((ufn = font_num("I")) == -1)        /* underline font number */
                    306:                ufn = curfont;
                    307: 
                    308:        /* Process special character definitions. */
                    309:        lib_file("specials.r", 1);              /* special characters */
                    310: #if    (DDEBUG & DBGCHEK)
                    311:        printd(DBGFUNC, "initialized...\n");
                    312: #endif
                    313: }
                    314: 
                    315: /*
                    316:  * Initialize pre-defined number registers.
                    317:  */
                    318: setnreg()
                    319: {
                    320:        time_t curtime;
                    321:        register struct tm *tmp;
                    322: 
                    323:        curtime = time((time_t *)0);
                    324:        tmp = localtime(&curtime);
                    325:        nryrreg->n_reg.r_nval = tmp->tm_year % 100;
                    326:        nrmoreg->n_reg.r_nval = tmp->tm_mon + 1;
                    327:        nrdyreg->n_reg.r_nval = tmp->tm_mday;
                    328:        nrdwreg->n_reg.r_nval = tmp->tm_wday + 1;
                    329: }
                    330: 
                    331: /*
                    332:  * Leave.
                    333:  * The passed exit status is:
                    334:  *     0       normal
                    335:  *     1       fatal error
                    336:  *     2       usage error
                    337:  */
                    338: leave(status) register int status;
                    339: {
                    340:        char name[2];
                    341:        static int depth = 0;
                    342: 
                    343:        if (status == 0 && depth++ == 0) {
                    344:                if (endtrap[0] != '\0') {
                    345:                        name[0] = endtrap[0];
                    346:                        name[1] = endtrap[1];
                    347:                        endtrap[0] = '\0';
                    348:                        execute(name);
                    349:                }
                    350:                setbreak();
                    351:                if (xflag == 0) {
                    352:                        byeflag = 1;
                    353:                        pspace();
                    354:                }
                    355:        } else if (status == 1 && depth++ == 0) {
                    356:                /* Space to bottom of page if status==1, useful for PS. */
                    357:                if (xflag == 0) {
                    358:                        byeflag = 1;
                    359:                        pspace();
                    360:                }
                    361:        }
                    362: 
                    363: #ifndef COHERENT
                    364: #if    (DDEBUG & DBGFILE)
                    365:        {
                    366:                struct stat statblk;
                    367: 
                    368:                fclose(tmp);                    /* Close the temp file. */
                    369:                stat(tempname, &statblk);       /* so we can stat it.   */
                    370:                printd(DBGFILE, "deleting temporary file %s, size = %ld\n",
                    371:                        tempname, statblk.st_size);
                    372:        }
                    373: #endif
                    374:        /* Unlink temp file if not COHERENT. */
                    375:        if (kflag == 0)
                    376:                unlink(tempname);
                    377: #endif
                    378:        exit(status);
                    379: }
                    380: 
                    381: /*
                    382:  * Print a fatal usage message and die.
                    383:  */
                    384: usage()
                    385: {
                    386:        fprintf(stderr, "Usage: %s [ option ... ] [ file ... ]\n",
                    387:                ntroff == NROFF ? "nroff" : "troff");
                    388:        fprintf(stderr, "Options:\n");
                    389:        fprintf(stderr, "\t-d\tDebug: print each request before executing\n");
                    390:        if (ntroff == TROFF)
                    391:                fprintf(stderr, "\t-D\tDisplay available fonts\n");
                    392:        fprintf(stderr, "\t-f name\tWrite temporary file in file name\n");
                    393:        fprintf(stderr, "\t-i\tRead stdin after each file has been read\n");
                    394:        fprintf(stderr, "\t-k\tKeep temporary file\n");
                    395:        if (ntroff == TROFF)
                    396:                fprintf(stderr, "\t-l\tLandscape mode\n");
                    397:        fprintf(stderr, "\t-mname\tRead macro package /usr/lib/tmac.name\n");
                    398:        fprintf(stderr, "\t-nN\tNumber first page of output N (default, 1)\n");
                    399:        if (ntroff == TROFF)
                    400:                fprintf(stderr, "\t-p\tProduce PostScript output\n");
                    401:        fprintf(stderr, "\t-raN\tSet number register a to value N\n");
                    402:        fprintf(stderr, "\t-x\tDo not eject to bottom of final page\n");
                    403:        leave(2);
                    404: }
                    405: 
                    406: /*
                    407:  * cp contains space-separated environmental args to be added to argv.
                    408:  * Change argc/argv accordingly.
                    409:  */
                    410: addargs(cp, argcp, argvp) char *cp; int *argcp; char ***argvp;
                    411: {
                    412:        register int n;
                    413:        register char *s, **nargv, **np;
                    414: 
                    415:        for (s = cp, n = 1; *s != '\0'; s++)
                    416:                if (*s == ' ')
                    417:                        ++n;            /* number of added args */
                    418:        *argcp += n;                    /* bump argc */
                    419:        np = nargv = (char **)nalloc((*argcp + 1) * sizeof (char *)); /* allocate */
                    420:        *np++ = *(*argvp)++;            /* copy old argv0 */
                    421:        for (s = cp; *s != '\0'; ) {
                    422:                *np++ = s;              /* store pointer to new arg */
                    423:                while (*s != '\0' && *s != ' ')
                    424:                        s++;            /* scan to NUL or space */
                    425:                if (*s == ' ')
                    426:                        *s++ = '\0';    /* NUL-terminate space-separated args */
                    427:        }
                    428:        while (**argvp != NULL)
                    429:                *np++ = *(*argvp)++;    /* copy old argv */
                    430:        *np = NULL;                     /* NULL-terminate new argv */
                    431:        *argvp = nargv;                 /* pass back new argv */
                    432: }
                    433: 
                    434: /* end of main.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.