1: /*
   2: ** cxref.c
   3: **
   4: ** C driver for Cxref program.
   5: ** does argument handling, then builds the right
   6: ** shell commands for passing to the system() routine.
   7: **
   8: ** Set up the argument vectors ourselves, the i/o with a pipe()
   9: ** call, and do all the forking and execing ourselves.
  10: **
  11: ** Arnold Robbins, Information and Computer Science, Georgia Tech
  12: **	gatech!arnold
  13: ** Copyright (c) 1984 by Arnold Robbins
  14: ** All rights reserved
  15: ** This program may not be sold, but may be distributed
  16: ** provided this header is included.
  17: */
  18: 
  19: #include <stdio.h>
  20: #include <ctype.h>
  21: #include <signal.h>
  22: 
  23: #define TRUE    1
  24: #define FALSE   0
  25: 
  26: char name[BUFSIZ];  /* save command name */
  27: 
  28: int xargc;      /* make argc and argv available globally */
  29: char **xargv;
  30: 
  31: int width = 0;      /* output width */
  32: 
  33: int sepflag = FALSE;    /* do each one separately */
  34: 
  35: int iflag = TRUE;   /* print out ints */
  36: int fflag = TRUE;   /* print out floats */
  37: int cflag = TRUE;   /* print out chars */
  38: int sflag = TRUE;   /* print out strings */
  39: int Fflag = FALSE;  /* fold case in indentifiers */
  40: 
  41: int ancestor;       /* id of this process, used by children */
  42: 
  43: char *filename();   /* turns "-" into "stdin" */
  44: 
  45: #define do_pipe(x)  if (pipe(x) < 0) { fprintf(stderr, "x: pipe failed\n");\
  46:                 fflush(stderr); exit (1); }
  47: 
  48: main(argc, argv)
  49: int argc;
  50: char **argv;
  51: {
  52:     int i;
  53:     int catchem();
  54: 
  55:     signal (SIGQUIT, catchem);
  56:     signal (SIGINT, catchem);
  57: 
  58:     strcpy (name, filename(argv[0]));
  59: 
  60:     ancestor = getpid();
  61: 
  62:     for(argv++, argc--; argc > 0; argv++, argc--)
  63:         if (argv[0][0] != '-')
  64:             break;
  65:         else if(argv[0][1] == '\0') /* filename of "-" */
  66:             break;
  67:         else
  68:             for(i = 1; argv[0][i] != '\0'; i++)
  69:             {
  70:                 switch(argv[0][i]) {
  71:                 case 'F':
  72:                     Fflag = TRUE;
  73:                     break;
  74: 
  75:                 case 'S':
  76:                     sepflag = TRUE;
  77:                     break;
  78: 
  79:                 case 'C':
  80:                     /* leave out all constants */
  81:                     cflag =
  82:                     iflag =
  83:                     fflag =
  84:                     sflag = FALSE;
  85:                     break;
  86: 
  87:                 case 'c':
  88:                     cflag = FALSE;
  89:                     break;
  90: 
  91:                 case 'i':
  92:                     iflag = FALSE;
  93:                     break;
  94: 
  95:                 case 'f':
  96:                     fflag = FALSE;
  97:                     break;
  98: 
  99:                 case 's':
 100:                     sflag = FALSE;
 101:                     break;
 102: 
 103:                 case 'w':
 104:                     if (isdigit(argv[0][i+1]))
 105:                     {
 106:                         width = 0;
 107:                         for(i++; isdigit(argv[0][i]); i++)
 108:                             width = width * 10 + argv[0][i] - '0';
 109:                         i--;
 110:                     }
 111:                     else
 112:                     {
 113:                         width = atoi(argv[1]);
 114:                         argv++;
 115:                         argc--;
 116:                     }
 117:                     break;
 118: 
 119:                 default:
 120:                     usage();
 121:                     break;
 122:                 }
 123:             }
 124: 
 125:     if (width != 0)
 126:         if (width < 51)
 127:             width = 80;
 128:         else if (width > 132)
 129:             width = 132;
 130: 
 131:     xargc = argc;
 132:     xargv = argv;
 133: 
 134:     setargs();      /* set up various argv buffers */
 135: 
 136:     runprogs();     /* set up and run pipelines */
 137: 
 138:     exit (0);
 139: }
 140: 
 141: /* argv vectors for various commands */
 142: 
 143: char *docxref[BUFSIZ] = { "docxref" };  /* allows BUFSIZ - 2 files */
 144: char *cxrfilt[] = { "cxrfilt", NULL, NULL, NULL };
 145: char *fmtxref[] = { "fmtxref", NULL, NULL, NULL };
 146: char *sort1[] = { "sort", "-u", "+0b", "-2", "+2n", NULL, NULL };
 147: char *sort2[] = { "sort", "-u", "+0n", "-1", "+1b", "-2", "+2n", NULL };
 148: char *sort3[] = { "sort", "-u", "+0n", "+1n", "-2", "+2b", "-3", "+3n", NULL };
 149: 
 150: /* pipes to connect programs */
 151: 
 152: typedef int PIPE[2];
 153: 
 154: PIPE pipe1, pipe2, pipe3;
 155: 
 156: setargs()       /* initialize argv vectors */
 157: {
 158:     static char widthbuf[100];
 159:     static char pidbuf[100];
 160: 
 161:     if (width != 0)
 162:     {
 163:         fmtxref[1] = "-w";
 164:         sprintf(widthbuf, "%d", width);
 165:         fmtxref[2] = widthbuf;
 166:         fmtxref[3] = NULL;
 167:     }
 168: 
 169:     sprintf(pidbuf, "%d", getpid());
 170: 
 171:     if (Fflag)
 172:         sort1[5] = "-f";    /* fold case in identifiers */
 173: 
 174:     if (! cflag && sflag)
 175:     {
 176:         cxrfilt[1] = "-c";
 177:         cxrfilt[2] = pidbuf;
 178:         cxrfilt[3] = NULL;
 179:     }
 180: 
 181:     else if (cflag && ! sflag)
 182:     {
 183:         cxrfilt[1] = "-s";
 184:         cxrfilt[2] = pidbuf;
 185:         cxrfilt[3] = NULL;
 186:     }
 187: 
 188:     else if (! cflag && ! sflag)
 189:     {
 190:         cxrfilt[1] = "-cs";
 191:         cxrfilt[2] = pidbuf;
 192:         cxrfilt[3] = NULL;
 193:     }
 194: 
 195:     else
 196:     {
 197:         cxrfilt[1] = pidbuf;
 198:         cxrfilt[2] = NULL;
 199:     }
 200: }
 201: 
 202: 
 203: /*
 204: flow of control is:
 205: 
 206: 	docxref  pipe1 sort1 pipe2 cxrfilt -userargs pipe3 fmtxref -userargs
 207: 	sort2 pipe1 cxrfilt -i pipe2 fmtxref -userargs
 208: 	sort3 pipe1 cxrfilt -f pipe2 fmtxref -userargs
 209: */
 210: 
 211: runprogs()      /* run the programs, obeying user's options */
 212: {
 213:     int i;
 214: 
 215:     if (sepflag)
 216:     {
 217:         for (i = 0; i < xargc; i++)
 218:         {
 219:             printf("\tC Cross Reference Listing of %s\n\n",
 220:                     filename(xargv[i]));
 221:             fflush(stdout);
 222: 
 223:             docxref[1] = xargv[i];
 224:             docxref[2] = NULL;
 225: 
 226:             idens();
 227: 
 228:             if (iflag)
 229:                 integers();
 230: 
 231:             if (fflag)
 232:                 floats();
 233: 
 234:             fflush(stdout);
 235: 
 236:             if (!isatty(fileno(stdout)))
 237:                 putchar('\f');
 238:         }
 239:     }
 240:     else
 241:     {
 242:         if (xargc == 1)
 243:             printf("\tC Cross Reference Listing of %s\n\n",
 244:                 filename(xargv[0]));
 245:         else
 246:             printf("\tC Cross Reference Listing\n\n");
 247:         fflush(stdout);
 248: 
 249:         for (i = 0; xargv[i] != NULL; i++)
 250:             docxref[i+1] = xargv[i];
 251: 
 252:         docxref[i+1] = NULL;
 253: 
 254:         idens();
 255: 
 256:         if (iflag)
 257:             integers();
 258: 
 259:         if (fflag)
 260:             floats();
 261: 
 262:         fflush(stdout);
 263: 
 264:         if (! isatty(fileno(stdout)))
 265:             putchar('\f');
 266:     }
 267: 
 268:     deltemps();
 269: }
 270: 
 271: deltemps()  /* delete temp files used for ints and floats */
 272: {
 273:     char buf[BUFSIZ];
 274:     int i;
 275: 
 276:     for (i = 1; i <= 2; i++)
 277:     {
 278:         sprintf(buf, "/tmp/cxr.%d.%d", getpid(), i);
 279:         unlink(buf);
 280:     }
 281: }
 282: 
 283: /*
 284:  * now begins the nitty gritty work of forking and setting up pipes.
 285:  */
 286: 
 287: int level;  /* how many children down are we */
 288: 
 289: idens()     /* cross reference identifiers */
 290: {
 291:     int status;
 292:     int pid;
 293:     int ischild;
 294:     char buf[BUFSIZ];
 295: 
 296:     level = 0;  /* starting off as grandparent */
 297: 
 298:     ischild = ((pid = fork()) == 0);
 299: 
 300: retest:
 301:     switch (level) {
 302:     case 0:         /* first fork */
 303:         if (ischild)
 304:         {
 305:             level++;
 306:             do_pipe(pipe3);
 307: 
 308:             if (ischild = ((pid = fork()) == 0))
 309:                 goto retest;
 310: 
 311:             close(pipe3[1]);    /* doesn't need this */
 312: 
 313:             close (0);
 314:             dup(pipe3[0]);
 315:             close(pipe3[0]);
 316:             sprintf (buf, "%s/fmtxref", SRCDIR);
 317:             execv (buf, fmtxref);
 318:             fprintf (stderr, "couldn't exec '%s'\n", buf);
 319:             exit (1);
 320:         }
 321:         else
 322:             while (wait(&status) != pid)
 323:                 ;
 324:         break;
 325: 
 326:     case 1:         /* second fork */
 327:         level++;
 328:         close (pipe3[0]);
 329: 
 330:         close(1);
 331:         dup(pipe3[1]);
 332:         close(pipe3[1]);
 333: 
 334:         /* set up i/o for next child */
 335:         do_pipe(pipe2);
 336: 
 337:         if (ischild = ((pid = fork()) == 0))
 338:             goto retest;
 339: 
 340:         close (pipe2[1]);
 341:         close (0);
 342:         dup(pipe2[0]);
 343:         close (pipe2[0]);
 344: 
 345:         sprintf (buf, "%s/cxrfilt", SRCDIR);
 346:         execv (buf, cxrfilt);
 347:         fprintf (stderr, "couldn't exec '%s'\n", buf);
 348:         exit (1);
 349:         break;
 350: 
 351:     case 2:
 352:         level++;
 353:         close (pipe2[0]);
 354: 
 355:         close(1);
 356:         dup(pipe2[1]);
 357:         close(pipe2[1]);    /* now writes to parent */
 358: 
 359:         /* set up to read from next child */
 360:         do_pipe(pipe1);
 361: 
 362:         if (ischild = ((pid = fork()) == 0))
 363:             goto retest;
 364: 
 365:         close (pipe1[1]);
 366: 
 367:         close (0);
 368:         dup(pipe1[0]);
 369:         close (pipe1[0]);
 370:         execv (SORT, sort1);
 371:         fprintf (stderr, "couldn't exec '%s'\n", SORT);
 372:         exit (1);
 373:         break;
 374: 
 375:     case 3:
 376:         level++;
 377:         close (pipe1[0]);
 378: 
 379:         close(1);
 380:         dup(pipe1[1]);
 381:         close(pipe1[1]);    /* now writes to parent */
 382: 
 383:         sprintf(buf, "%s/docxref", SRCDIR);
 384:         execv (buf, docxref);
 385:         fprintf (stderr, "couldn't exec '%s'\n", buf);
 386:         exit (1);
 387:         break;
 388: 
 389:     default:
 390:         fprintf(stderr, "in cxref (idens): can't happen\n");
 391:         fflush(stderr);
 392:         break;
 393:     }
 394: }
 395: 
 396: #include <sys/types.h>
 397: #include <sys/stat.h>
 398: 
 399: integers()
 400: {
 401:     int status;
 402:     int pid;
 403:     int ischild;
 404:     char buf[BUFSIZ];
 405:     struct stat fbuf;
 406: 
 407:     sprintf(buf, "/tmp/cxr.%d.1", ancestor);
 408:     if (stat(buf, &fbuf) >= 0 && fbuf.st_size > 0)
 409:         ;   /* file is not empty */
 410:     else
 411:         return;
 412: 
 413:     level = 0;  /* starting off as grandparent */
 414: 
 415:     ischild = ((pid = fork()) == 0);
 416: 
 417: retest:
 418:     switch (level) {
 419:     case 0:         /* first fork */
 420:         if (ischild)
 421:         {
 422:             level++;
 423:             do_pipe(pipe2);
 424: 
 425:             if (ischild = ((pid = fork()) == 0))
 426:                 goto retest;
 427: 
 428:             close(pipe2[1]);    /* doesn't need this */
 429: 
 430:             close (0);
 431:             dup(pipe2[0]);
 432:             close(pipe2[0]);
 433:             sprintf (buf, "%s/fmtxref", SRCDIR);
 434:             execv (buf, fmtxref);
 435:             fprintf (stderr, "couldn't exec '%s'\n", buf);
 436:             exit (1);
 437:         }
 438:         else
 439:             while (wait(&status) != pid)
 440:                 ;
 441:         break;
 442: 
 443:     case 1:         /* second fork */
 444:         level++;
 445:         close (pipe2[0]);
 446: 
 447:         close(1);
 448:         dup(pipe2[1]);
 449:         close(pipe2[1]);
 450: 
 451:         /* set up i/o for next child */
 452:         do_pipe(pipe1);
 453: 
 454:         if (ischild = ((pid = fork()) == 0))
 455:             goto retest;
 456: 
 457:         close (pipe1[1]);
 458:         close (0);
 459:         dup(pipe1[0]);
 460:         close (pipe1[0]);
 461: 
 462:         cxrfilt[1] = "-i";
 463:         cxrfilt[2] = NULL;
 464: 
 465:         sprintf (buf, "%s/cxrfilt", SRCDIR);
 466:         execv (buf, cxrfilt);
 467:         fprintf (stderr, "couldn't exec '%s'\n", buf);
 468:         exit (1);
 469:         break;
 470: 
 471:     case 2:
 472:         level++;
 473:         close (pipe1[0]);
 474: 
 475:         close(1);
 476:         dup(pipe1[1]);
 477:         close(pipe1[1]);    /* now writes to parent */
 478: 
 479:         /* read from tempfile */
 480: 
 481:         close (0);
 482:         sprintf (buf, "/tmp/cxr.%d.1", ancestor);
 483:         open (buf, 0);      /* will be fd 0 */
 484: 
 485:         execv (SORT, sort2);
 486:         fprintf (stderr, "couldn't exec '%s'\n", SORT);
 487:         exit (1);
 488:         break;
 489: 
 490:     default:
 491:         fprintf(stderr, "in cxref(integers): can't happen\n");
 492:         fflush(stderr);
 493:         break;
 494:     }
 495: }
 496: 
 497: floats()
 498: {
 499:     int status;
 500:     int pid;
 501:     int ischild;
 502:     char buf[BUFSIZ];
 503:     struct stat fbuf;
 504: 
 505:     sprintf(buf, "/tmp/cxr.%d.2", ancestor);
 506:     if (stat(buf, &fbuf) >= 0 && fbuf.st_size > 0)
 507:         ;   /* file is not empty */
 508:     else
 509:         return;
 510: 
 511:     level = 0;  /* starting off as grandparent */
 512: 
 513:     ischild = ((pid = fork()) == 0);
 514: 
 515: retest:
 516:     switch (level) {
 517:     case 0:         /* first fork */
 518:         if (ischild)
 519:         {
 520:             level++;
 521:             do_pipe(pipe2);
 522: 
 523:             if (ischild = ((pid = fork()) == 0))
 524:                 goto retest;
 525: 
 526:             close(pipe2[1]);    /* doesn't need this */
 527: 
 528:             close (0);
 529:             dup(pipe2[0]);
 530:             close(pipe2[0]);
 531:             sprintf (buf, "%s/fmtxref", SRCDIR);
 532:             execv (buf, fmtxref);
 533:             fprintf (stderr, "couldn't exec '%s'\n", buf);
 534:             exit (1);
 535:         }
 536:         else
 537:             while (wait(&status) != pid)
 538:                 ;
 539:         break;
 540: 
 541:     case 1:         /* second fork */
 542:         level++;
 543:         close (pipe2[0]);
 544: 
 545:         close(1);
 546:         dup(pipe2[1]);
 547:         close(pipe2[1]);
 548: 
 549:         /* set up i/o for next child */
 550:         do_pipe(pipe1);
 551: 
 552:         if (ischild = ((pid = fork()) == 0))
 553:             goto retest;
 554: 
 555:         close (pipe1[1]);
 556:         close (0);
 557:         dup(pipe1[0]);
 558:         close (pipe1[0]);
 559: 
 560:         cxrfilt[1] = "-f";
 561:         cxrfilt[2] = NULL;
 562: 
 563:         sprintf (buf, "%s/cxrfilt", SRCDIR);
 564:         execv (buf, cxrfilt);
 565:         fprintf (stderr, "couldn't exec '%s'\n", buf);
 566:         exit (1);
 567:         break;
 568: 
 569:     case 2:
 570:         level++;
 571:         close (pipe1[0]);
 572: 
 573:         close(1);
 574:         dup(pipe1[1]);
 575:         close(pipe1[1]);    /* now writes to parent */
 576: 
 577:         /* read from tempfile */
 578: 
 579:         close (0);
 580:         sprintf (buf, "/tmp/cxr.%d.2", ancestor);
 581:         open (buf, 0);      /* will be fd 0 */
 582: 
 583:         execv (SORT, sort3);
 584:         fprintf (stderr, "couldn't exec '%s'\n", SORT);
 585:         exit (1);
 586:         break;
 587: 
 588:     default:
 589:         fprintf(stderr, "in cxref(floats): can't happen\n");
 590:         fflush(stderr);
 591:         break;
 592:     }
 593: }
 594: 
 595: usage()
 596: {
 597:     fprintf(stderr, "usage: %s [-SCcsif] [-w width] [files]\n", name);
 598:     fflush(stderr);
 599:     exit (1);
 600: }
 601: 
 602: char *filename(fname)
 603: char *fname;
 604: {
 605:     char *cp, *basename();
 606: 
 607:     cp = basename(fname);
 608: 
 609:     return ( strcmp(cp, "-") == 0 ? "stdin" : cp);
 610: }
 611: 
 612: catchem()   /* simple signal catcher */
 613: {
 614:     signal(SIGQUIT, SIG_IGN);
 615:     signal(SIGINT, SIG_IGN);
 616: 
 617:     deltemps();
 618: 
 619:     exit (0);
 620: }
 621: 
 622: #include "basename.c"

