From 1cf484e186abf5ce54eb963d64081bc05d00ff33 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 7 Jun 2022 12:34:08 +0100 Subject: [PATCH] Treat non-standard options as extensions The -C option isn't specified by POSIX, so let's treat it as an extension. Add a -P option to request POSIX-conformance from the command line. If the -P option is specified any attempt to use a non-standard option, like -C, will be treated as an error. The possibility of a -P option was considered by the authors of the POSIX standard but rejected. Hence, it too is a non-standard option. Though, obviously, its presence won't be treated as an error. The -P option must be the first on the command line. It doesn't have to be the first in MAKEFLAGS as none of the options allowed there has side effects (at present). More than one -P option is permitted. The value of the MAKE macro has to be determined before any options have been processed. If it turns out that a -P option was present the MAKE macro has to revert to the value required by the current POSIX standard. --- main.c | 42 ++++++++++++++++++++++++++++++++---------- make.h | 50 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/main.c b/main.c index 56e3640..c9e362f 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,8 @@ /* - * make [-C path] [-f makefile] [-eiknpqrsSt] [macro=val ...] [target ...] + * make [-P] [-C path] [-f makefile] [-eiknpqrsSt] [macro=val ...] [target ...] * - * -C Change directory to path + * -P POSIX mode (non-POSIX) + * -C Change directory to path (non-POSIX) * -f Makefile name * -e Environment variables override macros in makefiles * -i Ignore exit status @@ -29,8 +30,11 @@ static void usage(void) { fprintf(stderr, - "Usage: %s [-C path] [-f makefile] [-eiknpqrsSt] [macro=val ...]" - "[target ...]\n", myname); + "Usage: %s" + IF_FEATURE_MAKE_EXTENSIONS(" [-P] [-C path]") + " [-f makefile] [-eiknpqrsSt] [macro=val ...]" + IF_FEATURE_MAKE_EXTENSIONS("\n\t") + " [target ...]\n", myname); exit(2); } @@ -46,14 +50,25 @@ process_options(int argc, char **argv, int from_env) while ((opt = getopt(argc, argv, OPTSTR1 OPTSTR2)) != -1) { switch(opt) { +#if ENABLE_FEATURE_MAKE_EXTENSIONS + case 'P': + if (!posix && !from_env && (flags & ~OPT_P)) { + error("-P option must be first"); + } + flags |= OPT_P; + posix = TRUE; + break; case 'C': - if (!from_env) { + if (!posix && !from_env) { if (chdir(optarg) == -1) { error("can't chdir to %s: %s", optarg, strerror(errno)); } flags |= OPT_C; + break; } + error("-C not allowed"); break; +#endif case 'f': // Alternate file name if (!from_env) { makefiles = newcmd(optarg, makefiles); @@ -302,7 +317,7 @@ int main(int argc, char **argv) { #if ENABLE_FEATURE_MAKE_EXTENSIONS - const char *path, *argv0; + const char *path, *newpath = NULL; #else const char *path = "make"; #endif @@ -314,10 +329,10 @@ main(int argc, char **argv) myname = basename(*argv); #if ENABLE_FEATURE_MAKE_EXTENSIONS - path = argv0 = argv[0]; + path = argv[0]; if (argv[0][0] != '/' && strchr(argv[0], '/')) { // Make relative path absolute - path = realpath(argv[0], NULL); + path = newpath = realpath(argv[0], NULL); if (!path) { error("can't resolve path for %s: %s", argv[0], strerror(errno)); } @@ -344,6 +359,14 @@ main(int argc, char **argv) opts |= process_options(argc, argv, FALSE); argv += optind; +#if ENABLE_FEATURE_MAKE_EXTENSIONS + if (posix) { + free((void *)newpath); + newpath = NULL; + path = "make"; + } +#endif + init_signal(SIGHUP); init_signal(SIGTERM); @@ -371,8 +394,7 @@ main(int argc, char **argv) setmacro("SHELL", "/bin/sh", 4); setmacro("MAKE", path, 4); #if ENABLE_FEATURE_MAKE_EXTENSIONS - if (path != argv0) - free((void *)path); + free((void *)newpath); #endif #if ENABLE_FEATURE_MAKE_EXTENSIONS diff --git a/make.h b/make.h index ab3c675..396879c 100644 --- a/make.h +++ b/make.h @@ -48,25 +48,47 @@ extern char **environ; #define FALSE (0) #define MAX(a,b) ((a)>(b)?(a):(b)) -#define OPTSTR1 "eiknqrsSt" +#if ENABLE_FEATURE_MAKE_EXTENSIONS +#define OPTSTR1 "PeiknqrsSt" #define OPTSTR2 "pf:C:" +#else +#define OPTSTR1 "eiknqrsSt" +#define OPTSTR2 "pf:" +#endif enum { - OPT_e = (1 << 0), - OPT_i = (1 << 1), - OPT_k = (1 << 2), - OPT_n = (1 << 3), - OPT_q = (1 << 4), - OPT_r = (1 << 5), - OPT_s = (1 << 6), - OPT_S = (1 << 7), - OPT_t = (1 << 8), + // If present P must be the first option + IF_FEATURE_MAKE_EXTENSIONS(OPTBIT_P,) + OPTBIT_e, + OPTBIT_i, + OPTBIT_k, + OPTBIT_n, + OPTBIT_q, + OPTBIT_r, + OPTBIT_s, + OPTBIT_S, + OPTBIT_t, + OPTBIT_p, + OPTBIT_f, + IF_FEATURE_MAKE_EXTENSIONS(OPTBIT_C,) + OPTBIT_precious, + + OPT_P = IF_FEATURE_MAKE_EXTENSIONS((1 << OPTBIT_P)) + 0, + OPT_e = (1 << OPTBIT_e), + OPT_i = (1 << OPTBIT_i), + OPT_k = (1 << OPTBIT_k), + OPT_n = (1 << OPTBIT_n), + OPT_q = (1 << OPTBIT_q), + OPT_r = (1 << OPTBIT_r), + OPT_s = (1 << OPTBIT_s), + OPT_S = (1 << OPTBIT_S), + OPT_t = (1 << OPTBIT_t), // These options aren't allowed in MAKEFLAGS - OPT_p = (1 << 9), - OPT_f = (1 << 10), - OPT_C = (1 << 11), + OPT_p = (1 << OPTBIT_p), + OPT_f = (1 << OPTBIT_f), + OPT_C = IF_FEATURE_MAKE_EXTENSIONS((1 << OPTBIT_C)) + 0, // OPT_precious isn't a command line option and must be last - OPT_precious = (1 << 12), + OPT_precious = (1 << OPTBIT_precious), }; // Options that aren't included in MAKEFLAGS -- 2.36.1