Sie sind auf Seite 1von 45

_AN AID TO DOCUMENTING C REVISITED_

by Ron Winter

[LISTING ONE]

/*********************************************************************
cpheader.h
*********************************************************************/

#include <malloc.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define Max_unget_buffer 20000


#define Max_general_buffers 3000
#define MAX_functions 5000
/* #define Max_functions 4000 */
#define Max_defined_functions 1400
#define Max_files 1400
#define Max_Recursion 50

#define false 0
#define true 1
#define completed 2

#define Escape 0x1b


#define Control_z 0x1a

/*********************************************************************/
typedef struct the_Pages
{
int on_this_page;
struct the_Pages *next_page_ptr;
}linked_pages_list;
/**********************************************************************/
typedef struct
{
char *functions_name;
char *its_filename;
int is_referenced;
int static_function;
}function_type;
/**********************************************************************/
typedef struct
{
char *source_filename;
char *source_file_comment;
unsigned int line_count;
long size;
}file_record_type;
/**********************************************************************/
typedef struct /* this is the main data base record */
{
file_record_type *file_record_ptr;
char *defined_function;
function_type *ptr_to_function_table;
int number_of_function_calls;
linked_pages_list *ptr_to_page_list;
int number_of_references;
int static_definition;
int overlay_number;
}data_base_record_type;
/**********************************************************************/

#if MAIN != 0
/***********************************************************************/

function_type /* 6 */
**sorted_called_list_ptrs,
*function_list,
*function_list_ptr;
int
Max_functions,
count_of_functions = 0;
/********************************/
file_record_type /* 14 */
*file_record_array,
*file_record_array_ptr;
int
count_of_source_files = 0;
/********************************/
data_base_record_type /* 20 */
*data_base_array,
*data_base_array_ptr,
**array_of_unused_ptrs_to_records,
**array_of_ptrs_to_records;
int
count_of_valid_records = 0;
/********************************/

char *recursion_array[ Max_Recursion ];


int recursion_depth = 0;

char nesting_display_buffer[ Max_general_buffers ];

char target[ 40 ] = "main";


FILE *output = NULL;

char push_buffer[ Max_unget_buffer ] = { 0, 0, 0, 0 };


char *push_buffer_ptr;

char file_comment_buffer[ Max_general_buffers ];


int first_comment;

int effective_width;

int
page = 1,
line = 0,
defined_page_width = 80,
defined_page_length = 60,
defined_left_margin = 1,
defined_right_margin = 1,
stats_only = false,
g_lib_flag = false,
g_comment_flag = false,
g_dec_def_flag = false,
g_help_flag = false,
ibm_flag = true,
g_quiet_flag = false,
g_tech_flag = false,
g_ov_flag = false,
g_un_flag = false,
target_flag = false;
int top_of_form_done;
char title[] =
/* mm/dd/yy0 hh:mm:ss0 */
{ " C PRINTER - (c) 1987, 1988 rev. 1.3" };

/********************************************************************/

#else
/*********************************************************************/

extern function_type
**sorted_called_list_ptrs,
*function_list,
*function_list_ptr;
extern file_record_type
*file_record_array,
*file_record_array_ptr;
extern data_base_record_type
*data_base_array,
*data_base_array_ptr,
**array_of_unused_ptrs_to_records,
**array_of_ptrs_to_records;
extern char *recursion_array[ ];
extern int
count_of_valid_records,
Max_functions,
count_of_functions,
count_of_source_files;
extern int page, line, recursion_depth;
extern int first_comment;
extern char nesting_display_buffer[ ];
extern char top_bottom_line_of_box[ ];
extern FILE *output;
extern char push_buffer[ ];
extern char *push_buffer_ptr;
extern char file_comment_buffer[ ];
extern int defined_page_width;
extern int defined_page_length;
extern int defined_left_margin;
extern int defined_right_margin;
extern int effective_width;
extern char target[ ];
extern int
stats_only,
g_lib_flag,
g_comment_flag,
g_dec_def_flag,
g_help_flag,
ibm_flag,
g_quiet_flag,
g_tech_flag,
g_ov_flag,
g_un_flag,
target_flag;
extern int top_of_form_done;
extern char title[];
/*********************************************************************/

#endif
/**********************************************************************/

[LISTING TWO]

/*********************************************************************
cp.c

static void near bump_line_count( void );


static void near do_top_of_page( void );
static void near deallocate_arrays( void );
static void near allocate_arrays( void );
static void near initialize_globals( void );
static void near build_records_from_list( FILE * );
static void near sort_the_data_base_array( void );
static void near count_all_defined_references( void );
static void near show_function_relationships( void );
static void near show_line_and_byte_counts( void );
static void near show_sorted_function_list( void );
static void near show_page_references( void );
static void near show_unused_if_any( );
static void near show_library_functions( void );
static void near show_files_leading_comments( );
int main( int, char ** );

***************************************************************************/

#define MAIN 1
#include "cpheader.h"
#include "time.h"

extern int near binary_search_sorted_data_base( char * );


extern void near build_box_parts( int );
extern int near build_the_data_base( char *, char * );
extern void near check_for_new_page( void );
extern int near doprint( int );
extern void near nasty( int );
extern void near process_arguments( int, int, char **, int );
extern void near scan_for_static_or_global( int *, int, char *, char * );
extern void near tab_to_left_margin( FILE * );

static void near allocate_arrays( void );


static void near build_records_from_list( FILE * );
static void near bump_line_count( void );
static void near count_all_defined_references( void );
static void near deallocate_arrays( void );
static void near do_top_of_page( void );
static void near initialize_globals( void );
static void near show_files_leading_comments( void );
static void near show_function_relationships( void );
static void near show_library_functions( void );
static void near show_line_and_byte_counts( void );
static void near show_page_references( void );
static void near show_sorted_function_list( void );
static void near show_unused_if_any( void );
static void near sort_the_data_base_array( void );
int main( int, char ** );

/***************************************************************************/

static void near bump_line_count( )


{
top_of_form_done = false;
++line;
check_for_new_page();
tab_to_left_margin( output );
}
/***************************************************************************/
static void near do_top_of_page( )
{
if( !top_of_form_done )
{
top_of_form_done = true;
line = 9999;
check_for_new_page();
tab_to_left_margin( output );
}
}
/***************************************************************************/
static void near deallocate_arrays( )
{
if( function_list )
free( function_list );
if( file_record_array )
free( file_record_array );
if( data_base_array )
free( data_base_array );
if( sorted_called_list_ptrs )
free( sorted_called_list_ptrs );
if( array_of_ptrs_to_records )
free( array_of_ptrs_to_records );
}
/***************************************************************************/

static void near allocate_arrays( )


{
unsigned long length;

length = (unsigned long)Max_functions * sizeof( function_type );


if( length > 65535 )
{
(void)printf( "too many called functions ( go to huge model code )\n" );
exit( 1 );
}
else
if(
!( function_list =
(function_type *)malloc( (unsigned int)length )
)
)
{
(void)printf( "No room for function_list\n" );
exit( 1 );
}
else
{
if( !g_quiet_flag && g_tech_flag )
(void)printf( "function list = %lu bytes long\n", length );
}

length = (unsigned long)Max_files * sizeof( file_record_type );


if( length > 65535 )
{
(void)printf( "too many files ( go to huge model code )\n" );
exit( 1 );
}
else
if(
!( file_record_array =
(file_record_type *)malloc( (unsigned int)length )
)
)
{
(void)printf( "No room for file_record_array\n" );
exit( 1 );
}
else
{
if( !g_quiet_flag && g_tech_flag )
(void)printf( "file record array = %lu bytes long\n", length );
}

length =
(unsigned long)Max_defined_functions * sizeof( data_base_record_type );
if( length > 65535 )
{
(void)printf( "too many defined functions ( go to huge model code )\n" );
exit( 1 );
}
else
if(
!( data_base_array =
(data_base_record_type *)malloc( (unsigned int)length )
)
)
{
(void)printf( "No room for data_base_array\n" );
exit( 1 );
}
else
{
if( !g_quiet_flag && g_tech_flag )
(void)printf( "data base array = %lu bytes long\n", length );
}
length =
(unsigned long)Max_defined_functions * sizeof( data_base_record_type * );
if( length > 65535 )
{
(void)printf(
"too many defined functions pointers( go to huge model code )\n"
);
exit( 1 );
}
else
if(
!( array_of_ptrs_to_records =
(data_base_record_type **)malloc( (unsigned int)length )
)
)
{
(void)printf( "No room for *array_of_ptrs_to_records\n" );
exit( 1 );
}
else
{
if( !g_quiet_flag && g_tech_flag )
(void)printf( "array of ptrs to data base = %lu bytes long\n",
length );
}

length = (unsigned long)Max_functions * sizeof( function_type * );


if( length > 65535 )
{
(void)printf(
"too many called function ptrs ( go to huge model code )\n"
);
exit( 1 );
}
else
if(
!( sorted_called_list_ptrs =
(function_type **)malloc( (unsigned int)length )
)
)
{
(void)printf( "No room for ptr function_list\n" );
exit( 1 );
}
else
{
if( !g_quiet_flag && g_tech_flag )
(void)printf( "sorted called list ptrs = %lu bytes long\n", length );
}
}
/***************************************************************************/

