commands.c revision a86d4c1bde70365cbbe874ad9ddb3f06916d2085
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