From f312d23f4598097b56883d95d598dc4b502498b7 Mon Sep 17 00:00:00 2001
From: Igor Pashev <pashev.igor@gmail.com>
Date: Tue, 24 Mar 2015 22:30:52 +0300
Subject: Implemented .WAIT

Based on this patch:
http://lists.gnu.org/archive/html/help-make/2005-04/msg00091.html

Test file (wait.mk):
simple: 1 .WAIT 2
    @echo $@
1:
    @sleep 2; echo $@
2:
    @echo $@

run:
./make --sun -f wait.mk -j50 simple
Output:
1
2
simple
---
 dep.h                           |  1 +
 file.c                          | 24 ++++++++++++++++++++++++
 remake.c                        | 28 ++++++++++++++++++++++++++++
 tests/scripts/features/sun-wait | 34 ++++++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+)
 create mode 100644 tests/scripts/features/sun-wait

diff --git a/dep.h b/dep.h
index b8c0d29..7551e63 100644
--- a/dep.h
+++ b/dep.h
@@ -42,6 +42,7 @@ struct dep
     unsigned int staticpattern : 1;
     unsigned int need_2nd_expansion : 1;
     unsigned int dontcare : 1;
+    unsigned int wait : 1;
   };
 
 
diff --git a/file.c b/file.c
index fab1d96..9cb5e52 100644
--- a/file.c
+++ b/file.c
@@ -474,6 +474,27 @@ split_prereqs (char *p)
   return new;
 }
 
+/* Notice special dependencies.  */
+static void
+notice_special_deps(struct dep **d_ptr)
+{
+  struct dep *d;
+
+restart_loop:
+  for (; *d_ptr; d_ptr = &(*d_ptr)->next)
+    {
+      d = *d_ptr;
+      if (!strcmp(d->name, ".WAIT"))
+       {
+         if (d->next)
+           d->next->wait = 1;
+         *d_ptr = d->next;
+         free_dep(d);
+         goto restart_loop;
+       }
+    }
+}
+
 /* Given a list of prerequisites, enter them into the file database.
    If STEM is set then first expand patterns using STEM.  */
 struct dep *
@@ -537,6 +558,9 @@ enter_prereqs (struct dep *deps, const char *stem)
         }
     }
 
+  if (sun_flag)
+    notice_special_deps(&deps);
+
   /* Enter them as files, unless they need a 2nd expansion.  */
   for (d1 = deps; d1 != 0; d1 = d1->next)
     {
diff --git a/remake.c b/remake.c
index 0888cff..fc71d06 100644
--- a/remake.c
+++ b/remake.c
@@ -409,6 +409,19 @@ complain (struct file *file)
     }
 }
 
+/* Mark the dependencies as considered in this pass (to avoid skipping them
+   on the next pass).  */
+static void
+consider_deps (struct dep *d)
+{
+  for (; d; d = d->next)
+    {
+      if (d->file->considered != considered)
+       consider_deps (d->file->deps);
+      d->file->considered = considered;
+    }
+}
+
 /* Consider a single 'struct file' and update it as appropriate.
    Return 0 on success, or non-0 on failure.  */
 
@@ -540,6 +553,13 @@ update_file_1 (struct file *file, unsigned int depth)
           int maybe_make;
           int dontcare = 0;
 
+          /* The code below will set the state to cs_deps_running.  */
+          if (d->wait && running)
+            {
+              consider_deps(d);
+              break;
+            }
+
           check_renamed (d->file);
 
           mtime = file_mtime (d->file);
@@ -616,6 +636,13 @@ update_file_1 (struct file *file, unsigned int depth)
   if (must_make || always_make_flag)
     {
       for (d = file->deps; d != 0; d = d->next)
+        {
+          /* The code below will set the state to cs_deps_running.  */
+          if (d->wait && running)
+            {
+              consider_deps(d);
+              break;
+            }
         if (d->file->intermediate)
           {
             enum update_status new;
@@ -667,6 +694,7 @@ update_file_1 (struct file *file, unsigned int depth)
               d->changed = ((file->phony && file->cmds != 0)
                             || file_mtime (d->file) != mtime);
           }
+        }
     }
 
   finish_updating (file);
diff --git a/tests/scripts/features/sun-wait b/tests/scripts/features/sun-wait
new file mode 100644
index 0000000..bc2fab6
--- /dev/null
+++ b/tests/scripts/features/sun-wait
@@ -0,0 +1,34 @@
+#                                                                    -*-perl-*-
+$description = "Check .WAIT special target";
+
+$details = "";
+
+run_make_test('
+one:
+	@sleep 2; echo $@
+two:
+	@echo $@
+
+three: one .WAIT two
+	@echo $@
+
+four: one two
+	@echo $@
+
+',
+'--sun three', # note: one job
+"one\ntwo\nthree");
+
+# Same file, but 3 jobs, must be the same result due to .WAIT:
+run_make_test(undef, '--sun -j3 three', "one\ntwo\nthree");
+
+# Same file, but "two" should not depend on "one":
+run_make_test(undef, '--sun two', "two");
+
+# Same file, but "two" should end earlier:
+run_make_test(undef, '--sun -j3 four', "two\none\nfour");
+# Same file, but "two" should end earlier even in mornal mode ;-)
+run_make_test(undef, '-j3 four', "two\none\nfour");
+
+# This tells the test driver that the perl test script executed properly.
+1;
-- 
cgit v1.2.3