static void near initialize_globals( )


{
int i;
char *cp;
function_list_ptr = function_list;
data_base_array_ptr = data_base_array;
file_record_array_ptr = file_record_array;

for( i = 0; i < Max_Recursion; ++i )


recursion_array[ i ] = NULL;
build_box_parts( ibm_flag );
effective_width = /******** set global output width ***********/
defined_page_width - defined_left_margin - defined_right_margin;
if( effective_width < 40 )
{
(void)printf( "\nThe page width is too narrow( needs > 40 )." );
exit( 1 );
}

cp = &title[ 0 ]; /* insert date and nice time into title */


(void)_strdate( cp );
title[ 8 ] = ' ';
cp = &title[ 10 ];
(void)_strtime( cp );

title[ 15 ] = ' '; /* knock off seconds */


title[ 16 ] = ' '; /* put am, pm here */
title[ 17 ] = 'm';
title[ 18 ] = ' ';

i = atoi( &title[ 10 ] ); /* f/ military to civilian time */


title[ 16 ] = ( i < 12 )? (char)'a': (char)'p';

if( i == 0 )
i = 12;
if( i >= 13 )
i -= 12;

(void)sprintf( &title[ 10 ], "%2d", i );


title[ 12 ] = ':';

if( title[ 10 ] == '0' )


title[ 10 ] = ' ';
}
/***********************************************************************/
static void near build_records_from_list( stream )
FILE *stream;
{
char input_list_filename[ 129 ], input_line[ 129 ], overlay_number[ 129 ];
int l;

while( !feof( stream ) )


{
input_list_filename[ 0 ] = '\0';
input_line[ 0 ] = '\0';
overlay_number[ 0 ] = '\0';
fgets( input_line, 128, stream ); /* ends at \n or eof */

if(
( l = strlen( input_line ) ) > 1 /* ie not nul string */
)
{
if( input_line[ l - 1 ] == '\n' )
input_line[ l - 1 ] = '\0';

l = sscanf( input_line, " %s %s ",


input_list_filename, overlay_number
);
if( !g_quiet_flag && g_tech_flag )
{
(void)printf( "pathname = %s ", input_list_filename );
if( l )
(void)printf( "overlay # = %s ", overlay_number );
}
(void)build_the_data_base( input_list_filename, overlay_number );
}
}
}
/***************************************************************************/

static void near sort_the_data_base_array( )


{
int i, still_sorting_flag;

for( i = 0, data_base_array_ptr = data_base_array;


i < count_of_valid_records;
++i
)
array_of_ptrs_to_records[ i ] = data_base_array_ptr++;

if( !g_quiet_flag )
{
(void)printf( "\n\nSorting the function list...\n" );
(void)printf( " of %d functions\n", count_of_valid_records );
}
still_sorting_flag = true;
while( still_sorting_flag )
{
still_sorting_flag = false;
if( !g_quiet_flag )
{
(void)printf( "." );
}
for( i = 0; i < count_of_valid_records - 1; ++i )
{
if( strcmp( array_of_ptrs_to_records[ i ]->defined_function,
array_of_ptrs_to_records[ i + 1 ]->defined_function ) > 0 )
{
still_sorting_flag = true;
data_base_array_ptr = array_of_ptrs_to_records[ i ];
array_of_ptrs_to_records[ i ] = array_of_ptrs_to_records[ i + 1 ];
array_of_ptrs_to_records[ i + 1 ] = data_base_array_ptr;
}
}
}
}
/************************************************************************/

static void near count_all_defined_references()


{
register int count;
int found;
register function_type *f_list_ptr;

f_list_ptr = function_list; /* the full list */

for( count = 0; count < count_of_functions; ++count )


{
found = binary_search_sorted_data_base( f_list_ptr->functions_name );
if( found >= 0 )
scan_for_static_or_global( &found,
f_list_ptr->static_function,
f_list_ptr->functions_name,
f_list_ptr->its_filename
);
if( found >= 0 )
array_of_ptrs_to_records[ found ]->number_of_references +=
f_list_ptr->is_referenced;
++f_list_ptr; /* for all defined functions */
}
if( !g_quiet_flag && g_dec_def_flag )
(void)printf( "\n" );
}
/***************************************************************************/

static void near show_function_relationships( )


{
int found;
int record_index;

found = binary_search_sorted_data_base( target );/* w/o knowing filename */


/* note if static, will find random one if more than */
/* one with same name */
if( found >= 0 )
{
recursion_depth = 0;
if( !g_quiet_flag )
{
(void)printf( "Checking for usage...\n" );
}
count_all_defined_references();
nesting_display_buffer[ 0 ] = '\0';
if( !g_quiet_flag )
{
(void)printf( "Starting the printout...\n" );
}
if( !target_flag ) /* main is only called once */
array_of_ptrs_to_records[ found ]->number_of_references = 1;
line = 0;
if( !stats_only )
{
(void)doprint( found ); /* of target function */
for( record_index = 0;
record_index < count_of_valid_records;
++record_index
)
{
(void)fprintf( output, "\n" );
++line;
if( array_of_ptrs_to_records[ record_index ]->number_of_references >
1
)
(void)doprint( record_index );
}
}
}
else /* cant find target */
{
(void)printf( "cant find %s, exitting\n", target );
exit( 1 );
}
}
/***************************************************************************/

static void near show_line_and_byte_counts( )


{
long int total_byte_count;
long int total_line_count;
int i;

file_record_array_ptr = file_record_array;

do_top_of_page();
(void)fprintf( output, "File statistics:\n" );
bump_line_count();
total_byte_count = 0l;
total_line_count = 0l;
for( i = 0; i < count_of_source_files; ++i )
{
(void)fprintf( output,
"%-40s - %8u lines, %12ld bytes\n",
file_record_array_ptr->source_filename,
file_record_array_ptr->line_count,
file_record_array_ptr->size
);
bump_line_count();

total_byte_count += file_record_array_ptr->size;
total_line_count += file_record_array_ptr->line_count;
++file_record_array_ptr;
}
(void)fputc( '\n', output );
bump_line_count();
(void)fprintf( output, "Totals:\n" );
bump_line_count();
/******** "%-40s - %8u lines, %12ld bytes\n", *******/
(void)fprintf( output, "%4d files%-30s - %8ld lines, %12ld bytes\n",
count_of_source_files, " ", total_line_count, total_byte_count
);
bump_line_count();
(void)fputc( '\n', output );
bump_line_count();
(void)fprintf( output,
" %d defined functions found.\n", count_of_valid_records
);
bump_line_count();
(void)fprintf( output, "Averages:\n" );
bump_line_count();
(void)fprintf( output,
"%6d lines/file, %6d functions/file, %6d lines/function\n",
(int)( total_line_count / count_of_source_files ),
(int)( count_of_valid_records / count_of_source_files ),
(int)( total_line_count / count_of_valid_records )
);
}
/***************************************************************************/

static void near show_sorted_function_list( )


