/* Command processing for GNU Make. Copyright (C) 1988, 89, 91, 92, 93, 94, 95 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 terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY 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 GNU Make; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "make.h" #include "dep.h" #include "filedef.h" #include "variable.h" #include "job.h" #include "commands.h" extern int remote_kill PARAMS ((int id, int sig)); #ifndef HAVE_UNISTD_H extern int getpid (); #endif /* Set FILE's automatic variables up. */ static void set_file_variables (file) register struct file *file; { register char *p; char *at, *percent, *star, *less; #ifndef NO_ARCHIVES /* If the target is an archive member `lib(member)', then $@ is `lib' and $% is `member'. */ if (ar_name (file->name)) { unsigned int len; p = index (file->name, '('); at = (char *) alloca (p - file->name + 1); bcopy (file->name, at, p - file->name); at[p - file->name] = '\0'; len = strlen (p + 1); percent = (char *) alloca (len); bcopy (p + 1, percent, len - 1); percent[len - 1] = '\0'; } else #endif /* NO_ARCHIVES. */ { at = file->name; percent = ""; } /* $* is the stem from an implicit or static pattern rule. */ if (file->stem == 0) { /* In Unix make, $* is set to the target name with any suffix in the .SUFFIXES list stripped off for explicit rules. We store this in the `stem' member. */ register struct dep *d; char *name; unsigned int len; #ifndef NO_ARCHIVES if (ar_name (file->name)) { name = index (file->name, '(') + 1; len = strlen (name) - 1; } else #endif { name = file->name; len = strlen (name); } for (d = enter_file (".SUFFIXES")->deps; d != 0; d = d->next) { unsigned int slen = strlen (dep_name (d)); if (len > slen && !strncmp (dep_name (d), name + (len - slen), slen)) { file->stem = savestring (name, len - slen); break; } } if (d == 0) file->stem = ""; } star = file->stem; /* $< is the first dependency. */ less = file->deps != 0 ? dep_name (file->deps) : ""; if (file->cmds == default_file->cmds) /* This file got its commands from .DEFAULT. In this case $< is the same as $@. */ less = at; #define DEFINE_VARIABLE(name, len, value) \ (void) define_variable_for_file (name, len, value, o_automatic, 0, file) /* Define the variables. */ DEFINE_VARIABLE ("<", 1, less); DEFINE_VARIABLE ("*", 1, star); DEFINE_VARIABLE ("@", 1, at); DEFINE_VARIABLE ("%", 1, percent); /* Compute the values for $^, $+, and $?. */ { register unsigned int qmark_len, plus_len; char *caret_value, *plus_value; register char *cp; char *qmark_value; register char *qp; register struct dep *d; unsigned int len; /* Compute first the value for $+, which is supposed to contain duplicate dependencies as they were listed in the makefile. */ plus_len = 0; for (d = file->deps; d != 0; d = d->next) plus_len += strlen (dep_name (d)) + 1; len = plus_len == 0 ? 1 : plus_len; cp = plus_value = (char *) alloca (len); qmark_len = plus_len; /* Will be this or less. */ for (d = file->deps; d != 0; d = d->next) { char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = index (c, '(') + 1; len = strlen (c) - 1; } else #endif len = strlen (c); bcopy (c, cp, len); cp += len; #if VMS *cp++ = ','; #else *cp++ = ' '; #endif if (! d->changed) qmark_len -= len + 1; /* Don't space in $? for this one. */ } /* Kill the last space and define the variable. */ cp[cp > plus_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("+", 1, plus_value); /* Make sure that no dependencies are repeated. This does not really matter for the purpose of updating targets, but it might make some names be listed twice for $^ and $?. */ uniquize_deps (file->deps); /* Compute the values for $^ and $?. */ cp = caret_value = plus_value; /* Reuse the buffer; it's big enough. */ len = qmark_len == 0 ? 1 : qmark_len; qp = qmark_value = (char *) alloca (len); for (d = file->deps; d != 0; d = d->next) { char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = index (c, '(') + 1; len = strlen (c) - 1; } else #endif len = strlen (c); bcopy (c, cp, len); cp += len; #if VMS *cp++ = ','; #else *cp++ = ' '; #endif if (d->changed) { bcopy (c, qp, len); qp += len; #if VMS *qp++ = ','; #else *qp++ = ' '; #endif } } /* Kill the last spaces and define the variables. */ cp[cp > caret_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("^", 1, caret_value); qp[qp > qmark_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("?", 1, qmark_value); } #undef DEFINE_VARIABLE } /* Chop CMDS up into individual command lines if necessary. Also set the `lines_flag' and `any_recurse' members. */ void chop_commands (cmds) register struct commands *cmds; { if (cmds != 0 && cmds->command_lines == 0) { /* Chop CMDS->commands up into lines in CMDS->command_lines. Also set the corresponding CMDS->lines_flags elements, and the CMDS->any_recurse flag. */ register char *p; unsigned int nlines, idx; char **lines; nlines = 5; lines = (char **) xmalloc (5 * sizeof (char *)); idx = 0; p = cmds->commands; while (*p != '\0') { char *end = p; find_end:; end = index (end, '\n'); if (end == 0) end = p + strlen (p); else if (end > p && end[-1] == '\\') { int backslash = 1; register char *b; for (b = end - 2; b >= p && *b == '\\'; --b) backslash = !backslash; if (backslash) { ++end; goto find_end; } } if (idx == nlines) { nlines += 2; lines = (char **) xrealloc ((char *) lines, nlines * sizeof (char *)); } lines[idx++] = savestring (p, end - p); p = end; if (*p != '\0') ++p; } if (idx != nlines) { nlines = idx; lines = (char **) xrealloc ((char *) lines, nlines * sizeof (char *)); } cmds->ncommand_lines = nlines; cmds->command_lines = lines; cmds->any_recurse = 0; cmds->lines_flags = (char *) xmalloc (nlines); for (idx = 0; idx < nlines; ++idx) { int flags = 0; for (p = lines[idx]; isblank (*p) || *p == '-' || *p == '@' || *p == '+'; ++p) switch (*p) { case '+': flags |= COMMANDS_RECURSE; break; case '@': flags |= COMMANDS_SILENT; break; case '-': flags |= COMMANDS_NOERROR; break; } if (!(flags & COMMANDS_RECURSE)) { unsigned int len = strlen (p); if (sindex (p, len, "$(MAKE)", 7) != 0 || sindex (p, len, "${MAKE}", 7) != 0) flags |= COMMANDS_RECURSE; } cmds->lines_flags[idx] = flags; cmds->any_recurse |= flags & COMMANDS_RECURSE; } } } /* Execute the commands to remake FILE. If they are currently executing, return or have already finished executing, just return. Otherwise, fork off a child process to run the first command line in the sequence. */ void execute_file_commands (file) struct file *file; { register char *p; /* Don't go through all the preparations if the commands are nothing but whitespace. */ for (p = file->cmds->commands; *p != '\0'; ++p) if (!isspace (*p) && *p != '-' && *p != '@') break; if (*p == '\0') { /* We are all out of commands. If we have gotten this far, all the previous commands have run successfully, so we have winning update status. */ file->update_status = 0; notice_finished_file (file); return; } /* First set the automatic variables according to this file. */ initialize_file_variables (file); set_file_variables (file); /* Start the commands running. */ new_job (file); } /* This is set while we are inside fatal_error_signal, so things can avoid nonreentrant operations. */ int handling_fatal_signal = 0; /* Handle fatal signals. */ RETSIGTYPE fatal_error_signal (sig) int sig; { #ifdef __MSDOS__ remove_intermediates (1); exit (1); #else /* Not MSDOS. */ handling_fatal_signal = 1; /* Set the handling for this signal to the default. It is blocked now while we run this handler. */ signal (sig, SIG_DFL); /* A termination signal won't be sent to the entire process group, but it means we want to kill the children. */ if (sig == SIGTERM) { register struct child *c; for (c = children; c != 0; c = c->next) if (!c->remote) (void) kill (c->pid, SIGTERM); } /* If we got a signal that means the user wanted to kill make, remove pending targets. */ if (sig == SIGTERM || sig == SIGINT || sig == SIGHUP || sig == SIGQUIT) { register struct child *c; /* Remote children won't automatically get signals sent to the process group, so we must send them. */ for (c = children; c != 0; c = c->next) if (c->remote) (void) remote_kill (c->pid, sig); for (c = children; c != 0; c = c->next) 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. */ while (job_slots_used > 0) reap_children (1, 0); } else /* Wait for our children to die. */ while (job_slots_used > 0) reap_children (1, 1); /* Delete any non-precious intermediate files that were made. */ remove_intermediates (1); if (sig == SIGQUIT) /* We don't want to send ourselves SIGQUIT, because it will cause a core dump. Just exit instead. */ exit (EXIT_FAILURE); /* 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) pfatal_with_name ("kill"); #endif /* MSDOS. */ } /* Delete FILE unless it's precious or not actually a file (phony), and it has changed on disk since we last stat'd it. */ static void delete_target (file, on_behalf_of) struct file *file; char *on_behalf_of; { struct stat st; if (file->precious || file->phony) return; #ifndef NO_ARCHIVES if (ar_name (file->name)) { if (ar_member_date (file->name) != file->last_mtime) { if (on_behalf_of) error ("*** [%s] Archive member `%s' may be bogus; not deleted", on_behalf_of, file->name); else error ("*** Archive member `%s' may be bogus; not deleted", file->name); } return; } #endif if (stat (file->name, &st) == 0 && S_ISREG (st.st_mode) && (time_t) st.st_mtime != file->last_mtime) { if (on_behalf_of) error ("*** [%s] Deleting file `%s'", on_behalf_of, file->name); else error ("*** Deleting file `%s'", file->name); if (unlink (file->name) < 0 && errno != ENOENT) /* It disappeared; so what. */ perror_with_name ("unlink: ", file->name); } } /* Delete all non-precious targets of CHILD unless they were already deleted. Set the flag in CHILD to say they've been deleted. */ void delete_child_targets (child) struct child *child; { struct dep *d; if (child->deleted) return; /* Delete the target file if it changed. */ delete_target (child->file, (char *) 0); /* Also remove any non-precious targets listed in the `also_make' member. */ for (d = child->file->also_make; d != 0; d = d->next) delete_target (d->file, child->file->name); child->deleted = 1; } /* Print out the commands in CMDS. */ void print_commands (cmds) register struct commands *cmds; { register char *s; fputs ("# commands to execute", stdout); if (cmds->filename == 0) puts (" (built-in):"); else printf (" (from `%s', line %u):\n", cmds->filename, cmds->lineno); s = cmds->commands; while (*s != '\0') { char *end; while (isspace (*s)) ++s; end = index (s, '\n'); if (end == 0) end = s + strlen (s); printf ("\t%.*s\n", (int) (end - s), s); s = end; } }