Add an UNSPEC_PROLOGUE_USE to prevent the link register from being considered dead.
[official-gcc.git] / fastjar / jargrep.c
blob01c04500c5bf332204bcd91c9f506e1742be6e71
1 /*
2 jargrep.c - main functions for jargrep utility
3 Copyright (C) 2002 Free Software Foundation
4 Copyright (C) 1999, 2000 Bryan Burns
5 Copyright (C) 2000 Cory Hollingsworth
7 Parts of this program are base on Bryan Burns work with fastjar
8 Copyright (C) 1999.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* Id: jargrep.c,v 1.5 2002/01/03 04:57:56 rodrigc Exp
27 Log: jargrep.c,v
28 Revision 1.5 2002/01/03 04:57:56 rodrigc
29 2001-01-02 Craig Rodrigues <rodrigc@gcc.gnu.org>
31 PR bootstrap/5117
32 * configure.in (AC_CHECK_HEADERS): Check for stdlib.h.
33 * Makefile.am: Move grepjar to bin_PROGRAMS.
34 * config.h.in: Regenerated.
35 * Makefile.in: Regenerated.
36 * aclocal.m4: Regenerated.
37 * jargrep.c: Eliminate some signed/unsigned and default
38 uninitialized warnings. Use HAVE_STDLIB_H instead of
39 STDC_HEADERS macro.
40 * jartool.c: Likewise.
41 * compress.c: Likewise.
43 Revision 1.4 2000/12/15 18:45:09 tromey
44 * jargrep.c: Include getopt.h if it exists.
45 (optind): Declare.
46 * configure, config.h: Rebuilt.
47 * configure.in: Check for getopt.h.
49 Revision 1.3 2000/12/14 18:45:35 ghazi
50 Warning fixes:
52 * compress.c: Include stdlib.h and compress.h.
53 (rcsid): Delete.
54 (report_str_error): Make static.
55 (ez_inflate_str): Delete unused variable. Add parens in if-stmt.
56 (hrd_inflate_str): Likewise.
58 * compress.h (init_compression, end_compression, init_inflation,
59 end_inflation): Prototype void arguments.
61 * dostime.c (rcsid): Delete.
63 * jargrep.c: Include ctype.h, stdlib.h, zlib.h and compress.h.
64 Make functions static. Cast ctype function argument to `unsigned
65 char'. Add parens in if-stmts. Constify.
66 (Usage): Change into a macro.
67 (jargrep): Remove unused parameter.
69 * jartool.c: Constify. Add parens in if-stmts. Align
70 signed/unsigned char pointers in functions calls using casts.
71 (rcsid): Delete.
72 (list_jar): Fix printf format specifier.
73 (usage): Chop long string into bits. Reformat.
75 * pushback.c (rcsid): Delete.
77 Revision 1.2 2000/12/11 02:59:55 apbianco
78 2000-12-10 Robert Lipe <robertlipe@usa.net>
80 * jargrep.c (jargrep): Added null statement after case.
82 2000-12-10 Alexandre Petit-Bianco <apbianco@cygnus.com>
84 * Makefile: Removed.
85 * Makefile.in: Rebuilt with `-i' and `--enable-foreign'.
87 (http://gcc.gnu.org/ml/gcc/2000-12/msg00294.html)
89 Revision 1.1 2000/12/09 03:08:23 apbianco
90 2000-12-08 Alexandre Petit-Bianco <apbianco@cygnus.com>
92 * fastjar: Imported.
94 Revision 1.8 2000/09/13 14:02:02 cory
95 Reformatted some of the code to more closly match the layout of the orriginal
96 fastjar utility.
98 Revision 1.7 2000/09/12 22:29:36 cory
99 Jargrep now seems to do what I want it to do. Performs properly on Linux x86,
100 will test some other platforms later.
105 #include "config.h"
106 #include <stdio.h>
107 #include <unistd.h>
108 #include <regex.h>
109 #include <errno.h>
110 #include <string.h>
111 #include <sys/types.h>
112 #include <sys/stat.h>
113 #include <fcntl.h>
114 #include <ctype.h>
115 #ifdef HAVE_STDLIB_H
116 #include <stdlib.h>
117 #endif
118 #include "jargrep.h"
119 #include "jartool.h"
120 #include "pushback.h"
121 #include "zipfile.h"
122 #include "zlib.h"
123 #include "compress.h"
124 #include <getopt.h>
126 void version(void);
127 void help(const char *name);
129 #define Usage "Usage: %s [-bcinsVw] [--version|--help] <-e PATTERN | PATTERN> FILE ...\n"
132 Function name: opt_valid
133 arg: options Bitfield flag that contains the command line options of grepjar.
134 purpose: To guard agains the occurance of certain incompatible flags being used
135 together.
136 returns: TRUE if options are valid, FALSE otherwise.
139 static int opt_valid(int options) {
140 int retflag;
142 if((options & JG_PRINT_COUNT) &&
143 (options & (JG_PRINT_BYTEOFFSET | JG_PRINT_LINE_NUMBER)))
145 retflag = FALSE;
147 else retflag = TRUE;
149 return retflag;
153 Function name: create_regexp
154 args: regstr String containing the uncompiled regular expression. This may be the
155 expression as is passed in through argv.
156 options This is the flag containing the commandline options that have been
157 parsed by getopt.
158 purpose: Handle the exception handling involved with setting upt a new regular
159 expression.
160 returns: Newly allocated compile regular expression ready to be used in an regexec call.
163 static regex_t *create_regexp(const char *regstr, int options) {
164 regex_t *exp;
165 int errcode;
166 int msgsize;
167 char *errmsg;
169 if((exp = (regex_t *) malloc(sizeof(regex_t))))
171 if((errcode = regcomp(exp, regstr, (options & JG_IGNORE_CASE) ? REG_ICASE : 0))) {
172 fprintf(stderr, "regcomp of regex failed,\n");
173 if((errmsg = (char *) malloc(msgsize = regerror(errcode, exp, NULL, 0) + 1))) {
174 regerror(errcode, exp, errmsg, msgsize);
175 fprintf(stderr, "Error: %s\n", errmsg);
176 free(exp);
177 free(errmsg);
178 exit(1);
180 else {
181 fprintf(stderr, "Malloc of errmsg failed.\n");
182 fprintf(stderr, "Error: %s\n", strerror(errno));
183 free(exp);
184 exit(1);
188 else {
189 fprintf(stderr, "Malloc of regex failed,\n");
190 fprintf(stderr, "Error: %s\n", strerror(errno));
191 exit(1);
194 return exp;
198 Function name: check_sig
199 args: scratch Pointer to array of bytes containing signature.
200 pbf Pointer to push back handle for jar file.
201 purpose: Verify that checksum is correct.
202 returns: 0, 1, or 2. 0 means we are ready to read embedded file information. 1 means
203 we have read beyound the embedded file list and can exit knowing we have read all the
204 relevent information. 2 means we still haven't reached embdedded file list and need to
205 do some more reading.
207 static int check_sig(ub1 *scratch, pb_file *pbfp) {
208 ub4 signature;
209 int retflag = 0;
211 signature = UNPACK_UB4(scratch, 0);
213 #ifdef DEBUG
214 printf("signature is %x\n", signature);
215 #endif
216 if(signature == 0x08074b50){
217 #ifdef DEBUG
218 printf("skipping data descriptor\n");
219 #endif
220 pb_read(pbfp, scratch, 12);
221 retflag = 2;
222 } else if(signature == 0x02014b50){
223 #ifdef DEBUG
224 printf("Central header reached.. we're all done!\n");
225 #endif
226 retflag = 1;
227 }else if(signature != 0x04034b50){
228 printf("Ick! %#x\n", signature);
229 retflag = 1;
232 return retflag;
236 Function name: decd_siz
237 args csize Pointer to embedded file's compressed size.
238 usize Pointer to embedded file's uncmpressed size.
239 fnlen Pointer to embedded file's file name length.
240 elfen Pointer to length of extra fields in jar file.
241 flags Pointer to bitmapped flags.
242 method Pointer to indicator of storage method of embedded file.
243 file_header Pointer to string containing the above values to be unbacked.
244 Purpose: Unpack the series of values from file_header.
247 static void decd_siz(ub4 *csize, ub4 *usize, ub2 *fnlen, ub2 *eflen, ub2 *flags, ub2 *method, ub1 *file_header) {
248 *csize = UNPACK_UB4(file_header, LOC_CSIZE);
249 #ifdef DEBUG
250 printf("Compressed size is %u\n", *csize);
251 #endif
253 *usize = UNPACK_UB4(file_header, LOC_USIZE);
254 #ifdef DEBUG
255 printf("Uncompressed size is %u\n", *usize);
256 #endif
258 *fnlen = UNPACK_UB2(file_header, LOC_FNLEN);
259 #ifdef DEBUG
260 printf("Filename length is %hu\n", *fnlen);
261 #endif
263 *eflen = UNPACK_UB2(file_header, LOC_EFLEN);
264 #ifdef DEBUG
265 printf("Extra field length is %hu\n", *eflen);
266 #endif
268 *flags = UNPACK_UB2(file_header, LOC_EXTRA);
269 #ifdef DEBUG
270 printf("Flags are %#hx\n", *flags);
271 #endif
273 *method = UNPACK_UB2(file_header, LOC_COMP);
274 #ifdef DEBUG
275 printf("Compression method is %#hx\n", *method);
276 #endif
281 Function name: new_filename
282 args: pbf Pointer to push back file handle. Used for reading input file.
283 len Length of file name to be read.
284 purpose: Read in the embedded file name from jar file.
285 returns: Pointer to newly allocated string containing file name.
288 static char *new_filename(pb_file *pbf, ub4 len) {
289 char *filename;
291 if(!(filename = (char *) malloc(len + 1))) {
292 fprintf(stderr, "Malloc failed of filename\n");
293 fprintf(stderr, "Error: %s\n", strerror(errno));
295 pb_read(pbf, filename, len);
296 filename[len] = '\0';
298 #ifdef DEBUG
299 printf("filename is %s\n", filename);
300 #endif
302 return filename;
306 Funtion name: read_string
307 args: pbf Pointer to push back file handle. Used for reading input file.
308 size Size of embedded file in bytes.
309 purpose: Create a string containing the contents of the embedded noncompressed file.
310 returns: Pointer to newly allocated string containing embedded file contents.
313 static char *read_string(pb_file *pbf, int size) {
314 char *page;
316 if((page = (char *) malloc(size + 1))) {
317 pb_read(pbf, page, size);
318 page[size] = '\0';
320 else {
321 fprintf(stderr, "Malloc of page buffer failed.\n");
322 fprintf(stderr, "Error: %s\n", strerror(errno));
323 exit(1);
326 return page;
330 Function name: extract_line
331 args: stream String containing the full contents of a file which is to be substringed
332 in order to provide line representing our grep output.
333 begin Index into stream which regular expression first matches.
334 end Index into stream which end of match to the regular expression.
335 b Pointer to the index of what will be the beginning of the line when
336 string is returned. Used for -b option.
337 purpose: Create a string that can be printed by jargrep from the long string stream.
338 The matching line that is printed out by jargrep is generated by this function.
339 returns: Pointer to newly allocated string containing matched expression.
342 static char *extract_line(const char *stream, regoff_t begin, regoff_t end, int *b) {
343 int e;
344 int length;
345 char *retstr;
347 for(*b = begin; *b >= 0 && !iscntrl((unsigned char)stream[*b]); (*b)--);
348 (*b)++;
349 for(e = end; stream[e] == '\t' || !iscntrl((unsigned char)stream[e]); e++);
350 length = e - *b;
351 if((retstr = (char *) malloc(length + 1))) {
352 sprintf(retstr, "%d:", *b);
353 strncpy(retstr, &(stream[*b]), length);
354 retstr[length] = '\0';
356 else {
357 fprintf(stderr, "Malloc failed of output string.\n");
358 fprintf(stderr, "Error: %s\n", strerror(errno));
359 exit(1);
362 return retstr;
366 Function name: chk_wrd
367 args: exp Pointer to compiled POSIX style regular expression of search target.
368 str String known to contain at least one match of exp.
369 purpose: Verify that the occurance of the regular expression in str occurs as a whole
370 word and not a substring of another word.
371 returns: TRUE if it is a word, FALSE of it is a substring.
374 static int chk_wrd(regex_t *exp, const char *str) {
375 int wrd_fnd = FALSE;
376 int frnt_ok;
377 int bck_ok;
378 const char *str2;
379 regmatch_t match;
381 str2 = str;
382 frnt_ok = bck_ok = FALSE;
383 while(!wrd_fnd && !regexec(exp, str2, 1, &match, 0)) {
384 if(!match.rm_so && (str2 == str)) frnt_ok = TRUE;
385 else if(!isalnum((unsigned char)str2[match.rm_so - 1])
386 && str2[match.rm_so - 1] != '_')
387 frnt_ok = TRUE;
388 else frnt_ok = FALSE;
389 if(frnt_ok) {
390 if(str2[match.rm_eo] == '\0') bck_ok = TRUE;
391 else if(!isalnum((unsigned char)str2[match.rm_eo])
392 && str2[match.rm_eo] != '_')
393 bck_ok = TRUE;
394 else bck_ok = FALSE;
396 wrd_fnd = frnt_ok && bck_ok;
397 str2 = &(str2[match.rm_eo]);
400 return wrd_fnd;
404 Function name: prnt_mtchs
405 args: exp Pointer to compiled POSIX style regular expression of search target.
406 filename String containing the name of the embedded file which matches have
407 been found in.
408 stream String containing the processed contents of the embedded jar file
409 represended with filename.
410 pmatch Array of regmatch_t matches into stream.
411 nl_offset Array of offsets of '\n' characters in stream. May be NULL if -n is
412 not set on command line.
413 num Number of matches in pmatch array.
414 lines Number of lines in file. Not set if -n is not set on command line.
415 options Bitwise flag containing flags set to represent the command line
416 options.
417 purpose: Control output of jargrep. Output is controlled by which options have been
418 set at the command line.
421 static void prnt_mtchs(regex_t *exp, const char *filename, const char *stream, regmatch_t *pmatch, regmatch_t *nl_offset, int num, int lines, int options) {
422 int i;
423 int j = 0;
424 int ln_cnt;
425 int begin;
426 int o_begin;
427 char *str;
429 o_begin = -1;
430 ln_cnt = 0;
431 for(i = 0; i < num; i++) {
432 str = extract_line(stream, pmatch[i].rm_so, pmatch[i].rm_eo, &begin);
433 if(begin > o_begin) {
434 if(!(options & JG_WORD_EXPRESSIONS) || chk_wrd(exp, str)) {
435 ln_cnt++;
436 if(!(options & JG_PRINT_COUNT)) {
437 printf("%s:", filename);
438 if(options & JG_PRINT_LINE_NUMBER) {
439 for(; j < lines && nl_offset[j].rm_so < begin; j++);
440 printf("%d:", j + 1);
442 if(options & JG_PRINT_BYTEOFFSET) printf("%d:", begin);
443 printf("%s\n", str);
447 o_begin = begin;
448 free(str);
450 if(options & JG_PRINT_COUNT) printf("%s:%d\n", filename, ln_cnt);
454 Function name: check_crc
455 args: pbf Pointer to pushback file pointer for jar file.
456 stream String containing the non modified contents fo the extraced file entry.
457 usize Size of file in bytes.
458 purpose: Verify the CRC matches that as what is stored in the jar file.
461 static void check_crc(pb_file *pbf, const char *stream, ub4 usize) {
462 ub4 crc=0;
463 ub4 lcrc;
464 ub1 scratch[16];
466 crc = crc32(crc, NULL, 0);
467 crc = crc32(crc, (const unsigned char *)stream, usize);
468 if(pb_read(pbf, scratch, 16) != 16) {
469 perror("read");
470 exit(1);
472 if(UNPACK_UB4(scratch, 0) != 0x08074b50) {
473 fprintf(stderr, "Error! Missing data descriptor!\n");
474 exit(1);
476 lcrc = UNPACK_UB4(scratch, 4);
477 if(crc != lcrc){
478 fprintf(stderr, "Error! CRCs do not match! Got %x, expected %x\n",
479 crc, lcrc);
480 exit(1);
485 Function name mk_ascii
486 args: stream String that contains the contents of the extraced file entry.
487 usize String size.
488 purpose: Make certain that the contents of the file are ASCII, not binary. This
489 permits grepping of binary files as well by converting non ASCII and control characters
490 into '\n'.
493 static void mk_ascii(char *stream, size_t usize) {
494 size_t i;
496 for(i = 0; i < usize; i++)
497 if(stream[i] != '\t'
498 && (iscntrl((unsigned char)stream[i])
499 || (unsigned char) stream[i] >= 128))
500 stream[i] = '\n';
504 Funtion name: fnd_match
505 args: exp Pointer to compiled POSIX style regular expression of search target.
506 str_stream String that contains the contents of the extracted file entry.
507 i Pointer to counter and index of matches.
508 purpose: Search str_stream for occurances of the regular expression exp and create
509 an array of matches.
510 returns: Pointer to newly allocated array of regmatch_t which gives indexes to start
511 and end of matches. NULL is returned upon no matches found.
514 static regmatch_t *fnd_match(regex_t *exp, const char *str_stream, int *i) {
515 int regflag;
516 regmatch_t match;
517 regmatch_t *match_array;
518 regmatch_t *tmp;
520 match_array = NULL;
521 for(*i = 0, regflag = regexec(exp, str_stream, 1, &match, 0); !regflag;
522 regflag = regexec(exp, &(str_stream[match.rm_eo]), 1, &match, 0), (*i)++)
524 if((tmp = (regmatch_t *)
525 realloc(match_array, sizeof(regmatch_t) * ((*i) + 1))))
527 match_array = tmp;
528 if(*i) {
529 match.rm_so += match_array[(*i) - 1].rm_eo;
530 match.rm_eo += match_array[(*i) - 1].rm_eo;
532 match_array[*i] = match;
534 else {
535 fprintf(stderr, "Realloc of match_array failed.\n");
536 fprintf(stderr, "Error: %s\n", strerror(errno));
537 exit(1);
541 return match_array;
545 Function name: cont_grep
546 args: exp Pointer to compiled POSIX style regular expression of search target.
547 nl_exp Pointer to compiled POSIX style regular expression of newlines. This
548 argument is NULL unless the -n option is used on the command line.
549 fd File descriptor of the jar file being grepped.
550 pbf Pointer to pushback file style file stream. This is for use with
551 the pushback.c file io funtions.
552 options Bitwise flag containing flags set to represent the command line options.
553 purpose: This function handles single entries in an open jar file. The header is
554 read and then the embeded file is extracted and grepped.
555 returns: FALSE upon failure, TRUE otherwise.
558 static int cont_grep(regex_t *exp, regex_t *nl_exp, int fd, pb_file *pbf, int options) {
559 int retflag = TRUE;
560 int i;
561 int j;
562 ub4 csize;
563 ub4 usize;
564 ub2 fnlen;
565 ub2 eflen;
566 ub2 flags;
567 ub2 method;
568 ub1 file_header[30];
569 char *filename;
570 char *str_stream;
571 regmatch_t *match_array;
572 regmatch_t *nl_offsets=0;
574 if(pb_read(pbf, (file_header + 4), 26) != 26) {
575 perror("read");
576 retflag = FALSE;
578 else {
579 decd_siz(&csize, &usize, &fnlen, &eflen, &flags, &method, file_header);
580 filename = new_filename(pbf, fnlen);
581 lseek(fd, eflen, SEEK_CUR);
582 if(filename[fnlen - 1] != '/') {
583 str_stream = (method == 8 || (flags & 0x0008)) ?
584 (char *) inflate_string(pbf, &csize, &usize) :
585 read_string(pbf, csize);
586 if(flags & 0x008) check_crc(pbf, str_stream, usize);
587 mk_ascii(str_stream, usize);
588 match_array = fnd_match(exp, str_stream, &i);
589 if((options & JG_PRINT_LINE_NUMBER) && i)
590 nl_offsets = fnd_match(nl_exp, str_stream, &j);
591 prnt_mtchs(exp, filename, str_stream, match_array, nl_offsets, i, j, options);
592 if(match_array) free(match_array);
593 free(str_stream);
595 free(filename);
596 retflag = TRUE;
599 return retflag;
603 Funtion name: jargrep
604 args: exp Pointer to compiled POSIX style regular expression of search target.
605 nl_exp Pointer to compiled regular expression for newlines or NULL. Only set
606 if -n option is present at command line.
607 jarfile Filename of jar file to be searched.
608 options Bitwise flag containing flags set to represent the command line options.
609 purpose: Open jar file. Check signatures. When right signature is found go to deeper
610 grep routine.
613 static void jargrep(regex_t *exp, regex_t *nl_exp, const char *jarfile, int options){
614 int fd;
615 int floop = TRUE;
616 pb_file pbf;
617 ub1 scratch[16];
619 if((fd = open(jarfile, O_RDONLY)) == -1) {
620 if(!(options & JG_SUPRESS_ERROR))
621 fprintf(stderr, "Error reading file '%s': %s\n", jarfile, strerror(errno));
623 else {
624 pb_init(&pbf, fd);
626 do {
627 if(pb_read(&pbf, scratch, 4) != 4) {
628 perror("read");
629 floop = FALSE;
631 else {
632 switch (check_sig(scratch, &pbf)) {
633 case 0:
634 floop = cont_grep(exp, nl_exp, fd, &pbf, options);
635 break;
636 case 1:
637 floop = FALSE;
638 break;
639 case 2:
640 /* fall through continue */
644 } while(floop);
648 /* This is used to mark options with no short value. */
649 #define LONG_OPT(Num) ((Num) + 128)
651 #define OPT_HELP LONG_OPT (0)
653 static const struct option option_vec[] =
655 { "help", no_argument, NULL, OPT_HELP },
656 { "version", no_argument, NULL, 'V' },
657 { NULL, no_argument, NULL, 0 }
661 Funtion Name: main
662 args: argc number of in coming args.
663 argv array of strings.
664 purpose: Entry point of the program. Parse command line arguments and set options.
665 Set up regular expressions. Call grep routines for each file as input.
666 returns: 1 on error 0 on success.
669 int main(int argc, char **argv) {
670 int c;
671 int retval = 0;
672 int fileindex;
673 int options = 0;
674 regex_t *regexp;
675 regex_t *nl_exp = NULL;
676 char *regexpstr = NULL;
678 while((c = getopt_long(argc, argv, "bce:insVw",
679 option_vec, NULL)) != -1) {
680 switch(c) {
681 case 'b':
682 options |= JG_PRINT_BYTEOFFSET;
683 break;
684 case 'c':
685 options |= JG_PRINT_COUNT;
686 break;
687 case 'e':
688 if(!(regexpstr = (char *) malloc(strlen(optarg) + 1))) {
689 fprintf(stderr, "Malloc failure.\n");
690 fprintf(stderr, "Error: %s\n", strerror(errno));
691 exit(1);
693 strcpy(regexpstr, optarg);
694 break;
695 case 'i':
696 options |= JG_IGNORE_CASE;
697 break;
698 case 'n':
699 options |= JG_PRINT_LINE_NUMBER;
700 break;
701 case 's':
702 options |= JG_SUPRESS_ERROR;
703 break;
704 case 'v':
705 options |= JG_INVERT;
706 break;
707 case 'V':
708 version ();
709 break;
710 case 'w':
711 options |= JG_WORD_EXPRESSIONS;
712 break;
713 case OPT_HELP:
714 help(argv[0]);
715 break;
716 default:
717 fprintf(stderr, Usage, argv[0]);
718 exit(1);
721 if(!regexpstr){
722 if(((argc - optind) >= 2)) {
723 regexpstr = argv[optind];
724 fileindex = optind + 1;
726 else {
727 fprintf(stderr, "Invalid arguments.\n");
728 fprintf(stderr, Usage, argv[0]);
729 exit(1);
732 else if((argc - optind) == 1) {
733 fileindex = optind;
735 else {
736 fprintf(stderr, "Invalid arguments.\n");
737 fprintf(stderr, Usage, argv[0]);
738 exit(1);
741 if(opt_valid(options)) {
742 regexp = create_regexp(regexpstr, options);
743 if(options & JG_PRINT_LINE_NUMBER) nl_exp = create_regexp("\n", 0);
744 init_inflation();
745 for(; fileindex < argc; fileindex++)
746 jargrep(regexp, nl_exp, argv[fileindex], options);
747 regfree(regexp);
748 if(options & JG_PRINT_LINE_NUMBER) regfree(nl_exp);
750 else {
751 retval = 1;
752 fprintf(stderr, "Error: Invalid combination of options.\n");
755 return retval;
758 void help(const char *filename)
760 printf (Usage, filename);
761 printf ("\
763 Search files in a jar file for a pattern.\n\
765 -b print byte offset of match\n\
766 -c print number of matches\n\
767 -i compare case-insensitively\n\
768 -n print line number of each match\n\
769 -s suppress error messages\n\
770 -w force PATTERN to match only whole words\n\
771 -e PATTERN use PATTERN as regular expression\n\
772 -V|--version print version number and exit\n\
773 --help print help\n\
776 exit (0);
779 void version ()
781 printf("grepjar (%s) %s\n\n", PACKAGE, VERSION);
782 printf("Copyright 1999, 2000, 2001 Bryan Burns\n");
783 printf("Copyright 2000 Cory Hollingsworth\n");
784 printf("Copyright 2002 Free Software Foundation\n");
785 printf("\
786 This is free software; see the source for copying conditions. There is NO\n\
787 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
788 exit (0);