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