home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 364_01 / glob_ca.c < prev    next >
C/C++ Source or Header  |  1992-05-26  |  27KB  |  1,023 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:       GLOB_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, GLOB_CA.C, FUNC_CA.C, IFDEF_CA.C, INTF_CA.C,
  33.            LINKL_CA.C, PARSE_CA.C, TDEF_CA.C, TYPES_CA, UTIL_CA.C,
  34.            UTLG_CA.C, 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.  
  42. /***************************  C-ACROSS  ***************************
  43.                    V. 1.02
  44.                Copyright (C) Myron Turner
  45.  
  46.               333 Bartlet Ave.
  47.               Winnipeg, Manitoba
  48.               Canada R3L 0Z9
  49.               (204) 284-8387
  50.  
  51. ********************************************************************/
  52.  
  53. /*lint -esym(534,storage_class,process_vars)  */
  54. #include <stdio.h>
  55. #include <string.h>
  56. #include <malloc.h>
  57. #include <ctype.h>
  58.  
  59. #define EXTERNAL
  60. #define INCLUDEFILES_DEFINE
  61. #define TYPEDEF_DEFINE
  62. #define TDEF_EXTERNAL
  63. #include "ca.h"
  64. #include "ca_decl.h"
  65. #include "keywords.h"
  66.  
  67. static void glob_ca_msgs(int Line, char * Mod, struct func *func_top );
  68. /* externs */
  69. extern struct includeFILE inclF;
  70. extern struct func  *FirstFunction;
  71. extern int function_no;
  72. extern int reading_includeF;
  73. extern int __mods[_MAX_MODS];
  74. extern FILE *scrn_out;
  75. extern int IfDefOFF;
  76. extern char *CurrentMod;
  77. /* globals */
  78. struct globals_list *global = NULL, *globals_start = NULL;
  79. char STRUNbuf[32];
  80.  
  81. #define SEMI_COLON (int) ';'
  82. #define OPEN_PAREN (int) '('
  83. #define CLOSE_PAREN (int) ')'
  84. #define CLOSE_BRACKET (int) '}'
  85. #define OPEN_BRACKET  '{'
  86. #define PROTOTYPE OPEN_PAREN
  87. #define COMPLEX_DECL CLOSE_PAREN
  88.  
  89. #define inSTRUCTUNION -1
  90. #define TYPEDEF_OPEN TYPEDEF + 101
  91. #define INCLUDEFILE 1
  92.  
  93. #define COMPLEX_INI  -1
  94.  
  95.  
  96. #define conv_sign_type(s,t) {   s = (char)((t & 0xFF00) >> 8); \
  97.                 t = (t & 0x00FF);   }
  98. #define is_outsideFunction(n) ((n <  func_top->line_no) \
  99.                 || (n > func_top->endfunc_line ))
  100.  
  101. static char COMPLEXdeclbuf[60];
  102. static int  COMPLExp = COMPLEX_INI;
  103. static int in_structunion = 0;
  104. static struct func * FN_ALPHAtop;
  105. extern int In_MainLoop;
  106. extern FILE **FP_ADDRESS;
  107. extern unsigned int inclfLine;
  108. extern unsigned int inclFini;
  109.  
  110. #define DEBUG_LINE 20
  111. struct func * record_variables(FILE *fp, FILE *rptfp,
  112.             struct func *start, struct func **func_alphatop)
  113. {
  114.   char  storage, *p,  *end_statement, buffer[261];
  115.   static struct func *func_top = NULL;
  116.   static struct func *previous = NULL;
  117.  
  118.   unsigned line_num = 0, lineno;
  119.   int inquotes = 0, intypedf = 0, t_pos = 0, delim = 0;
  120.   int preproc_type, skip_ifdef = 0;
  121.   int next_statement = 0, split_line = 0,  __type = NO_TYPE;
  122.   FILE * hold_fp  = fp;
  123.   char *in_comment = NULL;
  124.  
  125.   FP_ADDRESS = &fp;
  126.   rewind(fp);   In_MainLoop = 0;
  127.   FN_ALPHAtop = NULL;
  128.  
  129.   if(!func_top) func_top = FirstFunction;
  130.     else func_top = start->next_function;
  131.  
  132.   if(func_top && func_top->fnptr) func_top =  skip_fnptrs(func_top);
  133.  
  134.   glob_ca_msgs( __LINE__, __FILE__, func_top );
  135.  
  136.   ini_if_def_stack();
  137.  
  138. start_GlobalsLoop:
  139.  
  140.   while (  fgets (buffer, 160, fp) )
  141.     {
  142.  
  143.  
  144.     if (!reading_includeF)  lineno = ++line_num;
  145.         else lineno = ++inclfLine;
  146.  
  147.     p = buffer;
  148.     if(line_num == DEBUG_LINE)
  149.         line_num  = DEBUG_LINE;
  150.  
  151.      if (in_comment) {
  152.          in_comment = is_closed_comment(p);
  153.          if (in_comment == (char *) scrn_out) {
  154.         in_comment = comment_error(func_top, lineno, p);
  155.              }
  156.          }
  157.          else in_comment = is_comment(p);
  158.  
  159.   if(func_top)
  160.   {
  161.     if (is_outsideFunction(line_num) )
  162.     {
  163.  
  164.      next_statement = is_nextstatement(&p);  /* if not blank line */
  165.  
  166.      while (next_statement)
  167.       {
  168.  
  169.  
  170.        do {
  171.          if ( (inquotes = isliteral(p)) ) p++;
  172.          if (*p == '\n') { next_statement = 0; break; }
  173.        } while (inquotes );
  174.        while (iswhite(*p)) p++;
  175.  
  176.        if ( (preproc_type = is_includeF(p, hold_fp)) == INCLUDEFILE)
  177.                                 break;
  178.        if (preproc_type ==  PREPROCESSOR)
  179.            if (!IfDefOFF) skip_ifdef = is_else_if(p, skip_ifdef);
  180.        if (skip_ifdef) { next_statement = 0; break; }
  181.  
  182.         COMPLExp = COMPLEX_INI;
  183.         if( !(delim == PROTOTYPE  || split_line) )
  184.         if (!intypedf && !isdelim(*p) )
  185.           if (in_structunion || (t_pos = data_type_(p, &__type) )) {
  186.  
  187.         if (__type != NO_TYPE ) {
  188.             char *complex_p = p;
  189.             if(!intypedf && !in_structunion) complex_p += t_pos;
  190.             delim = is_prototype(p);
  191.             if ( (delim != PROTOTYPE) ||
  192.             (delim == PROTOTYPE &&
  193.             (COMPLExp = is_complex_decl(complex_p))) ) {
  194.                t_pos = sign_or_ld(p, t_pos, &__type);
  195.                process_vars(p, t_pos, func_top, __type, lineno,
  196.                             storage=0,  rptfp);
  197.               }
  198.  
  199.             }
  200.         }
  201.         else if (__type == TYPEDEF_OPEN) intypedf = 1;
  202.  
  203.         if(!t_pos && __type != PREPROCESSOR) {
  204.           if (!intypedf && !in_structunion) {
  205.           if (!vol_const(p, func_top, lineno, &__type, rptfp))
  206.          delim = storage_class(p, func_top, lineno, &__type, rptfp);
  207.            }
  208.         }
  209.        if (next_statement)
  210.         {
  211.          next_statement = 0;
  212.          end_statement = strchr(p, SEMI_COLON);
  213.          if (end_statement || __type == PREPROCESSOR) {
  214.         intypedf = 0;
  215.         delim = 0;
  216.         split_line = 0;
  217.         if (end_statement)  {
  218.            p = end_statement + 1;
  219.            next_statement = is_nextstatement(&p);
  220.            }
  221.         }
  222.         else
  223.         if (!intypedf && !in_structunion)
  224.             split_line = 1;
  225.  
  226.         }
  227.  
  228.  
  229.       }                  /* while (next_statement) */
  230.  
  231.     }                    /* if (is_outsideFunction(line_num)) */
  232.      else
  233.      storage_class(p, func_top, lineno,  &__type, rptfp);
  234.  
  235.  
  236.     if (line_num >= func_top->endfunc_line) {
  237.        previous = func_top;
  238.        func_top = func_top->next_function;
  239.        }
  240.  
  241.   }   /* if (func_top) */
  242.  
  243.     }     /* while (fgets. . .) */
  244.  
  245.     next_statement = 0;
  246.     end_statement = NULL;
  247.     intypedf = 0;
  248.     delim = 0;
  249.     split_line = 0;
  250.  
  251.   if (close_include(hold_fp, &fp, rptfp, CurrentMod))
  252.             goto start_GlobalsLoop;
  253.  
  254.   free_if_def_stack();
  255.   func_top = previous;
  256.   if (FN_ALPHAtop) *func_alphatop = FN_ALPHAtop;
  257.   return(previous);
  258.  
  259. }
  260.  
  261.  
  262. static int xt_struct_union(char *p, int __type)
  263. {
  264.   char *ptr = NULL;
  265.   char *initializing = NULL;
  266.   static char *close_brackets = NULL;
  267.   static char *open_brackets = NULL;
  268.   static char *ending_semicol = NULL;
  269.   static int identified = 0;
  270.   size_t count;
  271.  
  272.       if (ending_semicol) {
  273.       in_structunion = 0;
  274.       open_brackets = NULL;
  275.       close_brackets = NULL;
  276.       ending_semicol = NULL;
  277.       }
  278.  
  279.       initializing = strchr(p, '=');
  280.       if (initializing) {
  281.      *initializing = ';';
  282.      *(++initializing) = '\0';
  283.      }
  284.  
  285.       if(!open_brackets) {
  286.      open_brackets = strchr(p, (int) OPEN_BRACKET);
  287.      if(open_brackets) in_structunion = 1;
  288.      }
  289.  
  290.        if (open_brackets && !close_brackets)
  291.      close_brackets = strchr(p, CLOSE_BRACKET);
  292.  
  293.        if (close_brackets && !ending_semicol) {
  294.       ending_semicol = strchr(p, SEMI_COLON);
  295.       }
  296.  
  297.  
  298.        if (in_structunion && !close_brackets)  {
  299.       if (!identified) { isolate_strun(p, __type); identified = 1; }
  300.       return(inSTRUCTUNION);
  301.       }
  302.  
  303.        if (in_structunion) {
  304.           if(ending_semicol) {
  305.          in_structunion = 0;
  306.          identified = 0;
  307.          }
  308.           return(close_brackets - p + 1);
  309.           }
  310.  
  311.      count = isolate_strun(ptr = p, __type);
  312.      ptr += count;
  313.      ending_semicol = strchr(p, SEMI_COLON);
  314.      if (initializing)
  315.         *initializing = ' ';
  316.         identified = 1;
  317.      if (ending_semicol) return(count);
  318.  
  319.      while(*ptr && iswhite(*ptr))  {  ptr++; count++; }
  320.      if (*ptr == '\n' || *ptr == '\0') {
  321.            in_structunion = 1;
  322.            return(inSTRUCTUNION);
  323.            }
  324.  
  325.      while (*ptr && (isalnum(*ptr) || *ptr == '_') )
  326.           {
  327.           ptr++; count++;
  328.           }
  329.      return(count);
  330.  
  331.  
  332. }
  333.  
  334. int infunclist(char *token_string);
  335. static int process_vars(char *p, int token_pos, struct func *funcptr,
  336.             int __type, int line_num, char storage, FILE *rptfp)
  337. {
  338.    char *ptr = p, *token, *open_array = NULL, *white_in_token;
  339.    int count, str_pos = 0;
  340.    char token_string[41];
  341.    int mods[_MAX_MODS];
  342.    static char hold_storage = '\0';
  343.    char *complex_decl = NULL, *complex_tokenstr = NULL;
  344.  
  345.    COMPLEXdeclbuf[0] = '\0';
  346.  
  347.    if (in_structunion) storage = hold_storage;
  348.    if (__type == STRUCTURE || __type == UNION  || __type == ENUM) {
  349.         token_pos =  xt_struct_union(p, __type);
  350.         hold_storage = storage;
  351.         if (token_pos == inSTRUCTUNION) return (0);
  352.         }
  353.  
  354.    ptr = p + token_pos;
  355.    while(*ptr && iswhite(*ptr)) ptr++;
  356.    if (!*ptr) return(0);
  357.  
  358.    if (complex_decl = strchr(ptr, '('))
  359.     *complex_decl = '\0';
  360.  
  361.   /* test string to locate sequences of modifiers, both user-defined */
  362.   /* and C-language based */
  363.    ptr = get_modifiers(FINAL_MODS_CHECK, ptr, mods);
  364.    /*restore parenthesis deleted in get_modifiers() */
  365.    if (complex_decl) *complex_decl = '(';
  366.  
  367.    if (*ptr == SEMI_COLON) return(SEMI_COLON);
  368.      else if (*ptr == '\n' || *ptr == '\0' ) return (0);
  369.  
  370.      if (complex_decl) {
  371.     while(iswhite(*ptr)) ptr++;
  372.     complex_tokenstr = ptr;
  373.     while(*ptr == '*' || iswhite(*ptr) ) ptr++;
  374.  
  375.     do
  376.     {
  377.       while (*ptr == '(' || *ptr == '*') ptr++;
  378.       str_pos = _modifier(ptr, 0);
  379.       ptr += str_pos;
  380.     }
  381.     while (str_pos);
  382.     while (!isalnum(*ptr) && *ptr != '_') ptr++;
  383.        }
  384.  
  385.      open_array = strchr(ptr, '[');
  386.  
  387.      while ( (ptr && *ptr) && (*ptr != '\n' && *ptr != SEMI_COLON) ) {
  388.     count = 0;
  389.     token = ptr;
  390.     while (ptr && *ptr == '*')  { ptr++; count++; }
  391.     white_in_token = ptr;
  392.     while(ptr && iswhite(*ptr)) { ptr++; count++; }
  393.     if (white_in_token == ptr) white_in_token = NULL;
  394.     while(*ptr && (isalnum(*ptr) || *ptr == '_' || *ptr == '*') ) {
  395.         ptr++;
  396.         count++;
  397.           }
  398.  
  399.        if (open_array) {
  400.          char *holdp = ptr;
  401.          int holdc = count;
  402.          if(!white_in_token) white_in_token = ptr;
  403.          while(ptr && iswhite(*ptr)) { ptr++; count++; }
  404.          if (white_in_token == ptr) white_in_token = NULL;
  405.          if (*ptr == '[' )
  406.            count = get_dimensions(ptr, count);
  407.            else { ptr = holdp; count = holdc; }
  408.          }
  409.     if(count > 40) count = 40;
  410.     strncpy(token_string, token, (size_t)count );
  411.     token_string[count] = '\0';
  412.     token = token_string;
  413.  
  414.  
  415.     if(*token_string) {
  416.        if (is_variable(token_string)) {
  417.           if (white_in_token) white_out(token_string);
  418.  
  419.           if(__typ_mod[__typenum] == _FNPTR_ ) {
  420.                strcpy(COMPLEXdeclbuf, token_string);
  421.                COMPLExp = COMPLEX_FN;
  422.                }
  423.  
  424.           if (complex_decl || (COMPLExp == COMPLEX_FN) ) {
  425.         if( __typ_mod[__typenum] != _FNPTR_)
  426.           str_pos = make_complex_decl(complex_tokenstr);
  427.            if (COMPLExp == COMPLEX_FN ) {
  428.           if(!infunclist(token_string))
  429.            FN_ALPHAtop =
  430.             fill_func_struct(token_string, line_num, funcptr->module);
  431.            Globfnptrpush(p, token_string);
  432.           }
  433.            }
  434.  
  435.           globals_start = fill_globals_struct(token_string, funcptr,
  436.                 mods,  __type, line_num, storage, rptfp);
  437.                      }
  438.         }
  439.         else return(0);
  440.  
  441.      if (open_array) {
  442.         ptr = strchr(ptr, ']');
  443.         if (ptr) ptr++; else return(1);
  444.         }
  445.      while(*ptr && iswhite(*ptr)) ptr++;
  446.      if(*ptr == '=') {
  447.        ptr++;
  448.        while(*ptr && iswhite(*ptr)) ptr++;
  449.        if(*ptr == OPEN_BRACKET) return (1);
  450.        }
  451.  
  452.     if ( !(ptr = strchr(ptr, ','))) {
  453.         ptr = strchr(ptr, ';');
  454.         if (ptr) return(SEMI_COLON); else break;
  455.         }
  456.         else {
  457.          if (complex_decl) {
  458.                if (ptr < complex_tokenstr + str_pos) {
  459.                 ptr = strchr(ptr, ';');
  460.                 if (ptr) return(SEMI_COLON); else break;
  461.             }
  462.             }
  463.          while(*++ptr && iswhite(*ptr));
  464.          }
  465.  
  466.        }
  467.    return(1);
  468. }
  469.  
  470. static int storage_class(char *p, struct func *func_top, int line_num,
  471.                         int *__type,  FILE *rptfp)
  472. {
  473.  int str_pos = 0,  strpos = 0;
  474.  char *token_ptr ;
  475.  int  mods[_MAX_MODS], hold_type = 0;
  476.  char storage = 0, *hold_p;
  477.  char *open_paren = NULL;
  478.  char *truncation = NULL, trunc_char;
  479.  
  480.   while(*p && iswhite(*p)) p++;
  481.   hold_p = p;
  482.   token_ptr = p;
  483.   while(*p && (isalnum(*p) || *p == '_') ) {
  484.           p++;
  485.           }
  486.  
  487.   truncation = p;
  488.   trunc_char = *p;
  489.   *p = '\0';
  490.   str_pos = test_token(token_ptr, MODIFIERS[EXTERN]);
  491.   if (str_pos) storage = EXTERN;
  492.     else {
  493.      if (str_pos = test_token(token_ptr, MODIFIERS[STATIC]))
  494.          storage = STATIC;
  495.      }
  496.  
  497.  
  498.   if (str_pos) {
  499.     p++;
  500.  
  501.     while (iswhite(*p)) p++;
  502.     if (*p == PROTOTYPE) {
  503.        str_pos =  PROTOTYPE;
  504.        goto Not_Variable ;
  505.         }
  506.     open_paren = strchr(p, PROTOTYPE);
  507.  
  508.     /*test for FILE type */
  509.     str_pos = data_type_(p, __type);
  510.     if (*__type == file)
  511.           p += str_pos;
  512.     p = get_modifiers(FIRST_MODS_CHECK, p, mods);
  513.     if(*mods == TYPEDEF) hold_type = TYPEDEF;
  514.     if (*__type != file) {
  515.        strpos = data_type_(p, __type);
  516.        if (hold_type == TYPEDEF)
  517.       * __type = TYPEDEF;
  518.        else strpos = sign_or_ld(p,strpos, __type);
  519.     }
  520.     if (open_paren)
  521.     if (*open_paren != PROTOTYPE) *open_paren = PROTOTYPE;
  522.     if ( is_prototype(p) == PROTOTYPE ) {
  523.     char *complex_p = p;
  524.     if(!in_structunion) complex_p += strpos;
  525.     if ( !(COMPLExp = is_complex_decl(complex_p)) ) {
  526.            str_pos =  PROTOTYPE;
  527.            goto Not_Variable ;
  528.           }
  529.        }
  530.     process_vars(p, strpos, func_top, *__type, line_num, storage, rptfp);
  531.     }
  532.  
  533. Not_Variable:
  534.  
  535.     *truncation = trunc_char;
  536.     p = hold_p;
  537.  
  538.   return(str_pos);
  539. }
  540.  
  541.  
  542. struct globals_list *store_ll_globals( struct globals_list *i,
  543.                         struct globals_list *top);
  544. struct globals_list *fill_globals_struct(char *token, struct func *funcptr,
  545.    int mods[_MAX_MODS], int __type, int line_num, char storage, FILE * rptfp)
  546. {
  547.   size_t strL;
  548.   int spaces = 6;
  549.   static struct globals_list *top = NULL;
  550.   int mod_count;
  551.   char sign = '\0';
  552.  
  553.     if (inclFini ) {
  554.        fprintf(rptfp, "<Include File: %s>\n", inclF.file[inclF.level - 1]);
  555.        inclFini = 0;
  556.        }
  557.  
  558.     global = (struct globals_list *)
  559.      malloc ( sizeof (struct globals_list) );
  560.  
  561.     strL = strlen(token) + 1;
  562.     global->variable =  (char *) malloc(strL);
  563.     strcpy(global->variable, token);
  564.     global->module = funcptr->module;
  565.  
  566.     if(__type == NO_TYPE) __type = INTEGER;
  567.     global->type = __type;
  568.  
  569.     if (__type > END_TYPES) conv_sign_type(sign, __type);
  570.     if(__type == NO_TYPE) __type = INTEGER;
  571.  
  572.     if (__type == TYPEDEF) {
  573.       global->type_ident = (char *) malloc(strlen(__type_def[__typenum]) + 1);
  574.       strcpy (global->type_ident, __type_def[__typenum]);
  575.       }
  576.     if (__type == STRUCTURE || __type == UNION || __type == ENUM) {
  577.       global->struct_ident = (char *) malloc(strlen(STRUNbuf) + 1);
  578.       strcpy (global->struct_ident, STRUNbuf);
  579.       }
  580.  
  581.    if(COMPLEXdeclbuf[0]) {
  582.      char complex_id[2] = { (char )COMPLExp, '\0' };
  583.      global->complex_decl = (char *) malloc(strlen(COMPLEXdeclbuf) + 3);
  584.      strcpy(global->complex_decl, complex_id);
  585.      strncat(global->complex_decl, COMPLEXdeclbuf, 60);
  586.      } else global->complex_decl = NULL;
  587.  
  588.   if (mods[0]) {
  589.      for (mod_count = 0; mod_count < mods[0]; mod_count++)
  590.      global->modifiers[mod_count] = mods[mod_count];
  591.       }
  592.  
  593.   global->storage = (char)storage;
  594.     top = store_ll_globals(global, top);
  595.     if (reading_includeF) {
  596.        spaces = 4;
  597.        fprintf(rptfp, " <");
  598.        }
  599.     fprintf(rptfp, "%*d: ", spaces,  line_num);
  600.     if (storage)
  601.     fprintf(rptfp, "[%s] ", MODIFIERS[storage]);
  602.     if (sign) fprintf(rptfp, "[%c]", sign);
  603.     fprintf(rptfp, "[%s] %s\n",  TYPES[__type], token);
  604.  
  605.     if (mods[0] - 1) print_modifiers(0, mods, __type, rptfp);
  606.  
  607.     if (__type == TYPEDEF) {
  608.     fprintf(rptfp, "        type: %s\n", global->type_ident);
  609.     paginate(rptfp);
  610.       }
  611.  
  612.    if (global->type == STRUCTURE || global->type == UNION
  613.                     || global->type == ENUM) {
  614.        fprintf(rptfp, "         %s %s\n",
  615.                 TYPES[global->type], global->struct_ident);
  616.        paginate(rptfp);
  617.        }
  618.  
  619.     if(COMPLEXdeclbuf[0]) {
  620.        if(*global->complex_decl == (char)COMPLEX_FN)
  621.         fprintf(rptfp, "        <Fn Ptr> ");
  622.        else fprintf(rptfp, "          ");
  623.        fprintf(rptfp, "%s\n", global->complex_decl + 1);
  624.        paginate(rptfp);
  625.        }
  626.  
  627.     paginate(rptfp);
  628.     return(top);
  629. }
  630.  
  631.  
  632. void print_alphab_globals(struct globals_list *top, FILE *rptfp)
  633. {
  634.  
  635.   char *c1, *c2, temp[6];
  636.   int newinitletter = 0;
  637.   int spaces;
  638.   char sign;
  639.   struct globals_list *hold = top;
  640.  
  641.   print_headings(5, rptfp );
  642.  
  643.   while(top) {
  644.    if (newinitletter) {
  645.        newinitletter = 0;
  646.        fprintf(rptfp, "\n");
  647.        paginate(rptfp);
  648.        }
  649.  
  650.    if (top->storage)
  651.     fprintf(rptfp, "%s ", MODIFIERS[(int)top->storage]);
  652.     else fprintf(rptfp, "       ");
  653.  
  654.    sign = '\0';
  655.    spaces = 17;
  656.    if (top->type > END_TYPES)conv_sign_type(sign , top->type);
  657.    if(top->type == NO_TYPE) top->type = INTEGER;
  658.    if (sign)  fprintf(rptfp, "[%c]", sign); else fprintf(rptfp, "   ");
  659.  
  660.    fprintf(rptfp, "%-7s %-40s %s\n",
  661.             TYPES[top->type], top->variable, top->module);
  662.  
  663.    if (top->modifiers[0] - 1) {
  664.     print_modifiers(1, top->modifiers, top->type, rptfp);
  665.       /*  spaces = 2;*/
  666.     }
  667.  
  668.    if (top->type == TYPEDEF) {
  669.        fprintf(rptfp, "%*c[type:  %s]\n",spaces, ' ', top->type_ident);
  670.        paginate(rptfp);
  671.        }
  672.  
  673.    if (top->type == STRUCTURE || top->type == UNION || top->type == ENUM) {
  674.        fprintf(rptfp, " %*c[%s:  %s]\n",
  675.                 spaces, ' ',
  676.                 TYPES[top->type], top->struct_ident);
  677.        paginate(rptfp);
  678.        }
  679.  
  680.     if(top->complex_decl) {
  681.        if(*top->complex_decl == (char)COMPLEX_FN) {
  682.        fprintf(rptfp, " %*c<Fn Ptr>\n%*c ", spaces, ' ', spaces, ' ');
  683.        paginate(rptfp);
  684.        }
  685.      else
  686.        fprintf(rptfp, " %*c", spaces, ' ');
  687.        fprintf(rptfp, "%s\n",top->complex_decl + 1);
  688.        paginate(rptfp);
  689.        }
  690.  
  691.    c1 = top->variable;
  692.  
  693.    top = top->next;
  694.  
  695.    if(top) {
  696.      strncpy(temp, top->variable, 5);
  697.      temp[5] = '\0';
  698.      c2 = temp;
  699.      strupr(c1);
  700.      strupr(c2);
  701.      while(*c1 == '_' || *c1 == '*') c1++;
  702.      while(*c2 == '_' || *c2 == '*') c2++;
  703.      if(*c1 != *c2) newinitletter = 1;
  704.    }
  705.    paginate(rptfp);
  706.  
  707.    }
  708.  
  709.   strupr(c1);
  710.   top = hold;
  711.   fprintf(scrn_out,
  712.   "\n\n*******\n*******\n"
  713.    "ALPHABETICAL LIST OF GLOBAL SYMBOLS IN ALL MODULES\n\n");
  714.   while (top) {
  715.     if (top && hold)
  716.     if( (strcmp(top->variable, hold->variable)))
  717.     fprintf(scrn_out, "%s\n", top->variable);
  718.     hold = top;
  719.     top = top->next;
  720.     }
  721.    fprintf(scrn_out, "\n\n\nEND SCRNOUT\n");
  722. }
  723.  
  724.  
  725. static size_t isolate_strun(char *ptr, int __type)
  726. {
  727.  char *token;
  728.  size_t count = 0, token_count = 0;
  729.  
  730.      while(*ptr && iswhite(*ptr)) {  ptr++; count++; }
  731.      ptr += 6; count += 6;   /* 6 = size of keyword 'struct' */
  732.      if(__type == UNION || __type == ENUM) { ptr--; count--; }
  733.      while(*ptr && iswhite(*ptr))  {  ptr++; count++; }
  734.  
  735.          /* get past name of structure or union*/
  736.      token = ptr;
  737.      while(*ptr && (isalnum(*ptr) || *ptr == '_') ) {
  738.               ptr++;
  739.               count++;
  740.               token_count++;
  741.               }
  742.      if (token_count > 31) token_count = 31;
  743.      strncpy(STRUNbuf, token, token_count);
  744.      STRUNbuf[token_count] = '\0';
  745.  
  746.        return(count);
  747. }
  748.  
  749.  
  750. int is_nextstatement(char **p)
  751. {
  752.     while(iswhite(**p)) (*p)++;
  753.     if(**p != '\n' && **p != '\0') return (1);
  754.  
  755.     return (0);
  756. }
  757.  
  758. int is_includeF(char *p, FILE * hold_fp)
  759. {
  760.    char *token_ptr, *temp = p, *end_token;
  761.  
  762.    if(*p != '#') return (0);
  763.  
  764.    token_ptr = isolate_token(++(p), &end_token);
  765.  
  766.  
  767.    if ( !is_include(token_ptr, hold_fp)) {
  768.        p = temp;
  769.        return(PREPROCESSOR);
  770.        }
  771.    return(INCLUDEFILE);
  772. }
  773.  
  774.  
  775. static int sign_or_ld(char *p , int t_pos, int *__type)
  776. {
  777.    int type = *__type;
  778.    int str_pos = 0;
  779.  
  780.    if (type == LONG) {
  781.       str_pos = 5;
  782.       str_pos += data_type_(p + str_pos, __type);
  783.       if (*__type == DOUBLE) {
  784.          *__type |= LONG_DOUBLE;
  785.          return(str_pos);
  786.          }
  787.       return (t_pos);
  788.       }
  789.  
  790.    if(*__type == SIGNED) t_pos = 7;
  791.    else if(*__type == UNSIGNED) t_pos = 9;
  792.    str_pos = t_pos;
  793.  
  794.    if ( *__type == SIGNED || *__type == UNSIGNED  ) {
  795.       t_pos = data_type_(p + t_pos, __type);
  796.       if  (t_pos)  {
  797.     t_pos += str_pos;
  798.     if (type == UNSIGNED) *__type |= UNSIGNED_VAR;
  799.       else if (type == SIGNED) *__type |= SIGNED_VAR;
  800.     }
  801.       else if (str_pos == (t_pos += str_pos) )
  802.         *__type = type | INTEGER;
  803.    }
  804.  
  805.    return(t_pos);
  806. }
  807.  
  808. void print_modifiers(int alphab, int mods[_MAX_MODS], int __type, FILE *rptfp)
  809. {
  810.   int mod_count, nmber_ptrs = 0, type, p_count, userdef = 0;
  811.   char *type_ptr;
  812.  
  813.   if (alphab) fprintf(rptfp, "                  ");
  814.      else fprintf(rptfp, "         ");
  815.   fprintf(rptfp, "< ");
  816.  
  817.   for (mod_count = 1; mod_count < mods[0]; mod_count++) {
  818.        if (mods[mod_count] >= ( 1 << 8 ) ) {
  819.  
  820.        type = mods[mod_count];
  821.        if (type >= 0x2000) {
  822.           type &= 0x1fff;
  823.           userdef = 1;
  824.           }
  825.        nmber_ptrs =  (type & 0xff0) >> 8;
  826.        if (nmber_ptrs < 8)
  827.          for (p_count = 0; p_count < nmber_ptrs; p_count++)
  828.          fprintf(rptfp, "* ");
  829.        type &= 0x0f;
  830.        if (userdef) {
  831.          if (!(type_ptr = pop_usertype(type))) return;
  832.          }
  833.         else
  834.          type_ptr = MODIFIERS[ type ];
  835.  
  836.       }
  837.       else type_ptr = MODIFIERS[mods[mod_count]];
  838.        fprintf(rptfp, "%s  ", type_ptr);
  839.        }
  840.  
  841.    fseek(rptfp, (-1L), SEEK_CUR);
  842.    fprintf(rptfp, ">");
  843.   if ( !( __type == STRUCTURE || __type == UNION || __type == ENUM
  844.             || __type == TYPEDEF) || alphab ) {
  845.     fprintf(rptfp, "\n"); paginate(rptfp);
  846.     }
  847.  
  848. }
  849.  
  850.  
  851. int vol_const(char *p, struct func *func_top, int line_num,
  852.                     int *__type, FILE *rptfp)
  853. {
  854.  int str_pos = 0,  strpos = 0;
  855.  char *token_ptr, *hold_ptr, save_char;
  856.  int storage = 0;
  857.  int *mods_dummy = NULL;
  858.  
  859.   while(*p && iswhite(*p)) p++;
  860.   hold_ptr = p;
  861.   token_ptr = p;
  862.   while(*p && (isalnum(*p) || *p == '_') ) {
  863.           p++;
  864.           }
  865.   save_char = *p;
  866.   *p = '\0';
  867.  
  868.  
  869.     if ((str_pos = test_token(token_ptr, MODIFIERS[VOLATILE]))) {
  870.       __mods[0] = 1;
  871.       *p = save_char;
  872.       p = hold_ptr;
  873.       if (str_pos = _modifier (p, 0)) p += str_pos;
  874.       }
  875.       else
  876.       if (str_pos = test_token(token_ptr, MODIFIERS[CONSTANT])) {
  877.     __mods[0] = 1;
  878.     *p = save_char;
  879.     p = hold_ptr;
  880.     if (str_pos = _modifier (p, 0)) p += str_pos;
  881.     }
  882.  
  883.   if (str_pos) {
  884.  
  885.     while (iswhite(*p)) p++;
  886.     if (*p == PROTOTYPE) return(PROTOTYPE);
  887.  
  888.     p = get_modifiers(FIRST_MODS_CHECK, p, mods_dummy);
  889.     if (storage =  storage_class(p, func_top, line_num,  __type, rptfp))
  890.                         return(storage);
  891.     strpos = data_type_(p, __type);
  892.     strpos = sign_or_ld(p,strpos, __type);
  893.     if ( (is_prototype(p)) == PROTOTYPE ) {
  894.     char *complex_p = p;
  895.     if(!in_structunion) complex_p += strpos;
  896.     if ( !(COMPLExp = is_complex_decl(complex_p)) ) return(PROTOTYPE);
  897.     }
  898.     process_vars(p, strpos, func_top, *__type, line_num, (char)0, rptfp);
  899.     }
  900.     else {
  901.     *p = save_char;
  902.     p = hold_ptr;
  903.     __mods[0] = 0;
  904.     }
  905.   return(-str_pos);
  906. }
  907.  
  908. static int make_complex_decl(char *p)
  909. {
  910.    char *end_complex = NULL, *paren = NULL, *ptr;
  911.    size_t difference = 0;
  912.    ptr =  COMPLEXdeclbuf;
  913.  
  914.     ptr[60] = '\0';   /* keep string in bounds */
  915.     strcpy(ptr, p);
  916.  
  917.     end_complex =  strchr(ptr, ',');
  918.     if(end_complex) {
  919.        paren = strchr(end_complex, ')');
  920.        if (  !(strchr(end_complex, '(') > paren) )
  921.               end_complex = NULL;
  922.     }
  923.  
  924.     if (!end_complex)
  925.     end_complex =  strchr(ptr, ';');
  926.     if (!end_complex)
  927.     end_complex =  strchr(ptr, '\n');
  928.     *end_complex = '\0';
  929.  
  930.    difference = end_complex - ptr;
  931.    return(difference);
  932. }
  933.  
  934. static char *is_comment(char *p)
  935. {
  936.  char *start_comment = NULL, *end_comment = NULL;
  937.  char *start_quot = NULL, *end_quot = NULL;
  938.  int in_quot = 0;
  939.  
  940.  
  941.    start_comment = strchr(p, '/');
  942.    if (start_comment && *(start_comment + 1) == '*') {
  943.  
  944.     /* make sure we're not in a quotation */
  945.     start_quot = strchr(p, '\"');
  946.     if (start_quot) {
  947.      if (start_comment > start_quot) {
  948.         end_quot = start_quot + 1;
  949.         while (!(*end_quot == '\"')) {
  950.         if (*end_quot == '\\') end_quot++;
  951.          if (*end_quot == '\n' || *end_quot == '\0') {
  952.         in_quot = 1;
  953.         break;
  954.         }
  955.          end_quot++;
  956.         }
  957.        if (!in_quot)
  958.          if(*end_quot == '\"')
  959.            if (start_comment < end_quot) return (NULL);
  960.        }
  961.      }
  962.  
  963.     *start_comment = '\0';
  964.     end_comment = start_comment + 2;
  965.     /* if comment closed on current line return false: not in_comment */
  966.     while(*end_comment) {
  967.         if (*end_comment == '/')
  968.         if ( *(end_comment - 1) == '*' ) return(NULL);
  969.         end_comment++;
  970.         }
  971.     /* if comment not closed on current line return true: in_comment */
  972.     return (start_comment);
  973.       }
  974.  
  975.     return(NULL);
  976. }
  977.  
  978. static char * is_closed_comment(char * p)
  979. {
  980.     char *truncate = p;
  981.     while(*p) {
  982.     if (*p == '/') {
  983.     if ( *(p - 1) == '*' ) { *truncate = '\0'; return(NULL); }
  984.     if ( *(p + 1) == '*' ) return((char *)scrn_out);
  985.     }
  986.     p++;
  987.        }
  988.  
  989.     /* truncate line */
  990.     *truncate = '\0';
  991.     return(p);
  992.  
  993. }
  994.  
  995. static char *comment_error(struct func *func_top, unsigned lineno, char *p)
  996. {
  997.  
  998.    fprintf(scrn_out, "\n***"
  999.       "Possible comment error at line %u in module: %s\n   %s",
  1000.        lineno, func_top->module, p);
  1001.  
  1002.    return(p);
  1003. }
  1004.  
  1005. static void glob_ca_msgs(int Line, char * Mod, struct func *func_top )
  1006. {
  1007.  
  1008.   if (!func_top) {
  1009.        printf("\a");
  1010.        if (scrn_out != (FILE *)stdout)
  1011.        fprintf(scrn_out,
  1012.         "\nSecond Pass: NULL Pointer Found in Table of Functions:"
  1013.         "\n   function: record_variables()  module[%s]  Line: %d."
  1014.         "\n   Report File may prove unreliable.\n",  Mod, Line);
  1015.     return(NULL);
  1016.     }
  1017.  
  1018.   if (scrn_out != (FILE *)stdout) fprintf(scrn_out,
  1019.       "\nSecond Pass: %s\n", CurrentMod);
  1020.   printf("Second Pass: %s\n", CurrentMod);
  1021.  
  1022. }
  1023.