home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_300
/
364_01
/
ifdef_ca.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-26
|
13KB
|
466 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: IFDEF_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,
UTLG_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
*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
/* temporary storage of information on if/def defines for testing */
/* & analysis of truth values in ifdef_true() */
typedef struct if_def {
char *def1; /* definition name */
char *def2;
unsigned int boolean1; /* truth value of keyword [ifdef=1, ifndef=0 */
unsigned int boolean2;
int op; /* relational operator in if/def expresion: */
/* either && or || */
} IF_DEF;
/* stack of if/def defines & all undefs */
typedef struct if_def_stackType {
char *def_name;
unsigned int def_status; /* 0 = #undefined, 1 = #defined */
struct if_def_stackType *next;
} IF_DEF_STACK;
IF_DEF_STACK *start_ifdef_stack = NULL;
#define EXIT_CODES
#define IFDEFS_DEFINED
#include "ca.h"
#include "ca_decl.h"
#define EXCLUDE_IFDEF 1
#define INCLUDE_IFDEF 0
#define EXCLUDE_BLOCK -1
extern int verbose;
#define increment_levels() if_level++; elif_level = else_level = if_level
#define _AND 1
#define _OR 2
#define IFLEVEL_MAX 3
#define DEFINE_TYPES 9
enum DefineTYPES { _DEFINED, _DEF, _IF,_ELSEIF, _ELSE,
_IFDEF, _IFNDEF, _UNDEF, _ENDIF };
int if_code[DEFINE_TYPES] = { _DEFINED, _DEF, _IF, _ELSEIF,
_ELSE, _IFDEF, _IFNDEF,
_UNDEF, _ENDIF };
char *elseif[DEFINE_TYPES] = { "defined", "#define", "#if", "#elif",
"#else", "#ifdef", "#ifndef",
"#undef", "#endif"};
int is_else_if(char *p, int in_define)
{
int def_type, found = 0, restore_str = 1;
char *new_line = p;
/* This function begins by testing the token created in is_includeF() */
/* to see whether it is one of the #if/#def commands; we will */
/* restore the original string, if a newline character is not found, by */
/* replacing the '\0' inserted in the tokenizing function with a space. */
/* If a newline is not found the string hasn't been altered. */
/* First find the null or newline */
while (*new_line != '\0' && *new_line != '\n') new_line++;
if (*new_line == '\n') {
*new_line = '\0';
restore_str = 0;
}
for (def_type = _DEF; def_type <= _ENDIF; def_type++) {
if (found = test_token(p, elseif[def_type])) break;
}
if (found) {
if (restore_str)
*new_line = ' ';
if (if_code[def_type])
return(def_value(p, if_code[def_type]));
else
p = new_line++;
}
return(in_define);
}
static int def_value(char *p, int if_type)
{
static int if_level = 0;
static int elif_level = 0;
static int else_level = 0;
static int if_status[IFLEVEL_MAX] = { 0, 0, 0 };
IF_DEF ifdefs;
switch (if_type)
{
case _IF: case _IFDEF: case _IFNDEF:
if (if_level == IFLEVEL_MAX) break;
if (if_status[if_level])
if(if_status[if_level - 1] == EXCLUDE_IFDEF)
return(if_status[if_level] = EXCLUDE_BLOCK);
/* If_type converted in get_definition() to IFDEF or IFNDEF */
ifdefs = get_definition(p, if_type);
if (ifdefs.def1)
if(ifdef_true(ifdefs)) {
increment_levels();
return (if_status[if_level - 1] = INCLUDE_IFDEF);
}
increment_levels();
return (if_status[if_level - 1] = EXCLUDE_IFDEF);
case _ELSEIF:
if (elif_level != if_level) break;
elif_level--; else_level--;
if (if_status[elif_level])
if(if_status[elif_level - 1] == EXCLUDE_BLOCK)
return (EXCLUDE_BLOCK);
if (if_status[elif_level] == INCLUDE_IFDEF)
return (EXCLUDE_IFDEF);
/* If_type converted in get_definition() to IFDEF or IFNDEF */
ifdefs = get_definition(p, if_type);
if (ifdefs.def1)
if(ifdef_true(ifdefs))
return (if_status[elif_level] = INCLUDE_IFDEF);
return (if_status[elif_level] = EXCLUDE_IFDEF);
case _ELSE:
if (else_level != if_level) break;
elif_level--; else_level--;
if(if_status[else_level])
if(if_status[else_level - 1] == EXCLUDE_BLOCK)
return (EXCLUDE_BLOCK);
if (if_status[else_level] == INCLUDE_IFDEF)
return (EXCLUDE_IFDEF);
return (if_status[else_level] = INCLUDE_IFDEF);
case _ENDIF:
if_level--;
elif_level = else_level = if_level;
if_status[if_level] = INCLUDE_IFDEF;
break;
case _DEF:
ifdefs = get_definition(p, if_type);
if (ifdefs.def1) push_ifdef(ifdefs.def1, 1);
break;
case _UNDEF:
ifdefs = get_definition(p, if_type);
if (ifdefs.def1)
push_ifdef(ifdefs.def1, 0);
break;
}
return(if_status[if_level]);
}
/* 0 1 2 3
int if_code[DEFINE_TYPES] = { _DEFINED, _DEF, _IF, _ELSEIF,
4 5 6
_ELSE, _IFDEF, _IFNDEF,
7 8
_UNDEF, _ENDIF };
*/
/* two preprocessor statements on one line not accepted: #else #if defined()*/
static IF_DEF get_definition(char *p, int if_type)
{
size_t strL = 0;
char *ptr = elseif[if_type];
char *end_token, *boolean = NULL;
int boolean_found = 0, AND = 1, OR = 1;
IF_DEF ifdefs = { "", "", 0, 0, 0 };
char temp[100], *temp_p = temp;
strcpy(temp, p);
while (*ptr) { ptr++; strL++; }
p += strL;
while (iswhite(*p)) p++;
ifdefs.def1 = NULL;
ifdefs.def2 = NULL;
/* reject a second preprocessor statement on same line */
if (*p == '#') return (ifdefs);
if (if_type == _IF || if_type == _ELSEIF) {
if ( *p == '!') {
p++; ifdefs.boolean1 = 0;
}
else {
if_type = _IFNDEF;
ifdefs.boolean1 = 1;
}
}
else if (if_type == _IFDEF) ifdefs.boolean1 = 1;
else if (if_type == _IFNDEF) ifdefs.boolean1 = 0;
while (iswhite(*p)) p++;
ptr = NULL;
p = isolate_token(p, &end_token);
if (if_type == _DEF || if_type == _UNDEF) {
if (*(end_token - 1) != '\n') {
end_token++;
while (iswhite (*end_token)) end_token++;
if (*end_token != '\n') return(ifdefs);
}
*(end_token - 1) = '\0';
ifdefs.def1 = p;
return(ifdefs);
}
if(*(end_token - 1) == '\n')
*(--end_token) = '\0';
if (test_token(p, elseif[_DEFINED])) {
*end_token = ' '; /* replace null with space */
do {
boolean = NULL;
while (iswhite(*p)) p++;
if(boolean_found)
if (*p == '(') p++;
if(boolean_found) end_token = p;
ptr = strchr(p, ')');
if(!boolean_found) {
while (iswhite(*end_token)) end_token++;
if (*end_token == '(') end_token++;
}
p = isolate_token(end_token, &end_token);
/* normally ptr is byte preceding end_token and = ')' */
if (ptr) *ptr = '\0';
if(boolean_found) ifdefs.def2 = p;
else ifdefs.def1 = p;
if (!boolean_found)
if (*(end_token - 1) != '\n') {
/*
if there are extra spaces before the closed quot */
/* as in: (TYPE_DEFINED ) get past them: this */
/* means keeping in mind that there are two null bytes, */
/* *ptr and *end_token, which precede the spaces: */
/* unless this is done isolate_token() will return empty */
/* since it stops creating a token when it reaches a */
/* space
*/
while ((!*end_token || iswhite(*end_token) )
&& ptr >= end_token ) end_token++;
boolean = isolate_token(end_token + 1, &end_token);
if ( AND = strcmp(boolean, "&&"))
OR = strcmp(boolean, "||");
if (AND == 0 || OR == 0) {
if (!AND) ifdefs.op = _AND; else ifdefs.op = _OR;
boolean_found = 1;
p = end_token + 1;
while (iswhite(*p)) p++;
if ( *p == '!') { p++; ifdefs.boolean2 = 0; }
else ifdefs.boolean2 = 1;
while (iswhite(*p)) p++;
p += 7; /*(strlen of "defined") */
}
}
} while (boolean);
}
/* reject non-standard "NOT" */
else
if (if_type == _IF && if_type == _IFNDEF)
return(ifdefs);
else
ifdefs.def1 = p;
return(ifdefs);
}
static int ifdef_true(IF_DEF ifdefs)
{
unsigned int status1, status2;
status1 = pop_ifdef_status(ifdefs.def1);
ifdefs.boolean1 = (ifdefs.boolean1 == status1);
if (ifdefs.def2) {
status2 = pop_ifdef_status(ifdefs.def2);
ifdefs.boolean2 = (ifdefs.boolean2 == status2);
}
else {
return (ifdefs.boolean1 );
}
if (ifdefs.op == _AND)
return ( (ifdefs.boolean1 & ifdefs.boolean2) );
if (ifdefs.op == _OR)
return (ifdefs.boolean1 | ifdefs.boolean2);
return(0);
}
extern FILE *scrn_out;
static void push_ifdef(char *p, unsigned int status)
{
IF_DEF_STACK *ts, *top, *previous;
if (!start_ifdef_stack) {
ts = (IF_DEF_STACK *) calloc(1, sizeof(IF_DEF_STACK));
if (!ts) exit_ca(NO_IFDEF_STK,"");
ts->def_name = (char *) calloc(1, strlen(p) + 1);
if (!ts->def_name) exit_ca(NO_IFDEF_STK,"");
strcpy (ts->def_name, p);
ts->def_status = status;
ts->next = NULL;
start_ifdef_stack = ts;
return;
}
top = start_ifdef_stack;
while(top)
{
if (!strcmp(top->def_name, p)) {
top->def_status = status;
return;
}
previous = top;
top = top->next;
}
ts = (IF_DEF_STACK *) calloc(1, sizeof(IF_DEF_STACK));
previous->next = ts;
ts->next = NULL;
ts->def_name = (char *) calloc(1, strlen(p) + 1);
if (!ts->def_name) exit_ca(BAD_IFDEF_STK,"");
strcpy (ts->def_name, p);
ts->def_status = status;
}
static int pop_ifdef_status(char *p)
{
IF_DEF_STACK *top = start_ifdef_stack;
if(verbose) fprintf(scrn_out, "\nSEARCHING FOR: %s\n", p);
while (top)
{
if (!strcmp(p, top->def_name)) {
if(verbose)
fprintf(scrn_out, "FOUND & POPPED: %s, %d\n", top->def_name,
top->def_status);
return (top->def_status);
}
top = top->next;
}
if(verbose)
fprintf(scrn_out, "Could not Find IF/DEF name: %s\n", p);
if(verbose) fprintf(scrn_out, "\n");
return (0);
}
void ini_if_def_stack(void)
{
start_ifdef_stack = NULL;
}
void free_if_def_stack(void)
{
IF_DEF_STACK *current = start_ifdef_stack, *next;
fprintf(scrn_out, "\n\n#UNDEFS & BOOLEAN DEFINES WITH TRUTH VALUES\n");
while (current)
{
fprintf(scrn_out, "%s, %d\n", current->def_name, current->def_status);
next = current->next;
free(current);
current = next;
}
fprintf(scrn_out, "\n");
}
int skipifdefn(char *p, int skipdef_status)
{
char buffer[160], *token_ptr= NULL, *end_token = NULL;
extern IfDefOFF;
while (iswhite (*p)) p++;
if (*p != '#') return (skipdef_status);
strncpy(buffer, p, 159);
buffer[158] = '\0';
token_ptr = isolate_token(buffer, &end_token);
if(!token_ptr) return(skipdef_status);
if (!IfDefOFF) skipdef_status = is_else_if(buffer, skipdef_status);
return(skipdef_status);
}