--- /dev/null Fri Oct 29 17:01:51 2004 +++ next.c Fri Oct 29 17:01:41 2004 @@ -0,0 +1,226 @@ +#if defined(__APPLE__) || defined(NeXT) || defined(NeXT_PDO) /* for NEXT_VPATH_FLAG support */ +#include "make.h" +#include "job.h" +#include "commands.h" +#include "filedef.h" +#include "variable.h" +#include "dep.h" +#include +#include + +#if !__STDC__ +#define const +#endif + +/* Search through a pathlist for a file. `search_path' will parse `path', + * a list of pathnames separated by colons, prepending each pathname to + * `filename'. The resulting filename will be checked for existence via + * stat(). + */ +static int +search_path(path, file) + const char *path; + char **file; +{ + int n, length; + char *filename, *name; + const char *nextchar, *lastchar; + + filename = *file; + n = strlen(filename); + length = strlen(path) + n + 10; + name = alloca(length) + length - 1; + *name = '\0'; + + filename += n; + while (--n >= 0) + *--name = *--filename; + + if (*name == '/' || path == 0) + path = ""; + + /* Strip off leading './'s, if any. */ + while (*name == '.' && *(name + 1) == '/') + name += 2; + + do { + /* Advance to the end of the next path in our path list. */ + nextchar = path; +#if defined (__MSDOS__) || defined (WIN32) + while ((*nextchar != '\0' && *nextchar != ':' && !isspace (*nextchar)) + || (*nextchar == ':' && nextchar - path == 1 + && (nextchar[1] == '/' || nextchar[1] == '\\'))) + nextchar++; +#else + while (*nextchar != '\0' && *nextchar != ':' && !isspace (*nextchar)) + nextchar++; +#endif + + lastchar = nextchar; + filename = name; + + /* If we actually have a path, prepend the file name with a '/'. */ + if (nextchar != path) + *--filename = '/'; + + /* Prepend the file name with the path. */ + while (nextchar != path) + *--filename = *--nextchar; + + path = (*lastchar) ? lastchar + 1 : lastchar; + + { + struct stat s; + if (stat(filename, &s) >= 0) { + /* We have found a file. + * Store the name we found into *FILE for the caller. */ + *file = savestring(filename, strlen(filename)); + return (1); + } + } + } while (*path != 0); + return (0); +} + +int +general_vpath_search(file) + char **file; +{ + int s; + int savelen; + char *vpath, *save; + + save = save_variable_output(&savelen); + vpath = variable_expand ("$(VPATH)"); + if (**file == '/' || *vpath == '\0') { + restore_variable_output(save, savelen); + return 0; + } + s = search_path(vpath, file); + restore_variable_output(save, savelen); + return s; +} + +static int +match_dep(filename, file) + char **filename; + struct file *file; +{ + struct dep *d; + + /* don't substitute for . or .. */ + if (!strcmp (*filename, ".") || !strcmp (*filename, "..")) + return 0; + + for (d = file->deps; d != 0; d = d->next) { + if (d->file->old_name != 0) { + if (strcmp(*filename, d->file->old_name) == 0) { + *filename = dep_name(d); + return 1; + } + } + if (strcmp(*filename, dep_name(d)) == 0) { + if (general_vpath_search(filename)) + return 1; + } + } + return 0; +} + +/* Scan LINE for vpath references. */ + +static char * +vpath_expand(line, file) + char *line; + struct file *file; +{ + struct variable *v; + char *p, *p1, *o; + static char *meta = 0; + + if (meta == 0) { + static char buffer[256] = {0}; + meta = buffer; + meta['\0'] = 1; + for (p = "=|^();&<>*?[]:$`'\"\\\n"; *p != 0; p++) + meta[*p] = 1; + } + + p = line; + o = initialize_variable_output (); + + while (1) { + /* Copy all following uninteresting chars all at once to the + variable output buffer, and skip them. Uninteresting chars end + at the next space or semicolon. */ + + for (p1 = p; *p1 != 0 && (isspace(*p1) || meta[*p1]); p1++) + ; + o = variable_buffer_output (o, p, p1 - p); + if (*p1 == 0) + break; + p = p1; + while (*p1 != 0 && !(isspace(*p1) || meta[*p1])) + p1++; + { + unsigned int n = p1 - p; + char *buffer = malloc(n + 1); + char *filename = buffer; + struct dep *dep; + + strncpy(filename, p, n); + filename[n] = 0; + + if (match_dep(&filename, file)) { + static struct file *last_file = 0; + if (last_file != file) { + last_file = file; + if (!(next_flag & NEXT_QUIET_FLAG)) { + error(&file->cmds->fileinfo, + "Using old-style VPATH substitution."); + error(&file->cmds->fileinfo, + "Consider using automatic variable substitution instead."); + } + } + o = variable_buffer_output (o, filename, strlen(filename)); + } else { + o = variable_buffer_output (o, filename, n); + } + p = p1; + free(buffer); + } + if (*p == '\0') + break; + } + (void) variable_buffer_output (o, "", 1); + return initialize_variable_output (); +} + +char * +allocated_vpath_expand_for_file(line, file) + char *line; + struct file *file; +{ + char *save, *value; + struct variable_set_list *save_set_list; + int savelen; + + if (file == 0) + fatal(NILF, "Can't do VPATH expansion on a null file.\n"); + + save = save_variable_output (&savelen); + + save_set_list = current_variable_set_list; + current_variable_set_list = file->variables; + reading_file = &file->cmds->fileinfo; + value = vpath_expand (line, file); + current_variable_set_list = save_set_list; + reading_file = 0; + + value = savestring (value, strlen (value)); + + restore_variable_output (save, savelen); + + return value; +} +#endif /* __APPLE__ || NeXT || NeXT_PDO */