#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; { 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; 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 */