",*pheader);
else
(void)fprintf(html_fd,"" );
*pheader = (char*)NULL; /* so we don't print it again */
}
column = print_typename(the_type,the_type_name, sym_size,
sym_list[i]);
last_size = sym_size;
nv = 0; /* no variables yet in statement */
ncontin = 0;
}
if (DECLARE_COMPACT())
next_column = (nv==0?column:column + 2);
else
next_column = NEXT_COLUMN(nv==0?column:column + 2);
need = (int)strlen(sym_list[i]->name);
/* Add space for '+' or ' ' identifier to indicate var modification */
need++;
if (sym_list[i]->array_var /* leave space for "(...)" */
&& ARRAY_VARS_DIMENSIONED())
need += strlen(get_dimension_list(sym_list[i]));
if ((next_column + need) > SRC_COMMENT_MAX_WIDTH) /* ? start new declaration */
{
if (nv>0 && (NO_CONTINUATION_LINES() || ncontin == 19))
{
(void)putc('\n',html_fd);
column = print_typename(the_type,the_type_name, sym_size,
sym_list[i]);
ncontin = 0;
nv = 0; /* no variables yet in statement */
}
else
{
if( FREE_FORM() ) { /* do a free-form continuation */
print_blanks(next_column-column);
(void)fputs("& \n",html_fd);
print_blanks(html_indent);
column = html_indent;
}
else { /* do a fixed-form continuation */
(void)putc('\n',html_fd);
print_blanks(5);
(void)putc('x',html_fd);
column = 6;
}
if (DECLARE_COMPACT())
next_column = (nv==0?column:column + 2);
else
next_column = NEXT_COLUMN(nv==0?column:column + 2);
++ncontin;
}
last_size = sym_size;
}
if (nv > 0) /* multiple variables */
{
(void)fputs(", ",html_fd);
print_blanks(next_column - column - 2);
column = next_column;
}
/* Identify vars that are modified in this routine */
if ( sym_list[i]->assigned_flag && ! sym_list[i]->parameter )
(void)putc('+',html_fd);
else
(void)putc(' ',html_fd);
for (p = sym_list[i]->name; *p; ++p)
(void)putc(VARIABLES_AND_CONSTANTS_LOWERCASE() ?
makelower(*p) : makeupper(*p),html_fd);
if (sym_list[i]->array_var
&& ARRAY_VARS_DIMENSIONED())
(void)fputs(stmt_fragment,html_fd);
column += need;
nv++; /* count variables */
if (sym_list[i]->parameter)
{
fprintf( html_fd, "%*s", 38 - column, " " );
fprintf( html_fd, "%s\n",get_parameter_value(sym_list[i]) );
column = 0;
nv = 0;
}
}
if (column > 0)
(void)putc('\n',html_fd);
}
PRIVATE int
#if HAVE_STDC
print_selected_equiv_decls(
Lsymtab **sym_list,
int n,
char **pheader)
#else /* K&R style */
int print_selected_equiv_decls(sym_list, n, pheader)
Lsymtab *sym_list[];
int n;
char **pheader;
#endif /* HAVE_STDC */
{
int column, i, next_column,
sym_type=0, sym_size, block_name_col_width;
char *p, scope_str[128];
Lsymtab *cur_sym, *tmp_sym;
column = 0;
block_name_col_width = first_variable_column + 1;
for (i = 0; i < n; ++i)
{ /* loop over variables */
if ( sym_list[i]->equiv_link == NULL ) continue;
if (column == 0) /* at beginning of line, so */
{ /* we need a type name */
if ( *pheader != (char*)NULL )
{
if ( strlen( *pheader ) )
(void)fprintf(html_fd,
" \n%s | \n",
*pheader);
*pheader = (char *)NULL;
(void)fprintf(html_fd, "\n" );
}
column += fprintf( html_fd, "\n%-*.*s",
block_name_col_width, block_name_col_width, "EQUIV" );
}
/*
* Circulate within current equivalence list to print all members.
* After each member is printed set it's equiv_link to NULL so we don't
* report it again.
*
* NOTE: This affects the sym_list passed to make_html()
* Place this so remaining processing does not need the equiv_link.
*/
cur_sym = sym_list[i];
while ( cur_sym->equiv_link != NULL )
{
if ( column == 0 )
column += fprintf( html_fd, "\n%*.*s",
block_name_col_width, block_name_col_width, "" );
/*--- Print var type ---*/
sym_size = ACTUAL_SIZE( cur_sym );
sym_type = (datatype_of(cur_sym->type) == type_UNDECL) ?
get_type(cur_sym) : datatype_of(cur_sym->type);
column += print_typename(sym_type, NULL, sym_size, cur_sym);
/*--- Print var name, but first prefix "set" flag if required ---*/
next_column = MY_NEXT_COLUMN( column ) + 2; /* +2 to make it match common refs */
if ( cur_sym->assigned_flag && ! cur_sym->parameter )
(void)putc('+',html_fd);
else
(void)putc(' ',html_fd);
column ++;
/* Print var name upper or lower case as desired */
for (p = cur_sym->name; *p; ++p)
(void)putc(VARIABLES_AND_CONSTANTS_LOWERCASE() ?
makelower(*p) : makeupper(*p),html_fd);
column += strlen( cur_sym->name );
/* Append a hint that this is an array. Use "()" for array, " " if not */
column += fprintf( html_fd, "%s", cur_sym->array_var ? "()" : " " );
/* Finish up the var name print by spacing over for next "scope" column */
for ( ; column < next_column; column++ ) (void)putc( ' ', html_fd );
/*--- Print var scope ---*/
if ( cur_sym->common_block )
sprintf( scope_str, "COMMON /%s/", cur_sym->common_block->name );
else
sprintf( scope_str, "Local Var" );
column += fprintf( html_fd, "%-s", scope_str );
column = 0;
tmp_sym = cur_sym->equiv_link;
cur_sym->equiv_link = NULL;
cur_sym = tmp_sym;
}
}
if ( n > 0 )
fprintf( html_fd, " | \n" );
return( n );
}
PRIVATE int
#if HAVE_STDC
print_selected_common_decls(
Lsymtab **sym_list,
int n,
int the_type,
char *comname,
char **pheader)
#else /* K&R style */
int print_selected_common_decls(sym_list, n, the_type, comname, pheader)
Lsymtab *sym_list[];
int n;
int the_type;
char *comname;
char **pheader;
#endif /* HAVE_STDC */
{
int column, i, tv, last_size, need, next_column, nv,
raw_type, sym_type, sym_size, block_name_col_width;
char *p;
column = 0;
block_name_col_width = first_variable_column + 1;
last_size = 0;
nv = 0; /* count of variables in statement */
tv = 0; /* total number of vars printed */
for (i = 0; i < n; ++i)
{ /* loop over variables */
raw_type = datatype_of(sym_list[i]->type);
sym_type = (raw_type == type_UNDECL) ?
get_type(sym_list[i]) : datatype_of(sym_list[i]->type);
if ((the_type != type_ERROR) && (sym_type != the_type))
continue;
sym_size = ACTUAL_SIZE(sym_list[i]);
if ((nv > 0) && (sym_size != last_size))
{ /* have new length modifier, so must start new declaration */
(void)putc('\n',html_fd);
column = 0;
nv = 0;
}
if (column == 0) /* at beginning of line, so */
{ /* we need a type name */
if ( *pheader != (char*)NULL )
{
if ( strlen( *pheader ) )
(void)fprintf(html_fd,
"\n%s | \n",
*pheader);
*pheader = (char *)NULL;
}
column += fprintf( html_fd, "%-*.*s",
block_name_col_width, block_name_col_width, comname );
column += print_typename(the_type, NULL, sym_size, sym_list[i]);
last_size = sym_size;
nv = 0; /* no variables yet in statement */
}
next_column = MY_NEXT_COLUMN( nv == 0 ? column : column + 2 );
need = (int)strlen(sym_list[i]->name);
/* Add space for '+' or ' ' identifier to indicate var modification */
need++;
if (sym_list[i]->array_var /* leave space for "(...)" */
&& ARRAY_VARS_DIMENSIONED())
need += strlen(get_dimension_list(sym_list[i]));
/*
* Start new declaration if we are out of space on the line and one or more
* vars have already been printed
*/
if ( nv > 0 && (next_column + need) > SRC_COMMENT_MAX_WIDTH )
{
(void)putc('\n',html_fd);
column = 0;
column += fprintf( html_fd, "%-*.*s",
block_name_col_width, block_name_col_width, comname );
column += print_typename(the_type,NULL, sym_size, sym_list[i]);
nv = 0; /* no variables yet in statement */
last_size = sym_size;
}
if (nv > 0) /* multiple variables */
{
(void)fputs(", ",html_fd);
print_blanks(next_column - column - 2);
column = next_column;
}
/* Identify vars that are modified in this routine */
if ( sym_list[i]->assigned_flag && ! sym_list[i]->parameter )
(void)putc('+',html_fd);
else
(void)putc(' ',html_fd);
for (p = sym_list[i]->name; *p; ++p)
(void)putc(VARIABLES_AND_CONSTANTS_LOWERCASE() ?
makelower(*p) : makeupper(*p),html_fd);
tv ++;
if (sym_list[i]->array_var
&& ARRAY_VARS_DIMENSIONED())
(void)fputs(stmt_fragment,html_fd);
column += need;
nv++; /* count variables */
if (sym_list[i]->parameter)
{
fprintf( html_fd, "%*s", 39 - column, " " );
fprintf( html_fd, "%s\n",get_parameter_value(sym_list[i]) );
column = 0;
nv = 0;
}
}
if (column > 0)
(void)putc('\n',html_fd);
return( tv );
}
PRIVATE int
#if HAVE_STDC
print_typename(int the_type, char *the_type_name, int the_size, Lsymtab *symt)
/* type_ERROR if typename non-NULL */
/* non-NULL overrides type_table[] use */
#else /* K&R style */
print_typename(the_type,the_type_name,the_size,symt)
int the_type; /* type_ERROR if typename non-NULL */
char *typename; /* non-NULL overrides type_table[] use */
int the_size;
Lsymtab *symt;
#endif /* HAVE_STDC */
{ /* return value is last column printed */
int column;
char digits[sizeof("*18446744073709551616")]; /* big enough for 2^64 */
char *p;
char *size_expression;
print_blanks(html_indent);
column = html_indent;
for (p = (the_type_name == (char*)NULL) ? type_table[the_type] : the_type_name;
*p; ++p, ++column)
(void)putc(KEYWORDS_LOWERCASE() ? makelower(*p) : makeupper(*p),
html_fd);
if (symt != NULL) {
if (((symt->size_is_adjustable && (the_type == type_STRING))) ||
(the_size == size_ADJUSTABLE)) /* happens only for CHARACTER*(*) */
{
/* size_is_adjustable overrides the_size because def_parameter() */
/* in symtab.c replaced size_ADJUSTABLE with actual size. */
(void)fputs("*(*)",html_fd);
column += 4;
}
else if (symt->size_is_expression && (the_type == type_STRING))
{
size_expression = get_size_expression(symt);
(void)fputs(size_expression,html_fd);
column += strlen(size_expression);
}
else if ((the_size > 0) &&
(the_type != type_ERROR) &&
(the_size != std_size[the_type]))
{ /* supply length modifier for non-standard type sizes */
(void)sprintf(digits,"*%d",the_size);
(void)fputs(digits,html_fd);
column += strlen(digits);
}
}
if (DECLARE_COMPACT())
{
print_blanks(1);
column++;
}
else if (column < first_variable_column)
{
print_blanks(first_variable_column-column);
column = first_variable_column;
}
else if (column == first_variable_column)
{
print_blanks(1);
column++;
print_blanks(NEXT_COLUMN(column)-column);
column = NEXT_COLUMN(column);
}
else
{
print_blanks(NEXT_COLUMN(column)-column);
column = NEXT_COLUMN(column);
}
return (column);
}
PRIVATE int
#if HAVE_STDC
select_arguments(Lsymtab *sym_entry)
#else /* K&R style */
select_arguments(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is a module argument) */
if (sym_entry->declared_external ||
sym_entry->invoked_as_func)
return (0);
else if (sym_entry->argument)
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_externals_by_name(
Lsymtab *sym_entry )
#else /* K&R style */
select_externals_by_name( sym_entry )
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* Select subroutines and external function calls that are NOT the current
* Module.
*/
if ( sym_entry == current_module )
return( 0 );
else if (sym_entry->declared_intrinsic) /* must appear first, because symbols */
return (0); /* can be both declared_intrinsic and declared_external*/
/* ??? is this a bug in ftnchek 2.7 ??? */
else if ( datatype_of(sym_entry->type) == type_SUBROUTINE )
return (1);
else if (storage_class_of(sym_entry->type) == class_STMT_FUNCTION)
return (0);
else if (sym_entry->declared_external)
return (1);
else if (sym_entry->declared_intrinsic || sym_entry->intrinsic)
return (0);
else if (sym_entry->invoked_as_func)
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_entry_points_by_name(Lsymtab *sym_entry)
#else /* K&R style */
select_intrinsics_by_name(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is intrinsic and must appear in INTRINSIC declaration) */
if (sym_entry->entry_point && ! sym_entry->is_current_module )
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_intrinsics_by_name(Lsymtab *sym_entry)
#else /* K&R style */
select_intrinsics_by_name(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is intrinsic and must appear in INTRINSIC declaration) */
if (sym_entry->declared_intrinsic || sym_entry->intrinsic )
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_locals(Lsymtab *sym_entry)
#else /* K&R style */
select_locals(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is a local variable) */
if (EXCL_SF3_DECLARATIONS() && sf3_internal_name(sym_entry))
return (0);
else if (sym_entry->argument ||
sym_entry->common_var ||
( storage_class_of(sym_entry->type) == class_COMMON_BLOCK ) ||
sym_entry->declared_external ||
sym_entry->declared_intrinsic ||
sym_entry->entry_point ||
sym_entry->external ||
sym_entry->intrinsic ||
sym_entry->invoked_as_func ||
sym_entry->parameter)
return (0);
else if ( sym_entry->used_flag || sym_entry->assigned_flag )
return (1);
else
return( 0 );
}
PRIVATE int
#if HAVE_STDC
select_equivalences(Lsymtab *sym_entry)
#else /* K&R style */
select_equivalences(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is a local variable) */
if ( ( sym_entry->used_flag || sym_entry->assigned_flag ) &&
( sym_entry->equiv_link != NULL && sym_entry->equiv_link != sym_entry ) )
return (1);
else
return( 0 );
}
PRIVATE int
#if HAVE_STDC
select_common_blocks(Lsymtab *sym_entry)
#else /* K&R style */
select_common_blocks(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is a COMMON block name) */
if (storage_class_of(sym_entry->type) == class_COMMON_BLOCK)
{
return (1);
}
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_namelists(Lsymtab *sym_entry)
#else /* K&R style */
select_namelists(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is a NAMELIST name) */
if (storage_class_of(sym_entry->type) == class_NAMELIST)
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_parameters(Lsymtab *sym_entry)
#else /* K&R style */
select_parameters(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
/* return (symbol is a PARAMETER name) */
if (sym_entry->parameter && sym_entry->used_flag )
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
select_statement_functions(Lsymtab *sym_entry)
#else /* K&R style */
select_statement_functions(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{
if (storage_class_of(sym_entry->type) == class_STMT_FUNCTION)
return (1);
else
return (0);
}
PRIVATE int
#if HAVE_STDC
sf3_internal_name(Lsymtab *sym_entry)
#else /* K&R style */
sf3_internal_name(sym_entry)
Lsymtab *sym_entry;
#endif /* HAVE_STDC */
{ /* Return (symbol is an SFTRAN3 internal name). */
char *p = sym_entry->name;
/* The SFTRAN3 preprocessor uses internal names of the form NPRddd,
NXdddd, N2dddd, and N3dddd, where d is a decimal digit. */
if ((p[0] != 'N') || (strlen(p) != 6))
return (0);
switch (p[1])
{
case 'P':
if ((p[2] == 'R') && isdigit(p[3]) && isdigit(p[4]) && isdigit(p[5]))
return (1);
else
return (0);
case 'X': /* fall through */
case '2': /* fall through */
case '3':
if (isdigit(p[2]) && isdigit(p[3]) && isdigit(p[4]) && isdigit(p[5]))
return (1);
else
return (0);
default:
return (0);
}
}
PRIVATE int
#if HAVE_STDC
make_sym_list(Lsymtab **sym_list, int (*selector) (Lsymtab *))
#else /* K&R style */
make_sym_list(sym_list,selector)
Lsymtab *sym_list[];
PROTO(int (*selector),( Lsymtab *sym_entry ));
#endif /* HAVE_STDC */
{
int i;
int n;
for (i = 0, n = 0; i < loc_symtab_top; ++i)
{
if (selector(&loc_symtab[i]))
sym_list[n++] = &loc_symtab[i];
}
if (n > 0)
{
if (selector == select_parameters) {
/* Free form is not blank-insensitive, so go
thru parameter declarations and remove any
blanks from within numbers.
*/
if( FREE_FORM() ) {
for(i=0; i < n; i++) {
if( is_numeric_type(get_type(sym_list[i])) ) {
strip_blanks(sym_list[i]->info.param->src_text);
}
}
}
/* original PARAMETER statement order must be preserved so that
the expressions do not refer to as-yet-undefined parameter names */
sort_parameters(sym_list,n);
}
else
sort_lsymbols(sym_list,n);
}
return (n);
}
PRIVATE int
#if HAVE_STDC
make_unsorted_sym_list(Lsymtab **sym_list, int (*selector) (Lsymtab *))
#else /* K&R style */
make_unsorted_sym_list(sym_list,selector)
Lsymtab *sym_list[];
PROTO(int (*selector),( Lsymtab *sym_entry ));
#endif /* HAVE_STDC */
{
int i;
int n;
for (i = 0, n = 0; i < loc_symtab_top; ++i)
{
if (selector(&loc_symtab[i]))
sym_list[n++] = &loc_symtab[i];
}
if (n > 0)
{
if (selector == select_parameters) {
/* Free form is not blank-insensitive, so go
thru parameter declarations and remove any
blanks from within numbers.
*/
if( FREE_FORM() ) {
for(i=0; i < n; i++) {
if( is_numeric_type(get_type(sym_list[i])) ) {
strip_blanks(sym_list[i]->info.param->src_text);
}
}
}
/* original PARAMETER statement order must be preserved so that
the expressions do not refer to as-yet-undefined parameter names */
sort_parameters(sym_list,n);
}
else
sort_lsymbols(sym_list,n);
}
return (n);
}
/* Routine to remove whitespace from a string */
PRIVATE void
#if HAVE_STDC
strip_blanks(
char *s)
#else /* K&R style */
strip_blanks( s )
char *s;
#endif
{
char *t;
for( t=s; *s != '\0'; s++ )
{
if ( !isspace(*s) )
*t++ = *s;
}
*t = '\0';
}
/*=================================================================================
*
* Compare two structures (IO_Unit_Info). If they are the same return 1,
* otherwise return 0;
*
*================================================================================*/
PRIVATE int
#if HAVE_STDC
compare_info(
IO_Unit_Info *io1,
IO_Unit_Info *io2 )
#else /* K&R style */
compare_info( io1, io2 )
IO_Unit_Info *io1;
IO_Unit_Info *io2;
#endif
{
int i = 0;
if ( io1->io_access == io2->io_access && io1->io_form == io2->io_form )
if ( io1->unit_id == io2->unit_id )
if ( io1->unit_no == io2->unit_no )
i = 1;
return( i );
}
/*=================================================================================
*
* Use the ftnchek operation types to accumulate a character string abbreviation
* of the operations performed.
*
*================================================================================*/
PRIVATE void
#if HAVE_STDC
choose_opcode(
char *opcode,
int io_operation )
#else /* K&R style */
choose_opcode( opcode, io_operation )
char *opcode;
int io_operation;
#endif
{
switch( io_operation )
{
case tok_REWIND : opcode[0] = 'A'; break;
case tok_BACKSPACE: opcode[1] = 'B'; break;
case tok_ENDFILE : opcode[2] = 'E'; break;
case tok_CLOSE : opcode[3] = 'C'; break;
case tok_INQUIRE : opcode[4] = 'I'; break;
case tok_OPEN : opcode[5] = 'O'; break;
case tok_READ : opcode[6] = 'R'; break;
case tok_WRITE :
case tok_PRINT : opcode[7] = 'W'; break;
}
}
/*=================================================================================
*
* Determine and set the access and form type based on
* operation. We want to get rid of "default" for read,
* write, print and open but mark accordingly others
*================================================================================*/
PRIVATE void
#if HAVE_STDC
set_access_and_format_code(
IO_Unit_Info *save_info )
#else /* K&R style */
set_access_and_format_code( sav_info )
IO_Unit_Info *save_info;
#endif /* HAVE_STDC */
{
switch ( save_info->io_operation )
{
case tok_INQUIRE:
case tok_CLOSE:
save_info->io_access = IO_ACCESS_DEFAULT;
save_info->io_form = IO_FORM_DEFAULT;
break;
case tok_BACKSPACE:
case tok_REWIND:
case tok_ENDFILE:
save_info->io_access = IO_ACCESS_SEQUENTIAL;
save_info->io_form = IO_FORM_DEFAULT;
break;
default:
if ( save_info->io_access == IO_ACCESS_DEFAULT )
save_info->io_access = IO_ACCESS_SEQUENTIAL;
if ( save_info->io_form == IO_FORM_DEFAULT )
{
if ( save_info->io_access == IO_ACCESS_SEQUENTIAL )
save_info->io_form = IO_FORM_FORMATTED;
else
save_info->io_form = IO_FORM_UNFORMATTED;
}
break;
} /* End switch */
}
/*=================================================================================
*
* Routine to summarize I/O usage for the HTML output module. ftnchek generates
* internal lists of I/O operations by line number. This is too verbose for the
* HTML summary so this routine produces a report of all I/O operations by each
* unique combination of unit name, unit number, access type and format type.
*
* We don't want to modify ftnchek's internal lists because they might be used
* by some routine down-stream so local copies are made and destroyed after use.
*
*================================================================================*/
PRIVATE void
#if HAVE_STDC
htmlout_io_unit_usages(
void )
#else /* K&R style */
htmlout_io_unit_usages( )
#endif
{
static int i, j;
static char* IO_access[]={" ","DIR","SEQ"};
static char* IO_form[] ={" ","UNF","FMTD"};
static char opcode[] = " ";
static IO_Unit_Info **my_ioinfo, *ioinfo_ptr;
static const char *unit_name;
static int h;
IO_Unit_Info save_info = { 0 };
if ( num_io_unit_usages > 0 )
{
fprintf(html_fd,"\n I/O Operations: | \n");
fprintf(html_fd,"" );
fprintf(html_fd,"Unit ID Unit No Access Form Operation");
/* Copy the io information structure to a new array so we can rework it */
my_ioinfo = (IO_Unit_Info **) malloc( sizeof(IO_Unit_Info) * num_io_unit_usages );
memcpy( my_ioinfo, io_unit_info,
sizeof(IO_Unit_Info) * num_io_unit_usages );
/*---------------------------------------------------------------------------
* I/O information is stored by line number. We don't want line no. for the
* HTML summary so loop through the ftnchek list. We have a current I/O
* item of interest. It is compared with others in the list. Each match of
* unit name, unit no., access type AND format type results in accumulation of
* operation code in var opcode and setting the line number to -1.
*
* The next time through the loop ignores already counted operations by
* looking for a line number of -1.
*--------------------------------------------------------------------------*/
for ( i = 0; i < num_io_unit_usages; i++ )
{
/* A new io reference */
ioinfo_ptr = (IO_Unit_Info *)((char *)my_ioinfo + i * sizeof(IO_Unit_Info));
/* If line_num is -1 we already accounted for this reference so skip */
if ( ioinfo_ptr->line_num != -1 )
{
/* compare the current I/O reference to determine "NEWNESS" */
if ( compare_info( ioinfo_ptr, &save_info ) == 0 )
{
/* This is a new reference. Copy to the holding area, save_info */
memcpy( &save_info, ioinfo_ptr, sizeof( IO_Unit_Info ) );
ioinfo_ptr->line_num = -1;
/*
* Set access and format parameters for our summary report
*/
set_access_and_format_code( &save_info );
strcpy( opcode, " " ); /* Initialize for this ref */
choose_opcode( opcode, ioinfo_ptr->io_operation ); /* get abbrev */
/*------------------------------------------------------------------
* Look down the list for other matching references accumulating
* opcode abbreviations and setting matching reference line_num
* to -1.
*-----------------------------------------------------------------*/
for ( j = i + 1; j < num_io_unit_usages; j++ )
{
ioinfo_ptr = (IO_Unit_Info *)((char *)my_ioinfo +
j * sizeof(IO_Unit_Info));
/*
* Set access and format parameters for our summary report
*/
set_access_and_format_code( ioinfo_ptr );
/* compare the current I/O reference to the saved reference */
if ( compare_info( ioinfo_ptr, &save_info ) == 1 )
{
/* References match so set line_num and get opcode */
ioinfo_ptr->line_num = -1;
choose_opcode( opcode, ioinfo_ptr->io_operation );
}
}
/*------------------------------------------------------------------
* Now we should have all of one io reference with opcode
* summary. Print out results
*-----------------------------------------------------------------*/
/* Print unit name and number or blank if unknown */
if ( (h=save_info.unit_id) < 0)
{
/* handle cases of unknown and default */
unit_name = (h == IO_UNIT_DEFAULT)? "*": "";
}
else
{
/* handle cases where it is an identifier, unit_id=hashnum */
unit_name = hashtab[h].name;
}
/* Name portion */
fprintf( html_fd, "\n%7s%8s", unit_name,
/* if id is a parameter, print name=value */
( save_info.unit_id >= 0 &&
save_info.unit_no >= 0 ) ? "=" : " " );
/* Unit number portion */
if ( save_info.unit_no < 0 )
fprintf(html_fd,"%7s","");
else
fprintf(html_fd,"%-7d",save_info.unit_no);
/* Print out access type, format and operations summary */
fprintf(html_fd," %4s %4s %-9s",
IO_access[save_info.io_access],
IO_form[save_info.io_form] ,
opcode );
}
}
}
/* All units have been written, finish up the html table */
fprintf( html_fd, "\n"
"\nOperation codes A=rewind,B=backspace,C=close,E=endfile"
"\n I=inquire,O=open,R=read,W=write" );
fprintf( html_fd, " | \n" );
free( my_ioinfo );
}
}
| |