|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.