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