home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d160 / calls.lha / Calls / scan.c < prev    next >
C/C++ Source or Header  |  1988-10-02  |  8KB  |  364 lines

  1. /*
  2.  * scan.c -- a simple scanner for C, pulls out the function
  3.  *    calling pattern    (all by KSB)
  4.  */
  5.  
  6. #include <ctype.h>
  7. #include <stdio.h>
  8.  
  9. #include "debug.h"
  10.  
  11. #ifdef MCH_AMIGA
  12. extern int strlen();
  13. extern char *strcpy();
  14. extern char *malloc();
  15. #else
  16. #include <strings.h>
  17. #endif
  18.  
  19.  
  20. #include "scan.h"
  21. #include "main.h"
  22.  
  23. extern int debug;
  24.  
  25. int c;                /* parser look ahead            */
  26. FILE *input;            /* our input file pointer        */
  27. HASH *pHTRoot[2] =         /* our list of idents            */
  28.     {nilHASH, nilHASH};
  29. static char 
  30.     AUTO[] = "auto",    BREAK[] = "break",    CASE[] = "case",
  31.     CHAR[] = "char",    CONTINUE[] = "continue",DEFAULT[] = "default",
  32.     DO[] = "do",        DOUBLE[] = "double",    ELSE[] = "else",
  33.     ENUM[] = "enum",    EXTERN[] = "extern",    FLOAT[] = "float",
  34.     FOR[] = "for",        FORTRAN[] = "fortran",    GOTO[] = "goto",
  35.     IF[] = "if",        INT[] = "int",        LONG[] = "long",
  36.     REGISTER[] = "register",RETURN[] = "return",    SHORT[] = "short",
  37.     SIZEOF[] = "sizeof",    STATIC[] = "static",    STRUCT[] = "struct",
  38.     SWITCH[] = "switch",    TYPEDEF[] = "typedef",    UNION[] = "union",
  39.     UNSIGNED[] = "unsigned",VOID[] = "void",    WHILE[] = "while";
  40.  
  41. static HASH *
  42. newHASH()    /* get a new hash node                    */
  43. {
  44.     extern char *calloc();
  45.     register HASH *pHTRet;
  46.     static HASH *pHTQueue = nilHASH;
  47.  
  48. DEBUG0(1, "newHASH entered\n");
  49.  
  50.     if (nilHASH == pHTQueue) {
  51.         if (!(pHTRet = (HASH *)calloc(BUCKET, sizeof(HASH)))) {
  52.             (void) fprintf(stderr, "out of mem\n");
  53.             exit(2);
  54.         }
  55.         pHTQueue = (pHTRet+(BUCKET-1))->pHTnext = pHTRet;
  56.     }
  57.     pHTRet = pHTQueue;
  58.     pHTQueue = pHTRet->pHTnext ? nilHASH : pHTRet+1;
  59.     return pHTRet;
  60. }
  61.  
  62. HASH *
  63. search(name, Localp, pchFile)    /* translate name to hash node        */
  64. register char *name;
  65. int Localp;            /* -> trying to make a local def    */
  66. char *pchFile;
  67. {
  68.     register HASH **ppHT, *pHT;
  69.     register int i = 1;
  70.  
  71. DEBUG1(1, "search entered: name(%s) \n", name);
  72.  
  73.     ppHT = & pHTRoot[1];    /* first search statics    */
  74.     while((pHT = *ppHT) && (i = strcmp(pHT->pchname, name)) <= 0) {
  75.         if (0 == i && 0 == strcmp(pchFile, pHT->pchfile))
  76.             break;    /* found a visible static function    */
  77.         ppHT = & pHT->pHTnext;
  78.         i = 1;
  79.     }
  80.  
  81.     if (0 != i && ! Localp) {
  82.         ppHT = & pHTRoot[0];
  83.         while((pHT = *ppHT) && (i = strcmp(pHT->pchname, name)) < 0)
  84.             ppHT = & pHT->pHTnext;
  85.     }
  86.  
  87.     if (0 != i) {
  88.         pHT = newHASH();
  89.         pHT->pchname = (char *) strcpy((char *)malloc(strlen((name))+1), (name));
  90. #ifdef BADCALLOC        /* calloc does not zero mem?        */
  91.         pHT->pchfile = (char *) 0;
  92.         pHT->listp = 0;
  93.         pHT->calledp = 0;
  94.         pHT->pINcalls = nilINST;
  95. #endif BADCALLOC
  96.         pHT->localp = Localp;
  97.         pHT->pHTnext = *ppHT;
  98.         *ppHT = pHT;
  99.     }
  100.     return pHT;
  101. }
  102.  
  103. /*
  104.  * here we don't assume that cpp takes out comments, really
  105.  * paranoid of us, but I think that way
  106.  * f is a flag we use to make the look ahead come out right
  107.  * in all cases
  108.  */
  109. void
  110. eatwhite(f)    /* skip blanks, comments, "strings", 'chars' in input    */
  111. register int f;
  112. {
  113.  
  114. DEBUG1(1, "eatwhite entered: f(%d) \n", f);
  115.  
  116.     if (f)
  117.         c = getc(input);
  118.     for(/* void */; /* c != EOF */; c = getc(input)) {
  119.         if (isspace(c) || c == '\b') {
  120.             continue;
  121.         } else if ('/' == c) {        /* start of comment? */
  122.             if ('*' == (c = getc(input))) {
  123.                 c = getc(input);    /* eat comment */
  124.                 for(;;) {
  125.                     while (c != '*')
  126.                         c = getc(input);
  127.                     if ('/' == (c = getc(input)))
  128.                         break;
  129.                 }
  130.             } else {
  131.                 ungetc(c, input);
  132.                 c = '/';
  133.                 break;
  134.             }
  135.         } else if ('\'' == c || '"' == c) {
  136.             while(c != (f = getc(input))) {
  137.                 if ('\\' == f)
  138.                     getc(input);
  139.             }
  140.         } else if ('#' == c) {
  141.             while ('\n' != getc(input))
  142.                 /* void */;
  143.         } else {
  144.             break;
  145.         }
  146.     }
  147. }
  148.  
  149. void
  150. balance(l, r)    /* find balancing character                */
  151. register int l, r;
  152. {
  153.     register int brace = 1;
  154.  
  155.     do
  156.         eatwhite(1);
  157.     while (brace += (l == c) - (r == c));
  158. }
  159.  
  160. int
  161. getid(sb, ppchToken)    /* return 0 = var, 1 == func, 2 == keyword    */
  162. register char *sb;
  163. char **ppchToken;
  164. {
  165.     static char *keywords[] = {
  166.         AUTO, BREAK, CASE, CHAR, CONTINUE, DEFAULT,
  167.         DO, DOUBLE, ELSE, ENUM, EXTERN, FLOAT, FOR,
  168.         FORTRAN, GOTO, IF, INT, LONG, REGISTER,
  169.         RETURN, SHORT, SIZEOF, STATIC, STRUCT, SWITCH,
  170.         TYPEDEF, UNION, UNSIGNED, VOID, WHILE, (char *)0
  171.     };
  172.     register int i = 0;
  173.     register char **psbKey = keywords;
  174.  
  175.     do {
  176.         if (i < MAXCHARS)
  177.             sb[i++] = c;
  178.         c = getc(input);
  179.     } while (isalpha(c) || isdigit(c) || '_' == c);
  180.     sb[i] = '\000';        /* buffer really goes to MAXCHARS+1    */
  181.     eatwhite(0);    /* c == next char after id */
  182.  
  183.     while (*psbKey && 0 != strcmp(*psbKey, sb))
  184.         ++psbKey;
  185.  
  186.     if (*psbKey) {
  187.         *ppchToken = *psbKey;
  188.         return 2;
  189.     }
  190.  
  191.     return LPAREN == c;
  192. }
  193.  
  194. void
  195. eatdecl(sb)    /* eat anything that starts with any keyword listed    */
  196. register char *sb;
  197. {
  198.     static char *which[] = {    /* keywords mark a declaration    */
  199.         AUTO, CHAR, STATIC, DOUBLE, ENUM, EXTERN, FLOAT, INT,
  200.         LONG, REGISTER, SHORT, STATIC, STRUCT, TYPEDEF, UNION,
  201.         UNSIGNED, VOID, (char *) 0};
  202.     register char **psb = which;
  203.  
  204.     while(*psb)
  205.         if (*psb++ == sb)
  206.             break;
  207.     if (*psb) {
  208.         while ('=' != c && ';' != c && RPAREN != c) {
  209.             if (LCURLY == c)
  210.                 balance(LCURLY, RCURLY);
  211.             else if (LPAREN == c) {
  212.                 balance(LPAREN, RPAREN);
  213.             }
  214.             eatwhite(1);
  215.         }
  216.     }
  217. }
  218.  
  219. INST *
  220. newINST()    /* get a new instaniation  node                */
  221. {
  222.     extern char *calloc();
  223.     register INST *pINRet;
  224.     static INST *pINQueue = nilINST;
  225.  
  226.     if (nilINST == pINQueue) {
  227.         if (!(pINRet = (INST *)calloc(BUCKET, sizeof(INST)))) {
  228.             (void) fprintf(stderr, "out of mem\n");
  229.             exit(2);
  230.         }
  231.         pINQueue = (pINRet+(BUCKET-1))->pINnext = pINRet;
  232.     }
  233.     pINRet = pINQueue;
  234.     pINQueue = pINRet->pINnext ? nilINST : pINRet+1;
  235.     return pINRet;
  236. }
  237.  
  238. void
  239. level2(pHTCaller, pchFile)    /* inside a function looking for calls    */
  240. HASH *pHTCaller;
  241. char *pchFile;
  242. {
  243.     static char buffer[MAXCHARS+1];
  244.     register struct INnode *pINLoop;
  245.     register int brace = 0;
  246.     register HASH *pHTFound;
  247.     register struct INnode **ppIN = & (pHTCaller->pINcalls);
  248.     register int declp = 1;        /* eating declarations        */
  249.     auto char *pchToken;
  250.  
  251.     DEBUG0(1, "level2 entered: \n" );
  252.  
  253.     while (brace || declp) {
  254.         if (isalpha(c) || '_' == c) {
  255.             switch (getid(buffer, & pchToken)) {
  256.             case 1:
  257.                 pHTFound = search(buffer, 0, pchFile);
  258.                 if (Allp)
  259.                     goto regardless;
  260.                 for(pINLoop = pHTCaller->pINcalls;
  261.                     pINLoop;
  262.                     pINLoop = pINLoop->pINnext)
  263.                     if (pHTFound == pINLoop->pHTname)
  264.                         break;
  265.                 if (! pINLoop) {
  266.             regardless:
  267.                     pINLoop = *ppIN = newINST();
  268.                     pINLoop->pHTname = pHTFound;
  269.                     ppIN = & pINLoop->pINnext;
  270.                 }
  271.                 ++pHTFound->calledp;
  272.                 break;
  273.             case 2:
  274.                 eatdecl(pchToken);
  275.                 /* fall through */
  276.             case 0:
  277.                 break;
  278.             }
  279.         } else {
  280.             if (LCURLY == c)
  281.                 declp = 0, ++brace;
  282.             else if (RCURLY == c)
  283.                 --brace;
  284.             eatwhite(1);
  285.         }
  286.     }
  287.     *ppIN = nilINST;
  288. }
  289.  
  290. void
  291. level1(filename)    /* in a C source program, looking for fnx(){..}    */
  292. register char *filename;
  293. {
  294.     static char buffer[MAXCHARS+1];
  295.     static char *pchToken;
  296.     register HASH *pHTTemp;
  297.     register int parens = 0;
  298.     register int Localp = 0;
  299.     int i;
  300.  
  301.     DEBUG1(3, "level1 entered: filename(%s)\n", filename);
  302.  
  303.     c = ' ';
  304.  
  305.     do {        /* looking to a function decl    */
  306.  
  307.         DEBUG1(5, "level1: Top of loop c(%c)\n", c);
  308.  
  309.         if (isalpha(c) || '_' == c) {
  310.             i =  getid(buffer, & pchToken);
  311.  
  312.             DEBUG1(5, "level1: getid returned (%d)\n", getid);
  313.  
  314.             switch (i) {
  315.             case 1:
  316.                 while (parens += (LPAREN == c) - (RPAREN == c))
  317.                     eatwhite(1);
  318.                 for (;;) {    /* eat complex stuff    */
  319.                     eatwhite(1);
  320.                     if (LPAREN == c) {
  321.                         balance(LPAREN, RPAREN);
  322.                         continue;
  323.                     } else if (LBRACK == c) {
  324.                         balance(LBRACK, RBRACK);
  325.                         continue;
  326.                     } else {
  327.                         break;
  328.                     }
  329.                 }
  330.                 pHTTemp = search(buffer, Localp, filename);
  331.                 if (',' == c || ';' == c) {
  332.                     Localp = 0;
  333.                     break;
  334.                 }
  335.                 if (pHTTemp->pchfile && pHTTemp->pchfile != sbCmd &&
  336.                     (pHTTemp->pchfile == filename ||
  337.                     0 != strcmp(pHTTemp->pchfile, filename))) {
  338.                     fprintf(stderr, "%s is multiply defined [%s, %s]\n", pHTTemp->pchname, pHTTemp->pchfile, filename);
  339.                     exit(5);
  340.                 } else {
  341.                     pHTTemp->pchfile = filename;
  342.                     Localp = 0;
  343.                     level2(pHTTemp, filename);
  344.                 }
  345.                 continue;
  346.             case 2:
  347.                 if (STATIC == pchToken)
  348.                     Localp = 1;
  349.             case 0:
  350.                 continue;
  351.             }
  352.         } else if (LCURLY == c) {
  353.             balance(LCURLY, RCURLY);
  354.         } else if (LPAREN == c) {
  355.             ++parens;
  356.         } else if (RPAREN == c) {
  357.             --parens;
  358.         } else if ('*' != c) {
  359.             Localp = 0;
  360.         }
  361.         eatwhite(1);
  362.     } while (EOF != c);
  363. }
  364.