Simplify the print routines by using LST_FOREACH instead of Lst_ForEach
[dragonfly.git] / usr.bin / make / util.c
1 /*-
2  * Copyright (c) 2002 Juli Mallett.  All rights reserved.
3  * Copyright (c) 1988, 1989, 1990, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  * Copyright (c) 1989 by Berkeley Softworks
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Adam de Boor.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  * $FreeBSD: src/usr.bin/make/util.c,v 1.16 2005/02/04 13:23:39 harti Exp $
40  * $DragonFly: src/usr.bin/make/util.c,v 1.19 2005/03/12 11:31:30 okumoto Exp $
41  */
42
43 /*-
44  * util.c --
45  *      General utilitarian routines for make(1).
46  */
47
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <err.h>
51 #include <errno.h>
52 #include <stdarg.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56
57 #include "globals.h"
58 #include "job.h"
59 #include "targ.h"
60 #include "util.h"
61
62 static void enomem(void) __dead2;
63
64 /*-
65  * Debug --
66  *      Print a debugging message given its format.
67  *
68  * Results:
69  *      None.
70  *
71  * Side Effects:
72  *      The message is printed.
73  */
74 /* VARARGS */
75 void
76 Debug(const char *fmt, ...)
77 {
78         va_list ap;
79
80         va_start(ap, fmt);
81         vfprintf(stderr, fmt, ap);
82         va_end(ap);
83         fflush(stderr);
84 }
85
86 /*-
87  * Print a debugging message given its format and append the current
88  * errno description. Terminate with a newline.
89  */
90 /* VARARGS */
91 void
92 DebugM(const char *fmt, ...)
93 {
94         va_list ap;
95         int e = errno;
96
97         va_start(ap, fmt);
98         vfprintf(stderr, fmt, ap);
99         fprintf(stderr, ": %s\n", strerror(e));
100         va_end(ap);
101         fflush(stderr);
102 }
103
104 /*-
105  * Error --
106  *      Print an error message given its format.
107  *
108  * Results:
109  *      None.
110  *
111  * Side Effects:
112  *      The message is printed.
113  */
114 /* VARARGS */
115 void
116 Error(const char *fmt, ...)
117 {
118         va_list ap;
119
120         va_start(ap, fmt);
121         vfprintf(stderr, fmt, ap);
122         va_end(ap);
123         fprintf(stderr, "\n");
124         fflush(stderr);
125 }
126
127 /*-
128  * Fatal --
129  *      Produce a Fatal error message. If jobs are running, waits for them
130  *      to finish.
131  *
132  * Results:
133  *      None
134  *
135  * Side Effects:
136  *      The program exits
137  */
138 /* VARARGS */
139 void
140 Fatal(const char *fmt, ...)
141 {
142         va_list ap;
143
144         va_start(ap, fmt);
145         if (jobsRunning)
146                 Job_Wait();
147
148         vfprintf(stderr, fmt, ap);
149         va_end(ap);
150         fprintf(stderr, "\n");
151         fflush(stderr);
152
153         if (DEBUG(GRAPH2))
154                 Targ_PrintGraph(2);
155         exit(2);                /* Not 1 so -q can distinguish error */
156 }
157
158 /*
159  * Punt --
160  *      Major exception once jobs are being created. Kills all jobs, prints
161  *      a message and exits.
162  *
163  * Results:
164  *      None
165  *
166  * Side Effects:
167  *      All children are killed indiscriminately and the program Lib_Exits
168  */
169 /* VARARGS */
170 void
171 Punt(const char *fmt, ...)
172 {
173         va_list ap;
174
175         va_start(ap, fmt);
176         fprintf(stderr, "make: ");
177         vfprintf(stderr, fmt, ap);
178         va_end(ap);
179         fprintf(stderr, "\n");
180         fflush(stderr);
181
182         DieHorribly();
183 }
184
185 /*-
186  * DieHorribly --
187  *      Exit without giving a message.
188  *
189  * Results:
190  *      None
191  *
192  * Side Effects:
193  *      A big one...
194  */
195 void
196 DieHorribly(void)
197 {
198         if (jobsRunning)
199                 Job_AbortAll();
200         if (DEBUG(GRAPH2))
201                 Targ_PrintGraph(2);
202         exit(2);                /* Not 1, so -q can distinguish error */
203 }
204
205 /*
206  * Finish --
207  *      Called when aborting due to errors in child shell to signal
208  *      abnormal exit, with the number of errors encountered in Make_Make.
209  *
210  * Results:
211  *      None
212  *
213  * Side Effects:
214  *      The program exits
215  */
216 void
217 Finish(int errors)
218 {
219
220         Fatal("%d error%s", errors, errors == 1 ? "" : "s");
221 }
222
223 /*
224  * emalloc --
225  *      malloc, but die on error.
226  */
227 void *
228 emalloc(size_t len)
229 {
230         void *p;
231
232         if ((p = malloc(len)) == NULL)
233                 enomem();
234         return (p);
235 }
236
237 /*
238  * estrdup --
239  *      strdup, but die on error.
240  */
241 char *
242 estrdup(const char *str)
243 {
244         char *p;
245
246         if ((p = strdup(str)) == NULL)
247                 enomem();
248         return (p);
249 }
250
251 /*
252  * erealloc --
253  *      realloc, but die on error.
254  */
255 void *
256 erealloc(void *ptr, size_t size)
257 {
258
259         if ((ptr = realloc(ptr, size)) == NULL)
260                 enomem();
261         return (ptr);
262 }
263
264 /*
265  * enomem --
266  *      die when out of memory.
267  */
268 static void
269 enomem(void)
270 {
271         err(2, NULL);
272 }
273
274 /*
275  * enunlink --
276  *      Remove a file carefully, avoiding directories.
277  */
278 int
279 eunlink(const char *file)
280 {
281         struct stat st;
282
283         if (lstat(file, &st) == -1)
284                 return (-1);
285
286         if (S_ISDIR(st.st_mode)) {
287                 errno = EISDIR;
288                 return (-1);
289         }
290         return (unlink(file));
291 }
292
293 /*
294  * Convert a flag word to a printable thing and print it
295  */
296 void
297 print_flags(FILE *fp, const struct flag2str *tab, u_int flags)
298 {
299         int first = 1;
300
301         fprintf(fp, "(");
302         while (tab->str != NULL) {
303                 if (flags & tab->flag) {
304                         if (!first)
305                                 fprintf(fp, "|");
306                         first = 0;
307                         fprintf(fp, "%s", tab->str);
308                 }
309                 tab++;
310         }
311         fprintf(fp, ")");
312 }