Bug Summary

File:soltools/javadep/javadep.c
Location:line 679, column 5
Description:Access to field 'parray' results in a dereference of a null pointer (loaded from variable 'pgrow')

Annotated Source Code

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