home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / unix_c / languags / c / cxref.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-21  |  8.7 KB  |  356 lines

  1. 24-Oct-85 02:48:52-MDT,9218;000000000001
  2. Return-Path: <unix-sources-request@BRL.ARPA>
  3. Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Thu 24 Oct 85 02:48:26-MDT
  4. Received: from usenet by TGR.BRL.ARPA id a022958; 24 Oct 85 2:44 EDT
  5. From: wirch@puff.uucp
  6. Newsgroups: net.sources
  7. Subject: C cross reference, of sorts...
  8. Message-ID: <493@puff.UUCP>
  9. Date: 24 Oct 85 01:13:02 GMT
  10. To:       unix-sources@BRL-TGR.ARPA
  11.  
  12. /*
  13. This program scans a C source file, and sends a list of symbols
  14.     to the output file.  This list is comprised of function
  15.     and variable declarations.  A kind of cross reference.
  16.  
  17. The program tries to be intelligent about declarations of variables,
  18.     and keeps the whole declaration (with modifiers) on one line in the output.
  19.     (so that the symbols "char" and "foo" are output on one line, not two.)
  20.  
  21. usage: 
  22.     fun infile.ext        (Output is to infile.FUN)
  23.  
  24.     (if you don't like this redirection scheme, change it yourself.)
  25.  
  26. from John Foust, 17 Oct 85, Madison, Wis. in Lattice C V2.15 under PC-DOS.
  27.  
  28.  
  29. Everyone is welcome to improve and distribute this program, for
  30. any reason.  It would be nice if you posted your improved versions.
  31.  
  32. This needs improvements.  It could be more useful if it could get
  33. a little more effort put into it...  Now, it's a hack to a hack,
  34. but hopefully tossing it out to usenet will make it all better...
  35.  
  36. possible future improvements:
  37.  
  38.     o  maybe there is an easier way to scan source... like only
  39.     watching comment and function starts and ends.
  40.     o  scan .h files, too?
  41.     o  parse #include "stdio.h" and #include <stdio.h> the same way,
  42.     and don't echo the filename twice.
  43.     o  higher intelligence in recognizing popular declarations,
  44.     like main(argc,argv) int argc; char **argv;
  45.     o  recognition of pointer '*' in declarations (now, it just outputs
  46.     symbols, with no * & ** (*foo)() etc. part to the symbols
  47.     o  buffering each function as it's parsed isn't necessary - a relic
  48.     of fxu.c
  49.     
  50.  
  51. * mainly modified from public domain Lattice utility FXU.C
  52. * This is it's header, which is not accurate for this program.
  53.  
  54. * name         fxu -- function extract utility
  55. *
  56. * usage        fxu filename function
  57. *
  58. *              where "filename" is the name of a file containing
  59. *              several C functions, and "function" is the name of
  60. *              the particular function to be extracted.  If the
  61. *              named function is found, then (1) standard input is
  62. *              copied to the standard output until EOF, and (2) the
  63. *              text of the named function is written to the standard
  64. *              output.  The first option allows header information
  65. *              to be prepended to the output file.
  66. *
  67. **/
  68.  
  69. #include "stdio.h"
  70. #include "ctype.h"
  71.  
  72. #define MAX 16        /* maximum characters in function name */
  73. #define MAXBUF 9000   /* maximum characters buffered between functions */
  74.  
  75. char strs[3][20];
  76.  
  77. char strbuf[60];
  78.  
  79. char *stpchr();
  80.  
  81. unsigned _stack = MAXBUF + 2000;    /* reserve sufficient stack */
  82.  
  83. main(argc, argv)
  84. int argc;
  85. char *argv[];
  86. {
  87. char infn[30],    /* file name strings */
  88.     otfn[30];
  89.  
  90. FILE *sfp, *outf;
  91.  
  92. char *dot;
  93.  
  94. int c, 
  95.     brace, 
  96.     cnest, 
  97.     nc;
  98. int i, 
  99.     ns, 
  100.     copy, 
  101.     inlit, 
  102.     delim, 
  103.     pc;
  104.  
  105. char symbol[MAX+1];
  106. char text[MAXBUF];
  107.  
  108.     if (--argc) {    /* at least one argv[] */
  109.     strcpy(infn,argv[1]);    /* infn is name.DOC */
  110.     strcpy(otfn,argv[1]);    /* otfn is name.FUN */
  111.     dot = stpchr( otfn, '.' );
  112.     *dot = 0;
  113.     strcat(otfn,".FUN");
  114.     if (!(sfp=fopen(infn,"r"))) {
  115.         fprintf(stderr,"Open error on input file %s\n",infn);
  116.         exit(1);
  117.     }
  118.     if (!(outf=fopen(otfn,"w"))) {
  119.         fprintf(stderr,"Open error on output file %s\n",otfn);
  120.         exit(1);
  121.     }
  122.     }
  123.     else {
  124.     fputs("Usage: fxu infile.ext\n", stderr);
  125.     fputs("Output is to infile.FUN\n",stderr);
  126.     exit(1);
  127.     }
  128.  
  129.     fprintf(outf," \n");
  130.     fprintf(outf,"%s declared symbols:\n",argv[1]);
  131.     fprintf(outf," \n");
  132.  
  133.     *strs[0] = *strs[1] = *strs[2] = 0;
  134.  
  135.     brace = cnest = nc = ns = copy = inlit = pc = 0;
  136.  
  137.     c = getc(sfp);        /* get first char */
  138.     while (c != EOF) {                 /* scan through source file */
  139.     if (ns == MAXBUF) {
  140.         fputs("Maximum buffer size exceeded\n", stderr);
  141.         exit(1);
  142.     }
  143.     if (copy == 0) {
  144.         if (brace == 0)
  145.         text[ns++] = c;  /* save chars between functions */
  146.     }
  147.     else
  148.         if (putchar(c) == EOF) {
  149.         fputs("Copy error\n", stderr);
  150.         exit(1);
  151.         }
  152.     if (c == '/') {             /* possible comment */
  153.         nc = 0;
  154.         if ((c = getc(sfp)) == '*') {
  155.         ++cnest;   /* bump nesting level */
  156.         if (copy)
  157.             putchar(c);
  158.         else
  159.             if (brace == 0) 
  160.             text[ns++] = c;
  161.         c = getc(sfp);
  162.         }
  163.     continue;
  164.     }
  165.     if (cnest != 0) {             /* inside comment */
  166.     if (c == '*') {
  167.         if ((c = getc(sfp)) == '/') {
  168.         --cnest;       /* reduce nesting level */
  169.         if (copy) 
  170.             putchar(c);
  171.         else 
  172.             if (brace == 0)
  173.             text[ns++] = c;
  174.         c = getc(sfp);
  175.         }
  176.         continue;
  177.     }
  178.     nc = 0;
  179.     }
  180.     else 
  181.     if (inlit) {               /* inside literal string */
  182.         if (c == '\\' && pc == '\\') 
  183.         c = 0;
  184.         if (c == delim && pc != '\\') 
  185.         inlit = 0;
  186.         pc = c;         /* save previous character */
  187.     }
  188.     else 
  189.         if (c == '\'' || c == '\"') {               /* enter literal string */
  190.         inlit = 1;
  191.         pc = 0;
  192.         delim = c;
  193.         }
  194.         else 
  195.         if (c == '{')
  196.             ++brace;
  197.         else 
  198.             if (c == '}') {             /* right brace */
  199.             nc = 0;
  200.             if (--brace == 0)
  201.                 if (copy == 0) 
  202.                 ns = 0;      /* reset save index if not found */
  203.                 else {               /* copy complete */
  204.                 putchar('\n');
  205.                 exit(0);
  206.                 }
  207.             }
  208.             else 
  209.             if (brace == 0) {
  210.                 /* symbol not started yet */
  211.                 if (nc == 0) {
  212.                 if (iscsymf(c))    /* start new symbol */
  213.                     symbol[nc++] = c;
  214.                 }
  215.                 else 
  216.                 if (iscsym(c) || c == '$')    /* continue symbol */
  217.                     if (nc < MAX) 
  218.                     symbol[nc++] = c;
  219.                     else 
  220.                     symbol[0] = '\0';
  221.                 else
  222.                     if (nc != 0) {             /* end of current symbol */
  223.                     symbol[nc++] = '\0';
  224.  
  225.                     /* move stack */
  226.                     strcpy(strs[0],strs[1]);
  227.                     strcpy(strs[1],strs[2]);
  228.                     strcpy(strs[2],symbol);
  229.  
  230.     /* if symbol is !well-known, print it with any logical others on stack */
  231.                     if (!wellknown(symbol)) {
  232.                         buildbuf();
  233.                         fprintf(outf,"%s\n",strbuf);
  234.                     }
  235.     
  236.                     nc = 0;
  237.                     }
  238.     }
  239.     c = getc(sfp);      /* get next char */
  240.     }
  241.     exit(1);
  242. }
  243.  
  244. /* wellknown(symbol)
  245.     determines if a symbol is a known modifier
  246. */
  247.  
  248. int wellknown(p)
  249. char *p;
  250. {
  251.     if    (symcmp(p,"int")==0
  252.     || symcmp(p,"struct")==0
  253.     || symcmp(p,"long")==0
  254.     || symcmp(p,"char")==0
  255.     || symcmp(p,"unsigned")==0
  256.     || symcmp(p,"static")==0
  257.     || symcmp(p,"extern")==0
  258.     || symcmp(p,"struct")==0
  259.     || symcmp(p,"include")==0
  260.     || symcmp(p,"define")==0
  261.     || symcmp(p,"ifdef")==0
  262.     || symcmp(p,"endif")==0
  263. /* you can stick more common symbols here */
  264.         )
  265.     return(1);
  266.     else
  267.     return(0);
  268. }
  269.  
  270.     
  271. /* create a string strbuf[] of the most logical interpretation of symbols:
  272.     strs[0..2] is a stack of last symbols encountered, with
  273.     strs[2] being the newest, strs[0] the oldest.
  274.     */
  275.  
  276. buildbuf()
  277. {
  278. int x;
  279.  
  280.     strbuf[0] = 0;
  281.     
  282.     /* [define] [symbol] */
  283.     if (symcmp(strs[1],"define")==0) {
  284.     strcat(strbuf,"#");
  285.     strcat(strbuf,strs[1]);
  286.     strcat(strbuf," ");
  287.     strcat(strbuf,strs[2]);
  288.     }
  289.     /* [include] [symbol] [h] */
  290.     else if (symcmp(strs[0],"include")==0 && symcmp(strs[2],"h")==0) {
  291.     strcat(strbuf,"#");
  292.     strcat(strbuf,strs[0]);
  293.     strcat(strbuf," ");
  294.     strcat(strbuf,strs[1]);
  295.     strcat(strbuf,".");
  296.     strcat(strbuf,strs[2]);
  297.     }
  298.     /* [ifdef|undef] [symbol] */
  299.     else if (symcmp(&strs[1][2],"def")==0) {
  300.     strcat(strbuf,"#");
  301.     strcat(strbuf,strs[1]);
  302.     strcat(strbuf," ");
  303.     strcat(strbuf,strs[2]);
  304.     }
  305.     /* [[extern|static]] [char|int|long|unsigned] [symbol] */
  306.     else if ( symcmp(strs[1],"char")==0
  307.             || symcmp(strs[1],"int")==0
  308.             || symcmp(strs[1],"unsigned")==0
  309.             || symcmp(strs[1],"long")==0 ) {
  310.         if ( symcmp(strs[0],"extern")==0 
  311.             || symcmp(strs[0],"extern")==0 ) {
  312.         strcat(strbuf,strs[0]);
  313.         strcat(strbuf," ");
  314.         }
  315.     strcat(strbuf,strs[1]);
  316.     strcat(strbuf," ");
  317.     strcat(strbuf,strs[2]);
  318.     }
  319.     else if ( symcmp(strs[1],"struct")==0 ) {
  320.     strcat(strbuf,strs[1]);
  321.     strcat(strbuf," ");
  322.     strcat(strbuf,strs[2]);
  323.     }
  324.     else    /* unknown, so return latest symbol */
  325.     strcat(strbuf,strs[2]);
  326. }
  327.  
  328.  
  329. /**
  330. *
  331. * name         symcmp -- compare symbols
  332. *
  333. * synopsis     retval = symcmp(p, q);
  334. *              int retval;            return code: 0 if equal, 1 if not
  335. *              char *p, *q;           symbols to be compared
  336. *
  337. * description  This function compares two alphanumeric symbols for
  338. *              identity.  Upper and lower case alphabetic characters
  339. *              are considered equivalent by this function.
  340. *
  341. **/
  342.  
  343. int symcmp(p,q)
  344. char *p, *q;
  345. {
  346. int a, b;
  347.  
  348.     while ((toupper(*p)) == (toupper(*q))) {
  349.     if (*p == '\0') 
  350.         return(0);
  351.     p++;
  352.     q++;
  353.     }
  354.     return(1);
  355. }
  356.