Bug Summary

File:soltools/javadep/javadep.c
Location:line 653, column 5
Description:Array access (via field 'parray') results in a null pointer dereference

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 */
30
Taking true branch
272 if ( access(pstr, F_OK0) == 0 ) {
31
Taking true branch
273 append_to_growable(pdep, strdup(pstr));
32
Calling 'append_to_growable'
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 true. Entering loop body
18
Loop condition is true. Entering loop body
21
Loop condition is true. Entering loop body
24
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) {
16
Control jumps to the 'default' case at line 510
19
Control jumps to the 'default' case at line 510
22
Control jumps to 'case CONSTANT_Class:' at line 479
479 case CONSTANT_Class:
480 nindex = read_uint16(&file);
481 pc_class[nclass_cnt++] = nindex;
482 break;
23
Execution continues on line 467
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;
17
Execution continues on line 467
20
Execution continues on line 467
516
517 }
518 }
519
520 fclose(file.pfs);
521
522 pdepen = allocate_growable();
523
524 for (i = 0; i < nclass_cnt; i++) {
25
Loop condition is true. Entering loop body
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) ) {
26
Taking false branch
529 free(pstr);
530 pstr = NULL((void*)0);
531 continue;
532 }
533 /* strip off evt. array indicators */
534 if ( *ptmpstr == '[' ) {
27
Taking false branch
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) {
28
Taking true branch
551 add_to_dependencies(pdepen, pfilt, pstr, file.pname);
29
Calling 'add_to_dependencies'
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;
33
Array access (via field 'parray') results in a null pointer dereference
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));
679 pgrow->parray = xmalloc(NGROW_INIT*sizeof(char *));
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: */