Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src PR/46096: Jarmo Jaakkola: fix many problems with dependencie...



details:   https://anonhg.NetBSD.org/src/rev/dc921a35f61b
branches:  trunk
changeset: 331763:dc921a35f61b
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Aug 23 15:05:40 2014 +0000

description:
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086)

Quite extensive rewrite of the Suff module.  Some ripple effects into
Parse and Targ modules too.

Dependency searches in general were made to honor explicit rules so
implicit and explicit sources are no longer applied on targets that
do not invoke a transformation rule.

Archive member dependency search was rewritten.  Explicit rules now
work properly and $(.TARGET) is set correctly.  POSIX semantics for
lib(member.o) and .s1.a rules are supported.

.SUFFIXES list maintenance was rewritten so that scanning of existing
rules works when suffixes are added and that clearing the suffix list
removes single suffix rules too.  Transformation rule nodes are now
mixed with regular nodes so they are available as regular targets too
if needed (especially after the known suffixes are cleared).

The .NULL target was documented in the manual page, especially to
warn against using it when a single suffix rule would work.
A deprecation warning was also added to the manual and make also
warns the user if it encounters .NULL.

Search for suffix rules no longer allows the explicit dependencies
to override the selected transformation rule.  A check is made in
the search that the transformation that would be tried does not
already exist in the chain.  This prevents getting stuck in an infinite
loop under specific circumstances.  Local variables are now set
before node's children are expanded so dynamic sources work in
multi-stage transformations.  Make_HandleUse() no longer expands
the added children for transformation nodes, preventing triple
expansion and allowing the Suff module to properly postpone their
expansion until proper values are set for the local variables.

Directory prefix is no longer removed from $(.PREFIX) if the target
is found via directory search.

The last rule defined is now used instead of the first one (POSIX
requirement) in case a rule is defined multiple times.  Everything
defined in the first instance is undone, but things added "globally"
are honored.  To implement this, each node tracks attribute bits
which have been set by special targets (global) instead of special
sources (local).  They also track dependencies that were added by
a rule with commands (local) instead of rule with no commands (global).

New attribute, OP_FROM_SYS_MK is introduced.  It is set on all targets
found in system makefiles so that they are not eligible to become
the main target.  We cannot just set OP_NOTMAIN because it is one of
the attributes inherited from transformation and .USE rules and would
make any eligible target that uses a built-in inference rule ineligible.

The $(.IMPSRC) local variable now works like in gmake: it is set to
the first prerequisite for explicit rules.  For implicit rules it
is still the implied source.

The manual page is improved regarding the fixed features.  Test cases
for the fixed problems are added.

Other improvements in the Suff module include:
  - better debug messages for transformation rule search (length of
    the chain is now visualized by indentation)
  - Suff structures are created, destroyed and moved around by a set
    of maintenance functions so their reference counts are easier
    to track (this also gets rid of a lot of code duplication)
  - some unreasonably long functions were split into smaller ones
  - many local variables had their names changed to describe their
    purpose instead of their type

diffstat:

 tests/usr.bin/make/t_make.sh         |     4 +-
 usr.bin/make/compat.c                |    20 +-
 usr.bin/make/lst.h                   |    21 +-
 usr.bin/make/lst.lib/lstInt.h        |     8 +-
 usr.bin/make/lst.lib/lstRemove.c     |   146 +-
 usr.bin/make/main.c                  |    36 +-
 usr.bin/make/make.1                  |   291 +++-
 usr.bin/make/make.c                  |   104 +-
 usr.bin/make/make.h                  |    44 +-
 usr.bin/make/nonints.h               |    10 +-
 usr.bin/make/parse.c                 |   233 +-
 usr.bin/make/suff.c                  |  2985 ++++++++++++++++++---------------
 usr.bin/make/targ.c                  |    12 +-
 usr.bin/make/unit-tests/impsrc.exp   |    13 +
 usr.bin/make/unit-tests/impsrc.mk    |    43 +
 usr.bin/make/unit-tests/suffixes.exp |    35 +
 usr.bin/make/unit-tests/suffixes.mk  |    84 +
 17 files changed, 2526 insertions(+), 1563 deletions(-)

