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 >
Text File  |  1989-03-05  |  16KB  |  626 lines

  1.  
  2.  
  3. /* next_string() reads the header file and returns the next NON-COMMENT */
  4. /* string in the file, or NULL if end-of-file is reached */
  5. /* *f is the file pointer for the header file */
  6.  
  7. char *next_string(f)
  8. FILE *f;
  9. {
  10.     int num_fields; /* number of fields read & assigned by fscanf() */
  11.     static char instring[256];  /* buffer for fscanf() */
  12.         /* WARNING: While INSTRING is declared as a local variable, its */
  13.         /* actual scope is more global. INSTRING is declared STATIC */
  14.         /* because it is accessed by other functions via the STRING */
  15.         /* pointer.  The contents of INSTRING must remain valid beyond */
  16.         /* the life of the next_string() call.                      */
  17.  
  18.     char *string; /* pointer to INSTRING */
  19.  
  20.     num_fields=fscanf(f,"%s",instring);
  21.     string=instring;
  22.  
  23.         /* throw away the comments */
  24.     if(!strncmp("/*", string, 2))
  25.     {
  26.         do
  27.         {
  28.         num_fields=fscanf(f,"%s",string);
  29.         } while( strncmp("*/",&string[strlen(string)-2],2) && (num_fields != EOF));
  30.  
  31.         /* get the next string after the close of the comment */
  32.         /* to return.  Make sure that the next string is not also */
  33.         /* a comment by using the recursive call */
  34.         string=next_string(f);
  35.     }
  36.  
  37.     if(num_fields==EOF)
  38.         string=NULL;
  39.  
  40.     return(string);
  41.  
  42. }
  43.  
  44.  
  45.  
  46.  
  47.  
  48. Listing 1: The main parsing function of h_filter.
  49.  
  50.  
  51. ACUITY_H                                acuity.h
  52. ACUITY_SCALE_FACTOR                     acuity.h
  53. CORRECT                                 acuity.h
  54. DATAFILE                                acuity.h
  55. LARGER                                  acuity.h
  56. NEW_SIZE                                acuity.h
  57. NO_RESPONSE                             acuity.h
  58. SEARCH                                  acuity.h
  59. SMALLER                                 acuity.h
  60. STDOUT                                  acuity.h
  61. STDPRN                                  acuity.h
  62. TARG_DOWN                               acuity.h
  63. TARG_LEFT                               acuity.h
  64. TARG_RIGHT                              acuity.h
  65. TARG_UP                                 acuity.h
  66. TRACK                                   acuity.h
  67. VERTICAL_DASH                           acuity.h
  68. WRONG                                   acuity.h
  69.  
  70.  
  71.  
  72. Table 1: Sample output of h_filter.
  73.  
  74. AB_END                                  acu_menu.h
  75. ABS                                     itex100.h
  76. ABSOLUTE                                itex100.h
  77. ACU_MENU_H                              acu_menu.h
  78. ACUITY_ARRAY_SIZE                       acu_menu.h
  79. ACUITY_H                                acuity.h
  80. ACUITY_SCALE_FACTOR                     acuity.h
  81. AD_IN                                   dt2808.h
  82. ADD                                     itex100.h
  83. ALLOCATION_ERROR                        itex100.h
  84. ALT                                     keys.h
  85. AND                                     itex100.h
  86. ANSI_H                                  ansi.h
  87. ANY_BUTTON                              cont_lib.h
  88. aslope                                  scotoma.h
  89. AUTO_PAUSE                              scotoma.h
  90.  
  91.  
  92.  
  93.  
  94.  
  95. Table 2: Fragment of sample output from 
  96.          h_merge, including the 'a' entries
  97.          from table 1.
  98.  
  99. /* h_filter.c is a utility for extracting names of #define'd constants */
  100. /* and macros, structs, unions, and typedefs from a header file and */
  101. /* creating an alphabetical listing file of the names, like this: */
  102. /* NAME    HEADER.H filename, one entry per line in the file. */
  103. /* All header.h filename entries are the same in the output file */
  104. /* The output file can be used to create a cross-reference list of */
  105. /* header file names for a library by combining the appropriate */
  106. /* alphabetical lists using h_merge.c, a companion utility. */
  107. /*                                                              */
  108. /* WARNING: h_filter.c uses a simplified version of C grammar, in */
  109. /* which comment delimiters and keywords are assumed to be preceded */
  110. /* and followed by either a space or a newline.  Valid C code will not */
  111. /* necessarily be parsed properly.  Further, it is assumed that all */
  112. /* struct and union definitions have names, i.e., struct {int a;char b;}c; */
  113. /* will be viewed as having the name "int". */
  114. /*                                                                      */
  115. /* Written by T. Clune 8/88.  Copyright (c) 1988, Eye Research Institute */
  116. /* Boston, MA.  Permission is granted to individuals to use this utility */
  117. /* for noncommercial applications.  All commercial rights are reserved. */
  118.  
  119. /* Known MS C-specific aspects of this program are: use of process.h header */
  120. /* file to decalre exit() and use of strcmpi(), which is a Microsoft function */
  121. /* like strcmp() except that the string comparison is case-insensitive.  A */
  122. /* usable substitute for strcmpi() is available in my file strcmpi.c. */
  123.  
  124.  
  125. #include <stdio.h>
  126. #include <process.h>    /* MS C header that declares exit() */
  127. #include <string.h>
  128. #include <ctype.h>
  129. #include <malloc.h>
  130. #include <search.h>
  131.  
  132. #define MAXPTRS 500     /* max number of names supported from the .h file */
  133. #define PATH_CHAR '\\'  /* path delimiter in MS-DOS */
  134. #define DRIVE_CHAR ':' /* drive designator in MS-DOS */
  135.  
  136.  
  137. static char *ptr[MAXPTRS];   /* ptrs to names of definitions in .h file */
  138. static int numptrs; /* the number of names that are actually in the file */
  139.  
  140. char * next_string();
  141. char * lose_braces();
  142. void extract_names(), put_name();
  143. void make_list();
  144. int compare();
  145.  
  146.  
  147. /* main() Usage: h_filter foo.h bar.srt,                                 */
  148. /* where FOO.H is the name of the header file to work on                 */
  149. /* and BAR.SRT is the alphabetically-sorted list of FOO.H defined names. */
  150.  
  151. main(argc, argv)
  152. int argc;
  153. char *argv[];
  154. {
  155.  
  156.     FILE *f;
  157.     numptrs=0;  /* initialize number of names variable */
  158.  
  159.     if(argc != 3)
  160.     {
  161.     printf("Usage: %s foo.h bar.srt,\n", argv[0]);
  162.     printf("\twhere FOO.H is the name of the header file to work on,\n");
  163.     printf("\t and BAR.SRT is the alphabetically-sorted list of FOO.H defined names,\n");
  164.     exit(-1);
  165.     }
  166.  
  167.  
  168.     if((f=fopen(argv[1], "r"))==NULL)
  169.     {
  170.     printf("Unable to open %s\n", argv[1]);
  171.     exit(-1);
  172.     }
  173.  
  174.     extract_names(f);
  175.  
  176.     fclose(f);
  177.  
  178.     make_list(argv[1], argv[2]);
  179.  
  180. }
  181.  
  182.  
  183.  
  184.  
  185.  
  186. /* compare() is the function for qsort() comparisons in make_list() */
  187.  
  188. int compare(a, b)
  189. char **a, **b;
  190. {
  191.     return(strcmpi(*a, *b));
  192. }
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199. /* extract_names() parses the header file, throwing away everything except */
  200. /* #define, struct, union, or typedef names, and sends the names to put_names() */
  201. /* for storage in malloc()ed space. *f is the file pointer for the header file */
  202.  
  203. void extract_names(f)
  204. FILE *f;
  205. {
  206.     char *string, oldstring[256], *str_ptr;
  207.  
  208.     do
  209.     {
  210.  
  211.     string=next_string(f);
  212.  
  213.         /* get the names that immediately follow a keyword */
  214.         /* (i.e., #define name, struct name, or union name) */
  215.     if(!strcmp("#define", string))
  216.     {
  217.  
  218.         string=next_string(f);
  219.         put_name(string);
  220.     }
  221.  
  222.         /* get the '#      define' names */
  223.     if(!strcmp("#", string))
  224.     {
  225.         string=next_string(f);
  226.         if(!strcmp("define", string))
  227.         {
  228.         string=next_string(f);
  229.         put_name(string);
  230.         }
  231.     }
  232.  
  233.         /* get struct or union name and throw away the braces */
  234.     if( (!strcmp("struct", string)) || (!strcmp("union", string)) )
  235.     {
  236.  
  237.         string=next_string(f);
  238.         put_name(string);
  239.         /* it's either 'struct name{' */
  240.         if(str_ptr=strchr(string, '{'))
  241.         string=lose_braces(f, str_ptr);
  242.         else
  243.         {
  244.             /* or 'struct name {' */
  245.         string=next_string(f);
  246.         string=lose_braces(f, string);
  247.         }
  248.     }
  249.  
  250.  
  251.         /* for typedefs, the name is the last thing before ';' */
  252.         /* i.e., typedef identifier {...} name;                */
  253.     if(!strcmp("typedef", string))
  254.     {
  255.         for(;;)
  256.         {
  257.         string=next_string(f);
  258.         if(str_ptr=strchr(string, '{'))
  259.             string=lose_braces(f, str_ptr);
  260.  
  261.             /* the end of the typedef condition */
  262.            if(str_ptr=strrchr(string,';'))
  263.            {
  264.             /* this selects between 'name ;' and  'name; ' */
  265.             /* if the former, the previous string had the name */
  266.             *str_ptr='\0';
  267.             if(strlen(string))
  268.             put_name(string);
  269.             else
  270.             put_name(oldstring);
  271.             break;
  272.         }
  273.  
  274.         strcpy(oldstring, string);
  275.         }
  276.  
  277.     }
  278.  
  279.  
  280.     }while(string != NULL);
  281.  
  282. }
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290. /* lose_braces() throws away everything between the braces of a struct, */
  291. /* union, or typedef, so that ' struct a{ struct b; union c;};' does not */
  292. /* cause 'b' or 'c' to be listed as defined in this header. */
  293. /* *f is the file pointer for the header file and *str_ptr is the string to */
  294. /* work on.  lose_braces() returns the last string it was working on */
  295.  
  296. char * lose_braces(f, str_ptr)
  297. FILE *f;
  298. char *str_ptr;
  299. {
  300.     char *string;   /* copy of str_ptr while working */
  301.     int level=0;  /* level of braces counter for typedefs */
  302.  
  303.     string=str_ptr;
  304.     do
  305.     {
  306.           /* count the braces */
  307.     while(str_ptr=strchr(str_ptr,'{'))
  308.     {
  309.          str_ptr++;
  310.         level++;
  311.     }
  312.  
  313.     str_ptr=string;
  314.     while(str_ptr=strchr(str_ptr,'}'))
  315.     {
  316.         str_ptr++;
  317.         level--;
  318.     }
  319.  
  320.     if(level)
  321.     {
  322.         string=next_string(f);
  323.         str_ptr=string;
  324.     }
  325.  
  326.     }while(level);
  327.  
  328.     return(string);
  329.  
  330. }
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337. /* make_list() sorts and copies the names list to the output file, eliminating */
  338. /* duplication and labeling each name as having come from the specified .h file */
  339. /* hfile is the header file filespec, ofile is the output file filespec. */
  340.  
  341. void make_list(hfile, ofile)
  342. char *hfile, *ofile;
  343. {
  344.     char oldname[256];
  345.     char *str_ptr;
  346.     int i,j;
  347.     FILE *f;
  348.  
  349.  
  350.  
  351.     if((f=fopen(ofile, "w"))==NULL)
  352.     {
  353.     printf("Unable to open %s\n", ofile);
  354.     exit(-1);
  355.     }
  356.  
  357.  
  358.     /* strip out the path of the .h file name */
  359.  
  360.     if(str_ptr=strrchr(hfile, PATH_CHAR))
  361.     hfile=str_ptr+1;
  362.     else
  363.     if(str_ptr=strrchr(hfile, DRIVE_CHAR))
  364.         hfile=str_ptr+1;
  365.  
  366.         /* sort the name pointers alphabetically */
  367.     qsort(ptr, (unsigned)numptrs, sizeof(char *), compare);
  368.  
  369.     oldname[0]='\0';
  370.  
  371.     for(j=0;j<numptrs;j++)
  372.     {
  373.     if(strcmp(ptr[j], oldname)) /* eliminate duplication of names */
  374.     {
  375.         fprintf(f,"%s",ptr[j]);
  376.         /* format 1/2 page spacing between name & .h source file */
  377.         for(i=0;i<(5-(strlen(ptr[j])/8));i++)
  378.         fprintf(f, "\t");
  379.         fprintf(f,"%s\n", hfile);
  380.         strcpy(oldname, ptr[j]);
  381.  
  382.     }
  383.     }
  384.  
  385.     fclose(f);
  386.  
  387. }
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395. /* next_string() reads the header file and returns the next NON-COMMENT */
  396. /* string in the file, or NULL if end-of-file is reached */
  397. /* *f is the file pointer for the header file */
  398.  
  399. char *next_string(f)
  400. FILE *f;
  401. {
  402.     int num_fields; /* number of fields read & assigned by fscanf() */
  403.     static char instring[256];  /* buffer for fscanf() */
  404.         /* WARNING: While INSTRING is declared as a local variable, its */
  405.         /* actual scope is more global. INSTRING is declared STATIC */
  406.         /* because it is accessed by other functions via the STRING */
  407.         /* pointer.  The contents of INSTRING must remain valid beyond */
  408.         /* the life of the next_string() call.                      */
  409.  
  410.     char *string; /* pointer to INSTRING */
  411.  
  412.     num_fields=fscanf(f,"%s",instring);
  413.     string=instring;
  414.  
  415.         /* throw away the comments */
  416.     if(!strncmp("/*", string, 2))
  417.     {
  418.         do
  419.         {
  420.         num_fields=fscanf(f,"%s",string);
  421.         } while( strncmp("*/",&string[strlen(string)-2],2) && (num_fields != EOF));
  422.  
  423.         /* get the next string after the close of the comment */
  424.         /* to return.  Make sure that the next string is not also */
  425.         /* a comment by using the recursive call */
  426.         string=next_string(f);
  427.     }
  428.  
  429.     if(num_fields==EOF)
  430.         string=NULL;
  431.  
  432.     return(string);
  433.  
  434. }
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442. /* put_name() accepts as input the string containing the definition name */
  443. /* and strips any leading or trailing characers like '{', '(', or '*' */
  444. /* from the name before putting the name in malloc()ed space.  Note that */
  445. /* '_' IS NOT removed from the definition name, so '_exit' will end up */
  446. /* alphabetized by '_', not 'e' */
  447.  
  448. void put_name(string)
  449. char *string;
  450. {
  451.     int i,j;
  452.  
  453.     i=0;
  454.     j=strlen(string);
  455.  
  456.     /* throw away leading garbage */
  457.     while(!((i>=j) || (isalnum(*(string+i))) || (*(string+i) == '_')))
  458.     i++;
  459.     if(i<j)
  460.     string +=i;
  461.     j=strlen(string);
  462.  
  463.     /* throw away trailing garbage */
  464.     i=0;
  465.     while( (i<j) && ( (isalnum(*(string+i))) || (*(string+i) == '_') ) )
  466.     i++;
  467.     if(i<j)
  468.     *(string+i)='\0';
  469.  
  470.     /* is anything left? */
  471.     if(strlen(string))
  472.     {
  473.     ptr[numptrs]=malloc(strlen(string)+1);
  474.  
  475.     if(ptr[numptrs]==NULL)
  476.     {
  477.         printf("malloc() error.\n");
  478.         exit(-1);
  479.     }
  480.  
  481.     strcpy(ptr[numptrs], string);
  482.     numptrs++;
  483.  
  484.     }
  485.  
  486.     if(numptrs>=MAXPTRS)
  487.     {
  488.     printf("File has too many names for this program.\n");
  489.     exit(-1);
  490.     }
  491.  
  492.  
  493. }
  494.  
  495.  
  496. /* h_merge.c merges two alphabetically-ordered text files.  Used with */
  497. /* h_filter.c to build a cross-reference listing of a library's header */
  498. /* files.  Written by T. Clune 8/88.  Copyright (c) 1988,  Eye Research */
  499. /* Institute, Boston MA.  No rights reserved. */
  500.  
  501. /* See h_filter.c for comments on MS C dependencies */
  502.  
  503. #include <stdio.h>
  504. #include <process.h>    /* MS C exit() declaration header */
  505. #include <string.h>
  506.  
  507. void merge_list();
  508.  
  509.  
  510.  
  511. /* main() Usage: h_merge a.srt b.srt c.srt,             */
  512. /* where a.srt and b.srt are sorted files to be merged, */
  513. /* and c.srt is the name for the output file.           */
  514.  
  515. main(argc, argv)
  516. int argc;
  517. char *argv[];
  518. {
  519.     if(argc != 4)
  520.     {
  521.     printf("Usage: %s a.srt b.srt c.srt,\n", argv[0]);
  522.     printf("\twhere a.srt and b.srt are sorted files to be merged,\n");
  523.     printf("\tand c.srt is the name for the output file\n");
  524.     exit(-1);
  525.     }
  526.  
  527.     merge_list(argv[1], argv[2], argv[3]);
  528.  
  529. }
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537. /* merge_list() merges the alphabetically-sorted FIRSTFILE and SECONDFILE */
  538. /* and places the results in OUTFILE */
  539. /* FIRSTFILE, SECONDFILE, and OUTFILE are the respective filespec strings */
  540.  
  541. void merge_list(firstfile, secondfile, outfile)
  542. char *firstfile, *secondfile, *outfile;
  543. {
  544.     FILE *ff, *sf, *of; /* file pointers for firstfile, secondfile, outfile */
  545.     char f_string[256], s_string[256]; /* the active lines for interleaving */
  546.     char *f_end, *s_end; /* go to NULL when EOF for firstfile or secondfile */
  547.     int i;
  548.  
  549.  
  550.     if((of=fopen(outfile, "w"))==NULL)
  551.     {
  552.     printf("Unable to open %s\n", outfile);
  553.     exit(-1);
  554.     }
  555.  
  556.  
  557.     if((ff=fopen(firstfile, "r"))==NULL)
  558.     {
  559.     printf("Error opening %s\n", firstfile);
  560.     exit(-1);
  561.     }
  562.  
  563.  
  564.     if((sf=fopen(secondfile, "r"))==NULL)
  565.     {
  566.     printf("Unable to open %s\n", secondfile);
  567.     exit(-1);
  568.     }
  569.  
  570.     /* prime the pump */
  571.     f_end=fgets(f_string, 256, ff);
  572.     s_end=fgets(s_string, 256, sf);
  573.  
  574.     for(;;)
  575.     {
  576.         /* when one file is empty, just copy the other to output */
  577.     if(f_end==NULL)
  578.     {
  579.         while(s_end != NULL)
  580.         {
  581.         fprintf(of, "%s", s_string);
  582.         s_end=fgets(s_string, 256, sf);
  583.         }
  584.         break;
  585.     }
  586.  
  587.     else
  588.     {
  589.         if(s_end==NULL)
  590.         {
  591.         while(f_end != NULL)
  592.         {
  593.             fprintf(of,"%s",f_string);
  594.             f_end=fgets(f_string, 256, ff);
  595.         }
  596.         break;
  597.         }
  598.     }
  599.         
  600.     /* compare the next entry from FIRST and SECOND.  The alphabetically */
  601.     /* prior entry gets put to output, and a new entry is read */
  602.  
  603.     i=strcmpi(f_string, s_string);
  604.  
  605.     if(i<0)
  606.     {
  607.         fprintf(of,"%s",f_string);
  608.         f_end=fgets(f_string, 256, ff);
  609.     }
  610.  
  611.     else
  612.     {
  613.         fprintf(of,"%s",s_string);
  614.         s_end=fgets(s_string, 256, sf);
  615.     }
  616.  
  617.     }
  618.  
  619.     fclose(ff);
  620.     fclose(sf);
  621.     fclose(of);    
  622.  
  623.  
  624. }
  625.  
  626.