Module Name:    src
Committed By:   rillig
Date:           Wed Jul 29 20:57:31 UTC 2020

Modified Files:
        src/usr.bin/make: Makefile var.c

Log Message:
make(1): use specialized return type for ApplyModifier functions

This makes it immediately obvious what happens after a modifier has been
applied, instead of having to translate single-character mnemonics or
booleans to their actual intention.

This also reduces the size of the binary since there are fewer jumps.


To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/usr.bin/make/Makefile
cvs rdiff -u -r1.355 -r1.356 src/usr.bin/make/var.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/Makefile
diff -u src/usr.bin/make/Makefile:1.75 src/usr.bin/make/Makefile:1.76
--- src/usr.bin/make/Makefile:1.75	Sun Jul 26 20:04:57 2020
+++ src/usr.bin/make/Makefile	Wed Jul 29 20:57:31 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.75 2020/07/26 20:04:57 rillig Exp $
+#	$NetBSD: Makefile,v 1.76 2020/07/29 20:57:31 rillig Exp $
 #	@(#)Makefile	5.2 (Berkeley) 12/28/90
 
 PROG=	make
@@ -77,3 +77,10 @@ test: .MAKE
 
 accept: .MAKE
 	cd ${.CURDIR}/unit-tests && ${.MAKE} ${.TARGET}
+
+retest:
+	${.MAKE} -C ${.CURDIR}/unit-tests cleandir
+.if ${USE_COVERAGE} == yes
+	rm -f *.gcov *.gcda
+.endif
+	${.MAKE} test

Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.355 src/usr.bin/make/var.c:1.356
--- src/usr.bin/make/var.c:1.355	Wed Jul 29 20:33:38 2020
+++ src/usr.bin/make/var.c	Wed Jul 29 20:57:31 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 rillig Exp $	*/
+/*	$NetBSD: var.c,v 1.356 2020/07/29 20:57:31 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 rillig Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.356 2020/07/29 20:57:31 rillig Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 rillig Exp $");
+__RCSID("$NetBSD: var.c,v 1.356 2020/07/29 20:57:31 rillig Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -2066,6 +2066,14 @@ typedef struct {
 
 } ApplyModifiersState;
 
+typedef enum {
+    AMR_OK,			/* Continue parsing */
+    AMR_UNKNOWN,		/* Not a match, try others as well */
+    AMR_BAD,			/* Error out with message */
+    AMR_CLEANUP			/* Error out with "missing delimiter",
+				 * if st->missing_delim is set. */
+} ApplyModifierResult;
+
 /* we now have some modifiers with long names */
 static Boolean
 ModMatch(const char *mod, const char *modname, char endc)
