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

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