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