Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/sort Rework previous change to fixit() to not trip o...
details: https://anonhg.NetBSD.org/src/rev/c4eb1ef73f6a
branches: trunk
changeset: 755426:c4eb1ef73f6a
user: dholland <dholland%NetBSD.org@localhost>
date: Sat Jun 05 17:46:08 2010 +0000
description:
Rework previous change to fixit() to not trip on option arguments. (Noticed
by wiz.) Clarify the loop logic involved.
diffstat:
usr.bin/sort/init.c | 121 +++++++++++++++++++++++++++++++++++++++------------
1 files changed, 91 insertions(+), 30 deletions(-)
diffs (181 lines):
diff -r e5cc13a843eb -r c4eb1ef73f6a usr.bin/sort/init.c
--- a/usr.bin/sort/init.c Sat Jun 05 17:44:51 2010 +0000
+++ b/usr.bin/sort/init.c Sat Jun 05 17:46:08 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: init.c,v 1.25 2010/05/27 05:52:29 dholland Exp $ */
+/* $NetBSD: init.c,v 1.26 2010/06/05 17:46:08 dholland Exp $ */
/*-
* Copyright (c) 2000-2003 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
#include "sort.h"
-__RCSID("$NetBSD: init.c,v 1.25 2010/05/27 05:52:29 dholland Exp $");
+__RCSID("$NetBSD: init.c,v 1.26 2010/06/05 17:46:08 dholland Exp $");
#include <ctype.h>
#include <string.h>
@@ -238,38 +238,99 @@
}
/*
+ * Return true if the options found in ARG, according to the getopt
+ * spec in OPTS, require an additional argv word as an option
+ * argument.
+ */
+static int
+options_need_argument(const char *arg, const char *opts)
+{
+ size_t pos;
+ const char *s;
+
+ /*assert(arg[0] == '-');*/
+
+ pos = 1;
+ while (arg[pos]) {
+ s = strchr(opts, arg[pos]);
+ if (s == NULL) {
+ /* invalid option */
+ return 0;
+ }
+ if (s[1] == ':') {
+ /* option requires argument */
+ if (arg[pos+1] == '\0') {
+ /* no argument in this arg */
+ return 1;
+ }
+ else {
+ /* argument is in this arg; no more options */
+ return 0;
+ }
+ }
+ pos++;
+ }
+ return 0;
+}
+
+/*
* Replace historic +SPEC arguments with appropriate -kSPEC.
+ *
+ * The form can be either a single +SPEC or a pair +SPEC -SPEC.
+ * The followiing -SPEC is not recognized unless it follows
+ * immediately.
*/
void
-fixit(int *argc, char **argv)
+fixit(int *argc, char **argv, const char *opts)
{
- int i, j, fplus=0;
+ int i, j, sawplus;
char *vpos, *tpos, spec[20];
int col, indent;
size_t sz;
+ sawplus = 0;
for (i = 1; i < *argc; i++) {
/*
- * Stop where getopt will stop, to avoid turning e.g.
- * "sort x +3" into "sort x -k4.1" which will croak if
- * +3 was in fact really a file name.
+ * This loop must stop exactly where getopt will stop.
+ * Otherwise it turns e.g. "sort x +3" into "sort x
+ * -k4.1", which will croak if +3 was in fact really a
+ * file name. In order to do this reliably we need to
+ * be able to identify argv words that are option
+ * arguments.
*/
- if (argv[i][0] == '-' && argv[i][1] == '-')
- break;
- if (argv[i][0] != '-' && argv[i][0] != '+')
- break;
- if (argv[i][0] != '+' && !fplus)
- continue;
-
- if (fplus && (argv[i][0] != '-' || !isdigit((unsigned char)argv[i][1]))) {
- fplus = 0;
- if (argv[i][0] != '+') {
- /* not a -POS argument, skip */
- continue;
- }
+ if (!strcmp(argv[i], "--")) {
+ /* End of options; stop. */
+ break;
}
+ if (argv[i][0] == '+') {
+ /* +POS argument */
+ sawplus = 1;
+ } else if (argv[i][0] == '-' && sawplus &&
+ isdigit((unsigned char)argv[i][1])) {
+ /* -POS argument */
+ sawplus = 0;
+ } else if (argv[i][0] == '-') {
+ /* other option */
+ sawplus = 0;
+ if (options_need_argument(argv[i], opts)) {
+ /* skip over the argument */
+ i++;
+ }
+ continue;
+ } else {
+ /* not an option at all; stop */
+ sawplus = 0;
+ break;
+ }
+
+ /*
+ * At this point argv[i] is an old-style spec. The
+ * sawplus flag used by the above loop logic also
+ * tells us if it's a +SPEC or -SPEC.
+ */
+
/* parse spec */
tpos = argv[i]+1;
col = (int)strtol(tpos, &tpos, 10);
@@ -278,14 +339,14 @@
indent = (int) strtol(tpos, &tpos, 10);
} else
indent = 0;
- /* tpos points to optional flags now */
+ /* tpos now points to the optional flags */
/*
- * For x.y, the obsolescent variant assumed 0 == beginning
- * of line, while the new form uses 0 == end of line.
- * Convert accordingly.
+ * In the traditional form, x.0 means beginning of line;
+ * in the new form, x.0 means end of line. Adjust the
+ * value of INDENT accordingly.
*/
- if (!fplus) {
+ if (sawplus) {
/* +POS */
col += 1;
indent += 1;
@@ -295,19 +356,19 @@
col += 1;
}
- /* new style spec */
+ /* make the new style spec */
sz = snprintf(spec, sizeof(spec), "%d.%d%s", col, indent,
tpos);
- if (!fplus) {
+ if (sawplus) {
/* Replace the +POS argument with new-style -kSPEC */
asprintf(&vpos, "-k%s", spec);
argv[i] = vpos;
- fplus = 1;
} else {
/*
- * Append the spec to one previously generated from
- * +POS argument, and remove the argv element.
+ * Append the spec to the one from the
+ * preceding +POS argument, and remove the
+ * current argv element entirely.
*/
asprintf(&vpos, "%s,%s", argv[i-1], spec);
free(argv[i-1]);
Home |
Main Index |
Thread Index |
Old Index