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

Revision 13596, 11.3 KB checked in by danw, 25 years ago (diff)
use libgen.h basename, add "static" where appropriate
  • 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 <sys/types.h>
20#include <sys/stat.h>
21#include <sys/wait.h>
22
23#include <ctype.h>
24#include <fcntl.h>
25#include <signal.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <libgen.h>
31
32#define TRUE    1
33#define FALSE   0
34
35char name[BUFSIZ];      /* save command name */
36
37int xargc;              /* make argc and argv available globally */
38char **xargv;
39
40int width = 0;          /* output width */
41
42int sepflag = FALSE;    /* do each one separately */
43
44int iflag = TRUE;       /* print out ints */
45int fflag = TRUE;       /* print out floats */
46int cflag = TRUE;       /* print out chars */
47int sflag = TRUE;       /* print out strings */
48int Fflag = FALSE;      /* fold case in indentifiers */
49
50int ancestor;           /* id of this process, used by children */
51
52#define do_pipe(x)      if (pipe(x) < 0) { fprintf(stderr, "x: pipe failed\n");\
53                                fflush(stderr); exit (1); }
54
55static void setargs(void);
56static void runprogs(void);
57static void deltemps(void);
58static void idens(void);
59static void integers(void);
60static void floats(void);
61static void usage(void);
62static char *filename(char *fname);
63static void catchem(int);
64
65int main(int argc, char **argv)
66{
67        int i;
68        struct sigaction act;
69
70        sigemptyset(&act.sa_mask);
71        act.sa_flags = 0;
72        act.sa_handler = catchem;
73        (void) sigaction(SIGINT, &act, NULL);
74        (void) sigaction(SIGQUIT, &act, NULL);
75
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':
122                                        if (isdigit((int)argv[0][i+1]))
123                                        {
124                                                width = 0;
125                                                for(i++; isdigit((int)argv[0][i]); i++)
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       
143        if (width != 0) {
144                if (width < 51)
145                        width = 80;
146                else if (width > 132)
147                        width = 132;
148        }
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        return (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
175static void setargs(void)               /* initialize argv vectors */
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
188        sprintf(pidbuf, "%lu", (unsigned long)getpid());
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
230static void runprogs(void)      /* run the programs, obeying user's options */
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
290static void deltemps(void) /* delete temp files used for ints and floats */
291{
292        char buf[BUFSIZ];
293        int i;
294
295        for (i = 1; i <= 2; i++)
296        {
297                sprintf(buf, "/tmp/cxr.%lu.%d", (unsigned long)getpid(), i);
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
308static void idens(void)         /* cross reference identifiers */
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
327                        pid = fork();
328                        ischild = (pid == 0);
329                        if (ischild)
330                                goto retest;
331
332                        close(pipe3[1]);        /* doesn't need this */
333
334                        close (0);
335                        dup(pipe3[0]);
336                        close(pipe3[0]);
337                        sprintf (buf, "%s/cxref/fmtxref", LIBEXECDIR);
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
358                pid = fork();
359                ischild = (pid == 0);
360                if (ischild)
361                        goto retest;
362
363                close (pipe2[1]);
364                close (0);
365                dup(pipe2[0]);
366                close (pipe2[0]);
367
368                sprintf (buf, "%s/cxref/cxrfilt", LIBEXECDIR);
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
385                pid = fork();
386                ischild = (pid == 0);
387                if (ischild)
388                        goto retest;
389
390                close (pipe1[1]);
391
392                close (0);
393                dup(pipe1[0]);
394                close (pipe1[0]);
395                execvp ("sort", sort1);
396                fprintf (stderr, "couldn't exec 'sort'\n");
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
408                sprintf(buf, "%s/cxref/docxref", LIBEXECDIR);
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
421static void integers(void)
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
447                        pid = fork();
448                        ischild = (pid == 0);
449                        if (ischild)
450                                goto retest;
451
452                        close(pipe2[1]);        /* doesn't need this */
453
454                        close (0);
455                        dup(pipe2[0]);
456                        close(pipe2[0]);
457                        sprintf (buf, "%s/cxref/fmtxref", LIBEXECDIR);
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
478                pid = fork();
479                ischild = (pid == 0);
480                if (ischild)
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
491                sprintf (buf, "%s/cxref/cxrfilt", LIBEXECDIR);
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
511                execvp ("sort", sort2);
512                fprintf (stderr, "couldn't exec 'sort'\n");
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
523static void floats(void)
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
549                        pid = fork();
550                        ischild = (pid == 0);
551                        if (ischild)
552                                goto retest;
553
554                        close(pipe2[1]);        /* doesn't need this */
555
556                        close (0);
557                        dup(pipe2[0]);
558                        close(pipe2[0]);
559                        sprintf (buf, "%s/cxref/fmtxref", LIBEXECDIR);
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
580                pid = fork();
581                ischild = (pid == 0);
582                if (ischild)
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
593                sprintf (buf, "%s/cxref/cxrfilt", LIBEXECDIR);
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
613                execvp ("sort", sort3);
614                fprintf (stderr, "couldn't exec 'sort'\n");
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
625static void usage(void)
626{
627        fprintf(stderr, "usage: %s [-SCcsif] [-w width] [files]\n", name);
628        fflush(stderr);
629        exit (1);
630}
631
632static char *filename(char *fname)
633{
634        char *cp;
635
636        cp = basename(fname);
637
638        return ( strcmp(cp, "-") == 0 ? "stdin" : cp);
639}
640
641static void catchem(int signal) /* simple signal catcher */
642{
643        struct sigaction act;
644
645        sigemptyset(&act.sa_mask);
646        act.sa_flags = 0;
647        act.sa_handler = SIG_IGN;
648        (void) sigaction(SIGINT, &act, NULL);
649        (void) sigaction(SIGQUIT, &act, NULL);
650
651        deltemps();
652
653        exit (0);
654}
Note: See TracBrowser for help on using the repository browser.