diff -urN mingw32-make-3.80.0-3/read.c mingw32-make-3.80.0-3-new/read.c
--- read.c.orig	2007-06-22 10:48:45.018367300 -0600
+++ read.c	2007-06-21 17:45:10.685773400 -0600
@@ -61,7 +61,7 @@
 /* Types of "words" that can be read in a makefile.  */
 enum make_word_type
   {
-     w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon,
+     w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_tcolon, w_semicolon,
      w_varassign
   };
 
@@ -133,7 +133,7 @@
 static int conditional_line PARAMS ((char *line, const struct floc *flocp));
 static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
 			struct dep *deps, unsigned int cmds_started, char *commands,
-			unsigned int commands_idx, int two_colon,
+			unsigned int commands_idx, int two_colon, int three_colon,
 			int have_sysv_atvar,
                         const struct floc *flocp, int set_default));
 static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
@@ -470,6 +471,7 @@
   struct dep *deps = 0;
   long nlines = 0;
   int two_colon = 0;
+  int three_colon = 0;
   char *pattern = 0, *pattern_percent;
   struct floc *fstart;
   struct floc fi;
@@ -482,7 +484,7 @@
 	  fi.lineno = tgts_started;                                           \
 	  record_files (filenames, pattern, pattern_percent, deps,            \
                         cmds_started, commands, commands_idx, two_colon,      \
-                        have_sysv_atvar, &fi, set_default);                   \
+                        three_colon, have_sysv_atvar, &fi, set_default);      \
         }                                                                     \
       filenames = 0;							      \
       commands_idx = 0;							      \
@@ -922,6 +934,7 @@
 
           case w_colon:
           case w_dcolon:
+          case w_tcolon:
             /* We accept and ignore rules without targets for
                compatibility with SunOS 4 make.  */
             no_targets = 1;
@@ -1029,8 +1042,19 @@
 
         /* Is this a one-colon or two-colon entry?  */
         two_colon = *p2 == ':';
+        three_colon = 0;
         if (two_colon)
-          p2++;
+          {
+            p2++;
+
+            /* Is this a two-colon or three-colon entry?  */
+            three_colon = *p2 == ':';
+            if (three_colon)
+              {
+                two_colon = 0;
+                p2++;
+              }
+          }
 
         /* Test to see if it's a target-specific variable.  Copy the rest
            of the buffer over, possibly temporarily (we'll expand it later
@@ -1751,7 +1775,7 @@
 
 static void
 record_files (filenames, pattern, pattern_percent, deps, cmds_started,
-	      commands, commands_idx, two_colon, have_sysv_atvar,
+	      commands, commands_idx, two_colon, three_colon, have_sysv_atvar,
               flocp, set_default)
      struct nameseq *filenames;
      char *pattern, *pattern_percent;
@@ -1760,15 +1784,22 @@
      char *commands;
      unsigned int commands_idx;
      int two_colon;
+     int three_colon;
      int have_sysv_atvar;
      const struct floc *flocp;
      int set_default;
 {
-  struct nameseq *nextf;
+  struct nameseq *filenames_ptr;
   int implicit = 0;
   unsigned int max_targets = 0, target_idx = 0;
   char **targets = 0, **target_percents = 0;
   struct commands *cmds;
+  struct dep *also_make_head = 0;
+  struct dep *also_make_tail = 0;
+
+  if (pattern && three_colon)
+    fatal (flocp,
+           _("rule can't be both ::: and pattern"));
 
   if (commands_idx > 0)
     {
@@ -1781,17 +1812,15 @@
   else
     cmds = 0;
 
-  for (; filenames != 0; filenames = nextf)
+  for (filenames_ptr = filenames; filenames_ptr != 0; filenames_ptr = filenames_ptr->next)
     {
-      char *name = filenames->name;
+      char *name = filenames_ptr->name;
+      struct nameseq *nextf = filenames_ptr->next;
       struct file *f;
       struct dep *d;
       struct dep *this;
       char *implicit_percent;
 
-      nextf = filenames->next;
-      free (filenames);
-
       /* Check for .POSIX.  We used to do this in snap_deps() but that's not
          good enough: it doesn't happen until after the makefile is read,
          which means we cannot use its value during parsing.  */
@@ -2070,6 +2099,24 @@
 					 pattern_percent, percent);
 	      f->stem = savestring (buffer, o - buffer);
 	    }
+
+          if (three_colon)
+            {
+              struct dep *new = (struct dep *) xmalloc (sizeof (struct dep));
+              new->ignore_mtime = 0;
+              new->name = f->name;
+              new->file = f;
+              new->next = 0;
+              if (also_make_tail)
+                {
+                  also_make_tail->next = new;
+                }
+              also_make_tail = new;
+              if (!also_make_head)
+                {
+                  also_make_head = new;
+                }
+            }
 	}
       else
 	{
@@ -2145,6 +2192,38 @@
 	}
     }
 
+  /* three_colon mode, and at least 2 targets */
+  if (three_colon && also_make_head && also_make_head->next)
+    {
+      struct dep *also_make_head_orig = also_make_head;
+
+      do {
+        also_make_head->file->also_make = copy_dep_chain(also_make_head->next);
+
+        /* Rotate list */
+        also_make_tail->next = also_make_head;
+        also_make_head = also_make_head->next;
+        also_make_tail = also_make_tail->next;
+        also_make_tail->next = 0;
+      } while (also_make_head != also_make_head_orig);
+
+      /* Variables names in this block are used for a different purpose than their name would imply */
+      while (also_make_head)
+        {
+          also_make_tail = also_make_head->next;
+          free(also_make_head);
+          also_make_head = also_make_tail;
+        }
+    }
+
+  filenames_ptr = filenames;
+  while (filenames_ptr != 0)
+    {
+      struct nameseq *nextf = filenames_ptr->next;
+      free(filenames_ptr);
+      filenames_ptr = nextf;
+    }
+
   if (implicit)
     {
       targets[target_idx] = 0;
@@ -2644,6 +2723,7 @@
      w_variable     A word containing one or more variables/functions
      w_colon        A colon
      w_dcolon       A double-colon
+     w_tcolon       A triple-colon
      w_semicolon    A semicolon
      w_varassign    A variable assignment operator (=, :=, +=, or ?=)
 
@@ -2689,6 +2769,15 @@
         case ':':
           ++p;
           wtype = w_dcolon;
+          switch (*p)
+            {
+            case ':':
+              ++p;
+              wtype = w_tcolon;
+              break;
+            default:
+              break;
+            }
           break;
 
         case '=':
