From f6085c56e2d0a523e89424910affb64a6496f5c8 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Wed, 15 Oct 2025 04:40:28 +0100 Subject: [PATCH] New commands and bug fixes --- Makefile.pdw | 22 -- lib.c | 26 +++ lib.h | 3 +- read.c | 69 +++--- read.h | 2 +- rule.c | 31 ++- variable.c | 280 +++++++++++++++++++++++-- xmake.c | 579 +++++++++++++++++++++++++++++++++++++-------------- 8 files changed, 785 insertions(+), 227 deletions(-) delete mode 100644 Makefile.pdw diff --git a/Makefile.pdw b/Makefile.pdw deleted file mode 100644 index b269b7f..0000000 --- a/Makefile.pdw +++ /dev/null @@ -1,22 +0,0 @@ -#****************************************************************************** -# @file Makefile.pdw -#****************************************************************************** -AS=aswin -CC=gccwin -LD=ldwin - -COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib -I../pdos/src -D__WIN32__ -D__NOBIVA__ -D__PDOS__ -COBJ=cstr.o hashtab.o lib.o report.o read.o rule.o variable.o xmake.o - -all: clean xmake.exe - -xmake.exe: $(COBJ) - $(LD) -s -o xmake.exe ../pdos/pdpclib/w32start.o $(COBJ) ../pdos/pdpclib/msvcrt.a ../pdos/src/kernel32.a - -.c.o: - $(CC) $(COPTS) $< - $(AS) -o $@ $*.s - rm -f $*.s - -clean: - rm -f *.o xmake.exe diff --git a/lib.c b/lib.c index 94c69a5..4931ba0 100644 --- a/lib.c +++ b/lib.c @@ -419,6 +419,32 @@ char *xstrndup (const char *__s, unsigned long __len) { } +int xstrcasecmp (const char *__s1, const char *__s2) { + + const unsigned char *p1 = (const unsigned char *) __s1; + const unsigned char *p2 = (const unsigned char *) __s2; + + while (*p1 != '\0') { + + if (tolower ((int) *p1) < tolower ((int) *p2)) { + return (-1); + } else if (tolower ((int) *p1) > tolower ((int) *p2)) { + return (1); + } + + p1++; + p2++; + + } + + if (*p2 == '\0') { + return (0); + } + + return (-1); + +} + int parse_args (char **__args, int __cnt) { struct option *opt, *last; diff --git a/lib.h b/lib.h index d0afe68..871abcf 100644 --- a/lib.h +++ b/lib.h @@ -18,12 +18,13 @@ struct option { }; char *skip_whitespace (char *p); +void dynarray_add (void *__ptab, unsigned long *__nb_ptr, void *__data); char *xstrdup (const char *__s); char *xstrndup (const char *__s, unsigned long __len); +int xstrcasecmp (const char *__s1, const char *__s2); int parse_args (char **__args, int __cnt); -void dynarray_add (void *__ptab, unsigned long *__nb_ptr, void *__data); void *xmalloc (unsigned long __sz); void *xrealloc (void *__ptr, unsigned long __sz); diff --git a/read.c b/read.c index b19c453..b6cc7f8 100644 --- a/read.c +++ b/read.c @@ -172,7 +172,7 @@ static struct if_stack *cur_if_stack = 0; static void add_if_stack (void) { - struct if_stack *if_stack = xmalloc (sizeof *if_stack); + struct if_stack *if_stack = xmalloc (sizeof (*if_stack)); if (cur_if_stack) { if_stack->prev_ignoring = cur_if_stack->ignoring; @@ -265,22 +265,22 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { struct nameseq* filenames = 0; int ret; - char *cmds, *clean = 0, *depstr = 0, *q; - size_t clean_size = 0, cmds_idx = 0, cmds_sz = 256; + char *commands, *clean = 0, *depstr = 0, *q; + size_t clean_size = 0, commands_idx = 0, commands_sz = 256; char *colon, *semicolonp, *commentp; long lines_read; unsigned long line_no = 1; - cmds = xmalloc (cmds_sz); + commands = xmalloc (commands_sz + 1); #define record_waiting_files() \ do { \ if (filenames) { \ - record_files (lbuf->filename, line_no - 1, filenames, cmds, cmds_idx, depstr); \ - filenames = 0; \ + record_files (lbuf->filename, line_no - 1, filenames, commands, \ + commands_idx, depstr); filenames = 0; \ } \ - cmds_idx = 0; \ + commands_idx = 0; \ } while (0) while ((lines_read = read_line (lbuf))) { @@ -610,6 +610,8 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { continue; } + line = clean; + if (line[0] == ' ' || line[0] == '\t') { if (filenames) { @@ -618,15 +620,15 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { line++; } - if (cmds_idx + strlen (line) + 1 > cmds_sz) { + if (commands_idx + strlen (line) + 1 > commands_sz) { - cmds_sz = (cmds_idx + strlen (line) + 1) * 2; - cmds = xrealloc (cmds, cmds_sz); + commands_sz = (commands_idx + strlen (line) + 1) * 2; + commands = xrealloc (commands, commands_sz); } src = line; - dst = &cmds[cmds_idx]; + dst = &commands[commands_idx]; for (; *src; src++, dst++) { @@ -645,8 +647,8 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { *dst = '\0'; - cmds_idx += dst - &cmds[cmds_idx] + 1; - cmds[cmds_idx - 1] = '\n'; + commands_idx += dst - &commands[commands_idx] + 1; + commands[commands_idx - 1] = '\n'; continue; @@ -708,12 +710,7 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { } - if (*p == '$') { - - variable_expand_line (lbuf->filename, line_no, p); - continue; - - } else if (strchr (p, '=')) { + if (strchr (p, '=')) { record_waiting_files (); @@ -722,6 +719,10 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { } + if (*p == '$') { + line = variable_expand_line (lbuf->filename, line_no, xstrdup (p));; + } + record_waiting_files (); semicolonp = strchr (line, ';'); @@ -759,15 +760,15 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { if (semicolonp) { - if (cmds_idx + strlen (semicolonp) + 1 > cmds_sz) { + if (commands_idx + strlen (semicolonp) + 1 > commands_sz) { - cmds_sz = (cmds_idx + strlen (semicolonp) + 1) * 2; - cmds = xrealloc (cmds, cmds_sz); + commands_sz = (commands_idx + strlen (semicolonp) + 1) * 2; + commands = xrealloc (commands, commands_sz); } - memcpy (&(cmds[cmds_idx]), semicolonp, strlen (semicolonp) + 1); - cmds_idx += strlen (semicolonp) + 1; + memcpy (&(commands[commands_idx]), semicolonp, strlen (semicolonp) + 1); + commands_idx += strlen (semicolonp) + 1; } @@ -799,7 +800,7 @@ static int read_lbuf (struct linebuf *lbuf, int set_default) { } free (clean); - free (cmds); + free (commands); if (cur_if_stack) { @@ -948,22 +949,22 @@ void *parse_nameseq (char *line, size_t size) { } -void record_files (const char *filename, unsigned long line_no, struct nameseq *filenames, char *cmds, size_t cmds_idx, char *depstr) { +void record_files (const char *filename, unsigned long line_no, struct nameseq *filenames, char *commands, size_t commands_idx, char *depstr) { - struct commands *cmds_p; + struct commands *commands_p; struct dep *deps; struct nameseq *ns, *old_ns; - if (cmds_idx > 0) { + if (commands_idx > 0) { - cmds_p = xmalloc (sizeof (*cmds_p)); + commands_p = xmalloc (sizeof (*commands_p)); - cmds_p->text = xstrndup (cmds, cmds_idx); - cmds_p->len = cmds_idx; + commands_p->text = xstrndup (commands, commands_idx); + commands_p->len = commands_idx; } else { - cmds_p = 0; + commands_p = 0; } if (depstr) { @@ -975,9 +976,9 @@ void record_files (const char *filename, unsigned long line_no, struct nameseq * for (ns = filenames, old_ns = 0; ns; old_ns = ns, ns = ns->next, free (old_ns->name), free (old_ns)) { if (ns->name[0] == '.' && !strchr (ns->name, '\\') && !strchr (ns->name, '/')) { - rule_add_suffix (filename, line_no - 1, ns->name, cmds_p); + rule_add_suffix (filename, line_no - 1, ns->name, commands_p); } else { - rule_add (filename, line_no - 1, ns->name, deps, cmds_p); + rule_add (filename, line_no - 1, ns->name, deps, commands_p); } } diff --git a/read.h b/read.h index a880c0e..78adf43 100644 --- a/read.h +++ b/read.h @@ -14,7 +14,7 @@ struct nameseq { }; -void record_files (const char *filename, unsigned long line_no, struct nameseq *filenames, char *cmds, size_t cmds_idx, char *depstr); +void record_files (const char *filename, unsigned long line_no, struct nameseq *filenames, char *commands, size_t commands_idx, char *depstr); void *parse_nameseq (char *line, size_t size); #endif /* _READ_H */ diff --git a/rule.c b/rule.c index 0959631..c914146 100644 --- a/rule.c +++ b/rule.c @@ -49,11 +49,34 @@ struct rule *rule_find (const char *name) { } - key = hashtab_get_key (&hashtab_rules, hash_tagged_name); - free (hash_tagged_name); + if (!(key = hashtab_get_key (&hashtab_rules, hash_tagged_name))) { + + free (hash_tagged_name); + + hash_tagged_name = xstrdup (name); + ptr = hash_tagged_name; + + /* Replace filename by '%'. */ + if (*ptr) { + + dot = strrchr (ptr, '.'); + *ptr++ = '%'; + + if (dot) { + memmove (ptr, dot, strlen (dot) + 1); + } else { + *ptr = '\0'; + } + + } + + key = hashtab_get_key (&hashtab_rules, hash_tagged_name); + free (hash_tagged_name); + + if (!key) { + return 0; + } - if (!key) { - return 0; } } diff --git a/variable.c b/variable.c index a1fb77f..e52e5a2 100644 --- a/variable.c +++ b/variable.c @@ -21,6 +21,7 @@ #include +#include "cstr.h" #include "hashtab.h" #include "lib.h" #include "read.h" @@ -51,6 +52,21 @@ static char *func_eval (const char *filename, unsigned long line_no, char *input } +static char *func_dir (const char *filename, unsigned long line_no, char *input) { + + char *p; + + (void) filename; + (void) line_no; + + if ((p = strrchr (input, '/')) || (p = strrchr (input, '\\'))) { + return xstrndup (input, (p + 1) - input); + } + + return xstrdup ("./"); + +} + static char *func_error (const char *filename, unsigned long line_no, char *input) { fprintf (stderr, "%s: %s:%lu: *** %s. Stop.\n", program_name, filename, line_no, input); @@ -60,6 +76,67 @@ static char *func_error (const char *filename, unsigned long line_no, char *inpu } +static char *func_filter_out (const char *filename, unsigned long line_no, char *input) { + + char *filter, *goals; + char *goal, *p; + + CString str; + cstr_new (&str); + + (void) filename; + (void) line_no; + + filter = xstrdup (input); + + if (!(goals = strstr (filter, ",")) || !goals[0]) { + return 0; + } + + *goals++ = 0; + + filter = skip_whitespace (filter); + goals = skip_whitespace (goals); + + for (;;) { + + if ((p = strchr (goals, ' '))) { + + goal = xstrndup (goals, p - goals); + + if (!strstr (filter, goal)) { + cstr_cat (&str, goal, strlen (goal)); + } + + free (goal); + goals = skip_whitespace (p); + + } else { + + goal = xstrdup (goals); + + if (!strstr (filter, goal)) { + cstr_cat (&str, goal, strlen (goal)); + } + + free (goal); + break; + + } + + } + + cstr_ccat (&str, '\0'); + + if (*(goals = xstrdup (str.data))) { + return goals; + } + + free (goals); + return xstrdup ("@"); + +} + static char *func_subst (const char *filename, unsigned long line_no, char *input) { char *src, *dst, *new_body, *old_body, *p; @@ -416,6 +493,20 @@ static char *func_shell (const char *filename, unsigned long line_no, char *inpu # include # include # include + +static char *internal_commands[] = { + + "if", + "for", + "done", + "fi", + "do", + "while", + "continue", + "find" + +}; + static char *func_shell (const char *filename, unsigned long line_no, char *input) { int pipefd[2], pid, status; @@ -442,10 +533,157 @@ static char *func_shell (const char *filename, unsigned long line_no, char *inpu if (pid == 0) { - char *name = input, *space = 0, *slash; + unsigned long len; + char *temp; + + char **argv; + int argc = 1; + + char *prog = input, *space = 0, *ptr, *p; + int offset = 0, internal = 0, quote, i; + + if ((space = strchr (prog, ' '))) { + + ptr = space + 1; + + for (i = 0; ptr[i]; i++) { + + if (isspace ((int) ptr[i])) { + argc++; + } + + } + + prog = xstrndup (prog, space - prog); + + if (!(p = strchr (prog, '/'))) { + + unsigned long count = sizeof (internal_commands) / sizeof (internal_commands[0]) - 1; + unsigned long i; + + for (i = 0; i < count; i++) { + + if (xstrcasecmp (prog, internal_commands[i]) == 0) { + + if (prog) { free (prog); } + prog = xstrdup (getenv ("SHELL")); + + internal = 1; + break; + + } + + } + + } + + if (internal) { + + argv = xmalloc (sizeof (*argv) * 4); + + argv[1] = "-c"; + argv[2] = input; + argc = 3; + + } else { + + argv = xmalloc (sizeof (*argv) * (argc + 1)); + + for (i = 0; ; i++) { + + if (!isspace ((int) ptr[i])) { + break; + } + + } + + argv[1] = ptr + i; + argc = 1; + quote = 0; + + while (ptr[i]) { + + ptr[i - offset] = ptr[i]; + + if (quote) { + + if (ptr[i] == '\\' && (ptr[i + 1] == quote || ptr[i + 1] == '\\')) { + + offset++; + i++; + + ptr[i - offset] = ptr[i]; + + } else if (ptr[i] == quote) { + + len = strlen (ptr + i + 1); + temp = xstrdup (ptr + i + 1); + + memmove (ptr + i, temp, len); + *(ptr + i + len) = '\0'; + + quote = 0; + i--; + + } + + i++; + + } else if (ptr[i] == '\'' || ptr[i] == '"') { + + quote = ptr[i]; + + len = strlen (ptr + i + 1); + temp = xstrdup (ptr + i + 1); + + memmove (ptr + i, temp, len); + *(ptr + i + len) = '\0'; + + } else if (isspace ((int) ptr[i])) { + + ptr[i - offset] = '\0'; + argc++; + + for (i = i + 1; ; i++) { + + if (!isspace ((int) ptr[i])) { + break; + } + + } + + argv[argc] = ptr + i - offset; + + } else { + i++; + } + + } + + if (argv[argc] != ptr + i - offset) { + + ptr[i - offset] = '\0'; + argc++; + + } + + } + + } else { + argv = xmalloc (sizeof (*argv) * (argc + 1)); + } + + argv[0] = prog; + argv[argc] = 0; + + if (strcmp (prog, "ls") == 0 && argc == 1) { + + argv = xrealloc (argv, sizeof (*argv) * 3); + argc = 2; + + argv[1] = "-C"; + argv[2] = 0; - if ((space = strchr (name, ' '))) { - name = xstrndup (name, space - name); } dup2 (pipefd[1], STDOUT_FILENO); @@ -453,9 +691,10 @@ static char *func_shell (const char *filename, unsigned long line_no, char *inpu close (pipefd[0]); close (pipefd[1]); - execlp (name, (slash = strrchr (name, '/')) ? (slash + 1) : name, space ? skip_whitespace (space) : NULL, NULL); + execvp (prog, argv); + free (argv); - fprintf (stderr, "%s: %s:%lu: %s: %s\n", program_name, filename, line_no, name, strerror (errno)); + fprintf (stderr, "%s: %s:%lu: %s: %s\n", program_name, filename, line_no, prog, strerror (errno)); exit (EXIT_FAILURE); } @@ -536,16 +775,18 @@ static char *func_shell (const char *filename, unsigned long line_no, char *inpu static struct builtin_function builtin_functions[] ={ - { "error", &func_error }, + { "error", &func_error }, + { "filter-out", &func_filter_out }, #if defined (_WIN32) || defined (__WIN32__) || defined (unix) || defined (__unix) || defined (__unix__) || defined (__APPLE__) - { "shell", &func_shell }, + { "shell", &func_shell }, #endif - { "eval", &func_eval }, - { "subst", &func_subst }, + { "dir", &func_dir }, + { "eval", &func_eval }, + { "subst", &func_subst }, - { 0, 0 } + { 0, 0 } }; @@ -802,7 +1043,7 @@ char *variable_expand_line (const char *filename, unsigned long line_no, char *l } else { - if (state->env_override || strcmp (content, "PATH") == 0) { + if (state->env_override || strcmp (content, "PATH") == 0 || strcmp (content, "MAKEFLAGS") == 0) { if ((alloc_replacement = getenv (content))) { @@ -1111,7 +1352,22 @@ void parse_var_line (const char *filename, unsigned long line_no, char *line, en #else setenv ("PATH", new_value, 1); -#endif +#endif + + } else if (strcmp (var_name, "MAKEFLAGS") == 0) { + +#if defined (_WIN32) + + char *temp = xmalloc (10 + strlen (new_value) + 1); + + sprintf (temp, "MAKEFLAGS=%s", new_value); + _putenv (temp); + + free (temp); + +#else + setenv ("MAKEFLAGS", new_value, 1); +#endif } diff --git a/xmake.c b/xmake.c index e99b81e..c80ce7b 100644 --- a/xmake.c +++ b/xmake.c @@ -137,7 +137,7 @@ static int pipe_command (const char *filename, unsigned long line_no, char *inpu for (i = 0; i < count; i++) { - if (strcasecmp (lpApplicationName, internal_commands[i]) == 0) { + if (xstrcasecmp (lpApplicationName, internal_commands[i]) == 0) { if (lpApplicationName) { free (lpApplicationName); @@ -329,6 +329,20 @@ static int pipe_command (const char *filename, unsigned long line_no, char *inpu # include # include # include + +static char *internal_commands[] = { + + "if", + "for", + "done", + "fi", + "do", + "while", + "continue", + "find" + +}; + static int pipe_command (const char *filename, unsigned long line_no, char *input, int is_ignoring_errors, const char *name) { int pipefd[2], pid, status; @@ -354,11 +368,14 @@ static int pipe_command (const char *filename, unsigned long line_no, char *inpu if (pid == 0) { + unsigned long len; + char *temp; + char **argv; int argc = 1; - char *prog = input, *space = 0, *ptr; - int offset = 0, quote, i; + char *prog = input, *space = 0, *ptr, *p; + int offset = 0, internal = 0, quote, i; if ((space = strchr (prog, ' '))) { @@ -373,83 +390,124 @@ static int pipe_command (const char *filename, unsigned long line_no, char *inpu } prog = xstrndup (prog, space - prog); - argv = xmalloc (sizeof (*argv) * (argc + 1)); - for (i = 0; ; i++) { + if (!(p = strchr (prog, '/'))) { - if (!isspace ((int) ptr[i])) { - break; + unsigned long count = sizeof (internal_commands) / sizeof (internal_commands[0]) - 1; + unsigned long i; + + for (i = 0; i < count; i++) { + + if (xstrcasecmp (prog, internal_commands[i]) == 0) { + + internal = 1; + break; + + } + } } - argv[1] = ptr + i; - argc = 1; - quote = 0; + if (internal || strchr (input, '>')) { - while (ptr[i]) { + if (prog) { free (prog); } + + prog = xstrdup (getenv ("SHELL")); + argv = xmalloc (sizeof (*argv) * 4); + + argv[1] = "-c"; + argv[2] = input; + argc = 3; + + } else { - ptr[i - offset] = ptr[i]; + argv = xmalloc (sizeof (*argv) * (argc + 1)); + + for (i = 0; ; i++) { - if (quote) { + if (!isspace ((int) ptr[i])) { + break; + } - if (ptr[i] == '\\' && (ptr[i + 1] == quote || ptr[i + 1] == '\\')) { + } + + argv[1] = ptr + i; + argc = 1; + quote = 0; + + while (ptr[i]) { + + ptr[i - offset] = ptr[i]; + + if (quote) { - offset++; + if (ptr[i] == '\\' && (ptr[i + 1] == quote || ptr[i + 1] == '\\')) { + + offset++; + i++; + + ptr[i - offset] = ptr[i]; + + } else if (ptr[i] == quote) { + + len = strlen (ptr + i + 1); + temp = xstrdup (ptr + i + 1); + + memmove (ptr + i, temp, len); + *(ptr + i + len) = '\0'; + + quote = 0; + i--; + + } + i++; + + } else if (ptr[i] == '\'' || ptr[i] == '"') { + + quote = ptr[i]; + + len = strlen (ptr + i + 1); + temp = xstrdup (ptr + i + 1); - ptr[i - offset] = ptr[i]; + memmove (ptr + i, temp, len); + *(ptr + i + len) = '\0'; - } else if (ptr[i] == quote) { + } else if (isspace ((int) ptr[i])) { - quote = 0; - offset++; + ptr[i - offset] = '\0'; + argc++; + + for (i = i + 1; ; i++) { + + if (!isspace ((int) ptr[i])) { + break; + } + + } + + argv[argc] = ptr + i - offset; + } else { + i++; } - - i++; - - } else if (ptr[i] == '\'' || ptr[i] == '"') { - if (argv[argc] == ptr + i - offset) { - argv[argc]++; - } - - quote = ptr[i]; - i++; + } - } else if (isspace ((int) ptr[i])) { + if (argv[argc] != ptr + i - offset) { ptr[i - offset] = '\0'; argc++; - - for (i = i + 1; ; i++) { - - if (!isspace ((int) ptr[i])) { - break; - } - - } - - argv[argc] = ptr + i - offset; - } else { - i++; } } - - if (argv[argc] != ptr + i - offset) { - - ptr[i - offset] = '\0'; - argc++; - - } } else { argv = xmalloc (sizeof (*argv) * (argc + 1)); } - + argv[0] = prog; argv[argc] = 0; @@ -627,7 +685,7 @@ static int rule_run_command (const char *filename, unsigned long line_no, const fprintf (stderr, "%s: %s: No such file or directory\n", program_name, p); fprintf (stderr, "%s: *** [%s:%lu: %s] Error %d\n", program_name, filename, line_no, name, status); - if (!keep_going) { + if (!state->keep_going) { exit (EXIT_FAILURE); } @@ -670,7 +728,7 @@ static char *parse_command (char *text) { } - ret = xmalloc (strlen (cwd) + 1 + strlen (text)); + ret = xmalloc (strlen (cwd) + 1 + strlen (text) + 1); sprintf (ret, "%s/%s", cwd, text); return ret; @@ -708,14 +766,91 @@ static int run_commands (const char *filename, unsigned long line_no, struct com } +static int file_exists (char *name) { + + FILE *f; + + if (!(f = fopen (name, "r"))) { + return 0; + } + + fclose (f); + return 1; + +} + +static char *find_target (char *target) { + + struct variable *vpath_var; + char *vpath; + + if (file_exists (target)) { + return target; + } + + if (!(vpath_var = variable_find ("VPATH"))) { + return 0; + } + + vpath = variable_expand_line ("", 1, xstrdup (vpath_var->value)); + + while (vpath && *vpath) { + + char *vpath_part, *new_target; + char saved_ch; + + while (*vpath && (isspace ((int) *vpath) || (*vpath == ';'))) { + vpath++; + } + + vpath_part = vpath; + + while (*vpath && !isspace ((int) *vpath) && *vpath != ';') { + vpath++; + } + + saved_ch = *vpath; + *vpath = '\0'; + + new_target = xmalloc (strlen (vpath_part) + 1 + strlen (target) + 1); + strcpy (new_target, vpath_part); + + if (strchr (vpath_part, '\\')) { + strcat (new_target, "\\"); + } else { + strcat (new_target, "/"); + } + + strcat (new_target, target); + *vpath = saved_ch; + + if (file_exists (new_target)) { + return new_target; + } + + free (new_target); + + if (!(vpath = strchr (vpath, ';'))) { + break; + } + + vpath++; + + } + + return 0; + +} + static int rule_use (struct rule *r, char *name) { struct dep *dep; - char *hash_name = 0, *filename = 0, *dot = 0, *n2 = 0; + char *hash_name = 0, *filename = 0, *dot = 0; int ret; char *p, *star_name, *lesser_name; + char *n2, *n3; CString str; cstr_new (&str); @@ -728,7 +863,7 @@ static int rule_use (struct rule *r, char *name) { n2 = xmalloc (strlen (dep->name) + strlen (name) + 1); strncat (n2, dep->name, p - dep->name); - if (!(filename = strrchr (name, '/'))) { + /*if (!(filename = strrchr (name, '/'))) { filename = strrchr (name, '\\'); } @@ -736,7 +871,9 @@ static int rule_use (struct rule *r, char *name) { filename = name; } else { filename++; - } + }*/ + + filename = name; if ((dot = strrchr (filename, '.'))) { strncat (n2, filename, dot - filename); @@ -746,21 +883,57 @@ static int rule_use (struct rule *r, char *name) { strcat (n2, p + 1); - ret = rule_search_and_build (n2); - cstr_cat (&str, n2, strlen (n2)); + if (!(n3 = find_target (n2))) { + + if ((ret = rule_search_and_build (n2))) { + + free (n2); + return ret; + + } + + cstr_cat (&str, n2, strlen (n2)); + free (n2); - free (n2); + } else { + + free (n2); + + if ((ret = rule_search_and_build (n3))) { + + free (n3); + return ret; + + } + + cstr_cat (&str, n3, strlen (n3)); + free (n3); - if (ret) { - return ret; } + + if (ret) { return ret; } } else { - cstr_cat (&str, dep->name, strlen (dep->name)); + if (!(n3 = find_target (dep->name))) { + + if ((ret = rule_search_and_build (dep->name))) { + return ret; + } + + cstr_cat (&str, dep->name, strlen (dep->name)); + + } else { + + if ((ret = rule_search_and_build (n3))) { + + free (n3); + return ret; + + } + + cstr_cat (&str, n3, strlen (n3)); - if ((ret = rule_search_and_build (dep->name))) { - return ret; } } @@ -783,7 +956,49 @@ static int rule_use (struct rule *r, char *name) { doing_inference_rule_commands = 0; if (r->deps) { - lesser_name = xstrdup (r->deps->name); + + dep = r->deps; + + if ((p = strchr (dep->name, '%'))) { + + /* Replace the rule's '%' by the filename without extension. */ + n2 = xmalloc (strlen (dep->name) + strlen (name) + 1); + strncat (n2, dep->name, p - dep->name); + + /*if (!(filename = strrchr (name, '/'))) { + filename = strrchr (name, '\\'); + } + + if (!filename) { + filename = name; + } else { + filename++; + }*/ + + filename = name; + + if ((dot = strrchr (filename, '.'))) { + strncat (n2, filename, dot - filename); + } else { + strcat (n2, filename); + } + + strcat (n2, p + 1); + + if (!(lesser_name = find_target (n2))) { + lesser_name = n2; + } else { + free (n2); + } + + } else { + + if (!(lesser_name = find_target (dep->name))) { + lesser_name = xstrdup (dep->name); + } + + } + } else { lesser_name = xstrdup (""); } @@ -869,82 +1084,6 @@ static int single_suffix_rule_use (struct suffix_rule *s, char *name) { } -static int file_exists (char *name) { - - FILE *f; - - if (!(f = fopen (name, "r"))) { - return 0; - } - - fclose (f); - return 1; - -} - -static char *find_target (char *target) { - - struct variable *vpath_var; - char *vpath; - - if (file_exists (target)) { - return target; - } - - if (!(vpath_var = variable_find ("VPATH"))) { - return 0; - } - - vpath = variable_expand_line ("", 1, xstrdup (vpath_var->value)); - - while (vpath && *vpath) { - - char *vpath_part, *new_target; - char saved_ch; - - while (*vpath && (isspace ((int) *vpath) || (*vpath == ';'))) { - vpath++; - } - - vpath_part = vpath; - - while (*vpath && !isspace ((int) *vpath) && *vpath != ';') { - vpath++; - } - - saved_ch = *vpath; - *vpath = '\0'; - - new_target = xmalloc (strlen (vpath_part) + 1 + strlen (target) + 1); - strcpy (new_target, vpath_part); - - if (strchr (vpath_part, '\\')) { - strcat (new_target, "\\"); - } else { - strcat (new_target, "/"); - } - - strcat (new_target, target); - *vpath = saved_ch; - - if (file_exists (new_target)) { - return new_target; - } - - free (new_target); - - if (!(vpath = strchr (vpath, ';'))) { - break; - } - - vpath++; - - } - - return 0; - -} - int rule_search_and_build (char *name) { struct rule *r; @@ -1083,9 +1222,10 @@ int rule_search_and_build (char *name) { int main (int argc, char **argv) { - char *cwd = 0; + char *cwd = 0, *makeflags; int ret; + struct variable *makecmdgoals; unsigned long i; if (argc && *argv) { @@ -1103,19 +1243,135 @@ int main (int argc, char **argv) { rules_init (); default_goal_var = variable_add (xstrdup (".DEFAULT_GOAL"), xstrdup (""), VAR_ORIGIN_FILE); - variable_add (xstrdup ("OS"), xstrdup (os_name), VAR_ORIGIN_FILE); + + state = xmalloc (sizeof (*state)); + parse_args (argv, argc); + + if ((makeflags = getenv ("MAKEFLAGS"))) { + + char *ptr = xstrdup (makeflags), *temp; + int offset = 0, quote, i; + + char **argv; + int argc = 1; + + unsigned long len; + + for (i = 0; makeflags[i]; i++) { + + if (isspace ((int) makeflags[i])) { + argc++; + } + + } + + argv = xmalloc (sizeof (*argv) * (argc + 1)); + i = 0; + + argv[1] = ptr + i; + argc = 1; + quote = 0; + + while (ptr[i]) { + + ptr[i - offset] = ptr[i]; + + if (quote) { + + if (ptr[i] == '\\' && (ptr[i + 1] == quote || ptr[i + 1] == '\\')) { + + offset++; + i++; + + ptr[i - offset] = ptr[i]; + + } else if (ptr[i] == quote) { + + len = strlen (ptr + i + 1); + temp = xstrdup (ptr + i + 1); + + memmove (ptr + i, temp, len); + *(ptr + i + len) = '\0'; + + quote = 0; + i--; + + } + + i++; + + } else if (ptr[i] == '\'' || ptr[i] == '"') { + + quote = ptr[i]; + + len = strlen (ptr + i + 1); + temp = xstrdup (ptr + i + 1); + + memmove (ptr + i, temp, len); + *(ptr + i + len) = '\0'; + + } else if (isspace ((int) ptr[i])) { + + ptr[i - offset] = '\0'; + argc++; + + for (i = i + 1; ; i++) { + + if (!isspace ((int) ptr[i])) { + break; + } + + } + + argv[argc] = ptr + i - offset; + + } else { + i++; + } + + } + + if (argv[argc] != ptr + i - offset) { + + ptr[i - offset] = '\0'; + argc++; + + } + + argv[argc] = 0; + parse_args (argv, argc); + + } + variable_add (xstrdup ("MAKE"), xstrdup (argv[0]), VAR_ORIGIN_FILE); + if (state->nb_goals) { + + CString str; + cstr_new (&str); + + for (i = 0; i < state->nb_goals; i++) { + + cstr_cat (&str, state->goals[i], strlen (state->goals[i])); + + if (i < state->nb_goals - 1) { + cstr_ccat (&str, ' '); + } + + } + + cstr_ccat (&str, '\0'); + variable_add (xstrdup ("MAKECMDGOALS"), xstrdup (str.data), VAR_ORIGIN_FILE); + + } + #if defined (unix) || defined (__unix) || defined (__unix__) || defined (__APPLE__) variable_add (xstrdup ("SHELL"), xstrdup ("/bin/sh"), VAR_ORIGIN_FILE); #else variable_add (xstrdup ("SHELL"), xstrdup ("sh.exe"), VAR_ORIGIN_FILE); #endif - state = xmalloc (sizeof (*state)); - parse_args (argv, argc); - if (state->nb_directories > 0) { char *arg; @@ -1228,7 +1484,30 @@ int main (int argc, char **argv) { } - if (state->nb_goals == 0) { + if ((makecmdgoals = variable_find ("MAKECMDGOALS"))) { + + char *value = makecmdgoals->value, *goal, *p; + + while (*value) { + + if ((p = strchr (value, ' '))) { + goal = xstrndup (value, p - value); + } else { + goal = xstrdup (value); + } + + value = skip_whitespace (value + strlen (goal)); + + ret = rule_search_and_build (goal); + free (goal); + + if (ret && !state->keep_going) { + goto out; + } + + } + + } else { if (default_goal_var->value[0] == '\0') { @@ -1239,13 +1518,7 @@ int main (int argc, char **argv) { } - dynarray_add (&state->goals, &state->nb_goals, xstrdup (default_goal_var->value)); - - } - - for (i = 0; i < state->nb_goals; i++) { - - if ((ret = rule_search_and_build (state->goals[i]))) { + if ((ret = rule_search_and_build (default_goal_var->value))) { if (!state->keep_going) { goto out; -- 2.34.1