1a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Command processing for GNU Make. 2a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerCopyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 3a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software 4a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerFoundation, Inc. 5a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerThis file is part of GNU Make. 6a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 7a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerGNU Make is free software; you can redistribute it and/or modify it under the 8a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerterms of the GNU General Public License as published by the Free Software 9a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerFoundation; either version 2, or (at your option) any later version. 10a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 11a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY 12a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerA PARTICULAR PURPOSE. See the GNU General Public License for more details. 14a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 15a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerYou should have received a copy of the GNU General Public License along with 16a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerGNU Make; see the file COPYING. If not, write to the Free Software 17a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ 18a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 19a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "make.h" 20a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "dep.h" 21a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "filedef.h" 22a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "variable.h" 23a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "job.h" 24a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "commands.h" 25a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef WINDOWS32 26a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <windows.h> 27a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include "w32err.h" 28a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 29a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 30a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#if VMS 31a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner# define FILE_LIST_SEPARATOR ',' 32a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else 33a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner# define FILE_LIST_SEPARATOR ' ' 34a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 35a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 36a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerextern int remote_kill PARAMS ((int id, int sig)); 37a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 38a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef HAVE_UNISTD_H 39a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerextern int getpid (); 40a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 41a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 42a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Set FILE's automatic variables up. */ 43a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 44a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervoid 45a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerset_file_variables (struct file *file) 46a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 47a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner struct dep *d; 48a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *at, *percent, *star, *less; 49a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 50a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef NO_ARCHIVES 51a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* If the target is an archive member `lib(member)', 52a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner then $@ is `lib' and $% is `member'. */ 53a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 54a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (ar_name (file->name)) 55a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 56a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner unsigned int len; 57a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *p; 58a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 59a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner p = strchr (file->name, '('); 60a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner at = (char *) alloca (p - file->name + 1); 61a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bcopy (file->name, at, p - file->name); 62a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner at[p - file->name] = '\0'; 63a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (p + 1); 64a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner percent = (char *) alloca (len); 65a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bcopy (p + 1, percent, len - 1); 66a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner percent[len - 1] = '\0'; 67a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 68a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 69a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif /* NO_ARCHIVES. */ 70a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 71a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner at = file->name; 72a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner percent = ""; 73a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 74a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 75a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* $* is the stem from an implicit or static pattern rule. */ 76a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (file->stem == 0) 77a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 78a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* In Unix make, $* is set to the target name with 79a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner any suffix in the .SUFFIXES list stripped off for 80a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner explicit rules. We store this in the `stem' member. */ 81a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register struct dep *d; 82a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *name; 83a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner unsigned int len; 84a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 85a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef NO_ARCHIVES 86a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (ar_name (file->name)) 87a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 88a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner name = strchr (file->name, '(') + 1; 89a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (name) - 1; 90a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 91a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 92a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 93a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 94a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner name = file->name; 95a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (name); 96a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 97a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 98a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = enter_file (".SUFFIXES")->deps; d != 0; d = d->next) 99a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 100a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner unsigned int slen = strlen (dep_name (d)); 101a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (len > slen && strneq (dep_name (d), name + (len - slen), slen)) 102a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 103a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner file->stem = savestring (name, len - slen); 104a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner break; 105a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 106a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 107a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (d == 0) 108a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner file->stem = ""; 109a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 110a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner star = file->stem; 111a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 112a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* $< is the first not order-only dependency. */ 113a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner less = ""; 114a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = file->deps; d != 0; d = d->next) 115a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (!d->ignore_mtime) 116a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 117a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner less = dep_name (d); 118a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner break; 119a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 120a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 121a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (file->cmds == default_file->cmds) 122a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* This file got its commands from .DEFAULT. 123a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner In this case $< is the same as $@. */ 124a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner less = at; 125a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 126a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#define DEFINE_VARIABLE(name, len, value) \ 127a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner (void) define_variable_for_file (name,len,value,o_automatic,0,file) 128a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 129a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Define the variables. */ 130a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 131a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("<", 1, less); 132a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("*", 1, star); 133a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("@", 1, at); 134a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("%", 1, percent); 135a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 136a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Compute the values for $^, $+, $?, and $|. */ 137a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 138a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 139a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner static char *plus_value=0, *bar_value=0, *qmark_value=0; 140a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner static unsigned int qmark_max=0, plus_max=0, bar_max=0; 141a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 142a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner unsigned int qmark_len, plus_len, bar_len; 143a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *cp; 144a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *caret_value; 145a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *qp; 146a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *bp; 147a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner unsigned int len; 148a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 149a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Compute first the value for $+, which is supposed to contain 150a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner duplicate dependencies as they were listed in the makefile. */ 151a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 152a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner plus_len = 0; 153a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = file->deps; d != 0; d = d->next) 154a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (! d->ignore_mtime) 155a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner plus_len += strlen (dep_name (d)) + 1; 156a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (plus_len == 0) 157a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner plus_len++; 158a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 159a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (plus_len > plus_max) 160a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner plus_value = xrealloc (plus_value, plus_max = plus_len); 161a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cp = plus_value; 162a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 163a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner qmark_len = plus_len + 1; /* Will be this or less. */ 164a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = file->deps; d != 0; d = d->next) 165a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (! d->ignore_mtime) 166a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 167a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *c = dep_name (d); 168a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 169a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef NO_ARCHIVES 170a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (ar_name (c)) 171a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 172a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner c = strchr (c, '(') + 1; 173a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (c) - 1; 174a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 175a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 176a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 177a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (c); 178a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 179a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bcopy (c, cp, len); 180a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cp += len; 181a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *cp++ = FILE_LIST_SEPARATOR; 182a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (! d->changed) 183a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner qmark_len -= len + 1; /* Don't space in $? for this one. */ 184a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 185a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 186a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Kill the last space and define the variable. */ 187a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 188a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cp[cp > plus_value ? -1 : 0] = '\0'; 189a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("+", 1, plus_value); 190a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 191a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Make sure that no dependencies are repeated. This does not 192a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner really matter for the purpose of updating targets, but it 193a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner might make some names be listed twice for $^ and $?. */ 194a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 195a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner uniquize_deps (file->deps); 196a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 197a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bar_len = 0; 198a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = file->deps; d != 0; d = d->next) 199a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (d->ignore_mtime) 200a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bar_len += strlen (dep_name (d)) + 1; 201a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (bar_len == 0) 202a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bar_len++; 203a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 204a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Compute the values for $^, $?, and $|. */ 205a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 206a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cp = caret_value = plus_value; /* Reuse the buffer; it's big enough. */ 207a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 208a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (qmark_len > qmark_max) 209a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner qmark_value = xrealloc (qmark_value, qmark_max = qmark_len); 210a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner qp = qmark_value; 211a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 212a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (bar_len > bar_max) 213a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bar_value = xrealloc (bar_value, bar_max = bar_len); 214a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bp = bar_value; 215a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 216a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = file->deps; d != 0; d = d->next) 217a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 218a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *c = dep_name (d); 219a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 220a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef NO_ARCHIVES 221a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (ar_name (c)) 222a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 223a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner c = strchr (c, '(') + 1; 224a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (c) - 1; 225a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 226a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 227a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 228a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner len = strlen (c); 229a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 230a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (d->ignore_mtime) 231a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 232a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bcopy (c, bp, len); 233a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bp += len; 234a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *bp++ = FILE_LIST_SEPARATOR; 235a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 236a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 237a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 238a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bcopy (c, cp, len); 239a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cp += len; 240a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *cp++ = FILE_LIST_SEPARATOR; 241a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (d->changed) 242a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 243a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bcopy (c, qp, len); 244a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner qp += len; 245a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *qp++ = FILE_LIST_SEPARATOR; 246a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 247a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 248a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 249a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 250a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Kill the last spaces and define the variables. */ 251a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 252a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cp[cp > caret_value ? -1 : 0] = '\0'; 253a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("^", 1, caret_value); 254a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 255a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner qp[qp > qmark_value ? -1 : 0] = '\0'; 256a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("?", 1, qmark_value); 257a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 258a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner bp[bp > bar_value ? -1 : 0] = '\0'; 259a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DEFINE_VARIABLE ("|", 1, bar_value); 260a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 261a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 262a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#undef DEFINE_VARIABLE 263a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 264a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 265a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Chop CMDS up into individual command lines if necessary. 266a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner Also set the `lines_flags' and `any_recurse' members. */ 267a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 268a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervoid 269a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerchop_commands (struct commands *cmds) 270a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 271a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register char *p; 272a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner unsigned int nlines, idx; 273a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char **lines; 274a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 275a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* If we don't have any commands, 276a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner or we already parsed them, never mind. */ 277a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 278a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (!cmds || cmds->command_lines != 0) 279a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return; 280a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 281a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Chop CMDS->commands up into lines in CMDS->command_lines. 282a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner Also set the corresponding CMDS->lines_flags elements, 283a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner and the CMDS->any_recurse flag. */ 284a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 285a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner nlines = 5; 286a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner lines = (char **) xmalloc (5 * sizeof (char *)); 287a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner idx = 0; 288a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner p = cmds->commands; 289a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner while (*p != '\0') 290a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 291a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *end = p; 292a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner find_end:; 293a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner end = strchr (end, '\n'); 294a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (end == 0) 295a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner end = p + strlen (p); 296a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else if (end > p && end[-1] == '\\') 297a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 298a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner int backslash = 1; 299a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register char *b; 300a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (b = end - 2; b >= p && *b == '\\'; --b) 301a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner backslash = !backslash; 302a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (backslash) 303a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 304a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ++end; 305a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner goto find_end; 306a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 307a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 308a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 309a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (idx == nlines) 310a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 311a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner nlines += 2; 312a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner lines = (char **) xrealloc ((char *) lines, 313a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner nlines * sizeof (char *)); 314a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 315a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner lines[idx++] = savestring (p, end - p); 316a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner p = end; 317a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (*p != '\0') 318a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ++p; 319a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 320a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 321a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (idx != nlines) 322a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 323a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner nlines = idx; 324a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner lines = (char **) xrealloc ((char *) lines, 325a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner nlines * sizeof (char *)); 326a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 327a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 328a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->ncommand_lines = nlines; 329a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->command_lines = lines; 330a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 331a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->any_recurse = 0; 332a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->lines_flags = (char *) xmalloc (nlines); 333a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (idx = 0; idx < nlines; ++idx) 334a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 335a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner int flags = 0; 336a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 337a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (p = lines[idx]; 338a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+'; 339a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ++p) 340a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner switch (*p) 341a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 342a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner case '+': 343a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner flags |= COMMANDS_RECURSE; 344a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner break; 345a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner case '@': 346a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner flags |= COMMANDS_SILENT; 347a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner break; 348a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner case '-': 349a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner flags |= COMMANDS_NOERROR; 350a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner break; 351a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 352a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 353a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* If no explicit '+' was given, look for MAKE variable references. */ 354a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (!(flags & COMMANDS_RECURSE) 355a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0)) 356a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner flags |= COMMANDS_RECURSE; 357a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 358a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->lines_flags[idx] = flags; 359a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->any_recurse |= flags & COMMANDS_RECURSE; 360a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 361a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 362a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 363a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Execute the commands to remake FILE. If they are currently executing, 364a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return or have already finished executing, just return. Otherwise, 365a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner fork off a child process to run the first command line in the sequence. */ 366a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 367a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervoid 368a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerexecute_file_commands (struct file *file) 369a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 370a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register char *p; 371a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 372a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Don't go through all the preparations if 373a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner the commands are nothing but whitespace. */ 374a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 375a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (p = file->cmds->commands; *p != '\0'; ++p) 376a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (!isspace ((unsigned char)*p) && *p != '-' && *p != '@') 377a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner break; 378a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (*p == '\0') 379a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 380a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* If there are no commands, assume everything worked. */ 381a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner set_command_state (file, cs_running); 382a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner file->update_status = 0; 383a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner notice_finished_file (file); 384a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return; 385a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 386a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 387a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* First set the automatic variables according to this file. */ 388a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 389a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner initialize_file_variables (file, 0); 390a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 391a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner set_file_variables (file); 392a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 393a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Start the commands running. */ 394a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner new_job (file); 395a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 396a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 397a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* This is set while we are inside fatal_error_signal, 398a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner so things can avoid nonreentrant operations. */ 399a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 400a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerint handling_fatal_signal = 0; 401a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 402a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Handle fatal signals. */ 403a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 404a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerRETSIGTYPE 405a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerfatal_error_signal (int sig) 406a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 407a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef __MSDOS__ 408a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner extern int dos_status, dos_command_running; 409a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 410a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (dos_command_running) 411a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 412a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* That was the child who got the signal, not us. */ 413a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner dos_status |= (sig << 8); 414a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return; 415a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 416a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner remove_intermediates (1); 417a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner exit (EXIT_FAILURE); 418a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else /* not __MSDOS__ */ 419a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef _AMIGA 420a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner remove_intermediates (1); 421a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (sig == SIGINT) 422a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner fputs (_("*** Break.\n"), stderr); 423a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 424a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner exit (10); 425a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else /* not Amiga */ 426a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef WINDOWS32 427a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner extern HANDLE main_thread; 428a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 429a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Windows creates a sperate thread for handling Ctrl+C, so we need 430a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner to suspend the main thread, or else we will have race conditions 431a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner when both threads call reap_children. */ 432a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (main_thread) 433a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 434a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DWORD susp_count = SuspendThread (main_thread); 435a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 436a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (susp_count != 0) 437a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count); 438a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else if (susp_count == (DWORD)-1) 439a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 440a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner DWORD ierr = GetLastError (); 441a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 442a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner fprintf (stderr, "SuspendThread: error %ld: %s\n", 443a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ierr, map_windows32_error_to_string (ierr)); 444a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 445a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 446a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 447a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner handling_fatal_signal = 1; 448a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 449a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Set the handling for this signal to the default. 450a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner It is blocked now while we run this handler. */ 451a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner signal (sig, SIG_DFL); 452a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 453a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* A termination signal won't be sent to the entire 454a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner process group, but it means we want to kill the children. */ 455a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 456a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (sig == SIGTERM) 457a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 458a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register struct child *c; 459a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (c = children; c != 0; c = c->next) 460a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (!c->remote) 461a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner (void) kill (c->pid, SIGTERM); 462a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 463a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 464a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* If we got a signal that means the user 465a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner wanted to kill make, remove pending targets. */ 466a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 467a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (sig == SIGTERM || sig == SIGINT 468a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef SIGHUP 469a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner || sig == SIGHUP 470a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 471a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef SIGQUIT 472a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner || sig == SIGQUIT 473a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 474a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ) 475a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 476a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register struct child *c; 477a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 478a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Remote children won't automatically get signals sent 479a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner to the process group, so we must send them. */ 480a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (c = children; c != 0; c = c->next) 481a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (c->remote) 482a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner (void) remote_kill (c->pid, sig); 483a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 484a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (c = children; c != 0; c = c->next) 485a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner delete_child_targets (c); 486a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 487a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Clean up the children. We don't just use the call below because 488a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner we don't want to print the "Waiting for children" message. */ 489a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner while (job_slots_used > 0) 490a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner reap_children (1, 0); 491a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 492a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 493a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Wait for our children to die. */ 494a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner while (job_slots_used > 0) 495a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner reap_children (1, 1); 496a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 497a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Delete any non-precious intermediate files that were made. */ 498a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 499a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner remove_intermediates (1); 500a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 501a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef SIGQUIT 502a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (sig == SIGQUIT) 503a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* We don't want to send ourselves SIGQUIT, because it will 504a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cause a core dump. Just exit instead. */ 505a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner exit (EXIT_FAILURE); 506a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 507a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 508a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef WINDOWS32 509a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (main_thread) 510a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner CloseHandle (main_thread); 511a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Cannot call W32_kill with a pid (it needs a handle). The exit 512a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner status of 130 emulates what happens in Bash. */ 513a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner exit (130); 514a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else 515a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Signal the same code; this time it will really be fatal. The signal 516a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner will be unblocked when we return and arrive then to kill us. */ 517a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (kill (getpid (), sig) < 0) 518a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner pfatal_with_name ("kill"); 519a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif /* not WINDOWS32 */ 520a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif /* not Amiga */ 521a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif /* not __MSDOS__ */ 522a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 523a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 524a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Delete FILE unless it's precious or not actually a file (phony), 525a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner and it has changed on disk since we last stat'd it. */ 526a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 527a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic void 528a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerdelete_target (struct file *file, char *on_behalf_of) 529a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 530a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner struct stat st; 531a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner int e; 532a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 533a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (file->precious || file->phony) 534a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return; 535a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 536a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef NO_ARCHIVES 537a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (ar_name (file->name)) 538a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 539a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner time_t file_date = (file->last_mtime == NONEXISTENT_MTIME 540a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ? (time_t) -1 541a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner : (time_t) FILE_TIMESTAMP_S (file->last_mtime)); 542a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (ar_member_date (file->name) != file_date) 543a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 544a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (on_behalf_of) 545a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner error (NILF, _("*** [%s] Archive member `%s' may be bogus; not deleted"), 546a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner on_behalf_of, file->name); 547a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 548a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner error (NILF, _("*** Archive member `%s' may be bogus; not deleted"), 549a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner file->name); 550a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 551a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return; 552a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 553a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif 554a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 555a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner EINTRLOOP (e, stat (file->name, &st)); 556a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (e == 0 557a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner && S_ISREG (st.st_mode) 558a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime) 559a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 560a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (on_behalf_of) 561a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner error (NILF, _("*** [%s] Deleting file `%s'"), on_behalf_of, file->name); 562a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 563a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner error (NILF, _("*** Deleting file `%s'"), file->name); 564a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (unlink (file->name) < 0 565a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner && errno != ENOENT) /* It disappeared; so what. */ 566a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner perror_with_name ("unlink: ", file->name); 567a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 568a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 569a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 570a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 571a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Delete all non-precious targets of CHILD unless they were already deleted. 572a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner Set the flag in CHILD to say they've been deleted. */ 573a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 574a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervoid 575a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerdelete_child_targets (struct child *child) 576a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 577a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner struct dep *d; 578a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 579a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (child->deleted) 580a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner return; 581a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 582a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Delete the target file if it changed. */ 583a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner delete_target (child->file, (char *) 0); 584a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 585a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner /* Also remove any non-precious targets listed in the `also_make' member. */ 586a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner for (d = child->file->also_make; d != 0; d = d->next) 587a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner delete_target (d->file, child->file->name); 588a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 589a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner child->deleted = 1; 590a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 591a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 592a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Print out the commands in CMDS. */ 593a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 594a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervoid 595a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerprint_commands (struct commands *cmds) 596a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{ 597a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner register char *s; 598a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 599a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner fputs (_("# commands to execute"), stdout); 600a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 601a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (cmds->fileinfo.filenm == 0) 602a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner puts (_(" (built-in):")); 603a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner else 604a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner printf (_(" (from `%s', line %lu):\n"), 605a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner cmds->fileinfo.filenm, cmds->fileinfo.lineno); 606a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 607a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner s = cmds->commands; 608a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner while (*s != '\0') 609a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner { 610a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner char *end; 611a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 612a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner while (isspace ((unsigned char)*s)) 613a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner ++s; 614a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 615a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner end = strchr (s, '\n'); 616a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner if (end == 0) 617a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner end = s + strlen (s); 618a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 619a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner printf ("\t%.*s\n", (int) (end - s), s); 620a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner 621a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner s = end; 622a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner } 623a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner} 624