{
int i, record_index;
long reference_total = 0;

do_top_of_page();

(void)fprintf( output, "Function index:\n" );


bump_line_count();

if( g_ov_flag )
(void)fprintf( output, "%-39s %-28s %s %s\n",
"function", "in file", "ov#", "refs" );
else
(void)fprintf( output, "%-39s %-28s %s\n",
"function", "in file", "refs" );

bump_line_count();

for( i = 0; i < effective_width; ++i )


(void)fputc( '_', output );
(void)fprintf( output, "\n" );
bump_line_count();

for( record_index = 0;
record_index < count_of_valid_records;
++record_index
)
{
data_base_array_ptr = array_of_ptrs_to_records[ record_index ];
if( data_base_array_ptr->number_of_references > 0 )
{
if( g_ov_flag && data_base_array_ptr->overlay_number )
(void)fprintf( output, "%-7s%-32s %-28s %3d %d\n",
( data_base_array_ptr->static_definition )?
"static": "",
data_base_array_ptr->defined_function,
( data_base_array_ptr->file_record_ptr )->source_filename,
data_base_array_ptr->overlay_number,
data_base_array_ptr->number_of_references
);
else
(void)fprintf( output, "%-7s%-32s %-28s %d\n",
( data_base_array_ptr->static_definition )?
"static": "",
data_base_array_ptr->defined_function,
( data_base_array_ptr->file_record_ptr )->source_filename,
data_base_array_ptr->number_of_references
);
reference_total += (long)data_base_array_ptr->number_of_references;
bump_line_count();
}
}
(void)fprintf( output, "%-7s%-32s %-28s %s\n",
" ", " ", " ", "____"
);
bump_line_count();
(void)fprintf( output, "%-7s%-32s %-28s %ld\n",
" ", " ", "total ", reference_total
);
bump_line_count();
}
/***************************************************************************/

static void near show_page_references( )


{
int pmax; /* max x ref columns */
int i, pcnt;
linked_pages_list *p;

if( !stats_only && ( defined_page_length > 0 ) )


{
pmax = (int)( effective_width - 7 - 32 - 2 ) / 5;
do_top_of_page();
(void)fprintf( output, "Function cross reference:\n" );
bump_line_count();

for( i = 0; i < count_of_valid_records; ++i )


{
data_base_array_ptr = array_of_ptrs_to_records[ i ];
if( data_base_array_ptr->number_of_references > 0 )
{
(void)fprintf( output, "%-7s%-32s- ",
( data_base_array_ptr->static_definition )?
"static": "",
data_base_array_ptr->defined_function );
p = data_base_array_ptr->ptr_to_page_list;
if( p )
{
pcnt = 0;
while( p->next_page_ptr )
{
(void)fprintf( output, "%4d,", p->on_this_page );
p = p->next_page_ptr;
++pcnt;
if( pcnt >= pmax )
{
(void)fputc( '\n', output );
bump_line_count();
(void)fprintf( output, "%7s%32s ", " ", " " );
pcnt = 0;
}
}
(void)fprintf( output, "%4d\n", p->on_this_page );
}
else
(void)fprintf( output, "\n" );
bump_line_count();
}
}
}
}
/***************************************************************************/

static void near show_unused_if_any( )


{
int i, unused_count, unused_index, count, still_sorting_flag;
data_base_record_type **unused_list_ptr_ptr, *unused_list_ptr;

do_top_of_page();
(void)fprintf( output, "Un-used function list:\n" );
bump_line_count();

unused_count = 0;
for( i = 0; i < count_of_valid_records; ++i )
{
data_base_array_ptr = array_of_ptrs_to_records[ i ];
if( !data_base_array_ptr->number_of_references )
{
++unused_count;
if( !g_un_flag )
{
(void)fprintf( output,
"%-7s%-32s- %-33s\n",
( data_base_array_ptr->static_definition )?
"static": "",
data_base_array_ptr->defined_function,
( data_base_array_ptr->file_record_ptr )->source_filename
);
bump_line_count();
}
}
}
if( g_un_flag ) /* show sorted */
{
if( unused_count )
{
if(
!( array_of_unused_ptrs_to_records =
(data_base_record_type **)malloc( (unsigned int)unused_count )
)
)
(void)printf( "No room for *array_of_unused_ptrs_to_records\n" );
else
{
unused_index = 0;
for( i = 0; i < count_of_valid_records; ++i )
{
data_base_array_ptr = array_of_ptrs_to_records[ i ];
if( !data_base_array_ptr->number_of_references )
{ /* first just collect them */
array_of_unused_ptrs_to_records[ unused_index++ ] =
data_base_array_ptr;
}
} /* so now there are unused_index of them */
unused_list_ptr_ptr = array_of_unused_ptrs_to_records;
still_sorting_flag = true;
if( unused_count > 1 )
{
while( still_sorting_flag )
{
still_sorting_flag = false;
if( !g_quiet_flag && g_tech_flag )
(void)printf( ".%d \r", count );
for( count = 0; count < unused_count - 1; ++count )
{
if( strcmp( unused_list_ptr_ptr[ count ]->
file_record_ptr->source_filename,
unused_list_ptr_ptr[ count + 1 ]->
file_record_ptr->source_filename
) > 0
)
{
still_sorting_flag = true;
unused_list_ptr = unused_list_ptr_ptr[ count ];
unused_list_ptr_ptr[ count ] =
unused_list_ptr_ptr[ count + 1 ];
unused_list_ptr_ptr[ count + 1 ] = unused_list_ptr;
}
}
}
}
for( i = 0; i < unused_count; ++i )
{
(void)fprintf( output,
"%-7s%-32s- %-33s\n",
( unused_list_ptr_ptr[ i ]->static_definition )?
"static": "",
unused_list_ptr_ptr[ i ]->defined_function,
( unused_list_ptr_ptr[ i ]->file_record_ptr )->source_filename
);
bump_line_count();
}
}
}
}
if( !unused_count )
{
tab_to_left_margin( output );
(void)fprintf( output, "No un-used functions in the list.\n" );
bump_line_count();
}
else
{
(void)fprintf( output, "%-7s%-39s- %d\n", "", "totals", unused_count );
bump_line_count();
}
}
/************************************************************************/

static void near show_library_functions( )


{
register int count;
int found, total, still_sorting_flag, x_count, final_count, final_call;
function_type **f_list_ptr_ptr, *f_list_ptr;

if( g_lib_flag )
{
if( !g_quiet_flag && g_tech_flag )
(void)printf( "collecting library functions...\n" );
do_top_of_page();
(void)fprintf( output, "Library functions:\n" );
bump_line_count();

total = 0;
f_list_ptr = function_list;
for( count = 0; count < count_of_functions; ++count )
{
if( !f_list_ptr->static_function )
{
if(
( found =
binary_search_sorted_data_base( f_list_ptr->functions_name )
) < 0
)
sorted_called_list_ptrs[ total++ ] = f_list_ptr;
}
++f_list_ptr; /* for all called functions */
}

if( !g_quiet_flag && g_tech_flag )


(void)printf( "gathering identical library functions...\n" );
final_count = total; /* number of calls to be collected and sorted */
f_list_ptr_ptr = sorted_called_list_ptrs;
for( count = 0; count < ( total - 1 ); ++count )
{
for( x_count = count + 1; x_count < total; ++x_count )
{
if( ( f_list_ptr_ptr[ count ]->functions_name[ 0 ] != '\0' ) &&
!strcmp( f_list_ptr_ptr[ count ]->functions_name,
f_list_ptr_ptr[ x_count ]->functions_name )
)
{
f_list_ptr_ptr[ count ]->is_referenced +=
f_list_ptr_ptr[ x_count ]->is_referenced;
f_list_ptr_ptr[ x_count ]->functions_name[ 0 ] = '\0';
--final_count;
}
}
}

if( !g_quiet_flag && g_tech_flag )


{
(void)printf( "\nSorting the library function calls...\n" );
}

f_list_ptr_ptr = sorted_called_list_ptrs;
still_sorting_flag = true;
while( still_sorting_flag )
{
still_sorting_flag = false;
if( !g_quiet_flag && g_tech_flag )
(void)printf( ".%d \r", count );
for( count = 0; count < total - 1; ++count )
{
if( strcmp( f_list_ptr_ptr[ count ]->functions_name,
f_list_ptr_ptr[ count + 1 ]->functions_name ) > 0 )
{
still_sorting_flag = true;
f_list_ptr = f_list_ptr_ptr[ count ];
f_list_ptr_ptr[ count ] = f_list_ptr_ptr[ count + 1 ];
f_list_ptr_ptr[ count + 1 ] = f_list_ptr;
}
}
}
if( !g_quiet_flag && g_tech_flag )
(void)printf( "\n" );

(void)fprintf( output, "%-32s %-28s\n",


"library function", "calls" );
bump_line_count();

for( count = 0; count < effective_width; ++count )


(void)fputc( '_', output );
(void)fprintf( output, "\n" );
bump_line_count();

final_call = 0;
f_list_ptr_ptr = sorted_called_list_ptrs;
for( count = 0; count < total; ++count )
{
if( ( *f_list_ptr_ptr )->functions_name[ 0 ] != '\0' )
{
(void)fprintf( output, "%-32s %d\n",
( *f_list_ptr_ptr )->functions_name,
( *f_list_ptr_ptr )->is_referenced
);
final_call += ( *f_list_ptr_ptr )->is_referenced;
bump_line_count();
}
++f_list_ptr_ptr;
}
(void)fprintf( output, "Totals:\n" );
bump_line_count();
(void)fprintf( output, "%6d %-25s %d calls.\n",
final_count, "library functions,", final_call
);
bump_line_count();
}
}
/************************************************************************/

static void near show_files_leading_comments( )


{
int i;
char *cp;
if( g_comment_flag )
{
do_top_of_page();
(void)fprintf( output, "File comments:\n" );
bump_line_count();
file_record_array_ptr = file_record_array;
for( i = 0; i < count_of_source_files; ++i )
{
(void)fprintf( output, "%40s\n",
file_record_array_ptr->source_filename
);
bump_line_count();
cp = file_record_array_ptr->source_file_comment;
while( *cp )
{
(void)fprintf( output, "%c", *cp );
if( *++cp == '\n' )
{
bump_line_count();
}
}
++file_record_array_ptr;
do_top_of_page(); /* one page per comment at least */
}
}
}
/**********************************************************************/

int main( argc, argv )


char **argv;
int argc;
{
int index, in_error = false, out_error = false;
FILE *stream;

nasty( argc );

(void)printf( "\ncp - ver. 1.3, (C)1987, 1988 Stewart A. Nutter\n" );


(void)printf( " extended and corrected by Ron Winter\n" );

index = 1;
if( !( stream = fopen( argv[ index ], "rt" ) ) )
in_error = true;
else
++index;
if(
( argc > index ) &&
(
( argv[ index ][ 0 ] != '/' ) && ( argv[ index ][ 0 ] != '-' )
)
)
{
output = fopen( argv[ 2 ], "w+" ); /******* wt+ <<<<<<<< ******/
++index;
}
else
output = fopen( "prn", "w+" ); /******** wt+ <<<<<< ********/
if( !output )
out_error = true;

Max_functions = MAX_functions;
process_arguments( index, argc, argv, in_error || out_error );
if( in_error )
{
(void)printf( "\n can't open input list %s\n", argv[ 1 ] );
exit( 1 );
}
if( out_error )
{
(void)printf( "\n can't open output file, error %s\n", strerror( errno ) );
exit( 1 );
}
allocate_arrays( );
initialize_globals( );
(void)printf( "\n" );

build_records_from_list( stream );
sort_the_data_base_array( );
if( !g_quiet_flag )
{
(void)printf( "\n" );
}
top_of_form_done = false;
show_function_relationships( );
show_page_references( );
show_line_and_byte_counts( );
show_sorted_function_list( );
show_unused_if_any( );
show_library_functions( );
show_files_leading_comments( );
deallocate_arrays( );

/************* done *****************/


(void)fprintf( output, "%c", 0x0c ); /* ff */

return false; /* ok */
}
/********************************************************************/

[LISTING THREE]

/***********************************************************************
cpinput.c
void near nasty( int );
void near process_arguments( int, int, char **, int );
************************************************************************/
#define MAIN 0
#include "cpheader.h"

void near nasty( int );


void near process_arguments( int, int, char **, int );
/************************************************************************/

void near nasty( argc )


int argc;
{
if( argc < 2 )
{
(void)printf( "\ncp listfile [ outfile ] [\n" );
(void)printf(
" /p:nn /w:nn /m:nn /r:nn /t:main /f:nnnn\n"
);
(void)printf(
" /l /n /s /q /d /c /h /x\n"
);
(void)printf( " ]\n\n" );
(void)printf(
" outfile = prn\n" );
(void)printf(
" p: page length = %3d [ 0, 50 -255 ]\n", defined_page_length
);
(void)printf(
" w: page width = %3d [ 80 - 255 ]\n", defined_page_width
);
(void)printf(
" m: left margin = %2d [ 0 - 30 ]\n", defined_left_margin
);
(void)printf(
" r: right margin = %2d [ 0 - 30 ]\n", defined_right_margin
);
(void)printf(
" t: target function = %s\n", target
);
(void)printf(
" f: # of function calls = %4d [ 2 - 5461 ]\n", MAX_functions
);
(void)printf(
" n: normal characters( ie not ibm character graphics )\n"
);
(void)printf(
" l output library functions\n"
);
(void)printf(
" c output file\'s 1st comment\n"
);
(void)printf(
" s output statistics only\n"
);
(void)printf(
" d show declarations and definitions\n"
);
(void)printf(
" o show overlay information\n"
);
(void)printf(
" u show unused sorted by filename\n"
);
(void)printf(
" q show no messages\n"
);
(void)printf(
" h show more help\n"
);
(void)printf(
" x show tech info\n"
);

(void)printf( "\n" );
exit( 0 );
}
}
/**********************************************************************/
void near process_arguments( index, argc, argv, an_error )
int index, argc, an_error;
char **argv;
{
char c;
int i, tmp;

for( i = index; i < argc; ++i )


{
if( ( argv[ i ][ 0 ] == '/' ) || ( argv[ i ][ 0 ] == '-' ) )
{
c = (char)tolower( (int)argv[ i ][ 1 ] );
switch( c )
{
case 'n':
ibm_flag = ( ibm_flag )? false: true;
break;
case 'l':
g_lib_flag = ( g_lib_flag )? false: true;
break;
case 'c':
g_comment_flag = ( g_comment_flag )? false: true;
break;
case 'd':
g_dec_def_flag = ( g_dec_def_flag )? false: true;
break;
case 's':
stats_only = ( stats_only )? false: true;
break;
case 'q':
g_quiet_flag = ( g_quiet_flag )? false: true;
break;
case 'o':
g_ov_flag = true;
break;
case 'u':
g_un_flag = true;
break;
case 'h':
g_help_flag = true;
break;
case 'x':
g_tech_flag = true;
break;
default:
if( ( strlen( argv[ i ] ) > 3 ) && ( argv[ i ][ 2 ] == ':' ) )
{
tmp = atoi( &argv[ i ][ 3 ] );
switch( c )
{
case 'p':
if( ( ( 50 < tmp ) && ( tmp < 256 ) ) || ( tmp == 0 ) )
defined_page_length = tmp;
break;
case 'm':
if( ( 0 <= tmp ) && ( tmp <= 30 ) )
defined_left_margin = tmp;
break;
case 'r':
if( ( 0 <= tmp ) && ( tmp <= 30 ) )
defined_right_margin = tmp;
break;
case 't':
(void)strcpy( target, &argv[ i ][ 3 ] );
target_flag = true;
break;
case 'w':
if( ( 79 < tmp ) && ( tmp < 256 ) )
defined_page_width = tmp;
break;
case 'f':
if( ( 1 < tmp ) && ( tmp < 5462 ) )
Max_functions = tmp;
break;
default:
(void)printf(
"\nUnknown argument character: %c, ignored!\n",
argv[ i ][ 1 ]
);
break;
} /* end of switch on character after / or - */
} /* end of if :something */
else
(void)printf( "\nMissing : for argument %s, ignored!\n",
argv[ i ] );
break;
} /* end of switch on character after / or - */
} /* end of if / or - */
else
(void)printf( "\nUnknown argument: %s, ignored!\n", argv[ i ] );
} /* end of for loop on arguments */

if( g_tech_flag )
{
(void)printf( "\n" );
(void)printf( "Notes: 1. Max recursive function displacement of %d.\n",
Max_Recursion
);
(void)printf(
" 2. Max # of unique function calls per defined function\n\
for all defined functions is %d.\n",
Max_functions );
(void)printf( " 3. Max # of defined functions is %d.\n",
Max_defined_functions );
(void)printf( "\n" );
(void)printf( "sizeof()\'s:\n" );
(void)printf(
" function table = %u, contents = %u, data base = %u,\
database = %u, lib = %u\n",
sizeof( function_type ),
sizeof( file_record_type ),
sizeof( data_base_record_type ),
sizeof( array_of_ptrs_to_records ),
sizeof( sorted_called_list_ptrs )
);
(void)printf( "\n" );
(void)printf(
"The program will tend to show certain \'c\' functions as unused.\n" );
(void)printf(
"1. defined functions assigned to declared pointers to function names\n" );
(void)printf(
" and executed as pointers to those function names won't be seen.\n" );
(void)printf(
"2. #if(s) controlling the generation of code especially with\n" );
(void)printf(
" braces( { } ) in the conditional code section will especially\n" );
(void)printf(
" screw up if there is an #else code part. This program will work\n" );
(void)printf(
" on both code parts of the conditional and most probably get out\n" );
(void)printf(
" of sync with the braces. One might do a preprocessor pass compile\n" );
(void)printf(
" and heave it\'s output files as input files at this program.\n" );
(void)printf(
"3. #define(s) that expand to functions and call functions will also\n" );
(void)printf(
" be neglected. The preprocessor may be used as stated above.\n" );
/******
(void)printf(
"\n" );
******/
(void)printf( "\n" );
}

if( g_help_flag )
{
(void)printf( "\n" );
(void)printf(
"The listfile argument is an ascii text file containing the list of\n"
);
(void)printf(
"filenames to process, one filename per line (optional overlay number.)\n"
);
(void)printf(
"The output file may be a device or a filename. If there is no\n"
);
(void)printf(
"output filename, \'prn\' is assumed. Note that one may put \'con\'\n"
);
(void)printf(
"here and view the output of the program before printing or saving\n"
);
(void)printf(
"to a filename.\n"
);
(void)printf(
"Also note that the output filename and the input filenames in the\n"
);
(void)printf(
"listfile may be full pathnames with drives and or paths.\n"
);
(void)printf( "/ arguments accept the alternate - form.\n" );
(void)printf( "For example: cp x y -s, cp /h, cp x -x /d -t:junk\n" );
(void)printf( "arguments may be in upper or lower case.\n" );
(void)printf( "Note that the target function is case sensitive\n" );
(void)printf( "since it is a \'c\' function name.\n" );
(void)printf( "\n" );
}
if( an_error )
{
if( g_help_flag || g_tech_flag )
exit( 0 );
else
(void)printf( "Oops..." );
}
}
/***********************************************************************/

