home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 364_02 / utlg_ca.c < prev    next >
C/C++ Source or Header  |  1992-05-26  |  11KB  |  464 lines

  1. /*
  2. HEADER:         ;
  3. TITLE:          C-ACROSS;
  4. VERSION         1.02
  5.  
  6. DESCRIPTION:   "Utility for multiple module programs. Produces
  7.       Six indexes of functions, prototypes, and globals that
  8.       enable user to 'see across' modules for use in checking
  9.       and comparison.  One of these is type of hierarchical
  10.       functions list, a listing by module of functions
  11.       and calls made FROM them; another is alphabetical list
  12.       of functions and calls made TO them. Globals listed
  13.       in schematic descriptors which record all modifiers
  14.       and qualifiers and enable checking of declarators
  15.       across modules. Creates, on request, header file
  16.       consisting of prototypes constructed from function
  17.       definitions. Can list user types #defined and some
  18.       preprocessor #defines. Full documentation in README.CA";
  19.  
  20. KEYWORDS:       Utility, Cross Reference, Deubgging;
  21. SYSTEM:         MS-DOS;
  22. FILENAME:       UTLG_CA.C;
  23.  
  24. WARNINGS:      "1. Assumes function definitions conform with
  25.         ANSI standards and have prototype form. See
  26.         also "Caveats and Restrictions" in README.CA.
  27.         2. Assumes syntactically correct source files.
  28.         3. Written and tested using Microsoft QuickC.
  29.         4. Copyright retained.  See Copyright
  30.         information in README.CA.";
  31.  
  32. SEE-ALSO:      EXIT_CA.C, FUNC_CA.C, GLOB_CA.C, IFDEF_CA.C, INTF_CA.C,
  33.            LINKL_CA.C, PARSE_CA.C, TDEF_CA.C, TYPES_CA, UTIL_CA.C,
  34.            XRF_CA.C, README.CA,
  35.            CA.H, CA.PRJ, CA.RPT, CDECL_CA.H, KEYWORDS.H;
  36. AUTHORS:       Myron Turner;
  37. COMPILERS:     Microsoft C;
  38.  
  39. */
  40.  
  41. /***************************  C-ACROSS  ***************************
  42.                    V. 1.02
  43.                Copyright (C) Myron Turner
  44.  
  45.               333 Bartlet Ave.
  46.               Winnipeg, Manitoba
  47.               Canada R3L 0Z9
  48.               (204) 284-8387
  49.  
  50. *********************************************************************/
  51.  
  52. #define CLOSE_PAREN (int) ')'
  53. #define COMPLEX_DECL CLOSE_PAREN
  54.  
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <ctype.h>
  59. #include <malloc.h>
  60.  
  61. #define TYPEDEF_DEFINE
  62. #define TDEF_EXTERNAL
  63. #define EXTERNAL
  64. #define EXIT_CODES
  65. #include "ca.h"
  66. #include "ca_decl.h"
  67. #include "keywords.h"
  68.  
  69. /* externs and globals */
  70. int __mods[_MAX_MODS];
  71. struct user_typeStack *start_user_stack = NULL;
  72.  
  73. /*********Utilities for GLOBL_CA and for handling GLOBALS******************/
  74.  
  75.  
  76. int is_prototype(char *p)
  77. {
  78.   char *hold_p = p;
  79.  
  80.  
  81.      while(iswhite(*p)) p++;
  82.  
  83.      while (*p == '*') p++;
  84.      while(iswhite(*p)) p++;
  85.  
  86.      while (*p && !isdelim(*p) )
  87.      {
  88.      p++;
  89.      while(iswhite(*p)) p++;
  90.      while (*p == '*') p++;
  91.      while(iswhite(*p)) p++;
  92.      }
  93.  
  94.  
  95.      return ((int)*p);
  96. }
  97.  
  98.  
  99. int get_dimensions(char *ptr, int count)
  100. {
  101.     int k = 0;
  102.     while (*ptr && *ptr != ';') {
  103.     while (*ptr && *ptr != ']') { ptr++; k++; }
  104.     if (*ptr == ']') { ptr++; k++; }
  105.     while (*ptr && iswhite(*ptr)) ptr++;
  106.     if(*ptr != '[') break;
  107.     }
  108.     return(count + k);
  109. }
  110.  
  111.  
  112.  
  113. char * white_out(char *token)
  114. {
  115.  char *temp_from = token, *temp_to = token;
  116.  int i = 0;
  117.  
  118.  
  119.   do
  120.   {
  121.    if (!iswhite(*temp_from) )
  122.        *temp_to++
  123.        = *temp_from;
  124.   }
  125.    while(*temp_from++);
  126.  
  127.   *temp_to = '\0';
  128.  
  129.   return(token);
  130. }
  131.  
  132. int is_variable(char *token)
  133. {
  134.  int i;
  135.  
  136.  while(*token == '*') token++;
  137.  while(iswhite(*token)) token++;
  138.  if (key_word(token) || _modifier (token, 0) || check_types(token, &i) )
  139.                 return(0);
  140.  
  141.  return(1);
  142. }
  143.  
  144.  
  145. int check_pointers(char *p, int *ptr_count)
  146. {
  147.   int str_pos = 0;
  148.  
  149.  
  150.   while(iswhite(*p))
  151.   {
  152.   p++;
  153.   str_pos++;
  154.   }
  155.  
  156.   while (*p == '*') {
  157.    p++;
  158.    (*ptr_count)++;
  159.    str_pos++;
  160.    }
  161.   while(*p && iswhite(*p)) { p++; str_pos++; }
  162.  
  163.   return(str_pos);
  164. }
  165.  
  166.  
  167.   /* test variables string to locate sequences of modifiers, both */
  168.   /* user-defined and C-language based */
  169.  
  170. char *get_modifiers(int final_check, char *ptr, int mods[_MAX_MODS])
  171. {
  172.   int ptr_count, str_pos = 0, mod_count = 0 ;
  173.   char *pre_ptr_check, *ptr_to_null = ptr, *end_token;
  174.   int user_type_found, stack_pos, type_id_number;
  175.  
  176.    if (!__mods[0]) __mods[0] = 1;
  177.  
  178.    while (*ptr_to_null)
  179.    {
  180.       ptr_to_null++;
  181.     }
  182.  
  183.    do
  184.    {
  185.    pre_ptr_check = ptr;
  186.    ptr_count = 0;
  187.    user_type_found = 0;
  188.    ptr += check_pointers(ptr, &ptr_count);
  189.    /* create null terminated token to test in check_types() */
  190.    ptr = isolate_token(ptr, &end_token);
  191.  
  192.    /* restore token to original string if not a user defined modifier*/
  193.    if ( !(str_pos = check_types(ptr, &type_id_number)) ) {
  194.      if (end_token != ptr_to_null)
  195.        *end_token = ' ';
  196.      ptr =  pre_ptr_check;
  197.      }
  198.      else {
  199.      /* if user defined type modifier found */
  200.       user_type_found = 1;
  201.       if((__typ_mod[type_id_number] & 0xf) != _TYPE_) {
  202.     stack_pos = push_usertype(__type_def[type_id_number]);
  203.     if (__mods[0] < _MAX_MODS)  {
  204.         ptr_count <<= 8;
  205.       __mods[__mods[0]++] =  (stack_pos | ptr_count) | 0x2000;
  206.       }
  207.        }
  208.        else {
  209.      if (!final_check) mods[0] = TYPEDEF;
  210.      /* restore token to original string if a type & not a modifier*/
  211.      if (end_token != ptr_to_null)
  212.          *end_token = ' ';
  213.      ptr =  pre_ptr_check;
  214.      }
  215.  
  216.       ptr += str_pos;
  217.      }
  218.    /* check for C modifier */
  219.    mod_count = __mods[0];
  220.    str_pos = _modifier(ptr, 0);
  221.    if ((mod_count == __mods[0]) && str_pos) str_pos = 0;
  222.  
  223.    if (str_pos) ptr += str_pos;
  224.  
  225.    }
  226.    while (str_pos || user_type_found);
  227.  
  228.   if (final_check != FINAL_MODS_CHECK)  {
  229.      if (__mods[0] == 1) __mods[0] = 0;
  230.      return(ptr);
  231.      }
  232.  
  233.   for (mod_count = 0; mod_count < __mods[0]; mod_count++)  {
  234.      mods[mod_count] = __mods[mod_count];
  235.     }
  236.  
  237.   __mods[0] = 0;
  238.   return(ptr);
  239. }
  240.  
  241. /*struct user_typeStack start_user_stack;*/
  242.  
  243. int push_usertype(char * user_type)
  244. {
  245.    int count = 0;
  246.    struct user_typeStack *ts, *top, *previous;
  247.  
  248.     if (!start_user_stack) {
  249.  
  250.        ts = (struct user_typeStack *)
  251.                 calloc(1, sizeof(struct user_typeStack));
  252.        if (!ts) exit_ca(NO_USER_TYP_STK, "");
  253.        ts->type = (char *) calloc(1, strlen(user_type) + 1);
  254.        if (!ts->type) exit_ca(NO_USER_TYP_STK, "");
  255.        strcpy (ts->type, user_type);
  256.        ts->next = NULL;
  257.        start_user_stack = ts;
  258.        return (count);
  259.        }
  260.  
  261.  
  262.     top = start_user_stack;
  263.  
  264.     while(top)
  265.     {
  266.      if (!strcmp(top->type, user_type)) return (count);
  267.      previous = top;
  268.      top = top->next;
  269.      count++;
  270.      }
  271.  
  272.     ts =  (struct user_typeStack *) calloc(1, strlen(user_type) + 1);
  273.     previous->next = ts;
  274.     ts->next = NULL;
  275.     ts->type = (char *) calloc(1, strlen(user_type) + 1);
  276.     if (!ts->type) exit_ca(BAD_USER_TYP_STK, "");
  277.     strcpy (ts->type, user_type);
  278.     return (count);
  279.  
  280. }
  281.  
  282.  
  283. char *pop_usertype(int type_number)
  284. {
  285.  struct user_typeStack  *top = start_user_stack;
  286.  int count = 0;
  287.  
  288.     while (top)
  289.     {
  290.      if (type_number == count) return (top->type);
  291.      top = top->next;
  292.      count++;
  293.      }
  294.  
  295.    return (NULL);
  296. }
  297.  
  298.  
  299. /* checks string immediately after type specifier */
  300. /* makes assumption that open parenthesis following type specifier */
  301. /*and its modifiers will be a complex declaration */
  302.  
  303. extern int __Complex_Declarators;
  304. extern int __Complex_Prototypes;
  305.  
  306. int complex_value(char *p);
  307. int is_identifier(char **p);
  308. int is_complex_decl(char *p)
  309. {
  310.   char *closed_paren = NULL;
  311.   int str_pos = 0;
  312.  
  313.   if(!__Complex_Declarators) return (NO_COMPLEX);
  314.  
  315.   while(iswhite(*p) || *p == '*' || *p == '}' ) p++;
  316.  
  317.  
  318.   if (*p != '(') {
  319.       str_pos =_modifier (p, 0);
  320.       if (str_pos) {
  321.       p += str_pos;
  322.       while(iswhite(*p) || *p == '*') p++;
  323.       }
  324.      }
  325.  
  326.   if (*p != '(') return(NO_COMPLEX);
  327.  
  328.   return(complex_value(p));
  329. }
  330.  
  331. static char character[128];
  332. #define c_ident  1
  333. void ini_characterset(void)
  334. {
  335.  char *p =  character;
  336.  memset (p, 127, 128);
  337.  p += 48;
  338.  memset (p, c_ident, 10 );
  339.  p += 17;
  340.  memset (p, c_ident, 26 );
  341.  p += 32;
  342.  memset (p, c_ident, 26 );
  343.  
  344.  character['_'] =   c_ident;
  345.  character['*'] =  '*';
  346.  character['['] =  '[';
  347.  character[']'] =  ']';
  348.  character['('] =  '(';
  349.  character[')'] =  ')';
  350.  character['('] =  '(';
  351.  character[' '] =  ' ';
  352.  character['\t'] =  '\t';
  353.  character[';'] =  ';';
  354.  character['\0'] =  '\0';
  355.  
  356. }
  357.  
  358. int complex_value(char *p)
  359. {
  360.  int ptrs = 0, paren = 0, identifier = 0, array = 0;
  361.  int pointer_decl = 0, inner_paren = 0, ptr_mods = 0;
  362.  int function_decl = 0, nesting_levels = 0, array_levels = 0;
  363.  int hold_levels = 0;
  364.  char *holdp = p;
  365.  
  366.  
  367.     do
  368.     {
  369.  
  370.        switch (character[*p])
  371.        {
  372.        case '*':
  373.      ptrs++;
  374.      ptr_mods++;
  375.      break;
  376.  
  377.        case  '(':
  378.     if(function_decl && !pointer_decl)
  379.               return (NO_COMPLEX);
  380.     if (paren) inner_paren++;
  381.      paren++;
  382.      if (paren > inner_paren && identifier)
  383.          function_decl = 1;
  384.      ptrs = 0;
  385.      nesting_levels++;
  386.      break;
  387.  
  388.        case '[':
  389.      if ( ( nesting_levels> hold_levels ) ||
  390.           ( nesting_levels  && !inner_paren) )
  391.                         array_levels++;
  392.      array++;
  393.      hold_levels = nesting_levels;
  394.      if (array_levels) break;
  395.      if(function_decl && !pointer_decl) return (NO_COMPLEX);
  396.      break;
  397.  
  398.  
  399.        case  c_ident:
  400.      if ((pointer_decl || identifier) ) break;
  401.      identifier = is_identifier(&p);
  402.      break;
  403.  
  404.        case ']':
  405.        case ' ': case '\t':
  406.      break;
  407.  
  408.        case '\0': case ';':
  409.      /*  "A 'complex' declarator is an identifier qualified by more */
  410.      /*  than one array, pointer or function modifier."             */
  411.      /*                             --Microsoft Language Reference  */
  412.      if(function_decl && pointer_decl) return (COMPLEX_FN);
  413.      if (ptr_mods < 2 && array == 0) return (NO_COMPLEX);
  414.      if (pointer_decl) return (COMPLEX_VAR);
  415.      /* accept array declarations treated as complex */
  416.      if (array_levels) return (COMPLEX_VAR);
  417.      return (NO_COMPLEX);
  418.  
  419.        case ')':
  420.      paren--;
  421.      if (inner_paren) inner_paren--;
  422.  
  423.     /* let fall through */
  424.  
  425.       default:
  426.            if (!inner_paren && !pointer_decl) {
  427.             if (ptrs && identifier) pointer_decl = 1;
  428.             }
  429.  
  430.  
  431.       break;
  432.      }
  433.     }
  434.      while (*(++p));
  435.  
  436.  
  437.     return (NO_COMPLEX);
  438. }
  439.  
  440. int is_identifier(char **p)
  441. {
  442.   int count = 0, __type = 0;
  443.   char token[32];
  444.   char *token_ptr = token;
  445.  
  446.    while ( **p && count <32) {
  447.      if (iswhite(**p) || **p == ')' || **p == '[' || **p == '(') break;
  448.      *token_ptr++ = **p;
  449.      (*p)++;
  450.      count++;
  451.     }
  452.    (*p)--;  /* back-up so that current char is not lost when while loop */
  453.         /* increments pointer p in complex_value()    */
  454.    *token_ptr = '\0';
  455.    token_ptr = token;
  456.  
  457.    if (is_variable(token) ) {
  458.      data_type_ (token, &__type);
  459.      if (__type == NO_TYPE) return (1);
  460.      }
  461.  
  462.     return(0);
  463. }
  464.