source: trunk/athena/bin/cxref/cxref.c @ 11902

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