|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)deroff.c 4.7 (Berkeley) 88/04/24"; ! 3: #endif not lint ! 4: ! 5: #include <stdio.h> ! 6: ! 7: /* ! 8: * Deroff command -- strip troff, eqn, and Tbl sequences from ! 9: * a file. Has two flags argument, -w, to cause output one word per line ! 10: * rather than in the original format. ! 11: * -mm (or -ms) causes the corresponding macro's to be interpreted ! 12: * so that just sentences are output ! 13: * -ml also gets rid of lists. ! 14: * Deroff follows .so and .nx commands, removes contents of macro ! 15: * definitions, equations (both .EQ ... .EN and $...$), ! 16: * Tbl command sequences, and Troff backslash constructions. ! 17: * ! 18: * All input is through the Cget macro; ! 19: * the most recently read character is in c. ! 20: * ! 21: * Modified by Robert Henry to process -me and -man macros. ! 22: */ ! 23: ! 24: #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) ) ! 25: #define C1get ( (c=getc(infile)) == EOF ? eof() : c) ! 26: ! 27: #ifdef DEBUG ! 28: # define C _C() ! 29: # define C1 _C1() ! 30: #else not DEBUG ! 31: # define C Cget ! 32: # define C1 C1get ! 33: #endif not DEBUG ! 34: ! 35: #define SKIP while(C != '\n') ! 36: #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c ! 37: ! 38: #define YES 1 ! 39: #define NO 0 ! 40: #define MS 0 /* -ms */ ! 41: #define MM 1 /* -mm */ ! 42: #define ME 2 /* -me */ ! 43: #define MA 3 /* -man */ ! 44: ! 45: #ifdef DEBUG ! 46: char *mactab[] = {"-ms", "-mm", "-me", "-ma"}; ! 47: #endif DEBUG ! 48: ! 49: #define ONE 1 ! 50: #define TWO 2 ! 51: ! 52: #define NOCHAR -2 ! 53: #define SPECIAL 0 ! 54: #define APOS 1 ! 55: #define PUNCT 2 ! 56: #define DIGIT 3 ! 57: #define LETTER 4 ! 58: ! 59: int wordflag; ! 60: int msflag; /* processing a source written using a mac package */ ! 61: int mac; /* which package */ ! 62: int disp; ! 63: int parag; ! 64: int inmacro; ! 65: int intable; ! 66: int keepblock; /* keep blocks of text; normally false when msflag */ ! 67: ! 68: char chars[128]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */ ! 69: ! 70: char line[512]; ! 71: char *lp; ! 72: ! 73: int c; ! 74: int pc; ! 75: int ldelim; ! 76: int rdelim; ! 77: ! 78: ! 79: int argc; ! 80: char **argv; ! 81: ! 82: char fname[50]; ! 83: FILE *files[15]; ! 84: FILE **filesp; ! 85: FILE *infile; ! 86: FILE *opn(); ! 87: /* ! 88: * Flags for matching conditions other than ! 89: * the macro name ! 90: */ ! 91: #define NONE 0 ! 92: #define FNEST 1 /* no nested files */ ! 93: #define NOMAC 2 /* no macro */ ! 94: #define MAC 3 /* macro */ ! 95: #define PARAG 4 /* in a paragraph */ ! 96: #define MSF 5 /* msflag is on */ ! 97: #define NBLK 6 /* set if no blocks to be kept */ ! 98: ! 99: /* ! 100: * Return codes from macro minions, determine where to jump, ! 101: * how to repeat/reprocess text ! 102: */ ! 103: #define COMX 1 /* goto comx */ ! 104: #define COM 2 /* goto com */ ! 105: ! 106: main(ac, av) ! 107: int ac; ! 108: char **av; ! 109: { ! 110: register int i; ! 111: int errflg = 0; ! 112: register optchar; ! 113: FILE *opn(); ! 114: int kflag = NO; ! 115: char *p; ! 116: ! 117: wordflag = NO; ! 118: msflag = NO; ! 119: mac = ME; ! 120: disp = NO; ! 121: parag = NO; ! 122: inmacro = NO; ! 123: intable = NO; ! 124: ldelim = NOCHAR; ! 125: rdelim = NOCHAR; ! 126: keepblock = YES; ! 127: ! 128: for(argc = ac - 1, argv = av + 1; ! 129: ( (argc > 0) ! 130: && (argv[0][0] == '-') ! 131: && (argv[0][1] != '\0') ); ! 132: --argc, ++argv ! 133: ){ ! 134: for(p = argv[0]+1; *p; ++p) { ! 135: switch(*p) { ! 136: case 'p': ! 137: parag=YES; ! 138: break; ! 139: case 'k': ! 140: kflag = YES; ! 141: break; ! 142: case 'w': ! 143: wordflag = YES; ! 144: kflag = YES; ! 145: break; ! 146: case 'm': ! 147: msflag = YES; ! 148: keepblock = NO; ! 149: switch(p[1]){ ! 150: case 'm': mac = MM; p++; break; ! 151: case 's': mac = MS; p++; break; ! 152: case 'e': mac = ME; p++; break; ! 153: case 'a': mac = MA; p++; break; ! 154: case 'l': disp = YES; p++; break; ! 155: default: errflg++; break; ! 156: } ! 157: break; ! 158: default: ! 159: errflg++; ! 160: } ! 161: } ! 162: } ! 163: ! 164: if (kflag) ! 165: keepblock = YES; ! 166: if (errflg) ! 167: fatal("usage: deroff [ -w ] [ -k] [ -m (a e m s l) ] [ file ] ... \n", ! 168: (char *) NULL); ! 169: ! 170: #ifdef DEBUG ! 171: printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n", ! 172: msflag, mactab[mac], keepblock, disp); ! 173: #endif DEBUG ! 174: if (argc == 0){ ! 175: infile = stdin; ! 176: } else { ! 177: infile = opn(argv[0]); ! 178: --argc; ! 179: ++argv; ! 180: } ! 181: ! 182: ! 183: files[0] = infile; ! 184: filesp = &files[0]; ! 185: ! 186: for(i='a'; i<='z' ; ++i) ! 187: chars[i] = LETTER; ! 188: for(i='A'; i<='Z'; ++i) ! 189: chars[i] = LETTER; ! 190: for(i='0'; i<='9'; ++i) ! 191: chars[i] = DIGIT; ! 192: chars['\''] = APOS; ! 193: chars['&'] = APOS; ! 194: chars['.'] = PUNCT; ! 195: chars[','] = PUNCT; ! 196: chars[';'] = PUNCT; ! 197: chars['?'] = PUNCT; ! 198: chars[':'] = PUNCT; ! 199: work(); ! 200: } ! 201: char *calloc(); ! 202: ! 203: skeqn() ! 204: { ! 205: while((c = getc(infile)) != rdelim) ! 206: if(c == EOF) ! 207: c = eof(); ! 208: else if(c == '"') ! 209: while( (c = getc(infile)) != '"') ! 210: if(c == EOF) ! 211: c = eof(); ! 212: else if(c == '\\') ! 213: if((c = getc(infile)) == EOF) ! 214: c = eof(); ! 215: if(msflag)return(c='x'); ! 216: return(c = ' '); ! 217: } ! 218: ! 219: FILE *opn(p) ! 220: register char *p; ! 221: { ! 222: FILE *fd; ! 223: ! 224: if( (fd = fopen(p, "r")) == NULL) { ! 225: fprintf(stderr, "Deroff: "); ! 226: perror(p); ! 227: exit(1); ! 228: } ! 229: ! 230: return(fd); ! 231: } ! 232: ! 233: eof() ! 234: { ! 235: if(infile != stdin) ! 236: fclose(infile); ! 237: if(filesp > files) ! 238: infile = *--filesp; ! 239: else if (argc > 0) { ! 240: infile = opn(argv[0]); ! 241: --argc; ! 242: ++argv; ! 243: } else ! 244: exit(0); ! 245: return(C); ! 246: } ! 247: ! 248: getfname() ! 249: { ! 250: register char *p; ! 251: struct chain { ! 252: struct chain *nextp; ! 253: char *datap; ! 254: } *chainblock; ! 255: register struct chain *q; ! 256: static struct chain *namechain = NULL; ! 257: char *copys(); ! 258: ! 259: while(C == ' ') ; ! 260: ! 261: for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p) ! 262: C; ! 263: *p = '\0'; ! 264: while(c != '\n') ! 265: C; ! 266: ! 267: /* see if this name has already been used */ ! 268: ! 269: for(q = namechain ; q; q = q->nextp) ! 270: if( ! strcmp(fname, q->datap)) ! 271: { ! 272: fname[0] = '\0'; ! 273: return; ! 274: } ! 275: ! 276: q = (struct chain *) calloc(1, sizeof(*chainblock)); ! 277: q->nextp = namechain; ! 278: q->datap = copys(fname); ! 279: namechain = q; ! 280: } ! 281: ! 282: fatal(s,p) ! 283: char *s, *p; ! 284: { ! 285: fprintf(stderr, "Deroff: "); ! 286: fprintf(stderr, s, p); ! 287: exit(1); ! 288: } ! 289: ! 290: /*ARGSUSED*/ ! 291: textline(str, constant) ! 292: char *str; ! 293: int constant; ! 294: { ! 295: if (wordflag) { ! 296: msputwords(0); ! 297: return; ! 298: } ! 299: puts(str); ! 300: } ! 301: ! 302: work() ! 303: { ! 304: for( ;; ) ! 305: { ! 306: C; ! 307: #ifdef FULLDEBUG ! 308: printf("Starting work with `%c'\n", c); ! 309: #endif FULLDEBUG ! 310: if(c == '.' || c == '\'') ! 311: comline(); ! 312: else ! 313: regline(textline, TWO); ! 314: } ! 315: } ! 316: ! 317: regline(pfunc, constant) ! 318: int (*pfunc)(); ! 319: int constant; ! 320: { ! 321: line[0] = c; ! 322: lp = line; ! 323: for( ; ; ) ! 324: { ! 325: if(c == '\\') { ! 326: *lp = ' '; ! 327: backsl(); ! 328: } ! 329: if(c == '\n') ! 330: break; ! 331: if(intable && c=='T') { ! 332: *++lp = C; ! 333: if(c=='{' || c=='}') { ! 334: lp[-1] = ' '; ! 335: *lp = C; ! 336: } ! 337: } else { ! 338: *++lp = C; ! 339: } ! 340: } ! 341: ! 342: *lp = '\0'; ! 343: ! 344: if(line[0] != '\0') ! 345: (*pfunc)(line, constant); ! 346: } ! 347: ! 348: macro() ! 349: { ! 350: if(msflag){ ! 351: do { ! 352: SKIP; ! 353: } while(C!='.' || C!='.' || C=='.'); /* look for .. */ ! 354: if(c != '\n')SKIP; ! 355: return; ! 356: } ! 357: SKIP; ! 358: inmacro = YES; ! 359: } ! 360: ! 361: tbl() ! 362: { ! 363: while(C != '.'); ! 364: SKIP; ! 365: intable = YES; ! 366: } ! 367: stbl() ! 368: { ! 369: while(C != '.'); ! 370: SKIP_TO_COM; ! 371: if(c != 'T' || C != 'E'){ ! 372: SKIP; ! 373: pc=c; ! 374: while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c; ! 375: } ! 376: } ! 377: ! 378: eqn() ! 379: { ! 380: register int c1, c2; ! 381: register int dflg; ! 382: char last; ! 383: ! 384: last=0; ! 385: dflg = 1; ! 386: SKIP; ! 387: ! 388: for( ;;) ! 389: { ! 390: if(C1 == '.' || c == '\'') ! 391: { ! 392: while(C1==' ' || c=='\t') ! 393: ; ! 394: if(c=='E' && C1=='N') ! 395: { ! 396: SKIP; ! 397: if(msflag && dflg){ ! 398: putchar('x'); ! 399: putchar(' '); ! 400: if(last){ ! 401: putchar(last); ! 402: putchar('\n'); ! 403: } ! 404: } ! 405: return; ! 406: } ! 407: } ! 408: else if(c == 'd') /* look for delim */ ! 409: { ! 410: if(C1=='e' && C1=='l') ! 411: if( C1=='i' && C1=='m') ! 412: { ! 413: while(C1 == ' '); ! 414: if((c1=c)=='\n' || (c2=C1)=='\n' ! 415: || (c1=='o' && c2=='f' && C1=='f') ) ! 416: { ! 417: ldelim = NOCHAR; ! 418: rdelim = NOCHAR; ! 419: } ! 420: else { ! 421: ldelim = c1; ! 422: rdelim = c2; ! 423: } ! 424: } ! 425: dflg = 0; ! 426: } ! 427: ! 428: if(c != '\n') while(C1 != '\n'){ ! 429: if(chars[c] == PUNCT)last = c; ! 430: else if(c != ' ')last = 0; ! 431: } ! 432: } ! 433: } ! 434: ! 435: backsl() /* skip over a complete backslash construction */ ! 436: { ! 437: int bdelim; ! 438: ! 439: sw: ! 440: switch(C) ! 441: { ! 442: case '"': ! 443: SKIP; ! 444: return; ! 445: case 's': ! 446: if(C == '\\') backsl(); ! 447: else { ! 448: while(C>='0' && c<='9') ; ! 449: ungetc(c,infile); ! 450: c = '0'; ! 451: } ! 452: --lp; ! 453: return; ! 454: ! 455: case 'f': ! 456: case 'n': ! 457: case '*': ! 458: if(C != '(') ! 459: return; ! 460: ! 461: case '(': ! 462: if(msflag){ ! 463: if(C == 'e'){ ! 464: if(C == 'm'){ ! 465: *lp = '-'; ! 466: return; ! 467: } ! 468: } ! 469: else if(c != '\n')C; ! 470: return; ! 471: } ! 472: if(C != '\n') C; ! 473: return; ! 474: ! 475: case '$': ! 476: C; /* discard argument number */ ! 477: return; ! 478: ! 479: case 'b': ! 480: case 'x': ! 481: case 'v': ! 482: case 'h': ! 483: case 'w': ! 484: case 'o': ! 485: case 'l': ! 486: case 'L': ! 487: if( (bdelim=C) == '\n') ! 488: return; ! 489: while(C!='\n' && c!=bdelim) ! 490: if(c == '\\') backsl(); ! 491: return; ! 492: ! 493: case '\\': ! 494: if(inmacro) ! 495: goto sw; ! 496: default: ! 497: return; ! 498: } ! 499: } ! 500: ! 501: char *copys(s) ! 502: register char *s; ! 503: { ! 504: register char *t, *t0; ! 505: ! 506: if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL) ! 507: fatal("Cannot allocate memory", (char *) NULL); ! 508: ! 509: while( *t++ = *s++ ) ! 510: ; ! 511: return(t0); ! 512: } ! 513: ! 514: sce() ! 515: { ! 516: register char *ap; ! 517: register int n, i; ! 518: char a[10]; ! 519: for(ap=a;C != '\n';ap++){ ! 520: *ap = c; ! 521: if(ap == &a[9]){ ! 522: SKIP; ! 523: ap=a; ! 524: break; ! 525: } ! 526: } ! 527: if(ap != a)n = atoi(a); ! 528: else n = 1; ! 529: for(i=0;i<n;){ ! 530: if(C == '.'){ ! 531: if(C == 'c'){ ! 532: if(C == 'e'){ ! 533: while(C == ' '); ! 534: if(c == '0'){ ! 535: SKIP; ! 536: break; ! 537: } ! 538: else SKIP; ! 539: } ! 540: else SKIP; ! 541: } ! 542: else if(c == 'P' || C == 'P'){ ! 543: if(c != '\n')SKIP; ! 544: break; ! 545: } ! 546: else if(c != '\n')SKIP; ! 547: } ! 548: else { ! 549: SKIP; ! 550: i++; ! 551: } ! 552: } ! 553: } ! 554: ! 555: refer(c1) ! 556: { ! 557: register int c2; ! 558: if(c1 != '\n') ! 559: SKIP; ! 560: while(1){ ! 561: if(C != '.') ! 562: SKIP; ! 563: else { ! 564: if(C != ']') ! 565: SKIP; ! 566: else { ! 567: while(C != '\n') ! 568: c2=c; ! 569: if(chars[c2] == PUNCT)putchar(c2); ! 570: return; ! 571: } ! 572: } ! 573: } ! 574: } ! 575: ! 576: inpic() ! 577: { ! 578: register int c1; ! 579: register char *p1; ! 580: SKIP; ! 581: p1 = line; ! 582: c = '\n'; ! 583: while(1){ ! 584: c1 = c; ! 585: if(C == '.' && c1 == '\n'){ ! 586: if(C != 'P'){ ! 587: if(c == '\n')continue; ! 588: else { SKIP; c='\n'; continue;} ! 589: } ! 590: if(C != 'E'){ ! 591: if(c == '\n')continue; ! 592: else { SKIP; c='\n';continue; } ! 593: } ! 594: SKIP; ! 595: return; ! 596: } ! 597: else if(c == '\"'){ ! 598: while(C != '\"'){ ! 599: if(c == '\\'){ ! 600: if(C == '\"')continue; ! 601: ungetc(c,infile); ! 602: backsl(); ! 603: } ! 604: else *p1++ = c; ! 605: } ! 606: *p1++ = ' '; ! 607: } ! 608: else if(c == '\n' && p1 != line){ ! 609: *p1 = '\0'; ! 610: if(wordflag)msputwords(NO); ! 611: else { ! 612: puts(line); ! 613: putchar('\n'); ! 614: } ! 615: p1 = line; ! 616: } ! 617: } ! 618: } ! 619: ! 620: #ifdef DEBUG ! 621: _C1() ! 622: { ! 623: return(C1get); ! 624: } ! 625: _C() ! 626: { ! 627: return(Cget); ! 628: } ! 629: #endif DEBUG ! 630: ! 631: /* ! 632: * Macro processing ! 633: * ! 634: * Macro table definitions ! 635: */ ! 636: #define reg register ! 637: typedef int pacmac; /* compressed macro name */ ! 638: int argconcat = 0; /* concat arguments together (-me only) */ ! 639: ! 640: #define tomac(c1, c2) ((((c1) & 0xFF) << 8) | ((c2) & 0xFF)) ! 641: #define frommac(src, c1, c2) (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF)) ! 642: ! 643: struct mactab{ ! 644: int condition; ! 645: pacmac macname; ! 646: int (*func)(); ! 647: }; ! 648: struct mactab troffmactab[]; ! 649: struct mactab ppmactab[]; ! 650: struct mactab msmactab[]; ! 651: struct mactab mmmactab[]; ! 652: struct mactab memactab[]; ! 653: struct mactab manmactab[]; ! 654: /* ! 655: * macro table initialization ! 656: */ ! 657: #define M(cond, c1, c2, func) {cond, tomac(c1, c2), func} ! 658: ! 659: /* ! 660: * Put out a macro line, using ms and mm conventions. ! 661: */ ! 662: msputmac(s, constant) ! 663: register char *s; ! 664: int constant; ! 665: { ! 666: register char *t; ! 667: register found; ! 668: int last; ! 669: found = 0; ! 670: ! 671: if (wordflag) { ! 672: msputwords(YES); ! 673: return; ! 674: } ! 675: while(*s) ! 676: { ! 677: while(*s==' ' || *s=='\t') ! 678: putchar(*s++); ! 679: for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t) ! 680: ; ! 681: if(*s == '\"')s++; ! 682: if(t>s+constant && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){ ! 683: while(s < t) ! 684: if(*s == '\"')s++; ! 685: else ! 686: putchar(*s++); ! 687: last = *(t-1); ! 688: found++; ! 689: } ! 690: else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0') ! 691: putchar(*s++); ! 692: else{ ! 693: last = *(t-1); ! 694: s = t; ! 695: } ! 696: } ! 697: putchar('\n'); ! 698: if(msflag && chars[last] == PUNCT){ ! 699: putchar(last); ! 700: putchar('\n'); ! 701: } ! 702: } ! 703: /* ! 704: * put out words (for the -w option) with ms and mm conventions ! 705: */ ! 706: msputwords(macline) ! 707: int macline; /* is this is a macro line */ ! 708: { ! 709: register char *p, *p1; ! 710: int i, nlet; ! 711: ! 712: for(p1 = line ; ;) { ! 713: /* ! 714: * skip initial specials ampersands and apostrophes ! 715: */ ! 716: while( chars[*p1] < DIGIT) ! 717: if(*p1++ == '\0') return; ! 718: nlet = 0; ! 719: for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p) ! 720: if(i == LETTER) ++nlet; ! 721: ! 722: if (nlet > 1 && chars[p1[0]] == LETTER) { ! 723: /* ! 724: * delete trailing ampersands and apostrophes ! 725: */ ! 726: while( (i=chars[p[-1]]) == PUNCT || i == APOS ) ! 727: --p; ! 728: while(p1 < p) ! 729: putchar(*p1++); ! 730: putchar('\n'); ! 731: } else { ! 732: p1 = p; ! 733: } ! 734: } ! 735: } ! 736: /* ! 737: * put out a macro using the me conventions ! 738: */ ! 739: #define SKIPBLANK(cp) while(*cp == ' ' || *cp == '\t') { cp++; } ! 740: #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; } ! 741: ! 742: meputmac(cp, constant) ! 743: reg char *cp; ! 744: int constant; ! 745: { ! 746: reg char *np; ! 747: int found; ! 748: int argno; ! 749: int last; ! 750: int inquote; ! 751: ! 752: if (wordflag) { ! 753: meputwords(YES); ! 754: return; ! 755: } ! 756: for (argno = 0; *cp; argno++){ ! 757: SKIPBLANK(cp); ! 758: inquote = (*cp == '"'); ! 759: if (inquote) ! 760: cp++; ! 761: for (np = cp; *np; np++){ ! 762: switch(*np){ ! 763: case '\n': ! 764: case '\0': break; ! 765: case '\t': ! 766: case ' ': if (inquote) { ! 767: continue; ! 768: } else { ! 769: goto endarg; ! 770: } ! 771: case '"': if(inquote && np[1] == '"'){ ! 772: strcpy(np, np + 1); ! 773: np++; ! 774: continue; ! 775: } else { ! 776: *np = ' '; /* bye bye " */ ! 777: goto endarg; ! 778: } ! 779: default: continue; ! 780: } ! 781: } ! 782: endarg: ; ! 783: /* ! 784: * cp points at the first char in the arg ! 785: * np points one beyond the last char in the arg ! 786: */ ! 787: if ((argconcat == 0) || (argconcat != argno)) { ! 788: putchar(' '); ! 789: } ! 790: #ifdef FULLDEBUG ! 791: { ! 792: char *p; ! 793: printf("[%d,%d: ", argno, np - cp); ! 794: for (p = cp; p < np; p++) { ! 795: putchar(*p); ! 796: } ! 797: printf("]"); ! 798: } ! 799: #endif FULLDEBUG ! 800: /* ! 801: * Determine if the argument merits being printed ! 802: * ! 803: * constant is the cut off point below which something ! 804: * is not a word. ! 805: */ ! 806: if ( ( (np - cp) > constant) ! 807: && ( inquote ! 808: || (chars[cp[0]] == LETTER)) ){ ! 809: for (cp = cp; cp < np; cp++){ ! 810: putchar(*cp); ! 811: } ! 812: last = np[-1]; ! 813: found++; ! 814: } else ! 815: if(found && (np - cp == 1) && chars[*cp] == PUNCT){ ! 816: putchar(*cp); ! 817: } else { ! 818: last = np[-1]; ! 819: } ! 820: cp = np; ! 821: } ! 822: if(msflag && chars[last] == PUNCT) ! 823: putchar(last); ! 824: putchar('\n'); ! 825: } ! 826: /* ! 827: * put out words (for the -w option) with ms and mm conventions ! 828: */ ! 829: meputwords(macline) ! 830: int macline; ! 831: { ! 832: msputwords(macline); ! 833: } ! 834: /* ! 835: * ! 836: * Skip over a nested set of macros ! 837: * ! 838: * Possible arguments to noblock are: ! 839: * ! 840: * fi end of unfilled text ! 841: * PE pic ending ! 842: * DE display ending ! 843: * ! 844: * for ms and mm only: ! 845: * KE keep ending ! 846: * ! 847: * NE undocumented match to NS (for mm?) ! 848: * LE mm only: matches RL or *L (for lists) ! 849: * ! 850: * for me: ! 851: * ([lqbzcdf] ! 852: */ ! 853: ! 854: noblock(a1, a2) ! 855: char a1, a2; ! 856: { ! 857: register int c1,c2; ! 858: register int eqnf; ! 859: int lct; ! 860: lct = 0; ! 861: eqnf = 1; ! 862: SKIP; ! 863: while(1){ ! 864: while(C != '.') ! 865: if(c == '\n') ! 866: continue; ! 867: else ! 868: SKIP; ! 869: if((c1=C) == '\n') ! 870: continue; ! 871: if((c2=C) == '\n') ! 872: continue; ! 873: if(c1==a1 && c2 == a2){ ! 874: SKIP; ! 875: if(lct != 0){ ! 876: lct--; ! 877: continue; ! 878: } ! 879: if(eqnf) ! 880: putchar('.'); ! 881: putchar('\n'); ! 882: return; ! 883: } else if(a1 == 'L' && c2 == 'L'){ ! 884: lct++; ! 885: SKIP; ! 886: } ! 887: /* ! 888: * equations (EQ) nested within a display ! 889: */ ! 890: else if(c1 == 'E' && c2 == 'Q'){ ! 891: if ( (mac == ME && a1 == ')') ! 892: || (mac != ME && a1 == 'D') ) { ! 893: eqn(); ! 894: eqnf=0; ! 895: } ! 896: } ! 897: /* ! 898: * turning on filling is done by the paragraphing ! 899: * macros ! 900: */ ! 901: else if(a1 == 'f') { /* .fi */ ! 902: if ( (mac == ME && (c2 == 'h' || c2 == 'p')) ! 903: ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) { ! 904: SKIP; ! 905: return; ! 906: } ! 907: } else { ! 908: SKIP; ! 909: } ! 910: } ! 911: } ! 912: ! 913: EQ() ! 914: { ! 915: eqn(); ! 916: return(0); ! 917: } ! 918: domacro() ! 919: { ! 920: macro(); ! 921: return(0); ! 922: } ! 923: PS() ! 924: { ! 925: for (C; c == ' ' || c == '\t'; C); ! 926: if (c == '<') { /* ".PS < file" -- don't expect a .PE */ ! 927: SKIP; ! 928: return(0); ! 929: } ! 930: if (!msflag) { ! 931: inpic(); ! 932: } else { ! 933: noblock('P', 'E'); ! 934: } ! 935: return(0); ! 936: } ! 937: ! 938: skip() ! 939: { ! 940: SKIP; ! 941: return(0); ! 942: } ! 943: ! 944: intbl() ! 945: { ! 946: if(msflag){ ! 947: stbl(); ! 948: } ! 949: else tbl(); ! 950: return(0); ! 951: } ! 952: ! 953: outtbl(){ intable = NO; } ! 954: ! 955: so() ! 956: { ! 957: getfname(); ! 958: if( fname[0] ) ! 959: infile = *++filesp = opn( fname ); ! 960: return(0); ! 961: } ! 962: nx() ! 963: { ! 964: getfname(); ! 965: if(fname[0] == '\0') exit(0); ! 966: if(infile != stdin) ! 967: fclose(infile); ! 968: infile = *filesp = opn(fname); ! 969: return(0); ! 970: } ! 971: skiptocom(){ SKIP_TO_COM; return(COMX); } ! 972: ! 973: PP(c12) ! 974: pacmac c12; ! 975: { ! 976: int c1, c2; ! 977: ! 978: frommac(c12, c1, c2); ! 979: printf(".%c%c",c1,c2); ! 980: while(C != '\n')putchar(c); ! 981: putchar('\n'); ! 982: return(0); ! 983: } ! 984: AU() ! 985: { ! 986: if(mac==MM) { ! 987: return(0); ! 988: } else { ! 989: SKIP_TO_COM; ! 990: return(COMX); ! 991: } ! 992: } ! 993: ! 994: SH(c12) ! 995: pacmac c12; ! 996: { ! 997: int c1, c2; ! 998: ! 999: frommac(c12, c1, c2); ! 1000: ! 1001: if(parag){ ! 1002: printf(".%c%c",c1,c2); ! 1003: while(C != '\n')putchar(c); ! 1004: putchar(c); ! 1005: putchar('!'); ! 1006: while(1){ ! 1007: while(C != '\n')putchar(c); ! 1008: putchar('\n'); ! 1009: if(C == '.') ! 1010: return(COM); ! 1011: putchar('!'); ! 1012: putchar(c); ! 1013: } ! 1014: /*NOTREACHED*/ ! 1015: } else { ! 1016: SKIP_TO_COM; ! 1017: return(COMX); ! 1018: } ! 1019: } ! 1020: ! 1021: UX() ! 1022: { ! 1023: if(wordflag) ! 1024: printf("UNIX\n"); ! 1025: else ! 1026: printf("UNIX "); ! 1027: return(0); ! 1028: } ! 1029: ! 1030: MMHU(c12) ! 1031: pacmac c12; ! 1032: { ! 1033: int c1, c2; ! 1034: ! 1035: frommac(c12, c1, c2); ! 1036: if(parag){ ! 1037: printf(".%c%c",c1,c2); ! 1038: while(C != '\n')putchar(c); ! 1039: putchar('\n'); ! 1040: } else { ! 1041: SKIP; ! 1042: } ! 1043: return(0); ! 1044: } ! 1045: ! 1046: mesnblock(c12) ! 1047: pacmac c12; ! 1048: { ! 1049: int c1, c2; ! 1050: ! 1051: frommac(c12, c1, c2); ! 1052: noblock(')',c2); ! 1053: return(0); ! 1054: } ! 1055: mssnblock(c12) ! 1056: pacmac c12; ! 1057: { ! 1058: int c1, c2; ! 1059: ! 1060: frommac(c12, c1, c2); ! 1061: noblock(c1,'E'); ! 1062: return(0); ! 1063: } ! 1064: nf() ! 1065: { ! 1066: noblock('f','i'); ! 1067: return(0); ! 1068: } ! 1069: ! 1070: ce() ! 1071: { ! 1072: sce(); ! 1073: return(0); ! 1074: } ! 1075: ! 1076: meip(c12) ! 1077: pacmac c12; ! 1078: { ! 1079: if(parag) ! 1080: mepp(c12); ! 1081: else if (wordflag) /* save the tag */ ! 1082: regline(meputmac, ONE); ! 1083: else { ! 1084: SKIP; ! 1085: } ! 1086: return(0); ! 1087: } ! 1088: /* ! 1089: * only called for -me .pp or .sh, when parag is on ! 1090: */ ! 1091: mepp(c12) ! 1092: pacmac c12; ! 1093: { ! 1094: PP(c12); /* eats the line */ ! 1095: return(0); ! 1096: } ! 1097: /* ! 1098: * Start of a section heading; output the section name if doing words ! 1099: */ ! 1100: mesh(c12) ! 1101: pacmac c12; ! 1102: { ! 1103: if (parag) ! 1104: mepp(c12); ! 1105: else if (wordflag) ! 1106: defcomline(c12); ! 1107: else { ! 1108: SKIP; ! 1109: } ! 1110: return(0); ! 1111: } ! 1112: /* ! 1113: * process a font setting ! 1114: */ ! 1115: mefont(c12) ! 1116: pacmac c12; ! 1117: { ! 1118: argconcat = 1; ! 1119: defcomline(c12); ! 1120: argconcat = 0; ! 1121: return(0); ! 1122: } ! 1123: manfont(c12) ! 1124: pacmac c12; ! 1125: { ! 1126: return(mefont(c12)); ! 1127: } ! 1128: manpp(c12) ! 1129: pacmac c12; ! 1130: { ! 1131: return(mepp(c12)); ! 1132: } ! 1133: ! 1134: defcomline(c12) ! 1135: pacmac c12; ! 1136: { ! 1137: int c1, c2; ! 1138: ! 1139: frommac(c12, c1, c2); ! 1140: if(msflag && mac==MM && c2=='L'){ ! 1141: if(disp || c1 == 'R') { ! 1142: noblock('L','E'); ! 1143: } else { ! 1144: SKIP; ! 1145: putchar('.'); ! 1146: } ! 1147: } ! 1148: else if(c1=='.' && c2=='.'){ ! 1149: if(msflag){ ! 1150: SKIP; ! 1151: return; ! 1152: } ! 1153: while(C == '.') ! 1154: /*VOID*/; ! 1155: } ! 1156: ++inmacro; ! 1157: /* ! 1158: * Process the arguments to the macro ! 1159: */ ! 1160: switch(mac){ ! 1161: default: ! 1162: case MM: ! 1163: case MS: ! 1164: if(c1 <= 'Z' && msflag) ! 1165: regline(msputmac, ONE); ! 1166: else ! 1167: regline(msputmac, TWO); ! 1168: break; ! 1169: case ME: ! 1170: regline(meputmac, ONE); ! 1171: break; ! 1172: } ! 1173: --inmacro; ! 1174: } ! 1175: ! 1176: comline() ! 1177: { ! 1178: reg int c1; ! 1179: reg int c2; ! 1180: pacmac c12; ! 1181: reg int mid; ! 1182: int lb, ub; ! 1183: int hit; ! 1184: static int tabsize = 0; ! 1185: static struct mactab *mactab = (struct mactab *)0; ! 1186: reg struct mactab *mp; ! 1187: ! 1188: if (mactab == 0){ ! 1189: buildtab(&mactab, &tabsize); ! 1190: } ! 1191: com: ! 1192: while(C==' ' || c=='\t') ! 1193: ; ! 1194: comx: ! 1195: if( (c1=c) == '\n') ! 1196: return; ! 1197: c2 = C; ! 1198: if(c1=='.' && c2 !='.') ! 1199: inmacro = NO; ! 1200: if(msflag && c1 == '['){ ! 1201: refer(c2); ! 1202: return; ! 1203: } ! 1204: if(parag && mac==MM && c1 == 'P' && c2 == '\n'){ ! 1205: printf(".P\n"); ! 1206: return; ! 1207: } ! 1208: if(c2 == '\n') ! 1209: return; ! 1210: /* ! 1211: * Single letter macro ! 1212: */ ! 1213: if (mac == ME && (c2 == ' ' || c2 == '\t') ) ! 1214: c2 = ' '; ! 1215: c12 = tomac(c1, c2); ! 1216: /* ! 1217: * binary search through the table of macros ! 1218: */ ! 1219: lb = 0; ! 1220: ub = tabsize - 1; ! 1221: while(lb <= ub){ ! 1222: mid = (ub + lb) / 2; ! 1223: mp = &mactab[mid]; ! 1224: if (mp->macname < c12) ! 1225: lb = mid + 1; ! 1226: else if (mp->macname > c12) ! 1227: ub = mid - 1; ! 1228: else { ! 1229: hit = 1; ! 1230: #ifdef FULLDEBUG ! 1231: printf("preliminary hit macro %c%c ", c1, c2); ! 1232: #endif FULLDEBUG ! 1233: switch(mp->condition){ ! 1234: case NONE: hit = YES; break; ! 1235: case FNEST: hit = (filesp == files); break; ! 1236: case NOMAC: hit = !inmacro; break; ! 1237: case MAC: hit = inmacro; break; ! 1238: case PARAG: hit = parag; break; ! 1239: case NBLK: hit = !keepblock; break; ! 1240: default: hit = 0; ! 1241: } ! 1242: if (hit) { ! 1243: #ifdef FULLDEBUG ! 1244: printf("MATCH\n"); ! 1245: #endif FULLDEBUG ! 1246: switch( (*(mp->func))(c12) ) { ! 1247: default: return; ! 1248: case COMX: goto comx; ! 1249: case COM: goto com; ! 1250: } ! 1251: } ! 1252: #ifdef FULLDEBUG ! 1253: printf("FAIL\n"); ! 1254: #endif FULLDEBUG ! 1255: break; ! 1256: } ! 1257: } ! 1258: defcomline(c12); ! 1259: } ! 1260: ! 1261: int macsort(p1, p2) ! 1262: struct mactab *p1, *p2; ! 1263: { ! 1264: return(p1->macname - p2->macname); ! 1265: } ! 1266: ! 1267: int sizetab(mp) ! 1268: reg struct mactab *mp; ! 1269: { ! 1270: reg int i; ! 1271: i = 0; ! 1272: if (mp){ ! 1273: for (; mp->macname; mp++, i++) ! 1274: /*VOID*/ ; ! 1275: } ! 1276: return(i); ! 1277: } ! 1278: ! 1279: struct mactab *macfill(dst, src) ! 1280: reg struct mactab *dst; ! 1281: reg struct mactab *src; ! 1282: { ! 1283: if (src) { ! 1284: while(src->macname){ ! 1285: *dst++ = *src++; ! 1286: } ! 1287: } ! 1288: return(dst); ! 1289: } ! 1290: ! 1291: buildtab(r_back, r_size) ! 1292: struct mactab **r_back; ! 1293: int *r_size; ! 1294: { ! 1295: int size; ! 1296: ! 1297: struct mactab *p, *p1, *p2; ! 1298: struct mactab *back; ! 1299: ! 1300: size = sizetab(troffmactab); ! 1301: size += sizetab(ppmactab); ! 1302: p1 = p2 = (struct mactab *)0; ! 1303: if (msflag){ ! 1304: switch(mac){ ! 1305: case ME: p1 = memactab; break; ! 1306: case MM: p1 = msmactab; ! 1307: p2 = mmmactab; break; ! 1308: ! 1309: case MS: p1 = msmactab; break; ! 1310: case MA: p1 = manmactab; break; ! 1311: default: break; ! 1312: } ! 1313: } ! 1314: size += sizetab(p1); ! 1315: size += sizetab(p2); ! 1316: back = (struct mactab *)calloc(size+2, sizeof(struct mactab)); ! 1317: ! 1318: p = macfill(back, troffmactab); ! 1319: p = macfill(p, ppmactab); ! 1320: p = macfill(p, p1); ! 1321: p = macfill(p, p2); ! 1322: ! 1323: qsort(back, size, sizeof(struct mactab), macsort); ! 1324: *r_size = size; ! 1325: *r_back = back; ! 1326: } ! 1327: ! 1328: /* ! 1329: * troff commands ! 1330: */ ! 1331: struct mactab troffmactab[] = { ! 1332: M(NONE, '\\','"', skip), /* comment */ ! 1333: M(NOMAC, 'd','e', domacro), /* define */ ! 1334: M(NOMAC, 'i','g', domacro), /* ignore till .. */ ! 1335: M(NOMAC, 'a','m', domacro), /* append macro */ ! 1336: M(NBLK, 'n','f', nf), /* filled */ ! 1337: M(NBLK, 'c','e', ce), /* centered */ ! 1338: ! 1339: M(NONE, 's','o', so), /* source a file */ ! 1340: M(NONE, 'n','x', nx), /* go to next file */ ! 1341: ! 1342: M(NONE, 't','m', skip), /* print string on tty */ ! 1343: M(NONE, 'h','w', skip), /* exception hyphen words */ ! 1344: M(NONE, 0,0, 0) ! 1345: }; ! 1346: /* ! 1347: * Preprocessor output ! 1348: */ ! 1349: struct mactab ppmactab[] = { ! 1350: M(FNEST, 'E','Q', EQ), /* equation starting */ ! 1351: M(FNEST, 'T','S', intbl), /* table starting */ ! 1352: M(FNEST, 'T','C', intbl), /* alternative table? */ ! 1353: M(FNEST, 'T','&', intbl), /* table reformatting */ ! 1354: M(NONE, 'T','E', outtbl),/* table ending */ ! 1355: M(NONE, 'P','S', PS), /* picture starting */ ! 1356: M(NONE, 0,0, 0) ! 1357: }; ! 1358: /* ! 1359: * Particular to ms and mm ! 1360: */ ! 1361: struct mactab msmactab[] = { ! 1362: M(NONE, 'T','L', skiptocom), /* title follows */ ! 1363: M(NONE, 'F','S', skiptocom), /* start footnote */ ! 1364: M(NONE, 'O','K', skiptocom), /* Other kws */ ! 1365: ! 1366: M(NONE, 'N','R', skip), /* undocumented */ ! 1367: M(NONE, 'N','D', skip), /* use supplied date */ ! 1368: ! 1369: M(PARAG, 'P','P', PP), /* begin parag */ ! 1370: M(PARAG, 'I','P', PP), /* begin indent parag, tag x */ ! 1371: M(PARAG, 'L','P', PP), /* left blocked parag */ ! 1372: ! 1373: M(NONE, 'A','U', AU), /* author */ ! 1374: M(NONE, 'A','I', AU), /* authors institution */ ! 1375: ! 1376: M(NONE, 'S','H', SH), /* section heading */ ! 1377: M(NONE, 'S','N', SH), /* undocumented */ ! 1378: M(NONE, 'U','X', UX), /* unix */ ! 1379: ! 1380: M(NBLK, 'D','S', mssnblock), /* start display text */ ! 1381: M(NBLK, 'K','S', mssnblock), /* start keep */ ! 1382: M(NBLK, 'K','F', mssnblock), /* start float keep */ ! 1383: M(NONE, 0,0, 0) ! 1384: }; ! 1385: ! 1386: struct mactab mmmactab[] = { ! 1387: M(NONE, 'H',' ', MMHU), /* -mm ? */ ! 1388: M(NONE, 'H','U', MMHU), /* -mm ? */ ! 1389: M(PARAG, 'P',' ', PP), /* paragraph for -mm */ ! 1390: M(NBLK, 'N','S', mssnblock), /* undocumented */ ! 1391: M(NONE, 0,0, 0) ! 1392: }; ! 1393: ! 1394: struct mactab memactab[] = { ! 1395: M(PARAG, 'p','p', mepp), ! 1396: M(PARAG, 'l','p', mepp), ! 1397: M(PARAG, 'n','p', mepp), ! 1398: M(NONE, 'i','p', meip), ! 1399: ! 1400: M(NONE, 's','h', mesh), ! 1401: M(NONE, 'u','h', mesh), ! 1402: ! 1403: M(NBLK, '(','l', mesnblock), ! 1404: M(NBLK, '(','q', mesnblock), ! 1405: M(NBLK, '(','b', mesnblock), ! 1406: M(NBLK, '(','z', mesnblock), ! 1407: M(NBLK, '(','c', mesnblock), ! 1408: ! 1409: M(NBLK, '(','d', mesnblock), ! 1410: M(NBLK, '(','f', mesnblock), ! 1411: M(NBLK, '(','x', mesnblock), ! 1412: ! 1413: M(NONE, 'r',' ', mefont), ! 1414: M(NONE, 'i',' ', mefont), ! 1415: M(NONE, 'b',' ', mefont), ! 1416: M(NONE, 'u',' ', mefont), ! 1417: M(NONE, 'q',' ', mefont), ! 1418: M(NONE, 'r','b', mefont), ! 1419: M(NONE, 'b','i', mefont), ! 1420: M(NONE, 'b','x', mefont), ! 1421: M(NONE, 0,0, 0) ! 1422: }; ! 1423: ! 1424: ! 1425: struct mactab manmactab[] = { ! 1426: M(PARAG, 'B','I', manfont), ! 1427: M(PARAG, 'B','R', manfont), ! 1428: M(PARAG, 'I','B', manfont), ! 1429: M(PARAG, 'I','R', manfont), ! 1430: M(PARAG, 'R','B', manfont), ! 1431: M(PARAG, 'R','I', manfont), ! 1432: ! 1433: M(PARAG, 'P','P', manpp), ! 1434: M(PARAG, 'L','P', manpp), ! 1435: M(PARAG, 'H','P', manpp), ! 1436: M(NONE, 0,0, 0) ! 1437: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.