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 >
Wrap
C/C++ Source or Header
|
1992-05-26
|
11KB
|
464 lines
/*
HEADER: ;
TITLE: C-ACROSS;
VERSION 1.02
DESCRIPTION: "Utility for multiple module programs. Produces
Six indexes of functions, prototypes, and globals that
enable user to 'see across' modules for use in checking
and comparison. One of these is type of hierarchical
functions list, a listing by module of functions
and calls made FROM them; another is alphabetical list
of functions and calls made TO them. Globals listed
in schematic descriptors which record all modifiers
and qualifiers and enable checking of declarators
across modules. Creates, on request, header file
consisting of prototypes constructed from function
definitions. Can list user types #defined and some
preprocessor #defines. Full documentation in README.CA";
KEYWORDS: Utility, Cross Reference, Deubgging;
SYSTEM: MS-DOS;
FILENAME: UTLG_CA.C;
WARNINGS: "1. Assumes function definitions conform with
ANSI standards and have prototype form. See
also "Caveats and Restrictions" in README.CA.
2. Assumes syntactically correct source files.
3. Written and tested using Microsoft QuickC.
4. Copyright retained. See Copyright
information in README.CA.";
SEE-ALSO: EXIT_CA.C, FUNC_CA.C, GLOB_CA.C, IFDEF_CA.C, INTF_CA.C,
LINKL_CA.C, PARSE_CA.C, TDEF_CA.C, TYPES_CA, UTIL_CA.C,
XRF_CA.C, README.CA,
CA.H, CA.PRJ, CA.RPT, CDECL_CA.H, KEYWORDS.H;
AUTHORS: Myron Turner;
COMPILERS: Microsoft C;
*/
/*************************** C-ACROSS ***************************
V. 1.02
Copyright (C) Myron Turner
333 Bartlet Ave.
Winnipeg, Manitoba
Canada R3L 0Z9
(204) 284-8387
*********************************************************************/
#define CLOSE_PAREN (int) ')'
#define COMPLEX_DECL CLOSE_PAREN
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#define TYPEDEF_DEFINE
#define TDEF_EXTERNAL
#define EXTERNAL
#define EXIT_CODES
#include "ca.h"
#include "ca_decl.h"
#include "keywords.h"
/* externs and globals */
int __mods[_MAX_MODS];
struct user_typeStack *start_user_stack = NULL;
/*********Utilities for GLOBL_CA and for handling GLOBALS******************/
int is_prototype(char *p)
{
char *hold_p = p;
while(iswhite(*p)) p++;
while (*p == '*') p++;
while(iswhite(*p)) p++;
while (*p && !isdelim(*p) )
{
p++;
while(iswhite(*p)) p++;
while (*p == '*') p++;
while(iswhite(*p)) p++;
}
return ((int)*p);
}
int get_dimensions(char *ptr, int count)
{
int k = 0;
while (*ptr && *ptr != ';') {
while (*ptr && *ptr != ']') { ptr++; k++; }
if (*ptr == ']') { ptr++; k++; }
while (*ptr && iswhite(*ptr)) ptr++;
if(*ptr != '[') break;
}
return(count + k);
}
char * white_out(char *token)
{
char *temp_from = token, *temp_to = token;
int i = 0;
do
{
if (!iswhite(*temp_from) )
*temp_to++
= *temp_from;
}
while(*temp_from++);
*temp_to = '\0';
return(token);
}
int is_variable(char *token)
{
int i;
while(*token == '*') token++;
while(iswhite(*token)) token++;
if (key_word(token) || _modifier (token, 0) || check_types(token, &i) )
return(0);
return(1);
}
int check_pointers(char *p, int *ptr_count)
{
int str_pos = 0;
while(iswhite(*p))
{
p++;
str_pos++;
}
while (*p == '*') {
p++;
(*ptr_count)++;
str_pos++;
}
while(*p && iswhite(*p)) { p++; str_pos++; }
return(str_pos);
}
/* test variables string to locate sequences of modifiers, both */
/* user-defined and C-language based */
char *get_modifiers(int final_check, char *ptr, int mods[_MAX_MODS])
{
int ptr_count, str_pos = 0, mod_count = 0 ;
char *pre_ptr_check, *ptr_to_null = ptr, *end_token;
int user_type_found, stack_pos, type_id_number;
if (!__mods[0]) __mods[0] = 1;
while (*ptr_to_null)
{
ptr_to_null++;
}
do
{
pre_ptr_check = ptr;
ptr_count = 0;
user_type_found = 0;
ptr += check_pointers(ptr, &ptr_count);
/* create null terminated token to test in check_types() */
ptr = isolate_token(ptr, &end_token);
/* restore token to original string if not a user defined modifier*/
if ( !(str_pos = check_types(ptr, &type_id_number)) ) {
if (end_token != ptr_to_null)
*end_token = ' ';
ptr = pre_ptr_check;
}
else {
/* if user defined type modifier found */
user_type_found = 1;
if((__typ_mod[type_id_number] & 0xf) != _TYPE_) {
stack_pos = push_usertype(__type_def[type_id_number]);
if (__mods[0] < _MAX_MODS) {
ptr_count <<= 8;
__mods[__mods[0]++] = (stack_pos | ptr_count) | 0x2000;
}
}
else {
if (!final_check) mods[0] = TYPEDEF;
/* restore token to original string if a type & not a modifier*/
if (end_token != ptr_to_null)
*end_token = ' ';
ptr = pre_ptr_check;
}
ptr += str_pos;
}
/* check for C modifier */
mod_count = __mods[0];
str_pos = _modifier(ptr, 0);
if ((mod_count == __mods[0]) && str_pos) str_pos = 0;
if (str_pos) ptr += str_pos;
}
while (str_pos || user_type_found);
if (final_check != FINAL_MODS_CHECK) {
if (__mods[0] == 1) __mods[0] = 0;
return(ptr);
}
for (mod_count = 0; mod_count < __mods[0]; mod_count++) {
mods[mod_count] = __mods[mod_count];
}
__mods[0] = 0;
return(ptr);
}
/*struct user_typeStack start_user_stack;*/
int push_usertype(char * user_type)
{
int count = 0;
struct user_typeStack *ts, *top, *previous;
if (!start_user_stack) {
ts = (struct user_typeStack *)
calloc(1, sizeof(struct user_typeStack));
if (!ts) exit_ca(NO_USER_TYP_STK, "");
ts->type = (char *) calloc(1, strlen(user_type) + 1);
if (!ts->type) exit_ca(NO_USER_TYP_STK, "");
strcpy (ts->type, user_type);
ts->next = NULL;
start_user_stack = ts;
return (count);
}
top = start_user_stack;
while(top)
{
if (!strcmp(top->type, user_type)) return (count);
previous = top;
top = top->next;
count++;
}
ts = (struct user_typeStack *) calloc(1, strlen(user_type) + 1);
previous->next = ts;
ts->next = NULL;
ts->type = (char *) calloc(1, strlen(user_type) + 1);
if (!ts->type) exit_ca(BAD_USER_TYP_STK, "");
strcpy (ts->type, user_type);
return (count);
}
char *pop_usertype(int type_number)
{
struct user_typeStack *top = start_user_stack;
int count = 0;
while (top)
{
if (type_number == count) return (top->type);
top = top->next;
count++;
}
return (NULL);
}
/* checks string immediately after type specifier */
/* makes assumption that open parenthesis following type specifier */
/*and its modifiers will be a complex declaration */
extern int __Complex_Declarators;
extern int __Complex_Prototypes;
int complex_value(char *p);
int is_identifier(char **p);
int is_complex_decl(char *p)
{
char *closed_paren = NULL;
int str_pos = 0;
if(!__Complex_Declarators) return (NO_COMPLEX);
while(iswhite(*p) || *p == '*' || *p == '}' ) p++;
if (*p != '(') {
str_pos =_modifier (p, 0);
if (str_pos) {
p += str_pos;
while(iswhite(*p) || *p == '*') p++;
}
}
if (*p != '(') return(NO_COMPLEX);
return(complex_value(p));
}
static char character[128];
#define c_ident 1
void ini_characterset(void)
{
char *p = character;
memset (p, 127, 128);
p += 48;
memset (p, c_ident, 10 );
p += 17;
memset (p, c_ident, 26 );
p += 32;
memset (p, c_ident, 26 );
character['_'] = c_ident;
character['*'] = '*';
character['['] = '[';
character[']'] = ']';
character['('] = '(';
character[')'] = ')';
character['('] = '(';
character[' '] = ' ';
character['\t'] = '\t';
character[';'] = ';';
character['\0'] = '\0';
}
int complex_value(char *p)
{
int ptrs = 0, paren = 0, identifier = 0, array = 0;
int pointer_decl = 0, inner_paren = 0, ptr_mods = 0;
int function_decl = 0, nesting_levels = 0, array_levels = 0;
int hold_levels = 0;
char *holdp = p;
do
{
switch (character[*p])
{
case '*':
ptrs++;
ptr_mods++;
break;
case '(':
if(function_decl && !pointer_decl)
return (NO_COMPLEX);
if (paren) inner_paren++;
paren++;
if (paren > inner_paren && identifier)
function_decl = 1;
ptrs = 0;
nesting_levels++;
break;
case '[':
if ( ( nesting_levels> hold_levels ) ||
( nesting_levels && !inner_paren) )
array_levels++;
array++;
hold_levels = nesting_levels;
if (array_levels) break;
if(function_decl && !pointer_decl) return (NO_COMPLEX);
break;
case c_ident:
if ((pointer_decl || identifier) ) break;
identifier = is_identifier(&p);
break;
case ']':
case ' ': case '\t':
break;
case '\0': case ';':
/* "A 'complex' declarator is an identifier qualified by more */
/* than one array, pointer or function modifier." */
/* --Microsoft Language Reference */
if(function_decl && pointer_decl) return (COMPLEX_FN);
if (ptr_mods < 2 && array == 0) return (NO_COMPLEX);
if (pointer_decl) return (COMPLEX_VAR);
/* accept array declarations treated as complex */
if (array_levels) return (COMPLEX_VAR);
return (NO_COMPLEX);
case ')':
paren--;
if (inner_paren) inner_paren--;
/* let fall through */
default:
if (!inner_paren && !pointer_decl) {
if (ptrs && identifier) pointer_decl = 1;
}
break;
}
}
while (*(++p));
return (NO_COMPLEX);
}
int is_identifier(char **p)
{
int count = 0, __type = 0;
char token[32];
char *token_ptr = token;
while ( **p && count <32) {
if (iswhite(**p) || **p == ')' || **p == '[' || **p == '(') break;
*token_ptr++ = **p;
(*p)++;
count++;
}
(*p)--; /* back-up so that current char is not lost when while loop */
/* increments pointer p in complex_value() */
*token_ptr = '\0';
token_ptr = token;
if (is_variable(token) ) {
data_type_ (token, &__type);
if (__type == NO_TYPE) return (1);
}
return(0);
}