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