diffs (truncated from 5510 to 300 lines):

diff -r b084264dea88 -r dc921a35f61b tests/usr.bin/make/t_make.sh
--- a/tests/usr.bin/make/t_make.sh      Sat Aug 23 15:03:22 2014 +0000
+++ b/tests/usr.bin/make/t_make.sh      Sat Aug 23 15:05:40 2014 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: t_make.sh,v 1.3 2014/08/23 14:50:24 christos Exp $
+# $NetBSD: t_make.sh,v 1.4 2014/08/23 15:05:41 christos Exp $
 #
 # Copyright (c) 2008, 2010, 2014 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -43,7 +43,7 @@
                # the test shouldn't use anything not provided for by in
                # the POSIX standard.
                args="INPUTFILE='${in}'"
-               atf_expect_fail 'PR/49086 [$(<)], PR/49092 [output order]'
+               atf_expect_fail 'PR/49092 [output order]'
                atf_check -o file:"${out}" -x \
                    "make -kf'${in}' ${args} 2>&1 | sed -e 's,${srcdir}/d_,,'"
        else
diff -r b084264dea88 -r dc921a35f61b usr.bin/make/compat.c
--- a/usr.bin/make/compat.c     Sat Aug 23 15:03:22 2014 +0000
+++ b/usr.bin/make/compat.c     Sat Aug 23 15:05:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $  */
+/*     $NetBSD: compat.c,v 1.95 2014/08/23 15:05:40 christos Exp $     */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $";
+static char rcsid[] = "$NetBSD: compat.c,v 1.95 2014/08/23 15:05:40 christos Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)compat.c   8.2 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $");
+__RCSID("$NetBSD: compat.c,v 1.95 2014/08/23 15:05:40 christos Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -531,12 +531,7 @@
            goto cohorts;
        }
 