[LISTING FOUR]

/***************************************************************************
cpbuild.c
static void near mark_as_static( function_type *, char*, int );
static int near test_and_add( function_type *, char *, int );
static void near unget_chars( char );
static char near get_chars( FILE * );
static char near get_to_next_possible_token( FILE * );
static int near is_legal_identifier_character( char );
int near build_the_data_base( char * );
***************************************************************************/

#define MAIN 0
#include "cpheader.h"

int near build_the_data_base( char * );


static char near get_chars( FILE * );
static char near get_to_next_possible_token( FILE * );
static int near is_legal_identifier_character( char );
static void near mark_as_static( function_type *, char*, int );
static int near test_and_add( function_type *, char *, int );
static void near unget_chars( char );

/***************************************************************************/
static void near mark_as_static( ptr_to_function_list,
name_of_static_function, count
)
char *name_of_static_function;
function_type *ptr_to_function_list;
int count;
{
int i;

for( i = 0; i < count; ++i )


{
if(
!strcmp( name_of_static_function, ptr_to_function_list->functions_name )
)
ptr_to_function_list->static_function = true;
++ptr_to_function_list;
}
}
/***************************************************************************/
#define KEYS 7

static int near test_and_add( ptr_to_function_list, string, count )


function_type *ptr_to_function_list;
char *string;
int count;
{
int i, is_a_new_function_name;
static char *keywords[ KEYS ] =
{ /* must catch do (void)printf, while(), else (void)... etc. ***/
"do", "while", "if", "else", "for", "switch", "return"
};

for( i = 0; ( i < KEYS ) && ( strcmp( string, keywords[ i ] ) != 0 ); ++i )


;
if( i < KEYS )
is_a_new_function_name = false; /* ie a reserved word match */
else /* is a function name */
{
for( i = 0; i < count; ++i )
{
if( !strcmp( string, ptr_to_function_list->functions_name ) )
{ /* function name matches */
if( !ptr_to_function_list->static_function )
break; /* and isn't static */
else
{
if( !strcmp( ptr_to_function_list->its_filename,
file_record_array_ptr->source_filename
)
)
break; /* only statics in same file match */
}
}
++ptr_to_function_list;
}
if( i == count )
{ /* new function name */
is_a_new_function_name = true; /* add function name to list */
if( ( function_list_ptr->functions_name = strdup( string ) ) == NULL )
{
(void)fprintf( stderr, "Ran out of memory.\n" );
exit( 1 );
}
function_list_ptr->static_function = false;
function_list_ptr->its_filename =
file_record_array_ptr->source_filename;
function_list_ptr->is_referenced = 1;

++function_list_ptr; /* point to next empty cell */


++count_of_functions; /* increase current size */
if( count_of_functions > Max_functions )
{
(void)fprintf( stderr, "Too many functions.\n" );
exit( 1 );
}
}
else /* string already in function list */
{
is_a_new_function_name = false;
ptr_to_function_list->is_referenced++;
}
}
return is_a_new_function_name;
}
/***************************************************************************/
static void near unget_chars( c )
char c;
{
if( ( push_buffer_ptr - push_buffer ) < Max_unget_buffer )
*push_buffer_ptr++ = c;
else
{
(void)fprintf( stderr, "\nProgram syntax error:" );
(void)fprintf( stderr, " Too many pushed characters.\n" );
exit( 1 );
}
}
/***************************************************************************/
static char near get_chars( stream )
FILE * stream;
{
register char c;

if( push_buffer_ptr != push_buffer )


c = *--push_buffer_ptr;
else
{
c = (char)fgetc( stream );
if( c == EOF )
c = Control_z;
if( c == 0x0a )
{
file_record_array_ptr->line_count++;
file_record_array_ptr->size++; /* count the unseen <cr> */
}
file_record_array_ptr->size++;
}
return c;
}
/***************************************************************************/
static char near get_to_next_possible_token( stream )
FILE *stream;
{
register char
c;
char
next_char_peek;
int
done;

static int /* the only apparent reason these are static is for speed */
quotes_flag = false,
comment_flag = false,
escape_sequence_flag = false,
pound_sign_flag = false,
ascii_quote_flag = false;
static int
fp = 0; /*****<<<<< */
static char *cp;

done = false;
do {
c = get_chars( stream );
if( c != Control_z )
{
if( comment_flag )
{
/**************************
process /* comment sequence of characters
***************************/
if( first_comment == true )
{
if( fp < ( Max_general_buffers - 2 ) )
{
if(
( c != '\n' ) &&
( strlen( cp ) < effective_width )
)
{
file_comment_buffer[ fp++ ] = c;
file_comment_buffer[ fp ] = '\0';
}
else /* c == \n or length >= width */
{
file_comment_buffer[ fp++ ] = '\n';
file_comment_buffer[ fp ] = '\0';
cp = (char *)&file_comment_buffer[ fp ];
if( c != '\n' )
{
file_comment_buffer[ fp++ ] = c;
file_comment_buffer[ fp ] = '\0';
}
}
}
/* else /* 1st comment exceeds buffer */
} /* end of if first_comment == true */
if( c == '*' )
{
next_char_peek = get_chars( stream );
if( next_char_peek == '/' ) /* close comment */
{
comment_flag = false;
unget_chars( ' ' ); /* comments are white space in 'c' */
if( first_comment == true )
{
first_comment = completed;
fp = 0;
cp = (char *)&file_comment_buffer[ fp ];
}
}
else /* next_char_peek != '/' ie close comment */
unget_chars( (char)next_char_peek );
} /* end of if c == '*' */
}
else /* not /* */
{
/**************************
process \sequence character, hoping \" \' \\ etc inside " or '
***************************/
if( escape_sequence_flag )
escape_sequence_flag = false;
else /* not /*, not \ */
{
/**************************
process " string sequence of characters
***************************/
if( quotes_flag )
{
if( c == '\\' ) /* check for \'\n' */
{
next_char_peek = get_chars( stream );
if( next_char_peek != '\n' ) /* so not \'\n' */
{
escape_sequence_flag = true;
unget_chars( (char)next_char_peek );
}
/******* else /* \'\n' continuation */
}
else /* not \ */
if( c == '\"' )
quotes_flag = false;
}
else /* not ", not /*, not \ */
{
/**************************
process ' ascii character sequence
***************************/
if( ascii_quote_flag )
{
if( c == '\\' )
escape_sequence_flag = true;
else
if( c == '\'' )
ascii_quote_flag = false;
}
else /* not ', not ", not /*, not \ */
{
/**************************
process # sequence of characters, ie #if, #define, etc.
define causes code sequencing problems it would seem!
***************************/
if( pound_sign_flag )
{
if( c == '/' ) /* comments override #defines etc */
{
next_char_peek = get_chars( stream );
if( next_char_peek == '*' )
comment_flag = true;
else
unget_chars( (char)next_char_peek );
}
else
{
if( c == '\n' )
pound_sign_flag = false;
else /* c != \n */
{
if( c == '\\' ) /* check for \'\n' continuation */
{
next_char_peek = get_chars( stream );
if( next_char_peek != '\n' ) /* it aint \'\n' */
unget_chars( (char)next_char_peek );
/* else /* \'\n' means continue # */
}
}
}
}
else /* not ', not #, not ", not /*, not \ */
{
/**************************
process anything else
***************************/
done = false; /* assume a ' or " or # or /* */
switch( c )
{
case '\"':
quotes_flag = true;
break;
case '\'':
ascii_quote_flag = true;
break;
case '#':
pound_sign_flag = true;
break;
case '/':
next_char_peek = get_chars( stream );
if( next_char_peek == '*' )
{
comment_flag = true;
if( first_comment == false )
{ /* the 1st comment of the file */
first_comment = true;
fp = 0;
cp = (char *)&file_comment_buffer[ fp ];
}
}
else
{
unget_chars( (char)next_char_peek );
done = true;
}
break;
default: /* a worthy character to return */
done = true;
}
} /* end of else not ascii */
} /* end of else not # */
} /* end of else not " */
} /* end of else not /* */
} /* end of else not \ */
} /* end of if c != Control_z */
}
while( !done && ( c != Control_z ) );
if( c == Control_z )
{
ascii_quote_flag = false;
pound_sign_flag = false;
quotes_flag = false;
escape_sequence_flag = false;
comment_flag = false;
fp = 0;
}
return c;
}
/***************************************************************************/
static int near is_legal_identifier_character( c )
char c;
{
if(
( ( 'A' <= c ) && ( c <= 'Z' ) ) ||
( ( 'a' <= c ) && ( c <= 'z' ) ) ||
( ( '0' <= c ) && ( c <= '9' ) ) ||
( c == '_')
)
return true;
else
return false;
}
/***************************************************************************/
#define C_line_length 512
#define C_identifier_length 80