@@ -2084,7 +2092,7 @@ ModMatchEq(const char *mod, const char *
 }
 
 /* :@var@...${var}...@ */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) {
     ModifyWord_LoopArgs args;
 
@@ -2095,14 +2103,14 @@ ApplyModifier_Loop(const char *mod, Appl
 				  st->ctxt, NULL, NULL, NULL);
     if (args.tvar == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     args.str = ParseModifierPart(&st->next, delim, st->eflags & ~VARE_WANTRES,
 				 st->ctxt, NULL, NULL, NULL);
     if (args.str == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES);
@@ -2114,11 +2122,11 @@ ApplyModifier_Loop(const char *mod, Appl
     Var_Delete(args.tvar, st->ctxt);
     free(args.tvar);
     free(args.str);
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :Ddefined or :Uundefined */
-static void
+static ApplyModifierResult
 ApplyModifier_Defined(const char *mod, ApplyModifiersState *st)
 {
     Buffer buf;			/* Buffer for patterns */
@@ -2179,15 +2187,16 @@ ApplyModifier_Defined(const char *mod, A
 	st->newVal = st->val;
 	Buf_Destroy(&buf, TRUE);
     }
+    return AMR_OK;
 }
 
 /* :gmtime */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Gmtime(const char *mod, ApplyModifiersState *st)
 {
     if (!ModMatchEq(mod, "gmtime", st->endc)) {
 	st->next = mod + 1;
-	return FALSE;
+	return AMR_UNKNOWN;
     }
 
     time_t utc;
@@ -2200,7 +2209,7 @@ ApplyModifier_Gmtime(const char *mod, Ap
 	st->next = mod + 6;
     }
     st->newVal = VarStrftime(st->val, 1, utc);
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :localtime */
@@ -2209,7 +2218,7 @@ ApplyModifier_Localtime(const char *mod,
 {
     if (!ModMatchEq(mod, "localtime", st->endc)) {
 	st->next = mod + 1;
-	return FALSE;
+	return AMR_UNKNOWN;
     }
 
     time_t utc;
@@ -2222,25 +2231,25 @@ ApplyModifier_Localtime(const char *mod,
 	st->next = mod + 9;
     }
     st->newVal = VarStrftime(st->val, 0, utc);
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :hash */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Hash(const char *mod, ApplyModifiersState *st)
 {
     if (!ModMatch(mod, "hash", st->endc)) {
 	st->next = mod + 1;
-	return FALSE;
+	return AMR_UNKNOWN;
     }
 
     st->newVal = VarHash(st->val);
     st->next = mod + 4;
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :P */
-static void
+static ApplyModifierResult
 ApplyModifier_Path(const char *mod, ApplyModifiersState *st)
 {
     if (st->v->flags & VAR_JUNK)
@@ -2256,10 +2265,11 @@ ApplyModifier_Path(const char *mod, Appl
     if (!st->newVal)
 	st->newVal = bmake_strdup(st->v->name);
     st->next = mod + 1;
+    return AMR_OK;
 }
 
 /* :!cmd! */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st)
 {
     st->next = mod + 1;
@@ -2268,7 +2278,7 @@ ApplyModifier_Exclam(const char *mod, Ap
 				  NULL, NULL, NULL);
     if (cmd == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     const char *emsg = NULL;
@@ -2279,20 +2289,20 @@ ApplyModifier_Exclam(const char *mod, Ap
     free(cmd);
 
     if (emsg)
-	Error(emsg, st->val);
+	Error(emsg, st->val);	/* XXX: why still return AMR_OK? */
 
     if (st->v->flags & VAR_JUNK)
 	st->v->flags |= VAR_KEEP;
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :range */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Range(const char *mod, ApplyModifiersState *st)
 {
     if (!ModMatchEq(mod, "range", st->endc)) {
 	st->next = mod + 1;
-	return FALSE;
+	return AMR_UNKNOWN;
     }
 
     int n;
@@ -2305,11 +2315,11 @@ ApplyModifier_Range(const char *mod, App
 	st->next = mod + 5;
     }
     st->newVal = VarRange(st->val, n);
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :Mpattern or :Npattern */
-static void
+static ApplyModifierResult
 ApplyModifier_Match(const char *mod, ApplyModifiersState *st)
 {
     Boolean copy = FALSE;	/* pattern should be, or has been, copied */
@@ -2381,10 +2391,11 @@ ApplyModifier_Match(const char *mod, App
     st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val,
 			     callback, pattern);
     free(pattern);
+    return AMR_OK;
 }
 
 /* :S,from,to, */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Subst(const char * const mod, ApplyModifiersState *st)
 {
     ModifyWord_SubstArgs args;
@@ -2407,7 +2418,7 @@ ApplyModifier_Subst(const char * const m
 				  &args.lhsLen, &args.pflags, NULL);
     if (lhs == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
     args.lhs = lhs;
 
@@ -2415,7 +2426,7 @@ ApplyModifier_Subst(const char * const m
 				  &args.rhsLen, NULL, &args);
     if (rhs == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
     args.rhs = rhs;
 
@@ -2444,13 +2455,13 @@ ApplyModifier_Subst(const char * const m
 
     free(lhs);
     free(rhs);
-    return TRUE;
+    return AMR_OK;
 }
 
 #ifndef NO_REGEX
 
 /* :C,from,to, */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Regex(const char *mod, ApplyModifiersState *st)
 {
     ModifyWord_SubstRegexArgs args;
@@ -2465,7 +2476,7 @@ ApplyModifier_Regex(const char *mod, App
 				 NULL, NULL, NULL);
     if (re == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     args.replace = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
@@ -2473,7 +2484,7 @@ ApplyModifier_Regex(const char *mod, App
     if (args.replace == NULL) {
 	free(re);
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     for (;; st->next++) {
@@ -2496,7 +2507,7 @@ ApplyModifier_Regex(const char *mod, App
     if (error) {
 	VarREError(error, &args.re, "RE substitution error");
 	free(args.replace);
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     args.nsub = args.re.re_nsub + 1;
@@ -2508,7 +2519,7 @@ ApplyModifier_Regex(const char *mod, App
 			     ModifyWord_SubstRegex, &args);
     regfree(&args.re);
     free(args.replace);
-    return TRUE;
+    return AMR_OK;
 }
 #endif
 
@@ -2519,7 +2530,7 @@ ModifyWord_Copy(const char *word, SepBuf
 }
 
 /* :ts<separator> */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st)
 {
     if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
@@ -2552,38 +2563,38 @@ ApplyModifier_ToSep(const char *sep, App
 	    goto get_numeric;
 	default:
 	    if (!isdigit((unsigned char)sep[1]))
-		return FALSE;	/* ":ts<backslash><unrecognised>". */
+		return AMR_BAD;	/* ":ts<backslash><unrecognised>". */
 
 	    char *end;
 	get_numeric:
 	    st->sep = strtoul(sep + 1 + (sep[1] == 'x'), &end, base);
 	    if (*end != ':' && *end != st->endc)
-	        return FALSE;
+	        return AMR_BAD;
 	    st->next = end;
 	    break;
 	}
     } else {
-	return FALSE;		/* Found ":ts<unrecognised><unrecognised>". */
+	return AMR_BAD;		/* Found ":ts<unrecognised><unrecognised>". */
     }
 
     st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val,
 			     ModifyWord_Copy, NULL);
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :tA, :tu, :tl, :ts<separator>, etc. */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_To(const char *mod, ApplyModifiersState *st)
 {
     st->next = mod + 1;		/* make sure it is set */
     if (mod[1] == st->endc || mod[1] == ':')
-	return FALSE;		/* Found ":t<endc>" or ":t:". */
+	return AMR_BAD;		/* Found ":t<endc>" or ":t:". */
 
     if (mod[1] == 's')
 	return ApplyModifier_ToSep(mod + 2, st);
 
     if (mod[2] != st->endc && mod[2] != ':')
-	return FALSE;		/* Found ":t<unrecognised><unrecognised>". */
+	return AMR_BAD;		/* Found ":t<unrecognised><unrecognised>". */
 
     /* Check for two-character options: ":tu", ":tl" */
     if (mod[1] == 'A') {	/* absolute path */
@@ -2606,13 +2617,13 @@ ApplyModifier_To(const char *mod, ApplyM
 	st->next = mod + 2;
     } else {
 	/* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
-	return FALSE;
+	return AMR_BAD;
     }
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :[#], :[1], etc. */
-static int
+static ApplyModifierResult
 ApplyModifier_Words(const char *mod, ApplyModifiersState *st)
 {
     st->next = mod + 1;		/* point to char after '[' */
@@ -2621,7 +2632,7 @@ ApplyModifier_Words(const char *mod, App
 				   NULL, NULL, NULL);
     if (estr == NULL) {
 	st->missing_delim = delim;
-	return 'c';
+	return AMR_CLEANUP;
     }
 
     /* now st->next points just after the closing ']' */
@@ -2706,15 +2717,15 @@ ApplyModifier_Words(const char *mod, App
 
 ok:
     free(estr);
-    return 0;
+    return AMR_OK;
 
 bad_modifier:
     free(estr);
-    return 'b';
+    return AMR_BAD;
 }
 
 /* :O or :Ox */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Order(const char *mod, ApplyModifiersState *st)
 {
     char otype;
@@ -2727,14 +2738,14 @@ ApplyModifier_Order(const char *mod, App
 	otype = mod[1];
 	st->next = mod + 2;
     } else {
-	return FALSE;
+	return AMR_BAD;
     }
     st->newVal = VarOrder(st->val, otype);
-    return TRUE;
+    return AMR_OK;
 }
 
 /* :? then : else */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_IfElse(const char *mod, ApplyModifiersState *st)
 {
     Boolean value = FALSE;
@@ -2756,7 +2767,7 @@ ApplyModifier_IfElse(const char *mod, Ap
 					NULL, NULL, NULL);
     if (then_expr == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     delim = st->endc;		/* BRCLOSE or PRCLOSE */
@@ -2764,14 +2775,14 @@ ApplyModifier_IfElse(const char *mod, Ap
 					NULL, NULL, NULL);
     if (else_expr == NULL) {
 	st->missing_delim = delim;
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     st->next--;
     if (cond_rc == COND_INVALID) {
 	Error("Bad conditional expression `%s' in %s?%s:%s",
 	    st->v->name, st->v->name, then_expr, else_expr);
-	return FALSE;
+	return AMR_CLEANUP;
     }
 
     if (value) {
@@ -2783,7 +2794,7 @@ ApplyModifier_IfElse(const char *mod, Ap
     }
     if (st->v->flags & VAR_JUNK)
 	st->v->flags |= VAR_KEEP;
-    return TRUE;
+    return AMR_OK;
 }
 
 /*
@@ -2807,20 +2818,20 @@ ApplyModifier_IfElse(const char *mod, Ap
  *	  ::!=<cmd>	Assigns output of <cmd> as the new value of
  *			variable.
  */
-static int
+static ApplyModifierResult
 ApplyModifier_Assign(const char *mod, ApplyModifiersState *st)
 {
     const char *op = mod + 1;
     if (!(op[0] == '=' ||
 	(op[1] == '=' &&
 	 (op[0] == '!' || op[0] == '+' || op[0] == '?'))))
-	return 'd';		/* "::<unrecognised>" */
+	return AMR_UNKNOWN;	/* "::<unrecognised>" */
 
     GNode *v_ctxt;		/* context where v belongs */
 
     if (st->v->name[0] == 0) {
 	st->next = mod + 1;
-	return 'b';
+	return AMR_BAD;
     }
 
     v_ctxt = st->ctxt;
@@ -2860,7 +2871,7 @@ ApplyModifier_Assign(const char *mod, Ap
     }
     if (val == NULL) {
 	st->missing_delim = delim;
-	return 'c';
+	return AMR_CLEANUP;
     }
 
     st->next--;
@@ -2891,16 +2902,16 @@ ApplyModifier_Assign(const char *mod, Ap
     }
     free(val);
     st->newVal = varNoError;
-    return 0;
+    return AMR_OK;
 }
 
 /* remember current value */
-static Boolean
+static ApplyModifierResult
 ApplyModifier_Remember(const char *mod, ApplyModifiersState *st)
 {
     if (!ModMatchEq(mod, "_", st->endc)) {
 	st->next = mod + 1;
-	return FALSE;
+	return AMR_UNKNOWN;
     }
 
     if (mod[1] == '=') {
@@ -2914,12 +2925,12 @@ ApplyModifier_Remember(const char *mod, 
 	st->next = mod + 1;
     }
     st->newVal = st->val;
-    return TRUE;
+    return AMR_OK;
 }
 
 #ifdef SYSVVARSUB
 /* :from=to */
-static int
+static ApplyModifierResult
 ApplyModifier_SysV(const char *mod, ApplyModifiersState *st)
 {
     Boolean eqFound = FALSE;
@@ -2943,7 +2954,7 @@ ApplyModifier_SysV(const char *mod, Appl
 	    st->next++;
     }
     if (*st->next != st->endc || !eqFound)
-	return 0;
+	return AMR_UNKNOWN;
 
     char delim = '=';
     st->next = mod;
@@ -2951,7 +2962,7 @@ ApplyModifier_SysV(const char *mod, Appl
 				  NULL, NULL, NULL);
     if (lhs == NULL) {
 	st->missing_delim = delim;
-	return 'c';
+	return AMR_CLEANUP;
     }
 
     delim = st->endc;
@@ -2959,7 +2970,7 @@ ApplyModifier_SysV(const char *mod, Appl
 				  NULL, NULL, NULL);
     if (rhs == NULL) {
 	st->missing_delim = delim;
-	return 'c';
+	return AMR_CLEANUP;
     }
 
     /*
@@ -2976,7 +2987,7 @@ ApplyModifier_SysV(const char *mod, Appl
     }
     free(lhs);
     free(rhs);
-    return '=';
+    return AMR_OK;
 }
 #endif
 
@@ -3117,89 +3128,65 @@ ApplyModifiers(char *val, const char * c
 	    fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", st.v->name,
 		*p, st.val);
 	}
-	st.newVal = var_Error;
+	st.newVal = var_Error;		/* default value, in case of errors */
+	st.next = NULL; /* fail fast if an ApplyModifier forgets to set this */
+	ApplyModifierResult res = 0;
 	char modifier = *p;
-	st.next = NULL;	/* fail fast if an ApplyModifier forgets to set this */
 	switch (modifier) {
 	case ':':
-	    {
-		int res = ApplyModifier_Assign(p, &st);
-		if (res == 'b')
-		    goto bad_modifier;
-		if (res == 'c')
-		    goto cleanup;
-		if (res == 'd')
-		    goto default_case;
-		break;
-	    }
+	    res = ApplyModifier_Assign(p, &st);
+	    break;
 	case '@':
-	    if (!ApplyModifier_Loop(p, &st))
-		goto cleanup;
+	    res = ApplyModifier_Loop(p, &st);
 	    break;
 	case '_':
-	    if (!ApplyModifier_Remember(p, &st))
-		goto default_case;
+	    res = ApplyModifier_Remember(p, &st);
 	    break;
 	case 'D':
 	case 'U':
-	    ApplyModifier_Defined(p, &st);
+	    res = ApplyModifier_Defined(p, &st);
 	    break;
 	case 'L':
-	    {
-		if (st.v->flags & VAR_JUNK)
-		    st.v->flags |= VAR_KEEP;
-		st.newVal = bmake_strdup(st.v->name);
-		st.next = p + 1;
-		break;
-	    }
+	    if (st.v->flags & VAR_JUNK)
+		st.v->flags |= VAR_KEEP;
+	    st.newVal = bmake_strdup(st.v->name);
+	    st.next = p + 1;
+	    res = AMR_OK;
+	    break;
 	case 'P':
-	    ApplyModifier_Path(p, &st);
+	    res = ApplyModifier_Path(p, &st);
 	    break;
 	case '!':
-	    if (!ApplyModifier_Exclam(p, &st))
-		goto cleanup;
+	    res = ApplyModifier_Exclam(p, &st);
 	    break;
 	case '[':
-	    {
-		int res = ApplyModifier_Words(p, &st);
-		if (res == 'b')
-		    goto bad_modifier;
-		if (res == 'c')
-		    goto cleanup;
-		break;
-	    }
+	    res = ApplyModifier_Words(p, &st);
+	    break;
 	case 'g':
-	    if (!ApplyModifier_Gmtime(p, &st))
-		goto default_case;
+	    res = ApplyModifier_Gmtime(p, &st);
 	    break;
 	case 'h':
-	    if (!ApplyModifier_Hash(p, &st))
-		goto default_case;
+	    res = ApplyModifier_Hash(p, &st);
 	    break;
 	case 'l':
-	    if (!ApplyModifier_Localtime(p, &st))
-		goto default_case;
+	    res = ApplyModifier_Localtime(p, &st);
 	    break;
 	case 't':
-	    if (!ApplyModifier_To(p, &st))
-		goto bad_modifier;
+	    res = ApplyModifier_To(p, &st);
 	    break;
 	case 'N':
 	case 'M':
-	    ApplyModifier_Match(p, &st);
+	    res = ApplyModifier_Match(p, &st);
 	    break;
 	case 'S':
-	    if (!ApplyModifier_Subst(p, &st))
-		goto cleanup;
+	    res = ApplyModifier_Subst(p, &st);
 	    break;
 	case '?':
-	    if (!ApplyModifier_IfElse(p, &st))
-		goto cleanup;
+	    res = ApplyModifier_IfElse(p, &st);
 	    break;
 #ifndef NO_REGEX
 	case 'C':
-	    if (!ApplyModifier_Regex(p, &st))
-		goto cleanup;
+	    res = ApplyModifier_Regex(p, &st);
 	    break;
 #endif
 	case 'q':
@@ -3207,56 +3194,60 @@ ApplyModifiers(char *val, const char * c
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = VarQuote(st.val, modifier == 'q');
 		st.next = p + 1;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 	case 'T':
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Tail, NULL);
 		st.next = p + 1;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 	case 'H':
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Head, NULL);
 		st.next = p + 1;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 	case 'E':
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Suffix, NULL);
 		st.next = p + 1;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 	case 'R':
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Root, NULL);
 		st.next = p + 1;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 	case 'r':
-	    if (!ApplyModifier_Range(p, &st))
-		goto default_case;
+	    res = ApplyModifier_Range(p, &st);
 	    break;
 	case 'O':
-	    if (!ApplyModifier_Order(p, &st))
-		goto bad_modifier;
+	    res = ApplyModifier_Order(p, &st);
 	    break;
 	case 'u':
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = VarUniq(st.val);
 		st.next = p + 1;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 #ifdef SUNSHCMD
 	case 's':
 	    if (p[1] == 'h' && (p[2] == st.endc || p[2] == ':')) {
@@ -3268,30 +3259,32 @@ ApplyModifiers(char *val, const char * c
 		} else
 		    st.newVal = varNoError;
 		st.next = p + 2;
-		break;
-	    }
-	    goto default_case;
+		res = AMR_OK;
+	    } else
+		res = AMR_UNKNOWN;
+	    break;
 #endif
 	default:
-	default_case:
-	    {
+	    res = AMR_UNKNOWN;
+	}
+
 #ifdef SYSVVARSUB
-		int res = ApplyModifier_SysV(p, &st);
-		if (res == 'c')
-		    goto cleanup;
-		if (res != '=')
+	if (res == AMR_UNKNOWN)
+	    res = ApplyModifier_SysV(p, &st);
 #endif
-		{
-		    Error("Unknown modifier '%c'", *p);
-		    for (st.next = p + 1;
-			 *st.next != ':' && *st.next != st.endc &&
-			 *st.next != '\0';
-			 st.next++)
-			continue;
-		    st.newVal = var_Error;
-		}
-	    }
-	}
+
+	if (res == AMR_UNKNOWN) {
+	    Error("Unknown modifier '%c'", *p);
+	    st.next = p + 1;
+	    while (*st.next != ':' && *st.next != st.endc && *st.next != '\0')
+		st.next++;
+	    st.newVal = var_Error;
+	}
+	if (res == AMR_CLEANUP)
+	    goto cleanup;
+	if (res == AMR_BAD)
+	    goto bad_modifier;
+
 	if (DEBUG(VAR)) {
 	    fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
 		st.v->name, modifier, st.newVal);

Reply via email to