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[512];
  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: c2 = C;
 317: if(c1=='.' && c2!='.')
 318:     inmacro = NO;
 319: if(c2 == '\n')
 320:     return;
 321: 
 322: if(c1=='E' && c2=='Q' && filesp==files)
 323:     eqn();
 324: else if(c1=='T' && (c2=='S' || c2=='C' || c2=='&') && filesp==files)
 325:     tbl();
 326: else if(c1=='T' && c2=='E')
 327:     intable = NO;
 328: else if(!inmacro && c1=='d' && c2=='e')
 329:     macro();
 330: else if(!inmacro && c1=='i' && c2=='g')
 331:     macro();
 332: else if(!inmacro && c1=='a' && c2 == 'm')
 333:     macro();
 334: else if(c1=='s' && c2=='o')
 335:     {
 336:     getfname();
 337:     if( fname[0] )
 338:         infile = *++filesp = opn( fname );
 339:     }
 340: else if(c1=='n' && c2=='x')
 341:     {
 342:     getfname();
 343:     if(fname[0] == '\0') exit(0);
 344:     if(infile != stdin)
 345:         fclose(infile);
 346:     infile = *filesp = opn(fname);
 347:     }
 348: else if(c1=='h' && c2=='w')
 349:     { SKIP; }
 350: else
 351:     {
 352:     if(c1=='.' && c2=='.')
 353:         while(C == '.')
 354:             ;
 355:     ++inmacro;
 356:     regline(YES);
 357:     --inmacro;
 358:     }
 359: }
 360: 
 361: 
 362: 
 363: macro()
 364: {
 365: /*
 366: do { SKIP; }
 367: 	while(C!='.' || C!='.' || C=='.');	/* look for  .. */
 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: }

Defined functions

backsl defined in line 425; used 3 times
comline defined in line 308; used 1 times
copys defined in line 483; used 2 times
eof defined in line 138; used 5 times
eqn defined in line 382; used 1 times
fatal defined in line 192; used 3 times
getfname defined in line 158; used 2 times
macro defined in line 363; used 3 times
main defined in line 55; never used
opn defined in line 123; used 5 times
putmac defined in line 254; used 1 times
putwords defined in line 276; used 1 times
regline defined in line 215; used 2 times
skeqn defined in line 107; used 1 times
  • in line 16
tbl defined in line 375; used 1 times
work defined in line 200; used 1 times

Defined variables

argc defined in line 43; used 7 times
argv defined in line 44; used 9 times
c defined in line 38; used 41 times
chars defined in line 33; used 11 times
fname defined in line 46; used 8 times
inmacro defined in line 30; used 8 times
intable defined in line 31; used 3 times
ldelim defined in line 39; used 3 times
line defined in line 35; used 6 times
lp defined in line 36; used 8 times
rdelim defined in line 40; used 3 times
wordflag defined in line 29; used 2 times
xxxvers defined in line 1; never used

Defined struct's

chain defined in line 161; used 8 times

Defined macros

APOS defined in line 25; used 2 times
C defined in line 16; used 29 times
C1 defined in line 17; used 3 times
DIGIT defined in line 26; used 2 times
LETTER defined in line 27; used 7 times
NO defined in line 21; used 6 times
NOCHAR defined in line 23; used 4 times
SKIP defined in line 18; used 7 times
SPECIAL defined in line 24; used 1 times
YES defined in line 20; used 4 times
Last modified: 1981-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1351
Valid CSS Valid XHTML 1.0 Strict