|
|
1.1 ! root 1: /* ! 2: * misc.c ! 3: * Nroff/Troff. ! 4: * Miscellaneous routines. ! 5: */ ! 6: ! 7: #include "roff.h" ! 8: #include <access.h> ! 9: #include <ctype.h> ! 10: #include <string.h> ! 11: ! 12: /* ! 13: * Define a macro. ! 14: * 'mp' is a pointer to a macro descriptor which is ! 15: * filled in with the appropriate information and name is the name ! 16: * of the macro upon which the definition ends. ! 17: */ ! 18: deftext(mp, name) register MAC *mp; char name[2]; ! 19: { ! 20: static char residue[4]; ! 21: register STR *sp; ! 22: register char *bp; ! 23: int nlflag; ! 24: ! 25: if (mp != NULL) { ! 26: mp->t_div.m_next = NULL; ! 27: mp->t_div.m_type = MTEXT; ! 28: mp->t_div.m_core = NULL; ! 29: mp->t_div.m_seek = tmpseek; ! 30: } ! 31: #if 0 ! 32: /* Conditionalized out 4/11/91 by steve, seems wrong. */ ! 33: infalse = 1; ! 34: #endif ! 35: bp = miscbuf; ! 36: for (nlflag = 1;;) { ! 37: ! 38: /* nlflag indicates if last character was \n. */ ! 39: if (bp > miscbuf) ! 40: nlflag = (*(bp-1) == '\n'); ! 41: ! 42: /* Flush if necessary, leaving room for "..\n" or ".XX". */ ! 43: if (bp >= &miscbuf[MSCSIZE-3]) { ! 44: if (mp != NULL) ! 45: nwrite(miscbuf, 1, bp-miscbuf); ! 46: bp = miscbuf; ! 47: } ! 48: ! 49: /* Ignore remainder of line not starting with endmark. */ ! 50: if (!nlflag) { ! 51: *bp++ = getf(2); ! 52: continue; ! 53: } ! 54: ! 55: /* Last character was \n, look for endmark on next line. */ ! 56: if (name[0]=='\0') { ! 57: if ((*bp++ = getf(2))!='.' || escflag!=0) ! 58: continue; ! 59: if ((*bp++ = getf(2))!='.' || escflag!=0) ! 60: continue; ! 61: if ((*bp++ = getf(2)) != '\n') ! 62: continue; ! 63: bp -= 3; ! 64: break; ! 65: } else { ! 66: if ((*bp++ = getf(2))!=ccc || escflag!=0) ! 67: continue; ! 68: if ((*bp++ = getf(2))!=name[0] || escflag!=0) ! 69: continue; ! 70: if ((*bp++ = getf(2))!=name[1] || escflag!=0) ! 71: continue; ! 72: bp -= 3; ! 73: residue[0] = bp[0]; ! 74: residue[1] = bp[1]; ! 75: residue[2] = bp[2]; ! 76: residue[3] = '\0'; ! 77: sp = allstr(SCORE); ! 78: sp->x3.s_cp = residue; ! 79: sp->x3.s_srel = NULL; ! 80: break; ! 81: } ! 82: } ! 83: *bp++ = '\0'; ! 84: if (mp != NULL) ! 85: nwrite(miscbuf, 1, bp-miscbuf); ! 86: #if 0 ! 87: /* Conditionalized out 4/11/91 by steve, as above. */ ! 88: infalse = 0; ! 89: #endif ! 90: } ! 91: ! 92: /* ! 93: * Define a special character. ! 94: */ ! 95: spc_def(name, value) char name[2]; char *value; ! 96: { ! 97: register SPECIAL **spp; ! 98: register int n; ! 99: int len; ! 100: SPECIAL *sp; ! 101: char *cp; ! 102: ! 103: len = strlen(value) + 1; ! 104: for (spp = &spc_list; *spp != NULL; spp = &((*spp)->spc_link)) { ! 105: sp = *spp; ! 106: n = strncmp(sp->spc_name, name, 2); ! 107: if (n < 0) ! 108: continue; /* keep looking */ ! 109: else if (n > 0) ! 110: break; /* not found, add it */ ! 111: /* Gotcha, redefine it. */ ! 112: nfree(sp->spc_val); /* free old value */ ! 113: sp->spc_val = nalloc(len); /* allocate new space */ ! 114: strcpy(sp->spc_val, value); /* and copy in value */ ! 115: return; ! 116: } ! 117: /* Add new entry. */ ! 118: sp = (SPECIAL *)nalloc(sizeof(*sp)); /* allocate new entry */ ! 119: cp = nalloc(len); /* allocate new value space */ ! 120: sp->spc_link = *spp; /* link into SPECIAL list */ ! 121: *spp = sp; ! 122: sp->spc_name[0] = name[0]; ! 123: sp->spc_name[1] = name[1]; ! 124: sp->spc_val = cp; ! 125: strcpy(cp, value); ! 126: } ! 127: ! 128: /* ! 129: * Find a special character entry in the special character list. ! 130: * Print error message and return NULL if not found. ! 131: */ ! 132: SPECIAL * ! 133: spc_find(name) char name[2]; ! 134: { ! 135: register SPECIAL *sp; ! 136: register int n; ! 137: ! 138: for (sp = spc_list; sp != NULL; sp = sp->spc_link) { ! 139: n = strncmp(sp->spc_name, name, 2); ! 140: if (n < 0) ! 141: continue; ! 142: else if (n > 0) ! 143: break; ! 144: else ! 145: return sp; ! 146: } ! 147: printe("special character %c%c not found", name[0], name[1]); ! 148: return NULL; ! 149: } ! 150: ! 151: /* ! 152: * Process requests from a library file if it exists. ! 153: * The flag is 1 if file contains requests, 0 if binary data. ! 154: * Return 1 if it exists, 0 if not. ! 155: */ ! 156: lib_file(s, flag) char *s; int flag; ! 157: { ! 158: register char file[40]; ! 159: ! 160: /* Look file, process it if found. */ ! 161: sprintf(file, "%s%s%s", LIBDIR, ! 162: (ntroff == NROFF) ? NRDIR : (pflag) ? TPSDIR : TPCLDIR, s); ! 163: if (access(file, AREAD) != 0) ! 164: return 0; ! 165: if (flag) { ! 166: adsfile(file); ! 167: process(); ! 168: return 1; ! 169: } ! 170: return copy_file(file); ! 171: } ! 172: ! 173: /* ! 174: * Copy a file verbatim. ! 175: * Return 0 if not found or not readable, 1 on success. ! 176: */ ! 177: copy_file(s) char *s; ! 178: { ! 179: register FILE *fp; ! 180: register int c; ! 181: ! 182: if ((fp = fopen(s, "rb")) == NULL) ! 183: return 0; ! 184: while ((c = fgetc(fp)) != EOF) ! 185: putchar(c); ! 186: fclose(fp); ! 187: return 1; ! 188: } ! 189: ! 190: /* ! 191: * Read a block into the buffer 'bp' starting at seek position ! 192: * 'l' in the temp file. ! 193: */ ! 194: nread(l, bp) ! 195: long l; ! 196: char *bp; ! 197: { ! 198: if (tmpseek-l <= DBFSIZE) { ! 199: copystr(bp, diskbuf, DBFSIZE, 1); ! 200: return; ! 201: } ! 202: lseek(fileno(tmp), (long) l, 0); ! 203: if (read(fileno(tmp), bp, DBFSIZE) != DBFSIZE) ! 204: panic("temporary file read error"); ! 205: } ! 206: ! 207: /* ! 208: * Write the buffer 'bp' which contains 'n' elements of size 's' ! 209: * onto the end of the temp file. ! 210: */ ! 211: nwrite(bp, s, n) register char *bp; unsigned s; register unsigned n; ! 212: { ! 213: unsigned bno, off; ! 214: register char *dp; ! 215: ! 216: bno = tmpseek / DBFSIZE; ! 217: off = tmpseek % DBFSIZE; ! 218: if (bno!=0 && off==0) { ! 219: --bno; ! 220: off += DBFSIZE; ! 221: } ! 222: dp = &diskbuf[off]; ! 223: s = n *= s; ! 224: while (n--) { ! 225: if (dp >= &diskbuf[DBFSIZE]) { ! 226: lseek(fileno(tmp), (long) bno++*DBFSIZE, 0); ! 227: if (write(fileno(tmp), diskbuf, DBFSIZE) != DBFSIZE) ! 228: panic("temporary file write error"); ! 229: dp = &diskbuf[0]; ! 230: } ! 231: *dp++ = *bp++; ! 232: } ! 233: tmpseek += s; ! 234: } ! 235: ! 236: /* ! 237: * Given a string, return a pointer to a copy of it. ! 238: */ ! 239: char * ! 240: duplstr(s) register char *s; ! 241: { ! 242: return strcpy(nalloc(strlen(s) + 1), s); ! 243: } ! 244: ! 245: /* ! 246: * Copy the array of 'n' elements containing a structure of size ! 247: * 'size' from 's2' to 's1'. ! 248: */ ! 249: copystr(s1, s2, size, n) char *s1, *s2; int size; register int n; ! 250: { ! 251: if ((n *= size) == 0) ! 252: return; ! 253: memcpy(s1, s2, n); ! 254: } ! 255: ! 256: /* ! 257: * Allocate 'n' bytes. ! 258: */ ! 259: char * ! 260: nalloc(n) ! 261: { ! 262: extern char *calloc(); ! 263: register char *cp; ! 264: ! 265: if ((cp = calloc(n, 1)) == NULL) ! 266: #if MSDOS ! 267: panic("out of space"); /* no memok() in MS-DOS libc */ ! 268: #else ! 269: panic("out of space - memory %s", (memok() ? "good" : "bad")); ! 270: #endif ! 271: return cp; ! 272: } ! 273: ! 274: /* ! 275: * Release the given storage. ! 276: */ ! 277: nfree(cp) ! 278: char *cp; ! 279: { ! 280: free(cp); ! 281: } ! 282: ! 283: /* ! 284: * Execute conditional. ! 285: * bp points to the remainder of the line. ! 286: * Called from .el and .ie. ! 287: */ ! 288: do_cond(cond, bp) int cond; unsigned char *bp; ! 289: { ! 290: unsigned char charbuf[CBFSIZE]; ! 291: register unsigned char *cp; ! 292: unsigned char c; ! 293: ! 294: while (isascii(*bp) && isspace(*bp)) ! 295: bp++; /* skip leading space */ ! 296: if (cond) { ! 297: /* Execute true branch. */ ! 298: cp = charbuf; ! 299: bracelevel = oldbracelevel; /* restore original brace level */ ! 300: if (*bp == EBEG) { ! 301: bp++; /* ignore \{ */ ! 302: bracelevel++; ! 303: } ! 304: while (c = *bp++) ! 305: if (cp < &charbuf[CBFSIZE-2]) ! 306: *cp++ = c; ! 307: *cp++ = '\n'; ! 308: *cp = '\0'; ! 309: cp = duplstr(charbuf); ! 310: adscore(cp); /* execute remainder */ ! 311: strp->x3.s_srel = cp; ! 312: } else { ! 313: /* Skip false branch. */ ! 314: if (*bp != EBEG) ! 315: return; /* one-line conditional */ ! 316: for (; *bp; bp++) { ! 317: if (*bp == EBEG) ! 318: ++infalse; ! 319: else if (*bp == EEND) ! 320: --infalse; ! 321: } ! 322: if (infalse == 0) ! 323: return; /* \{ ... \} on one line */ ! 324: while (infalse && (c = getf(0))) { ! 325: if (c == EBEG) ! 326: ++infalse; ! 327: else if (c == EEND) ! 328: --infalse; /* scan to matching \} */ ! 329: } ! 330: while (getf(0) != '\n') ! 331: ; /* then scan to newline */ ! 332: } ! 333: } ! 334: ! 335: /* ! 336: * Set a value, saving old value. ! 337: * Called by various requests. ! 338: */ ! 339: setval(vp, op, arg, mul, div) int *vp, *op; char *arg; long mul, div; ! 340: { ! 341: register int val; ! 342: ! 343: val = *vp; /* save value */ ! 344: *vp = number(arg, mul, div, val, 0, *op); /* set value */ ! 345: *op = val; /* save old */ ! 346: } ! 347: ! 348: /* ! 349: * Return the number of the named font. ! 350: * Return -1 if not found. ! 351: */ ! 352: int ! 353: font_num(name) char name[2]; ! 354: { ! 355: register FTB *p; ! 356: ! 357: for (p = fontab; p < &fontab[NFNAMES]; p++) { ! 358: if (p->f_name[0] == '\0') ! 359: break; ! 360: else if ((p->f_name[0] == name[0]) && (p->f_name[1] == name[1])) ! 361: return p->f_font; ! 362: } ! 363: return -1; ! 364: } ! 365: ! 366: /* ! 367: * Return the number of the named font. ! 368: * Print an error message and return -1 if not found. ! 369: */ ! 370: int ! 371: font_number(name, s) char name[2]; char *s; ! 372: { ! 373: register int n; ! 374: ! 375: if ((n = font_num(name)) == -1) ! 376: printe("%scannot find font %c%c", (s==NULL) ? "" : s, name[0], name[1]); ! 377: return n; ! 378: } ! 379: ! 380: /* ! 381: * Assign a font number to a name. ! 382: * If there is no font of the given name, add one. ! 383: * Return the previously assigned font number, or -1 if none. ! 384: */ ! 385: int ! 386: assign_font(name, c) char *name; int c; ! 387: { ! 388: char a, b; ! 389: register FTB *p; ! 390: ! 391: a = name[0]; ! 392: b = name[1]; ! 393: for (p = fontab; p < &fontab[NFNAMES]; p++) { ! 394: if ((p->f_name[0] == a) && (p->f_name[1] == b)) { ! 395: ! 396: /* Replace existing entry */ ! 397: a = p->f_font; ! 398: p->f_font = c; ! 399: ! 400: /* Watch for current, tab, underline fonts. */ ! 401: if (a == curfont) ! 402: dev_font(c); ! 403: if (a == tfn) ! 404: tfn = c; ! 405: if (a == ufn) ! 406: ufn = c; ! 407: ! 408: return a; ! 409: } else if (p->f_name[0] == '\0') { ! 410: /* Add new entry */ ! 411: p->f_name[0] = a; ! 412: p->f_name[1] = b; ! 413: p->f_font = c; ! 414: return -1; ! 415: } ! 416: } ! 417: printe("no room for new font name %c%c", a, ((b) ? b : ' ')); ! 418: return -1; ! 419: } ! 420: ! 421: /* ! 422: * Given a font number, change font. ! 423: */ ! 424: setfontnum(n, setflag) register int n; int setflag; ! 425: { ! 426: register FTB *p; ! 427: ! 428: for (p = fontab; p < &fontab[NFNAMES]; p++) { ! 429: if (p->f_font == n) { ! 430: setfont(p->f_name, setflag); ! 431: return; ! 432: } else if (p->f_name[0] == '\0') ! 433: break; ! 434: } ! 435: printe("cannot find font %d", n); ! 436: } ! 437: ! 438: /* ! 439: * Given a font name, change font. ! 440: * Understands \fP and \fn, saves previous font in oldfon. ! 441: * Return the new font number, or -1 if not found. ! 442: * dev_font() does the real work. ! 443: */ ! 444: int ! 445: setfont(name, setflag) char name[2]; int setflag; ! 446: { ! 447: register int n; ! 448: ! 449: if ((name[0] >= '0') && (name[0] <= '9')) { ! 450: n = name[0] - '0'; ! 451: name[0] = mapfont[n][0]; ! 452: name[1] = mapfont[n][1]; ! 453: } ! 454: if (name[0]=='P' && name[1]=='\0') { ! 455: name[0] = oldfon[0]; ! 456: name[1] = oldfon[1]; ! 457: } ! 458: if ((n = font_number(name, NULL)) < 0) { ! 459: if (setflag) { ! 460: /* ! 461: * Bogus font change sets oldfon so \fP gets back ! 462: * from the bogus font to the present font. ! 463: * The bogus font change is really ignored. ! 464: */ ! 465: oldfon[0] = fon[0]; ! 466: oldfon[1] = fon[1]; ! 467: } ! 468: return -1; ! 469: } ! 470: dev_font(n); ! 471: if (setflag) { ! 472: oldfon[0] = fon[0]; ! 473: oldfon[1] = fon[1]; ! 474: fon[0] = name[0]; ! 475: fon[1] = name[1]; ! 476: } ! 477: return n; ! 478: } ! 479: ! 480: /* ! 481: * Print out a warning. ! 482: */ ! 483: /*VARARGS*/ ! 484: printe(a1) char *a1; ! 485: { ! 486: register STR *sp; ! 487: ! 488: fprintf(stderr, "%s: ", argv0); ! 489: for (sp=strp; sp; sp=sp->x1.s_next) { ! 490: if (sp->x1.s_type == SFILE) { ! 491: fprintf(stderr, "%s: %d: ", sp->x2.s_fname, sp->x2.s_clnc); ! 492: break; ! 493: } ! 494: } ! 495: fprintf(stderr, "%r\n", &a1); ! 496: if (dflag) ! 497: fprintf(stderr, "Request: %s\n", miscbuf); ! 498: } ! 499: ! 500: /* ! 501: * Print an unimplemented warning. ! 502: */ ! 503: printu(s) char *s; ! 504: { ! 505: printe("%s not implemented yet", s); ! 506: } ! 507: ! 508: /* ! 509: * An irrecoverable error was found. ! 510: * Print out an error message and leave. ! 511: */ ! 512: /*VARARGS*/ ! 513: panic(s) ! 514: { ! 515: fprintf(stderr, "%s: %r\n", argv0, &s); ! 516: leave(1); ! 517: } ! 518: ! 519: /* Debug stuff follows, used to be in codebug.c. */ ! 520: ! 521: #if (DDEBUG != 0) ! 522: #if (DDEBUG & DBGCODE) ! 523: ! 524: static char *codtab[] = { ! 525: "DNULL", ! 526: "DHMOV (move horizontal)", ! 527: "DVMOV (move vertical)", ! 528: "DFONT (change font)", ! 529: "DPSZE (change pointsize)", ! 530: "DSPAR (space down and return)", ! 531: "DPADC (Paddable character)", ! 532: "DHYPH (Place to hyphenate)", ! 533: "DHYPC (Hyphen character)" ! 534: }; ! 535: ! 536: codebug(code, parm1) ! 537: { ! 538: if (code <= 0) { ! 539: printd(DBGCODE, "%s %u\n", codtab[-code], parm1); ! 540: } else { ! 541: printd(DBGCODE, "%c (width=%d)\n", code, parm1); ! 542: } ! 543: } ! 544: #endif ! 545: ! 546: static char *dbgtbl[] = { ! 547: "CHECKpoints", ! 548: "REGisterS", ! 549: "REGister eXecution", ! 550: "output CODEs", ! 551: "DIVeRsions", ! 552: "FILEs", ! 553: "FUNCtions", ! 554: "CHARacters", ! 555: "PROCess trace", ! 556: "MACro eXecution", ! 557: "MISCelaneous", ! 558: "MOVEment", ! 559: "ENViRonment", ! 560: "CALL tracing" ! 561: }; ! 562: ! 563: printd(lvl, fmt) ! 564: int lvl; ! 565: char *fmt; ! 566: { ! 567: if (lvl & dbglvl) ! 568: fprintf(stderr, "%r", &fmt); ! 569: } ! 570: ! 571: void dbginit() ! 572: { ! 573: register int t=dbglvl; ! 574: register int j; ! 575: register int m=1; ! 576: ! 577: if (dbglvl == 0) ! 578: return; ! 579: for (j=0; j<15; j++) { ! 580: if (t & m) ! 581: fprintf(stderr, "debugging %s\n", dbgtbl[j]); ! 582: m <<= 1; ! 583: } ! 584: } ! 585: #endif ! 586: ! 587: /* end of misc.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.