update dev300-m57
[ooovba.git] / soltools / javadep / javadep.c
bloba742c4ac8d3beaf3048c144c7e3de63196efe3be
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: javadep.c,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 /* All Java Virtual Machine Specs are from
32 * "The Java Virtual Machine Specification", T. Lindholm, F. Yellin
33 * (JVMS)
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <ctype.h>
42 #include <limits.h>
44 #if defined(UNX) || defined(OS2)
45 #include <unistd.h>
46 #include <netinet/in.h> /* ntohl(), ntohs() */
47 #elif defined(WNT)
48 #include <io.h>
49 #define access _access
50 #define vsnprintf _vsnprintf
51 #define CDECL _cdecl
52 #define F_OK 00
53 #define PATH_MAX _MAX_PATH
54 #define ntohl(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
55 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
57 #define ntohs(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
58 #endif
60 #if defined(OS2)
61 #define CDECL
62 #endif
64 /* max. length of line in response file */
65 #define RES_FILE_BUF 65536
67 struct file {
68 char *pname;
69 FILE *pfs;
72 struct growable {
73 int ncur;
74 int nmax;
75 char **parray;
78 typedef struct file file_t;
79 typedef unsigned char uint8;
80 typedef unsigned short uint16;
81 typedef unsigned int uint32;
83 struct utf8 {
84 uint16 nlen;
85 void *pdata;
88 typedef struct utf8 utf8_t;
90 /* The contents of the Constant_pool is described in JVMS p. 93
92 enum {
93 CONSTANT_Class = 7,
94 CONSTANT_Fieldref = 9,
95 CONSTANT_Methodref = 10,
96 CONSTANT_InterfaceMethodref = 11,
97 CONSTANT_String = 8,
98 CONSTANT_Integer = 3,
99 CONSTANT_Float = 4,
100 CONSTANT_Long = 5,
101 CONSTANT_Double = 6,
102 CONSTANT_NameAndType = 12,
103 CONSTANT_Utf8 = 1
106 enum { NGROW_INIT = 10, NGROW = 2 };
108 static char *pprogname = "javadep";
109 static char csep = ';';
110 #if defined (UNX) || defined(OS2)
111 #define CDECL
112 static char cpathsep = '/';
113 #elif defined (WNT) || defined(OS2)
114 static char cpathsep = '\\';
115 #endif
116 static FILE *pfsout = NULL;
117 static char *pout_file = NULL;
120 /* prototypes */
121 uint8 read_uint8(const file_t *pfile);
122 uint16 read_uint16(const file_t *pfile);
123 uint32 read_uint32(const file_t *pfile);
124 void skip_bytes(const file_t *pfile, const size_t nnum);
125 char *escape_slash(const char *pstr);
126 int is_inner(const char *pstr);
127 void print_dependencies(const struct growable *pdep,
128 const char* pclass_file);
129 void process_class_file(const char *pfilenamem,
130 const struct growable *pfilt);
131 char *utf8tolatin1(const utf8_t a_utf8);
132 void *xmalloc(size_t size);
133 void *xcalloc(size_t nmemb, size_t size);
134 void *xrealloc(void *ptr, size_t size);
135 void grow_if_needed (struct growable *pgrow);
136 int append_to_growable(struct growable *, char *);
137 struct growable *allocate_growable(void);
138 void free_growable(struct growable *pgrowvoid);
139 void create_filters(struct growable *pfilt, const struct growable *pinc);
140 void usage(void);
141 void err_quit(const char *, ...);
142 void silent_quit(void);
144 /* poor man's getopt() */
145 int simple_getopt(char *pargv[], const char *poptstring);
146 char *optarg = NULL;
147 int optind = 1;
148 int optopt = 0;
149 int opterr = 0;
151 uint8
152 read_uint8(const file_t *pfile)
154 /* read a byte from classfile */
155 int nread;
156 uint8 ndata;
157 nread = fread(&ndata, sizeof(uint8), 1, pfile->pfs);
158 if ( !nread ) {
159 fclose(pfile->pfs);
160 err_quit("%s: truncated class file", pfile->pname);
162 return ndata;
165 uint16
166 read_uint16(const file_t *pfile)
168 /* read a short from classfile and convert it to host format */
169 int nread;
170 uint16 ndata;
171 nread = fread(&ndata, sizeof(uint16), 1, pfile->pfs);
172 if ( !nread ) {
173 fclose(pfile->pfs);
174 err_quit("%s: truncated class file", pfile->pname);
176 ndata = ntohs(ndata);
177 return ndata;
180 uint32
181 read_uint32(const file_t *pfile)
183 /* read an int from classfile and convert it to host format */
184 int nread;
185 uint32 ndata;
186 nread = fread(&ndata, sizeof(uint32), 1, pfile->pfs);
187 if ( !nread ) {
188 fclose(pfile->pfs);
189 err_quit("%s: truncated class file", pfile->pname);
191 ndata = ntohl(ndata);
192 return ndata;
195 utf8_t
196 read_utf8(const file_t *pfile)
198 /* Read a java utf-8-string with uint16 length prependend
199 * from class file. Returns utf8 struct
200 * with fresh allocated datablock,
201 * caller is responsible for freeing.
202 * Data is still in network byteorder
205 utf8_t a_utf8;
206 int nread;
208 a_utf8.pdata = NULL;
210 a_utf8.nlen = read_uint16(pfile);
211 if (a_utf8.nlen > 0) {
212 a_utf8.pdata = xmalloc(a_utf8.nlen*sizeof(char));
213 nread = fread(a_utf8.pdata, a_utf8.nlen*sizeof(char), 1, pfile->pfs);
214 if ( !nread ) {
215 fclose(pfile->pfs);
216 err_quit("%s: truncated class file", pfile->pname);
220 return a_utf8;
223 char *utf8tolatin1(const utf8_t a_utf8)
225 /* function returns fresh allocated zero terminated string,
226 * caller is responsible for freeing
229 /* JVMS p. 101: the null byte is encoded using a two byte format,
230 * Java Virtual Machine Utf8 strings differ in this respect from
231 * standard UTF-8 strings
234 /* Multibyte data is in network byte order */
236 char *p;
237 char *pp;
238 char *pstr;
240 pstr = pp = xmalloc((a_utf8.nlen+1) * sizeof(char));
242 for ( p = (char*)a_utf8.pdata;
243 p < (char*)a_utf8.pdata+a_utf8.nlen;
244 p++ ) {
245 if ( *p & 0x80 ) {
246 err_quit("sorry, real UTF8 decoding not yet implemented\n");
247 } else {
248 *pp++ = *p;
251 *pp = '\0';
253 return pstr;
257 void
258 skip_bytes(const file_t *pfile, const size_t nnumber)
260 /* skip a nnumber of bytes in classfile */
261 if ( fseek(pfile->pfs, nnumber, SEEK_CUR) == -1 )
262 err_quit("%s: %s", pfile->pname, strerror(errno));
265 void
266 add_to_dependencies(struct growable *pdep,
267 const struct growable *pfilt,
268 char *pdepstr,
269 const char *pclass_file)
271 /* create dependencies */
272 int i;
273 int nlen_filt, nlen_str, nlen_pdepstr;
274 char *pstr, *ptrunc;
275 char path[PATH_MAX+1];
276 char cnp_class_file[PATH_MAX+1];
277 char cnp_str[PATH_MAX+1];
279 nlen_pdepstr = strlen(pdepstr);
280 pstr = xmalloc((nlen_pdepstr+6+1)*sizeof(char));
281 memcpy(pstr, pdepstr, nlen_pdepstr+1);
282 strncat(pstr, ".class", 6);
284 if ( pfilt->ncur == 0 ) { /* no filters */
285 if ( access(pstr, F_OK) == 0 ) {
286 append_to_growable(pdep, strdup(pstr));
288 } else {
289 nlen_str = strlen(pstr);
290 for ( i = 0; i < pfilt->ncur; i++ ) {
291 nlen_filt = strlen(pfilt->parray[i]);
292 if ( nlen_filt + 1 + nlen_str > PATH_MAX )
293 err_quit("path to long");
294 memcpy(path, pfilt->parray[i], nlen_filt);
295 path[nlen_filt] = '/';
296 memcpy( path+nlen_filt+1, pstr, nlen_str+1);
298 if ( access(path, F_OK) != 0 ) {
299 free(pstr);
300 pstr = NULL;
301 return; /* path doesn't represent a real file, don't bother */
304 /* get the canonical path */
305 #if defined (UNX) || defined(OS2)
306 if ( !(realpath(pclass_file, cnp_class_file)
307 && realpath(path, cnp_str) ) ) {
308 err_quit("can't get the canonical path");
310 #else
311 if ( !(_fullpath(cnp_class_file, pclass_file, sizeof(cnp_class_file))
312 && _fullpath(cnp_str, path, sizeof(cnp_str)) ) ) {
313 err_quit("can't get the canonical path");
315 #endif
317 /* truncate so that only the package prefix remains */
318 ptrunc = strrchr(cnp_str, cpathsep);
319 *ptrunc = '\0';
320 ptrunc = strrchr(cnp_class_file, cpathsep);
321 *ptrunc = '\0';
323 if ( !strcmp(cnp_str, cnp_class_file) ) {
324 free(pstr);
325 pstr = NULL;
326 return; /* identical, don't bother with this one */
329 append_to_growable(pdep, strdup(path));
332 free(pstr);
333 return;
336 char *
337 escape_slash(const char *pstr)
339 /* returns a fresh allocated string with all cpathsep escaped exchanged
340 * with "$/"
342 * caller is responsible for freeing
345 const char *pp = pstr;
346 char *p, *pnp;
347 char *pnew_str;
348 int nlen_pnp, nlen_pp;
349 int i = 0;
351 while ( (p=strchr(pp, cpathsep)) != NULL ) {
352 ++i;
353 pp = ++p;
356 nlen_pnp = strlen(pstr) + i;
357 pnp = pnew_str = xmalloc((nlen_pnp+1) * sizeof(char));
359 pp = pstr;
361 if ( i > 0 ) {
362 while ( (p=strchr(pp, cpathsep)) != NULL ) {
363 memcpy(pnp, pp, p-pp);
364 pnp += p-pp;
365 *pnp++ = '$';
366 *pnp++ = '/';
367 pp = ++p;
370 nlen_pp = strlen(pp);
371 memcpy(pnp, pp, nlen_pp+1);
373 return pnew_str;
377 void
378 print_dependencies(const struct growable *pdep, const char* pclass_file)
380 char *pstr;
381 int i;
383 pstr = escape_slash(pclass_file);
384 fprintf(pfsout, "%s:", pstr);
385 free(pstr);
387 for( i=0; i<pdep->ncur; ++i) {
388 fprintf(pfsout, " \\\n");
389 pstr=escape_slash(pdep->parray[i]);
390 fprintf(pfsout, "\t%s", pstr);
391 free(pstr);
394 fprintf(pfsout,"\n\n");
395 return;
399 is_inner(const char *pstr)
401 /* return true if character '$' is found in classname */
404 * note that a '$' in a classname is not an exact indicator
405 * for an inner class. Java identifier may legally contain
406 * this chararcter, and so may classnames. In the context
407 * of javadep this doesn't matter since the makefile system
408 * can't cope with classfiles with '$'s in the filename
409 * anyway.
413 if ( strchr(pstr, '$') != NULL )
414 return 1;
416 return 0;
419 void
420 process_class_file(const char *pfilename, const struct growable *pfilt)
422 /* read class file and extract object information
423 * java class files are in bigendian data format
424 * (JVMS, p. 83)
426 int i;
427 uint32 nmagic;
428 uint16 nminor, nmajor;
429 uint16 ncnt;
430 uint16 nclass_cnt;
431 utf8_t* pc_pool;
432 uint16* pc_class;
433 file_t file;
435 struct growable *pdepen;
437 file.pname = (char*)pfilename;
439 file.pfs = fopen(file.pname,"rb");
440 if ( !file.pfs )
441 silent_quit();
443 nmagic = read_uint32(&file);
445 if ( nmagic != 0xCAFEBABE ) {
446 fclose(file.pfs);
447 err_quit("%s: invalid magic", file.pname);
450 nminor = read_uint16(&file);
451 nmajor = read_uint16(&file);
453 /* get number of entries in constant pool */
454 ncnt = read_uint16(&file);
456 #ifdef DEBUG
457 printf("Magic: %p\n", (void*)nmagic);
458 printf("Major %d, Minor %d\n", nmajor, nminor);
459 printf("Const_pool_count %d\n", ncnt);
460 #endif
462 /* There can be ncount entries in the constant_pool table
463 * so at most ncount-1 of them can be of type CONSTANT_Class
464 * (at leat one CONSTANT_Utf8 entry must exist).
465 * Usually way less CONSTANT_Class entries exists, of course
468 pc_pool = xcalloc(ncnt,sizeof(utf8_t));
469 pc_class = xmalloc((ncnt-1)*sizeof(uint16));
471 /* pc_pool[0] is reserved to the java virtual machine and does
472 * not exist in the class file
475 nclass_cnt = 0;
477 for (i = 1; i < ncnt; i++) {
478 uint8 ntag;
479 uint16 nindex;
480 utf8_t a_utf8;
482 ntag = read_uint8(&file);
484 /* we are only interested in CONSTANT_Class entries and
485 * Utf8 string entries, because they might belong to
486 * CONSTANT_Class entries
488 switch(ntag) {
489 case CONSTANT_Class:
490 nindex = read_uint16(&file);
491 pc_class[nclass_cnt++] = nindex;
492 break;
493 case CONSTANT_Fieldref:
494 case CONSTANT_Methodref:
495 case CONSTANT_InterfaceMethodref:
496 skip_bytes(&file, 4L);
497 break;
498 case CONSTANT_String:
499 skip_bytes(&file, 2L);
500 break;
501 case CONSTANT_Integer:
502 case CONSTANT_Float:
503 skip_bytes(&file, 4L);
504 break;
505 case CONSTANT_Long:
506 case CONSTANT_Double:
507 skip_bytes(&file, 8L);
508 /* Long and Doubles take 2(!)
509 * entries in constant_pool_table
511 i++;
512 break;
513 case CONSTANT_NameAndType:
514 skip_bytes(&file, 4L);
515 break;
516 case CONSTANT_Utf8:
517 a_utf8 = read_utf8(&file);
518 pc_pool[i] = a_utf8;
519 break;
520 default:
521 /* Unknown Constant_pool entry, this means we are
522 * in trouble
524 err_quit("corrupted class file\n");
525 break;
530 fclose(file.pfs);
532 pdepen = allocate_growable();
534 for (i = 0; i < nclass_cnt; i++) {
535 char *pstr, *ptmpstr;
536 pstr = ptmpstr = utf8tolatin1(pc_pool[pc_class[i]]);
537 /* we are not interested in inner classes */
538 if ( is_inner(pstr) ) {
539 free(pstr);
540 pstr = NULL;
541 continue;
543 /* strip off evt. array indicators */
544 if ( *ptmpstr == '[' ) {
545 while ( *ptmpstr == '[' )
546 ptmpstr++;
547 /* we only interested in obj. arrays, which are marked with 'L' */
548 if ( *ptmpstr == 'L' ) {
549 char *p = pstr;
550 pstr = strdup(++ptmpstr);
551 /* remove final ';' from object array name */
552 pstr[strlen(pstr)-1] = '\0';
553 free(p);
554 } else {
555 free(pstr);
556 pstr = NULL;
560 if (pstr) {
561 add_to_dependencies(pdepen, pfilt, pstr, file.pname);
562 free(pstr);
566 print_dependencies(pdepen, file.pname);
567 free_growable(pdepen);
568 pdepen = NULL;
570 for (i = 0; i < ncnt; i++)
571 free(pc_pool[i].pdata);
573 free(pc_class);
574 free(pc_pool);
577 void *
578 xmalloc(size_t size)
580 void *ptr;
582 ptr = malloc(size);
584 if ( !ptr )
585 err_quit("out of memory");
587 return ptr;
591 void *
592 xcalloc(size_t nmemb, size_t size)
594 void *ptr;
596 ptr = calloc(nmemb, size);
598 if ( !ptr )
599 err_quit("out of memory");
601 return ptr;
604 void *
605 xrealloc(void *ptr, size_t size)
607 ptr = realloc(ptr, size);
609 if ( !ptr )
610 err_quit("out of memory");
612 return ptr;
615 void
616 err_quit(const char* fmt, ...)
618 /* No dependency file must be generated for any error condition,
619 * just print message and exit.
621 va_list args;
622 char buffer[PATH_MAX];
624 va_start(args, fmt);
626 if ( pprogname )
627 fprintf(stderr, "%s: ", pprogname);
628 vsnprintf(buffer, sizeof(buffer), fmt, args);
629 fputs(buffer, stderr);
630 fputc('\n', stderr);
632 va_end(args);
634 /* clean up */
635 if ( pfsout && pfsout != stdout ) {
636 fclose(pfsout);
637 unlink(pout_file);
639 exit(1);
642 void
643 silent_quit()
645 /* In some cases we should just do a silent exit */
647 /* clean up */
648 if ( pfsout && pfsout != stdout ) {
649 fclose(pfsout);
650 unlink(pout_file);
652 exit(0);
655 int append_to_growable(struct growable *pgrow, char *pstr)
657 /* append an element pstr to pgrow,
658 * return new number of elements
660 grow_if_needed(pgrow);
661 pgrow->parray[pgrow->ncur++] = pstr;
662 return pgrow->ncur;
665 void
666 grow_if_needed(struct growable *pgrow)
668 /* grow growable arrays */
670 if ( pgrow->ncur >= pgrow->nmax ) {
671 pgrow->parray = xrealloc(pgrow->parray,
672 (NGROW*pgrow->nmax)*sizeof(char*));
673 pgrow->nmax *= NGROW;
675 return;
678 struct growable *allocate_growable(void)
680 /* allocate an growable array,
681 * initialize with NGROW_INIT elements
684 struct growable *pgrow;
686 pgrow = xmalloc(sizeof(struct growable));
687 pgrow->parray = xmalloc(NGROW_INIT*sizeof(char *));
688 pgrow->nmax = NGROW_INIT;
689 pgrow->ncur = 0;
690 return pgrow;
693 void
694 free_growable(struct growable *pgrow)
696 int i;
697 for( i = 0; i < pgrow->ncur; i++ )
698 free(pgrow->parray[i]);
699 free(pgrow->parray);
700 free(pgrow);
703 void
704 create_filters(struct growable *pfilt, const struct growable *pinc)
706 char *p, *pp, *pstr;
707 int i, nlen, nlen_pstr;
708 /* break up includes into filter list */
709 for ( i = 0; i < pinc->ncur; i++ ) {
710 pp = pinc->parray[i];
712 while ( (p = strchr(pp, csep)) != NULL) {
713 nlen = p - pp;
714 pstr = xmalloc((nlen+1)*sizeof(char*));
715 memcpy(pstr, pp, nlen);
716 pstr[nlen] = '\0';
717 append_to_growable(pfilt, pstr);
718 pp = p + 1;
720 nlen_pstr = strlen(pp);
721 pstr = xmalloc((nlen_pstr+1)*sizeof(char*));
722 memcpy(pstr, pp, nlen_pstr+1);
723 append_to_growable(pfilt, pstr);
728 void
729 usage()
731 fprintf(stderr,
732 "usage: %s [-i|-I includepath ... -s|-S seperator "
733 "-o|-O outpath -v|-V -h|-H] <file> ....\n",
734 pprogname);
737 /* my very simple minded implementation of getopt()
738 * it's to sad that getopt() is not available everywhere
739 * note: this is not a full POSIX conforming getopt()
741 int simple_getopt(char *pargv[], const char *poptstring)
743 char *parg = pargv[optind];
745 /* skip all response file arguments */
746 if ( parg ) {
747 while ( *parg == '@' )
748 parg = pargv[++optind];
750 if ( parg[0] == '-' && parg[1] != '\0' ) {
751 char *popt;
752 int c = parg[1];
753 if ( (popt = strchr(poptstring, c)) == NULL ) {
754 optopt = c;
755 if ( opterr )
756 fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
757 return '?';
759 if ( *(++popt) == ':') {
760 if ( parg[2] != '\0' ) {
761 optarg = ++parg;
762 } else {
763 optarg = pargv[++optind];
765 } else {
766 optarg = NULL;
768 ++optind;
769 return c;
772 return -1;
776 int CDECL
777 main(int argc, char *argv[])
779 int bv_flag = 0;
780 struct growable *presp, *pincs, *pfilters;
781 int c, i, nall_argc;
782 char **pall_argv;
784 presp = allocate_growable();
786 /* FIXME: cleanup the option parsing */
787 /* search for response file, read it */
788 for ( i = 1; i < argc; i++ ) {
789 char *parg = argv[i];
790 char buffer[RES_FILE_BUF];
792 if ( *parg == '@' ) {
793 FILE *pfile = fopen(++parg, "r");
794 if ( !pfile )
795 err_quit("%s: %s", parg, strerror(errno));
796 while ( !feof(pfile) ) {
797 char *p, *token;
799 if ( fgets(buffer, RES_FILE_BUF, pfile) ) {;
800 p = buffer;
801 while ( (token = strtok(p, " \t\n")) != NULL ) {
802 p = NULL;
803 append_to_growable(presp, strdup(token));
807 fclose(pfile);
811 /* copy all arguments incl. response file in one array
812 * for parsing with getopt
814 nall_argc = argc + presp->ncur;
815 pall_argv = xmalloc((nall_argc+1)*sizeof(char *));
816 memcpy(pall_argv, argv, argc*sizeof(char *));
817 memcpy(pall_argv+argc, presp->parray, presp->ncur*sizeof(char *));
818 *(pall_argv+argc+presp->ncur) = '\0'; /* terminate */
820 opterr = 0;
821 pincs = allocate_growable();
823 while( (c = simple_getopt(pall_argv, ":i:I:s:S:o:OhHvV")) != -1 ) {
824 switch(c) {
825 case 'i':
826 case 'I':
827 append_to_growable(pincs, strdup(optarg));
828 break;
829 case 's':
830 case 'S':
831 csep = optarg[0];
832 break;
833 case 'o':
834 case 'O':
835 pout_file = optarg;
836 break;
837 case 'h':
838 case 'H':
839 usage();
840 return 0;
841 break;
842 case 'v':
843 case 'V':
844 bv_flag = 1;
845 break;
846 case '?':
847 if (isprint (optopt))
848 fprintf (stderr,
849 "Unknown option `-%c'.\n", optopt);
850 else
851 fprintf (stderr,
852 "Unknown option character `\\x%x'.\n",
853 optopt);
854 usage();
855 return 1;
856 break;
857 case ':':
858 fprintf(stderr, "Missing parameter.\n");
859 usage();
860 return 1;
861 break;
862 default:
863 usage();
864 return 1;
865 break;
869 pfilters = allocate_growable();
870 create_filters(pfilters, pincs);
871 free_growable(pincs);
872 pincs = NULL;
874 if ( pout_file ) {
875 pfsout = fopen(pout_file, "w");
876 if ( !pfsout )
877 err_quit("%s: %s", pout_file, strerror(errno));
878 } else {
879 pfsout = stdout;
882 /* the remaining arguments are either class file
883 * names or response files, ignore response file
884 * since they have already been included
886 for ( i = optind; i < nall_argc; i++ ) {
887 char *parg = pall_argv[i];
888 if ( *parg != '@' ) {
889 process_class_file(parg, pfilters);
890 if ( pfsout != stdout ) {
891 if ( bv_flag )
892 printf("Processed %s ...\n", parg);
897 free_growable(pfilters);
898 pfilters = NULL;
899 free(pall_argv);
900 pall_argv = NULL;
901 free_growable(presp);
902 presp = NULL;
904 fclose(pfsout);
905 exit(0);