Patch: FYI: fastjar -vs- --help aka PR 5303

Tom Tromey tromey@redhat.com
Wed Jan 9 15:21:00 GMT 2002


I'm checking this in.

This addresses part of PR libgcj/5303.  Namely, it adds `--help' to
`jar' and `grepjar'.  It also adds --version support, and changes jar
to use getopt instead of its own mechanism.  There's a couple
miscellaneous bug fixes (e.g., configure.in had a typo) thrown in too.

Tested on x86 Red Hat Linux 6.2.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	For PR libgcj/5303:
	* jargrep.h: Removed RCS keywords.
	(GVERSION): Removed.
	* configure, Makefile.in, config.h.in: Rebuilt.
	* configure.in: Added AM_MAINTAINER_MODE.
	Don't look for getopt.h.  Use `fastjar' as package name.
	* Makefile.am (INCLUDES): Look in ../include.
	(LIBIBERTY): New macro.
	(jar_LDADD): Use it.
	(jar_DEPENDENCIES): Likewise.
	(grepjar_LDADD): Likewise.
	(grepjar_DEPENDENCIES): Likewise.
	* jargrep.c: Removed RCS keywords.  Always include getopt.h.
	(LONG_OPT): New macro.
	(OPT_HELP): Likewise.
	(main): Use getopt_long.  Let getopt print invalid argument
	message.  Handle --help.  Use version().
	(version): New function.
	(optarg, optind): Don't declare.
	(option_vec): New global.
	(help): New function.
	(Usage): Updated to GNU standards.
	* jartool.c: Removed RCS keywords.  Include getopt.h.
	(LONG_OPT): New macro.
	(OPT_HELP): Likewise.
	(options): New global.
	(help): New function.
	(usage): Print a single line.
	(version): New function.
	(expand_options): New function.
	(main): Use getopt_long and expand_options.  Fail if `-u'
	specified.  Changed handling of -f, -m, -V options.
	(OPTION_STRING): New macro.
	(version_string): Removed.

Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/fastjar/Makefile.am,v
retrieving revision 1.5
diff -u -r1.5 Makefile.am
--- Makefile.am 2002/01/03 04:57:56 1.5
+++ Makefile.am 2002/01/09 23:19:50
@@ -38,14 +38,19 @@
 	"RANLIB=$(RANLIB)" \
 	"DESTDIR=$(DESTDIR)"
 
-INCLUDES = -I. -I$(top_srcdir) $(ZINCS)
+INCLUDES = -I. -I$(top_srcdir) $(ZINCS) -I$(top_srcdir)/../include
 
+LIBIBERTY = ../libiberty/libiberty.a
+
 bin_PROGRAMS = jar grepjar
-jar_SOURCES = jartool.c dostime.c compress.c pushback.c jartool.h zipfile.h dostime.h compress.h pushback.h
-jar_LDADD = $(ZLIBS)
-jar_DEPENDENCIES = $(ZDEPS)
-grepjar_SOURCES = jargrep.c dostime.c compress.c pushback.c jartool.h zipfile.h dostime.h compress.h pushback.h
-grepjar_LDADD = $(ZLIBS)
-grepjar_DEPENDENCIES = $(ZDEPS)
+jar_SOURCES = jartool.c dostime.c compress.c pushback.c jartool.h \
+zipfile.h dostime.h compress.h pushback.h
+jar_LDADD = $(ZLIBS) $(LIBIBERTY)
+jar_DEPENDENCIES = $(ZDEPS) $(LIBIBERTY)
+
+grepjar_SOURCES = jargrep.c dostime.c compress.c pushback.c jartool.h \
+zipfile.h dostime.h compress.h pushback.h
+grepjar_LDADD = $(ZLIBS) $(LIBIBERTY)
+grepjar_DEPENDENCIES = $(ZDEPS) $(LIBIBERTY)
 
 AM_CFLAGS = @fastjar_warn_cflags@
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/fastjar/configure.in,v
retrieving revision 1.6
diff -u -r1.6 configure.in
--- configure.in 2002/01/03 04:57:56 1.6
+++ configure.in 2002/01/09 23:19:55
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(jartool.h)
-AM_INIT_AUTOMAKE(fastar, 0.92-gcc)
+AM_INIT_AUTOMAKE(fastjar, 0.92-gcc)
 AM_CONFIG_HEADER(config.h)
 
 dnl Checks for programs.
@@ -12,6 +12,8 @@
 AC_PATH_PROG(CHMOD, chmod, /bin/chmod, $PATH:/bin:/usr/bin:/usr/local/bin)
 AC_EXEEXT
 
+AM_MAINTAINER_MODE
+
 dnl Add warning flags if we are using gcc.
 if test "$GCC" = yes; then
   fastjar_warn_cflags='-W -Wall -pedantic -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings'
@@ -22,7 +24,7 @@
 AC_HEADER_DIRENT
 AC_HEADER_STDC
 AC_STRUCT_TM
-AC_CHECK_HEADERS(fcntl.h unistd.h sys/param.h getopt.h stdlib.h)
+AC_CHECK_HEADERS(fcntl.h unistd.h sys/param.h stdlib.h)
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_TYPE_OFF_T
Index: jargrep.c
===================================================================
RCS file: /cvs/gcc/gcc/fastjar/jargrep.c,v
retrieving revision 1.5
diff -u -r1.5 jargrep.c
--- jargrep.c 2002/01/03 04:57:56 1.5
+++ jargrep.c 2002/01/09 23:19:55
@@ -1,5 +1,6 @@
 /*
   jargrep.c - main functions for jargrep utility
+  Copyright (C) 2002 Free Software Foundation
   Copyright (C) 1999, 2000 Bryan Burns
   Copyright (C) 2000 Cory Hollingsworth 
  
@@ -21,9 +22,9 @@
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
-/* $Id: jargrep.c,v 1.5 2002/01/03 04:57:56 rodrigc Exp $
+/* Id: jargrep.c,v 1.5 2002/01/03 04:57:56 rodrigc Exp
 
-$Log: jargrep.c,v $
+Log: jargrep.c,v 
 Revision 1.5  2002/01/03 04:57:56  rodrigc
 2001-01-02  Craig Rodrigues  <rodrigc@gcc.gnu.org>
 
@@ -120,14 +121,12 @@
 #include "zipfile.h"
 #include "zlib.h"
 #include "compress.h"
-#ifdef HAVE_GETOPT_H
 #include <getopt.h>
-#endif
 
-#define Usage "Usage: %s [-bcinsw] <-e regexp | regexp> file(s)\n"
+void version(void);
+void help(const char *name);
 
-extern char *optarg;
-extern int optind;
+#define Usage "Usage: %s [-bcinsw] <-e PATTERN | PATTERN> FILE ...\n"
 
 /*
 Function name: opt_valid
@@ -647,6 +646,18 @@
 	}
 }
 
+/* This is used to mark options with no short value.  */
+#define LONG_OPT(Num)  ((Num) + 128)
+
+#define OPT_HELP     LONG_OPT (0)
+
+static const struct option option_vec[] =
+{
+  { "help", no_argument, NULL, OPT_HELP },
+  { "version", no_argument, NULL, 'V' },
+  { NULL, no_argument, NULL, 0 }
+};
+
 /*
 Funtion Name: main
 args:	argc	number of in coming args.
@@ -665,7 +676,8 @@
 	regex_t *nl_exp = NULL;
 	char *regexpstr = NULL;
 
-	while((c = getopt(argc, argv, "bce:insVw")) != -1) {
+	while((c = getopt_long(argc, argv, "bce:insVw",
+			       option_vec, NULL)) != -1) {
 		switch(c) {
 			case 'b':
 				options |= JG_PRINT_BYTEOFFSET;
@@ -694,13 +706,15 @@
 				options |= JG_INVERT;
 				break;
 			case 'V':
-				printf("%s\n", GVERSION);
-				exit(0);
+				version ();
+				break;
 			case 'w':
 				options |= JG_WORD_EXPRESSIONS;
 				break;
+			case OPT_HELP:
+				help(argv[0]);
+				break;
 			default:
-				fprintf(stderr, "Unknown option -%c\n", c);
 				fprintf(stderr, Usage, argv[0]);
 				exit(1);
 		}
@@ -740,4 +754,35 @@
 	}
 
 	return retval;
+}
+
+void help(const char *filename)
+{
+  printf (Usage, filename);
+  printf ("\
+\n\
+Search files in a jar file for a pattern.\n\
+\n\
+   -b                print byte offset of match\n\
+   -c                print number of matches\n\
+   -i                compare case-insensitively\n\
+   -n                print line number of each match\n\
+   -s                suppress error messages\n\
+   -w                force PATTERN to match only whole words\n\
+   -e PATTERN        use PATTERN as regular exprssion\n\
+");
+
+  exit (0);
+}
+
+void version ()
+{
+  printf("grepjar (%s) %s\n\n", PACKAGE, VERSION);
+  printf("Copyright 1999, 2000, 2001  Bryan Burns\n");
+  printf("Copyright 2000 Cory Hollingsworth\n");
+  printf("Copyright 2002 Free Software Foundation\n");
+  printf("\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+  exit (0);
 }
Index: jargrep.h
===================================================================
RCS file: /cvs/gcc/gcc/fastjar/jargrep.h,v
retrieving revision 1.1
diff -u -r1.1 jargrep.h
--- jargrep.h 2000/12/09 03:08:23 1.1
+++ jargrep.h 2002/01/09 23:19:55
@@ -1,5 +1,6 @@
 /*
   jargrep.h - header file for jargrep utility
+  Copyright (C) 2002 Free Software Foundation
   Copyright (C) 2000 Cory Hollingsworth
 
   This program is free software; you can redistribute it and/or
@@ -17,9 +18,6 @@
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
-/*$Id: jargrep.h,v 1.1 2000/12/09 03:08:23 apbianco Exp $
-*/
-
 #define JG_PRINT_BYTEOFFSET		0x00000001
 #define JG_PRINT_COUNT			0x00000002
 #define JG_IGNORE_CASE			0x00000004
@@ -27,5 +25,3 @@
 #define JG_SUPRESS_ERROR		0x00000010
 #define JG_INVERT				0x00000020
 #define JG_WORD_EXPRESSIONS		0x00000040
-
-#define GVERSION "jargrep version 0.1 (09/12/2000)"
Index: jartool.c
===================================================================
RCS file: /cvs/gcc/gcc/fastjar/jartool.c,v
retrieving revision 1.10
diff -u -r1.10 jartool.c
--- jartool.c 2002/01/03 04:57:56 1.10
+++ jartool.c 2002/01/09 23:19:56
@@ -1,5 +1,6 @@
 /*
   jartool.c - main functions for fastjar utility
+  Copyright (C) 2002 Free Software Foundation
   Copyright (C) 1999, 2000, 2001  Bryan Burns
   
   This program is free software; you can redistribute it and/or
@@ -17,9 +18,7 @@
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
-/* $Id: jartool.c,v 1.10 2002/01/03 04:57:56 rodrigc Exp $
-
-   $Log: jartool.c,v $
+/*
    Revision 1.10  2002/01/03 04:57:56  rodrigc
    2001-01-02  Craig Rodrigues  <rodrigc@gcc.gnu.org>
 
@@ -232,6 +231,8 @@
 #include <time.h>
 #endif
 
+#include <getopt.h>
+
 #include "jartool.h"
 #include "zipfile.h"
 #include "dostime.h"
@@ -249,8 +250,6 @@
 
 #endif
 
-static char version_string[] = VERSION;
-
 #ifndef errno
 extern int errno;
 #endif
@@ -260,6 +259,8 @@
 #endif
 
 void usage(const char*);
+void help(const char *);
+void version(void);
 void add_entry(struct zipentry *);
 void init_headers(void);
 
@@ -273,6 +274,7 @@
 static void init_args(char **, int);
 static char *get_next_arg (void);
 static char *jt_strdup (char*);
+static void expand_options (int *argcp, char ***argvp);
 
 /* global variables */
 ub1 file_header[30];
@@ -296,19 +298,37 @@
 
 int number_of_entries; /* number of entries in the linked list */
 
+/* This is used to mark options with no short value.  */
+#define LONG_OPT(Num)  ((Num) + 128)
+
+#define OPT_HELP     LONG_OPT (0)
+
+/* This holds all options except `-C', which is handled specially.  */
+#define OPTION_STRING "-ctxuvVf:m:0ME@"
+
+static const struct option options[] =
+{
+  { "help", no_argument, NULL, OPT_HELP },
+  { "version", no_argument, NULL, 'V' },
+  { NULL, no_argument, NULL, 0 }
+};
+
 int main(int argc, char **argv){
 
-  char mfile[256];
+  char *mfile = NULL;
   
   int action = ACTION_NONE;
   int manifest = TRUE;
-  int manifest_file = FALSE;
-  int file = FALSE;
-  int file_first = FALSE;
+  int opt;
   
-  int i, j;
+  int j;
   int jarfd = -1;
   
+  /* These are used to collect file names and `-C' options for the
+     second pass through the command line.  */
+  int new_argc;
+  char **new_argv;
+
   do_compress = TRUE;
   verbose = FALSE;
   
@@ -321,8 +341,18 @@
   
   j = strlen(argv[1]);
   
-  for(i = 0; i < j; i++){
-    switch(argv[1][i]){
+  new_argc = 0;
+  new_argv = (char **) malloc (argc * sizeof (char *));
+
+  expand_options (&argc, &argv);
+  while ((opt = getopt_long (argc, argv, OPTION_STRING,
+			     options, NULL)) != -1) {
+    switch(opt){
+    case 1:
+      /* File name or unparsed option, due to RETURN_IN_ORDER.  In
+	 particular `-C' is handled here and not elsewhere.  */
+      new_argv[new_argc++] = optarg;
+      break;
     case 'c':
       action = ACTION_CREATE;
       break;
@@ -339,17 +369,13 @@
       verbose = TRUE;
       break;
     case 'V':
-      printf("%s\n", version_string);
+      version();
       exit(0);
     case 'f':
-      file = TRUE;
-      if(!manifest_file)
-        file_first = TRUE;
-      else
-        file_first = FALSE;
+      jarfile = optarg;
       break;
     case 'm':
-      manifest_file = TRUE;
+      mfile = optarg;
       break;
     case '0':
       do_compress = FALSE;
@@ -357,8 +383,11 @@
     case 'M':
       manifest = FALSE;
       break;
-    case '-':
+
+    case OPT_HELP:
+      help(argv[0]);
       break;
+
     /* The following options aren't supported by the original jar tool. */
     case 'E':
       use_explicit_list_only = TRUE;
@@ -367,16 +396,25 @@
       read_names_from_stdin = TRUE;
       break;
     default:
-      fprintf(stderr, "Illegal option: %c\n", argv[1][i]);
       usage(argv[0]);
     }
   }
 
+  /* We might have seen `--'.  In this case we want to make sure that
+     all following options are handled as file names.  */
+  while (optind < argc)
+    new_argv[new_argc++] = argv[optind++];
+
   if(action == ACTION_NONE){
     fprintf(stderr, "One of options -{ctxu} must be specified.\n");
     usage(argv[0]);
   }
 
+  if(action == ACTION_UPDATE){
+    fprintf(stderr, "%s: `-u' mode unimplemented.\n", argv[0]);
+    exit(1);
+  }
+
   /* Verify unsupported combinations and warn of the use of non
      standard features */
   if(verbose && use_explicit_list_only)
@@ -389,32 +427,9 @@
       usage(argv[0]);
   }
 
-  i = 2;
-
-  /* get the jarfile and manifest file (if any) */
-  if(file && file_first){
-    if(i >= argc)
-      usage(argv[0]);
-
-    jarfile = jt_strdup (argv[i++]);
-  }
-  if(manifest_file){
-    if(i >= argc)
-      usage(argv[0]);
-
-    strncpy(mfile, argv[i++], 256);
-  }
-
-  if(file && !file_first){
-    if(i >= argc)
-      usage(argv[0]);
-
-    jarfile = jt_strdup (argv[i++]);
-  }
-
   /* create the jarfile */
   if(action == ACTION_CREATE){
-    if(file){
+    if(jarfile){
       jarfd = open(jarfile, O_CREAT | O_BINARY | O_WRONLY | O_TRUNC,
 		   S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
@@ -440,7 +455,7 @@
     }
   } else if(action == ACTION_LIST || action == ACTION_EXTRACT){
 
-    if(file){
+    if(jarfile){
       jarfd = open(jarfile, O_RDONLY | O_BINARY);
 
       if(jarfd < 0){
@@ -462,7 +477,7 @@
     const char *arg;
     init_headers();
 
-   if((action == ACTION_UPDATE) && file) {
+   if((action == ACTION_UPDATE) && jarfile) {
       if((jarfd = open(jarfile, O_RDWR | O_BINARY)) < 0) {
 	fprintf(stderr, "Error opening %s for reading!\n", jarfile);
         perror(jarfile);
@@ -475,12 +490,12 @@
   
 
     /* Add the META-INF/ directory and the manifest */
-    if(manifest && manifest_file)
+    if(manifest && mfile)
       make_manifest(jarfd, mfile);
     else if(manifest)
       make_manifest(jarfd, NULL);
     
-    init_args (argv, i);
+    init_args (new_argv, new_argc);
     /* now we add the files to the archive */
     while ((arg = get_next_arg ())){
 
@@ -510,9 +525,9 @@
       fprintf(stderr, "Error closing jar archive!\n");
     }
   } else if(action == ACTION_LIST){
-    list_jar(jarfd, &argv[i], (argc - i));
+    list_jar(jarfd, &new_argv[0], new_argc);
   } else if(action == ACTION_EXTRACT){
-    extract_jar(jarfd, &argv[i], (argc - i));
+    extract_jar(jarfd, &new_argv[0], new_argc);
   }
   
   exit(0);
@@ -1845,26 +1860,47 @@
 }
 
 void usage(const char *filename){
-  fprintf(stderr, "\
+  fprintf(stderr, "Try `%s --help' for more information.\n", filename);
+  exit (1);
+}
+
+void version ()
+{
+  printf("jar (%s) %s\n\n", PACKAGE, VERSION);
+  printf("Copyright 1999, 2000, 2001  Bryan Burns\n");
+  printf("Copyright 2002 Free Software Foundation\n");
+  printf("\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+  exit (0);
+}
+
+void help(const char *filename)
+{
+  printf("\
 Usage: %s {ctxuV}[vfm0ME@] [jar-file] [manifest-file] [-C dir] files ...\n\
-Options\n\
- -c  create new archive\n\
- -t  list table of contents for archive\n\
- -x  extract named (or all) files from archive\n\
+\n\
+Store many files together in a single `jar' file.\n\
+\n\
+  -c              create new archive\n\
+  -t              list table of contents for archive\n\
+  -x              extract named (or all) files from archive\n\
+  -u              update existing archive\n\
 ", filename);
-  fprintf(stderr, "\
- -u  update existing archive\n\
- -V  display version information\n\
- -v  generate verbose output on standard output\n\
- -f  specify archive file name\n\
- -m  include manifest information from specified manifest file\n\
- -0  store only; use no ZIP compression\n\
- -M  Do not create a manifest file for the entries\n\
- -C  change to the specified directory and include the following file\n\
- -E  don't include the files found in a directory\n\
- -@  Read names from stdin\n\
+  printf("\n\
+  -@              read names from stdin\n\
+  -0              store only; use no ZIP compression\n\
+  -C DIR FILE     change to the specified directory and include\n\
+                  the following file\n\
+  -E              don't include the files found in a directory\n\
+  -f FILE         specify archive file name\n\
+  --help          print this help, then exit\n\
+  -m FILE         include manifest information from specified manifest file\n\
+  -M              Do not create a manifest file for the entries\n\
+  -v              generate verbose output on standard output\n\
+  -V, --version   display version information\n\
 ");
-  fprintf(stderr, "\
+  printf("\n\
 If any file is a directory then it is processed recursively.\n\
 The manifest file name and the archive file name needs to be specified\n\
 in the same order the 'm' and 'f' flags are specified.\n\
@@ -1876,7 +1912,7 @@
      jar cvfm classes.jar mymanifest -C foo/ .\n\
 ");
 
-  exit(1);
+  exit(0);
 }
 
 static char *
@@ -1888,4 +1924,60 @@
     return (char*)0;
   strcpy(result, s);
   return result;
+}
+
+/* Convert "tar-style" first argument to a form expected by getopt.
+   This idea and the code comes from GNU tar.  This can allocate a new
+   argument vector.  This might leak some memory, but we don't care.  */
+static void
+expand_options (int *argcp, char ***argvp)
+{
+  int argc = *argcp;
+  char **argv = *argvp;
+
+  if (argc > 1 && argv[1][0] != '-')
+    {
+      char buf[3];
+      char **new_argv;
+      int new_argc;
+      char *p;
+      char **in, **out;
+
+      buf[0] = '-';
+      buf[2] = '\0';
+
+      new_argc = argc - 1 + strlen (argv[1]);
+      new_argv = (char **) malloc (new_argc * sizeof (char *));
+      in = argv;
+      out = new_argv;
+
+      *out++ = *in++;
+      for (p = *in++; *p; ++p)
+	{
+	  char *opt;
+	  buf[1] = *p;
+	  *out++ = jt_strdup (buf);
+	  /* If the option takes an argument, move the next argument
+	     to just after this option.  */
+	  opt = strchr (OPTION_STRING, *p);
+	  if (opt && opt[1] == ':')
+	    {
+	      if (in < argv + argc)
+		*out++ = *in++;
+	      else
+		{
+		  fprintf(stderr, "%s: option `%s' requires an argument.\n",
+			  argv[0], buf);
+		  usage(argv[0]);
+		}
+	    }
+	}
+
+      /* Copy remaining options.  */
+      while (in < argv + argc)
+	*out++ = *in++;
+
+      *argcp = new_argc;
+      *argvp = new_argv;
+    }
 }



More information about the Java-patches mailing list