diff options
Diffstat (limited to 'src/kmk/function.c')
-rw-r--r-- | src/kmk/function.c | 192 |
1 files changed, 111 insertions, 81 deletions
diff --git a/src/kmk/function.c b/src/kmk/function.c index 0cb5c2c..2af48c6 100644 --- a/src/kmk/function.c +++ b/src/kmk/function.c @@ -1,7 +1,7 @@ /* Builtin function expansion for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -81,6 +81,10 @@ static math_int math_int_from_string (const char *str); /** Checks if the @a_cch characters (bytes) in @a a_psz equals @a a_szConst. */ # define STR_N_EQUALS(a_psz, a_cch, a_szConst) \ ( (a_cch) == sizeof (a_szConst) - 1 && !strncmp ((a_psz), (a_szConst), sizeof (a_szConst) - 1) ) + +# ifdef _MSC_VER +# include "kmkbuiltin/mscfakes.h" +# endif #endif @@ -507,23 +511,11 @@ string_glob (char *line) struct nameseq *chain; unsigned int idx; -#ifndef CONFIG_WITH_ALLOC_CACHES - chain = multi_glob (parse_file_seq - (&line, '\0', sizeof (struct nameseq), - /* We do not want parse_file_seq to strip `./'s. - That would break examples like: - $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ - 0), - sizeof (struct nameseq)); -#else /* CONFIG_WITH_ALLOC_CACHES */ - chain = multi_glob (parse_file_seq - (&line, '\0', &nameseq_cache, - /* We do not want parse_file_seq to strip `./'s. - That would break examples like: - $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ - 0), - &nameseq_cache); -#endif /* CONFIG_WITH_ALLOC_CACHES */ + chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL, + /* We do not want parse_file_seq to strip `./'s. + That would break examples like: + $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ + PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS); if (result == 0) { @@ -534,30 +526,26 @@ string_glob (char *line) idx = 0; while (chain != 0) { - const char *name = chain->name; - unsigned int len = strlen (name); - struct nameseq *next = chain->next; + unsigned int len = strlen (chain->name); + + if (idx + len + 1 > length) + { + length += (len + 1) * 2; + result = xrealloc (result, length); + } + memcpy (&result[idx], chain->name, len); + idx += len; + result[idx++] = ' '; + + /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */ + free ((char *)chain->name); #ifndef CONFIG_WITH_ALLOC_CACHES free (chain); #else alloccache_free (&nameseq_cache, chain); #endif chain = next; - - /* multi_glob will pass names without globbing metacharacters - through as is, but we want only files that actually exist. */ - if (file_exists_p (name)) - { - if (idx + len + 1 > length) - { - length += (len + 1) * 2; - result = xrealloc (result, length); - } - memcpy (&result[idx], name, len); - idx += len; - result[idx++] = ' '; - } } /* Kill the last space and terminate the string. */ @@ -1338,7 +1326,7 @@ func_foreach (char *o, char **argv, const char *funcname UNUSED) char *result = 0; free (var->value); - var->value = savestring (p, len); + var->value = xstrndup (p, len); result = allocated_variable_expand (body); @@ -2210,7 +2198,7 @@ int shell_function_pid = 0, shell_function_completed; void -windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) +windows32_openpipe (int *pipedes, pid_t *pid_p, char **command_argv, char **envp) { SECURITY_ATTRIBUTES saAttr; HANDLE hIn; @@ -2231,7 +2219,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"), + fatal (NILF, _("windows32_openpipe(): DuplicateHandle(In) failed (e=%ld)\n"), GetLastError()); } @@ -2242,7 +2230,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"), + fatal (NILF, _("windows32_open_pipe(): DuplicateHandle(Err) failed (e=%ld)\n"), GetLastError()); } @@ -2252,23 +2240,26 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) hProcess = process_init_fd(hIn, hChildOutWr, hErr); if (!hProcess) - fatal (NILF, _("windows32_openpipe (): process_init_fd() failed\n")); + fatal (NILF, _("windows32_openpipe(): process_init_fd() failed\n")); /* make sure that CreateProcess() has Path it needs */ sync_Path_environment(); + /* `sync_Path_environment' may realloc `environ', so take note of + the new value. */ + envp = environ; if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) { /* register process for wait */ process_register(hProcess); /* set the pid for returning to caller */ - *pid_p = (int) hProcess; + *pid_p = (pid_t) hProcess; /* set up to read data from child */ - pipedes[0] = _open_osfhandle((long) hChildOutRd, O_RDONLY); + pipedes[0] = _open_osfhandle((intptr_t) hChildOutRd, O_RDONLY); /* this will be closed almost right away */ - pipedes[1] = _open_osfhandle((long) hChildOutWr, O_APPEND); + pipedes[1] = _open_osfhandle((intptr_t) hChildOutWr, O_APPEND); } else { /* reap/cleanup the failed process */ process_cleanup(hProcess); @@ -2283,7 +2274,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) /* set status for return */ pipedes[0] = pipedes[1] = -1; - *pid_p = -1; + *pid_p = (pid_t)-1; } } #endif @@ -2356,7 +2347,7 @@ msdos_openpipe (int* pipedes, int *pidp, char *text) #else #ifndef _AMIGA static char * -func_shell (char *o, char **argv, const char *funcname UNUSED) +func_shell (char * volatile o, char **argv, const char *funcname UNUSED) { char *batch_filename = NULL; @@ -2364,10 +2355,10 @@ func_shell (char *o, char **argv, const char *funcname UNUSED) FILE *fpipe; #endif char **command_argv; - const char *error_prefix; + const char * volatile error_prefix; /* bird: this volatile and the 'o' one, is for shutting up gcc warnings */ char **envp; int pipedes[2]; - int pid; + pid_t pid; #ifndef __MSDOS__ /* Construct the argument list. */ @@ -2457,11 +2448,11 @@ func_shell (char *o, char **argv, const char *funcname UNUSED) free (command_argv[0]); free (command_argv); - /* Close the write side of the pipe. */ -# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */ - if (pipedes[1] != -1) -# endif - close (pipedes[1]); + /* Close the write side of the pipe. We test for -1, since + pipedes[1] is -1 on MS-Windows, and some versions of MS + libraries barf when `close' is called with -1. */ + if (pipedes[1] >= 0) + close (pipedes[1]); #endif /* Set up and read from the pipe. */ @@ -2997,7 +2988,7 @@ func_translate (char *o, char **argv, const char *funcname UNUSED) /* Implements $^ and $+. - The first is somes with with FUNCNAME 'deps', the second as 'deps-all'. + The first comes with FUNCNAME 'deps', the second as 'deps-all'. If no second argument is given, or if it's empty, or if it's zero, all dependencies will be returned. If the second argument is non-zero @@ -3033,9 +3024,16 @@ func_deps (char *o, char **argv, const char *funcname) file = lookup_file (argv[0]); if (file) { - struct dep *deps = funcname[4] != '\0' && file->org_deps - ? file->org_deps : file->deps; + struct dep *deps; struct dep *d; + if (funcname[4] == '\0') + { + deps = file->deps_no_dupes; + if (!deps && file->deps) + deps = file->deps = create_uniqute_deps_chain (file->deps); + } + else + deps = file->deps; if ( file->double_colon && ( file->double_colon != file @@ -3424,6 +3422,14 @@ func_defined (char *o, char **argv, const char *funcname UNUSED) #endif /* CONFIG_WITH_DEFINED*/ +#ifdef HAVE_DOS_PATHS +#define IS_ABSOLUTE(n) (n[0] && n[1] == ':') +#define ROOT_LEN 3 +#else +#define IS_ABSOLUTE(n) (n[0] == '/') +#define ROOT_LEN 1 +#endif + /* Return the absolute name of file NAME which does not contain any `.', `..' components nor any repeated path separators ('/'). */ #ifdef KMK @@ -3435,6 +3441,7 @@ abspath (const char *name, char *apath) { char *dest; const char *start, *end, *apath_limit; + unsigned long root_len = ROOT_LEN; if (name[0] == '\0' || apath == NULL) return NULL; @@ -3461,18 +3468,7 @@ abspath (const char *name, char *apath) #else /* !WINDOWS32 && !__OS2__ */ apath_limit = apath + GET_PATH_MAX; -#ifdef HAVE_DOS_PATHS /* bird added this */ - if (isalpha(name[0]) && name[1] == ':') - { - /* drive spec */ - apath[0] = toupper(name[0]); - apath[1] = ':'; - apath[2] = '/'; - name += 2; - } - else -#endif /* HAVE_DOS_PATHS */ - if (name[0] != '/') + if (!IS_ABSOLUTE(name)) { /* It is unlikely we would make it until here but just to make sure. */ if (!starting_directory) @@ -3480,12 +3476,47 @@ abspath (const char *name, char *apath) strcpy (apath, starting_directory); +#ifdef HAVE_DOS_PATHS + if (IS_PATHSEP(name[0])) + { + if (IS_PATHSEP(name[1])) + { + /* A UNC. Don't prepend a drive letter. */ + apath[0] = name[0]; + apath[1] = name[1]; + root_len = 2; + } + /* We have /foo, an absolute file name except for the drive + letter. Assume the missing drive letter is the current + drive, which we can get if we remove from starting_directory + everything past the root directory. */ + apath[root_len] = '\0'; + } +#endif + dest = strchr (apath, '\0'); } else { - apath[0] = '/'; - dest = apath + 1; + strncpy (apath, name, root_len); + apath[root_len] = '\0'; + dest = apath + root_len; + /* Get past the root, since we already copied it. */ + name += root_len; +#ifdef HAVE_DOS_PATHS + if (!IS_PATHSEP(apath[2])) + { + /* Convert d:foo into d:./foo and increase root_len. */ + apath[2] = '.'; + apath[3] = '/'; + dest++; + root_len++; + /* strncpy above copied one character too many. */ + name--; + } + else + apath[2] = '/'; /* make sure it's a forward slash */ +#endif } for (start = end = name; *start != '\0'; start = end) @@ -3493,11 +3524,11 @@ abspath (const char *name, char *apath) unsigned long len; /* Skip sequence of multiple path-separators. */ - while (*start == '/') + while (IS_PATHSEP(*start)) ++start; /* Find end of path component. */ - for (end = start; *end != '\0' && *end != '/'; ++end) + for (end = start; *end != '\0' && !IS_PATHSEP(*end); ++end) ; len = end - start; @@ -3509,12 +3540,12 @@ abspath (const char *name, char *apath) else if (len == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ - if (dest > apath + 1) - while ((--dest)[-1] != '/'); + if (dest > apath + root_len) + for (--dest; !IS_PATHSEP(dest[-1]); --dest); } else { - if (dest[-1] != '/') + if (!IS_PATHSEP(dest[-1])) *dest++ = '/'; if (dest + len >= apath_limit) @@ -3528,11 +3559,7 @@ abspath (const char *name, char *apath) #endif /* !WINDOWS32 && !__OS2__ */ /* Unless it is root strip trailing separator. */ -#ifdef HAVE_DOS_PATHS /* bird (is this correct? what about UNC?) */ - if (dest > apath + 1 + (apath[0] != '/') && dest[-1] == '/') -#else - if (dest > apath + 1 && dest[-1] == '/') -#endif + if (dest > apath + root_len && IS_PATHSEP(dest[-1])) --dest; *dest = '\0'; @@ -3549,6 +3576,9 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED) const char *path = 0; int doneany = 0; unsigned int len = 0; +#ifndef HAVE_REALPATH + struct stat st; +#endif PATH_VAR (in); PATH_VAR (out); @@ -3563,7 +3593,7 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED) #ifdef HAVE_REALPATH realpath (in, out) #else - abspath (in, out) + abspath (in, out) && stat (out, &st) == 0 #endif ) { |