Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make make(1): split ParseDoDependency into several s...
details: https://anonhg.NetBSD.org/src/rev/ebbfcc417014
branches: trunk
changeset: 976859:ebbfcc417014
user: rillig <rillig%NetBSD.org@localhost>
date: Mon Oct 05 16:33:20 2020 +0000
description:
make(1): split ParseDoDependency into several smaller functions
diffstat:
usr.bin/make/parse.c | 652 ++++++++++++++++++++++++++++----------------------
1 files changed, 366 insertions(+), 286 deletions(-)
diffs (truncated from 736 to 300 lines):
diff -r 571bc8437cc3 -r ebbfcc417014 usr.bin/make/parse.c
--- a/usr.bin/make/parse.c Mon Oct 05 16:17:05 2020 +0000
+++ b/usr.bin/make/parse.c Mon Oct 05 16:33:20 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.363 2020/10/05 15:43:32 rillig Exp $ */
+/* $NetBSD: parse.c,v 1.364 2020/10/05 16:33:20 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -131,7 +131,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.363 2020/10/05 15:43:32 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.364 2020/10/05 16:33:20 rillig Exp $");
/* types and constants */
@@ -204,6 +204,8 @@
Attribute /* Generic attribute */
} ParseSpecial;
+typedef List SearchPathList;
+
/* result data */
/*
@@ -1110,6 +1112,357 @@
*pp = cp;
}
+/*
+ * Certain special targets have special semantics:
+ * .PATH Have to set the dirSearchPath
+ * variable too
+ * .MAIN Its sources are only used if
+ * nothing has been specified to
+ * create.
+ * .DEFAULT Need to create a node to hang
+ * commands on, but we don't want
+ * it in the graph, nor do we want
+ * it to be the Main Target, so we
+ * create it, set OP_NOTMAIN and
+ * add it to the list, setting
+ * DEFAULT to the new node for
+ * later use. We claim the node is
+ * A transformation rule to make
+ * life easier later, when we'll
+ * use Make_HandleUse to actually
+ * apply the .DEFAULT commands.
+ * .PHONY The list of targets
+ * .NOPATH Don't search for file in the path
+ * .STALE
+ * .BEGIN
+ * .END
+ * .ERROR
+ * .DELETE_ON_ERROR
+ * .INTERRUPT Are not to be considered the
+ * main target.
+ * .NOTPARALLEL Make only one target at a time.
+ * .SINGLESHELL Create a shell for each command.
+ * .ORDER Must set initial predecessor to NULL
+ */
+static void
+ParseDoDependencyTargetSpecial(ParseSpecial *const inout_specType,
+ const char *const line,
+ SearchPathList **const inout_paths)
+{
+ switch (*inout_specType) {
+ case ExPath:
+ if (*inout_paths == NULL) {
+ *inout_paths = Lst_Init();
+ }
+ Lst_Append(*inout_paths, dirSearchPath);
+ break;
+ case Main:
+ if (!Lst_IsEmpty(create)) {
+ *inout_specType = Not;
+ }
+ break;
+ case Begin:
+ case End:
+ case Stale:
+ case dotError:
+ case Interrupt: {
+ GNode *gn = Targ_GetNode(line);
+ if (doing_depend)
+ ParseMark(gn);
+ gn->type |= OP_NOTMAIN|OP_SPECIAL;
+ Lst_Append(targets, gn);
+ break;
+ }
+ case Default: {
+ GNode *gn = Targ_NewGN(".DEFAULT");
+ gn->type |= OP_NOTMAIN|OP_TRANSFORM;
+ Lst_Append(targets, gn);
+ DEFAULT = gn;
+ break;
+ }
+ case DeleteOnError:
+ deleteOnError = TRUE;
+ break;
+ case NotParallel:
+ maxJobs = 1;
+ break;
+ case SingleShell:
+ compatMake = TRUE;
+ break;
+ case Order:
+ predecessor = NULL;
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * .PATH<suffix> has to be handled specially.
+ * Call on the suffix module to give us a path to modify.
+ */
+static Boolean
+ParseDoDependencyTargetPath(const char *const line,
+ SearchPathList **const inout_paths)
+{
+ SearchPath *path;
+
+ path = Suff_GetPath(&line[5]);
+ if (path == NULL) {
+ Parse_Error(PARSE_FATAL,
+ "Suffix '%s' not defined (yet)",
+ &line[5]);
+ return FALSE;
+ } else {
+ if (*inout_paths == NULL) {
+ *inout_paths = Lst_Init();
+ }
+ Lst_Append(*inout_paths, path);
+ }
+ return TRUE;
+}
+
+/*
+ * See if it's a special target and if so set specType to match it.
+ */
+static Boolean
+ParseDoDependencyTarget(const char *const line,
+ ParseSpecial *const inout_specType,
+ GNodeType *out_tOp,
+ SearchPathList **inout_paths)
+{
+ int keywd;
+
+ if (!(*line == '.' && ch_isupper(line[1])))
+ return TRUE;
+
+ /*
+ * See if the target is a special target that must have it
+ * or its sources handled specially.
+ */
+ keywd = ParseFindKeyword(line);
+ if (keywd != -1) {
+ if (*inout_specType == ExPath && parseKeywords[keywd].spec != ExPath) {
+ Parse_Error(PARSE_FATAL, "Mismatched special targets");
+ return FALSE;
+ }
+
+ *inout_specType = parseKeywords[keywd].spec;
+ *out_tOp = parseKeywords[keywd].op;
+
+ ParseDoDependencyTargetSpecial(inout_specType, line, inout_paths);
+
+ } else if (strncmp(line, ".PATH", 5) == 0) {
+ *inout_specType = ExPath;
+ if (!ParseDoDependencyTargetPath(line, inout_paths))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+ParseDoDependencyTargetMundane(char *const line,
+ StringList *const curTargs)
+{
+ if (Dir_HasWildcards(line)) {
+ /*
+ * Targets are to be sought only in the current directory,
+ * so create an empty path for the thing. Note we need to
+ * use Dir_Destroy in the destruction of the path as the
+ * Dir module could have added a directory to the path...
+ */
+ SearchPath *emptyPath = Lst_Init();
+
+ Dir_Expand(line, emptyPath, curTargs);
+
+ Lst_Destroy(emptyPath, Dir_Destroy);
+ } else {
+ /*
+ * No wildcards, but we want to avoid code duplication,
+ * so create a list with the word on it.
+ */
+ Lst_Append(curTargs, line);
+ }
+
+ /* Apply the targets. */
+
+ while(!Lst_IsEmpty(curTargs)) {
+ char *targName = Lst_Dequeue(curTargs);
+ GNode *gn = Suff_IsTransform(targName)
+ ? Suff_AddTransform(targName)
+ : Targ_GetNode(targName);
+ if (doing_depend)
+ ParseMark(gn);
+
+ Lst_Append(targets, gn);
+ }
+}
+
+static void
+ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart)
+{
+ Boolean warning = FALSE;
+ char *cp = *pp;
+
+ while (*cp && (ParseIsEscaped(lstart, cp) ||
+ (*cp != '!' && *cp != ':'))) {
+ if (ParseIsEscaped(lstart, cp) ||
+ (*cp != ' ' && *cp != '\t')) {
+ warning = TRUE;
+ }
+ cp++;
+ }
+ if (warning) {
+ Parse_Error(PARSE_WARNING, "Extra target ignored");
+ }
+ *pp = cp;
+}
+
+static void
+ParseDoDependencyCheckSpec(ParseSpecial const specType)
+{
+ switch(specType) {
+ default:
+ Parse_Error(PARSE_WARNING,
+ "Special and mundane targets don't mix. Mundane ones ignored");
+ break;
+ case Default:
+ case Stale:
+ case Begin:
+ case End:
+ case dotError:
+ case Interrupt:
+ /*
+ * These four create nodes on which to hang commands, so
+ * targets shouldn't be empty...
+ */
+ case Not:
+ /*
+ * Nothing special here -- targets can be empty if it wants.
+ */
+ break;
+ }
+}
+
+static Boolean
+ParseDoDependencyParseOp(char **const pp, const char *const lstart,
+ GNodeType *const out_op)
+{
+ const char *cp = *pp;
+
+ if (*cp == '!') {
+ *out_op = OP_FORCE;
+ (*pp)++;
+ return TRUE;
+ }
+
+ if (*cp == ':') {
+ if (cp[1] == ':') {
+ *out_op = OP_DOUBLEDEP;
+ (*pp) += 2;
+ } else {
+ *out_op = OP_DEPENDS;
+ (*pp)++;
+ }
+ return TRUE;
+ }
+
+ {
+ const char *msg = lstart[0] == '.' ? "Unknown directive"
+ : "Missing dependency operator";
+ Parse_Error(PARSE_FATAL, "%s", msg);
+ return FALSE;
+ }
+}
+
+static void
+ParseDoDependencySourcesEmpty(ParseSpecial const specType,
+ SearchPathList *const paths)
+{
+ switch (specType) {
+ case Suffixes:
Home |
Main Index |
Thread Index |
Old Index