summaryrefslogtreecommitdiff
path: root/usr.bin/patch
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2003-07-22 20:17:07 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2003-07-22 20:17:07 +0000
commit3d92e59274e0a2d3343a9b936de7fbad28cb20f3 (patch)
tree6efe812a4f7bb0f71af9117db4e94fc49ec02fde /usr.bin/patch
parentc9549ed55691fa892303ed6a7113417079598b5f (diff)
Use getopt_long() to parse options instead of rolling our own.
OK deraadt@ and otto@
Diffstat (limited to 'usr.bin/patch')
-rw-r--r--usr.bin/patch/patch.120
-rw-r--r--usr.bin/patch/patch.c345
2 files changed, 143 insertions, 222 deletions
diff --git a/usr.bin/patch/patch.1 b/usr.bin/patch/patch.1
index 80f332bcadb..65dfe0e12b0 100644
--- a/usr.bin/patch/patch.1
+++ b/usr.bin/patch/patch.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: patch.1,v 1.7 2003/07/18 02:00:09 deraadt Exp $ -*- nroff -*-
+.\" $OpenBSD: patch.1,v 1.8 2003/07/22 20:17:06 millert Exp $ -*- nroff -*-
.\" Copyright 1986, Larry Wall
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -61,7 +61,7 @@
patch - apply a diff file to an original
.SH SYNOPSIS
.B patch
-[options] [origfile [patchfile]] [+ [options] [origfile]]...
+[options] [origfile [patchfile]]
.sp
but usually just
.sp
@@ -216,11 +216,6 @@ to patch must be determined for each diff listing,
and that the garbage before each diff listing will
be examined for interesting things such as filenames and revision level, as
mentioned previously.
-You can give switches (and another original file name) for the second and
-subsequent patches by separating the corresponding argument lists
-by a \*(L'+\*(R'.
-(The argument list for a second or subsequent patch may not specify a new
-patch file, however.)
.PP
.I Patch
recognizes the following switches:
@@ -394,17 +389,6 @@ makes
.I patch
do its work silently, unless an error occurs.
.TP 5
-.B \-S or \-\-skip
-causes
-.I patch
-to ignore this patch from the patch file, but continue on looking
-for the next patch in the file.
-Thus
-.sp
- patch -S + -S + <patchfile
-.sp
-will ignore the first and second of three patches.
-.TP 5
.B \-u or \-\-unified
forces
.I patch
diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c
index 348399f2c21..01b1ee0bd99 100644
--- a/usr.bin/patch/patch.c
+++ b/usr.bin/patch/patch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: patch.c,v 1.23 2003/07/22 17:18:49 otto Exp $ */
+/* $OpenBSD: patch.c,v 1.24 2003/07/22 20:17:06 millert Exp $ */
/*
* patch - a program to apply diffs to original files
@@ -27,7 +27,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: patch.c,v 1.23 2003/07/22 17:18:49 otto Exp $";
+static const char rcsid[] = "$OpenBSD: patch.c,v 1.24 2003/07/22 20:17:06 millert Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -36,6 +36,7 @@ static const char rcsid[] = "$OpenBSD: patch.c,v 1.23 2003/07/22 17:18:49 otto E
#include <assert.h>
#include <ctype.h>
+#include <getopt.h>
#include <string.h>
#include <stdlib.h>
@@ -60,8 +61,7 @@ static void spew_output(void);
static void dump_line(LINENUM);
static bool patch_match(LINENUM, LINENUM, LINENUM);
static bool similar(char *, char *, int);
-static int optcmp(const void *, const void *);
-static char decode_long_option(char *);
+static __dead void usage(void);
/* TRUE if -E was specified on command line. */
static int remove_empty_files = FALSE;
@@ -359,222 +359,159 @@ reinitialize_almost_everything(void)
skip_rest_of_patch = FALSE;
get_some_switches();
-
- if (filec >= 2)
- fatal("you may not change to a different patch file\n");
-}
-
-static char *
-nextarg(void)
-{
- if (!--Argc)
- fatal("missing argument after `%s'\n", *Argv);
- return *++Argv;
-}
-
-/* Module for handling of long options. */
-
-struct option {
- char *long_opt;
- char short_opt;
-};
-
-static int
-optcmp(const void *v1, const void *v2)
-{
- const struct option *a = v1, *b = v2;
-
- return strcmp(a->long_opt, b->long_opt);
-}
-
-/* Decode Long options beginning with "--" to their short equivalents. */
-
-static char
-decode_long_option(char *opt)
-{
- /*
- * This table must be sorted on the first field. We also decode
- * unimplemented options as those will be handled later anyway.
- */
- static struct option options[] = {
- {"batch", 't'},
- {"check", 'C'},
- {"context", 'c'},
- {"debug", 'x'},
- {"directory", 'd'},
- {"ed", 'e'},
- {"force", 'f'},
- {"forward", 'N'},
- {"fuzz", 'F'},
- {"ifdef", 'D'},
- {"ignore-whitespace", 'l'},
- {"normal", 'n'},
- {"output", 'o'},
- {"prefix", 'B'},
- {"quiet", 's'},
- {"reject-file", 'r'},
- {"remove-empty-files", 'E'},
- {"reverse", 'R'},
- {"silent", 's'},
- {"skip", 'S'},
- {"strip", 'p'},
- {"suffix", 'b'},
- {"unified", 'u'},
- {"version", 'v'},
- {"version-control", 'V'},
- };
- struct option key, *found;
-
- key.long_opt = opt;
- found = (struct option *) bsearch(&key, options,
- sizeof(options) / sizeof(options[0]),
- sizeof(options[0]), optcmp);
- return found ? found->short_opt : '\0';
}
-/* Process switches and filenames up to next '+' or end of list. */
+/* Process switches and filenames. */
static void
get_some_switches(void)
{
- char *s;
+ const char *options = "b:B:cCd:D:eEfF:lnNo:p::r:RstuvV:x:";
+ static struct option longopts[] = {
+ {"batch", no_argument, 0, 't'},
+ {"check", no_argument, 0, 'C'},
+ {"context", no_argument, 0, 'c'},
+ {"debug", required_argument, 0, 'x'},
+ {"directory", required_argument, 0, 'd'},
+ {"ed", no_argument, 0, 'e'},
+ {"force", no_argument, 0, 'f'},
+ {"forward", no_argument, 0, 'N'},
+ {"fuzz", required_argument, 0, 'F'},
+ {"ifdef", required_argument, 0, 'D'},
+ {"ignore-whitespace", no_argument, 0, 'l'},
+ {"normal", no_argument, 0, 'n'},
+ {"output", required_argument, 0, 'o'},
+ {"prefix", required_argument, 0, 'B'},
+ {"quiet", no_argument, 0, 's'},
+ {"reject-file", required_argument, 0, 'r'},
+ {"remove-empty-files", no_argument, 0, 'E'},
+ {"reverse", no_argument, 0, 'R'},
+ {"silent", no_argument, 0, 's'},
+ {"strip", optional_argument, 0, 'p'},
+ {"suffix", required_argument, 0, 'b'},
+ {"unified", no_argument, 0, 'u'},
+ {"version", no_argument, 0, 'v'},
+ {"version-control", required_argument, 0, 'V'},
+ {NULL, 0, 0, 0}
+ };
+ int ch;
rejname[0] = '\0';
Argc_last = Argc;
Argv_last = Argv;
if (!Argc)
return;
- for (Argc--, Argv++; Argc; Argc--, Argv++) {
- s = Argv[0];
- if (strEQ(s, "+")) {
- return; /* + will be skipped by for loop */
- }
- if (*s != '-' || !s[1]) {
- if (filec == MAXFILEC)
- fatal("too many file arguments\n");
- filearg[filec++] = savestr(s);
- } else {
- char opt;
-
- if (*(s + 1) == '-') {
- opt = decode_long_option(s + 2);
- s += strlen(s) - 1;
- } else
- opt = *++s;
- switch (opt) {
- case 'b':
- simple_backup_suffix = savestr(nextarg());
- break;
- case 'B':
- origprae = savestr(nextarg());
- break;
- case 'c':
- diff_type = CONTEXT_DIFF;
- break;
- case 'C':
- check_only = TRUE;
- break;
- case 'd':
- if (!*++s)
- s = nextarg();
- if (chdir(s) < 0)
- pfatal("can't cd to %s", s);
- break;
- case 'D':
- do_defines = TRUE;
- if (!*++s)
- s = nextarg();
- if (!isalpha(*s) && '_' != *s)
- fatal("argument to -D is not an identifier\n");
- snprintf(if_defined, sizeof if_defined,
- "#ifdef %s\n", s);
- snprintf(not_defined, sizeof not_defined,
- "#ifndef %s\n", s);
- snprintf(end_defined, sizeof end_defined,
- "#endif /* %s */\n", s);
- break;
- case 'e':
- diff_type = ED_DIFF;
- break;
- case 'E':
- remove_empty_files = TRUE;
- break;
- case 'f':
- force = TRUE;
- break;
- case 'F':
- if (!*++s)
- s = nextarg();
- else if (*s == '=')
- s++;
- maxfuzz = atoi(s);
- break;
- case 'l':
- canonicalize = TRUE;
- break;
- case 'n':
- diff_type = NORMAL_DIFF;
- break;
- case 'N':
- noreverse = TRUE;
- break;
- case 'o':
- outname = savestr(nextarg());
- break;
- case 'p':
- if (!*++s)
- s = nextarg();
- else if (*s == '=')
- s++;
- strippath = atoi(s);
- break;
- case 'r':
- if (strlcpy(rejname, nextarg(),
- sizeof(rejname)) >= sizeof(rejname))
- fatal("argument for -r is too long\n");
- break;
- case 'R':
- reverse = TRUE;
- reverse_flag_specified = TRUE;
- break;
- case 's':
- verbose = FALSE;
- break;
- case 'S':
- skip_rest_of_patch = TRUE;
- break;
- case 't':
- batch = TRUE;
- break;
- case 'u':
- diff_type = UNI_DIFF;
- break;
- case 'v':
- version();
- break;
- case 'V':
- backup_type = get_version(nextarg());
- break;
+ optreset = optind = 1;
+ while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'b':
+ simple_backup_suffix = savestr(optarg);
+ break;
+ case 'B':
+ origprae = savestr(optarg);
+ break;
+ case 'c':
+ diff_type = CONTEXT_DIFF;
+ break;
+ case 'C':
+ check_only = TRUE;
+ break;
+ case 'd':
+ if (chdir(optarg) < 0)
+ pfatal("can't cd to %s", optarg);
+ break;
+ case 'D':
+ do_defines = TRUE;
+ if (!isalpha(*optarg) && *optarg != '_')
+ fatal("argument to -D is not an identifier\n");
+ snprintf(if_defined, sizeof if_defined,
+ "#ifdef %s\n", optarg);
+ snprintf(not_defined, sizeof not_defined,
+ "#ifndef %s\n", optarg);
+ snprintf(end_defined, sizeof end_defined,
+ "#endif /* %s */\n", optarg);
+ break;
+ case 'e':
+ diff_type = ED_DIFF;
+ break;
+ case 'E':
+ remove_empty_files = TRUE;
+ break;
+ case 'f':
+ force = TRUE;
+ break;
+ case 'F':
+ maxfuzz = atoi(optarg);
+ break;
+ case 'l':
+ canonicalize = TRUE;
+ break;
+ case 'n':
+ diff_type = NORMAL_DIFF;
+ break;
+ case 'N':
+ noreverse = TRUE;
+ break;
+ case 'o':
+ outname = savestr(optarg);
+ break;
+ case 'p':
+ strippath = optarg ? atoi(optarg) : 0;
+ break;
+ case 'r':
+ if (strlcpy(rejname, optarg,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("argument for -r is too long\n");
+ break;
+ case 'R':
+ reverse = TRUE;
+ reverse_flag_specified = TRUE;
+ break;
+ case 's':
+ verbose = FALSE;
+ break;
+ case 't':
+ batch = TRUE;
+ break;
+ case 'u':
+ diff_type = UNI_DIFF;
+ break;
+ case 'v':
+ version();
+ break;
+ case 'V':
+ backup_type = get_version(optarg);
+ break;
#ifdef DEBUGGING
- case 'x':
- if (!*++s)
- s = nextarg();
- debug = atoi(s);
- break;
+ case 'x':
+ debug = atoi(optarg);
+ break;
#endif
- default:
- fprintf(stderr, "patch: unrecognized option `%s'\n",
- Argv[0]);
- fprintf(stderr, "\
-Usage: patch [options] [origfile [patchfile]] [+ [options] [origfile]]...\n\
-Options:\n\
- [-cCeEflnNRsStuv] [-b backup-ext] [-B backup-prefix] [-d directory]\n\
- [-D symbol] [-Fmax-fuzz] [-o out-file] [-p[strip-count]]\n\
- [-r rej-name] [-V {numbered,existing,simple}]\n");
- my_exit(1);
- }
+ default:
+ usage();
+ break;
}
}
+ Argc -= optind;
+ Argv += optind;
+
+ while (Argc > 0) {
+ if (filec == MAXFILEC)
+ fatal("too many file arguments\n");
+ filearg[filec++] = savestr(*Argv++);
+ Argc--;
+ }
+}
+
+static __dead void
+usage(void)
+{
+ fprintf(stderr,
+"usage: patch [-cCeEflnNRstuv] [-b backup-ext] [-B backup-prefix] [-d directory]\n"
+" [-D symbol] [-Fmax-fuzz] [-o out-file] [-p[strip-count]]\n"
+" [-r rej-name] [-V {numbered,existing,simple}]\n"
+" [origfile [patchfile]]\n");
+ my_exit(1);
}
/*