darling-gnumake/next.c
2016-01-18 19:49:15 +01:00

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 */