int near build_the_data_base( the_filename )


char * the_filename;
{
static char fake_comment[ ] = "no room!";
int found_a_possible_function;
int brace_count, body_found;
int open_parenthesis, parenthesis_count;
int at_end_of_source_file;
int dummy_index, total_called_count;
int function_definition_flag, static_flag;
int analyze_buffer_flag = false;
char c;
char *function_name_buffer_ptr;
char function_name_buffer[ C_identifier_length ];
char look_ahead_buffer[ C_line_length + 1 ];
FILE *stream;
data_base_record_type *data_base_ptr, *starting_data_base_ptr;
function_type *starting_called_function_ptr;

if( !g_quiet_flag )
{
(void)printf( "Processing file: %-12s\n", the_filename );
}
if( !( stream = fopen( the_filename, "r" ) ) ) /***** rt <<<<<<<<<< */
{
(void)printf( "Cant open %s\n", the_filename );
return -1;
}

push_buffer_ptr = push_buffer; /* reset input character stack */


/* add file name to data base */
if( !( file_record_array_ptr->source_filename = strdup( the_filename ) ) )
{
(void)printf( "Ran out of memory.\n" );
exit( 1 );
}

starting_called_function_ptr = function_list_ptr;
starting_data_base_ptr = data_base_array_ptr; /* mark start of defined list */

look_ahead_buffer[ 0 ] = '\0';

first_comment = false;
file_comment_buffer[ 0 ] = '\0';

file_record_array_ptr->line_count = 0; /* clear it's variables */


file_record_array_ptr->size = 0l;

function_name_buffer_ptr = function_name_buffer;
function_name_buffer[ 0 ] = '\0';

static_flag = false;
found_a_possible_function = false;
open_parenthesis = false;
body_found = false;

brace_count = 0;
parenthesis_count = 0;

at_end_of_source_file = false;
while( !at_end_of_source_file )
{
c = get_to_next_possible_token( stream );
switch( c )
{
case '{':
++brace_count;
break;
case '}':
--brace_count;
break;
case Control_z:
at_end_of_source_file = true;
analyze_buffer_flag = true;
break;
case '(':
if( !open_parenthesis )
++open_parenthesis;
analyze_buffer_flag = true;
break;
case ' ': /* this is where we eat white space */
case '\v':
case '\b':
case '\f':
case '\t':
case '\r':
case '\n':
do {
c = get_to_next_possible_token( stream );
}
while(
( c == '\f' ) || ( c == ' ' ) || ( c == '\v' ) ||
( c == '\b' ) || ( c == '\t' ) || ( c == '\r' ) ||
( c == '\n' )
);
unget_chars( c ); /* put next non white character back */

if( c != '(' )
analyze_buffer_flag = true;
/*** else /* c == '(' and next pass will find it */
break;
default:
if( is_legal_identifier_character( c ) )
{ /* it's a good identifier character */
*function_name_buffer_ptr++ = c;
*function_name_buffer_ptr = '\0';
}
else /* it aint, so toss it */
{
if( static_flag && ( c == ';' ) )
static_flag = false;
/* if( c != '*' ) */
analyze_buffer_flag = true;
}
break;
} /* end of preliminary character parse */
/*****************
start checking characters accumulated in function_name_buffer[]
******************/
if( analyze_buffer_flag )
{
analyze_buffer_flag = false;
if(
function_name_buffer[ 0 ] && /* ie not null string */
( /* & not number */
( function_name_buffer[ 0 ] < '0' ) ||
( function_name_buffer[ 0 ] > '9' )
)
)
found_a_possible_function = true;
else /* it aint an identifier */
{ /* so erase buffer */
function_name_buffer_ptr = function_name_buffer;
function_name_buffer[ 0 ] = '\0';
if( static_flag && ( c == ';' ) )
static_flag = false;
open_parenthesis = false;
}
} /* end of analyze_buffer_flag */
/*****************
if function_name_buffer[] has legal function name, scan ahead
******************/
if( found_a_possible_function )
{
found_a_possible_function = false;
*function_name_buffer_ptr = '\0'; /* append nul char to end */
if( !static_flag ) /* don't retest if true */
if( !strcmp( function_name_buffer, "static" ) )
static_flag = true;
if( open_parenthesis )
{
open_parenthesis = false;
if( !brace_count )
{ /* ie outside any function body */
parenthesis_count = 1;
for( dummy_index = 0;
( dummy_index < C_line_length ) && parenthesis_count;
++dummy_index
)
{ /* scan ahead for function() */
c = get_to_next_possible_token( stream );
if( c == Control_z )
break; /* dummy_index not bumped */
look_ahead_buffer[ dummy_index ] = c;
look_ahead_buffer[ dummy_index + 1 ] = '\0';
switch( c )
{
case '(':
++parenthesis_count;
break;
case ')':
--parenthesis_count;
break;
} /* dummy_index is bumped */
} /* end of for loop scanning for (...) */
if( ( c == Control_z ) || ( !parenthesis_count ) )
--dummy_index;
function_definition_flag = false;
for( ++dummy_index;
( dummy_index < C_line_length ) && !function_definition_flag;
++dummy_index
)
{ /* what happens past (..) */
c = get_to_next_possible_token( stream );
if( c == Control_z )
break; /* w/ function_definition_flag == false */
look_ahead_buffer[ dummy_index ] = c;
look_ahead_buffer[ dummy_index + 1 ] = '\0';
switch( c )
{
case ' ': /* this is where we eat white space */
case '\v':
case '\b':
case '\f':
case '\t':
case '\n':
case '\r':
break;
case '{':
++body_found;
break;
case ';':
case ',':
case '(': /* at (*)() type declaration */
if( !body_found )
{
function_definition_flag = true; /* declaration */
if( !g_quiet_flag )
{
if( g_dec_def_flag )
{
if( static_flag )
(void)printf( " static" );
else
(void)printf( " " );
(void)printf( " declaration " );
(void)printf( "%s(%s\n",
function_name_buffer,
look_ahead_buffer );
}
}
}
break;
default: /* any other non white character means */
function_definition_flag = completed;
if( !g_quiet_flag )
{
if( g_dec_def_flag )
{
if( static_flag )
(void)printf( "static " );
else
(void)printf( " " );
(void)printf( "define " );
}
}
break;
} /* dummy_index is bumped */
} /* end of for loop parsing character after ) */
body_found = false;
if( function_definition_flag == false )
{
(void)printf( "\nSyntax error: " );
(void)printf( "Function description.\n" );
look_ahead_buffer[ dummy_index ] = '\0';
(void)printf( "\n%s\n", look_ahead_buffer );
exit( 1 );
}
while( dummy_index )
{ /* put all characters after ( back */
unget_chars( look_ahead_buffer[ dummy_index - 1 ] );
--dummy_index;
}
if( function_definition_flag == completed )
{
if( !g_quiet_flag )
{
if( g_dec_def_flag )
(void)printf( "%-40s\n", function_name_buffer );
}
/*******************
this element can distinguish static functions
in different files with the same name
*******************/
data_base_array_ptr->file_record_ptr = file_record_array_ptr;
data_base_array_ptr->number_of_function_calls = 0;
data_base_array_ptr->ptr_to_function_table = function_list_ptr;
data_base_array_ptr->static_definition = static_flag;
static_flag = false;

if(
!( data_base_array_ptr->defined_function =
strdup( function_name_buffer )
)
)
{
(void)printf( "\nRan out of memory( for strdup() )." );
exit( 1 );
}
data_base_array_ptr->number_of_references = 0;
data_base_array_ptr->ptr_to_page_list = NULL;

data_base_ptr = data_base_array_ptr; /* save current pointer */


++data_base_array_ptr; /* next entry */
++count_of_valid_records;
if( count_of_valid_records > Max_defined_functions )
{
(void)printf( "\nToo many new functions\n" );
exit( 1 );
}
} /* end of function definition */
static_flag = false;
}
else /* brace_count is not zero */
{ /* so inside a function */
data_base_ptr->number_of_function_calls +=
test_and_add( data_base_ptr->ptr_to_function_table,
function_name_buffer,
data_base_ptr->number_of_function_calls
);
}
look_ahead_buffer[ 0 ] = '\0'; /* reset tail buffer */
static_flag = false;
} /* end of parenthesis */
function_name_buffer_ptr = function_name_buffer; /* reset buffer */
*function_name_buffer_ptr = '\0';
} /* end of found_a_possible_function */
} /* end of while !at_end_of_source_file */
(void)fclose( stream );
if( !g_quiet_flag )
{
(void)printf( "\n" );
}

if(
!( file_record_array_ptr->source_file_comment =
strdup( file_comment_buffer )
)
)
file_record_array_ptr->source_file_comment = fake_comment;

/***** mark called functions in list as static if in defined list *******/


total_called_count = 0;
data_base_ptr = starting_data_base_ptr;
while( data_base_ptr != data_base_array_ptr )
{
total_called_count += data_base_ptr->number_of_function_calls;
++data_base_ptr;
}
data_base_ptr = starting_data_base_ptr;
while( data_base_ptr < data_base_array_ptr )
{
if( data_base_ptr->static_definition )
mark_as_static( starting_called_function_ptr,
data_base_ptr->defined_function,
total_called_count
);
++data_base_ptr;
}
++file_record_array_ptr; /* next file name entry */
++count_of_source_files;
if( count_of_source_files >= Max_files )
{
(void)printf( "\nError: too many files to process.\n" );
exit( 1 );
}
return at_end_of_source_file;
}
/***************************************************************************/

