Submitted By:            William Harrington at <kb0iic at cross-lfs dot org>
Date:                    2013-08-01
Initial Package Version: 3.82
Upstream Status:         Fixed Upstream
Origin:                  Upstream
Description:             Several bug fixes from upstream git

diff -Naur make-3.82.orig/expand.c make-3.82/expand.c
--- make-3.82.orig/expand.c	2010-07-13 01:20:39.000000000 +0000
+++ make-3.82/expand.c	2013-08-01 20:44:22.773645293 +0000
@@ -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);
diff -Naur make-3.82.orig/function.c make-3.82/function.c
--- make-3.82.orig/function.c	2010-07-13 01:20:39.000000000 +0000
+++ make-3.82/function.c	2013-08-01 20:45:09.100176320 +0000
@@ -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];
diff -Naur make-3.82.orig/job.c make-3.82/job.c
--- make-3.82.orig/job.c	2010-07-24 08:27:50.000000000 +0000
+++ make-3.82/job.c	2013-08-01 20:44:54.400222908 +0000
@@ -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.  */
diff -Naur make-3.82.orig/main.c make-3.82/main.c
--- make-3.82.orig/main.c	2010-07-19 07:10:53.000000000 +0000
+++ make-3.82/main.c	2013-08-01 20:45:20.540147980 +0000
@@ -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
@@ -2093,7 +2093,7 @@
             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))
diff -Naur make-3.82.orig/read.c make-3.82/read.c
--- make-3.82.orig/read.c	2010-07-13 01:20:42.000000000 +0000
+++ make-3.82/read.c	2013-08-01 20:44:39.690263962 +0000
@@ -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)
