Bug Summary

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