[LISTING FIVE]

/***************************************************************************
cpfuncts.c
void near build_box_parts( int );
void near tab_to_left_margin( FILE * );
static void near stop( void );
static void near setpage( data_base_record_type * );
static int near recursion_check( char *, int );
void near check_for_new_page( void );
static void near draw_output_block( char *, char *, char *,
char *, int, int, int );
int near doprint( int );
void near scan_for_static_or_global( int *, int, char *, char * );
int near binary_search_sorted_data_base( char * );

***************************************************************************/

#define MAIN 0
#include "cpheader.h"

static char
top_line_of_box[ 37 ], bottom_line_of_box[ 37 ],
wall, ibm_line, bottom_attach,
upper_left_corner, lower_left_corner,
upper_right_corner, lower_right_corner,
left_attach, right_attach;

static char *recursion_filename, *test_filename;


static int static_recursion;

int near binary_search_sorted_data_base( char * );


void near build_box_parts( int );
void near check_for_new_page( void );
int near doprint( int );
void near scan_for_static_or_global( int *, int, char *, char * );
void near tab_to_left_margin( FILE * );

static void near draw_output_block( char *, char *, char *,


char *, int, int, int );
static int near recursion_check( char *, int );
static void near stop( void );
static void near setpage( data_base_record_type * );

/***************************************************************************/
void near build_box_parts( is_ibm )
int is_ibm;
{
int i;

if( is_ibm )
{
wall = '\xb3';
ibm_line = '\xc4';
bottom_attach = '\xc2';
upper_left_corner = '\xda';
lower_left_corner = '\xc0';
upper_right_corner = '\xbf';
lower_right_corner = '\xd9';
left_attach = '\xb4';
right_attach = '\xc3';
}
else
{
wall = '|';
ibm_line = '-';
bottom_attach = '+';
upper_left_corner = '+';
lower_left_corner = '+';
upper_right_corner = '+';
lower_right_corner = '+';
left_attach = '+';
right_attach = '+';
}

top_line_of_box[ 0 ] = upper_left_corner;
bottom_line_of_box[ 0 ] = lower_left_corner;
for( i = 1; i <= 34; ++i )
{
top_line_of_box[ i ] = ibm_line;
bottom_line_of_box[ i ] = ibm_line;
}
top_line_of_box[ i ] = upper_right_corner;
bottom_line_of_box[ i ] = lower_right_corner;
top_line_of_box[ ++i ] = '\0';
bottom_line_of_box[ i ] = '\0';
}
/***************************************************************************/
void near tab_to_left_margin( output )
FILE *output;
{
register int i;

for( i = 0; i < defined_left_margin; ++i )


(void)fputc( ' ', output );
}
/***************************************************************************/
static void near stop()
{
(void)printf( "hello" );
}
/***************************************************************************/
static void near setpage( data_base_ptr )
data_base_record_type *data_base_ptr;
{
linked_pages_list *page_list_ptr;

page_list_ptr = data_base_ptr->ptr_to_page_list;
if( page_list_ptr == NULL )
{
if(
!( page_list_ptr =
(linked_pages_list *)malloc( sizeof( linked_pages_list ) )
)
)
{
(void)fprintf( stderr, "Ran out of memory for page # list.\n" );
exit( 1 );
}

data_base_ptr->ptr_to_page_list = page_list_ptr;
}
else
{
while( page_list_ptr->next_page_ptr )
page_list_ptr = page_list_ptr->next_page_ptr;
if(
!( page_list_ptr->next_page_ptr =
(linked_pages_list *)malloc( sizeof( linked_pages_list ) )
)
)
{
(void)fprintf( stderr, "Ran out of memory for page # list.\n" );
exit( 1 );
}

page_list_ptr = page_list_ptr->next_page_ptr;
}
page_list_ptr->next_page_ptr = NULL;
page_list_ptr->on_this_page = page - 1;
}
/***************************************************************************/
static int near recursion_check( string, static_call )
char *string;
int static_call;
{
register char **recursion_array_ptr;

recursion_array_ptr = recursion_array;
if( static_recursion )
{ /* defined function is static */
while(
*recursion_array_ptr && /* not null */
/* and different function names */
( strcmp( *recursion_array_ptr, string ) ||
/* or same function names and */
/* in different files */
strcmp( test_filename, recursion_filename )
)
)
++recursion_array_ptr;
}
else
{ /* defined function is not static */
while(
*recursion_array_ptr && /* not null & */
/* and different function names */
( strcmp( *recursion_array_ptr, string ) ||
/* or same function names and */
static_call /* called is static */
)
)
++recursion_array_ptr;
}
return ( *recursion_array_ptr )? true: false;
}
/***************************************************************************/
void near check_for_new_page()
{
int i;

if( defined_page_length == 0 && line == 9999 )


{
(void)fprintf( output, "\n\n\n\n" );
line = 0;
}
else
{
if( defined_page_length != 0 )
{
if( line > ( defined_page_length - 5 ) )
{
(void)fprintf( output, "\f" );
line = 0;
}
if( line == 0 )
{
top_of_form_done = true;
tab_to_left_margin( output );
(void)fprintf( output, "%s", title );
for( i = strlen( title ); i < ( effective_width - 10 ); ++i )
(void)fputc( ' ', output );
(void)fprintf( output, "Page:%4d\n", page );
tab_to_left_margin( output );
for( i = 0; i < effective_width; ++i )
(void)fputc( '_', output );
(void)fprintf( output, "\n\n" );
line = 3;
++page;
}
}
}
}
/***************************************************************************/
static void near draw_output_block( lead_in_string,
name_of_function,
description,
name_of_file,
either_count,
tail_flag,
kill_flag
)
char *lead_in_string,
*name_of_function,
*description,
*name_of_file;
int either_count, tail_flag, kill_flag;
{
unsigned int string_length;
static char alternate_lead_in[ 140 ];

/******* 1st line ***********************************************************/


tab_to_left_margin( output );
(void)fprintf( output, "%s %s\n", lead_in_string, top_line_of_box );

/******* 2nd line ***********************************************************/


tab_to_left_margin( output );
string_length = strlen( lead_in_string );
if( string_length ) /******* ie not main or defined function box ***/
{
(void)strncpy( alternate_lead_in, lead_in_string, --string_length );
alternate_lead_in[ string_length++ ] = '\0'; /* restore string_length */
}
if( string_length ) /******* ie not main or defined function box ***/
(void)fprintf( output, "%s%c%c%c%-33s %c\n",
alternate_lead_in,
/*** if( kill_flag ) /****** last line to this box ******************/
/*** else /****** line continues downwards ***************/
( kill_flag )? lower_left_corner: right_attach,
ibm_line, left_attach, name_of_function, wall );
else /****** main or defined box starting ***********/
(void)fprintf( output, "%c%c%-33s %c\n",
ibm_line, left_attach, name_of_function, wall );

/******* 3rd line ***********************************************************/


tab_to_left_margin( output );
if( string_length-- ) /***** kill outside vertical line on last box ****/
lead_in_string[ string_length++ ] = ( kill_flag )? (char)' ': wall;
(void)fprintf( output, "%s %c%-20s %8s%3d %c\n",
lead_in_string, wall, description,
name_of_file, either_count, wall );

/******* 4th line ***********************************************************/


tab_to_left_margin( output );
bottom_line_of_box[ 2 ] = /******** if defined box has calls ***********/
( tail_flag && either_count )? bottom_attach: ibm_line;
(void)fprintf( output, "%s %s\n", lead_in_string, bottom_line_of_box );

line += 4;
top_of_form_done = false;
}
/***************************************************************************/
static char library_string[] = { "(library)" };
static char usage_string[] = { "Used=" };
static char funct_string[] = { "Functs=" };

