Bug Summary

File:src/usr.bin/make/parse.c
Warning:line 1304, column 4
Value stored to 'paren_to_match' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name parse.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/make/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/make/obj -I /usr/src/usr.bin/make -D HAS_PATHS_H -D HAS_EXTENDED_GETCWD -I /usr/src/usr.bin/make/lst.lib -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/make/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/make/parse.c
1/* $OpenBSD: parse.c,v 1.134 2021/03/06 08:31:42 espie Exp $ */
2/* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
3
4/*
5 * Copyright (c) 1999 Marc Espie.
6 *
7 * Extensive code changes for the OpenBSD project.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/*
31 * Copyright (c) 1988, 1989, 1990, 1993
32 * The Regents of the University of California. All rights reserved.
33 * Copyright (c) 1989 by Berkeley Softworks
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to Berkeley by
37 * Adam de Boor.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 */
63
64#include <assert.h>
65#include <ctype.h>
66#include <stddef.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <ohash.h>
71#include "config.h"
72#include "defines.h"
73#include "dir.h"
74#include "direxpand.h"
75#include "job.h"
76#include "buf.h"
77#include "for.h"
78#include "lowparse.h"
79#include "arch.h"
80#include "cond.h"
81#include "suff.h"
82#include "parse.h"
83#include "var.h"
84#include "targ.h"
85#include "error.h"
86#include "str.h"
87#include "main.h"
88#include "gnode.h"
89#include "memory.h"
90#include "extern.h"
91#include "lst.h"
92#include "parsevar.h"
93#include "stats.h"
94#include "garray.h"
95#include "node_int.h"
96#include "nodehashconsts.h"
97
98
99/* gsources and gtargets should be local to some functions, but they're
100 * set as persistent arrays for performance reasons.
101 */
102static struct growableArray gsources, gtargets;
103static struct ohash htargets;
104static bool_Bool htargets_setup = false0;
105#define SOURCES_SIZE128 128
106#define TARGETS_SIZE32 32
107
108static LIST theUserIncPath;/* list of directories for "..." includes */
109static LIST theSysIncPath; /* list of directories for <...> includes */
110Lst systemIncludePath = &theSysIncPath;
111Lst userIncludePath = &theUserIncPath;
112
113static GNode *mainNode; /* The main target to create. This is the
114 * first target on the first dependency
115 * line in the first makefile */
116/*-
117 * specType contains the special TYPE of the current target. It is
118 * SPECIAL_NONE if the target is unspecial. If it *is* special, however,
119 * the children are linked as children of the parent but not vice versa.
120 * This variable is set in ParseDoDependency
121 */
122
123static unsigned int specType;
124static int waiting;
125
126/*
127 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
128 * seen, then set to each successive source on the line.
129 */
130static GNode *predecessor;
131
132static void ParseLinkSrc(GNode *, GNode *);
133static int ParseDoOp(GNode **, unsigned int);
134static void ParseDoSpecial(GNode *, unsigned int);
135static int ParseAddDep(GNode *, GNode *);
136static void ParseDoSrc(struct growableArray *, struct growableArray *, int,
137 const char *, const char *);
138static int ParseFindMain(void *, void *);
139static void ParseClearPath(void *);
140
141static void add_target_node(const char *, const char *);
142static void add_target_nodes(const char *, const char *);
143static void apply_op(struct growableArray *, unsigned int, GNode *);
144static void ParseDoDependency(const char *);
145static void ParseAddCmd(void *, void *);
146static void ParseHasCommands(void *);
147static bool_Bool handle_poison(const char *);
148static bool_Bool handle_for_loop(Buffer, const char *);
149static bool_Bool handle_undef(const char *);
150#define ParseReadLoopLine(linebuf)Parse_ReadUnparsedLine(linebuf, "for loop") Parse_ReadUnparsedLine(linebuf, "for loop")
151static bool_Bool handle_bsd_command(Buffer, Buffer, const char *);
152static bool_Bool register_target(GNode *, struct ohash *);
153static char *strip_comments(Buffer, const char *);
154static char *resolve_include_filename(const char *, const char *, bool_Bool);
155static void handle_include_file(const char *, const char *, bool_Bool, bool_Bool);
156static bool_Bool lookup_bsd_include(const char *);
157static void lookup_sysv_style_include(const char *, const char *, bool_Bool);
158static void lookup_sysv_include(const char *, const char *);
159static void lookup_conditional_include(const char *, const char *);
160static bool_Bool parse_as_special_line(Buffer, Buffer, const char *);
161static unsigned int parse_operator(const char **);
162
163static const char *parse_do_targets(Lst, unsigned int *, const char *);
164static void parse_target_line(struct growableArray *, const char *,
165 const char *, bool_Bool *);
166
167static void finish_commands(struct growableArray *);
168static void parse_commands(struct growableArray *, const char *);
169static void create_special_nodes(void);
170static bool_Bool found_delimiter(const char *);
171static unsigned int handle_special_targets(Lst);
172static void dump_targets(void);
173static void dedup_targets(struct growableArray *);
174static void build_target_group(struct growableArray *, struct ohash *t);
175static void reset_target_hash(void);
176
177
178#define P(k) k, sizeof(k), K_##k
179
180static struct {
181 const char *keyword;
182 size_t sz;
183 uint32_t hv;
184 unsigned int special;
185 unsigned int special_op;
186} specials[] = {
187 { P(NODE_EXEC".EXEC"), SPECIAL_DEPRECATED7U, 0 },
188 { P(NODE_IGNORE".IGNORE"), SPECIAL_IGNORE5U, OP_IGNORE0x00000040 },
189 { P(NODE_INCLUDES".INCLUDES"), SPECIAL_DEPRECATED7U, 0 },
190 { P(NODE_INVISIBLE".INVISIBLE"), SPECIAL_DEPRECATED7U, 0 },
191 { P(NODE_JOIN".JOIN"), SPECIAL_DEPRECATED7U, 0 },
192 { P(NODE_LIBS".LIBS"), SPECIAL_DEPRECATED7U, 0 },
193 { P(NODE_MADE".MADE"), SPECIAL_DEPRECATED7U, 0 },
194 { P(NODE_MAIN".MAIN"), SPECIAL_MAIN12U, 0 },
195 { P(NODE_MAKE".MAKE"), SPECIAL_MAKE13U, OP_MAKE0x00000200 },
196 { P(NODE_MAKEFLAGS".MAKEFLAGS"), SPECIAL_MFLAGS14U, 0 },
197 { P(NODE_MFLAGS".MFLAGS"), SPECIAL_MFLAGS14U, 0 },
198 { P(NODE_NOTMAIN".NOTMAIN"), SPECIAL_NOTMAIN15U, OP_NOTMAIN0x00002000 },
199 { P(NODE_NOTPARALLEL".NOTPARALLEL"), SPECIAL_NOTPARALLEL16U, 0 },
200 { P(NODE_NO_PARALLEL".NOPARALLEL"), SPECIAL_NOTPARALLEL16U, 0 },
201 { P(NODE_NULL".NULL"), SPECIAL_DEPRECATED7U, 0 },
202 { P(NODE_OPTIONAL".OPTIONAL"), SPECIAL_OPTIONAL18U, OP_OPTIONAL0x00000008 },
203 { P(NODE_ORDER".ORDER"), SPECIAL_ORDER19U, 0 },
204 { P(NODE_PARALLEL".PARALLEL"), SPECIAL_PARALLEL20U, 0 },
205 { P(NODE_PATH".PATH"), SPECIAL_PATH62U, 0 },
206 { P(NODE_PHONY".PHONY"), SPECIAL_PHONY22U, OP_PHONY0x00004000 },
207 { P(NODE_PRECIOUS".PRECIOUS"), SPECIAL_PRECIOUS23U, OP_PRECIOUS0x00000080 },
208 { P(NODE_RECURSIVE".RECURSIVE"), SPECIAL_MAKE13U, OP_MAKE0x00000200 },
209 { P(NODE_SILENT".SILENT"), SPECIAL_SILENT25U, OP_SILENT0x00000100 },
210 { P(NODE_SINGLESHELL".SINGLESHELL"), SPECIAL_NOTHING6U, 0 },
211 { P(NODE_SUFFIXES".SUFFIXES"), SPECIAL_SUFFIXES27U, 0 },
212 { P(NODE_USE".USE"), SPECIAL_USE28U, OP_USE0x00000010 },
213 { P(NODE_WAIT".WAIT"), SPECIAL_WAIT29U, 0 },
214 { P(NODE_CHEAP".CHEAP"), SPECIAL_CHEAP32U, OP_CHEAP0x02000000 },
215 { P(NODE_EXPENSIVE".EXPENSIVE"), SPECIAL_EXPENSIVE33U, OP_EXPENSIVE0x04000000 },
216 { P(NODE_POSIX".POSIX"), SPECIAL_NOTHING6U, 0 },
217 { P(NODE_SCCS_GET".SCCS_GET"), SPECIAL_NOTHING6U, 0 },
218};
219
220#undef P
221
222static void
223create_special_nodes()
224{
225 unsigned int i;
226
227 for (i = 0; i < sizeof(specials)/sizeof(specials[0]); i++) {
228 (void)Targ_mk_special_node(specials[i].keyword,
229 specials[i].sz, specials[i].hv,
230 OP_ZERO0x00000000, specials[i].special, specials[i].special_op);
231 }
232}
233
234/*-
235 *---------------------------------------------------------------------
236 * ParseLinkSrc --
237 * Link the parent node to its new child. Used by
238 * ParseDoDependency. If the specType isn't 'Not', the parent
239 * isn't linked as a parent of the child.
240 *
241 * Side Effects:
242 * New elements are added to the parents list of cgn and the
243 * children list of cgn. the children_left field of pgn is updated
244 * to reflect the additional child.
245 *---------------------------------------------------------------------
246 */
247static void
248ParseLinkSrc(GNode *pgn, GNode *cgn)
249{
250 if (Lst_AddNew(&pgn->children, cgn)) {
251 if (specType == SPECIAL_NONE0U)
252 Lst_AtEnd(&cgn->parents, pgn);
253 pgn->children_left++;
254 }
255}
256
257static char *
258operator_string(int op)
259{
260 /* XXX we don't bother freeing this, it's used for a fatal error
261 * anyways
262 */
263 char *result = emalloc(5);
264 char *t = result;
265 if (op & OP_DEPENDS0x00000001) {
266 *t++ = ':';
267 }
268 if (op & OP_FORCE0x00000002) {
269 *t++ = '!';
270 }
271 if (op & OP_DOUBLEDEP0x00000004) {
272 *t++ = ':';
273 *t++ = ':';
274 }
275 *t = 0;
276 return result;
277}
278
279/*-
280 *---------------------------------------------------------------------
281 * ParseDoOp --
282 * Apply the parsed operator to the given target node. Used in a
283 * Array_Find call by ParseDoDependency once all targets have
284 * been found and their operator parsed. If the previous and new
285 * operators are incompatible, a major error is taken, and the find
286 * stops early
287 *
288 * Side Effects:
289 * The node gets the right dependency operator.
290 * Cohorts may be created for double dep.
291 *---------------------------------------------------------------------
292 */
293static int
294ParseDoOp(GNode **gnp, unsigned int op)
295{
296 GNode *gn = *gnp;
297
298 assert(op == (op & OP_OPMASK))((op == (op & (0x00000001|0x00000002|0x00000004))) ? (void
)0 : __assert2("/usr/src/usr.bin/make/parse.c", 298, __func__
, "op == (op & OP_OPMASK)"))
;
299
300 /* if the node didn't already appear on the left hand side (no known
301 * dependency operator), we don't need to do much. */
302 if (!OP_NOP(gn->type)(((gn->type) & (0x00000001|0x00000002|0x00000004)) == 0x00000000
)
) {
303 /*
304 * If the dependency mask of the operator and the node don't
305 * match and the node has actually had an operator applied to
306 * it before, and the operator actually has some dependency
307 * information in it, complain. */
308 if (op != (gn->type & OP_OPMASK(0x00000001|0x00000002|0x00000004))) {
309 Parse_Error(PARSE_FATAL1,
310 "Inconsistent dependency operator for target %s\n"
311 "\t(was %s%s, now %s%s)",
312 gn->name, gn->name, operator_string(gn->type),
313 gn->name, operator_string(op));
314 return 0;
315 }
316
317 if (op == OP_DOUBLEDEP0x00000004) {
318 /* If the node was the object of a :: operator, we need
319 * to create a new instance of it for the children and
320 * commands on this dependency line. The new instance
321 * is placed on the 'cohorts' list of the initial one
322 * (note the initial one is not on its own cohorts
323 * list) and the new instance is linked to all parents
324 * of the initial instance. */
325 GNode *cohort;
326 LstNode ln;
327
328 cohort = Targ_NewGN(gn->name)Targ_NewGNi(gn->name, ((void*)0));;
329 /* Duplicate links to parents so graph traversal is
330 * simple. Perhaps some type bits should be
331 * duplicated?
332 *
333 * Make the cohort invisible as well to avoid
334 * duplicating it into other variables. True, parents
335 * of this target won't tend to do anything with their
336 * local variables, but better safe than sorry. */
337 for (ln = Lst_First(&gn->parents)((&gn->parents)->firstPtr); ln != NULL((void*)0);
338 ln = Lst_Adv(ln)((ln)->nextPtr))
339 ParseLinkSrc(Lst_Datum(ln)((ln)->datum), cohort);
340 cohort->type = OP_DOUBLEDEP0x00000004|OP_INVISIBLE0x00001000;
341 Lst_AtEnd(&gn->cohorts, cohort);
342
343 /* Replace the node in the targets list with the new
344 * copy */
345 *gnp = cohort;
346 gn = cohort;
347 }
348 }
349 /* Preserve possible special flags already applied to the operator */
350 gn->type |= op;
351 return 1;
352}
353
354static void
355ParseDoSpecial(GNode *gn, unsigned int special_op)
356{
357 gn->type |= special_op;
358}
359
360/*-
361 *---------------------------------------------------------------------
362 * ParseAddDep --
363 * Check if the pair of GNodes given needs to be synchronized.
364 * This has to be when two nodes are on different sides of a
365 * .WAIT directive.
366 *
367 * Results:
368 * Returns 0 if the two targets need to be ordered, 1 otherwise.
369 * If it returns 0, the search can stop.
370 *
371 * Side Effects:
372 * A dependency can be added between the two nodes.
373 *
374 *---------------------------------------------------------------------
375 */
376static int
377ParseAddDep(GNode *p, GNode *s)
378{
379 if (p->order < s->order) {
380 /* XXX: This can cause cycles but finding them is hard
381 * and debugging output will show the problem. */
382 Lst_AtEnd(&s->predecessors, p);
383 Lst_AtEnd(&p->successors, s);
384 return 1;
385 } else
386 return 0;
387}
388
389static void
390apply_op(struct growableArray *targets, unsigned int op, GNode *gn)
391{
392 if (op)
393 gn->type |= op;
394 else
395 Array_ForEach(targets, ParseLinkSrc, gn)do { unsigned int i; for (i = 0; i < (targets)->n; i++)
(ParseLinkSrc)((targets)->a[i], (gn)); } while (0)
;
396}
397
398/*-
399 *---------------------------------------------------------------------
400 * ParseDoSrc --
401 * Given the name of a source, figure out if it is an attribute
402 * and apply it to the targets if it is. Else decide if there is
403 * some attribute which should be applied *to* the source because
404 * of some special target and apply it if so. Otherwise, make the
405 * source be a child of the targets in the list 'targets'
406 *
407 * Side Effects:
408 * Operator bits may be added to the list of targets or to the source.
409 * The targets may have a new source added to their lists of children.
410 *---------------------------------------------------------------------
411 */
412static void
413ParseDoSrc(
414 struct growableArray *targets,
415 struct growableArray *sources,
416 int tOp, /* operator (if any) from special targets */
417 const char *src, /* name of the source to handle */
418 const char *esrc)
419{
420 GNode *gn = Targ_FindNodei(src, esrc, TARG_CREATE0x01);
421 if (gn->special == SPECIAL_DEPRECATED7U) {
422 Parse_Error(PARSE_FATAL1, "Deprecated keyword found %s\n",
423 gn->name);
424 return;
425 }
426 if (gn->special_op) {
427 Array_ForEach(targets, ParseDoSpecial, gn->special_op)do { unsigned int i; for (i = 0; i < (targets)->n; i++)
(ParseDoSpecial)((targets)->a[i], (gn->special_op)); }
while (0)
;
428 return;
429 }
430 if (gn->special == SPECIAL_WAIT29U) {
431 waiting++;
432 return;
433 }
434
435 switch (specType) {
436 case SPECIAL_MAIN12U:
437 /*
438 * If we have noted the existence of a .MAIN, it means we need
439 * to add the sources of said target to the list of things
440 * to create. Note that this will only be invoked if the user
441 * didn't specify a target on the command line. This is to
442 * allow #ifmake's to succeed, or something...
443 */
444 Lst_AtEnd(create, gn->name);
445 /*
446 * Add the name to the .TARGETS variable as well, so the user
447 * can employ that, if desired.
448 */
449 Var_Append(".TARGETS", gn->name)Var_Appendi_with_ctxt(".TARGETS", ((void*)0), gn->name, 0);
450 return;
451
452 case SPECIAL_ORDER19U:
453 /*
454 * Create proper predecessor/successor links between the
455 * previous source and the current one.
456 */
457 if (predecessor != NULL((void*)0)) {
458 Lst_AtEnd(&predecessor->successors, gn);
459 Lst_AtEnd(&gn->predecessors, predecessor);
460 }
461 predecessor = gn;
462 break;
463
464 default:
465 /*
466 * In the case of a source that was the object of a :: operator,
467 * the attribute is applied to all of its instances (as kept in
468 * the 'cohorts' list of the node) or all the cohorts are linked
469 * to all the targets.
470 */
471 apply_op(targets, tOp, gn);
472 if ((gn->type & OP_OPMASK(0x00000001|0x00000002|0x00000004)) == OP_DOUBLEDEP0x00000004) {
473 LstNode ln;
474
475 for (ln=Lst_First(&gn->cohorts)((&gn->cohorts)->firstPtr); ln != NULL((void*)0);
476 ln = Lst_Adv(ln)((ln)->nextPtr)){
477 apply_op(targets, tOp, Lst_Datum(ln)((ln)->datum));
478 }
479 }
480 break;
481 }
482
483 gn->order = waiting;
484 Array_AtEnd(sources, gn)do { if ((sources)->n >= (sources)->size) { (sources
)->size *= 2; (sources)->a = ereallocarray((sources)->
a, (sources)->size, sizeof(struct GNode *)); ; } (sources)
->a[(sources)->n++] = (gn); } while (0)
;
485 if (waiting)
486 Array_Find(sources, ParseAddDep, gn)do { unsigned int i; for (i = 0; i < (sources)->n; i++)
if ((ParseAddDep)((sources)->a[i], (gn)) == 0) break; } while
(0)
;
487}
488
489/*-
490 *-----------------------------------------------------------------------
491 * ParseFindMain --
492 * Find a real target in the list and set it to be the main one.
493 * Called by ParseDoDependency when a main target hasn't been found
494 * yet.
495 *
496 * Results:
497 * 1 if main not found yet, 0 if it is.
498 *
499 * Side Effects:
500 * mainNode is changed and.
501 *-----------------------------------------------------------------------
502 */
503static int
504ParseFindMain(void *gnp, void *dummy UNUSED__attribute__((__unused__)))
505{
506 GNode *gn = gnp;
507
508 if ((gn->type & OP_NOTARGET(0x00002000|0x00000010|0x00040000)) == 0 && gn->special == SPECIAL_NONE0U) {
509 mainNode = gn;
510 return 0;
511 } else {
512 return 1;
513 }
514}
515
516/*-
517 *-----------------------------------------------------------------------
518 * ParseClearPath --
519 * Reinit path to an empty path
520 *-----------------------------------------------------------------------
521 */
522static void
523ParseClearPath(void *p)
524{
525 Lst path = p;
526
527 Lst_Destroy(path, Dir_Destroy);
528 Lst_Init(path)(path)->firstPtr = (path)->lastPtr = ((void*)0);
529}
530
531static void
532add_target_node(const char *line, const char *end)
533{
534 GNode *gn;
535
536 gn = Suff_ParseAsTransform(line, end);
537
538 if (gn == NULL((void*)0)) {
539 gn = Targ_FindNodei(line, end, TARG_CREATE0x01);
540 gn->type &= ~OP_DUMMY0x00020000;
541 }
542
543 Array_AtEnd(&gtargets, gn)do { if ((&gtargets)->n >= (&gtargets)->size
) { (&gtargets)->size *= 2; (&gtargets)->a = ereallocarray
((&gtargets)->a, (&gtargets)->size, sizeof(struct
GNode *)); ; } (&gtargets)->a[(&gtargets)->n++
] = (gn); } while (0)
;
544}
545
546static void
547add_target_nodes(const char *line, const char *end)
548{
549
550 if (Dir_HasWildcardsi(line, end)) {
551 /*
552 * Targets are to be sought only in the current directory,
553 * so create an empty path for the thing. Note we need to
554 * use Dir_Destroy in the destruction of the path as the
555 * Dir module could have added a directory to the path...
556 */
557 char *targName;
558 LIST emptyPath;
559 LIST curTargs;
560
561 Lst_Init(&emptyPath)(&emptyPath)->firstPtr = (&emptyPath)->lastPtr =
((void*)0)
;
562 Lst_Init(&curTargs)(&curTargs)->firstPtr = (&curTargs)->lastPtr = (
(void*)0)
;
563 Dir_Expandi(line, end, &emptyPath, &curTargs);
564 Lst_Destroy(&emptyPath, Dir_Destroy);
565 while ((targName = Lst_DeQueue(&curTargs)) != NULL((void*)0)) {
566 add_target_node(targName, targName + strlen(targName));
567 }
568 Lst_Destroy(&curTargs, NOFREE((SimpleProc) 0));
569 } else {
570 add_target_node(line, end);
571 }
572}
573
574/* special target line check: a proper delimiter is a ':' or '!', but
575 * we don't want to end a target on such a character if there is a better
576 * match later on.
577 * By "better" I mean one that is followed by whitespace. This allows the
578 * user to have targets like:
579 * fie::fi:fo: fum
580 * where "fie::fi:fo" is the target. In real life this is used for perl5
581 * library man pages where "::" separates an object from its class. Ie:
582 * "File::Spec::Unix".
583 * This behaviour is also consistent with other versions of make.
584 */
585static bool_Bool
586found_delimiter(const char *s)
587{
588 if (*s == '!' || *s == ':') {
589 const char *p = s + 1;
590
591 if (*s == ':' && *p == ':')
592 p++;
593
594 /* Found the best match already. */
595 if (ISSPACE(*p)(isspace((unsigned char)(*p))) || *p == '\0')
596 return true1;
597
598 do {
599 p += strcspn(p, "!:");
600 if (*p == '\0')
601 break;
602 /* always prefer : to ! if not space separated */
603 if (*p == ':' && *s == '!')
604 return false0;
605 p++;
606 } while (*p != '\0' && !ISSPACE(*p)(isspace((unsigned char)(*p))));
607
608 /* No better match later on... */
609 if (*p == '\0')
610 return true1;
611 }
612 return false0;
613}
614
615static const char *
616parse_do_targets(Lst paths, unsigned int *op, const char *line)
617{
618 const char *cp;
619
620 do {
621 for (cp = line; *cp && !ISSPACE(*cp)(isspace((unsigned char)(*cp))) && *cp != '(';) {
622 if (*cp == '$')
623 /* Must be a dynamic source (would have been
624 * expanded otherwise), so call the Var module
625 * to parse the puppy so we can safely advance
626 * beyond it...There should be no errors in
627 * this, as they would have been discovered in
628 * the initial Var_Subst and we wouldn't be
629 * here. */
630 Var_ParseSkip(&cp, NULL((void*)0));
631 else {
632 if (found_delimiter(cp))
633 break;
634 cp++;
635 }
636 }
637
638 if (*cp == '(') {
639 LIST temp;
640 Lst_Init(&temp)(&temp)->firstPtr = (&temp)->lastPtr = ((void*)
0)
;
641 /* Archives must be handled specially to make sure the
642 * OP_ARCHV flag is set in their 'type' field, for one
643 * thing, and because things like "archive(file1.o
644 * file2.o file3.o)" are permissible.
645 * Arch_ParseArchive will set 'line' to be the first
646 * non-blank after the archive-spec. It creates/finds
647 * nodes for the members and places them on the given
648 * list, returning true if all went well and false if
649 * there was an error in the specification. On error,
650 * line should remain untouched. */
651 if (!Arch_ParseArchive(&line, &temp, NULL((void*)0))) {
652 Parse_Error(PARSE_FATAL1,
653 "Error in archive specification: \"%s\"",
654 line);
655 return NULL((void*)0);
656 } else {
657 AppendList2Array(&temp, &gtargets)do { LstNode ln; for (ln = (((&temp))->firstPtr); ln !=
((void*)0); ln = ((ln)->nextPtr)) do { if (((&gtargets
))->n >= ((&gtargets))->size) { ((&gtargets)
)->size *= 2; ((&gtargets))->a = ereallocarray(((&
gtargets))->a, ((&gtargets))->size, sizeof(struct GNode
*)); ; } ((&gtargets))->a[((&gtargets))->n++] =
(((ln)->datum)); } while (0); } while (0)
;
658 Lst_Destroy(&temp, NOFREE((SimpleProc) 0));
659 cp = line;
660 continue;
661 }
662 }
663 if (*cp == '\0') {
664 /* Ending a dependency line without an operator is a
665 * Bozo no-no */
666 /* Deeper check for cvs conflicts */
667 if (gtargets.n > 0 &&
668 (strcmp(gtargets.a[0]->name, "<<<<<<<") == 0 ||
669 strcmp(gtargets.a[0]->name, ">>>>>>>") == 0)) {
670 Parse_Error(PARSE_FATAL1,
671 "Need an operator (likely from a cvs update conflict)");
672 } else {
673 Parse_Error(PARSE_FATAL1,
674 "Need an operator in '%s'", line);
675 }
676 return NULL((void*)0);
677 }
678 /*
679 * Have word in line. Get or create its nodes and stick it at
680 * the end of the targets list
681 */
682 if (*line != '\0')
683 add_target_nodes(line, cp);
684
685 while (ISSPACE(*cp)(isspace((unsigned char)(*cp))))
686 cp++;
687 line = cp;
688 } while (*line != '!' && *line != ':' && *line);
689 *op = handle_special_targets(paths);
690 return cp;
691}
692
693static void
694dump_targets()
695{
696 size_t i;
697 for (i = 0; i < gtargets.n; i++)
698 fprintf(stderr(&__sF[2]), "%s", gtargets.a[i]->name);
699 fprintf(stderr(&__sF[2]), "\n");
700}
701
702static unsigned int
703handle_special_targets(Lst paths)
704{
705 size_t i;
706 int seen_path = 0;
707 int seen_special = 0;
708 int seen_normal = 0;
709 int type;
710
711 for (i = 0; i < gtargets.n; i++) {
712 type = gtargets.a[i]->special;
713 if (type == SPECIAL_DEPRECATED7U) {
714 Parse_Error(PARSE_FATAL1,
715 "Deprecated keyword found %s\n",
716 gtargets.a[i]->name);
717 specType = SPECIAL_ERROR31U;
718 return 0;
719 }
720 if (type == SPECIAL_PATH62U) {
721 seen_path++;
722 Lst_AtEnd(paths, find_suffix_path(gtargets.a[i]));
723 } else if (type != 0)
724 seen_special++;
725 else
726 seen_normal++;
727 }
728 if ((seen_path != 0) + (seen_special != 0) + (seen_normal != 0) > 1) {
729 Parse_Error(PARSE_FATAL1, "Wrong mix of special targets");
730 dump_targets();
731 specType = SPECIAL_ERROR31U;
732 return 0;
733 }
734 if (seen_normal != 0) {
735 specType = SPECIAL_NONE0U;
736 return 0;
737 } else if (seen_path != 0) {
738 specType = SPECIAL_PATH62U;
739 return 0;
740 } else if (seen_special == 0) {
741 specType = SPECIAL_NONE0U;
742 return 0;
743 } else if (seen_special != 1) {
744 Parse_Error(PARSE_FATAL1,
745 "Mixing special targets is not allowed");
746 dump_targets();
747 return 0;
748 } else if (seen_special == 1) {
749 specType = gtargets.a[0]->special;
750 switch (specType) {
751 case SPECIAL_MAIN12U:
752 if (!Lst_IsEmpty(create)((create)->firstPtr == ((void*)0))) {
753 specType = SPECIAL_NONE0U;
754 }
755 break;
756 case SPECIAL_NOTPARALLEL16U:
757 set_notparallel();
758 break;
759 case SPECIAL_ORDER19U:
760 predecessor = NULL((void*)0);
761 break;
762 default:
763 break;
764 }
765 return gtargets.a[0]->special_op;
766 } else {
767 /* we're allowed to have 0 target */
768 specType = SPECIAL_NONE0U;
769 return 0;
770 }
771}
772
773static unsigned int
774parse_operator(const char **pos)
775{
776 const char *cp = *pos;
777 unsigned int op = OP_ERROR0x00000007;
778
779 if (*cp == '!') {
780 op = OP_FORCE0x00000002;
781 } else if (*cp == ':') {
782 if (cp[1] == ':') {
783 op = OP_DOUBLEDEP0x00000004;
784 cp++;
785 } else {
786 op = OP_DEPENDS0x00000001;
787 }
788 } else {
789 Parse_Error(PARSE_FATAL1, "Missing dependency operator");
790 return OP_ERROR0x00000007;
791 }
792
793 cp++; /* Advance beyond operator */
794
795 /* Get to the first source */
796 while (ISSPACE(*cp)(isspace((unsigned char)(*cp))))
797 cp++;
798 *pos = cp;
799 return op;
800}
801
802/*-
803 *---------------------------------------------------------------------
804 * ParseDoDependency --
805 * Parse the dependency line in line.
806 *
807 * Side Effects:
808 * The nodes of the sources are linked as children to the nodes of the
809 * targets. Some nodes may be created.
810 *
811 * We parse a dependency line by first extracting words from the line and
812 * finding nodes in the list of all targets with that name. This is done
813 * until a character is encountered which is an operator character. Currently
814 * these are only ! and :. At this point the operator is parsed and the
815 * pointer into the line advanced until the first source is encountered.
816 * The parsed operator is applied to each node in the 'targets' list,
817 * which is where the nodes found for the targets are kept, by means of
818 * the ParseDoOp function.
819 * The sources are read in much the same way as the targets were except
820 * that now they are expanded using the wildcarding scheme of the C-Shell
821 * and all instances of the resulting words in the list of all targets
822 * are found. Each of the resulting nodes is then linked to each of the
823 * targets as one of its children.
824 * Certain targets are handled specially. These are the ones detailed
825 * by the specType variable.
826 * The storing of transformation rules is also taken care of here.
827 * A target is recognized as a transformation rule by calling
828 * Suff_IsTransform. If it is a transformation rule, its node is gotten
829 * from the suffix module via Suff_AddTransform rather than the standard
830 * Targ_FindNode in the target module.
831 *---------------------------------------------------------------------
832 */
833static void
834ParseDoDependency(const char *line) /* the line to parse */
835{
836 const char *cp; /* our current position */
837 unsigned int op; /* the operator on the line */
838 LIST paths; /* List of search paths to alter when parsing
839 * a list of .PATH targets */
840 unsigned int tOp; /* operator from special target */
841
842 waiting = 0;
843 Lst_Init(&paths)(&paths)->firstPtr = (&paths)->lastPtr = ((void
*)0)
;
844
845 Array_Reset(&gsources)do { (&gsources)->n = 0; } while (0);
846
847 cp = parse_do_targets(&paths, &tOp, line);
848 assert(specType == SPECIAL_PATH || Lst_IsEmpty(&paths))((specType == 62U || ((&paths)->firstPtr == ((void*)0)
)) ? (void)0 : __assert2("/usr/src/usr.bin/make/parse.c", 848
, __func__, "specType == SPECIAL_PATH || Lst_IsEmpty(&paths)"
))
;
849 if (cp == NULL((void*)0) || specType == SPECIAL_ERROR31U) {
850 /* invalidate targets for further processing */
851 Array_Reset(&gtargets)do { (&gtargets)->n = 0; } while (0);
852 return;
853 }
854
855 op = parse_operator(&cp);
856 if (op == OP_ERROR0x00000007) {
857 /* invalidate targets for further processing */
858 Array_Reset(&gtargets)do { (&gtargets)->n = 0; } while (0);
859 return;
860 }
861
862 Array_FindP(&gtargets, ParseDoOp, op)do { unsigned int i; for (i = 0; i < (&gtargets)->n
; i++) if ((ParseDoOp)(&((&gtargets)->a[i]), (op))
== 0) break; } while (0)
;
863 dedup_targets(&gtargets);
864
865 line = cp;
866
867 /* Several special targets have specific semantics with no source:
868 * .SUFFIXES clears out all old suffixes
869 * .PRECIOUS/.IGNORE/.SILENT
870 * apply to all target
871 * .PATH clears out all search paths. */
872 if (!*line) {
873 switch (specType) {
874 case SPECIAL_SUFFIXES27U:
875 Suff_DisableAllSuffixes();
876 break;
877 case SPECIAL_PRECIOUS23U:
878 allPrecious = true1;
879 break;
880 case SPECIAL_IGNORE5U:
881 ignoreErrors = true1;
882 break;
883 case SPECIAL_SILENT25U:
884 beSilent = true1;
885 break;
886 case SPECIAL_PATH62U:
887 Lst_Every(&paths, ParseClearPath);
888 break;
889 default:
890 break;
891 }
892 } else if (specType == SPECIAL_MFLAGS14U) {
893 Main_ParseArgLine(line);
894 return;
895 } else if (specType == SPECIAL_NOTPARALLEL16U) {
896 return;
897 }
898
899 /* NOW GO FOR THE SOURCES */
900 if (specType == SPECIAL_SUFFIXES27U || specType == SPECIAL_PATH62U ||
901 specType == SPECIAL_NOTHING6U) {
902 while (*line) {
903 /* Some special targets take a list of space-separated
904 * words. For each word,
905 *
906 * if .SUFFIXES, add it to the list of suffixes maintained
907 * by suff.c.
908 *
909 * if .PATHS, add it as a directory on the main search path.
910 *
911 * if .LIBS/.INCLUDE/.NULL... this has been deprecated,
912 * ignore
913 */
914 while (*cp && !ISSPACE(*cp)(isspace((unsigned char)(*cp))))
915 cp++;
916 switch (specType) {
917 case SPECIAL_SUFFIXES27U:
918 Suff_AddSuffixi(line, cp);
919 break;
920 case SPECIAL_PATH62U:
921 {
922 LstNode ln;
923
924 for (ln = Lst_First(&paths)((&paths)->firstPtr); ln != NULL((void*)0);
925 ln = Lst_Adv(ln)((ln)->nextPtr))
926 Dir_AddDiri(Lst_Datum(ln)((ln)->datum), line, cp);
927 break;
928 }
929 default:
930 break;
931 }
932 if (*cp != '\0')
933 cp++;
934 while (ISSPACE(*cp)(isspace((unsigned char)(*cp))))
935 cp++;
936 line = cp;
937 }
938 } else {
939 while (*line) {
940 /*
941 * The targets take real sources, so we must beware of
942 * archive specifications (i.e. things with left
943 * parentheses in them) and handle them accordingly.
944 */
945 while (*cp && !ISSPACE(*cp)(isspace((unsigned char)(*cp)))) {
946 if (*cp == '(' && cp > line && cp[-1] != '$') {
947 /*
948 * Only stop for a left parenthesis if
949 * it isn't at the start of a word
950 * (that'll be for variable changes
951 * later) and isn't preceded by a
952 * dollar sign (a dynamic source).
953 */
954 break;
955 } else {
956 cp++;
957 }
958 }
959
960 if (*cp == '(') {
961 GNode *gn;
962 LIST sources; /* list of archive source
963 * names after expansion */
964
965 Lst_Init(&sources)(&sources)->firstPtr = (&sources)->lastPtr = ((
void*)0)
;
966 if (!Arch_ParseArchive(&line, &sources, NULL((void*)0))) {
967 Parse_Error(PARSE_FATAL1,
968 "Error in source archive spec \"%s\"",
969 line);
970 return;
971 }
972
973 while ((gn = Lst_DeQueue(&sources)) != NULL((void*)0))
974 ParseDoSrc(&gtargets, &gsources, tOp,
975 gn->name, NULL((void*)0));
976 cp = line;
977 } else {
978 const char *endSrc = cp;
979
980 ParseDoSrc(&gtargets, &gsources, tOp, line,
981 endSrc);
982 if (*cp)
983 cp++;
984 }
985 while (ISSPACE(*cp)(isspace((unsigned char)(*cp))))
986 cp++;
987 line = cp;
988 }
989 }
990
991 /* If we're not in the SPEC_PATH case the list is empty, but who
992 * cares ? This is cheap.
993 */
994 Lst_Destroy(&paths, NOFREE((SimpleProc) 0));
995
996 if (mainNode == NULL((void*)0)) {
997 /* If we have yet to decide on a main target to make, in the
998 * absence of any user input, we want the first target on
999 * the first dependency line that is actually a real target
1000 * (i.e. isn't a .USE or .EXEC rule) to be made. */
1001 Array_Find(&gtargets, ParseFindMain, NULL)do { unsigned int i; for (i = 0; i < (&gtargets)->n
; i++) if ((ParseFindMain)((&gtargets)->a[i], (((void*
)0))) == 0) break; } while (0)
;
1002 }
1003}
1004
1005/*-
1006 * ParseAddCmd --
1007 * Lst_ForEach function to add a command line to all targets
1008 *
1009 * The new command may be added to the commands list of the node.
1010 *
1011 * If the target already had commands, we ignore the new ones, but
1012 * we note that we got double commands (in case we actually get to run
1013 * that ambiguous target).
1014 *
1015 * Note this does not apply to :: dependency lines, since those
1016 * will generate fresh cloned nodes and add them to the cohorts
1017 * field of the main node.
1018 */
1019static void
1020ParseAddCmd(void *gnp, void *cmd)
1021{
1022 GNode *gn = gnp;
1023
1024 if (!(gn->type & OP_HAS_COMMANDS0x00400000))
1025 Lst_AtEnd(&gn->commands, cmd);
1026 else
1027 gn->type |= OP_DOUBLE0x00100000;
1028}
1029
1030/*-
1031 *-----------------------------------------------------------------------
1032 * ParseHasCommands --
1033 * Record that the target gained commands through OP_HAS_COMMANDS,
1034 * so that double command lists may be ignored.
1035 *-----------------------------------------------------------------------
1036 */
1037static void
1038ParseHasCommands(void *gnp)
1039{
1040 GNode *gn = gnp;
1041 gn->type |= OP_HAS_COMMANDS0x00400000;
1042
1043}
1044
1045
1046/* Strip comments from line. Build a copy in buffer if necessary, */
1047static char *
1048strip_comments(Buffer copy, const char *line)
1049{
1050 const char *comment;
1051 const char *p;
1052
1053 comment = strchr(line, '#');
1054 if (comment == NULL((void*)0))
1055 return (char *)line;
1056 else {
1057 Buf_Reset(copy)((void)((copy)->inPtr = (copy)->buffer + (0)));
1058
1059 for (p = line; *p != '\0'; p++) {
1060 if (*p == '\\') {
1061 if (p[1] == '#') {
1062 Buf_Addi(copy, line, p)Buf_AddChars((copy), (p) - (line), (line));
1063 Buf_AddChar(copy, '#')do { if ((copy)->endPtr - (copy)->inPtr <= 1) BufExpand
(copy, 1); *(copy)->inPtr++ = ('#'); } while (0)
;
1064 line = p+2;
1065 }
1066 if (p[1] != '\0')
1067 p++;
1068 } else if (*p == '#')
1069 break;
1070 }
1071 Buf_Addi(copy, line, p)Buf_AddChars((copy), (p) - (line), (line));
1072 return Buf_Retrieve(copy)(*(copy)->inPtr = '\0', (copy)->buffer);
1073 }
1074}
1075
1076
1077
1078/***
1079 *** Support for various include constructs
1080 ***/
1081
1082
1083void
1084Parse_AddIncludeDir(const char *dir)
1085{
1086 Dir_AddDir(userIncludePath, dir)Dir_AddDiri(userIncludePath, dir, ((void*)0));
1087}
1088
1089static char *
1090resolve_include_filename(const char *file, const char *efile, bool_Bool isSystem)
1091{
1092 char *fullname;
1093
1094 /* Look up system files on the system path first */
1095 if (isSystem) {
1096 fullname = Dir_FindFileNoDoti(file, efile, systemIncludePath)Dir_FindFileComplexi(file, efile, systemIncludePath, 0);
1097 if (fullname)
1098 return fullname;
1099 }
1100
1101 /* Handle non-system non-absolute files... */
1102 if (!isSystem && file[0] != '/') {
1103 /* ... by looking first under the same directory as the
1104 * current file */
1105 char *slash = NULL((void*)0);
1106 const char *fname;
1107
1108 fname = Parse_Getfilename();
1109
1110 if (fname != NULL((void*)0))
1111 slash = strrchr(fname, '/');
1112
1113 if (slash != NULL((void*)0)) {
1114 char *newName;
1115
1116 newName = Str_concati(fname, slash, file, efile, '/');
1117 fullname = Dir_FindFile(newName, userIncludePath)Dir_FindFileComplexi(newName, strchr(newName, '\0'), userIncludePath
, 1)
;
1118 if (fullname == NULL((void*)0))
1119 fullname = Dir_FindFile(newName, defaultPath)Dir_FindFileComplexi(newName, strchr(newName, '\0'), defaultPath
, 1)
;
1120 free(newName);
1121 if (fullname)
1122 return fullname;
1123 }
1124 }
1125
1126 /* Now look first on the -I search path, then on the .PATH
1127 * search path, if not found in a -I directory.
1128 * XXX: Suffix specific? */
1129 fullname = Dir_FindFilei(file, efile, userIncludePath)Dir_FindFileComplexi(file, efile, userIncludePath, 1);
1130 if (fullname)
1131 return fullname;
1132 fullname = Dir_FindFilei(file, efile, defaultPath)Dir_FindFileComplexi(file, efile, defaultPath, 1);
1133 if (fullname)
1134 return fullname;
1135
1136 /* Still haven't found the makefile. Look for it on the system
1137 * path as a last resort (if we haven't already). */
1138 if (isSystem)
1139 return NULL((void*)0);
1140 else
1141 return Dir_FindFilei(file, efile, systemIncludePath)Dir_FindFileComplexi(file, efile, systemIncludePath, 1);
1142}
1143
1144static void
1145handle_include_file(const char *file, const char *efile, bool_Bool isSystem,
1146 bool_Bool errIfNotFound)
1147{
1148 char *fullname;
1149
1150 fullname = resolve_include_filename(file, efile, isSystem);
1151 if (fullname == NULL((void*)0) && errIfNotFound)
1152 Parse_Error(PARSE_FATAL1, "Could not find %.*s",
1153 (int)(efile - file), file);
1154
1155 if (fullname != NULL((void*)0)) {
1156 FILE *f;
1157
1158 f = fopen(fullname, "r");
1159 if (f == NULL((void*)0) && errIfNotFound)
1160 Parse_Error(PARSE_FATAL1, "Cannot open %s", fullname);
1161 else
1162 Parse_FromFile(fullname, f);
1163 }
1164}
1165
1166/* .include <file> (system) or .include "file" (normal) */
1167static bool_Bool
1168lookup_bsd_include(const char *file)
1169{
1170 char endc;
1171 const char *efile;
1172 char *file2;
1173 bool_Bool isSystem;
1174
1175 /* find starting delimiter */
1176 while (ISSPACE(*file)(isspace((unsigned char)(*file))))
1177 file++;
1178
1179 /* determine type of file */
1180 if (*file == '<') {
1181 isSystem = true1;
1182 endc = '>';
1183 } else if (*file == '"') {
1184 isSystem = false0;
1185 endc = '"';
1186 } else {
1187 Parse_Error(PARSE_WARNING2,
1188 ".include filename must be delimited by '\"' or '<'");
1189 return false0;
1190 }
1191
1192 /* delimit file name between file and efile */
1193 for (efile = ++file; *efile != endc; efile++) {
1194 if (*efile == '\0') {
1195 Parse_Error(PARSE_WARNING2,
1196 "Unclosed .include filename. '%c' expected", endc);
1197 return false0;
1198 }
1199 }
1200 /* Substitute for any variables in the file name before trying to
1201 * find the thing. */
1202 file2 = Var_Substi(file, efile, NULL((void*)0), false0);
1203 handle_include_file(file2, strchr(file2, '\0'), isSystem, true1);
1204 free(file2);
1205 return true1;
1206}
1207
1208
1209static void
1210lookup_sysv_style_include(const char *line, const char *directive,
1211 bool_Bool errIfMissing)
1212{
1213 char *file;
1214 char *name;
1215 char *ename;
1216 bool_Bool okay = false0;
1217
1218 /* Substitute for any variables in the file name before trying to
1219 * find the thing. */
1220 file = Var_Subst(line, NULL((void*)0), false0);
1221
1222 /* sys5 allows for list of files separated by spaces */
1223 name = file;
1224 while (1) {
1225 /* find beginning of name */
1226 while (ISSPACE(*name)(isspace((unsigned char)(*name))))
1227 name++;
1228 if (*name == '\0')
1229 break;
1230 for (ename = name; *ename != '\0' && !ISSPACE(*ename)(isspace((unsigned char)(*ename)));)
1231 ename++;
1232 handle_include_file(name, ename, true1, errIfMissing);
1233 okay = true1;
1234 name = ename;
1235 }
1236
1237 free(file);
1238 if (!okay) {
1239 Parse_Error(PARSE_FATAL1, "Filename missing from \"%s\"",
1240 directive);
1241 }
1242}
1243
1244
1245/* system V construct: include file */
1246static void
1247lookup_sysv_include(const char *file, const char *directive)
1248{
1249 lookup_sysv_style_include(file, directive, true1);
1250}
1251
1252
1253/* sinclude file and -include file */
1254static void
1255lookup_conditional_include(const char *file, const char *directive)
1256{
1257 lookup_sysv_style_include(file, directive, false0);
1258}
1259
1260
1261/***
1262 *** BSD-specific . constructs
1263 *** They all follow the same pattern:
1264 *** if the syntax matches BSD stuff, then we're committed to handle
1265 *** them and report fatal errors (like, include file not existing)
1266 *** otherwise, we return false, and hope somebody else will handle it.
1267 ***/
1268
1269static bool_Bool
1270handle_poison(const char *line)
1271{
1272 const char *p = line;
1273 int type = POISON_NORMAL64;
1274 bool_Bool not = false0;
1275 bool_Bool paren_to_match = false0;
1276 const char *name, *ename;
1277
1278 while (ISSPACE(*p)(isspace((unsigned char)(*p))))
1279 p++;
1280 if (*p == '!') {
1281 not = true1;
1282 p++;
1283 }
1284 while (ISSPACE(*p)(isspace((unsigned char)(*p))))
1285 p++;
1286 if (strncmp(p, "defined", 7) == 0) {
1287 type = POISON_DEFINED1;
1288 p += 7;
1289 } else if (strncmp(p, "empty", 5) == 0) {
1290 type = POISON_EMPTY128;
1291 p += 5;
1292 }
1293 while (ISSPACE(*p)(isspace((unsigned char)(*p))))
1294 p++;
1295 if (*p == '(') {
1296 paren_to_match = true1;
1297 p++;
1298 }
1299 while (ISSPACE(*p)(isspace((unsigned char)(*p))))
1300 p++;
1301 name = ename = p;
1302 while (*p != '\0' && !ISSPACE(*p)(isspace((unsigned char)(*p)))) {
1303 if (*p == ')' && paren_to_match) {
1304 paren_to_match = false0;
Value stored to 'paren_to_match' is never read
1305 p++;
1306 break;
1307 }
1308 p++;
1309 ename = p;
1310 }
1311 while (ISSPACE(*p)(isspace((unsigned char)(*p))))
1312 p++;
1313 switch(type) {
1314 case POISON_NORMAL64:
1315 case POISON_EMPTY128:
1316 if (not)
1317 type = POISON_INVALID0;
1318 break;
1319 case POISON_DEFINED1:
1320 if (not)
1321 type = POISON_NOT_DEFINED256;
1322 else
1323 type = POISON_INVALID0;
1324 break;
1325 }
1326 if ((*p != '\0' && *p != '#') || type == POISON_INVALID0) {
1327 Parse_Error(PARSE_WARNING2, "Invalid syntax for .poison: %s",
1328 line);
1329 return false0;
1330 } else {
1331 Var_Mark(name, ename, type);
1332 return true1;
1333 }
1334}
1335
1336
1337static bool_Bool
1338handle_for_loop(Buffer linebuf, const char *line)
1339{
1340 For *loop;
1341
1342 loop = For_Eval(line);
1343 if (loop != NULL((void*)0)) {
1344 bool_Bool ok;
1345 do {
1346 /* Find the matching endfor. */
1347 line = ParseReadLoopLine(linebuf)Parse_ReadUnparsedLine(linebuf, "for loop");
1348 if (line == NULL((void*)0)) {
1349 Parse_Error(PARSE_FATAL1,
1350 "Unexpected end of file in for loop.\n");
1351 return false0;
1352 }
1353 ok = For_Accumulate(loop, line);
1354 } while (ok);
1355 For_Run(loop);
1356 return true1;
1357 } else
1358 return false0;
1359}
1360
1361static bool_Bool
1362handle_undef(const char *line)
1363{
1364 const char *eline;
1365
1366 while (ISSPACE(*line)(isspace((unsigned char)(*line))))
1367 line++;
1368 for (eline = line; !ISSPACE(*eline)(isspace((unsigned char)(*eline))) && *eline != '\0';)
1369 eline++;
1370 Var_Deletei(line, eline);
1371 return true1;
1372}
1373
1374/* global hub for the construct */
1375static bool_Bool
1376handle_bsd_command(Buffer linebuf, Buffer copy, const char *line)
1377{
1378 char *stripped;
1379
1380 while (ISSPACE(*line)(isspace((unsigned char)(*line))))
1381 line++;
1382
1383 /* delegate basic classification to the conditional module */
1384 switch (Cond_Eval(line)) {
1385 case COND_SKIP1:
1386 /* Skip to next conditional that evaluates to COND_PARSE. */
1387 do {
1388 line = Parse_ReadNextConditionalLine(linebuf);
1389 if (line != NULL((void*)0)) {
1390 while (ISSPACE(*line)(isspace((unsigned char)(*line))))
1391 line++;
1392 stripped = strip_comments(copy, line);
1393 }
1394 } while (line != NULL((void*)0) && Cond_Eval(stripped) != COND_PARSE0);
1395 /* FALLTHROUGH */
1396 case COND_PARSE0:
1397 return true1;
1398 case COND_ISFOR3:
1399 return handle_for_loop(linebuf, line + 3);
1400 case COND_ISINCLUDE5:
1401 return lookup_bsd_include(line + 7);
1402 case COND_ISPOISON6:
1403 return handle_poison(line + 6);
1404 case COND_ISUNDEF4:
1405 return handle_undef(line + 5);
1406 default:
1407 break;
1408 }
1409
1410 return false0;
1411}
1412
1413/* postprocess group of targets prior to linking stuff with them */
1414static bool_Bool
1415register_target(GNode *gn, struct ohash *t)
1416{
1417 unsigned int slot;
1418 uint32_t hv;
1419 const char *ename = NULL((void*)0);
1420 GNode *gn2;
1421
1422 hv = ohash_interval(gn->name, &ename);
1423
1424 slot = ohash_lookup_interval(t, gn->name, ename, hv);
1425 gn2 = ohash_find(t, slot);
1426
1427 if (gn2 == NULL((void*)0)) {
1428 ohash_insert(t, slot, gn);
1429 return true1;
1430 } else
1431 return false0;
1432}
1433
1434static void
1435build_target_group(struct growableArray *targets, struct ohash *t)
1436{
1437 LstNode ln;
1438 bool_Bool seen_target = false0;
1439 unsigned int i;
1440
1441 /* may be 0 if wildcard expansion resulted in zero match */
1442 if (targets->n <= 1)
1443 return;
1444
1445 /* Perform checks to see if we must tie targets together */
1446 /* XXX */
1447 if (targets->a[0]->type & OP_TRANSFORM0x00040000)
1448 return;
1449
1450 for (ln = Lst_First(&targets->a[0]->commands)((&targets->a[0]->commands)->firstPtr); ln != NULL((void*)0);
1451 ln = Lst_Adv(ln)((ln)->nextPtr)) {
1452 struct command *cmd = Lst_Datum(ln)((ln)->datum);
1453 if (Var_Check_for_target(cmd->string)) {
1454 seen_target = true1;
1455 break;
1456 }
1457 }
1458 if (DEBUG(TARGGROUP)(debug & 0x80000)) {
1459 fprintf(stderr(&__sF[2]),
1460 seen_target ? "No target group at %lu: ":
1461 "Target group at %lu:", Parse_Getlineno());
1462 for (i = 0; i < targets->n; i++)
1463 fprintf(stderr(&__sF[2]), " %s", targets->a[i]->name);
1464 fprintf(stderr(&__sF[2]), "\n");
1465 }
1466 if (seen_target)
1467 return;
1468
1469 GNode *gn, *gn2;
1470 /* targets may already participate in groupling lists,
1471 * so rebuild the circular list "from scratch"
1472 */
1473
1474 for (i = 0; i < targets->n; i++) {
1475 gn = targets->a[i];
1476 for (gn2 = gn->groupling; gn2 != gn; gn2 = gn2->groupling) {
1477 if (!gn2)
1478 break;
1479 register_target(gn2, t);
1480 }
1481 }
1482
1483 for (gn = ohash_first(t, &i); gn != NULL((void*)0); gn = ohash_next(t, &i)) {
1484 gn->groupling = gn2;
1485 gn2 = gn;
1486 }
1487 gn = ohash_first(t, &i);
1488 gn->groupling = gn2;
1489}
1490
1491static void
1492reset_target_hash()
1493{
1494 if (htargets_setup)
1495 ohash_delete(&htargets);
1496 ohash_init(&htargets, 5, &gnode_info);
1497 htargets_setup = true1;
1498}
1499
1500void
1501Parse_End()
1502{
1503 if (htargets_setup)
1504 ohash_delete(&htargets);
1505}
1506
1507static void
1508dedup_targets(struct growableArray *targets)
1509{
1510 unsigned int i, j;
1511
1512 if (targets->n <= 1)
1513 return;
1514
1515 reset_target_hash();
1516 /* first let's de-dup the list */
1517 for (i = 0, j = 0; i < targets->n; i++) {
1518 GNode *gn = targets->a[i];
1519 if (register_target(gn, &htargets))
1520 targets->a[j++] = targets->a[i];
1521 }
1522 targets->n = j;
1523}
1524
1525
1526/***
1527 *** handle a group of commands
1528 ***/
1529
1530static void
1531finish_commands(struct growableArray *targets)
1532{
1533 build_target_group(targets, &htargets);
1534 Array_Every(targets, ParseHasCommands)do { unsigned int i; for (i = 0; i < (targets)->n; i++)
(ParseHasCommands)((targets)->a[i]); } while (0)
;
1535}
1536
1537static void
1538parse_commands(struct growableArray *targets, const char *line)
1539{
1540 /* add the command to the list of
1541 * commands of all targets in the dependency spec */
1542
1543 struct command *cmd;
1544 size_t len = strlen(line);
1545
1546 cmd = emalloc(sizeof(struct command) + len);
1547 memcpy(&cmd->string, line, len+1);
1548 Parse_FillLocation(&cmd->location);
1549
1550 Array_ForEach(targets, ParseAddCmd, cmd)do { unsigned int i; for (i = 0; i < (targets)->n; i++)
(ParseAddCmd)((targets)->a[i], (cmd)); } while (0)
;
1551}
1552
1553static bool_Bool
1554parse_as_special_line(Buffer buf, Buffer copy, const char *line)
1555{
1556 if (*line == '.' && handle_bsd_command(buf, copy, line+1))
1557 return true1;
1558 if (FEATURES(FEATURE_SYSVINCLUDE)(((8 | 16 | 32 | 64 | 128 | 256) & (32)) != 0) &&
1559 strncmp(line, "include", 7) == 0 &&
1560 ISSPACE(line[7])(isspace((unsigned char)(line[7]))) &&
1561 strchr(line, ':') == NULL((void*)0)) {
1562 /* It's an S3/S5-style "include". */
1563 lookup_sysv_include(line + 7, "include");
1564 return true1;
1565 }
1566 if (FEATURES(FEATURE_CONDINCLUDE)(((8 | 16 | 32 | 64 | 128 | 256) & (256)) != 0) &&
1567 strncmp(line, "sinclude", 8) == 0 &&
1568 ISSPACE(line[8])(isspace((unsigned char)(line[8]))) &&
1569 strchr(line, ':') == NULL((void*)0)) {
1570 lookup_conditional_include(line+8, "sinclude");
1571 return true1;
1572 }
1573 if (FEATURES(FEATURE_CONDINCLUDE)(((8 | 16 | 32 | 64 | 128 | 256) & (256)) != 0) &&
1574 strncmp(line, "-include", 8) == 0 &&
1575 ISSPACE(line[8])(isspace((unsigned char)(line[8]))) &&
1576 strchr(line, ':') == NULL((void*)0)) {
1577 lookup_conditional_include(line+8, "-include");
1578 return true1;
1579 }
1580 return false0;
1581}
1582
1583static void
1584parse_target_line(struct growableArray *targets, const char *line,
1585 const char *stripped, bool_Bool *pcommands_seen)
1586{
1587 size_t pos;
1588 char *end;
1589 char *cp;
1590 char *cmd;
1591
1592 /* let's start a new set of commands */
1593 Array_Reset(targets)do { (targets)->n = 0; } while (0);
1594
1595 /* XXX this is a dirty heuristic to handle target: dep ; commands */
1596 cmd = NULL((void*)0);
1597 /* First we need to find eventual dependencies */
1598 pos = strcspn(stripped, ":!");
1599 /* go over :!, and find ; */
1600 if (stripped[pos] != '\0' &&
1601 (end = strchr(stripped+pos+1, ';')) != NULL((void*)0)) {
1602 if (line != stripped)
1603 /* find matching ; in original... The
1604 * original might be slightly longer. */
1605 cmd = strchr(line+(end-stripped), ';');
1606 else
1607 cmd = end;
1608 /* kill end of line. */
1609 *end = '\0';
1610 }
1611 /* We now know it's a dependency line so it needs to
1612 * have all variables expanded before being parsed.
1613 */
1614 cp = Var_Subst(stripped, NULL((void*)0), false0);
1615 ParseDoDependency(cp);
1616 free(cp);
1617
1618 /* Parse command if it's not empty. */
1619 if (cmd != NULL((void*)0)) {
1620 do {
1621 cmd++;
1622 } while (ISSPACE(*cmd)(isspace((unsigned char)(*cmd))));
1623 if (*cmd != '\0') {
1624 parse_commands(targets, cmd);
1625 *pcommands_seen = true1;
1626 }
1627 }
1628}
1629
1630void
1631Parse_File(const char *filename, FILE *stream)
1632{
1633 char *line;
1634 bool_Bool expectingCommands = false0;
1635 bool_Bool commands_seen = false0;
1636
1637 /* permanent spaces to shave time */
1638 static BUFFER buf;
1639 static BUFFER copy;
1640
1641 Buf_Reinit(&buf, MAKE_BSIZE256);
1642 Buf_Reinit(&copy, MAKE_BSIZE256);
1643
1644 Parse_FromFile(filename, stream);
1645 do {
1646 while ((line = Parse_ReadNormalLine(&buf)) != NULL((void*)0)) {
1647 if (*line == '\t') {
1648 if (expectingCommands) {
1649 commands_seen = true1;
1650 parse_commands(&gtargets, line+1);
1651 } else
1652 Parse_Error(PARSE_FATAL1,
1653 "Unassociated shell command \"%s\"",
1654 line);
1655 } else {
1656 const char *stripped = strip_comments(&copy,
1657 line);
1658 if (!parse_as_special_line(&buf, &copy,
1659 stripped)) {
1660 if (commands_seen)
1661 finish_commands(&gtargets);
1662 commands_seen = false0;
1663 if (Parse_As_Var_Assignment(stripped))
1664 expectingCommands = false0;
1665 else {
1666 parse_target_line(&gtargets,
1667 line, stripped,
1668 &commands_seen);
1669 expectingCommands = true1;
1670 }
1671 }
1672 }
1673 }
1674 } while (Parse_NextFile());
1675
1676 if (commands_seen)
1677 finish_commands(&gtargets);
1678 /* Make sure conditionals are clean. */
1679 Cond_End();
1680
1681 Parse_ReportErrors();
1682}
1683
1684void
1685Parse_Init(void)
1686{
1687 mainNode = NULL((void*)0);
1688 Static_Lst_Init(userIncludePath);
1689 Static_Lst_Init(systemIncludePath);
1690 Array_Init(&gtargets, TARGETS_SIZE)do { (&gtargets)->size = (32); (&gtargets)->n =
0; (&gtargets)->a = ereallocarray(((void*)0), (&gtargets
)->size, sizeof(GNode *)); } while (0)
;
1691 Array_Init(&gsources, SOURCES_SIZE)do { (&gsources)->size = (128); (&gsources)->n =
0; (&gsources)->a = ereallocarray(((void*)0), (&gsources
)->size, sizeof(GNode *)); } while (0)
;
1692 create_special_nodes();
1693}
1694
1695void
1696Parse_MainName(Lst listmain) /* result list */
1697{
1698 if (mainNode == NULL((void*)0)) {
1699 Punt("no target to make.");
1700 /*NOTREACHED*/
1701 } else if (mainNode->type & OP_DOUBLEDEP0x00000004) {
1702 Lst_AtEnd(listmain, mainNode);
1703 Lst_Concat(listmain, &mainNode->cohorts);
1704 }
1705 else
1706 Lst_AtEnd(listmain, mainNode);
1707}