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