Defined functions

catchem defined in line 612; used 3 times
deltemps defined in line 271; used 2 times
filename defined in line 602; used 4 times
floats defined in line 497; used 2 times
idens defined in line 289; used 2 times
integers defined in line 399; used 2 times
main defined in line 48; never used
runprogs defined in line 211; used 1 times
setargs defined in line 156; used 1 times
usage defined in line 595; used 1 times

Defined variables

Fflag defined in line 39; used 2 times
ancestor defined in line 41; used 5 times
cflag defined in line 37; used 5 times
cxrfilt defined in line 144; used 18 times
docxref defined in line 143; used 5 times
fflag defined in line 36; used 4 times
fmtxref defined in line 145; used 6 times
iflag defined in line 35; used 4 times
level defined in line 287; used 16 times
name defined in line 26; used 2 times
pipe1 defined in line 154; used 21 times
pipe2 defined in line 154; used 21 times
pipe3 defined in line 154; used 7 times
sepflag defined in line 33; used 2 times
sflag defined in line 38; used 5 times
sort1 defined in line 146; used 2 times
sort2 defined in line 147; used 1 times
sort3 defined in line 148; used 1 times
width defined in line 31; used 11 times
xargc defined in line 28; used 3 times
xargv defined in line 29; used 6 times

Defined typedef's

PIPE defined in line 152; used 1 times

Defined macros

FALSE defined in line 24; used 7 times
TRUE defined in line 23; used 6 times
do_pipe defined in line 45; used 7 times
Last modified: 1991-11-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4888
Valid CSS Valid XHTML 1.0 Strict