mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-02 10:42:27 +00:00
Import GNU Make 4.4.1
Landlock Make hasn't been working well on AARCH64 systems. Let's do this over the right way, using our new build tools.
This commit is contained in:
parent
9315ebbfd9
commit
14bf57180f
88 changed files with 13931 additions and 16191 deletions
193
third_party/make/commands.c
vendored
193
third_party/make/commands.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* Command processing for GNU Make.
|
||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2023 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
|
||||
|
@ -12,20 +12,22 @@ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/filedef.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/variable.h"
|
||||
/**/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "os.h"
|
||||
#include "dep.h"
|
||||
#include "variable.h"
|
||||
#include "job.h"
|
||||
#include "commands.h"
|
||||
|
||||
#define FILE_LIST_SEPARATOR ' '
|
||||
#if VMS
|
||||
# define FILE_LIST_SEPARATOR (vms_comma_separator ? ',' : ' ')
|
||||
#else
|
||||
# define FILE_LIST_SEPARATOR ' '
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned long
|
||||
dep_hash_1 (const void *key)
|
||||
|
@ -49,10 +51,13 @@ dep_hash_cmp (const void *x, const void *y)
|
|||
return strcmp (dep_name (dx), dep_name (dy));
|
||||
}
|
||||
|
||||
/* Set FILE's automatic variables up. */
|
||||
/* Set FILE's automatic variables up.
|
||||
* Use STEM to set $*.
|
||||
* If STEM is 0, then set FILE->STEM and $* to the target name with any
|
||||
* suffix in the .SUFFIXES list stripped off. */
|
||||
|
||||
void
|
||||
set_file_variables (struct file *file)
|
||||
set_file_variables (struct file *file, const char *stem)
|
||||
{
|
||||
struct dep *d;
|
||||
const char *at, *percent, *star, *less;
|
||||
|
@ -86,7 +91,7 @@ set_file_variables (struct file *file)
|
|||
}
|
||||
|
||||
/* $* is the stem from an implicit or static pattern rule. */
|
||||
if (file->stem == 0)
|
||||
if (stem == 0)
|
||||
{
|
||||
/* In Unix make, $* is set to the target name with
|
||||
any suffix in the .SUFFIXES list stripped off for
|
||||
|
@ -109,25 +114,25 @@ set_file_variables (struct file *file)
|
|||
|
||||
for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
|
||||
{
|
||||
size_t slen = strlen (dep_name (d));
|
||||
if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
|
||||
const char *dn = dep_name (d);
|
||||
size_t slen = strlen (dn);
|
||||
if (len > slen && memcmp (dn, name + (len - slen), slen) == 0)
|
||||
{
|
||||
file->stem = strcache_add_len (name, len - slen);
|
||||
file->stem = stem = strcache_add_len (name, len - slen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d == 0)
|
||||
file->stem = "";
|
||||
file->stem = stem = "";
|
||||
}
|
||||
star = file->stem;
|
||||
star = stem;
|
||||
|
||||
/* $< is the first not order-only dependency. */
|
||||
less = "";
|
||||
for (d = file->deps; d != 0; d = d->next)
|
||||
if (!d->ignore_mtime && !d->ignore_automatic_vars)
|
||||
if (!d->ignore_mtime && !d->ignore_automatic_vars && !d->need_2nd_expansion)
|
||||
{
|
||||
if (!d->need_2nd_expansion)
|
||||
less = dep_name (d);
|
||||
less = dep_name (d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -205,8 +210,7 @@ set_file_variables (struct file *file)
|
|||
#endif
|
||||
len = strlen (c);
|
||||
|
||||
memcpy (cp, c, len);
|
||||
cp += len;
|
||||
cp = mempcpy (cp, c, len);
|
||||
*cp++ = FILE_LIST_SEPARATOR;
|
||||
if (! (d->changed || always_make_flag))
|
||||
qmark_len -= len + 1; /* Don't space in $? for this one. */
|
||||
|
@ -276,19 +280,16 @@ set_file_variables (struct file *file)
|
|||
|
||||
if (d->ignore_mtime)
|
||||
{
|
||||
memcpy (bp, c, len);
|
||||
bp += len;
|
||||
bp = mempcpy (bp, c, len);
|
||||
*bp++ = FILE_LIST_SEPARATOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (cp, c, len);
|
||||
cp += len;
|
||||
cp = mempcpy (cp, c, len);
|
||||
*cp++ = FILE_LIST_SEPARATOR;
|
||||
if (d->changed || always_make_flag)
|
||||
{
|
||||
memcpy (qp, c, len);
|
||||
qp += len;
|
||||
qp = mempcpy (qp, c, len);
|
||||
*qp++ = FILE_LIST_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
@ -317,14 +318,12 @@ set_file_variables (struct file *file)
|
|||
void
|
||||
chop_commands (struct commands *cmds)
|
||||
{
|
||||
unsigned int nlines;
|
||||
unsigned short idx;
|
||||
unsigned short nlines;
|
||||
unsigned short i;
|
||||
char **lines;
|
||||
|
||||
/* If we don't have any commands,
|
||||
or we already parsed them, never mind. */
|
||||
|
||||
if (!cmds || cmds->command_lines != 0)
|
||||
/* If we don't have any commands, or we already parsed them, never mind. */
|
||||
if (!cmds || cmds->command_lines != NULL)
|
||||
return;
|
||||
|
||||
/* Chop CMDS->commands up into lines in CMDS->command_lines. */
|
||||
|
@ -343,25 +342,27 @@ chop_commands (struct commands *cmds)
|
|||
}
|
||||
else
|
||||
{
|
||||
const char *p;
|
||||
const char *p = cmds->commands;
|
||||
size_t max = 5;
|
||||
|
||||
nlines = 5;
|
||||
lines = xmalloc (nlines * sizeof (char *));
|
||||
idx = 0;
|
||||
p = cmds->commands;
|
||||
nlines = 0;
|
||||
lines = xmalloc (max * sizeof (char *));
|
||||
while (*p != '\0')
|
||||
{
|
||||
const char *end = p;
|
||||
find_end:;
|
||||
end = strchr (end, '\n');
|
||||
if (end == 0)
|
||||
if (end == NULL)
|
||||
end = p + strlen (p);
|
||||
else if (end > p && end[-1] == '\\')
|
||||
{
|
||||
int backslash = 1;
|
||||
const char *b;
|
||||
for (b = end - 2; b >= p && *b == '\\'; --b)
|
||||
backslash = !backslash;
|
||||
if (end > p + 1)
|
||||
{
|
||||
const char *b;
|
||||
for (b = end - 2; b >= p && *b == '\\'; --b)
|
||||
backslash = !backslash;
|
||||
}
|
||||
if (backslash)
|
||||
{
|
||||
++end;
|
||||
|
@ -369,40 +370,36 @@ chop_commands (struct commands *cmds)
|
|||
}
|
||||
}
|
||||
|
||||
if (idx == nlines)
|
||||
if (nlines == USHRT_MAX)
|
||||
ON (fatal, &cmds->fileinfo,
|
||||
_("Recipe has too many lines (limit %hu)"), nlines);
|
||||
|
||||
if (nlines == max)
|
||||
{
|
||||
nlines += 2;
|
||||
lines = xrealloc (lines, nlines * sizeof (char *));
|
||||
max += 2;
|
||||
lines = xrealloc (lines, max * sizeof (char *));
|
||||
}
|
||||
lines[idx++] = xstrndup (p, (size_t) (end - p));
|
||||
|
||||
lines[nlines++] = xstrndup (p, (size_t) (end - p));
|
||||
p = end;
|
||||
if (*p != '\0')
|
||||
++p;
|
||||
}
|
||||
|
||||
if (idx != nlines)
|
||||
{
|
||||
nlines = idx;
|
||||
lines = xrealloc (lines, nlines * sizeof (char *));
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, set the corresponding CMDS->lines_flags elements and the
|
||||
CMDS->any_recurse flag. */
|
||||
|
||||
if (nlines > USHRT_MAX)
|
||||
ON (fatal, &cmds->fileinfo, _("Recipe has too many lines (%ud)"), nlines);
|
||||
|
||||
cmds->ncommand_lines = (unsigned short)nlines;
|
||||
cmds->ncommand_lines = nlines;
|
||||
cmds->command_lines = lines;
|
||||
|
||||
cmds->any_recurse = 0;
|
||||
cmds->lines_flags = xmalloc (nlines);
|
||||
|
||||
for (idx = 0; idx < nlines; ++idx)
|
||||
for (i = 0; i < nlines; ++i)
|
||||
{
|
||||
unsigned char flags = 0;
|
||||
const char *p = lines[idx];
|
||||
const char *p = lines[i];
|
||||
|
||||
while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
|
||||
switch (*(p++))
|
||||
|
@ -419,12 +416,12 @@ chop_commands (struct commands *cmds)
|
|||
}
|
||||
|
||||
/* If no explicit '+' was given, look for MAKE variable references. */
|
||||
if (!(flags & COMMANDS_RECURSE)
|
||||
if (! ANY_SET (flags, COMMANDS_RECURSE)
|
||||
&& (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
|
||||
flags |= COMMANDS_RECURSE;
|
||||
|
||||
cmds->lines_flags[idx] = flags;
|
||||
cmds->any_recurse |= flags & COMMANDS_RECURSE ? 1 : 0;
|
||||
cmds->lines_flags[i] = flags;
|
||||
cmds->any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,12 +453,17 @@ execute_file_commands (struct file *file)
|
|||
|
||||
initialize_file_variables (file, 0);
|
||||
|
||||
set_file_variables (file);
|
||||
set_file_variables (file, file->stem);
|
||||
|
||||
/* If this is a loaded dynamic object, unload it before remaking.
|
||||
Some systems don't support overwriting a loaded object. */
|
||||
if (file->loaded)
|
||||
unload_file (file->name);
|
||||
/* Some systems don't support overwriting a loaded object so if this one
|
||||
unload it before remaking. Keep its name in .LOADED: it will be rebuilt
|
||||
and loaded again. If rebuilding or loading again fail, then we'll exit
|
||||
anyway and it won't matter. */
|
||||
if (file->loaded && unload_file (file->name) == 0)
|
||||
{
|
||||
file->loaded = 0;
|
||||
file->unloaded = 1;
|
||||
}
|
||||
|
||||
/* Start the commands running. */
|
||||
new_job (file);
|
||||
|
@ -470,17 +472,36 @@ execute_file_commands (struct file *file)
|
|||
/* This is set while we are inside fatal_error_signal,
|
||||
so things can avoid nonreentrant operations. */
|
||||
|
||||
int handling_fatal_signal = 0;
|
||||
volatile sig_atomic_t handling_fatal_signal = 0;
|
||||
|
||||
/* Handle fatal signals. */
|
||||
|
||||
RETSIGTYPE
|
||||
void
|
||||
fatal_error_signal (int sig)
|
||||
{
|
||||
#ifdef __MSDOS__
|
||||
extern int dos_status, dos_command_running;
|
||||
|
||||
if (dos_command_running)
|
||||
{
|
||||
/* That was the child who got the signal, not us. */
|
||||
dos_status |= (sig << 8);
|
||||
return;
|
||||
}
|
||||
remove_intermediates (1);
|
||||
exit (EXIT_FAILURE);
|
||||
#else /* not __MSDOS__ */
|
||||
#ifdef _AMIGA
|
||||
remove_intermediates (1);
|
||||
if (sig == SIGINT)
|
||||
fputs (_("*** Break.\n"), stderr);
|
||||
|
||||
exit (10);
|
||||
#else /* not Amiga */
|
||||
#ifdef WINDOWS32
|
||||
extern HANDLE main_thread;
|
||||
|
||||
/* Windows creates a sperate thread for handling Ctrl+C, so we need
|
||||
/* Windows creates a separate thread for handling Ctrl+C, so we need
|
||||
to suspend the main thread, or else we will have race conditions
|
||||
when both threads call reap_children. */
|
||||
if (main_thread)
|
||||
|
@ -488,12 +509,12 @@ fatal_error_signal (int sig)
|
|||
DWORD susp_count = SuspendThread (main_thread);
|
||||
|
||||
if (susp_count != 0)
|
||||
fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count);
|
||||
fprintf (stderr, "SuspendThread: suspend count = %lu\n", susp_count);
|
||||
else if (susp_count == (DWORD)-1)
|
||||
{
|
||||
DWORD ierr = GetLastError ();
|
||||
|
||||
fprintf (stderr, "SuspendThread: error %ld: %s\n",
|
||||
fprintf (stderr, "SuspendThread: error %lu: %s\n",
|
||||
ierr, map_windows32_error_to_string (ierr));
|
||||
}
|
||||
}
|
||||
|
@ -504,6 +525,10 @@ fatal_error_signal (int sig)
|
|||
It is blocked now while we run this handler. */
|
||||
signal (sig, SIG_DFL);
|
||||
|
||||
temp_stdin_unlink ();
|
||||
osync_clear ();
|
||||
jobserver_clear ();
|
||||
|
||||
/* A termination signal won't be sent to the entire
|
||||
process group, but it means we want to kill the children. */
|
||||
|
||||
|
@ -519,9 +544,12 @@ fatal_error_signal (int sig)
|
|||
wanted to kill make, remove pending targets. */
|
||||
|
||||
if (sig == SIGTERM || sig == SIGINT
|
||||
#ifdef SIGHUP
|
||||
|| sig == SIGHUP
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
|| sig == SIGQUIT
|
||||
|| sig == SIGPIPE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct child *c;
|
||||
|
@ -533,10 +561,7 @@ fatal_error_signal (int sig)
|
|||
(void) remote_kill (c->pid, sig);
|
||||
|
||||
for (c = children; c != 0; c = c->next)
|
||||
{
|
||||
delete_child_targets (c);
|
||||
delete_tmpdir (c);
|
||||
}
|
||||
delete_child_targets (c);
|
||||
|
||||
/* Clean up the children. We don't just use the call below because
|
||||
we don't want to print the "Waiting for children" message. */
|
||||
|
@ -552,10 +577,12 @@ fatal_error_signal (int sig)
|
|||
|
||||
remove_intermediates (1);
|
||||
|
||||
#ifdef SIGQUIT
|
||||
if (sig == SIGQUIT)
|
||||
/* We don't want to send ourselves SIGQUIT, because it will
|
||||
cause a core dump. Just exit instead. */
|
||||
exit (MAKE_TROUBLE);
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if (main_thread)
|
||||
|
@ -566,9 +593,11 @@ fatal_error_signal (int sig)
|
|||
#else
|
||||
/* Signal the same code; this time it will really be fatal. The signal
|
||||
will be unblocked when we return and arrive then to kill us. */
|
||||
if (kill (getpid (), sig) < 0)
|
||||
if (kill (make_pid (), sig) < 0)
|
||||
pfatal_with_name ("kill");
|
||||
#endif /* not WINDOWS32 */
|
||||
#endif /* not Amiga */
|
||||
#endif /* not __MSDOS__ */
|
||||
}
|
||||
|
||||
/* Delete FILE unless it's precious or not actually a file (phony),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue