home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_07_03
/
v7n3083a.txt
< prev
next >
Wrap
Text File
|
1989-03-05
|
16KB
|
626 lines
/* next_string() reads the header file and returns the next NON-COMMENT */
/* string in the file, or NULL if end-of-file is reached */
/* *f is the file pointer for the header file */
char *next_string(f)
FILE *f;
{
int num_fields; /* number of fields read & assigned by fscanf() */
static char instring[256]; /* buffer for fscanf() */
/* WARNING: While INSTRING is declared as a local variable, its */
/* actual scope is more global. INSTRING is declared STATIC */
/* because it is accessed by other functions via the STRING */
/* pointer. The contents of INSTRING must remain valid beyond */
/* the life of the next_string() call. */
char *string; /* pointer to INSTRING */
num_fields=fscanf(f,"%s",instring);
string=instring;
/* throw away the comments */
if(!strncmp("/*", string, 2))
{
do
{
num_fields=fscanf(f,"%s",string);
} while( strncmp("*/",&string[strlen(string)-2],2) && (num_fields != EOF));
/* get the next string after the close of the comment */
/* to return. Make sure that the next string is not also */
/* a comment by using the recursive call */
string=next_string(f);
}
if(num_fields==EOF)
string=NULL;
return(string);
}
Listing 1: The main parsing function of h_filter.
ACUITY_H acuity.h
ACUITY_SCALE_FACTOR acuity.h
CORRECT acuity.h
DATAFILE acuity.h
LARGER acuity.h
NEW_SIZE acuity.h
NO_RESPONSE acuity.h
SEARCH acuity.h
SMALLER acuity.h
STDOUT acuity.h
STDPRN acuity.h
TARG_DOWN acuity.h
TARG_LEFT acuity.h
TARG_RIGHT acuity.h
TARG_UP acuity.h
TRACK acuity.h
VERTICAL_DASH acuity.h
WRONG acuity.h
Table 1: Sample output of h_filter.
AB_END acu_menu.h
ABS itex100.h
ABSOLUTE itex100.h
ACU_MENU_H acu_menu.h
ACUITY_ARRAY_SIZE acu_menu.h
ACUITY_H acuity.h
ACUITY_SCALE_FACTOR acuity.h
AD_IN dt2808.h
ADD itex100.h
ALLOCATION_ERROR itex100.h
ALT keys.h
AND itex100.h
ANSI_H ansi.h
ANY_BUTTON cont_lib.h
aslope scotoma.h
AUTO_PAUSE scotoma.h
Table 2: Fragment of sample output from
h_merge, including the 'a' entries
from table 1.
/* h_filter.c is a utility for extracting names of #define'd constants */
/* and macros, structs, unions, and typedefs from a header file and */
/* creating an alphabetical listing file of the names, like this: */
/* NAME HEADER.H filename, one entry per line in the file. */
/* All header.h filename entries are the same in the output file */
/* The output file can be used to create a cross-reference list of */
/* header file names for a library by combining the appropriate */
/* alphabetical lists using h_merge.c, a companion utility. */
/* */
/* WARNING: h_filter.c uses a simplified version of C grammar, in */
/* which comment delimiters and keywords are assumed to be preceded */
/* and followed by either a space or a newline. Valid C code will not */
/* necessarily be parsed properly. Further, it is assumed that all */
/* struct and union definitions have names, i.e., struct {int a;char b;}c; */
/* will be viewed as having the name "int". */
/* */
/* Written by T. Clune 8/88. Copyright (c) 1988, Eye Research Institute */
/* Boston, MA. Permission is granted to individuals to use this utility */
/* for noncommercial applications. All commercial rights are reserved. */
/* Known MS C-specific aspects of this program are: use of process.h header */
/* file to decalre exit() and use of strcmpi(), which is a Microsoft function */
/* like strcmp() except that the string comparison is case-insensitive. A */
/* usable substitute for strcmpi() is available in my file strcmpi.c. */
#include <stdio.h>
#include <process.h> /* MS C header that declares exit() */
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <search.h>
#define MAXPTRS 500 /* max number of names supported from the .h file */
#define PATH_CHAR '\\' /* path delimiter in MS-DOS */
#define DRIVE_CHAR ':' /* drive designator in MS-DOS */
static char *ptr[MAXPTRS]; /* ptrs to names of definitions in .h file */
static int numptrs; /* the number of names that are actually in the file */
char * next_string();
char * lose_braces();
void extract_names(), put_name();
void make_list();
int compare();
/* main() Usage: h_filter foo.h bar.srt, */
/* where FOO.H is the name of the header file to work on */
/* and BAR.SRT is the alphabetically-sorted list of FOO.H defined names. */
main(argc, argv)
int argc;
char *argv[];
{
FILE *f;
numptrs=0; /* initialize number of names variable */
if(argc != 3)
{
printf("Usage: %s foo.h bar.srt,\n", argv[0]);
printf("\twhere FOO.H is the name of the header file to work on,\n");
printf("\t and BAR.SRT is the alphabetically-sorted list of FOO.H defined names,\n");
exit(-1);
}
if((f=fopen(argv[1], "r"))==NULL)
{
printf("Unable to open %s\n", argv[1]);
exit(-1);
}
extract_names(f);
fclose(f);
make_list(argv[1], argv[2]);
}
/* compare() is the function for qsort() comparisons in make_list() */
int compare(a, b)
char **a, **b;
{
return(strcmpi(*a, *b));
}
/* extract_names() parses the header file, throwing away everything except */
/* #define, struct, union, or typedef names, and sends the names to put_names() */
/* for storage in malloc()ed space. *f is the file pointer for the header file */
void extract_names(f)
FILE *f;
{
char *string, oldstring[256], *str_ptr;
do
{
string=next_string(f);
/* get the names that immediately follow a keyword */
/* (i.e., #define name, struct name, or union name) */
if(!strcmp("#define", string))
{
string=next_string(f);
put_name(string);
}
/* get the '# define' names */
if(!strcmp("#", string))
{
string=next_string(f);
if(!strcmp("define", string))
{
string=next_string(f);
put_name(string);
}
}
/* get struct or union name and throw away the braces */
if( (!strcmp("struct", string)) || (!strcmp("union", string)) )
{
string=next_string(f);
put_name(string);
/* it's either 'struct name{' */
if(str_ptr=strchr(string, '{'))
string=lose_braces(f, str_ptr);
else
{
/* or 'struct name {' */
string=next_string(f);
string=lose_braces(f, string);
}
}
/* for typedefs, the name is the last thing before ';' */
/* i.e., typedef identifier {...} name; */
if(!strcmp("typedef", string))
{
for(;;)
{
string=next_string(f);
if(str_ptr=strchr(string, '{'))
string=lose_braces(f, str_ptr);
/* the end of the typedef condition */
if(str_ptr=strrchr(string,';'))
{
/* this selects between 'name ;' and 'name; ' */
/* if the former, the previous string had the name */
*str_ptr='\0';
if(strlen(string))
put_name(string);
else
put_name(oldstring);
break;
}
strcpy(oldstring, string);
}
}
}while(string != NULL);
}
/* lose_braces() throws away everything between the braces of a struct, */
/* union, or typedef, so that ' struct a{ struct b; union c;};' does not */
/* cause 'b' or 'c' to be listed as defined in this header. */
/* *f is the file pointer for the header file and *str_ptr is the string to */
/* work on. lose_braces() returns the last string it was working on */
char * lose_braces(f, str_ptr)
FILE *f;
char *str_ptr;
{
char *string; /* copy of str_ptr while working */
int level=0; /* level of braces counter for typedefs */
string=str_ptr;
do
{
/* count the braces */
while(str_ptr=strchr(str_ptr,'{'))
{
str_ptr++;
level++;
}
str_ptr=string;
while(str_ptr=strchr(str_ptr,'}'))
{
str_ptr++;
level--;
}
if(level)
{
string=next_string(f);
str_ptr=string;
}
}while(level);
return(string);
}
/* make_list() sorts and copies the names list to the output file, eliminating */
/* duplication and labeling each name as having come from the specified .h file */
/* hfile is the header file filespec, ofile is the output file filespec. */
void make_list(hfile, ofile)
char *hfile, *ofile;
{
char oldname[256];
char *str_ptr;
int i,j;
FILE *f;
if((f=fopen(ofile, "w"))==NULL)
{
printf("Unable to open %s\n", ofile);
exit(-1);
}
/* strip out the path of the .h file name */
if(str_ptr=strrchr(hfile, PATH_CHAR))
hfile=str_ptr+1;
else
if(str_ptr=strrchr(hfile, DRIVE_CHAR))
hfile=str_ptr+1;
/* sort the name pointers alphabetically */
qsort(ptr, (unsigned)numptrs, sizeof(char *), compare);
oldname[0]='\0';
for(j=0;j<numptrs;j++)
{
if(strcmp(ptr[j], oldname)) /* eliminate duplication of names */
{
fprintf(f,"%s",ptr[j]);
/* format 1/2 page spacing between name & .h source file */
for(i=0;i<(5-(strlen(ptr[j])/8));i++)
fprintf(f, "\t");
fprintf(f,"%s\n", hfile);
strcpy(oldname, ptr[j]);
}
}
fclose(f);
}
/* next_string() reads the header file and returns the next NON-COMMENT */
/* string in the file, or NULL if end-of-file is reached */
/* *f is the file pointer for the header file */
char *next_string(f)
FILE *f;
{
int num_fields; /* number of fields read & assigned by fscanf() */
static char instring[256]; /* buffer for fscanf() */
/* WARNING: While INSTRING is declared as a local variable, its */
/* actual scope is more global. INSTRING is declared STATIC */
/* because it is accessed by other functions via the STRING */
/* pointer. The contents of INSTRING must remain valid beyond */
/* the life of the next_string() call. */
char *string; /* pointer to INSTRING */
num_fields=fscanf(f,"%s",instring);
string=instring;
/* throw away the comments */
if(!strncmp("/*", string, 2))
{
do
{
num_fields=fscanf(f,"%s",string);
} while( strncmp("*/",&string[strlen(string)-2],2) && (num_fields != EOF));
/* get the next string after the close of the comment */
/* to return. Make sure that the next string is not also */
/* a comment by using the recursive call */
string=next_string(f);
}
if(num_fields==EOF)
string=NULL;
return(string);
}
/* put_name() accepts as input the string containing the definition name */
/* and strips any leading or trailing characers like '{', '(', or '*' */
/* from the name before putting the name in malloc()ed space. Note that */
/* '_' IS NOT removed from the definition name, so '_exit' will end up */
/* alphabetized by '_', not 'e' */
void put_name(string)
char *string;
{
int i,j;
i=0;
j=strlen(string);
/* throw away leading garbage */
while(!((i>=j) || (isalnum(*(string+i))) || (*(string+i) == '_')))
i++;
if(i<j)
string +=i;
j=strlen(string);
/* throw away trailing garbage */
i=0;
while( (i<j) && ( (isalnum(*(string+i))) || (*(string+i) == '_') ) )
i++;
if(i<j)
*(string+i)='\0';
/* is anything left? */
if(strlen(string))
{
ptr[numptrs]=malloc(strlen(string)+1);
if(ptr[numptrs]==NULL)
{
printf("malloc() error.\n");
exit(-1);
}
strcpy(ptr[numptrs], string);
numptrs++;
}
if(numptrs>=MAXPTRS)
{
printf("File has too many names for this program.\n");
exit(-1);
}
}
/* h_merge.c merges two alphabetically-ordered text files. Used with */
/* h_filter.c to build a cross-reference listing of a library's header */
/* files. Written by T. Clune 8/88. Copyright (c) 1988, Eye Research */
/* Institute, Boston MA. No rights reserved. */
/* See h_filter.c for comments on MS C dependencies */
#include <stdio.h>
#include <process.h> /* MS C exit() declaration header */
#include <string.h>
void merge_list();
/* main() Usage: h_merge a.srt b.srt c.srt, */
/* where a.srt and b.srt are sorted files to be merged, */
/* and c.srt is the name for the output file. */
main(argc, argv)
int argc;
char *argv[];
{
if(argc != 4)
{
printf("Usage: %s a.srt b.srt c.srt,\n", argv[0]);
printf("\twhere a.srt and b.srt are sorted files to be merged,\n");
printf("\tand c.srt is the name for the output file\n");
exit(-1);
}
merge_list(argv[1], argv[2], argv[3]);
}
/* merge_list() merges the alphabetically-sorted FIRSTFILE and SECONDFILE */
/* and places the results in OUTFILE */
/* FIRSTFILE, SECONDFILE, and OUTFILE are the respective filespec strings */
void merge_list(firstfile, secondfile, outfile)
char *firstfile, *secondfile, *outfile;
{
FILE *ff, *sf, *of; /* file pointers for firstfile, secondfile, outfile */
char f_string[256], s_string[256]; /* the active lines for interleaving */
char *f_end, *s_end; /* go to NULL when EOF for firstfile or secondfile */
int i;
if((of=fopen(outfile, "w"))==NULL)
{
printf("Unable to open %s\n", outfile);
exit(-1);
}
if((ff=fopen(firstfile, "r"))==NULL)
{
printf("Error opening %s\n", firstfile);
exit(-1);
}
if((sf=fopen(secondfile, "r"))==NULL)
{
printf("Unable to open %s\n", secondfile);
exit(-1);
}
/* prime the pump */
f_end=fgets(f_string, 256, ff);
s_end=fgets(s_string, 256, sf);
for(;;)
{
/* when one file is empty, just copy the other to output */
if(f_end==NULL)
{
while(s_end != NULL)
{
fprintf(of, "%s", s_string);
s_end=fgets(s_string, 256, sf);
}
break;
}
else
{
if(s_end==NULL)
{
while(f_end != NULL)
{
fprintf(of,"%s",f_string);
f_end=fgets(f_string, 256, ff);
}
break;
}
}
/* compare the next entry from FIRST and SECOND. The alphabetically */
/* prior entry gets put to output, and a new entry is read */
i=strcmpi(f_string, s_string);
if(i<0)
{
fprintf(of,"%s",f_string);
f_end=fgets(f_string, 256, ff);
}
else
{
fprintf(of,"%s",s_string);
s_end=fgets(s_string, 256, sf);
}
}
fclose(ff);
fclose(sf);
fclose(of);
}