Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make make(1): move ParseModifierPart further down in...
details: https://anonhg.NetBSD.org/src/rev/0971fe749c2a
branches: trunk
changeset: 938978:0971fe749c2a
user: rillig <rillig%NetBSD.org@localhost>
date: Tue Sep 22 17:42:57 2020 +0000
description:
make(1): move ParseModifierPart further down in the code
This way, it can access the ApplyModifierState, which will be used in a
follow-up commit to reduce the code duplication around the error
handling for missing delimiters.
diffstat:
usr.bin/make/var.c | 305 ++++++++++++++++++++++++++--------------------------
1 files changed, 153 insertions(+), 152 deletions(-)
diffs (truncated from 421 to 300 lines):
diff -r efaeb3125eff -r 0971fe749c2a usr.bin/make/var.c
--- a/usr.bin/make/var.c Tue Sep 22 16:18:54 2020 +0000
+++ b/usr.bin/make/var.c Tue Sep 22 17:42:57 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.528 2020/09/22 06:23:33 rillig Exp $ */
+/* $NetBSD: var.c,v 1.529 2020/09/22 17:42:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -121,7 +121,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.528 2020/09/22 06:23:33 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.529 2020/09/22 17:42:57 rillig Exp $");
#define VAR_DEBUG_IF(cond, fmt, ...) \
if (!(DEBUG(VAR) && (cond))) \
@@ -1585,141 +1585,6 @@
}
-/*-
- * Parse a part of a modifier such as the "from" and "to" in :S/from/to/
- * or the "var" or "replacement" in :@var@replacement+${var}@, up to and
- * including the next unescaped delimiter. The delimiter, as well as the
- * backslash or the dollar, can be escaped with a backslash.
- *
- * Return the parsed (and possibly expanded) string, or NULL if no delimiter
- * was found. On successful return, the parsing position pp points right
- * after the delimiter. The delimiter is not included in the returned
- * value though.
- */
-static char *
-ParseModifierPart(
- const char **pp, /* The parsing position, updated upon return */
- int delim, /* Parsing stops at this delimiter */
- VarEvalFlags eflags, /* Flags for evaluating nested variables;
- * if VARE_WANTRES is not set, the text is
- * only parsed */
- GNode *ctxt, /* For looking up nested variables */
- size_t *out_length, /* Optionally stores the length of the returned
- * string, just to save another strlen call. */
- VarPatternFlags *out_pflags,/* For the first part of the :S modifier,
- * sets the VARP_ANCHOR_END flag if the last
- * character of the pattern is a $. */
- ModifyWord_SubstArgs *subst /* For the second part of the :S modifier,
- * allow ampersands to be escaped and replace
- * unescaped ampersands with subst->lhs. */
-) {
- Buffer buf;
- const char *p;
- char *rstr;
-
- Buf_Init(&buf, 0);
-
- /*
- * Skim through until the matching delimiter is found;
- * pick up variable substitutions on the way. Also allow
- * backslashes to quote the delimiter, $, and \, but don't
- * touch other backslashes.
- */
- p = *pp;
- while (*p != '\0' && *p != delim) {
- const char *varstart;
-
- Boolean is_escaped = p[0] == '\\' && (
- p[1] == delim || p[1] == '\\' || p[1] == '$' ||
- (p[1] == '&' && subst != NULL));
- if (is_escaped) {
- Buf_AddByte(&buf, p[1]);
- p += 2;
- continue;
- }
-
- if (*p != '$') { /* Unescaped, simple text */
- if (subst != NULL && *p == '&')
- Buf_AddBytes(&buf, subst->lhs, subst->lhsLen);
- else
- Buf_AddByte(&buf, *p);
- p++;
- continue;
- }
-
- if (p[1] == delim) { /* Unescaped $ at end of pattern */
- if (out_pflags != NULL)
- *out_pflags |= VARP_ANCHOR_END;
- else
- Buf_AddByte(&buf, *p);
- p++;
- continue;
- }
-
- if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */
- const char *nested_p = p;
- const char *nested_val;
- void *nested_val_freeIt;
- VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN;
-
- (void)Var_Parse(&nested_p, ctxt, nested_eflags,
- &nested_val, &nested_val_freeIt);
- /* TODO: handle errors */
- Buf_AddStr(&buf, nested_val);
- free(nested_val_freeIt);
- p += nested_p - p;
- continue;
- }
-
- /* XXX: This whole block is very similar to Var_Parse without
- * VARE_WANTRES. There may be subtle edge cases though that are
- * not yet covered in the unit tests and that are parsed differently,
- * depending on whether they are evaluated or not.
- *
- * This subtle difference is not documented in the manual page,
- * neither is the difference between parsing :D and :M documented.
- * No code should ever depend on these details, but who knows. */
-
- varstart = p; /* Nested variable, only parsed */
- if (p[1] == '(' || p[1] == '{') {
- /*
- * Find the end of this variable reference
- * and suck it in without further ado.
- * It will be interpreted later.
- */
- int have = p[1];
- int want = have == '(' ? ')' : '}';
- int depth = 1;
-
- for (p += 2; *p != '\0' && depth > 0; p++) {
- if (p[-1] != '\\') {
- if (*p == have)
- depth++;
- if (*p == want)
- depth--;
- }
- }
- Buf_AddBytesBetween(&buf, varstart, p);
- } else {
- Buf_AddByte(&buf, *varstart);
- p++;
- }
- }
-
- if (*p != delim) {
- *pp = p;
- return NULL;
- }
-
- *pp = ++p;
- if (out_length != NULL)
- *out_length = Buf_Size(&buf);
-
- rstr = Buf_Destroy(&buf, FALSE);
- VAR_DEBUG("Modifier part: \"%s\"\n", rstr);
- return rstr;
-}
-
/* Quote shell meta-characters and space characters in the string.
* If quoteDollar is set, also quote and double any '$' characters. */
static char *
@@ -1936,6 +1801,141 @@
* if st->missing_delim is set. */
} ApplyModifierResult;
+/*-
+ * Parse a part of a modifier such as the "from" and "to" in :S/from/to/
+ * or the "var" or "replacement" in :@var@replacement+${var}@, up to and
+ * including the next unescaped delimiter. The delimiter, as well as the
+ * backslash or the dollar, can be escaped with a backslash.
+ *
+ * Return the parsed (and possibly expanded) string, or NULL if no delimiter
+ * was found. On successful return, the parsing position pp points right
+ * after the delimiter. The delimiter is not included in the returned
+ * value though.
+ */
+static char *
+ParseModifierPart(
+ const char **pp, /* The parsing position, updated upon return */
+ int delim, /* Parsing stops at this delimiter */
+ VarEvalFlags eflags, /* Flags for evaluating nested variables;
+ * if VARE_WANTRES is not set, the text is
+ * only parsed */
+ ApplyModifiersState *st,
+ size_t *out_length, /* Optionally stores the length of the returned
+ * string, just to save another strlen call. */
+ VarPatternFlags *out_pflags,/* For the first part of the :S modifier,
+ * sets the VARP_ANCHOR_END flag if the last
+ * character of the pattern is a $. */
+ ModifyWord_SubstArgs *subst /* For the second part of the :S modifier,
+ * allow ampersands to be escaped and replace
+ * unescaped ampersands with subst->lhs. */
+) {
+ Buffer buf;
+ const char *p;
+ char *rstr;
+
+ Buf_Init(&buf, 0);
+
+ /*
+ * Skim through until the matching delimiter is found;
+ * pick up variable substitutions on the way. Also allow
+ * backslashes to quote the delimiter, $, and \, but don't
+ * touch other backslashes.
+ */
+ p = *pp;
+ while (*p != '\0' && *p != delim) {
+ const char *varstart;
+
+ Boolean is_escaped = p[0] == '\\' && (
+ p[1] == delim || p[1] == '\\' || p[1] == '$' ||
+ (p[1] == '&' && subst != NULL));
+ if (is_escaped) {
+ Buf_AddByte(&buf, p[1]);
+ p += 2;
+ continue;
+ }
+
+ if (*p != '$') { /* Unescaped, simple text */
+ if (subst != NULL && *p == '&')
+ Buf_AddBytes(&buf, subst->lhs, subst->lhsLen);
+ else
+ Buf_AddByte(&buf, *p);
+ p++;
+ continue;
+ }
+
+ if (p[1] == delim) { /* Unescaped $ at end of pattern */
+ if (out_pflags != NULL)
+ *out_pflags |= VARP_ANCHOR_END;
+ else
+ Buf_AddByte(&buf, *p);
+ p++;
+ continue;
+ }
+
+ if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */
+ const char *nested_p = p;
+ const char *nested_val;
+ void *nested_val_freeIt;
+ VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN;
+
+ (void)Var_Parse(&nested_p, st->ctxt, nested_eflags,
+ &nested_val, &nested_val_freeIt);
+ /* TODO: handle errors */
+ Buf_AddStr(&buf, nested_val);
+ free(nested_val_freeIt);
+ p += nested_p - p;
+ continue;
+ }
+
+ /* XXX: This whole block is very similar to Var_Parse without
+ * VARE_WANTRES. There may be subtle edge cases though that are
+ * not yet covered in the unit tests and that are parsed differently,
+ * depending on whether they are evaluated or not.
+ *
+ * This subtle difference is not documented in the manual page,
+ * neither is the difference between parsing :D and :M documented.
+ * No code should ever depend on these details, but who knows. */
+
+ varstart = p; /* Nested variable, only parsed */
+ if (p[1] == '(' || p[1] == '{') {
+ /*
+ * Find the end of this variable reference
+ * and suck it in without further ado.
+ * It will be interpreted later.
+ */
+ int have = p[1];
+ int want = have == '(' ? ')' : '}';
+ int depth = 1;
+
+ for (p += 2; *p != '\0' && depth > 0; p++) {
+ if (p[-1] != '\\') {
+ if (*p == have)
+ depth++;
+ if (*p == want)
+ depth--;
+ }
+ }
+ Buf_AddBytesBetween(&buf, varstart, p);
+ } else {
+ Buf_AddByte(&buf, *varstart);
+ p++;
+ }
+ }
+
+ if (*p != delim) {
+ *pp = p;
+ return NULL;
+ }
+
+ *pp = ++p;
+ if (out_length != NULL)
+ *out_length = Buf_Size(&buf);
+
+ rstr = Buf_Destroy(&buf, FALSE);
+ VAR_DEBUG("Modifier part: \"%s\"\n", rstr);
+ return rstr;
+}
+
/* Test whether mod starts with modname, followed by a delimiter. */
Home |
Main Index |
Thread Index |
Old Index