OOO330
[LibreOffice.git] / soltools / javadep / javadep.c
bloba573d78eed75a287be8f5ebd9947a5fe5f9d5c50
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 /* All Java Virtual Machine Specs are from
29 * "The Java Virtual Machine Specification", T. Lindholm, F. Yellin
30 * (JVMS)
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <ctype.h>
39 #include <limits.h>
41 #if defined(UNX) || defined(OS2)
42 #include <unistd.h>
43 #include <netinet/in.h> /* ntohl(), ntohs() */
44 #elif defined(WNT)
45 #include <io.h>
46 #define access _access
47 #define vsnprintf _vsnprintf
48 #define CDECL _cdecl
49 #define F_OK 00
50 #define PATH_MAX _MAX_PATH
51 #define ntohl(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
52 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
54 #define ntohs(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
55 #endif
57 #if defined(OS2)
58 #define CDECL
59 #endif
61 /* max. length of line in response file */
62 #define RES_FILE_BUF 65536
64 struct file {
65 char *pname;
66 FILE *pfs;
69 struct growable {
70 int ncur;
71 int nmax;
72 char **parray;
75 typedef struct file file_t;
76 typedef unsigned char uint8;
77 typedef unsigned short uint16;
78 typedef unsigned int uint32;
80 struct utf8 {
81 uint16 nlen;
82 void *pdata;
85 typedef struct utf8 utf8_t;
87 /* The contents of the Constant_pool is described in JVMS p. 93
89 enum {
90 CONSTANT_Class = 7,
91 CONSTANT_Fieldref = 9,
92 CONSTANT_Methodref = 10,
93 CONSTANT_InterfaceMethodref = 11,
94 CONSTANT_String = 8,
95 CONSTANT_Integer = 3,
96 CONSTANT_Float = 4,
97 CONSTANT_Long = 5,
98 CONSTANT_Double = 6,
99 CONSTANT_NameAndType = 12,
100 CONSTANT_Utf8 = 1
103 enum { NGROW_INIT = 10, NGROW = 2 };
105 static char *pprogname = "javadep";
106 static char csep = ';';
107 #if defined (UNX) || defined(OS2)
108 #define CDECL
109 static char cpathsep = '/';
110 #elif defined (WNT) || defined(OS2)
111 static char cpathsep = '\\';
112 #endif
113 static FILE *pfsout = NULL;
114 static char *pout_file = NULL;
117 /* prototypes */
118 uint8 read_uint8(const file_t *pfile);
119 uint16 read_uint16(const file_t *pfile);
120 uint32 read_uint32(const file_t *pfile);
121 void skip_bytes(const file_t *pfile, const size_t nnum);
122 char *escape_slash(const char *pstr);
123 int is_inner(const char *pstr);
124 void print_dependencies(const struct growable *pdep,
125 const char* pclass_file);
126 void process_class_file(const char *pfilenamem,
127 const struct growable *pfilt);
128 char *utf8tolatin1(const utf8_t a_utf8);
129 void *xmalloc(size_t size);
130 void *xcalloc(size_t nmemb, size_t size);
131 void *xrealloc(void *ptr, size_t size);
132 void grow_if_needed (struct growable *pgrow);
133 int append_to_growable(struct growable *, char *);
134 struct growable *allocate_growable(void);
135 void free_growable(struct growable *pgrowvoid);
136 void create_filters(struct growable *pfilt, const struct growable *pinc);
137 void usage(void);
138 void err_quit(const char *, ...);
139 void silent_quit(void);
141 #ifdef WNT
142 /* poor man's getopt() */
143 int simple_getopt(char *pargv[], const char *poptstring);
144 char *optarg = NULL;
145 int optind = 1;
146 int optopt = 0;
147 int opterr = 0;
148 #endif
150 uint8
151 read_uint8(const file_t *pfile)
153 /* read a byte from classfile */
154 int nread;
155 uint8 ndata;
156 nread = fread(&ndata, sizeof(uint8), 1, pfile->pfs);
157 if ( !nread ) {
158 fclose(pfile->pfs);
159 err_quit("%s: truncated class file", pfile->pname);
161 return ndata;
164 uint16
165 read_uint16(const file_t *pfile)
167 /* read a short from classfile and convert it to host format */
168 int nread;
169 uint16 ndata;
170 nread = fread(&ndata, sizeof(uint16), 1, pfile->pfs);
171 if ( !nread ) {
172 fclose(pfile->pfs);
173 err_quit("%s: truncated class file", pfile->pname);
175 ndata = ntohs(ndata);
176 return ndata;
179 uint32
180 read_uint32(const file_t *pfile)
182 /* read an int from classfile and convert it to host format */
183 int nread;
184 uint32 ndata;
185 nread = fread(&ndata, sizeof(uint32), 1, pfile->pfs);
186 if ( !nread ) {
187 fclose(pfile->pfs);
188 err_quit("%s: truncated class file", pfile->pname);
190 ndata = ntohl(ndata);
191 return ndata;
194 utf8_t
195 read_utf8(const file_t *pfile)
197 /* Read a java utf-8-string with uint16 length prependend
198 * from class file. Returns utf8 struct
199 * with fresh allocated datablock,
200 * caller is responsible for freeing.
201 * Data is still in network byteorder
204 utf8_t a_utf8;
205 int nread;
207 a_utf8.pdata = NULL;
209 a_utf8.nlen = read_uint16(pfile);
210 if (a_utf8.nlen > 0) {
211 a_utf8.pdata = xmalloc(a_utf8.nlen*sizeof(char));
212 nread = fread(a_utf8.pdata, a_utf8.nlen*sizeof(char), 1, pfile->pfs);
213 if ( !nread ) {
214 fclose(pfile->pfs);
215 err_quit("%s: truncated class file", pfile->pname);
219 return a_utf8;
222 char *utf8tolatin1(const utf8_t a_utf8)
224 /* function returns fresh allocated zero terminated string,
225 * caller is responsible for freeing
228 /* JVMS p. 101: the null byte is encoded using a two byte format,
229 * Java Virtual Machine Utf8 strings differ in this respect from
230 * standard UTF-8 strings
233 /* Multibyte data is in network byte order */
235 char *p;
236 char *pp;
237 char *pstr;
239 pstr = pp = xmalloc((a_utf8.nlen+1) * sizeof(char));
241 for ( p = (char*)a_utf8.pdata;
242 p < (char*)a_utf8.pdata+a_utf8.nlen;
243 p++ ) {
244 if ( *p & 0x80 ) {
245 err_quit("sorry, real UTF8 decoding not yet implemented\n");
246 } else {
247 *pp++ = *p;
250 *pp = '\0';
252 return pstr;
256 void
257 skip_bytes(const file_t *pfile, const size_t nnumber)
259 /* skip a nnumber of bytes in classfile */
260 if ( fseek(pfile->pfs, nnumber, SEEK_CUR) == -1 )
261 err_quit("%s: %s", pfile->pname, strerror(errno));
264 void
265 add_to_dependencies(struct growable *pdep,
266 const struct growable *pfilt,
267 char *pdepstr,
268 const char *pclass_file)
270 /* create dependencies */
271 int i;
272 int nlen_filt, nlen_str, nlen_pdepstr;
273 char *pstr, *ptrunc;
274 char path[PATH_MAX+1];
275 char cnp_class_file[PATH_MAX+1];
276 char cnp_str[PATH_MAX+1];
278 nlen_pdepstr = strlen(pdepstr);
279 pstr = xmalloc((nlen_pdepstr+6+1)*sizeof(char));
280 memcpy(pstr, pdepstr, nlen_pdepstr+1);
281 strncat(pstr, ".class", 6);
283 if ( pfilt->ncur == 0 ) { /* no filters */
284 if ( access(pstr, F_OK) == 0 ) {
285 append_to_growable(pdep, strdup(pstr));
287 } else {
288 nlen_str = strlen(pstr);
289 for ( i = 0; i < pfilt->ncur; i++ ) {
290 nlen_filt = strlen(pfilt->parray[i]);
291 if ( nlen_filt + 1 + nlen_str > PATH_MAX )
292 err_quit("path to long");
293 memcpy(path, pfilt->parray[i], nlen_filt);
294 path[nlen_filt] = '/';
295 memcpy( path+nlen_filt+1, pstr, nlen_str+1);
297 if ( access(path, F_OK) != 0 ) {
298 free(pstr);
299 pstr = NULL;
300 return; /* path doesn't represent a real file, don't bother */
303 /* get the canonical path */
304 #if defined (UNX) || defined(OS2)
305 if ( !(realpath(pclass_file, cnp_class_file)
306 && realpath(path, cnp_str) ) ) {
307 err_quit("can't get the canonical path");
309 #else
310 if ( !(_fullpath(cnp_class_file, pclass_file, sizeof(cnp_class_file))
311 && _fullpath(cnp_str, path, sizeof(cnp_str)) ) ) {
312 err_quit("can't get the canonical path");
314 #endif
316 /* truncate so that only the package prefix remains */
317 ptrunc = strrchr(cnp_str, cpathsep);
318 *ptrunc = '\0';
319 ptrunc = strrchr(cnp_class_file, cpathsep);
320 *ptrunc = '\0';
322 if ( !strcmp(cnp_str, cnp_class_file) ) {
323 free(pstr);
324 pstr = NULL;
325 return; /* identical, don't bother with this one */
328 append_to_growable(pdep, strdup(path));
331 free(pstr);
332 return;
335 char *
336 escape_slash(const char *pstr)
338 /* returns a fresh allocated string with all cpathsep escaped exchanged
339 * with "$/"
341 * caller is responsible for freeing
344 const char *pp = pstr;
345 char *p, *pnp;
346 char *pnew_str;
347 int nlen_pnp, nlen_pp;
348 int i = 0;
350 while ( (p=strchr(pp, cpathsep)) != NULL ) {
351 ++i;
352 pp = ++p;
355 nlen_pnp = strlen(pstr) + i;
356 pnp = pnew_str = xmalloc((nlen_pnp+1) * sizeof(char));
358 pp = pstr;
360 if ( i > 0 ) {
361 while ( (p=strchr(pp, cpathsep)) != NULL ) {
362 memcpy(pnp, pp, p-pp);
363 pnp += p-pp;
364 *pnp++ = '$';
365 *pnp++ = '/';
366 pp = ++p;
369 nlen_pp = strlen(pp);
370 memcpy(pnp, pp, nlen_pp+1);
372 return pnew_str;
376 void
377 print_dependencies(const struct growable *pdep, const char* pclass_file)
379 char *pstr;
380 int i;
382 pstr = escape_slash(pclass_file);
383 fprintf(pfsout, "%s:", pstr);
384 free(pstr);
386 for( i=0; i<pdep->ncur; ++i) {
387 fprintf(pfsout, " \\\n");
388 pstr=escape_slash(pdep->parray[i]);
389 fprintf(pfsout, "\t%s", pstr);
390 free(pstr);
393 fprintf(pfsout,"\n\n");
394 return;
398 is_inner(const char *pstr)
400 /* return true if character '$' is found in classname */
403 * note that a '$' in a classname is not an exact indicator
404 * for an inner class. Java identifier may legally contain
405 * this chararcter, and so may classnames. In the context
406 * of javadep this doesn't matter since the makefile system
407 * can't cope with classfiles with '$'s in the filename
408 * anyway.
412 if ( strchr(pstr, '$') != NULL )
413 return 1;
415 return 0;
418 void
419 process_class_file(const char *pfilename, const struct growable *pfilt)
421 /* read class file and extract object information
422 * java class files are in bigendian data format
423 * (JVMS, p. 83)
425 int i;
426 uint32 nmagic;
427 uint16 nminor, nmajor;
428 uint16 ncnt;
429 uint16 nclass_cnt;
430 utf8_t* pc_pool;
431 uint16* pc_class;
432 file_t file;
434 struct growable *pdepen;
436 file.pname = (char*)pfilename;
438 file.pfs = fopen(file.pname,"rb");
439 if ( !file.pfs )
440 silent_quit();
442 nmagic = read_uint32(&file);
444 if ( nmagic != 0xCAFEBABE ) {
445 fclose(file.pfs);
446 err_quit("%s: invalid magic", file.pname);
449 nminor = read_uint16(&file);
450 nmajor = read_uint16(&file);
452 /* get number of entries in constant pool */
453 ncnt = read_uint16(&file);
455 #ifdef DEBUG
456 printf("Magic: %p\n", (void*)nmagic);
457 printf("Major %d, Minor %d\n", nmajor, nminor);
458 printf("Const_pool_count %d\n", ncnt);
459 #endif
461 /* There can be ncount entries in the constant_pool table
462 * so at most ncount-1 of them can be of type CONSTANT_Class
463 * (at leat one CONSTANT_Utf8 entry must exist).
464 * Usually way less CONSTANT_Class entries exists, of course
467 pc_pool = xcalloc(ncnt,sizeof(utf8_t));
468 pc_class = xmalloc((ncnt-1)*sizeof(uint16));
470 /* pc_pool[0] is reserved to the java virtual machine and does
471 * not exist in the class file
474 nclass_cnt = 0;
476 for (i = 1; i < ncnt; i++) {
477 uint8 ntag;
478 uint16 nindex;
479 utf8_t a_utf8;
481 ntag = read_uint8(&file);
483 /* we are only interested in CONSTANT_Class entries and
484 * Utf8 string entries, because they might belong to
485 * CONSTANT_Class entries
487 switch(ntag) {
488 case CONSTANT_Class:
489 nindex = read_uint16(&file);
490 pc_class[nclass_cnt++] = nindex;
491 break;
492 case CONSTANT_Fieldref:
493 case CONSTANT_Methodref:
494 case CONSTANT_InterfaceMethodref:
495 skip_bytes(&file, 4L);
496 break;
497 case CONSTANT_String:
498 skip_bytes(&file, 2L);
499 break;
500 case CONSTANT_Integer:
501 case CONSTANT_Float:
502 skip_bytes(&file, 4L);
503 break;
504 case CONSTANT_Long:
505 case CONSTANT_Double:
506 skip_bytes(&file, 8L);
507 /* Long and Doubles take 2(!)
508 * entries in constant_pool_table
510 i++;
511 break;
512 case CONSTANT_NameAndType:
513 skip_bytes(&file, 4L);
514 break;
515 case CONSTANT_Utf8:
516 a_utf8 = read_utf8(&file);
517 pc_pool[i] = a_utf8;
518 break;
519 default:
520 /* Unknown Constant_pool entry, this means we are
521 * in trouble
523 err_quit("corrupted class file\n");
524 break;
529 fclose(file.pfs);
531 pdepen = allocate_growable();
533 for (i = 0; i < nclass_cnt; i++) {
534 char *pstr, *ptmpstr;
535 pstr = ptmpstr = utf8tolatin1(pc_pool[pc_class[i]]);
536 /* we are not interested in inner classes */
537 if ( is_inner(pstr) ) {
538 free(pstr);
539 pstr = NULL;
540 continue;
542 /* strip off evt. array indicators */
543 if ( *ptmpstr == '[' ) {
544 while ( *ptmpstr == '[' )
545 ptmpstr++;
546 /* we only interested in obj. arrays, which are marked with 'L' */
547 if ( *ptmpstr == 'L' ) {
548 char *p = pstr;
549 pstr = strdup(++ptmpstr);
550 /* remove final ';' from object array name */
551 pstr[strlen(pstr)-1] = '\0';
552 free(p);
553 } else {
554 free(pstr);
555 pstr = NULL;
559 if (pstr) {
560 add_to_dependencies(pdepen, pfilt, pstr, file.pname);
561 free(pstr);
565 print_dependencies(pdepen, file.pname);
566 free_growable(pdepen);
567 pdepen = NULL;
569 for (i = 0; i < ncnt; i++)
570 free(pc_pool[i].pdata);
572 free(pc_class);
573 free(pc_pool);
576 void *
577 xmalloc(size_t size)
579 void *ptr;
581 ptr = malloc(size);
583 if ( !ptr )
584 err_quit("out of memory");
586 return ptr;
590 void *
591 xcalloc(size_t nmemb, size_t size)
593 void *ptr;
595 ptr = calloc(nmemb, size);
597 if ( !ptr )
598 err_quit("out of memory");
600 return ptr;
603 void *
604 xrealloc(void *ptr, size_t size)
606 ptr = realloc(ptr, size);
608 if ( !ptr )
609 err_quit("out of memory");
611 return ptr;
614 void
615 err_quit(const char* fmt, ...)
617 /* No dependency file must be generated for any error condition,
618 * just print message and exit.
620 va_list args;
621 char buffer[PATH_MAX];
623 va_start(args, fmt);
625 if ( pprogname )
626 fprintf(stderr, "%s: ", pprogname);
627 vsnprintf(buffer, sizeof(buffer), fmt, args);
628 fputs(buffer, stderr);
629 fputc('\n', stderr);
631 va_end(args);
633 /* clean up */
634 if ( pfsout && pfsout != stdout ) {
635 fclose(pfsout);
636 unlink(pout_file);
638 exit(1);
641 void
642 silent_quit()
644 /* In some cases we should just do a silent exit */
646 /* clean up */
647 if ( pfsout && pfsout != stdout ) {
648 fclose(pfsout);
649 unlink(pout_file);
651 exit(0);
654 int append_to_growable(struct growable *pgrow, char *pstr)
656 /* append an element pstr to pgrow,
657 * return new number of elements
659 grow_if_needed(pgrow);
660 pgrow->parray[pgrow->ncur++] = pstr;
661 return pgrow->ncur;
664 void
665 grow_if_needed(struct growable *pgrow)
667 /* grow growable arrays */
669 if ( pgrow->ncur >= pgrow->nmax ) {
670 pgrow->parray = xrealloc(pgrow->parray,
671 (NGROW*pgrow->nmax)*sizeof(char*));
672 pgrow->nmax *= NGROW;
674 return;
677 struct growable *allocate_growable(void)
679 /* allocate an growable array,
680 * initialize with NGROW_INIT elements
683 struct growable *pgrow;
685 pgrow = xmalloc(sizeof(struct growable));
686 pgrow->parray = xmalloc(NGROW_INIT*sizeof(char *));
687 pgrow->nmax = NGROW_INIT;
688 pgrow->ncur = 0;
689 return pgrow;
692 void
693 free_growable(struct growable *pgrow)
695 int i;
696 for( i = 0; i < pgrow->ncur; i++ )
697 free(pgrow->parray[i]);
698 free(pgrow->parray);
699 free(pgrow);
702 void
703 create_filters(struct growable *pfilt, const struct growable *pinc)
705 char *p, *pp, *pstr;
706 int i, nlen, nlen_pstr;
707 /* break up includes into filter list */
708 for ( i = 0; i < pinc->ncur; i++ ) {
709 pp = pinc->parray[i];
711 while ( (p = strchr(pp, csep)) != NULL) {
712 nlen = p - pp;
713 pstr = xmalloc((nlen+1)*sizeof(char*));
714 memcpy(pstr, pp, nlen);
715 pstr[nlen] = '\0';
716 append_to_growable(pfilt, pstr);
717 pp = p + 1;
719 nlen_pstr = strlen(pp);
720 pstr = xmalloc((nlen_pstr+1)*sizeof(char*));
721 memcpy(pstr, pp, nlen_pstr+1);
722 append_to_growable(pfilt, pstr);
727 void
728 usage()
730 fprintf(stderr,
731 "usage: %s [-i|-I includepath ... -s|-S seperator "
732 "-o|-O outpath -v|-V -h|-H] <file> ....\n",
733 pprogname);
736 /* my very simple minded implementation of getopt()
737 * it's to sad that getopt() is not available everywhere
738 * note: this is not a full POSIX conforming getopt()
740 int simple_getopt(char *pargv[], const char *poptstring)
742 char *parg = pargv[optind];
744 /* skip all response file arguments */
745 if ( parg ) {
746 while ( *parg == '@' )
747 parg = pargv[++optind];
749 if ( parg[0] == '-' && parg[1] != '\0' ) {
750 char *popt;
751 int c = parg[1];
752 if ( (popt = strchr(poptstring, c)) == NULL ) {
753 optopt = c;
754 if ( opterr )
755 fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
756 return '?';
758 if ( *(++popt) == ':') {
759 if ( parg[2] != '\0' ) {
760 optarg = ++parg;
761 } else {
762 optarg = pargv[++optind];
764 } else {
765 optarg = NULL;
767 ++optind;
768 return c;
771 return -1;
774 int CDECL
775 main(int argc, char *argv[])
777 int bv_flag = 0;
778 struct growable *presp, *pincs, *pfilters;
779 int c, i, nall_argc;
780 char **pall_argv;
782 presp = allocate_growable();
784 /* FIXME: cleanup the option parsing */
785 /* search for response file, read it */
786 for ( i = 1; i < argc; i++ ) {
787 char *parg = argv[i];
788 char buffer[RES_FILE_BUF];
790 if ( *parg == '@' ) {
791 FILE *pfile = fopen(++parg, "r");
792 if ( !pfile )
793 err_quit("%s: %s", parg, strerror(errno));
794 while ( !feof(pfile) ) {
795 char *p, *token;
797 if ( fgets(buffer, RES_FILE_BUF, pfile) ) {;
798 p = buffer;
799 while ( (token = strtok(p, " \t\n")) != NULL ) {
800 p = NULL;
801 append_to_growable(presp, strdup(token));
805 fclose(pfile);
809 /* copy all arguments incl. response file in one array
810 * for parsing with getopt
812 nall_argc = argc + presp->ncur;
813 pall_argv = xmalloc((nall_argc+1)*sizeof(char *));
814 memcpy(pall_argv, argv, argc*sizeof(char *));
815 memcpy(pall_argv+argc, presp->parray, presp->ncur*sizeof(char *));
816 *(pall_argv+argc+presp->ncur) = '\0'; /* terminate */
818 opterr = 0;
819 pincs = allocate_growable();
821 #ifdef WNT
822 while( (c = simple_getopt(pall_argv, ":i:I:s:S:o:OhHvV")) != -1 ) {
823 #else
824 while( (c = getopt(nall_argc, pall_argv, ":i:I:s:S:o:OhHvV")) != -1 ) {
825 #endif
826 switch(c) {
827 case 'i':
828 case 'I':
829 append_to_growable(pincs, strdup(optarg));
830 break;
831 case 's':
832 case 'S':
833 csep = optarg[0];
834 break;
835 case 'o':
836 case 'O':
837 pout_file = optarg;
838 break;
839 case 'h':
840 case 'H':
841 usage();
842 return 0;
843 break;
844 case 'v':
845 case 'V':
846 bv_flag = 1;
847 break;
848 case '?':
849 if (isprint (optopt))
850 fprintf (stderr,
851 "Unknown option `-%c'.\n", optopt);
852 else
853 fprintf (stderr,
854 "Unknown option character `\\x%x'.\n",
855 optopt);
856 usage();
857 return 1;
858 break;
859 case ':':
860 fprintf(stderr, "Missing parameter.\n");
861 usage();
862 return 1;
863 break;
864 default:
865 usage();
866 return 1;
867 break;
871 pfilters = allocate_growable();
872 create_filters(pfilters, pincs);
873 free_growable(pincs);
874 pincs = NULL;
876 if ( pout_file ) {
877 pfsout = fopen(pout_file, "w");
878 if ( !pfsout )
879 err_quit("%s: %s", pout_file, strerror(errno));
880 } else {
881 pfsout = stdout;
884 /* the remaining arguments are either class file
885 * names or response files, ignore response file
886 * since they have already been included
888 for ( i = optind; i < nall_argc; i++ ) {
889 char *parg = pall_argv[i];
890 if ( *parg != '@' ) {
891 process_class_file(parg, pfilters);
892 if ( pfsout != stdout ) {
893 if ( bv_flag )
894 printf("Processed %s ...\n", parg);
899 free_growable(pfilters);
900 pfilters = NULL;
901 free(pall_argv);
902 pall_argv = NULL;
903 free_growable(presp);
904 presp = NULL;
906 fclose(pfsout);
907 exit(0);