int near doprint( index )


int index;
{
int
loop_counter,
max_count,
starting_index,
found,
return_value;
data_base_record_type *record_ptr;
function_type *f_list_ptr;

static int kill_flag = false;

starting_index = index;
record_ptr = array_of_ptrs_to_records[ starting_index ];

recursion_array[ recursion_depth ] = record_ptr->defined_function;


if( !recursion_depth )
{
recursion_filename = record_ptr->file_record_ptr->source_filename;
/* add function to list for recursion check */
static_recursion = record_ptr->static_definition;
}
check_for_new_page();
setpage( array_of_ptrs_to_records[ starting_index ] );

return_value = page - 1; /* must be a relic! */


/* start w/ target function */
draw_output_block( nesting_display_buffer,
record_ptr->defined_function,
( record_ptr->file_record_ptr )->source_filename,
funct_string,
record_ptr->number_of_function_calls,
true,
kill_flag
);

++recursion_depth;
/**** mystic width = 4 *****/
(void)strcat( nesting_display_buffer, " |" );
nesting_display_buffer[ strlen( nesting_display_buffer ) - 1 ] = wall;

max_count = record_ptr->number_of_function_calls;
for( loop_counter = 0, f_list_ptr = record_ptr->ptr_to_function_table;
loop_counter < max_count;
++loop_counter, ++f_list_ptr
)
{
kill_flag = ( loop_counter == ( max_count - 1 ) )? true: false;
check_for_new_page();
/* is called function defined? */
found = binary_search_sorted_data_base( f_list_ptr->functions_name );
if( found >= 0 )
{
scan_for_static_or_global( &found,
f_list_ptr->static_function,
f_list_ptr->functions_name,
f_list_ptr->its_filename
);

}
if( found >= 0 ) /* yes */
{
test_filename = f_list_ptr->its_filename;
if( recursion_check( f_list_ptr->functions_name,
f_list_ptr->static_function )
)
{
/* tab_to_left_margin( output );
/* (void)fprintf( output, "%s\n", nesting_display_buffer ); */
setpage( array_of_ptrs_to_records[ found ] );
/* ++line; */
top_of_form_done = false;
draw_output_block( nesting_display_buffer,
f_list_ptr->functions_name,
"(recursive)",
"",
0,
false,
kill_flag
);
}
else /* not recursive and found >= 0 */
{
if( array_of_ptrs_to_records[ found ]->number_of_references == 1 )
{ /* got a new function */
/* tab_to_left_margin( output );
/* (void)fprintf( output, "%s\n", nesting_display_buffer );
/* ++line;
/* top_of_form_done = false; */
doprint( found ); /* used only once */
}
else
{ /* a previously defined function */
/* tab_to_left_margin( output );
/* (void)fprintf( output, "%s\n", nesting_display_buffer ); */
setpage( array_of_ptrs_to_records[ found ] );
/* ++line;
/* top_of_form_done = false; */
draw_output_block( nesting_display_buffer,
f_list_ptr->functions_name,
"(defined)",
usage_string,
f_list_ptr->is_referenced,
false,
kill_flag
);
}
}
}
else /* found = -1 ie not defined means */
{ /* a library function */
/* tab_to_left_margin( output );
/* (void)fprintf( output, "%s\n", nesting_display_buffer );
/* ++line;
/* top_of_form_done = false; */
draw_output_block( nesting_display_buffer,
f_list_ptr->functions_name,
library_string,
usage_string,
f_list_ptr->is_referenced,
false,
kill_flag
);
}
} /* end of loop on all called functions */

/* remove function f/ recursion list */


recursion_array[ recursion_depth ] = NULL;
/**** mystic width = 4 *****/
nesting_display_buffer[ strlen( nesting_display_buffer ) - 4 ] = '\0';
--recursion_depth;
return return_value;
}
/***************************************************************************/
void near scan_for_static_or_global(
index_ptr, is_static, function_name, file_name
)
int *index_ptr, is_static;
char *function_name, *file_name;
{
int index;

index = *index_ptr;
if( index )
while( index-- )
if( strcmp( function_name,
array_of_ptrs_to_records[ index ]->defined_function )
)
{
++index; /* exit at last matching defined function */
break;
}
do {
if(
( !is_static && !array_of_ptrs_to_records[ index ]->static_definition
) ||
( is_static &&
array_of_ptrs_to_records[ index ]->static_definition &&
!strcmp( array_of_ptrs_to_records[ index ]->
file_record_ptr->source_filename,
file_name
)
)
)
break;
}
while(
( ++index < count_of_functions ) &&
!strcmp( function_name,
array_of_ptrs_to_records[ index ]->defined_function
)
);
if(
( index >= count_of_functions ) ||
strcmp( function_name, array_of_ptrs_to_records[ index ]->defined_function
)
)
index = -1;
*index_ptr = index;
}
/***************************************************************************/
int near binary_search_sorted_data_base( key )
char *key;
{
int lo, hi, index;
int doesnt_match;

lo = 0;
hi = count_of_valid_records - 1;
index = ( hi - lo ) / 2;

while( true )
{
doesnt_match =
strcmp( key, array_of_ptrs_to_records[ index ]->defined_function );
if( !doesnt_match ) /* a match found at index */
break;
if( lo >= hi ) /* no match found */
{
index = -1;
break;
}
if( doesnt_match < 0 ) /* key < choice so go downwards */
hi = index - 1;
else /* key > choice so go upwards */
lo = index + 1;
index = ( hi + lo ) / 2; /* new choice */
}
return index;
}
/***************************************************************************/

[LISTING SIX]

cp.obj : cp.c cpheader.h cp


cl -AL -c cp.c

cpinput.obj : cpinput.c cpheader.h cp


cl -AL -c cpinput.c

cpfuncts.obj : cpfuncts.c cpheader.h cp


cl -AL -c cpfuncts.c

cpbuild.obj: cpbuild.c cpheader.h cp


cl -AL cpbuild.c -c

cp.exe : cp.obj cpinput.obj cpfuncts.obj cpbuild.obj cp


link cp+ cpinput+ cpbuild+ cpfuncts/packcode/st:16000,,cp;

[LISTING SEVEN]

cpheader.h
cp.c
cpbuild.c
cpfuncts.c
cpinput.c

Das könnte Ihnen auch gefallen