home *** CD-ROM | disk | FTP | other *** search
- From: linus!gatech!arnold
- Date: 17 Jan 85 16:30:36-EST (Thu)
- Original-From: Arnold Robbins <arnold@gatech>
- Subject: Cxref -- C cross referencer
-
- Here is the latest version of my 'cxref' program, ready for posting. It
- has been posted to net.sources several times before; This version has
- one or two small enhancements, and should port across Unix versions fairly
- easily.
-
- Arnold Robbins
- CSNET: arnold@gatech
- ARPA: arnold%gatech.csnet@csnet-relay.arpa
- UUCP: { akgua, allegra, hplabs, ihnp4, seismo, ut-sally }!gatech!arnold
-
- ------------------ tear here --------------------
- #! /bin/sh
- echo 'extracting --- README' 1>&2
- cat > README << 'End of README'
- README:
-
- This directory contains the files for 'cxref', a C language cross
- referencing program.
-
- The makefile will build the program. Use 'make install' to put a copy in
- the right places. Cxref is a driver, and goes in DESTDIR, which will be your
- local bin of choice. LIB is where the programs go that do the work. The
- makefile makes the directory /usr/local/lib/cxref (i.e. LIB) to hold the
- programs. The cxref driver is dependant on where LIB is. I have them set to
- use my BIN. BIN is taken from the environment, since I use the UNIX 4.0 make.
- SORT is the full pathname for the Unix sort program, sometimes /bin/sort,
- other times /usr/bin/sort. Edit the makefile to set everything up properly.
-
- System III and V users should edit the file 'basename.c' to change the
- call to 'rindex' to 'strrchr'.
-
- The flow of information between programs is shown below.
- I suggest that you run the programs separately, successively adding the next
- program in a particular pipeline, to see how the information is transformed.
- The outline below of the flow of control does not necessarily show all
- the arguments that each program requires; see the source code to
- be sure, when you run the programs by hand.
-
- With some work in the cscan.l and cxref.c files, this program could be
- easily made to cross reference other languages.
-
- Here is a list of the files, and what they contain:
-
- README --- this file.
- cxref.1 --- man page.
- makefile --- the makefile.
-
- cxref.c --- driver, calls all the other programs, does arg handling.
- old.cxref.c --- old version, used the shell to do the dirty work.
- (this file can probably be deleted.)
-
- constdefs.h --- header file, used by cscan.l and cxrfilt.c.
-
- cscan.l --- does the work of finding indentifiers and contsants.
- docxref.c --- main program and some other stuff to drive lex.
-
- cxrfilt.c --- filters int and floats to their own files.
- also puts ints and floats back together after sorting.
-
- fmtxref.c --- formats output for printing.
-
- SORT[1-3] --- shell files to save typing during testing and development.
-
-
- For development, the flow of programs is:
-
- docxref files | SORT1 | cxrfilt | fmtxref
- SORT2 < tempfile1 | cxrfilt -i | fmtxref
- SORT3 < tempfile2 | cxrfilt -f | fmtxref
-
- Arnold Robbins, Information and Computer Science, Georgia Tech
- gatech!arnold
- January 1985.
- Copyright (c) 1985 by Arnold Robbins.
- All rights reserved.
- End of README
- echo 'extracting --- SORT1' 1>&2
- cat > SORT1 << 'End of SORT1'
- # SORT1 -- do the first sorting job for cxref.
- #
- # the purpose of this file is to save typing during testing and development.
- #
- # Arnold Robbins, Information and Computer Science, Georgia Tech
- # gatech!arnold
- # Copyright (c) 1984 by Arnold Robbins.
- # All rights reserved.
- # This program may not be sold, but may be distributed
- # provided this header is included.
-
- exec sort -u +0b -2 +2n
- End of SORT1
- echo 'extracting --- SORT2' 1>&2
- cat > SORT2 << 'End of SORT2'
- # SORT2 -- do the second sorting job for cxref.
- #
- # the purpose of this file is to save typing during testing and development.
- #
- # Arnold Robbins, Information and Computer Science, Georgia Tech
- # gatech!arnold
- # Copyright (c) 1984 by Arnold Robbins.
- # All rights reserved.
- # This program may not be sold, but may be distributed
- # provided this header is included.
-
- exec sort -u +0n -1 +1b -2 +2n
- End of SORT2
- echo 'extracting --- SORT3' 1>&2
- cat > SORT3 << 'End of SORT3'
- # SORT3 -- do the third sorting job for cxref.
- #
- # the purpose of this file is to save typing during testing and development.
- #
- # Arnold Robbins, Information and Computer Science, Georgia Tech
- # gatech!arnold
- # Copyright (c) 1984 by Arnold Robbins.
- # All rights reserved.
- # This program may not be sold, but may be distributed
- # provided this header is included.
-
- exec sort -u +0n +1n -2 +2b -3 +3n
- End of SORT3
- echo 'extracting --- basename.c' 1>&2
- cat > basename.c << 'End of basename.c'
- /*
- ** basename.c
- **
- ** return the last portion of a path name.
- ** included by all the cxref component programs.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins.
- ** All rights reserved.
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- char *basename(str) /* return last portion of a path name */
- char *str;
- {
- char *cp, *rindex(); /* change to strrchr() for USG systems */
-
- if((cp = rindex(str, '/')) == NULL)
- return(str);
- else
- return(++cp);
- }
- End of basename.c
- echo 'extracting --- constdefs.h' 1>&2
- cat > constdefs.h << 'End of constdefs.h'
- /*
- ** constdefs.h
- **
- ** definitions of keyletters for different constants.
- ** arbitrary, as long as char < string < int < float.
- **
- ** used by several of the cxref component programs.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins.
- ** All rights reserved.
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- **
- */
-
- #define CHAR 'a'
- #define STRING 'b'
- #define INT 'c'
- #define FLOAT 'd'
- End of constdefs.h
- echo 'extracting --- cscan.l' 1>&2
- cat > cscan.l << 'End of cscan.l'
- /*
- ** cscan.l
- **
- ** Does the major work of removing identifiers and constants
- ** from the input stream, for Cxref. Its output is then extensively
- ** postprocessed.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins.
- ** All rights reserved.
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- %{
- extern int line_no;
- extern char *fname, *basename();
- %}
-
- letter [A-Za-z_]
- digit [0-9]
-
- %%
- int |
- char |
- float |
- double |
- struct |
- union |
- long |
- short |
- unsigned |
- auto |
- extern |
- register |
- typedef |
- static |
- goto |
- return |
- sizeof |
- break |
- continue |
- if |
- else |
- for |
- do |
- while |
- switch |
- case |
- default |
- entry |
- enum |
- void |
- define |
- undef |
- include |
- ifdef |
- ifndef |
- defined |
- endif ; /* ignore C and cpp keywords */
-
- "<".+">" ; /* forget about include-file names */
-
- "\n" line_no++;
-
- "/*" { /* get rid of comments */
- register char c, c1;
-
- loop: while((c = input()) != '*' && c != 0)
- if(c == '\n')
- line_no++;
-
- if(c == 0)
- {
- fprintf(stderr,
- "unexpected EOF in comment at line %d, file %s\n",
- line_no, basename(fname));
- exit(1);
- }
-
- if((c1 = input()) != '/')
- {
- unput(c1); /* could be '*' before '/' */
- goto loop;
- }
- }
-
- {letter}({letter}|{digit})* outid(); /* what we actually want */
-
- '[^\\']' |
- '\\{digit}{1,3}' |
- '\\[\\bfrnlt']' outchar();
-
- \" { /* collect quoted strings */
- register char c;
- register int i;
-
- for(i = 1, c = input(); ; i++, c = input())
- switch (c) {
- case '"':
- yytext[i] = c;
- yytext[++i] = '\0';
- yyleng = i - 1;
- goto fini;
-
- case '\\':
- yytext[i] = '\\';
- yytext[++i] = input();
- if (yytext[i] == '\n')
- {
- line_no++;
- yytext[i] = 'N';
- /* make visible */
- }
- break;
-
- case 0:
- fprintf(stderr,
- "unexpected EOF inside string at line %d, file %s\n",
- line_no, basename(fname));
- exit(1);
- break;
-
- default:
- yytext[i] = c;
- break;
- }
-
- fini:
- outstring();
- }
-
- [+-]?{digit}+[lL]? |
- [+-]?0[Xx]({digit}|[a-fA-F])+[lL]? outint();
-
- [+-]?{digit}*"."{digit}+([Ee][+-]?{digit}+)? |
- [+-]?{digit}+"."{digit}*([Ee][+-]?{digit}+)? |
- [+-]?{digit}+[Ee][+-]?{digit}+ outfloat();
-
- . ; /* delete everything else */
-
- %%
-
- yywrap() /* wrap up for lex, return 1 */
- {
- return(1);
- }
-
- #include "constdefs.h"
-
- extern char *fname;
- extern char *basename();
-
- outchar()
- {
- outtext(CHAR);
- }
-
- outstring()
- {
- outtext(STRING);
- }
-
- outint()
- {
- int i = strlen(yytext);
-
- /* handle long integer constants */
-
- if (yytext[i-1] == 'l' || yytext[i-1] == 'L')
- yytext[i-1] = '\0';
-
- outtext(INT);
- }
-
- outfloat()
- {
- outtext(FLOAT);
- }
-
- outtext(type)
- char type;
- {
- printf("~%c%s\t%s\t%d\n", type, yytext, basename(fname), line_no);
- }
- End of cscan.l
- echo 'extracting --- cxref.1' 1>&2
- cat > cxref.1 << 'End of cxref.1'
- .TH CXREF 1 "Georgia Tech"
- .SH NAME
- cxref \- cross reference C source files
- .SH SYNOPSIS
- .B cxref
- [
- .B \-FSCcfis
- ] [
- .B \-w
- .IR width " ]"
- [files]
- .SH DESCRIPTION
- .PP
- .I Cxref
- reads the named C source files and produces on the standard output
- a cross reference of all the identifiers and constants in the files.
- Constants are integer constants (12, 0421, 0x1A),
- floating point constants (123.45, 0.2e-4),
- string constants ("this is a string\en"),
- and character constants ('a', '\e033').
- Identifiers, character constants, and string constants
- are sorted lexicographically, i.e. according to the machine collating
- sequence (7-bit ASCII on the Vax or the Pyramid).
- Integer and floating point constants are sorted numerically.
- The trailing 'l' or 'L' on long integer constants will not show
- up in the output listing.
- .PP
- If no files are named,
- .I cxref
- reads the standard input. For multiple files, the argument "\-"
- (a single dash) indicates that the standard input should be read
- at that point.
- .PP
- If arguments are given, they must come before any file names.
- .PP
- .I Cxref
- recognizes the following arguments:
- .RS
- .TP
- .B \-F
- Fold case in comparison. By default, case is distinct in comparison of
- identifiers and string and character constants.
- .RI ( cxref
- simply passes the "\-F" option on to
- .IR sort (1)
- as "\-f".)
- .TP
- .B \-S
- Cross reference all files separately.
- The default action is to cross reference all named files together.
- .TP
- .B \-c
- Leave character constants out of the cross reference listing.
- .TP
- .B \-f
- Leave floating point constants out of the cross reference listing.
- .TP
- .B \-i
- Leave integer constants out of the cross reference listing.
- .TP
- .B \-s
- Leave string constants out of the cross reference listing.
- .TP
- .B \-C
- Leave
- .I all
- constants, character, string, integer, and floating point, out of
- the cross reference listing.
- By default, all types of constants are included in the cross reference.
- .TP
- .BI "\-w " width
- Make the output be
- .I width
- columns wide.
- The output width will never be less than 51 or more than 132 columns.
- .I Cxref
- silently adjusts incorrect settings to the nearest allowable setting.
- If no width is specified, the output will default to 80 columns wide.
- .RE
- .PP
- .IR Cxref " does " not
- include #include files, or expand macro definitions. Files named
- in #include lines can be listed on the command line if they should
- also be cross referenced.
- .PP
- If a quoted string has an escaped newline in it (see ``The C Programming
- Language'', page 181, or Section 2.5 of the C Reference Manual),
- it will show up inside the string in the output listing as \eN.
- This is to make it visible to the programmer, and to keep the
- various filters which
- .I Cxref
- uses to actually do the work from getting terribly confused.
- .PP
- .I Cxref
- is best run in the background, with its output redirected into
- a file or the line printer spooler
- .IR lpr (1),
- since it reads all
- the named files, using
- .IR sort (1)
- as an intermediate pass.
- The sorting can take time which the user can probably put to more productive
- use.
- .SH DIAGNOSTICS
- .PP
- Self explanatory.
- .SH BUGS
- .PP
- Systems running UNIX 4.0 and later already have a program named
- .IR cxref .
- Therefore, on those systems, this program should be renamed.
- .PP
- .I Cxref
- does not do any formatting on its output (other than to
- insure that it writes the proper number of columns),
- so it should probably be run piping its output into
- .IR pr (1).
- .PP
- Floating point constants are converted to a common format for sorting,
- therefore they may appear in the output in a format different from
- (but numerically equivalent to) their form in the original source code.
- .SH "SEE ALSO"
- .IR lex (1),
- .IR lpr (1),
- .IR pr (1),
- .IR sort (1)
- .SH FILES
- .TP
- /tmp/cxr.$$.*
- temporary files for integer and floating point contstants.
- .I Cxref
- removes these files when it is through.
- .SH AUTHOR
- .PP
- .nf
- Arnold Robbins
- School of Information and Computer Science
- Georgia Institute of Technology
- Atlanta, Geogia 30332
-
- UUCP: gatech!arnold
- CSNET: arnold@gatech
- ARPANET: arnold%gatech.csnet@csnet-relay.arpa
- .fi
-
- Copyright (c) 1984 by Arnold Robbins.
- All rights reserved.
- This program may not be sold, but may be distributed
- provided this notice is included.
- End of cxref.1
- echo 'extracting --- cxref.c' 1>&2
- cat > cxref.c << 'End of cxref.c'
- /*
- ** cxref.c
- **
- ** C driver for Cxref program.
- ** does argument handling, then builds the right
- ** shell commands for passing to the system() routine.
- **
- ** Set up the argument vectors ourselves, the i/o with a pipe()
- ** call, and do all the forking and execing ourselves.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins
- ** All rights reserved
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
-
- #define TRUE 1
- #define FALSE 0
-
- char name[BUFSIZ]; /* save command name */
-
- int xargc; /* make argc and argv available globally */
- char **xargv;
-
- int width = 0; /* output width */
-
- int sepflag = FALSE; /* do each one separately */
-
- int iflag = TRUE; /* print out ints */
- int fflag = TRUE; /* print out floats */
- int cflag = TRUE; /* print out chars */
- int sflag = TRUE; /* print out strings */
- int Fflag = FALSE; /* fold case in indentifiers */
-
- int ancestor; /* id of this process, used by children */
-
- char *filename(); /* turns "-" into "stdin" */
-
- #define do_pipe(x) if (pipe(x) < 0) { fprintf(stderr, "x: pipe failed\n");\
- fflush(stderr); exit (1); }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int i;
- int catchem();
-
- signal (SIGQUIT, catchem);
- signal (SIGINT, catchem);
-
- strcpy (name, filename(argv[0]));
-
- ancestor = getpid();
-
- for(argv++, argc--; argc > 0; argv++, argc--)
- if (argv[0][0] != '-')
- break;
- else if(argv[0][1] == '\0') /* filename of "-" */
- break;
- else
- for(i = 1; argv[0][i] != '\0'; i++)
- {
- switch(argv[0][i]) {
- case 'F':
- Fflag = TRUE;
- break;
-
- case 'S':
- sepflag = TRUE;
- break;
-
- case 'C':
- /* leave out all constants */
- cflag =
- iflag =
- fflag =
- sflag = FALSE;
- break;
-
- case 'c':
- cflag = FALSE;
- break;
-
- case 'i':
- iflag = FALSE;
- break;
-
- case 'f':
- fflag = FALSE;
- break;
-
- case 's':
- sflag = FALSE;
- break;
-
- case 'w':
- if (isdigit(argv[0][i+1]))
- {
- width = 0;
- for(i++; isdigit(argv[0][i]); i++)
- width = width * 10 + argv[0][i] - '0';
- i--;
- }
- else
- {
- width = atoi(argv[1]);
- argv++;
- argc--;
- }
- break;
-
- default:
- usage();
- break;
- }
- }
-
- if (width != 0)
- if (width < 51)
- width = 80;
- else if (width > 132)
- width = 132;
-
- xargc = argc;
- xargv = argv;
-
- setargs(); /* set up various argv buffers */
-
- runprogs(); /* set up and run pipelines */
-
- exit (0);
- }
-
- /* argv vectors for various commands */
-
- char *docxref[BUFSIZ] = { "docxref" }; /* allows BUFSIZ - 2 files */
- char *cxrfilt[] = { "cxrfilt", NULL, NULL, NULL };
- char *fmtxref[] = { "fmtxref", NULL, NULL, NULL };
- char *sort1[] = { "sort", "-u", "+0b", "-2", "+2n", NULL, NULL };
- char *sort2[] = { "sort", "-u", "+0n", "-1", "+1b", "-2", "+2n", NULL };
- char *sort3[] = { "sort", "-u", "+0n", "+1n", "-2", "+2b", "-3", "+3n", NULL };
-
- /* pipes to connect programs */
-
- typedef int PIPE[2];
-
- PIPE pipe1, pipe2, pipe3;
-
- setargs() /* initialize argv vectors */
- {
- static char widthbuf[100];
- static char pidbuf[100];
-
- if (width != 0)
- {
- fmtxref[1] = "-w";
- sprintf(widthbuf, "%d", width);
- fmtxref[2] = widthbuf;
- fmtxref[3] = NULL;
- }
-
- sprintf(pidbuf, "%d", getpid());
-
- if (Fflag)
- sort1[5] = "-f"; /* fold case in identifiers */
-
- if (! cflag && sflag)
- {
- cxrfilt[1] = "-c";
- cxrfilt[2] = pidbuf;
- cxrfilt[3] = NULL;
- }
-
- else if (cflag && ! sflag)
- {
- cxrfilt[1] = "-s";
- cxrfilt[2] = pidbuf;
- cxrfilt[3] = NULL;
- }
-
- else if (! cflag && ! sflag)
- {
- cxrfilt[1] = "-cs";
- cxrfilt[2] = pidbuf;
- cxrfilt[3] = NULL;
- }
-
- else
- {
- cxrfilt[1] = pidbuf;
- cxrfilt[2] = NULL;
- }
- }
-
-
- /*
- flow of control is:
-
- docxref pipe1 sort1 pipe2 cxrfilt -userargs pipe3 fmtxref -userargs
- sort2 pipe1 cxrfilt -i pipe2 fmtxref -userargs
- sort3 pipe1 cxrfilt -f pipe2 fmtxref -userargs
- */
-
- runprogs() /* run the programs, obeying user's options */
- {
- int i;
-
- if (sepflag)
- {
- for (i = 0; i < xargc; i++)
- {
- printf("\tC Cross Reference Listing of %s\n\n",
- filename(xargv[i]));
- fflush(stdout);
-
- docxref[1] = xargv[i];
- docxref[2] = NULL;
-
- idens();
-
- if (iflag)
- integers();
-
- if (fflag)
- floats();
-
- fflush(stdout);
-
- if (!isatty(fileno(stdout)))
- putchar('\f');
- }
- }
- else
- {
- if (xargc == 1)
- printf("\tC Cross Reference Listing of %s\n\n",
- filename(xargv[0]));
- else
- printf("\tC Cross Reference Listing\n\n");
- fflush(stdout);
-
- for (i = 0; xargv[i] != NULL; i++)
- docxref[i+1] = xargv[i];
-
- docxref[i+1] = NULL;
-
- idens();
-
- if (iflag)
- integers();
-
- if (fflag)
- floats();
-
- fflush(stdout);
-
- if (! isatty(fileno(stdout)))
- putchar('\f');
- }
-
- deltemps();
- }
-
- deltemps() /* delete temp files used for ints and floats */
- {
- char buf[BUFSIZ];
- int i;
-
- for (i = 1; i <= 2; i++)
- {
- sprintf(buf, "/tmp/cxr.%d.%d", getpid(), i);
- unlink(buf);
- }
- }
-
- /*
- * now begins the nitty gritty work of forking and setting up pipes.
- */
-
- int level; /* how many children down are we */
-
- idens() /* cross reference identifiers */
- {
- int status;
- int pid;
- int ischild;
- char buf[BUFSIZ];
-
- level = 0; /* starting off as grandparent */
-
- ischild = ((pid = fork()) == 0);
-
- retest:
- switch (level) {
- case 0: /* first fork */
- if (ischild)
- {
- level++;
- do_pipe(pipe3);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close(pipe3[1]); /* doesn't need this */
-
- close (0);
- dup(pipe3[0]);
- close(pipe3[0]);
- sprintf (buf, "%s/fmtxref", SRCDIR);
- execv (buf, fmtxref);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- }
- else
- while (wait(&status) != pid)
- ;
- break;
-
- case 1: /* second fork */
- level++;
- close (pipe3[0]);
-
- close(1);
- dup(pipe3[1]);
- close(pipe3[1]);
-
- /* set up i/o for next child */
- do_pipe(pipe2);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close (pipe2[1]);
- close (0);
- dup(pipe2[0]);
- close (pipe2[0]);
-
- sprintf (buf, "%s/cxrfilt", SRCDIR);
- execv (buf, cxrfilt);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- break;
-
- case 2:
- level++;
- close (pipe2[0]);
-
- close(1);
- dup(pipe2[1]);
- close(pipe2[1]); /* now writes to parent */
-
- /* set up to read from next child */
- do_pipe(pipe1);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close (pipe1[1]);
-
- close (0);
- dup(pipe1[0]);
- close (pipe1[0]);
- execv (SORT, sort1);
- fprintf (stderr, "couldn't exec '%s'\n", SORT);
- exit (1);
- break;
-
- case 3:
- level++;
- close (pipe1[0]);
-
- close(1);
- dup(pipe1[1]);
- close(pipe1[1]); /* now writes to parent */
-
- sprintf(buf, "%s/docxref", SRCDIR);
- execv (buf, docxref);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- break;
-
- default:
- fprintf(stderr, "in cxref (idens): can't happen\n");
- fflush(stderr);
- break;
- }
- }
-
- #include <sys/types.h>
- #include <sys/stat.h>
-
- integers()
- {
- int status;
- int pid;
- int ischild;
- char buf[BUFSIZ];
- struct stat fbuf;
-
- sprintf(buf, "/tmp/cxr.%d.1", ancestor);
- if (stat(buf, &fbuf) >= 0 && fbuf.st_size > 0)
- ; /* file is not empty */
- else
- return;
-
- level = 0; /* starting off as grandparent */
-
- ischild = ((pid = fork()) == 0);
-
- retest:
- switch (level) {
- case 0: /* first fork */
- if (ischild)
- {
- level++;
- do_pipe(pipe2);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close(pipe2[1]); /* doesn't need this */
-
- close (0);
- dup(pipe2[0]);
- close(pipe2[0]);
- sprintf (buf, "%s/fmtxref", SRCDIR);
- execv (buf, fmtxref);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- }
- else
- while (wait(&status) != pid)
- ;
- break;
-
- case 1: /* second fork */
- level++;
- close (pipe2[0]);
-
- close(1);
- dup(pipe2[1]);
- close(pipe2[1]);
-
- /* set up i/o for next child */
- do_pipe(pipe1);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close (pipe1[1]);
- close (0);
- dup(pipe1[0]);
- close (pipe1[0]);
-
- cxrfilt[1] = "-i";
- cxrfilt[2] = NULL;
-
- sprintf (buf, "%s/cxrfilt", SRCDIR);
- execv (buf, cxrfilt);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- break;
-
- case 2:
- level++;
- close (pipe1[0]);
-
- close(1);
- dup(pipe1[1]);
- close(pipe1[1]); /* now writes to parent */
-
- /* read from tempfile */
-
- close (0);
- sprintf (buf, "/tmp/cxr.%d.1", ancestor);
- open (buf, 0); /* will be fd 0 */
-
- execv (SORT, sort2);
- fprintf (stderr, "couldn't exec '%s'\n", SORT);
- exit (1);
- break;
-
- default:
- fprintf(stderr, "in cxref(integers): can't happen\n");
- fflush(stderr);
- break;
- }
- }
-
- floats()
- {
- int status;
- int pid;
- int ischild;
- char buf[BUFSIZ];
- struct stat fbuf;
-
- sprintf(buf, "/tmp/cxr.%d.2", ancestor);
- if (stat(buf, &fbuf) >= 0 && fbuf.st_size > 0)
- ; /* file is not empty */
- else
- return;
-
- level = 0; /* starting off as grandparent */
-
- ischild = ((pid = fork()) == 0);
-
- retest:
- switch (level) {
- case 0: /* first fork */
- if (ischild)
- {
- level++;
- do_pipe(pipe2);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close(pipe2[1]); /* doesn't need this */
-
- close (0);
- dup(pipe2[0]);
- close(pipe2[0]);
- sprintf (buf, "%s/fmtxref", SRCDIR);
- execv (buf, fmtxref);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- }
- else
- while (wait(&status) != pid)
- ;
- break;
-
- case 1: /* second fork */
- level++;
- close (pipe2[0]);
-
- close(1);
- dup(pipe2[1]);
- close(pipe2[1]);
-
- /* set up i/o for next child */
- do_pipe(pipe1);
-
- if (ischild = ((pid = fork()) == 0))
- goto retest;
-
- close (pipe1[1]);
- close (0);
- dup(pipe1[0]);
- close (pipe1[0]);
-
- cxrfilt[1] = "-f";
- cxrfilt[2] = NULL;
-
- sprintf (buf, "%s/cxrfilt", SRCDIR);
- execv (buf, cxrfilt);
- fprintf (stderr, "couldn't exec '%s'\n", buf);
- exit (1);
- break;
-
- case 2:
- level++;
- close (pipe1[0]);
-
- close(1);
- dup(pipe1[1]);
- close(pipe1[1]); /* now writes to parent */
-
- /* read from tempfile */
-
- close (0);
- sprintf (buf, "/tmp/cxr.%d.2", ancestor);
- open (buf, 0); /* will be fd 0 */
-
- execv (SORT, sort3);
- fprintf (stderr, "couldn't exec '%s'\n", SORT);
- exit (1);
- break;
-
- default:
- fprintf(stderr, "in cxref(floats): can't happen\n");
- fflush(stderr);
- break;
- }
- }
-
- usage()
- {
- fprintf(stderr, "usage: %s [-SCcsif] [-w width] [files]\n", name);
- fflush(stderr);
- exit (1);
- }
-
- char *filename(fname)
- char *fname;
- {
- char *cp, *basename();
-
- cp = basename(fname);
-
- return ( strcmp(cp, "-") == 0 ? "stdin" : cp);
- }
-
- catchem() /* simple signal catcher */
- {
- signal(SIGQUIT, SIG_IGN);
- signal(SIGINT, SIG_IGN);
-
- deltemps();
-
- exit (0);
- }
-
- #include "basename.c"
- End of cxref.c
- echo 'extracting --- cxrfilt.c' 1>&2
- cat > cxrfilt.c << 'End of cxrfilt.c'
- /*
- ** cxrfilt.c
- **
- ** if called with no flags, or with the -c or -s flags, it will
- ** separate out integer and floating point constants into
- ** their own files, pass char and string constants on through.
- ** input: sorted output of docxref, contains identifiers and constants.
- ** output: identifiers, char and string constants, depending on flags.
- ** output goes to fmtxref. floats and ints to separate files for sorting.
- **
- ** if called with -i or -f option, behavior is to put sorted ints or floats
- ** back into their original formats, and then pass the output to fmtxref.
- **
- ** originally, there was a separate program to do float and int, but these two
- ** have been merged to reduce the total number of programs needed for cxref.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins
- ** All rights reserved
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- #include <stdio.h>
- #include "constdefs.h"
-
- #define MAXFILE 120
- #define MAXLINE 120
-
- FILE *fp1, *fp2;
- int cflag = 0;
- int sflag = 0;
- char *name;
- char *basename();
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char buf[BUFSIZ];
- char file1[MAXFILE], file2[MAXFILE];
- int i;
-
- name = basename(argv[0]);
-
- if (argc <= 1)
- usage();
-
- if(argv[1][0] == '-')
- {
- for (i = 1; argv[1][i] != '\0'; i++)
- switch (argv[1][i]) {
- case 'c':
- cflag = 1;
- break;
-
- case 's':
- sflag = 1;
- break;
-
- case 'i':
- intfilter();
- exit(0);
- break;
-
- case 'f':
- floatfilter();
- exit(0);
- break;
-
- default: /* bad option given */
- usage();
- break;
- }
-
- /* if it gets to here, we were called only w/-c or -s */
- if (argc == 2)
- usage();
-
- argv++;
- }
-
- /* code for splitting constants off into separate files */
-
- sprintf(file1, "/tmp/cxr.%d.1", atoi(argv[1]));
- sprintf(file2, "/tmp/cxr.%d.2", atoi(argv[1]));
-
- if ((fp1 = fopen(file1, "w")) == NULL)
- {
- fprintf(stderr,"%s: couldn't create tempfile 1\n");
- exit (2);
- }
-
- if ((fp2 = fopen(file2, "w")) == NULL)
- {
- fprintf(stderr,"%s: couldn't create tempfile 2\n");
- exit (3);
- }
-
- while (gets(buf) != NULL)
- {
- if (buf[0] != '~')
- printf("%s\n", buf);
- else
- switch (buf[1]) {
- case CHAR:
- if (! cflag)
- printf("%s\n", &buf[2]);
- break;
-
- case STRING:
- if (! sflag)
- printf("%s\n", &buf[2]);
- break;
-
- case INT:
- outint(buf);
- break;
-
- case FLOAT:
- outfloat(buf);
- break;
-
- default:
- fprintf(stderr,"%s: bad input line '%s'\n",
- name, buf);
- exit (4);
- }
- }
-
- fclose(fp1);
- fclose(fp2);
-
- exit(0);
- }
-
- #define OCTAL 1
- #define HEX 2
- #define DEC 3
-
- outint(buf)
- char *buf;
- {
- char file[MAXLINE], line[MAXLINE];
- int val;
- int type = 0;
-
- buf += 2; /* skip leading ~INT */
- file[0] = line[0] = '\0';
-
- if (buf[0] == '0') /* octal or hex */
- {
- if (buf[1] == 'x' || buf[1] == 'X') /* hex */
- {
- type = HEX;
- buf += 2; /* skip leading 0x */
- sscanf(buf, "%x %s %s", &val, file, line);
- }
- else
- {
- type = OCTAL;
- sscanf(buf, "%o %s %s", &val, file, line);
- }
- }
- else
- {
- type = DEC;
- sscanf(buf, "%d %s %s", &val, file, line); /* decimal */
- }
-
- /*
- * strategy is to convert to decimal for numeric sorting,
- * then have output filter convert back to right base.
- *
- * type is used to tell intfilter() what to turn it back into.
- */
-
- fprintf(fp1, "%d\t%s\t%s\t%d\n", val, file, line, type);
- }
-
- outfloat(buf)
- char *buf;
- {
- char file[MAXLINE], line[MAXLINE];
- char mantissa[MAXLINE], exponent[MAXLINE];
- char strval[MAXLINE]; /* character representation of float */
- char controlstr[MAXLINE];
- double val;
- int i, j;
-
- buf += 2; /* skip ~FLOAT */
-
- mantissa[0] = exponent[0] = file[0] = line[0] = '\0';
-
- sscanf(buf, "%lf %s %s", &val, file, line);
-
- for (i = 0; buf[i] != '\t'; i++)
- if (buf[i] == '.')
- break;
-
- for (j = i + 1; buf[j] != 'E' && buf[j] != 'e' && buf[j] != '\t'; j++)
- ;
-
- j -= i - 1; /* j is now num digits to right decimal point. */
- if (j < 6)
- j = 6; /* default */
-
- sprintf(controlstr, "%%1.%dg", j); /* make control string */
- sprintf(strval, controlstr, val); /* make character string */
-
- /*
- * strategy is a follows:
- * 1) convert all floats to a common printed format (%g)
- * 2) split up mantissa and exponent into separate parts for sorting
- * 3) put them back together later when called w/-f option.
- */
-
- for(i = j = 0; strval[j] != 'e' && strval[j] != 'E' && strval[j] != '\0'; i++, j++)
- mantissa[i] = strval[j];
- mantissa[i] = '\0';
-
- if (strval[j] == 'e' || strval[j] == 'E')
- {
- j++;
- for(i = 0; strval[j] != '\0'; i++, j++)
- exponent[i] = strval[j];
- exponent[i] = '\0';
- }
- else
- exponent[0] = '\0';
-
- fprintf(fp2, "%s\t%s\t%s\t%s\n", mantissa,
- exponent[0] != '\0' ? exponent : "0", file, line);
- }
-
- usage()
- {
- fprintf(stderr, "usage: %s [-csfi] pid\n", name);
- exit (1);
- }
-
-
- intfilter() /* put sorted ints back into their original bases */
- {
- char buf[BUFSIZ];
- char file[MAXLINE], number[MAXLINE];
- int val;
- int type;
-
- while (gets(buf) != NULL)
- {
- sscanf(buf, "%d %s %s %d", &val, file, number, &type);
-
- switch (type) {
- case OCTAL:
- if (val == 0) /* don't print 00 */
- printf("0\t%s\t%s\n", file, number);
- else
- printf("0%o\t%s\t%s\n", val, file, number);
- /* supply leading 0 */
- break;
-
- case DEC:
- printf("%d\t%s\t%s\n", val, file, number);
- break;
-
- case HEX:
- printf("0x%x\t%s\t%s\n", val, file, number);
- break;
-
- default:
- fprintf(stderr,"%s: bad input line '%s'\n", name, buf);
- exit (4);
- }
- }
- }
-
- floatfilter() /* put sorted floats back together */
- {
- char buf[BUFSIZ];
- char file[MAXLINE], number[MAXLINE];
- char mantissa[MAXLINE], exponent[MAXLINE];
-
- while (gets(buf) != NULL)
- {
- sscanf(buf, "%s %s %s %s", mantissa, exponent, file, number);
-
- if (strcmp(exponent, "0") == 0)
- printf("%s", mantissa);
- else
- printf("%sE%s", mantissa, exponent);
-
- printf("\t%s\t%s\n", file, number);
- }
- }
-
- #include "basename.c"
- End of cxrfilt.c
- echo 'extracting --- docxref.c' 1>&2
- cat > docxref.c << 'End of docxref.c'
- /*
- ** docxref.c
- **
- ** Driver for lex based scanner. Arranges for stdin to be each named
- ** file in turn, so that yylex() never has to know about files.
- ** Some of this code is not pretty, but it's not too bad.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins.
- ** All rights reserved.
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- #include <stdio.h>
- #include <ctype.h>
-
- #define TRUE 1
- #define FALSE 0
-
- extern char yytext[];
- extern int yyleng;
-
- int line_no = 1; /* current line number */
- char *fname = NULL; /* current file name */
-
- char *basename(); /* strips leading path of a file name */
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- FILE saved_in, *fp;
- char *name;
- int more_input = FALSE; /* more files to process */
- int read_stdin = FALSE;
-
- name = basename(argv[0]); /* save command name */
- fname = "stdin"; /* assume stdin */
-
- if(argc == 1)
- {
- yylex();
- exit(0);
- }
-
- if(argv[1][0] == '-' && argv[1][1] != '\0')
- usage(argv[0]); /* will exit */
-
- saved_in = *stdin;
- /* save stdin in case "-" is found in middle of command line */
-
- for(--argc, argv++; argc > 0; --argc, argv++)
- {
- if(fileno(stdin) != fileno((&saved_in)) || read_stdin)
- fclose(stdin);
- /* free unix file descriptors */
-
- if(strcmp(*argv, "-") == 0)
- {
- *stdin = saved_in;
- fname = "stdin";
- read_stdin = TRUE;
- more_input = (argc - 1 > 0);
- }
- else if((fp = fopen(*argv,"r")) == NULL)
- {
- fprintf(stderr,"%s: can't open %s\n", name, *argv);
- continue;
- }
- else
- {
- *stdin = *fp;
- /* do it this way so that yylex() */
- /* never knows about files etc. */
- more_input = (argc - 1 > 0);
- fname = *argv;
- }
-
- yylex(); /* do the work */
-
- if(more_input)
- line_no = 1;
- }
- }
-
- outid()
- {
- char *basename();
-
- printf("%s\t%s\t%d\n", yytext, basename(fname), line_no);
- }
-
- usage(name)
- char *name;
- {
- fprintf(stderr,"usage: %s [files]\n", name);
- exit(1);
- }
-
- #include "basename.c"
- End of docxref.c
- echo 'extracting --- fmtxref.c' 1>&2
- cat > fmtxref.c << 'End of fmtxref.c'
- /*
- ** fmtxref.c
- **
- ** format the output of the C cross referencer.
- ** this program relies on the fact that its input
- ** is sorted and uniq-ed.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins.
- ** All rights reserved.
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- #include <stdio.h>
- #include <ctype.h>
-
- #define TRUE 1
- #define FALSE 0
-
- #define MAXID 121 /* maximum lengths of identifiers, file names, etc. */
- #define MAXFILE 15
- #define MAXLINE 121
- #define MAXNUM 7
-
- #define ID 1 /* return codes to indicate what is new on input line */
- #define NEWFILE 2
- #define LINE 3
- #define ERROR 4
-
- #define WIDTH 80 /* default line output width */
-
- int width = WIDTH;
-
- char prev_id[MAXID] = "";
- char prev_file[MAXFILE] = "";
-
- char id[MAXID] = "";
- char file[MAXFILE] = "";
- char line[MAXNUM] = "";
-
- char *name;
- char *basename(); /* strips leading path name */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char inline[BUFSIZ];
- char *gets();
- int val;
-
- name = basename(argv[0]);
-
- /*
- * since this program is ONLY called by the cxref driver,
- * we know that it will be called "fmtxref -w width"
- * so we don't have to do complicated argument parsing.
- * we also know that cxref makes sure we get a valid width.
- */
-
- if (argc > 1)
- if (argc == 3)
- if (strcmp(argv[1], "-w") == 0)
- width = atoi(argv[2]);
- else
- usage();
- else
- usage();
- /* else
- use default width */
-
- if(gets(inline) == NULL)
- {
- fprintf(stderr, "%s: standard input is empty.\n", name);
- exit(1);
- }
-
- if((val = breakup(inline)) == ERROR)
- {
- fprintf(stderr, "%s: malformed input '%s'\n", name, inline);
- exit(2);
- }
-
- output(val); /* does proper formatting */
-
- while(gets(inline) != NULL && val != ERROR)
- {
- val = breakup(inline);
- output(val);
- }
-
- if(val == ERROR)
- {
- fprintf(stderr, "%s: malformed input '%s'\n", name, inline);
- exit(2);
- }
-
- putchar('\n');
- }
-
- breakup(text)
- char *text;
- {
- int retval;
- int i, j;
-
- if(text[0] == '"' || text[0] == '\'')
- {
- /* quoted stuff, break the line up by hand */
-
- i = 0;
- id[i++] = text[0];
-
- for(j = 1; text[j] != text[0]; i++, j++)
- {
- id[i] = text[j];
- if(id[i] == '\\')
- id[++i] = text[++j]; /* e.g. \" */
- }
- id[i++] = text[0];
- id[i] = '\0';
- j++; /* skip close quote */
-
- while(isspace(text[j]))
- j++;
-
- for(i = 0; !isspace(text[j]); i++, j++)
- file[i] = text[j];
- file[i] = '\0';
-
-
- while(isspace(text[j]))
- j++;
-
- for(i = 0; !isspace(text[j]) && text[j] != '\0'; i++, j++)
- line[i] = text[j];
- line[i] = '\0';
- }
- else
- {
- if(sscanf(text, "%s %s %s", id, file, line) != 3)
- return(ERROR);
- }
-
- /* now decide about return code for formatting */
-
- if(strcmp(prev_id, id) != 0) /* different identifiers */
- {
- strcpy(prev_id, id);
- strcpy(prev_file, file);
- retval = ID;
- }
- else if(strcmp(prev_file, file) != 0) /* different files */
- {
- strcpy(prev_file, file);
- retval = NEWFILE;
- }
- else
- retval = LINE;
-
- return(retval);
- }
-
- output(val)
- int val;
- {
- static int curpos = 1;
- static int first = TRUE;
- int line_len = strlen(line);
-
- switch(val) {
- case ID:
- if(! first)
- putchar('\n'); /* finish off last line of prev id */
- else
- first = FALSE;
-
- printf("%-20.20s\t%-14.14s\t%s", id, file, line);
- curpos = 40 + line_len;
- break;
-
- case NEWFILE:
- printf("\n\t\t\t%-14.14s\t%s", file, line);
- curpos = 40 + line_len;
- break;
-
- case LINE:
- if(curpos + line_len + 2 < width)
- {
- printf(", %s", line); /* same output line */
- curpos += 2 + line_len;
- }
- else
- {
- printf(",\n\t\t\t\t\t%s", line); /* new line */
- curpos = 40 + line_len;
- }
- break;
-
- case ERROR:
- /* shouldn't come to here */
- fprintf(stderr, "%s: internal error: output() called with %s\n",
- name, "a value of ERROR");
- fprintf(stderr, "%s: id == '%s'\tfile == '%s'\tline == '%s'\n",
- name, id, file, line);
- break;
-
- default:
- /* shouldn't come to here either */
- fprintf(stderr, "%s: internal error: output() called with %s %d\n",
- name, "the unknown value", val);
- fprintf(stderr, "%s: id == '%s'\tfile == '%s'\tline == '%s'\n",
- name, id, file, line);
- break;
- }
- }
-
- usage()
- {
- char *basename();
-
- fprintf(stderr, "usage: %s [-w width]\n", basename(name));
- exit (1);
- }
-
- #include "basename.c"
- End of fmtxref.c
- echo 'extracting --- makefile' 1>&2
- cat > makefile << 'End of makefile'
- # makefile for cxref -- C cross referencing program
- #
- # Arnold Robbins, Information and Computer Science, Georgia Tech
- # gatech!arnold
- # Copyright (c) 1985 by Arnold Robbins.
- # All rights reserved.
- # This program may not be sold, but may be distributed
- # provided this header is included.
-
- # some files are system dependant, e.g. where sort is.
- # change the appropriate macro definitions and recompile.
-
-
- ### definitions of files to compile and load, and other targets for make
-
- SCANOBJS= docxref.o cscan.o
- SCANSRCS= docxref.c cscan.l
-
- CXREF = cxref
- INCLS= constdefs.h basename.c
- PROGS= docxref fmtxref cxrfilt $(CXREF)
- SRCS= $(SCANSRCS) fmtxref.c cxrfilt.c $(CXREF).c
- DOCS= README makefile cxref.1
-
- PRINTS= $(INCLS) $(SRCS) $(DOCS)
-
- CFLAGS= -O
-
- ### system dependant definitions, change when you install cxref
-
- # for my use during development, put in my bin, but see next few lines.
- DESTDIR= $(BIN)
- LIB= $(BIN)
-
- # when installing, use the lines below; change DESTDIR to local bin of choice.
- # DESTDIR=/ics/bin
- # LIB=/usr/local/lib/cxref
-
- # where to put the man page, use 1 instead of l if you don't have a manl.
- MANSEC=l
-
- # lex library, may be -lln on some systems
- LEXLIB= -ll
-
- # may be /bin/sort on some systems
- SORT=/usr/bin/sort
-
- # printer program, prt is for me, use pr on other systems
- P=prt
-
- # the owner and group of the installed program. Both are 'admin' on our
- # system, but they may different on yours.
- OWNER= admin
- GROUP= admin
-
- all: $(PROGS)
- @echo " all" done
-
- docxref: $(SCANOBJS)
- $(CC) $(SCANOBJS) $(LEXLIB) -o $@
-
- cscan.o docxref.o cxrfilt.o: $(INCLS)
-
- fmtxref: fmtxref.c
- $(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@
-
- cxrfilt: cxrfilt.c
- $(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@
-
- $(CXREF): $(CXREF).c
- $(CC) $(CFLAGS) -DSRCDIR='"$(LIB)"' -DSORT='"$(SORT)"' $@.c $(LDFLAGS) -o $@
-
- print:
- $(P) $(PRINTS) | lpr -b 'Cxref Source'
- touch print2
-
- print2: $(PRINTS)
- $(P) $? | lpr -b 'Cxref New Source'
- touch print2
-
- ### edit this before installing!!
-
- install: $(PROGS)
- # don't remove my bin!
- # rm -fr $(LIB)
- rm -f $(DESTDIR)/cxref
- # mkdir $(LIB)
- cp $(CXREF) $(DESTDIR)/$(CXREF)
- cp docxref $(LIB)/docxref
- cp fmtxref $(LIB)/fmtxref
- cp cxrfilt $(LIB)/cxrfilt
- # cp cxref.1 /usr/man/man$(MANSEC)/cxref.$(MANSEC)
- # cd $(DESTDIR); chmod 711 cxref; chown $(OWNER) cxref; chgrp $(GROUP) cxref
- # cd $(LIB); chmod 711 docxref fmtxref cxrfilt
- # cd $(LIB); chown $(OWNER) docxref fmtxref cxrfilt
- # cd $(LIB); chgrp $(GROUP) docxref fmtxref cxrfilt
-
- clean:
- rm -f $(SCANOBJS)
-
- clobber: clean
- rm -f $(PROGS) print2
- End of makefile
- echo 'extracting --- old.cxref.c' 1>&2
- cat > old.cxref.c << 'End of old.cxref.c'
- /*
- ** cxref.c
- **
- ** C driver for Cxref program.
- ** does argument handling, then builds the right
- ** shell commands for passing to the system() routine.
- **
- ** A possible but difficult speed improvement would be to
- ** set up the argument vectors ourselves, the i/o with a pipe()
- ** call, and do all the forking and execing ourselves.
- ** But, in keeping w/the philosophy of "Let someone else do
- ** the hard part", we leave well enough alone and let the shell do it.
- **
- ** Arnold Robbins, Information and Computer Science, Georgia Tech
- ** gatech!arnold
- ** Copyright (c) 1984 by Arnold Robbins
- ** All rights reserved
- ** This program may not be sold, but may be distributed
- ** provided this header is included.
- */
-
- #include <stdio.h>
- #include <ctype.h>
-
- #ifdef DEBUG
- #define system(str) printf("%s\n", str)
- #endif
-
- #ifdef TESTOUT
- dosystem(str)
- char *str;
- {
- int pid;
-
- fprintf(stderr, "%s\n", str);
- system(str);
- }
-
- #define system(str) dosystem(str) /* takes effect after above routine */
- #endif
-
- #define TRUE 1
- #define FALSE 0
-
- char *name; /* save command name */
-
- int xargc; /* make argc and argv available globally */
- char **xargv;
-
- int width = 0; /* output width */
-
- int sepflag = FALSE; /* do each one separately */
-
- int iflag = TRUE; /* print out ints */
- int fflag = TRUE; /* print out floats */
- int cflag = TRUE; /* print out chars */
- int sflag = TRUE; /* print out strings */
-
- char *filename(); /* turns "-" into "stdin" */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int i;
- int extra_arg = FALSE;
-
- name = filename(argv[0]);
-
- for(argv++, argc--; argc > 0; argv++, argc--)
- if (argv[0][0] != '-')
- break;
- else if(argv[0][1] == '\0') /* filename of "-" */
- break;
- else
- for(i = 1; argv[0][i] != '\0'; i++)
- {
- switch(argv[0][i]) {
- case 'S':
- sepflag = TRUE;
- break;
-
- case 'C':
- /* leave out all constants */
- cflag =
- iflag =
- fflag =
- sflag = FALSE;
- break;
-
- case 'c':
- cflag = FALSE;
- break;
-
- case 'i':
- iflag = FALSE;
- break;
-
- case 'f':
- fflag = FALSE;
- break;
-
- case 's':
- sflag = FALSE;
- break;
-
- case 'w':
- if (isdigit(argv[0][i+1]))
- {
- width = 0;
- for(i++; isdigit(argv[0][i]); i++)
- width = width * 10 + argv[0][i] - '0';
- i--;
- }
- else
- {
- width = atoi(argv[1]);
- extra_arg = TRUE;
- }
- break;
-
- default:
- usage();
- break;
- }
-
- if (extra_arg) /* skip column width */
- {
- extra_arg = FALSE;
- /* do this only once */
- /* inside the for loop */
- argv++;
- argc--;
- }
- }
-
- if (width != 0)
- if (width < 51)
- width = 80;
- else if (width > 132)
- width = 132;
-
- xargc = argc;
- xargv = argv;
-
- runprogs();
- }
-
- char command[BUFSIZ * 10]; /* may need LOTS of room */
- char com_buf[BUFSIZ * 10]; /* use short name for portability */
-
- char *docxref(); /* functions to generate commands with args */
- char *filter();
- char *fmtxref();
-
- #define ONLYONE 1
- #define ALLOFTHEM 2
-
- runprogs() /* execute the programs */
- {
- int i;
-
- if (sepflag) /* do each file separately */
- {
- for (i = 0; i < xargc; i++)
- {
- printf("\tC Cross Refence Listing of %s\n\n",
- filename(xargv[i]));
- fflush(stdout);
- /* send to ouput before commands start */
- sprintf(command,
- "%s | sort -u +0b -2 +2n | %s | %s",
- docxref(i, ONLYONE), filter(), fmtxref());
- system(command);
- if (iflag)
- {
- sprintf(com_buf,
- "sort -u +0n -1 +1b -2 +2n < /tmp/cxr.%d.1 | %s/cxrfilt -i | %s",
- getpid(), SRCDIR, fmtxref());
- sprintf(command,
- "if test -s /tmp/cxr.%d.1 ; then %s ; fi",
- getpid(), com_buf);
- system(command);
- }
- if (fflag)
- {
- sprintf(com_buf,
- "sort -u +0n +1n -2 +2b -3 +3n < /tmp/cxr.%d.2 | %s/cxrfilt -f | %s",
- getpid(), SRCDIR, fmtxref());
- sprintf(command,
- "if test -s /tmp/cxr.%d.2 ; then %s ; fi",
- getpid(), com_buf);
- system(command);
- }
- fflush(stdout);
- if (! isatty(fileno(stdout)))
- putchar('\f');
- }
- }
- else
- {
- if (xargc == 1)
- printf("\tC Cross Refence Listing of %s\n\n",
- filename(xargv[0]));
- else
- printf("\tC Cross Reference Listing\n\n");
- fflush(stdout);
- sprintf(command, "%s | sort -u +0b -2 +2n | %s | %s",
- docxref(0, ALLOFTHEM), filter(), fmtxref());
- system (command);
- if (iflag)
- {
- sprintf(com_buf,
- "sort -u +0n -1 +1b -2 +2n < /tmp/cxr.%d.1 | %s/cxrfilt -i | %s",
- getpid(), SRCDIR, fmtxref());
-
- sprintf(command,
- "if test -s /tmp/cxr.%d.1 ; then %s ; fi",
- getpid(), com_buf);
- system(command);
- }
- if (fflag)
- {
- sprintf(com_buf,
- "sort -u +0n +1n -2 +2b -3 +3n < /tmp/cxr.%d.2 | %s/cxrfilt -f | %s",
- getpid(), SRCDIR, fmtxref());
- sprintf(command,
- "if test -s /tmp/cxr.%d.2 ; then %s ; fi",
- getpid(), com_buf);
- system(command);
- }
- fflush(stdout);
- if (! isatty(fileno(stdout)))
- putchar('\f');
- }
-
- sprintf(command, "rm -f /tmp/cxr.%d.[12]", getpid());
- system(command);
- }
-
- char *docxref(index, howmany)
- int index, howmany;
- {
- static char buf[BUFSIZ * 10];
- int i, j;
-
- if (howmany == ONLYONE)
- sprintf(buf, "%s/docxref %s", SRCDIR, xargv[index]);
- else
- {
- /* put all the args on one command line */
- sprintf(buf, "%s/docxref ", SRCDIR);
-
- i = strlen(buf);
- for(; xargc > 0; xargc--, xargv++)
- {
- for(j = 0; xargv[0][j] != '\0'; j++)
- buf[i++] = xargv[0][j];
- buf[i++] = ' ';
- }
- buf[i] = '\0';
- }
-
- return (buf);
- }
-
- char *filter() /* command line for splitting off ints and floats */
- {
- static char buf[40];
-
- if (! cflag && sflag)
- sprintf(buf, "%s/cxrfilt -c %d", SRCDIR, getpid());
- else if (cflag && ! sflag)
- sprintf(buf, "%s/cxrfilt -s %d", SRCDIR, getpid());
- else if (! cflag && ! sflag)
- sprintf(buf, "%s/cxrfilt -cs %d", SRCDIR, getpid());
- else
- sprintf(buf, "%s/cxrfilt %d", SRCDIR, getpid());
-
- return (buf);
- }
-
- char *fmtxref()
- {
- static char buf[40];
-
- if (width != 0)
- sprintf(buf, "%s/fmtxref -w %d", SRCDIR, width);
- else
- sprintf(buf, "%s/fmtxref", SRCDIR);
-
- return(buf);
- }
-
- usage()
- {
- fprintf(stderr, "usage: %s [-SCcsif] [-w width] [files]\n", name);
- exit (1);
- }
-
- char *filename(fname)
- char *fname;
- {
- char *cp, *basename();
-
- cp = basename(fname);
-
- return ( strcmp(cp, "-") == 0 ? "stdin" : cp);
- }
-
- #include "basename.c"
- End of old.cxref.c
-
-