2 RPM and it's source code are covered under two separate licenses.
4 The entire code base may be distributed under the terms of the GNU General
5 Public License (GPL), which appears immediately below. Alternatively,
6 all of the source code in the lib subdirectory of the RPM source code
7 distribution as well as any code derived from that code may instead be
8 distributed under the GNU Library General Public License (LGPL), at the
9 choice of the distributor. The complete text of the LGPL appears
10 at the bottom of this file.
12 This alternatively is allowed to enable applications to be linked against
13 the RPM library (commonly called librpm) without forcing such applications
14 to be distributed under the GPL.
16 Any questions regarding the licensing of RPM should be addressed to
17 marc@redhat.com and ewt@redhat.com.
21 Simple progam for pullng all the referenced java classes out of a
22 class file. Java files are supposed to be platform independent, so
23 this program should work on all platforms. This code is based on
24 the information found in:
26 "Java Virtual Machine" by Jon Meyer & Troy Downing.
27 O'Reilly & Associates, INC. (First Edition, March 1997)
30 Jonathan Ross, Ken Estes
38 JAR consists of a zip archive, as defined by PKWARE, containing
39 a manifest file and potentially signature files, as defined in
40 the Manifest and Signature specification. So we use infozip's
41 'unzip -p' found at http://www.cdrom.com/pub/infozip/.
43 Additional documentation, about this fact, at:
45 http://java.sun.com/products/jdk/1.1/docs/guide/jar/jarGuide.html
46 http://java.sun.com/products/jdk/1.2/docs/guide/jar/jarGuide.html
48 http://java.sun.com/products/jdk/1.1/docs/guide/jar/manifest.html
49 http://java.sun.com/products/jdk/1.2/docs/guide/jar/manifest.html
56 these includes are for my use, rpm will use #include "system.h"*
69 /*---------typedefs---------*/
72 /* The symbol table is a waste of memory..
73 but it's easy to code! */
83 /*---------Global Variables, in all caps---------*/
85 /*name of this program*/
88 /*name of the current class file*/
91 /*the name of the last class file seen*/
101 /*keywords found in class file*/
102 char *KEYWORD_VERSION=0;
103 char *KEYWORD_REVISION=0;
104 char *KEYWORD_EPOCH=0;
108 Quantify says over 80 percent of the time of the program is spent
109 in printf (and the functions it calls) AND I verified that only
110 about a quarter of the classes found in the dependency analysis are
111 unique. After the change no function used more then 26% of the over
114 I implement a simple mechanism to remove most duplicate dependencies.
115 The print_table is a table of string which are to be printed. Just
116 before the program exists it is sorted and all unique entries are
117 printed. If it fills up during then it is flushed using the same
120 The functions which manipulate the table are:
121 void print_table_flush(void)
122 void print_table_add(char *str)
127 #define MAX_PRINT_TABLE 10000
128 char *PRINT_TABLE[MAX_PRINT_TABLE];
129 int SIZE_PRINT_TABLE;
131 /*--------- declare all functions ---------*/
134 void outofmemory(void);
135 void die(char *format, ...);
136 size_t my_fread(void *ptr, size_t size, size_t nitems, FILE *stream);
137 void check_range(short value, short poolSize);
138 char *is_lower_equal (char *string, char *pattern);
139 int findJavaMagic (FILE *fileHandle);
140 int my_strcmp (const void *a, const void *b);
141 void print_table_flush(void);
142 void print_table_add(char *str);
143 char *formatClassName(char *pSomeString, char terminator, char print_star);
144 void dumpRefType(char *pSomeString);
145 void dumpRequires(symbolTable_t *symbolTable);
146 void genSymbolTable (FILE *fileHandle, symbolTable_t *symbolTable);
147 void findClassName (FILE *fileHandle, symbolTable_t *symbolTable);
148 void freeSymbolTable (symbolTable_t *symbolTable);
149 void processJavaFile (FILE *fileHandle);
151 /*--------- functions ---------*/
156 printf("NAME:\n\tjavadeps - Examine Java class files and\n"
157 "\t\t\treturn information about their dependencies.\n\n");
159 printf("\t javadeps { --provides | --requires } \n"
160 "\t\t [--rpmformat] [--keywords] \n"
161 "\t\t [--] classfile-name ... \n\n"
162 "\t javadeps [--help]\n\n");
164 printf("DESCRIPTION:\n\n");
165 printf("List the dependencies or the fully qualified class names, of the \n"
166 "classfiles listed on the command line. \n\n");
167 printf("OPTIONS:\n\n");
168 printf("--requires For each class files listed in the arguments,\n"
169 " -r print the list of class files that would be\n"
170 " required to run these java programs. This does not \n"
171 " include anyting instantiated by reflection.\n\n");
172 printf("--provides For each class files listed in the arguments, \n"
173 " -p Print the fully qualified java classes,\n"
174 " that they provide.\n\n");
175 printf("--rpmformat format the output to match that used by RPM's \n"
176 " -F (Red Hat Package Manager) dependency analysis \n"
177 " database. The default is not --rpmformat.\n\n");
178 printf("--keywords Make use of any keywords embeded in the classfile.\n"
179 " -k The default is not --keyword.\n\n");
180 printf("--starprov Add the star notation provides to the provides list.\n"
181 " -s The default is not --starprov. This is only for use\n"
182 " with (Sun) jhtml dependencies, and since jhtml is \n"
183 " deprecated so is this option.\n\n");
184 printf("--help Display this page and exit.\n\n");
185 printf("-- This stops the processing of arguments, making it \n"
186 " easier for users to have filenames like '--keywords',\n"
187 " without the command line parser getting confused.\n\n");
189 printf("If any of the class file names in the argument list is '-' then\n"
190 "<stdin> will be read instead of reading from a file. The\n"
191 "contents of <stdin> should be the contents of a class file and \n"
192 "not a list of class files to read. It is assumed that when run \n"
193 "with '-', this program is in a pipeline preceeded by the \n"
194 "command 'unzip -p filename.jar' so that <stdin> may contain\n"
195 "the contents of several classfiles concatenated together.\n");
197 printf("If --keywords is specified then the following strings are \n"
198 "searched for (case insensitive) in the class file string table\n"
199 "and, if a string is found with a prefix matching the keyword then \n"
200 "the dependencies are changed accordingly. There may be multiple \n"
201 "string tables entries prefixed with RPM_Provides and RPM_Requires. \n"
202 "This would indicate that the dependency is the union\n"
206 "'$Revision: ' This RCS/CVS compatible keyword is assumed to \n"
207 " contain the version number of the class file \n"
208 " it is found in. Care should be taken with this\n"
209 " option as RPM's notion of which version is later\n"
210 " may not corrispond with your own, especially\n"
211 " if you use branches. This keyword\n"
212 " only effects the output of --provides and only\n"
213 " when RPM_Version is not defined.\n\n"
214 "'RPM_Version: ' This is an alternative method of specifing the\n"
215 " version number of the class. It will override\n"
216 " $Revision if set. This keyword only effects\n"
217 " the output of --provides \n\n"
218 "'RPM_Epoch: ' This string contains the epoch to use with the \n"
219 " version number stored in Revision. If not \n"
220 " specified, the epoch is assumed to be zero.\n"
221 " This keyword only effects the output of\n "
222 " --provides and only when $Revision number is\n"
224 "'RPM_Provides: ' This string lists additional capabilites\n"
225 " provided by the java class. The string should\n"
226 " be a white space ([\\t\\v\\n\\r\\f\\ ])\n"
227 " separated list of dependency strings. Each\n"
228 " dependency string must be of the same format as\n"
229 " would be valid in the Requires or Provides line\n"
230 " of the specfile. This keyword only effects the\n"
231 " output of --provides.\n\n"
232 "'RPM_Requires: ' This string lists additional requirements of\n"
233 " the java class. The string should be a white \n"
234 " space ([\\t\v\\n\\r\\f\\ ]) separated list of \n"
235 " dependency strings. Each dependency string must\n"
236 " be of the same format as would be valid in the \n"
237 " Requires or Provides line of the specfile. This\n"
238 " keyword only effects the output of --requires.\n "
240 "Note that there is no means of setting the release number. This\n"
241 "is necessary because release numbers are incremented when the\n"
242 "source does not change but the package needs to be rebuilt. So\n"
243 "relase numbers can not be stored in the source. The release is\n"
244 "assumed to be zero. \n\n"
246 printf("EXAMPLES (Java Keywords): \n\n"
247 "\t public static final String REVISION = \"$Revision: 2.8 $\";\n"
248 "\t public static final String EPOCH = \"4\";\n"
249 "\t public static final String REQUIRES = \"RPM_Requires: "
250 "java(gnu.regexp.RE) java(com.ibm.site.util.Options)>=1.5\";\n"
253 printf("EXAMPLES (Arguments): \n\n"
254 "\tjavadeps --requires -- filename.class\n\n"
255 "\tjavadeps --provides -- filename.class\n\n"
256 "\tjavadeps --help\n\n"
258 "\tjavadeps --requires --rpmformat --keywords -- filename.class\n\n"
259 "\tjavadeps --requires -- filename1.class filename2.class\n\n"
260 "\tcat filename2.class | javadeps --requires -- filename1.class -\n\n"
261 "\tunzip -p filename.jar | javadeps --requires -- - \n\n"
263 printf("This program is distributed with RPM the Redhat Package \n"
264 "Managment system. Further information about RPM can be found at \n"
265 "\thttp://www.rpm.org/\n\n");
271 void outofmemory(void) {
273 /* Its doubtful we could do a printf if there is really a memory
274 issue but at least halt the program */
276 fprintf(stderr, "Could not allocate memory");
281 void die(char *format, ...) {
282 /* Most errors are fatal.
283 This function throws a fatal error and
284 accepts arguments like printf does*/
286 char *newformat = NULL, *newmsg = NULL;
289 if ( !(newformat = malloc(1024)) || !(newmsg = malloc(1024)) )
292 /* Rewrite format line, to include additional information. The
293 format line we chose depends on how much information is availible
294 at the time of the error. Display the maximum ammount of
297 /* notice the FILE_NAME is useless for jar files. We would want to
298 print the name of the classfile which caused the error. That
299 is hard since we only know that name when we are done parsing
300 the file, and most errors will occur before that.*/
302 va_start(ap, format);
304 if ( (!FILE_NAME) ) {
306 sprintf (newformat, "\n%s: %s",
307 PROGRAM_NAME, format);
309 } else if ( (FILE_NAME) && (!CLASS_NAME) ) {
311 sprintf (newformat, "\n%s: Java classfile: %s, %s",
312 PROGRAM_NAME, FILE_NAME, format);
314 } else if (CLASS_NAME) {
315 sprintf (newformat, "\n%s: Java classfile: %s, classname: %s, %s",
316 PROGRAM_NAME, FILE_NAME, CLASS_NAME, format);
319 vsprintf (newmsg, newformat, ap);
321 /* print error to where it needs to go:
322 stdout, stderr, or syslog
325 fprintf(stderr, newmsg);
334 /* wrap fread for safety. It is a fatal error to get an unexpected
335 EOF inside a class file. */
337 size_t my_fread(void *ptr, size_t size, size_t nitems, FILE *stream) {
339 /*these variables are helpful in the debugger*/
344 rc = fread(ptr, size, nitems, stream);
345 if ( (size!=0) && (rc == 0) ) {
347 error = ferror(stream);
348 die("Error reading from file, or unexpected EOF\n");
354 void check_range(short value, short poolSize) {
356 if (value > poolSize) {
357 die("Value: %d, is out of range of the constant pool\n",
365 /* If lower case conversion of string is equal to pattern return a
366 pointer into string, just after the match. If the string does not
367 patch the pattern the null pointer is returned. This does not
370 This is similar to strcasecmp, but I expect my patterns to be a
371 prefix of my strings. */
374 *is_lower_equal (char *string, char *pattern)
377 while ( (tolower(*string) == *pattern) &&
378 *string && *pattern ) {
383 if ( *pattern == 0 ) {
392 Read fileHandle until we find the next instance of the Java
393 Classfile magic number indicating a java file or find EOF or
394 fileread error. Since we are reading from stdin which may contain
395 the concatination of many class files we can not be sure that the
396 magic number will be the first few bytes.
398 Return 1 on success 0 on failure. */
400 #define mod4(num) ( (num) & 3 )
403 int findJavaMagic (FILE *fileHandle)
409 /* what were looking for */
410 unsigned char magicInt[4] = {0xCA, 0xFE, 0xBA, 0xBE};
411 /*the hex reads in decimal: 202 254 186 190 */
413 /* a circular buffer indicating the last few bytes we read */
414 unsigned char buffer[4] = {0};
417 while( !foundMagic ) {
419 rc = fread(&buffer[offset], 1, 1, fileHandle);
422 /* Either this was not a java file or we were given a jar file
423 and have already found the last java file in it.*/
425 if ( feof(fileHandle) ) {
429 if ( ferror(fileHandle) ) {
430 die ("Error reading character from file.\n");
435 /* offset points to the most recent char we read so offest+1
436 points to the oldest char we saved. */
439 (magicInt[0] == buffer[mod4(offset+1)]) &&
440 (magicInt[1] == buffer[mod4(offset+2)]) &&
441 (magicInt[2] == buffer[mod4(offset+3)]) &&
442 (magicInt[3] == buffer[mod4(offset+0)]) &&
446 offset = mod4(offset+1);
457 my_strcmp (const void *a, const void *b) {
458 char **a1; char **b1;
463 ret = strcmp(*a1,*b1);
467 /* print the unique strings found in PRINT_TABLE and clear it out */
470 print_table_flush(void) {
474 if (!SIZE_PRINT_TABLE) {
478 /* The qsort line gives a warning on some unicies who insist that
479 strcmp takes arguments of type pointers to void not the
480 traditional pointers to char. */
482 qsort( (void *) PRINT_TABLE, (size_t) SIZE_PRINT_TABLE,
483 sizeof(char *), &my_strcmp);
485 printf("%s",PRINT_TABLE[0]);
486 last_string = PRINT_TABLE[0];
487 PRINT_TABLE[0] = NULL;
489 for (i = 1; i < SIZE_PRINT_TABLE; i++) {
490 if ( strcmp(last_string, PRINT_TABLE[i]) ){
491 printf("%s",PRINT_TABLE[i]);
493 last_string = PRINT_TABLE[i];
495 free(PRINT_TABLE[i]);
497 PRINT_TABLE[i] = NULL;
501 SIZE_PRINT_TABLE = 0;
506 /* add an element to PRINT_TABLE for later printing to stdout. We do
507 not make a copy of the string so each string must be unique,
508 (different calls must pass pointers to different areas of memory)
509 and the string must not be freed anywhere else in the code and the
510 string must be from memory which can be freed.*/
513 print_table_add(char *str) {
515 if (SIZE_PRINT_TABLE == MAX_PRINT_TABLE) {
519 PRINT_TABLE[SIZE_PRINT_TABLE] = str;
526 print_list(char *in_string) {
528 /* This function is no longer needed due to fixes in RPM's
529 processing of dependencies. Keep the code until I get a chance
530 to use RPM3.0 personally */
533 printf("%s\n", in_string);
539 Given a list separated by whitespace, put each element in the print
540 table with an added "\n" */
543 char *WhiteSpace_Set = "\t\v\n\r\f ";
544 char *newEnd, *out_string;
547 in_string += strspn(in_string, WhiteSpace_Set);
550 newEnd = strpbrk(in_string, WhiteSpace_Set);
553 copy_len = newEnd-in_string;
556 copy_len = strlen(in_string);
562 out_string = malloc(copy_len+10);
569 strncat(out_string, in_string, copy_len);
571 strcat(out_string, "\n");
572 print_table_add(out_string);
575 in_string += strspn(in_string+copy_len, WhiteSpace_Set);
583 /* Print a properly formatted java class name, and returns the length
584 of the class string . Do not print \n here as we may wish to
585 append the version number IFF we are printing the name of this classfile
587 We also provide the class with the leaf node replaced with '*'.
588 This would not be necessary if we only had to worry about java
589 Class files. However our parsing of jhtml files depends on this
590 information. This is deprecated since jhtml is deprecated and
591 this method allows for very inaccurate dependencies.
593 Also users may wish to refer to dependencies using star notation
594 (though this would be less accurate then explicit dependencies
595 since any leaf class will satify a star dependency). */
598 *formatClassName(char *in_string, char terminator,
601 char *leaf_class=0, *out_string=0;
602 char *ClassName_Break_Set=0;
605 out_string = malloc(strlen(in_string) + 10);
611 /*these characters end the current parse of the string in function
614 ClassName_Break_Set = malloc(3);
615 if ( !ClassName_Break_Set ) {
618 ClassName_Break_Set[0] = '/';
619 /*terminator can be '\0' this must go after '/'*/
620 ClassName_Break_Set[1] = terminator;
621 ClassName_Break_Set[2] = '\0';
624 strcat(out_string, "java(");
627 /* print the path to the leaf class but do not print the leaf
628 class, stop at the last '/' we fix this back below*/
629 leaf_class = strrchr(in_string, '/');
631 leaf_class[0] = terminator;
635 while (*in_string != terminator) {
639 /* handle the break_set */
641 if (in_string[0] == '\0' ) {
642 die("Classname does not terminate with: '%c', '%s'\n",
643 terminator, in_string);
645 if (in_string[0] == '/' ) {
646 /* convert '/' to '.' */
647 strcat(out_string, ".");
652 newEnd = strpbrk(in_string, ClassName_Break_Set);
655 copy_len = newEnd-in_string;
657 if (terminator == '\0') {
658 copy_len = strlen(in_string);
664 /* handle upto but not including the break_set*/
666 strncat(out_string, in_string, copy_len);
673 /* print the star and fix the leaf class*/
674 strcat(out_string, ".*");
678 strcat(out_string, ")");
681 strcat(out_string, "\n");
682 free(ClassName_Break_Set);
687 /* Parse out just the class names from a java type and moves the string
688 pointer to the end of the string. */
691 dumpRefType(char *string)
693 /* All class types start with a 'L' and and end with a ';'. We want
694 everyting in between. There might be more then one per string
695 like (params for a method call) */
697 string = strchr(string, 'L');
700 print_table_add(formatClassName(string, ';', 0));
701 string = strchr(string, ';');
702 string = strchr(string, 'L');
709 /* Print out the classes referenced in the symbol table */
712 dumpRequires(symbolTable_t *symbolTable) {
716 for(tem=1; tem < symbolTable->poolSize; tem++ ) {
718 /* dump all the classes in the const table. */
719 ref = symbolTable->classRef[tem];
721 char *string = symbolTable->stringList[ref];
723 die("class num: %d, referenced string num: %d, "
727 if ( string[0] == '[' ) {
729 This is an array. We need to ingore
735 This hack leaves blank lines in the output
736 when a string not containing a class is
739 string = strchr(string, 'L');
744 print_table_add(formatClassName(string, '\0', 0));
748 /* dump all the references */
749 ref = symbolTable->typeRef[tem];
751 char *string = symbolTable->stringList[ref];
753 die("type num: %d, referenced string num: %d, "
757 /* this is a java type... parse out the class names */
767 /* Read a java class files symbol table into memory.
769 Find the proper name of the current Java Class file.
770 Print it regardless of: --provides | --requires
774 void genSymbolTable (FILE *fileHandle, symbolTable_t *symbolTable)
780 /* We are called just after fileHandle saw the magic number, seek a
781 few bytes in to find the poolsize */
783 my_fread(&ignore, 4, 1, fileHandle);
785 my_fread(&(symbolTable->poolSize), 2, 1, fileHandle);
789 symbolTable->stringList = (char**) calloc(symbolTable->poolSize,
791 if(!symbolTable->stringList){
795 symbolTable->classRef = (short*) calloc(symbolTable->poolSize,
797 if(!symbolTable->classRef){
801 symbolTable->typeRef = (short*) calloc(symbolTable->poolSize,
803 if(!symbolTable->typeRef){
807 /* zero 'em all out. */
808 for(i=0; i < symbolTable->poolSize; i++) {
809 symbolTable->stringList[i] = NULL;
810 symbolTable->classRef[i] = 0;
811 symbolTable->typeRef[i] = 0;
815 /* for the number of entries
819 for(i=1; i < symbolTable->poolSize; i++) {
820 unsigned short type = 0;
821 unsigned short value = 0;
822 unsigned char tag = 0;
824 /* read the type of this entry */
826 my_fread(&tag, 1, 1, fileHandle);
828 case 1: /* master string pool. */
830 /* record all these strings */
832 unsigned short length = 0;
834 /* I am not sure if these strings must be null
835 terminated. I termiante them to be safe. */
837 my_fread(&length, 2, 1, fileHandle);
838 someString = (char*) malloc(length+1);
842 my_fread(someString, length, 1, fileHandle);
843 someString[length]=0;
844 symbolTable->stringList[i] = someString;
849 /* Each keyword can appear multiple times. Don't
850 bother with datastructures to store these strings,
851 if we need to print it print it now. */
853 /* it would be better if instead of printing the
854 strings "raw" I turn the space separated list
855 into a "\n" separated list*/
858 ptr = is_lower_equal(someString, "rpm_requires: ");
864 ptr = is_lower_equal(someString, "rpm_provides: ");
869 /* I wish there was a good way to handle this
870 ptr = is_lower_equal(someString, "rpm_conflicts: ");
872 ptr = is_lower_equal(someString, "$revision: ");
874 KEYWORD_REVISION=ptr;
875 /* terminate the string before " $" */
876 ptr = strchr(KEYWORD_REVISION, ' ');
881 ptr = is_lower_equal(someString, "rpm_version: ");
884 /* terminate the string at first whitespace */
885 ptr = strchr(KEYWORD_VERSION, ' ');
890 ptr = is_lower_equal(someString, "rpm_epoch: ");
893 /* terminate the string at first whitespace */
894 ptr = strchr(KEYWORD_EPOCH, ' ');
902 case 2: /* unknow type!! */
903 die("Unknown type in constant table. "
907 my_fread(&ignore, 4, 1, fileHandle);
910 my_fread(&ignore, 4, 1, fileHandle);
912 case 5: /* long (counts as 2) */
913 my_fread(&ignore, 8, 1, fileHandle);
916 case 6: /* double (counts as 2) */
917 my_fread(&ignore, 8, 1, fileHandle);
921 my_fread(&value, 2, 1, fileHandle);
922 /* record which const it's referencing */
923 check_range(value, symbolTable->poolSize);
924 symbolTable->classRef[i]=value;
927 my_fread(&ignore, 2, 1, fileHandle);
929 case 9: /* field reference */
930 my_fread(&ignore, 4, 1, fileHandle);
932 case 10: /* method reference */
933 my_fread(&ignore, 4, 1, fileHandle);
935 case 11: /* interface method reference */
936 my_fread(&ignore, 4, 1, fileHandle);
938 case 12: /* constant name/type */
939 my_fread(&ignore, 2, 1, fileHandle);
940 my_fread(&type, 2, 1, fileHandle);
941 /* record the name, and the type it's referencing. */
942 check_range(type, symbolTable->poolSize);
943 symbolTable->typeRef[i]=type;
946 die("Unknown tag type: %d.\n",
947 "Entry: %d. \n", tag, i);
957 Find the proper name of the current Java Class file.
958 Print it regardless of: --provides | --requires
962 findClassName (FILE *fileHandle, symbolTable_t *symbolTable) {
964 unsigned short type = 0;
965 unsigned short class = 0;
969 /* seek a little past the end of the table */
971 my_fread(&ignore, 2, 1, fileHandle);
973 /* read the name of this classfile */
975 my_fread(&type, 2, 1, fileHandle);
976 class = symbolTable->classRef[type];
978 !symbolTable->stringList[class] ) {
979 die("Couln't find class: %d, provided by file.\n", class);
981 CLASS_NAME=symbolTable->stringList[class];
983 out_string = formatClassName(symbolTable->stringList[class], '\0', 0);
989 len += strlen(out_string);
992 len += strlen(KEYWORD_EPOCH);
994 if (KEYWORD_VERSION) {
995 len += strlen(KEYWORD_VERSION);
997 if (KEYWORD_REVISION) {
998 len += strlen(KEYWORD_REVISION);
1001 out_string = realloc(out_string, len );
1008 if( KEYWORD_VERSION || KEYWORD_REVISION ){
1009 /* It is easier to remove the extra new line here in one place
1010 then to try and add a newline every where that formatClassName
1014 /* I am not using rpm 3.0 yet so I need both the dependencies with
1015 and without the version numbers, when I upgrade I will remove
1016 this block (with copy_string) and change the "=" to " = " ten
1020 copy_string = (char*) malloc(strlen(out_string));
1024 copy_string = strcpy(copy_string, out_string);
1025 print_table_add(copy_string);
1028 newline = strrchr(out_string, '\n');
1032 strcat(out_string, " = ");
1034 strcat(out_string, KEYWORD_EPOCH);
1035 strcat(out_string, ":");
1037 if(KEYWORD_VERSION){
1038 strcat(out_string, KEYWORD_VERSION);
1040 strcat(out_string, KEYWORD_REVISION);
1042 strcat(out_string, "\n");
1045 print_table_add(out_string);
1048 /* Provide the star version of this class for jhtml
1049 dependencies. This option is deprecated since jhtml is
1053 out_string = formatClassName(symbolTable->stringList[class], '\0', 1);
1054 print_table_add(out_string);
1064 void freeSymbolTable (symbolTable_t *symbolTable)
1068 for(i=1; i < symbolTable->poolSize; i++) {
1069 if( symbolTable->stringList[i] ) {
1070 free(symbolTable->stringList[i]);
1071 symbolTable->stringList[i] = 0;
1075 free(symbolTable->stringList);
1076 symbolTable->stringList=0;
1078 free(symbolTable->classRef);
1079 symbolTable->classRef=0;
1081 free(symbolTable->typeRef);
1082 symbolTable->typeRef=0;
1091 /* process each file,
1092 must be called directly after finding
1096 void processJavaFile (FILE *fileHandle) {
1097 symbolTable_t symbolTable= {0};
1099 genSymbolTable(fileHandle, &symbolTable);
1100 findClassName(fileHandle, &symbolTable);
1103 dumpRequires(&symbolTable);
1106 freeSymbolTable(&symbolTable);
1114 main(int argc, char **argv)
1121 PROGRAM_NAME=argv[0];
1123 if(argv[1] == NULL) {
1127 /* parse arguments which are not filenames*/
1129 for (i = 1; argv[i] != NULL; i++) {
1133 First entry a dummy to get the
1134 other entries to align correctly
1137 } else if ( !strcmp("-p",argv[i]) || !strcmp("--provides",argv[i]) ) {
1139 } else if ( !strcmp("-r",argv[i]) || !strcmp("--requires",argv[i]) ) {
1141 } else if ( !strcmp("-h",argv[i]) || !strcmp("--help",argv[i]) ||
1142 !strcmp("-?",argv[i]) ) {
1145 } else if ( !strcmp("-F",argv[i]) || !strcmp("--rpmformat",argv[i]) ) {
1147 } else if ( !strcmp("-k",argv[i]) || !strcmp("--keywords",argv[i]) ) {
1149 } else if ( !strcmp("-s",argv[i]) || !strcmp("--starprov",argv[i]) ) {
1151 } else if ( !strcmp("--",argv[i]) ) {
1155 /* we do not recognize the argument, must be a filename*/
1158 } /*end for arguments which are not filenames*/
1160 /* check arguments for consistancy */
1162 if ( !ARG_PROVIDES && !ARG_REQUIRES ) {
1163 die ("Must specify either --provides or --requires.\n");
1166 if ( ARG_PROVIDES && ARG_REQUIRES ) {
1167 die ("Can not specify both --provides and --requires.\n");
1170 if ( ARG_REQUIRES && ARG_STARPROV) {
1171 die ("Can not specify both --requires and --starpov.\n");
1174 if(argv[i] == NULL) {
1175 die ("Must specify Java class files.\n");
1178 /* parse arguments which are filenames. */
1180 for ( /*null initializer*/; argv[i] != NULL; i++) {
1182 /*open the correct file and process it*/
1184 if ( !strcmp("-", argv[i]) ) {
1185 /* use stdin, might be a jar file */
1187 FILE_NAME = "<stdin>";
1189 foundMagic = findJavaMagic(fileHandle);
1190 while (foundMagic) {
1191 processJavaFile(fileHandle);
1192 foundMagic = findJavaMagic(fileHandle);
1195 /* Open a disk file*/
1196 fileHandle = fopen(argv[i], "r");
1197 if( fileHandle == 0 ) {
1198 die ("Could not open file: %s.\n", argv[i]);
1200 fileHandle = fileHandle;
1201 FILE_NAME = argv[i];
1203 foundMagic = findJavaMagic(fileHandle);
1205 processJavaFile(fileHandle);
1209 rc = fclose(fileHandle);
1211 die ("Could not close file: %s.\n", FILE_NAME);
1214 } /*end parsing arguments which are filenames*/
1216 print_table_flush();