-       if (Lst_Member(gn->iParents, pgn) != NULL) {
-           char *p1;
-           Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
-           if (p1)
-               free(p1);
-       }
+       Make_SetImpsrcLocalVar(gn, pgn);
 
        /*
         * All the children were made ok. Now cmgn->mtime contains the
@@ -635,12 +630,7 @@
         */
        pgn->flags &= ~REMAKE;
     } else {
-       if (Lst_Member(gn->iParents, pgn) != NULL) {
-           char *p1;
-           Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
-           if (p1)
-               free(p1);
-       }
+       Make_SetImpsrcLocalVar(gn, pgn);
        switch(gn->made) {
            case BEINGMADE:
                Error("Graph cycles through %s", gn->name);
diff -r b084264dea88 -r dc921a35f61b usr.bin/make/lst.h
--- a/usr.bin/make/lst.h        Sat Aug 23 15:03:22 2014 +0000
+++ b/usr.bin/make/lst.h        Sat Aug 23 15:05:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lst.h,v 1.18 2009/01/23 21:58:27 dsl Exp $     */
+/*     $NetBSD: lst.h,v 1.19 2014/08/23 15:05:40 christos Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -94,6 +94,7 @@
 
 typedef void           *DuplicateProc(void *);
 typedef void           FreeProc(void *);
+typedef void           FreeProc2(void *, void *);
 
 #define LST_CONCNEW    0   /* create new LstNode's when using Lst_Concat */
 #define LST_CONCLINK   1   /* relink LstNode's when using Lst_Concat */
@@ -113,6 +114,7 @@
 /*
  * Functions to modify a list
  */
+/* NB!  SUCCESS is 0, FAILURE is 1! */
 /* Insert an element before another */
 ReturnStatus   Lst_InsertBefore(Lst, LstNode, void *);
 /* Insert an element after another */
@@ -123,6 +125,10 @@
 ReturnStatus   Lst_AtEnd(Lst, void *);
 /* Remove an element */
 ReturnStatus   Lst_Remove(Lst, LstNode);
+#if 0
+/* Remove multiple successive elements. */
+ReturnStatus   Lst_RemoveSlice(Lst, LstNode, LstNode, FreeProc2 *, void *);
+#endif
 /* Replace a node with a new value */
 ReturnStatus   Lst_Replace(LstNode, void *);
 /* Concatenate two lists */
@@ -145,6 +151,10 @@
 /*
  * Functions for entire lists
  */
+/*
+ * NB!  The predicate function logic is inverted!  You have to return 0
+ * if the item you're looking for has been found, and non-zero if it hasn't.
+ */
 /* Find an element in a list */
 LstNode                Lst_Find(Lst, const void *, int (*)(const void *, const void *));
 /* Find an element starting from somewhere */
@@ -168,12 +178,19 @@
  * these functions are for dealing with a list as a table, of sorts.
  * An idea of the "current element" is kept and used by all the functions
  * between Lst_Open() and Lst_Close().
+ * Usage:
+ *     LstNode ln;
+ *     Lst_Open(lst);
+ *     while (ln = Lst_Next(lst) && !Lst_IsAtEnd(lst)) {
+ *             ...
+ *     }
+ *     Lst_Close(lst);
  */
 /* Open the list */
 ReturnStatus   Lst_Open(Lst);
 /* Next element please */
 LstNode                Lst_Next(Lst);
-/* Done yet? */
+/* Done yet, i.e. is the result of the latest Lst_Next() a valid node? */
 Boolean                Lst_IsAtEnd(Lst);
 /* Finish table access */
 void           Lst_Close(Lst);
diff -r b084264dea88 -r dc921a35f61b usr.bin/make/lst.lib/lstInt.h
--- a/usr.bin/make/lst.lib/lstInt.h     Sat Aug 23 15:03:22 2014 +0000
+++ b/usr.bin/make/lst.lib/lstInt.h     Sat Aug 23 15:05:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lstInt.h,v 1.20 2009/01/24 14:43:29 dsl Exp $  */
+/*     $NetBSD: lstInt.h,v 1.21 2014/08/23 15:05:40 christos Exp $     */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -59,7 +59,11 @@
 #define LN_DELETED     0x0001      /* List node should be removed when done */
 
 typedef enum {
-    Head, Middle, Tail, Unknown
+    Head,      /* list is just opened and its empty */
+    Middle,    /* not empty and not at end */
+    Tail,      /* end has been reached, the result of previous Lst_Next()
+                * is bogus */
+    Unknown    /* list is just opened and its not empty */
 } Where;
 
 typedef struct List {
diff -r b084264dea88 -r dc921a35f61b usr.bin/make/lst.lib/lstRemove.c
--- a/usr.bin/make/lst.lib/lstRemove.c  Sat Aug 23 15:03:22 2014 +0000
+++ b/usr.bin/make/lst.lib/lstRemove.c  Sat Aug 23 15:05:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $       */
+/*     $NetBSD: lstRemove.c,v 1.15 2014/08/23 15:05:40 christos Exp $  */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -33,14 +33,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $";
+static char rcsid[] = "$NetBSD: lstRemove.c,v 1.15 2014/08/23 15:05:40 christos Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)lstRemove.c        8.1 (Berkeley) 6/6/93";
 #else
-__RCSID("$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $");
+__RCSID("$NetBSD: lstRemove.c,v 1.15 2014/08/23 15:05:40 christos Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -64,6 +64,8 @@
  *     The list's firstPtr will be set to NULL if ln is the last
  *     node on the list. firsPtr and lastPtr will be altered if ln is
  *     either the first or last node, respectively, on the list.
+ *     If the list is open for sequential access and the removed node
+ *     is the current one, the current node is reset to the previous one.
  *
  *-----------------------------------------------------------------------
  */
@@ -102,23 +104,33 @@
     /*
      * Sequential access stuff. If the node we're removing is the current
      * node in the list, reset the current node to the previous one. If the
-     * previous one was non-existent (prevPtr == NULL), we set the
-     * end to be Unknown, since it is.
+     * previous one is non-existent, the removed item is the first item of
+     * a non-circular list and we have to adjust atEnd while keeping in
+     * mind that it might have also been the only item.
      */
-    if (list->isOpen && (list->curPtr == lNode)) {
-       list->curPtr = list->prevPtr;
-       if (list->curPtr == NULL) {
-           list->atEnd = Unknown;
+    if (list->isOpen && list->curPtr == lNode) {
+       if (list->curPtr->prevPtr == NULL) {
+           if (list->curPtr->nextPtr == NULL)
+               list->atEnd = Head;     /* only item */
+           else
+               list->atEnd = Unknown;
        }
+
+       list->curPtr = list->curPtr->prevPtr;
     }
 
     /*
-     * the only way firstPtr can still point to ln is if ln is the last
-     * node on the list (the list is circular, so lNode->nextptr == lNode in
-     * this case). The list is, therefore, empty and is marked as such
+     * The only way firstPtr can still point to ln is if ln was the last
+     * node of a circular list and thus lNode->nextptr == lNode.  Therefore,
+     * the list has now become empty and is marked as such.
      */
     if (list->firstPtr == lNode) {
        list->firstPtr = NULL;
+       if (list->isOpen) {
+           /* stop sequential access too */
+           list->curPtr = NULL;
+           list->atEnd = Head;
+       }
     }
 
     /*
@@ -134,3 +146,113 @@
     return (SUCCESS);
 }
 
+#if 0
+/*
+ * This was implemented, but turned out to be unnecessary.  Put it into
+ * version control, remove later and leave a note, so the effort is not
+ * wasted and it can be revived later if needed.
+ */
+
+/*-
+ *-----------------------------------------------------------------------
+ * Lst_RemoveSlice -- remove the given interval from the given list.
+ *
+ * Remove all items between s and e, inclusive.  If s == e, only one
+ * item is removed.  freeProc is invoked on all removed items, if it is
+ * provided.
+ *
+ * If the first item of the list falls into the removed range,
+ * the start is moved to the first item after the removed range.
+ * If the last item of the list or the current sequential access
+ * position falls into the removed range, the it is moved to
+ * the first item before the removed range.
+ *
+ * If the list becomes totally empty, the special locations are
+ * also set properly.
+ *
+ * Pre-condition:
+ *     In a non-circular list, the s must not be after e.
+ *
+ * Input:
+ *     l       list to remove the items from
+ *     s       first item to remove
+ *     e       last item to remove
+ *     freeProc        when non-NULL, invoked for each removed item as
+ *                     (*freeProc)(Lst_Datum(item), data)
+ *      data   extra parameters for freeProc
+ *
+ * Results:
+ *      FAILURE if any parameter is invalid, SUCCESS otherwise.
+ *-----------------------------------------------------------------------
+ */
+ReturnStatus
+Lst_RemoveSlice(Lst l, LstNode s, LstNode e, FreeProc2 *freeProc, void *data)
+{
+    List       list;           /* list being processerd */
+    ListNode   end, start;     /* endpoints of range to remove */
+    ListNode   predecessor, successor; /* start->prevPtr and end->nextPtr */
+    ListNode   i, iNext;       /* iterators into the range */
+
+    /* flags to recognize when special nodes are removed */
+    Boolean    firstRemoved, lastRemoved, curRemoved;
+
+    if (!LstValid (l) || !LstNodeValid (s, l) || !LstNodeValid(e, l))
+       return FAILURE;
+
+    list = l;
+    start = s;
+    end = e;



Home | Main Index | Thread Index | Old Index