URI:
       make: Escape values passed in MAKEFLAGS - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 534a9fa01a8a0c080df60800a370421dc594532c
   DIR parent d94c6547755e253374bb6da489b5c01f69680dbc
  HTML Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
       Date:   Sun, 15 Feb 2026 11:12:28 +0100
       
       make: Escape values passed in MAKEFLAGS
       
       The POSIX standard says:
       
               The macro= value macro definition operands can also be
               included. The difference between the contents of MAKEFLAGS
               and the make utility command line is that the contents of the
               variable shall not be subjected to the word expansions (see Word
               Expansions) associated with parsing the command line values.
       
       And it basically means that we have to escape the parameters passed
       in MAKEFLAGS and then unescape and doing the word spliting. The code
       had a naive strtok() implementation for word spliting, and it had to
       be replaced for a more complex parsing function which also handles
       escapes and quotes with ' and ".
       
       Diffstat:
         M src/cmd/scc-make/main.c             |      92 ++++++++++++++++++++++++++++---
         A tests/make/execute/0109-makeflags.… |      18 ++++++++++++++++++
         A tests/make/execute/test2.mk         |      15 +++++++++++++++
       
       3 files changed, 117 insertions(+), 8 deletions(-)
       ---
   DIR diff --git a/src/cmd/scc-make/main.c b/src/cmd/scc-make/main.c
       @@ -1,3 +1,4 @@
       +#include <ctype.h>
        #include <errno.h>
        #include <signal.h>
        #include <stdarg.h>
       @@ -141,6 +142,44 @@ appendmakeflags(char *text)
                free(t);
        }
        
       +static void
       +appendmacro(char *text)
       +{
       +        int n, idlen;
       +        char *p, *t, *s;
       +
       +        n = strlen(text) + 2;
       +        for (p = text; p = strchr(p, '\''); ++p)
       +                n++;
       +        s = emalloc(n + 1);
       +
       +        p = strchr(text, '=');
       +        idlen = p - text;
       +
       +        memcpy(s, text, idlen);
       +        s[idlen] = '\0';
       +
       +        if (strpbrk(s, " \t\v\n'\"")) {
       +                fprintf(stderr, "make: invalid macro name '%s'\n", text);
       +                exit(EXIT_FAILURE);
       +        }
       +
       +        p = s + idlen;
       +        *p++ = '=';
       +
       +        *p++ = '\'';
       +        for (t = text + idlen + 1; *t; ++t) {
       +                if (*t == '\'')
       +                        *p++ = '\\';
       +                *p++ = *t;
       +        }
       +        *p++ = '\'';
       +
       +        *p = '\0';
       +        appendmakeflags(s);
       +        free(s);
       +}
       +
        static int
        hasargs(int c)
        {
       @@ -183,7 +222,7 @@ parseflag(int flag, char **args, char ***argv)
                case 'r':
                        addtarget(".SUFFIXES", 0);
                        appendmakeflags("-r");
       -                break;        
       +                break;
                case 'S':
                        kflag = 0;
                        appendmakeflags("-S");
       @@ -216,7 +255,7 @@ assign(char *s, int where, int export)
        
                pos = t - s;
        
       -        appendmakeflags(s);
       +        appendmacro(s);
                t = estrdup(s); 
                t[pos] = '\0';
        
       @@ -253,8 +292,8 @@ parseargv(char **argv, char ***targets, int where, int export)
        static void
        parsemakeflags(void)
        {
       -        int c, n;
       -        char *s, *flags, **arr;
       +        int esc, c, n;
       +        char *t, *s, *buf, *flags, **arr;
        
                if ((flags = getenv("MAKEFLAGS")) == NULL)
                        return;
       @@ -272,16 +311,53 @@ parsemakeflags(void)
                } else {
                        n = 0;
                        arr = NULL;
       -                for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) {
       +                buf = emalloc(strlen(flags) + 1);
       +
       +                for (s = flags; *s; ) {
       +                        while (isspace(*s))
       +                                ++s;
       +
       +                        t = buf;
       +                        for (esc = 0; c = *s; ++s) {
       +                                if (!esc && isspace(c))
       +                                        break;
       +                                if (!esc && (c == '\'' || c == '"')) {
       +                                        esc = c;
       +                                        continue;
       +                                }
       +                                if (c == esc) {
       +                                        esc = 0;
       +                                        continue;
       +                                }
       +                                if (c == '\\')
       +                                        ++s;
       +                                if ((*t++ = *s) == '\0') {
       +                                        fputs("make: trailing \\ in MAKEFLAGS\n",
       +                                              stderr);
       +                                        exit(EXIT_FAILURE);
       +                                }
       +                        }
       +                        if (esc) {
       +                                fputs("make: no closing quote\n", stderr);
       +                                exit(EXIT_FAILURE);
       +                        }
       +                        if (t == buf)
       +                                continue;
       +                        *t = '\0';
       +
                                n++;
                                arr = erealloc(arr, sizeof(char *) * (n+1));
       -                        arr[n-1] = s;
       +                        arr[n-1] = estrdup(buf);
                                arr[n] = NULL;
                        }
       +                free(buf);
        
       -                if (arr)
       +                if (arr) {
                                parseargv(arr, NULL, MAKEFLAGS, NOEXPORT);
       -                free(arr);
       +                        while (n-- > 0)
       +                                free(arr[n]);
       +                        free(arr);
       +                }
                }
        }
        
   DIR diff --git a/tests/make/execute/0109-makeflags.sh b/tests/make/execute/0109-makeflags.sh
       @@ -0,0 +1,18 @@
       +#!/bin/sh
       +
       +trap 'rm -f $tmp' EXIT
       +trap 'exit $?' HUP INT TERM
       +
       +tmp=$$.tmp
       +
       +$EXEC scc make -f test2.mk MOREOBJS='a.o b.o' <<'EOF' > $tmp
       +
       +diff -u - $tmp <<EOF
       +MAKEFLAGS=MOREOBJS=a.o b.o
       +MOREOBJS=a.o b.o
       +OBJS= a.o b.o main.o
       +MAKEFLAGS=MOREOBJS='a.o b.o'
       +MAKEFLAGS=MOREOBJS=a.o b.o
       +MOREOBJS=a.o b.o
       +OBJS= a.o b.o main.o
       +EOF
   DIR diff --git a/tests/make/execute/test2.mk b/tests/make/execute/test2.mk
       @@ -0,0 +1,15 @@
       +OBJS=\
       +        $(MOREOBJS)\
       +        main.o
       +
       +all:
       +        @echo MAKEFLAGS='$(MAKEFLAGS)'
       +        @echo MOREOBJS='$(MOREOBJS)'
       +        @echo OBJS='$(OBJS)'
       +        @$(MAKE) -f test2.mk debug
       +
       +debug:
       +        @env | grep MAKEFLAGS
       +        @echo MAKEFLAGS='$(MAKEFLAGS)'
       +        @echo MOREOBJS='$(MOREOBJS)'
       +        @echo OBJS='$(OBJS)'