make(1): clean up Buf_AddEscaped in .for loops
All this dance of determining the needed escape characters before iterating, saving them upfront, evaluating them later using complicated boolean expressions was not necessary at all. All that is needed is a simple NeedsEscapes, called at just the right time.
This commit is contained in:
parent
82e2acd33b
commit
6bcbf8f8c5
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: for.c,v 1.114 2020/11/07 14:11:58 rillig Exp $ */
|
||||
/* $NetBSD: for.c,v 1.115 2020/11/07 21:04:43 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, The Regents of the University of California.
|
||||
|
@ -60,15 +60,7 @@
|
|||
#include "make.h"
|
||||
|
||||
/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */
|
||||
MAKE_RCSID("$NetBSD: for.c,v 1.114 2020/11/07 14:11:58 rillig Exp $");
|
||||
|
||||
/* The .for loop substitutes the items as ${:U<value>...}, which means
|
||||
* that characters that break this syntax must be backslash-escaped. */
|
||||
typedef enum ForEscapes {
|
||||
FOR_SUB_ESCAPE_CHAR = 0x0001,
|
||||
FOR_SUB_ESCAPE_BRACE = 0x0002,
|
||||
FOR_SUB_ESCAPE_PAREN = 0x0004
|
||||
} ForEscapes;
|
||||
MAKE_RCSID("$NetBSD: for.c,v 1.115 2020/11/07 21:04:43 rillig Exp $");
|
||||
|
||||
static int forLevel = 0; /* Nesting level */
|
||||
|
||||
|
@ -120,30 +112,6 @@ For_Free(For *f)
|
|||
free(f);
|
||||
}
|
||||
|
||||
static ForEscapes
|
||||
GetEscapes(const char *word)
|
||||
{
|
||||
const char *p;
|
||||
ForEscapes escapes = 0;
|
||||
|
||||
for (p = word; *p != '\0'; p++) {
|
||||
switch (*p) {
|
||||
case ':':
|
||||
case '$':
|
||||
case '\\':
|
||||
escapes |= FOR_SUB_ESCAPE_CHAR;
|
||||
break;
|
||||
case ')':
|
||||
escapes |= FOR_SUB_ESCAPE_PAREN;
|
||||
break;
|
||||
case '}':
|
||||
escapes |= FOR_SUB_ESCAPE_BRACE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return escapes;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
IsFor(const char *p)
|
||||
{
|
||||
|
@ -326,18 +294,30 @@ for_var_len(const char *var)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* The .for loop substitutes the items as ${:U<value>...}, which means
|
||||
* that characters that break this syntax must be backslash-escaped. */
|
||||
static Boolean
|
||||
NeedsEscapes(const char *word, char endc)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = word; *p != '\0'; p++) {
|
||||
if (*p == ':' || *p == '$' || *p == '\\' || *p == endc)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* While expanding the body of a .for loop, write the item in the ${:U...}
|
||||
* expression, escaping characters as needed. See ApplyModifier_Defined. */
|
||||
* expression, escaping characters as needed.
|
||||
*
|
||||
* The result is later unescaped by ApplyModifier_Defined. */
|
||||
static void
|
||||
Buf_AddEscaped(Buffer *cmds, const char *item, char ech)
|
||||
{
|
||||
ForEscapes escapes = GetEscapes(item);
|
||||
char ch;
|
||||
|
||||
/* If there were no escapes, or the only escape is the other variable
|
||||
* terminator, then just substitute the full string */
|
||||
if (!(escapes & (ech == ')' ? ~(unsigned)FOR_SUB_ESCAPE_BRACE
|
||||
: ~(unsigned)FOR_SUB_ESCAPE_PAREN))) {
|
||||
if (!NeedsEscapes(item, ech)) {
|
||||
Buf_AddStr(cmds, item);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue