Submitted By:            Armin K. <krejzi at email dot com>
Date:                    2012-09-19
Initial Package Version: 3.82
Upstream Status:         Fixed Upstream
Origin:                  Upstream
Description:             Several bug fixes from upstream cvs.

--- make.orig/expand.c	2010-07-13 03:20:39.000000000 +0200
+++ make/expand.c	2012-09-19 17:25:52.496989738 +0200
@@ -197,7 +197,7 @@
 {
   struct variable *v;
   const char *p, *p1;
-  char *abuf = NULL;
+  char *save;
   char *o;
   unsigned int line_offset;
 
@@ -212,16 +212,11 @@
       return (variable_buffer);
     }
 
-  /* If we want a subset of the string, allocate a temporary buffer for it.
-     Most of the functions we use here don't work with length limits.  */
-  if (length > 0 && string[length] != '\0')
-    {
-      abuf = xmalloc(length+1);
-      memcpy(abuf, string, length);
-      abuf[length] = '\0';
-      string = abuf;
-    }
-  p = string;
+  /* We need a copy of STRING: due to eval, it's possible that it will get
+     freed as we process it (it might be the value of a variable that's reset
+     for example).  Also having a nil-terminated string is handy.  */
+  save = length < 0 ? xstrdup (string) : xstrndup (string, length);
+  p = save;
 
   while (1)
     {
@@ -411,8 +406,7 @@
       ++p;
     }
 
-  if (abuf)
-    free (abuf);
+  free (save);
 
   variable_buffer_output (o, "", 1);
   return (variable_buffer + line_offset);
--- make.orig/function.c	2010-07-13 03:20:39.000000000 +0200
+++ make/function.c	2012-09-19 17:25:52.509989959 +0200
@@ -706,7 +706,7 @@
   const char *word_iterator = argv[0];
   char buf[20];
 
-  while (find_next_token (&word_iterator, (unsigned int *) 0) != 0)
+  while (find_next_token (&word_iterator, NULL) != 0)
     ++i;
 
   sprintf (buf, "%d", i);
@@ -1133,21 +1133,14 @@
 
   /* Find the maximum number of words we'll have.  */
   t = argv[0];
-  wordi = 1;
-  while (*t != '\0')
+  wordi = 0;
+  while ((p = find_next_token (&t, NULL)) != 0)
     {
-      char c = *(t++);
-
-      if (! isspace ((unsigned char)c))
-        continue;
-
+      ++t;
       ++wordi;
-
-      while (isspace ((unsigned char)*t))
-        ++t;
     }
 
-  words = xmalloc (wordi * sizeof (char *));
+  words = xmalloc ((wordi == 0 ? 1 : wordi) * sizeof (char *));
 
   /* Now assign pointers to each string in the array.  */
   t = argv[0];
--- make.orig/job.c	2010-07-24 10:27:50.000000000 +0200
+++ make/job.c	2012-09-19 17:25:52.509989959 +0200
@@ -29,6 +29,15 @@
 
 #include <string.h>
 
+#if defined(__linux__) /* defined (HAVE_LINUX_BINFMTS_H) && defined (HAVE_SYS_USER_H) */
+#include <sys/user.h>
+#include <unistd.h>
+#ifndef PAGE_SIZE
+#define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
+#endif
+#include <linux/binfmts.h>
+#endif
+
 /* Default shell to use.  */
 #ifdef WINDOWS32
 #include <windows.h>
@@ -2791,6 +2800,15 @@
        argument list.  */
 
     unsigned int shell_len = strlen (shell);
+#ifdef MAX_ARG_STRLEN
+    static char eval_line[] = "eval\\ \\\"set\\ x\\;\\ shift\\;\\ ";
+#define ARG_NUMBER_DIGITS 5
+#define EVAL_LEN (sizeof(eval_line)-1 + shell_len + 4 \
+                 + (7 + ARG_NUMBER_DIGITS) * 2 * line_len / (MAX_ARG_STRLEN - 2))
+#else
+#define EVAL_LEN 0
+#endif
+    char *args_ptr;
     unsigned int line_len = strlen (line);
     unsigned int sflags_len = strlen (shellflags);
     char *command_ptr = NULL; /* used for batch_mode_shell mode */
@@ -2866,7 +2884,7 @@
       }
 
     new_line = alloca (shell_len + 1 + sflags_len + 1
-                             + (line_len*2) + 1);
+                             + (line_len*2) + 1 + EVAL_LEN);
     ap = new_line;
     memcpy (ap, shell, shell_len);
     ap += shell_len;
@@ -2875,6 +2893,30 @@
     ap += sflags_len;
     *(ap++) = ' ';
     command_ptr = ap;
+
+#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN)
+    if (unixy_shell && line_len > MAX_ARG_STRLEN)
+      {
+	unsigned j;
+	memcpy (ap, eval_line, sizeof (eval_line) - 1);
+	ap += sizeof (eval_line) - 1;
+	for (j = 1; j <= 2 * line_len / (MAX_ARG_STRLEN - 2); j++)
+	  ap += sprintf (ap, "\\$\\{%u\\}", j);
+	*ap++ = '\\';
+	*ap++ = '"';
+	*ap++ = ' ';
+	/* Copy only the first word of SHELL to $0.  */
+	for (p = shell; *p != '\0'; ++p)
+	  {
+	    if (isspace ((unsigned char)*p))
+	      break;
+	    *ap++ = *p;
+	  }
+	*ap++ = ' ';
+      }
+#endif
+    args_ptr = ap;
+
     for (p = line; *p != '\0'; ++p)
       {
 	if (restp != NULL && *p == '\n')
@@ -2922,6 +2964,14 @@
           }
 #endif
 	*ap++ = *p;
+
+#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN)
+	if (unixy_shell && line_len > MAX_ARG_STRLEN && (ap - args_ptr > MAX_ARG_STRLEN - 2))
+	  {
+	    *ap++ = ' ';
+	    args_ptr = ap;
+	  }
+#endif
       }
     if (ap == new_line + shell_len + sflags_len + 2)
       /* Line was empty.  */
--- make.orig/main.c	2010-07-19 09:10:53.000000000 +0200
+++ make/main.c	2012-09-19 17:25:52.510989976 +0200
@@ -1138,7 +1138,7 @@
      a macro and some compilers (MSVC) don't like conditionals in macros.  */
   {
     const char *features = "target-specific order-only second-expansion"
-                           " else-if shortest-stem undefine"
+                           " else-if shortest-stem undefine oneshell"
 #ifndef NO_ARCHIVES
                            " archives"
 #endif
@@ -2088,12 +2088,17 @@
 
           ++restarts;
 
+          /* If we're re-exec'ing the first make, put back the number of
+             job slots so define_makefiles() will get it right.  */
+          if (master_job_slots)
+            job_slots = master_job_slots;
+
           /* Reset makeflags in case they were changed.  */
           {
             const char *pv = define_makeflags (1, 1);
             char *p = alloca (sizeof ("MAKEFLAGS=") + strlen (pv) + 1);
             sprintf (p, "MAKEFLAGS=%s", pv);
-            putenv (p);
+            putenv (allocated_variable_expand (p));
           }
 
 	  if (ISDB (DB_BASIC))
@@ -2824,9 +2829,6 @@
 		       && (*(unsigned int *) cs->value_ptr ==
 			   *(unsigned int *) cs->noarg_value))
 		ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
-	      else if (cs->c == 'j')
-		/* Special case for `-j'.  */
-		ADD_FLAG ("1", 1);
 	      else
 		{
 		  char *buf = alloca (30);
--- make.orig/read.c	2010-07-13 03:20:42.000000000 +0200
+++ make/read.c	2012-09-19 17:25:52.511989993 +0200
@@ -2904,6 +2904,7 @@
       const char *name;
       const char **nlist = 0;
       char *tildep = 0;
+      int globme = 1;
 #ifndef NO_ARCHIVES
       char *arname = 0;
       char *memname = 0;
@@ -3028,7 +3029,7 @@
             {
               /* This looks like the first element in an open archive group.
                  A valid group MUST have ')' as the last character.  */
-              const char *e = p + nlen;
+              const char *e = p;
               do
                 {
                   e = next_token (e);
@@ -3084,19 +3085,19 @@
          Go to the next item in the string.  */
       if (flags & PARSEFS_NOGLOB)
         {
-          NEWELT (concat (2, prefix, tp));
+          NEWELT (concat (2, prefix, tmpbuf));
           continue;
         }
 
       /* If we get here we know we're doing glob expansion.
          TP is a string in tmpbuf.  NLEN is no longer used.
          We may need to do more work: after this NAME will be set.  */
-      name = tp;
+      name = tmpbuf;
 
       /* Expand tilde if applicable.  */
-      if (tp[0] == '~')
+      if (tmpbuf[0] == '~')
 	{
-	  tildep = tilde_expand (tp);
+	  tildep = tilde_expand (tmpbuf);
 	  if (tildep != 0)
             name = tildep;
 	}
@@ -3112,32 +3113,40 @@
 	}
 #endif /* !NO_ARCHIVES */
 
-      switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl))
-	{
-	case GLOB_NOSPACE:
-	  fatal (NILF, _("virtual memory exhausted"));
-
-	case 0:
-          /* Success.  */
-          i = gl.gl_pathc;
-          nlist = (const char **)gl.gl_pathv;
-          break;
-
-        case GLOB_NOMATCH:
-          /* If we want only existing items, skip this one.  */
-          if (flags & PARSEFS_EXISTS)
-            {
-              i = 0;
-              break;
-            }
-          /* FALLTHROUGH */
-
-	default:
-          /* By default keep this name.  */
+      /* glob() is expensive: don't call it unless we need to.  */
+      if (!(flags & PARSEFS_EXISTS) && strpbrk (name, "?*[") == NULL)
+        {
+          globme = 0;
           i = 1;
           nlist = &name;
-          break;
-	}
+        }
+      else
+        switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl))
+          {
+          case GLOB_NOSPACE:
+            fatal (NILF, _("virtual memory exhausted"));
+
+          case 0:
+            /* Success.  */
+            i = gl.gl_pathc;
+            nlist = (const char **)gl.gl_pathv;
+            break;
+
+          case GLOB_NOMATCH:
+            /* If we want only existing items, skip this one.  */
+            if (flags & PARSEFS_EXISTS)
+              {
+                i = 0;
+                break;
+              }
+            /* FALLTHROUGH */
+
+          default:
+            /* By default keep this name.  */
+            i = 1;
+            nlist = &name;
+            break;
+          }
 
       /* For each matched element, add it to the list.  */
       while (i-- > 0)
@@ -3152,7 +3161,10 @@
             else
               {
                 /* We got a chain of items.  Attach them.  */
-                (*newp)->next = found;
+                if (*newp)
+                  (*newp)->next = found;
+                else
+                  *newp = found;
 
                 /* Find and set the new end.  Massage names if necessary.  */
                 while (1)
@@ -3174,7 +3186,8 @@
 #endif /* !NO_ARCHIVES */
           NEWELT (concat (2, prefix, nlist[i]));
 
-      globfree (&gl);
+      if (globme)
+        globfree (&gl);
 
 #ifndef NO_ARCHIVES
       if (arname)
--- make.orig/remake.c	2010-07-13 03:20:42.000000000 +0200
+++ make/remake.c	2012-09-19 17:26:09.116270849 +0200
@@ -614,6 +614,10 @@
                 d->file->dontcare = file->dontcare;
               }
 
+            /* We may have already considered this file, when we didn't know
+               we'd need to update it.  Force update_file() to consider it and
+               not prune it.  */
+            d->file->considered = !considered;
 
 	    dep_status |= update_file (d->file, depth);
 
