mirror of
https://github.com/darlinghq/darling-gnumake.git
synced 2024-11-23 03:49:58 +00:00
225 lines
5.2 KiB
C
225 lines
5.2 KiB
C
#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 <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#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 */
|