unsigned char flags = 0;
const char *p = lines[idx];
- while (isblank (*p) || *p == '-' || *p == '@' || *p == '+')
+ while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
switch (*(p++))
{
case '+':
the commands are nothing but whitespace. */
for (p = file->cmds->commands; *p != '\0'; ++p)
- if (!isspace ((unsigned char)*p) && *p != '-' && *p != '@')
+ if (!ISSPACE (*p) && *p != '-' && *p != '@' && *p != '+')
break;
if (*p == '\0')
{
break;
default:
- if (isblank ((unsigned char)p[-1]))
+ if (ISSPACE (p[-1]))
break;
/* A $ followed by a random char is a variable reference:
/* If we're substituting only by fully matched words,
or only at the ends of words, check that this case qualifies. */
if (by_word
- && ((p > text && !isblank ((unsigned char)p[-1]))
- || ! STOP_SET (p[slen], MAP_BLANK|MAP_NUL)))
+ && ((p > text && !ISSPACE (p[-1]))
+ || ! STOP_SET (p[slen], MAP_SPACE|MAP_NUL)))
/* Struck out. Output the rest of the string that is
no longer to be replaced. */
o = variable_buffer_output (o, subst, slen);
char *
strip_whitespace (const char **begpp, const char **endpp)
{
- while (*begpp <= *endpp && isspace ((unsigned char)**begpp))
+ while (*begpp <= *endpp && ISSPACE (**begpp))
(*begpp) ++;
- while (*endpp >= *begpp && isspace ((unsigned char)**endpp))
+ while (*endpp >= *begpp && ISSPACE (**endpp))
(*endpp) --;
return (char *)*begpp;
}
unsigned int len;
struct variable *var;
+ /* Clean up the variable name by removing whitespace. */
+ char *vp = next_token (varname);
+ end_of_token (vp)[0] = '\0';
+
push_new_variable_scope ();
- var = define_variable (varname, strlen (varname), "", o_automatic, 0);
+ var = define_variable (vp, strlen (vp), "", o_automatic, 0);
/* loop through LIST, put the value in VAR and expand BODY */
while ((p = find_next_token (&list_iterator, &len)) != 0)
int i=0;
const char *word_start;
- while (isspace ((unsigned char)*p))
- ++p;
+ NEXT_TOKEN (p);
word_start = p;
- for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
+ for (i=0; *p != '\0' && !ISSPACE (*p); ++p, ++i)
{}
if (!i)
break;
extern int dos_command_running, dos_status;
/* Make sure not to bother processing an empty line. */
- while (isblank ((unsigned char)*text))
- ++text;
+ NEXT_TOKEN (text);
if (*text == '\0')
return 0;
{
const char *s = argv[0];
int result = 0;
- while (isspace ((unsigned char)*s))
- s++;
+ NEXT_TOKEN (s);
result = ! (*s);
o = variable_buffer_output (o, result ? "1" : "", result);
return o;
mode = "a";
++fn;
}
- fn = next_token (fn);
+ NEXT_TOKEN (fn);
if (fn[0] == '\0')
O (fatal, *expanding_var, _("file: missing filename"));
char *preo = o;
FILE *fp;
- fn = next_token (++fn);
+ ++fn;
+ NEXT_TOKEN (fn);
if (fn[0] == '\0')
O (fatal, *expanding_var, _("file: missing filename"));
/* We found a builtin function. Find the beginning of its arguments (skip
whitespace after the name). */
- beg = next_token (beg + entry_p->len);
+ beg += entry_p->len;
+ NEXT_TOKEN (beg);
/* Find the end of the function invocation, counting nested use of
whichever kind of parens we use. Since we're looking, count commas
{
static int max_args = 0;
char *fname;
- char *cp;
char *body;
int flen;
int i;
const struct function_table_entry *entry_p;
struct variable *v;
- /* There is no way to define a variable with a space in the name, so strip
- leading and trailing whitespace as a favor to the user. */
- fname = argv[0];
- while (isspace ((unsigned char)*fname))
- ++fname;
-
- cp = fname + strlen (fname) - 1;
- while (cp > fname && isspace ((unsigned char)*cp))
- --cp;
- cp[1] = '\0';
+ /* Clean up the name of the variable to be invoked. */
+ fname = next_token (argv[0]);
+ end_of_token (fname)[0] = '\0';
/* Calling nothing is a no-op */
if (*fname == '\0')
char c;
/* Skip any leading whitespace. */
- while (isblank ((unsigned char)*p))
- ++p;
+ NEXT_TOKEN (p);
beg = p;
c = *(p++);
flags |= COMMANDS_RECURSE;
else if (*p == '-')
child->noerror = 1;
- else if (!isblank ((unsigned char)*p))
+ /* Don't skip newlines. */
+ else if (!ISBLANK (*p))
break;
++p;
}
/* Skip any leading whitespace */
while (*p)
{
- if (!isspace(*p))
+ if (!ISSPACE (*p))
{
if (*p != '\\')
break;
*out++ = *in++;
else
{
- /* Skip the backslash, newline and
- any following whitespace. */
- in = next_token (in + 2);
+ /* Skip the backslash, newline, and whitespace. */
+ in += 2;
+ NEXT_TOKEN (in);
/* Discard any preceding whitespace that has
already been written to the output. */
- while (out > outref
- && isblank ((unsigned char)out[-1]))
+ while (out > outref && ISBLANK (out[-1]))
--out;
/* Replace it all with a single space. */
if (restp != NULL)
*restp = NULL;
- /* Make sure not to bother processing an empty line. */
- while (isblank ((unsigned char)*line))
+ /* Make sure not to bother processing an empty line but stop at newline. */
+ while (ISBLANK (*line))
++line;
if (*line == '\0')
return 0;
/* Throw out the backslash and newline. */
++p;
- /* If there's nothing in this argument yet, skip any
- whitespace before the start of the next word. */
+ /* At the beginning of the argument, skip any whitespace other
+ than newline before the start of the next word. */
if (ap == new_argv[i])
- p = next_token (p + 1) - 1;
+ while (ISBLANK (p[1]))
+ ++p;
}
#ifdef WINDOWS32
/* Backslash before whitespace is not special if our shell
is not Unixy. */
- else if (isspace (p[1]) && !unixy_shell)
+ else if (ISSPACE (p[1]) && !unixy_shell)
{
*ap++ = *p;
break;
else
#endif
if (p[1] != '\\' && p[1] != '\''
- && !isspace ((unsigned char)p[1])
+ && !ISSPACE (p[1])
&& strchr (sh_chars_sh, p[1]) == 0)
/* back up one notch, to copy the backslash */
--p;
}
}
- /* Ignore multiple whitespace chars. */
- p = next_token (p) - 1;
+ /* Skip whitespace chars, but not newlines. */
+ while (ISBLANK (p[1]))
+ ++p;
break;
default:
*/
/* Make sure not to bother processing an empty line. */
- while (isspace ((unsigned char)*line))
- ++line;
+ NEXT_TOKEN (line);
if (*line == '\0')
return 0;
#endif /* WINDOWS32 */
{
int esc = 0;
- /* This is the start of a new recipe line.
- Skip whitespace and prefix characters. */
- while (isblank (*f) || *f == '-' || *f == '@' || *f == '+')
+ /* This is the start of a new recipe line. Skip whitespace
+ and prefix characters but not newlines. */
+ while (ISBLANK (*f) || *f == '-' || *f == '@' || *f == '+')
++f;
/* Copy until we get to the next logical recipe line. */
[@+-]: they're meaningless in .ONESHELL mode. */
while (*f != '\0')
{
- /* This is the start of a new recipe line.
- Skip whitespace and prefix characters. */
- while (isblank (*f) || *f == '-' || *f == '@' || *f == '+')
+ /* This is the start of a new recipe line. Skip whitespace
+ and prefix characters but not newlines. */
+ while (ISBLANK (*f) || *f == '-' || *f == '@' || *f == '+')
++f;
/* Copy until we get to the next logical recipe line. */
while (*f != '\0')
{
- /* Remove the escaped newlines in the command, and
- the whitespace that follows them. Windows
- shells cannot handle escaped newlines. */
+ /* Remove the escaped newlines in the command, and the
+ blanks that follow them. Windows shells cannot handle
+ escaped newlines. */
if (*f == '\\' && f[1] == '\n')
{
f += 2;
- while (isblank (*f))
+ while (ISBLANK (*f))
++f;
}
*(t++) = *(f++);
/* DOS shells don't know about backslash-escaping. */
if (unixy_shell && !batch_mode_shell &&
(*p == '\\' || *p == '\'' || *p == '"'
- || isspace ((unsigned char)*p)
+ || ISSPACE (*p)
|| strchr (sh_chars, *p) != 0))
*ap++ = '\\';
#ifdef __MSDOS__
cptr = line;
for (;;)
{
- while ((*cptr != 0)
- && (isspace ((unsigned char)*cptr)))
+ while ((*cptr != 0) && (ISSPACE (*cptr)))
cptr++;
if (*cptr == 0)
break;
- while ((*cptr != 0)
- && (!isspace ((unsigned char)*cptr)))
+ while ((*cptr != 0) && (!ISSPACE (*cptr)))
cptr++;
argc++;
}
argc = 0;
for (;;)
{
- while ((*cptr != 0)
- && (isspace ((unsigned char)*cptr)))
+ while ((*cptr != 0) && (ISSPACE (*cptr)))
cptr++;
if (*cptr == 0)
break;
DB (DB_JOBS, ("argv[%d] = [%s]\n", argc, cptr));
argv[argc++] = cptr;
- while ((*cptr != 0)
- && (!isspace ((unsigned char)*cptr)))
+ while ((*cptr != 0) && (!ISSPACE (*cptr)))
cptr++;
if (*cptr != 0)
*cptr++ = 0;
stopchar_map[(int)'/'] = MAP_DIRSEP;
#if defined(VMS)
- stopchar_map[(int)':'] = MAP_COLON | MAP_DIRSEP;
- stopchar_map[(int)']'] = MAP_DIRSEP;
- stopchar_map[(int)'>'] = MAP_DIRSEP;
+ stopchar_map[(int)':'] |= MAP_DIRSEP;
+ stopchar_map[(int)']'] |= MAP_DIRSEP;
+ stopchar_map[(int)'>'] |= MAP_DIRSEP;
#elif defined(HAVE_DOS_PATHS)
- stopchar_map[(int)'\\'] = MAP_DIRSEP;
+ stopchar_map[(int)'\\'] |= MAP_DIRSEP;
#endif
for (i = 1; i <= UCHAR_MAX; ++i)
{
- if (isblank(i))
- stopchar_map[i] = MAP_BLANK;
- if (isspace(i))
- stopchar_map[i] |= MAP_SPACE;
- if (isalnum(i))
- stopchar_map[i] = MAP_USERFUNC;
+ if (isblank (i))
+ stopchar_map[i] |= MAP_BLANK;
+ else if (isspace (i))
+ /* Don't mark blank characters as newline characters. */
+ stopchar_map[i] |= MAP_NEWLINE;
+ else if (isalnum (i))
+ stopchar_map[i] |= MAP_USERFUNC;
}
}
value = variable_expand (varref);
/* Skip whitespace, and check for an empty value. */
- value = next_token (value);
+ NEXT_TOKEN (value);
len = strlen (value);
if (len == 0)
return;
{
if (*value == '\\' && value[1] != '\0')
++value; /* Skip the backslash. */
- else if (isblank ((unsigned char)*value))
+ else if (ISBLANK (*value))
{
/* End of the word. */
*p++ = '\0';
argv[++argc] = p;
do
++value;
- while (isblank ((unsigned char)*value));
+ while (ISBLANK (*value));
continue;
}
*p++ = *value++;
{
if (*in == '$')
*out++ = '$';
- else if (isblank ((unsigned char)*in) || *in == '\\')
+ else if (ISBLANK (*in) || *in == '\\')
*out++ = '\\';
*out++ = *in++;
}
extern int errno;
#endif
-#ifndef isblank
-# define isblank(c) ((c) == ' ' || (c) == '\t')
-#endif
-
#ifdef __VMS
/* In strict ANSI mode, VMS compilers should not be defining the
VMS macro. Define it here instead of a bulk edit for the correct code.
#define N_(msgid) gettext_noop (msgid)
#define S_(msg1,msg2,num) ngettext (msg1,msg2,num)
-/* Handle other OSs.
- To overcome an issue parsing paths in a DOS/Windows environment when
- built in a unix based environment, override the PATH_SEPARATOR_CHAR
- definition unless being built for Cygwin. */
-#if defined(HAVE_DOS_PATHS) && !defined(__CYGWIN__)
-# undef PATH_SEPARATOR_CHAR
-# define PATH_SEPARATOR_CHAR ';'
-#elif !defined(PATH_SEPARATOR_CHAR)
-# if defined (VMS)
-# define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':')
-# else
-# define PATH_SEPARATOR_CHAR ':'
-# endif
-#endif
-
/* This is needed for getcwd() and chdir(), on some W32 systems. */
#if defined(HAVE_DIRECT_H)
# include <direct.h>
# endif
/* Include only the minimal stuff from windows.h. */
-#define WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
#endif /* WINDOWS32 */
#define ANY_SET(_v,_m) (((_v)&(_m)) != 0)
#define MAP_NUL 0x0001
#define MAP_BLANK 0x0002
-#define MAP_SPACE 0x0004
+#define MAP_NEWLINE 0x0004
#define MAP_COMMENT 0x0008
#define MAP_SEMI 0x0010
#define MAP_EQUALS 0x0020
# define MAP_VMSCOMMA 0x0000
#endif
-#define STOP_SET(_v,_m) ANY_SET (stopchar_map[(unsigned char)(_v)],(_m))
+#define MAP_SPACE (MAP_BLANK|MAP_NEWLINE)
+
+/* Handle other OSs.
+ To overcome an issue parsing paths in a DOS/Windows environment when
+ built in a unix based environment, override the PATH_SEPARATOR_CHAR
+ definition unless being built for Cygwin. */
+#if defined(HAVE_DOS_PATHS) && !defined(__CYGWIN__)
+# undef PATH_SEPARATOR_CHAR
+# define PATH_SEPARATOR_CHAR ';'
+# define MAP_PATHSEP MAP_SEMI
+#elif !defined(PATH_SEPARATOR_CHAR)
+# if defined (VMS)
+# define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':')
+# define MAP_PATHSEP (vms_comma_separator ? MAP_COMMA : MAP_SEMI)
+# else
+# define PATH_SEPARATOR_CHAR ':'
+# define MAP_PATHSEP MAP_COLON
+# endif
+#elif PATH_SEPARATOR_CHAR == ':'
+# define MAP_PATHSEP MAP_COLON
+#elif PATH_SEPARATOR_CHAR == ';'
+# define MAP_PATHSEP MAP_SEMI
+#elif PATH_SEPARATOR_CHAR == ','
+# define MAP_PATHSEP MAP_COMMA
+#else
+# error "Unknown PATH_SEPARATOR_CHAR"
+#endif
+
+#define STOP_SET(_v,_m) ANY_SET(stopchar_map[(unsigned char)(_v)],(_m))
+
+#define ISBLANK(c) STOP_SET((c),MAP_BLANK)
+#define ISSPACE(c) STOP_SET((c),MAP_SPACE)
+#define NEXT_TOKEN(s) while (ISSPACE (*(s))) ++(s)
+#define END_OF_TOKEN(s) while (! STOP_SET (*(s), MAP_SPACE|MAP_NUL)) ++(s)
#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
# define SET_STACK_SIZE
{
/* Backslash/newline handling:
In traditional GNU make all trailing whitespace, consecutive
- backslash/newlines, and any leading whitespace on the next line
- is reduced to a single space.
+ backslash/newlines, and any leading non-newline whitespace on the
+ next line is reduced to a single space.
In POSIX, each backslash/newline and is replaced by a space. */
- in = next_token (in);
+ while (ISBLANK (*in))
+ ++in;
if (! posix_pedantic)
- while (out > line && isblank ((unsigned char)out[-1]))
+ while (out > line && ISBLANK (out[-1]))
--out;
*out++ = ' ';
}
char *
end_of_token (const char *s)
{
- while (! STOP_SET (*s, MAP_BLANK|MAP_NUL))
- ++s;
+ END_OF_TOKEN (s);
return (char *)s;
}
char *
next_token (const char *s)
{
- while (isblank ((unsigned char)*s))
- ++s;
+ NEXT_TOKEN (s);
return (char *)s;
}
memset (vmod, '\0', sizeof (*vmod));
/* Find the start of the next token. If there isn't one we're done. */
- line = next_token (line);
+ NEXT_TOKEN (line);
if (*line == '\0')
return (char *)line;
/* Get rid if starting space (including formfeed, vtab, etc.) */
p = collapsed;
- while (isspace ((unsigned char)*p))
- ++p;
+ NEXT_TOKEN (p);
/* See if this is a variable assignment. We need to do this early, to
allow variables with names like 'ifdef', 'export', 'private', etc. */
p2 = end_of_token (p);
wlen = p2 - p;
- p2 = next_token (p2);
+ NEXT_TOKEN (p2);
/* If we're in an ignored define, skip this line (but maybe get out). */
if (in_ignored_define)
The rule is that it's only a target, if there are TWO :'s
OR a space around the :.
*/
- if (p && !(isspace ((unsigned char)p[1]) || !p[1]
- || isspace ((unsigned char)p[-1])))
+ if (p && !(ISSPACE (p[1]) || !p[1] || ISSPACE (p[-1])))
p = 0;
#endif
#ifdef HAVE_DOS_PATHS
if (*name == '\0')
O (fatal, &ebuf->floc, _("empty variable name"));
p = name + strlen (name) - 1;
- while (p > name && isblank ((unsigned char)*p))
+ while (p > name && ISBLANK (*p))
--p;
p[1] = '\0';
if (name[0] == '\0')
O (fatal, &defstart, _("empty variable name"));
p = name + strlen (name) - 1;
- while (p > name && isblank ((unsigned char)*p))
+ while (p > name && ISBLANK (*p))
--p;
p[1] = '\0';
len = strlen (p);
/* If this is another 'define', increment the level count. */
- if ((len == 6 || (len > 6 && isblank ((unsigned char)p[6])))
+ if ((len == 6 || (len > 6 && ISBLANK (p[6])))
&& strneq (p, "define", 6))
++nlevels;
/* If this is an 'endef', decrement the count. If it's now 0,
we've found the last one. */
- else if ((len == 5 || (len > 5 && isblank ((unsigned char)p[5])))
+ else if ((len == 5 || (len > 5 && ISBLANK (p[5])))
&& strneq (p, "endef", 5))
{
p += 5;
return -2;
/* Found one: skip past it and any whitespace after it. */
- line = next_token (line + len);
+ line += len;
+ NEXT_TOKEN (line);
#define EXTRATEXT() OS (error, flocp, _("extraneous text after '%s' directive"), cmdname)
#define EXTRACMD() OS (fatal, flocp, _("extraneous '%s'"), cmdname)
/* Make sure there's only one variable name to test. */
p = end_of_token (var);
i = p - var;
- p = next_token (p);
+ NEXT_TOKEN (p);
if (*p != '\0')
return -1;
{
/* Strip blanks after the first string. */
char *p = line++;
- while (isblank ((unsigned char)p[-1]))
+ while (ISBLANK (p[-1]))
--p;
*p = '\0';
}
if (termin != ',')
/* Find the start of the second string. */
- line = next_token (line);
+ NEXT_TOKEN (line);
termin = termin == ',' ? ')' : *line;
if (termin != ')' && termin != '"' && termin != '\'')
if (*line == '\0')
return -1;
- *line = '\0';
- line = next_token (++line);
+ *(line++) = '\0';
+ NEXT_TOKEN (line);
if (*line != '\0')
EXTRATEXT ();
char c;
/* Skip any leading whitespace. */
- while (isblank ((unsigned char)*p))
+ while (ISBLANK (*p))
++p;
beg = p;
int i;
/* Skip whitespace; at the end of the string or STOPCHAR we're done. */
- p = next_token (p);
+ NEXT_TOKEN (p);
if (STOP_SET (*p, stopmap))
break;
#endif
#ifdef _AMIGA
if (p && STOP_SET (*p, stopmap & MAP_COLON)
- && !(isspace ((unsigned char)p[1]) || !p[1]
- || isspace ((unsigned char)p[-1])))
+ && !(ISSPACE (p[1]) || !p[1] || ISSPACE (p[-1])))
p = find_char_unquote (p+1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#endif
#ifdef HAVE_DOS_PATHS
Note that tokens separated by spaces should be treated as separate
tokens since make doesn't allow path names with spaces */
if (stopmap | MAP_COLON)
- while (p != 0 && !isspace ((unsigned char)*p) &&
+ while (p != 0 && !ISSPACE (*p) &&
(p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
p = find_char_unquote (p + 1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#endif
do
{
const char *o = e;
- e = next_token (e);
+ NEXT_TOKEN (e);
/* Find the end of this word. We don't want to unquote and
we don't care about quoting since we're looking for the
last char in the word. */
$details = "Try various uses of call and ensure they all give the correct
results.\n";
-open(MAKEFILE, "> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE <<'EOMAKE';
+run_make_test(q!
# Simple, just reverse two things
#
reverse = $2 $1
echo '$(call my-foreach,a,,,)'; \
echo '$(call my-if,a,b,c)'; \
echo '$(call two,bar,baz)'; \
- echo '$(call tclose,foo)'
-
-
+ echo '$(call tclose,foo)';
+!,
+ "", "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n");
-EOMAKE
-
-# These won't work until/unless PR/1527 is resolved.
-# echo '$(call my-foreach,a,x y z,$(a)$(a))'; \
-# echo '$(call my-if,,$(warning don't print this),ok)'
+# These won't work because call expands all its arguments first, before
+# passing them on, then marks them as resolved/simple, so they're not
+# expanded again by the function.
#
-# $answer = "xx yy zz\nok\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n";
-&compare_output($answer, &get_logfile(1));
-
+# echo '$(call my-foreach,a,x y z,$$(a)$$(a))'; \
+# echo '$(call my-if,,$$(info don't print this),$$(info do print this))'
+#
+# $answer = "xx yy zz\ndo print this\n";
# TEST eclipsing of arguments when invoking sub-calls
-$makefile2 = &get_tmpfile;
-
-open(MAKEFILE,"> $makefile2");
-
-print MAKEFILE <<'EOF';
-
+run_make_test(q!
all = $1 $2 $3 $4 $5 $6 $7 $8 $9
level1 = $(call all,$1,$2,$3,$4,$5)
@echo $(call level1,1,2,3,4,5,6,7,8)
@echo $(call level2,1,2,3,4,5,6,7,8)
@echo $(call level3,1,2,3,4,5,6,7,8)
-EOF
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile2, "", &get_logfile);
-$answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n";
-&compare_output($answer,&get_logfile(1));
+!,
+ "", "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n");
# Ensure that variables are defined in global scope even in a $(call ...)
'', "\n");
1;
+
+### Local Variables:
+### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
+### End:
'',
'FOREACH');
+# Allow variable names with trailing space
+run_make_test(q!
+$(foreach \
+ a \
+, b c d \
+, $(info $a))
+all:;@:
+!,
+ "", "b\nc\nd\n");
+
+# Allow empty variable names. We still expand the body.
-# TEST 2: Check some error conditions.
+run_make_test('
+x = $(foreach ,1 2 3,a)
+y := $x
+
+all: ; @echo $y',
+ '', "a a a\n");
+
+# Check some error conditions.
run_make_test('
x = $(foreach )
512);
run_make_test('
-x = $(foreach )
+x = $(foreach x,y)
y := $x
all: ; @echo $y',
'',
- "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.",
+ "#MAKEFILE#:2: *** insufficient number of arguments (2) to function 'foreach'. Stop.",
512);
1;
run_make_test("FOO = a b\tc\rd\fe \f \f \f \f \ff
all: ; \@echo \$(words \$(sort \$(FOO)))\n",
- '', "5\n");
+ '', "6\n");
1;
+
+### Local Variables:
+### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
+### End:
run_make_with_options($m2, '', get_logfile());
compare_output("foo bar\n", get_logfile(1));
+# Test different types of whitespace, and bsnl inside functions
+
+sub xlate
+{
+ $_ = $_[0];
+ s/\\r/\r/g;
+ s/\\t/\t/g;
+ s/\\f/\f/g;
+ s/\\v/\v/g;
+ s/\\n/\n/g;
+ return $_;
+}
+
+run_make_test(xlate(q!
+$(foreach\r a \t , b\t c \r ,$(info $a \r ) )
+all:;@:
+!),
+ '', "b \r \nc \r \n");
+
+run_make_test(xlate(q!
+all:;@:$(foreach\r a \t , b\t c \r ,$(info $a \r ) )
+!),
+ '', "b \r \nc \r \n");
+
+run_make_test(xlate(q!
+$(foreach \
+\r a \t\
+ , b\t \
+ c \r ,$(info \
+ $a \r ) \
+ )
+all:;@:
+!),
+ '', "b \r \nc \r \n");
+
+run_make_test(xlate(q!
+all:;@:$(foreach \
+\r a \t\
+ , b\t \
+ c \r ,$(info \
+ $a \r ) \
+ )
+!),
+ '', "b \r \nc \r \n");
+
+run_make_test(xlate(q!
+define FOO
+$(foreach
+\r a \t
+ , b\t
+ c \r ,$(info
+ $a \r )
+ )
+endef
+$(FOO)
+all:;@:
+!),
+ '', "b \r \nc \r \n");
+
+run_make_test(xlate(q!
+define FOO
+$(foreach
+\r a \t
+ , b\t
+ c \r ,$(info
+ $a \r )
+ )
+endef
+all:;@:$(FOO)
+!),
+ '', "b \r \nc \r \n");
+
+# Test variables in recipes that expand to multiple lines
+
+run_make_test(q!
+define var
+
+echo foo
+
+
+echo bar
+endef
+all:;$(var)
+!,
+ '', "echo foo\nfoo\necho bar\nbar\n");
+
+run_make_test(q!
+define var
+
+echo foo
+
+@
+
+echo bar
+endef
+all:;$(var)
+!,
+ '', "echo foo\nfoo\necho bar\nbar\n");
1;
int wspace = 0;
const char *e = NULL;
- p = next_token (p);
+ NEXT_TOKEN (p);
var->name = (char *)p;
var->length = 0;
/* This begins a variable expansion reference. Make sure we don't
treat chars inside the reference as assignment tokens. */
char closeparen;
- int count;
+
c = *p++;
if (c == '(')
closeparen = ')';
/* P now points past the opening paren or brace.
Count parens or braces until it is matched. */
- count = 0;
- for (; *p != '\0'; ++p)
+ for (unsigned int count = 1; *p != '\0'; ++p)
{
- if (*p == c)
- ++count;
- else if (*p == closeparen && --count < 0)
+ if (*p == closeparen && --count == 0)
{
++p;
break;
}
+ if (*p == c)
+ ++count;
}
continue;
}
/* If we find whitespace skip it, and remember we found it. */
- if (isblank ((unsigned char)c))
+ if (ISBLANK (c))
{
wspace = 1;
e = p - 1;
- p = next_token (p);
+ NEXT_TOKEN (p);
c = *p;
if (c == '\0')
return NULL;
#endif
/* Skip over any initial separators and blanks. */
- while (*dirpath == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*dirpath))
+ while (STOP_SET (*dirpath, MAP_BLANK|MAP_PATHSEP))
++dirpath;
/* Figure out the maximum number of VPATH entries and put it in
maxelem = 2;
p = dirpath;
while (*p != '\0')
- if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
+ if (STOP_SET (*p++, MAP_BLANK|MAP_PATHSEP))
++maxelem;
vpath = xmalloc (maxelem * sizeof (const char *));
#else
&& *p != PATH_SEPARATOR_CHAR
#endif
- && !isblank ((unsigned char)*p))
+ && !ISBLANK (*p))
++p;
len = p - v;
}
/* Skip over separators and blanks between entries. */
- while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
+ while (STOP_SET (*p, MAP_BLANK|MAP_PATHSEP))
++p;
}