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

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