|
|
1.1 ! root 1: char *xxxvers = "\nDeroff Version 1.02 24 July 1978\n"; ! 2: ! 3: ! 4: #include <stdio.h> ! 5: ! 6: /* Deroff command -- strip troff, eqn, and Tbl sequences from ! 7: a file. Has one flag argument, -w, to cause output one word per line ! 8: rather than in the original format. ! 9: Deroff follows .so and .nx commands, removes contents of macro ! 10: definitions, equations (both .EQ ... .EN and $...$), ! 11: Tbl command sequences, and Troff backslash constructions. ! 12: ! 13: All input is through the C macro; the most recently read character is in c. ! 14: */ ! 15: ! 16: #define C ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) ) ! 17: #define C1 ( (c=getc(infile)) == EOF ? eof() : c) ! 18: #define SKIP while(C != '\n') ! 19: ! 20: #define YES 1 ! 21: #define NO 0 ! 22: ! 23: #define NOCHAR -2 ! 24: #define SPECIAL 0 ! 25: #define APOS 1 ! 26: #define DIGIT 2 ! 27: #define LETTER 3 ! 28: ! 29: int wordflag = NO; ! 30: int inmacro = NO; ! 31: int intable = NO; ! 32: ! 33: char chars[128]; /* SPECIAL, APOS, DIGIT, or LETTER */ ! 34: ! 35: char line[BUFSIZ]; ! 36: char *lp; ! 37: ! 38: int c; ! 39: int ldelim = NOCHAR; ! 40: int rdelim = NOCHAR; ! 41: ! 42: ! 43: int argc; ! 44: char **argv; ! 45: ! 46: char fname[50]; ! 47: FILE *files[15]; ! 48: FILE **filesp; ! 49: FILE *infile; ! 50: ! 51: char *calloc(); ! 52: ! 53: ! 54: ! 55: main(ac, av) ! 56: int ac; ! 57: char **av; ! 58: { ! 59: register int i; ! 60: register char *p; ! 61: static char onechar[2] = "X"; ! 62: FILE *opn(); ! 63: ! 64: argc = ac - 1; ! 65: argv = av + 1; ! 66: ! 67: while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') ! 68: { ! 69: for(p=argv[0]+1; *p; ++p) switch(*p) ! 70: { ! 71: case 'w': ! 72: wordflag = YES; ! 73: break; ! 74: default: ! 75: onechar[0] = *p; ! 76: fatal("Invalid flag %s\n", onechar); ! 77: } ! 78: --argc; ! 79: ++argv; ! 80: } ! 81: ! 82: if(argc == 0) ! 83: infile = stdin; ! 84: else { ! 85: infile = opn(argv[0]); ! 86: --argc; ! 87: ++argv; ! 88: } ! 89: ! 90: files[0] = infile; ! 91: filesp = &files[0]; ! 92: ! 93: for(i='a'; i<='z' ; ++i) ! 94: chars[i] = LETTER; ! 95: for(i='A'; i<='Z'; ++i) ! 96: chars[i] = LETTER; ! 97: for(i='0'; i<='9'; ++i) ! 98: chars[i] = DIGIT; ! 99: chars['\''] = APOS; ! 100: chars['&'] = APOS; ! 101: ! 102: work(); ! 103: } ! 104: ! 105: ! 106: ! 107: skeqn() ! 108: { ! 109: while((c = getc(infile)) != rdelim) ! 110: if(c == EOF) ! 111: c = eof(); ! 112: else if(c == '"') ! 113: while( (c = getc(infile)) != '"') ! 114: if(c == EOF) ! 115: c = eof(); ! 116: else if(c == '\\') ! 117: if((c = getc(infile)) == EOF) ! 118: c = eof(); ! 119: return(C); ! 120: } ! 121: ! 122: ! 123: FILE *opn(p) ! 124: register char *p; ! 125: { ! 126: FILE *fd; ! 127: ! 128: if(p[0]=='-' && p[1]=='\0') ! 129: fd = stdin; ! 130: else if( (fd = fopen(p, "r")) == NULL) ! 131: fatal("Cannot open file %s\n", p); ! 132: ! 133: return(fd); ! 134: } ! 135: ! 136: ! 137: ! 138: eof() ! 139: { ! 140: if(infile != stdin) ! 141: fclose(infile); ! 142: if(filesp > files) ! 143: infile = *--filesp; ! 144: else if(argc > 0) ! 145: { ! 146: infile = opn(argv[0]); ! 147: --argc; ! 148: ++argv; ! 149: } ! 150: else ! 151: exit(0); ! 152: ! 153: return(C); ! 154: } ! 155: ! 156: ! 157: ! 158: getfname() ! 159: { ! 160: register char *p; ! 161: struct chain { struct chain *nextp; char *datap; } *chainblock; ! 162: register struct chain *q; ! 163: static struct chain *namechain = NULL; ! 164: char *copys(); ! 165: ! 166: while(C == ' ') ; ! 167: ! 168: for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p) ! 169: C; ! 170: *p = '\0'; ! 171: while(c != '\n') ! 172: C; ! 173: ! 174: /* see if this name has already been used */ ! 175: ! 176: for(q = namechain ; q; q = q->nextp) ! 177: if( ! strcmp(fname, q->datap)) ! 178: { ! 179: fname[0] = '\0'; ! 180: return; ! 181: } ! 182: ! 183: q = (struct chain *) calloc(1, sizeof(*chainblock)); ! 184: q->nextp = namechain; ! 185: q->datap = copys(fname); ! 186: namechain = q; ! 187: } ! 188: ! 189: ! 190: ! 191: ! 192: fatal(s,p) ! 193: char *s, *p; ! 194: { ! 195: fprintf(stderr, "Deroff: "); ! 196: fprintf(stderr, s, p); ! 197: exit(1); ! 198: } ! 199: ! 200: work() ! 201: { ! 202: ! 203: for( ;; ) ! 204: { ! 205: if(C == '.' || c == '\'') ! 206: comline(); ! 207: else ! 208: regline(NO); ! 209: } ! 210: } ! 211: ! 212: ! 213: ! 214: ! 215: regline(macline) ! 216: int macline; ! 217: { ! 218: line[0] = c; ! 219: lp = line; ! 220: for( ; ; ) ! 221: { ! 222: if(c == '\\') ! 223: { ! 224: *lp = ' '; ! 225: backsl(); ! 226: } ! 227: if(c == '\n') break; ! 228: if(intable && c=='T') ! 229: { ! 230: *++lp = C; ! 231: if(c=='{' || c=='}') ! 232: { ! 233: lp[-1] = ' '; ! 234: *lp = C; ! 235: } ! 236: } ! 237: else *++lp = C; ! 238: } ! 239: ! 240: *lp = '\0'; ! 241: ! 242: if(line[0] != '\0') ! 243: if(wordflag) ! 244: putwords(macline); ! 245: else if(macline) ! 246: putmac(line); ! 247: else ! 248: puts(line); ! 249: } ! 250: ! 251: ! 252: ! 253: ! 254: putmac(s) ! 255: register char *s; ! 256: { ! 257: register char *t; ! 258: ! 259: while(*s) ! 260: { ! 261: while(*s==' ' || *s=='\t') ! 262: putchar(*s++); ! 263: for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t) ! 264: ; ! 265: if(t>s+2 && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER) ! 266: while(s < t) ! 267: putchar(*s++); ! 268: else ! 269: s = t; ! 270: } ! 271: putchar('\n'); ! 272: } ! 273: ! 274: ! 275: ! 276: putwords(macline) /* break into words for -w option */ ! 277: int macline; ! 278: { ! 279: register char *p, *p1; ! 280: int i, nlet; ! 281: ! 282: ! 283: for(p1 = line ; ;) ! 284: { ! 285: /* skip initial specials ampersands and apostrophes */ ! 286: while( chars[*p1] < DIGIT) ! 287: if(*p1++ == '\0') return; ! 288: nlet = 0; ! 289: for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p) ! 290: if(i == LETTER) ++nlet; ! 291: ! 292: if( (!macline && nlet>1) /* MDM definition of word */ ! 293: || (macline && nlet>2 && chars[ p1[0] ]==LETTER && chars[ p1[1] ]==LETTER) ) ! 294: { ! 295: /* delete trailing ampersands and apostrophes */ ! 296: while(p[-1]=='\'' || p[-1]=='&') ! 297: --p; ! 298: while(p1 < p) putchar(*p1++); ! 299: putchar('\n'); ! 300: } ! 301: else ! 302: p1 = p; ! 303: } ! 304: } ! 305: ! 306: ! 307: ! 308: comline() ! 309: { ! 310: register int c1, c2; ! 311: ! 312: while(C==' ' || c=='\t') ! 313: ; ! 314: if( (c1=c) == '\n') ! 315: return; ! 316: if(c1 == '.') ! 317: { ! 318: inmacro = NO; ! 319: SKIP; ! 320: return; ! 321: } ! 322: if( (c2=C) == '\n') ! 323: return; ! 324: ! 325: if(c1=='E' && c2=='Q' && filesp==files) ! 326: eqn(); ! 327: else if(c1=='T' && (c2=='S' || c2=='C' || c2=='&') && filesp==files) ! 328: tbl(); ! 329: else if(c1=='T' && c2=='E') ! 330: intable = NO; ! 331: else if(!inmacro && c1=='d' && c2=='e') ! 332: macro(); ! 333: else if(!inmacro && c1=='i' && c2=='g') ! 334: macro(); ! 335: else if(!inmacro && c1=='a' && c2 == 'm') ! 336: macro(); ! 337: else if(c1=='s' && c2=='o') ! 338: { ! 339: getfname(); ! 340: if( fname[0] ) ! 341: infile = *++filesp = opn( fname ); ! 342: } ! 343: else if(c1=='n' && c2=='x') ! 344: { ! 345: getfname(); ! 346: if(fname[0] == '\0') exit(0); ! 347: if(infile != stdin) ! 348: fclose(infile); ! 349: infile = *filesp = opn(fname); ! 350: } ! 351: else if(c1=='h' && c2=='w') ! 352: { SKIP; } ! 353: else ! 354: { ! 355: ++inmacro; ! 356: regline(YES); ! 357: --inmacro; ! 358: } ! 359: } ! 360: ! 361: ! 362: ! 363: macro() ! 364: { ! 365: /* ! 366: do { SKIP; } ! 367: while(C!='.' || C!='.'); /* look for .EN */ ! 368: SKIP; ! 369: inmacro = YES; ! 370: } ! 371: ! 372: ! 373: ! 374: ! 375: tbl() ! 376: { ! 377: while(C != '.'); ! 378: SKIP; ! 379: intable = YES; ! 380: } ! 381: ! 382: eqn() ! 383: { ! 384: register int c1, c2; ! 385: ! 386: SKIP; ! 387: ! 388: for( ;;) ! 389: { ! 390: if(C == '.' || c == '\'') ! 391: { ! 392: while(C==' ' || c=='\t') ! 393: ; ! 394: if(c=='E' && C=='N') ! 395: { ! 396: SKIP; ! 397: return; ! 398: } ! 399: } ! 400: else if(c == 'd') /* look for delim */ ! 401: { ! 402: if(C=='e' && C=='l') ! 403: if( C=='i' && C=='m') ! 404: { ! 405: while(C1 == ' '); ! 406: if((c1=c)=='\n' || (c2=C1)=='\n' ! 407: || (c1=='o' && c2=='f' && C1=='f') ) ! 408: { ! 409: ldelim = NOCHAR; ! 410: rdelim = NOCHAR; ! 411: } ! 412: else { ! 413: ldelim = c1; ! 414: rdelim = c2; ! 415: } ! 416: } ! 417: } ! 418: ! 419: if(c != '\n') SKIP; ! 420: } ! 421: } ! 422: ! 423: ! 424: ! 425: backsl() /* skip over a complete backslash construction */ ! 426: { ! 427: int bdelim; ! 428: ! 429: sw: switch(C) ! 430: { ! 431: case '"': ! 432: SKIP; ! 433: return; ! 434: case 's': ! 435: if(C == '\\') backsl(); ! 436: else { ! 437: while(C>='0' && c<='9') ; ! 438: ungetc(c,infile); ! 439: c = '0'; ! 440: } ! 441: --lp; ! 442: return; ! 443: ! 444: case 'f': ! 445: case 'n': ! 446: case '*': ! 447: if(C != '(') ! 448: return; ! 449: ! 450: case '(': ! 451: if(C != '\n') C; ! 452: return; ! 453: ! 454: case '$': ! 455: C; /* discard argument number */ ! 456: return; ! 457: ! 458: case 'b': ! 459: case 'x': ! 460: case 'v': ! 461: case 'h': ! 462: case 'w': ! 463: case 'o': ! 464: case 'l': ! 465: case 'L': ! 466: if( (bdelim=C) == '\n') ! 467: return; ! 468: while(C!='\n' && c!=bdelim) ! 469: if(c == '\\') backsl(); ! 470: return; ! 471: ! 472: case '\\': ! 473: if(inmacro) ! 474: goto sw; ! 475: default: ! 476: return; ! 477: } ! 478: } ! 479: ! 480: ! 481: ! 482: ! 483: char *copys(s) ! 484: register char *s; ! 485: { ! 486: register char *t, *t0; ! 487: ! 488: if( (t0 = t = calloc( strlen(s)+1, sizeof(*t) ) ) == NULL) ! 489: fatal("Cannot allocate memory", (char *) NULL); ! 490: ! 491: while( *t++ = *s++ ) ! 492: ; ! 493: return(t0); ! 494: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.