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"