[gnu.utils.bug] Make 3.05 bugs and semi-fixes.

jay@UUNET.UU.NET (Jay Schuster) (11/01/88)

Hope this helps the effort.

Jay Schuster				uunet!uvm-gen!banzai!jay
The People's Computer Company		`Revolutionary Programming'

What follows are diff's from when we tried to get GNU make version 3.05
working on our Sys5r2 machine.  They represent fixes to the following
problems:

    O_RDONLY, etc. are in <fcntl.h> not <sys/file.h>, and <sys/file.h>
    doesn't have anything necessary that <fcntl.h> doesn't provide.

    Some #ifdef USG's for bcopy(), bcmp(), <memory.h>, and for what
    wait() returns and how to tell if how what was waited for terminated.

    In our archives, filenames have a trailing slash.  So in addition
    to wiping out the trailing spaces, I wipe out the trailing slashes as
    well.  I do not know if that is just our system, or a general Sys5ism.

    In our make, $?, when used in the commands associated with building
    an archive, expands to the member .o files, and not archive.a(member.o).
    I added code to do this, and to change $^ similarly.

    Sometimes xmalloc() was being called with zero, and then the space
    allocated was written into.  I changed it to always allocate at
    least one character.  This happened in both glob.c and commands.c.

    SIGINT, SIGHUP, and SIGQUIT should remain ignored if they were
    ignored upon entrance.

    In read.c, the name of the included file being read was being freed
    when it still had references to it, causing -p to print out garbage
    as to where the rules came from.

    In read.c, there were two if statements following each other that
    were redundant.  It looked like one of them could have been removed.

    maxsuffix was being calculated after it was used.  I moved the
    calculation out of the function count_implicit_rule_limits() and
    into convert_to_pattern(), but left the declaration global.

    When converting the .X.a rules, savestring was being called with
    an incorrect argument.

    install_default_pattern_rules() was *always* replacing the current
    suffix rules with the defaults, thus overriding and .c.o, etc. rules
    you had in your makefiles.

    In new_environ(), when loading in the new environment, vcnt was
    being incremented regardless of whether an environment entry was
    loaded, leading to a hole in the environment.  The amount of space
    being allocated still can be one entry too large, because the counting
    loop doesn't take into account an entry might be skipped.

    In remake.c, I added a change to partially implement a common SysVism.
    Often, in library makefiles, we do something like the following:

    .c.a: ;

    $(LIB): $(LIB)(foo.o) $(LIB)(bar.o)
	    $(CC) -c $(CFLAGS) $(?:.o=.c)
	    ar rv $(LIB) $?
	    rm $?
    
    This has the effect of only invoking the c compiler once, and only
    invoking ar once, a big win.

    Unfortunately, make -n shows the correct output, but a true make
    does not.  Apparently, make was thinking that it executed a command,
    so it was updating its internal status as to when the file was
    modified, believing it had remade the file.


UNRESOLVED PROBLEMS

    Duplicates in the .SUFFIXES list will cause make to do bizarre things
    and eventually dump core.  This is triggered most commonly by adding
    a .c into the SUFFIXES list.

    With the library hack above, if I change the rule to a double-colon
    rule, and add the following:

    .c.a: ;
    .y.a: ;

    $(LIB):: $(LIB)(foo.o) $(LIB)(bar.o)
	    $(CC) -c $(CFLAGS) $(?:.o=.c)
	    ar rv $(LIB) $?
	    rm $?

    $(LIB):: $(LIB)(parse.o)
	    $(MAKE) $(?:.o=.y)
	    ar rv $(LIB) $?
	    rm $?
    
    Make dumps core.

THINGS YOU CAN IGNORE

    We added a tab to print before echoing the command that gets executed.
    It was easier to leave it in this diff than to take it out and have all
    the line numbers be off.


DESIRES:

    I would really like it if make did an implicit `make Makefile' if it
    couldn't find one in the current directory.


Here's the diff:

*** arscan.c~	Sat Apr 30 03:22:40 1988
--- arscan.c	Wed Oct  5 14:58:11 1988
***************
*** 82,90 ****
   what you give them.   Help stamp out software-hoarding!  */
  
  #include <ar.h>
- #include <sys/file.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  
  /* Takes three arguments ARCHIVE, FUNCTION and ARG.
  
--- 82,97 ----
   what you give them.   Help stamp out software-hoarding!  */
  
  #include <ar.h>
  #include <sys/types.h>
  #include <sys/stat.h>
+ #ifdef USG
+ #include <fcntl.h>
+ #include <memory.h>
+ #define bcopy(s, d, n) memcpy ((d), (s), (n))
+ #define bcmp(s1, s2, cnt) memcmp((s1), (s2), (cnt))
+ #else /* not USG */
+ #include <sys/file.h>
+ #endif /* not USG */
  
  /* Takes three arguments ARCHIVE, FUNCTION and ARG.
  
***************
*** 162,169 ****
  	  }
  	bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
  	{
  	  register char *p = name + sizeof member_header.ar_name;
! 	  while (p > name && *--p == ' ') *p = 0;
  	}
  
  	sscanf (member_header.ar_mode, "%o", &eltmode);
--- 169,177 ----
  	  }
  	bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
  	{
+ 	  /* Remove trailing spaces (all) and slashes (SystemV) */
  	  register char *p = name + sizeof member_header.ar_name;
! 	  while (p > name && (*--p == ' ' || *p == '/')) *p = 0;
  	}
  
  	sscanf (member_header.ar_mode, "%o", &eltmode);
*** commands.c~	Wed Aug 10 00:15:11 1988
--- commands.c	Wed Oct  5 18:16:40 1988
***************
*** 18,31 ****
  #include "commands.h"
  #include "file.h"
  #include "variable.h"
- #include <sys/wait.h>
- 
  
  #ifdef	USG
  #define	vfork		fork
  #define	VFORK_NAME	"fork"
  #else	/* not USG	*/
  #define	VFORK_NAME	"vfork"
  #endif	/* USG		*/
  
  extern int vfork (), execvp (), wait (), kill (), getpid ();
--- 18,40 ----
  #include "commands.h"
  #include "file.h"
  #include "variable.h"
  
  #ifdef	USG
  #define	vfork		fork
  #define	VFORK_NAME	"fork"
+ #define	WAITTYPE	int
+ #define	WIFEXITED(status)	(((status)&0xff)==0)
+ #define	WIFEXITretcode(status)	(((status)>>8)&0xff)
+ #define	WIFSIGNALED(status)	(((status)&0xff)!=0)
+ #define	WIFSIGNALtermsig(status)	((status)&0x7f)
+ #define	WIFSIGNALcoredump(status)	((status)&0x80)
  #else	/* not USG	*/
+ #include <sys/wait.h>
  #define	VFORK_NAME	"vfork"
+ #define	WAITTYPE	union wait
+ #define	WIFEXITretcode(status)	(status.w_retcode)
+ #define	WIFSIGNALtermsig(status)	(status.w_termsig)
+ #define	WIFSIGNALcoredump(status)	(status.w_coredump)
  #endif	/* USG		*/
  
  extern int vfork (), execvp (), wait (), kill (), getpid ();
***************
*** 165,171 ****
  #undef	FILEONLY
  #undef	DIRONLY
  
!   /* Compute the values for $^ and $?.  */
  
    {
      register unsigned int dep_size = 0, c_size = 0;
--- 174,183 ----
  #undef	FILEONLY
  #undef	DIRONLY
  
!   /* Compute the values for $^ and $?.
!      In SystemV, if $? is a list of archive members `lib(member)'',
!      then $? is the list of `member''s.  We do a similar thing with
!      $^ */
  
    {
      register unsigned int dep_size = 0, c_size = 0;
***************
*** 174,187 ****
  
      for (d = file->deps; d != 0; d = d->next)
        {
! 	register unsigned int i = strlen (dep_name (d)) + 1;
  	c_size += i;
  	if (d->changed)
  	  dep_size += i;
        }
  
!     line = (char *) xmalloc (dep_size);
!     cline = (char *) xmalloc (c_size);
      *line = *cline = '\0';
  
      if (c_size > 0 && dep_size > 0)
--- 186,205 ----
  
      for (d = file->deps; d != 0; d = d->next)
        {
! 	register unsigned int i;
! 
! 	if (ar_name (dep_name(d)))
! 	  i = strlen (1 + index (dep_name(d), '('));
! 	else
! 	  i = strlen (dep_name (d)) + 1;
! 
  	c_size += i;
  	if (d->changed)
  	  dep_size += i;
        }
  
!     line = (char *) xmalloc (dep_size == 0 ? 1 : dep_size);
!     cline = (char *) xmalloc (c_size == 0 ? 1 : c_size);
      *line = *cline = '\0';
  
      if (c_size > 0 && dep_size > 0)
***************
*** 190,201 ****
  	for (d = file->deps; d != 0; d = d->next)
  	  {
  	    unsigned int len = strlen (dep_name (d));
! 	    bcopy (dep_name (d), cp, len);
  	    cp += len;
  	    *cp++ = ' ';
  	    if (d->changed)
  	      {
! 		bcopy (dep_name (d), lp, len);
  		lp += len;
  		*lp++ = ' ';
  	      }
--- 208,227 ----
  	for (d = file->deps; d != 0; d = d->next)
  	  {
  	    unsigned int len = strlen (dep_name (d));
! 	    char *dep = dep_name(d);
! 
! 	    if (ar_name (dep))
! 	      {
! 	        dep = (1 + index (dep, '('));
! 		len = strlen (dep) - 1;
! 	      }
! 
! 	    bcopy (dep, cp, len);
  	    cp += len;
  	    *cp++ = ' ';
  	    if (d->changed)
  	      {
! 		bcopy (dep, lp, len);
  		lp += len;
  		*lp++ = ' ';
  	      }
***************
*** 286,291 ****
--- 312,318 ----
  
        if (just_print_flag || (!silent_flag && !noprint))
  	{
+ 	  putchar ('\t');
  	  puts (line);
  	  fflush (stdout);
  	}
***************
*** 357,363 ****
    register char *ap;
    char *end;
    int instring;
!   union wait status;
    int pid;
    char **new_argv;
  
--- 384,390 ----
    register char *ap;
    char *end;
    int instring;
!   WAITTYPE status;
    int pid;
    char **new_argv;
  
***************
*** 499,505 ****
        else if (wpid != pid)
  	continue;
        else if (WIFEXITED (status))
! 	return (status.w_retcode);
        else if (WIFSIGNALED (status))
  	{
  	  int s;
--- 526,532 ----
        else if (wpid != pid)
  	continue;
        else if (WIFEXITED (status))
! 	return (WIFEXITretcode(status));
        else if (WIFSIGNALED (status))
  	{
  	  int s;
***************
*** 519,526 ****
  
  	  /* Treat this as failure.  */
  
! 	  s = status.w_termsig | SIGNAL_STATUS;
! 	  if (status.w_coredump)
  	    s |= SIGNAL_COREDUMP;
  	  return s;
  	}
--- 546,553 ----
  
  	  /* Treat this as failure.  */
  
! 	  s = WIFSIGNALtermsig(status) | SIGNAL_STATUS;
! 	  if (WIFSIGNALcoredump(status))
  	    s |= SIGNAL_COREDUMP;
  	  return s;
  	}
*** make.c~	Sun Aug 21 00:36:52 1988
--- make.c	Wed Oct  5 16:27:54 1988
***************
*** 235,243 ****
    reading_filename = 0;
    reading_lineno_ptr = 0;
    
!   signal (SIGHUP, fatal_error_signal);
!   signal (SIGQUIT, fatal_error_signal);
!   signal (SIGINT, fatal_error_signal);
    signal (SIGILL, fatal_error_signal);
    signal (SIGTRAP, fatal_error_signal);
    signal (SIGIOT, fatal_error_signal);
--- 235,246 ----
    reading_filename = 0;
    reading_lineno_ptr = 0;
    
!   if (SIG_IGN != signal (SIGHUP, SIG_IGN))
!     signal (SIGHUP, fatal_error_signal);
!   if (SIG_IGN != signal (SIGQUIT, SIG_IGN))
!     signal (SIGQUIT, fatal_error_signal);
!   if (SIG_IGN != signal (SIGINT, SIG_IGN))
!     signal (SIGINT, fatal_error_signal);
    signal (SIGILL, fatal_error_signal);
    signal (SIGTRAP, fatal_error_signal);
    signal (SIGIOT, fatal_error_signal);
*** read.c~	Mon Sep  5 20:15:45 1988
--- read.c	Wed Oct  5 16:16:29 1988
***************
*** 320,326 ****
  	  p = variable_expand (p);
  	  p = savestring (p, strlen (p));
  	  read_makefile (p, 1, 1);
! 	  free (p);
  	  conditionals = save;
  	  continue;
  	}
--- 320,326 ----
  	  p = variable_expand (p);
  	  p = savestring (p, strlen (p));
  	  read_makefile (p, 1, 1);
! 	  /* Don't free (p); because commands point to it. */
  	  conditionals = save;
  	  continue;
  	}
***************
*** 943,949 ****
  	     even if the file already has one.  */
  	  f = lookup_file (name);
  	  if (f != 0 && !f->double_colon)
- 	  if (!f->double_colon)
  	    fatal ("target file `%s' has both : and :: entries", f->name);
  	  f = enter_file (name);
  	  f->double_colon = 1;
--- 943,948 ----
*** remake.c~	Sat Sep  3 22:12:53 1988
--- remake.c	Fri Oct 14 21:28:53 1988
***************
*** 17,23 ****
--- 17,27 ----
  #include "commands.h"
  #include "dep.h"
  #include "file.h"
+ #ifdef USG
+ #include <fcntl.h>
+ #else /* !USG */
  #include <sys/file.h>
+ #endif
  
  
  extern int open (), fstat (), read (), lseek (), write (), close ();
***************
*** 360,367 ****
--- 364,393 ----
      status = execute_file_commands (file);
  
    file->update_status = status;
+   /* If the command we just tried to execute was empty, pretend that
+      we did something anyway.  This way things that depended on this
+      file get updated as well.  This is a hack, and not correct, but it
+      will make the efficient library update method work. */
+   {
+     if (just_print_flag)
+       file->last_mtime = time ((time_t *) 0);
+     else {
+       if (file->cmds != 0) {
+         char *p;
+         for (p = file->cmds->commands; *p != '\0'; ++p)
+           if (*p != ' ' && *p != '\t' && *p != '\n')
+             break;
+         file->last_mtime = (*p == '\0')
+                          ? time ((time_t *) 0) : name_mtime (file->name);
+       }
+       else
+         file->last_mtime = name_mtime (file->name);
+     }
+   }
+   /*
    file->last_mtime = just_print_flag
                       ? time ((time_t *) 0) : name_mtime (file->name);
+   */
    file->updated = 1;
  
    if (file->also_make != 0)
*** rule.c~	Mon Sep  5 20:25:40 1988
--- rule.c	Wed Oct  5 17:59:49 1988
***************
*** 342,351 ****
    unsigned int deps_found;
  
    /* Names of possible dependencies are constructed in this buffer.  */
!   register char *depname = (char *) alloca (namelen + max_pattern_dep_length);
  
    /* The start and length of the stem of FILENAME for the current rule.  */
!   register char *stem;
    register unsigned int stemlen;
  
    /* Buffer in which we store all the rules that are possibly applicable.  */
--- 342,351 ----
    unsigned int deps_found;
  
    /* Names of possible dependencies are constructed in this buffer.  */
!   /* register */ char *depname = (char *) alloca (namelen + max_pattern_dep_length);
  
    /* The start and length of the stem of FILENAME for the current rule.  */
!   /* register */ char *stem;
    register unsigned int stemlen;
  
    /* Buffer in which we store all the rules that are possibly applicable.  */
***************
*** 812,829 ****
    char *name;
    unsigned int namelen;
    register struct rule *rule, *lastrule;
-   register struct dep *d;
  
-   /* Compute maximum length of all the suffixes.  */
- 
-   maxsuffix = 0;
-   for (d = suffix_file->deps; d != 0; d = d->next)
-     {
-       namelen = strlen (dep_name (d));
-       if (namelen > maxsuffix)
- 	maxsuffix = namelen;
-     }
-   
    num_pattern_rules = 0;
    
    name = 0;
--- 812,818 ----
***************
*** 895,903 ****
  {
    register struct dep *d, *d2, *newd;
    register struct file *f;
!   register char *rulename = (char *) alloca ((maxsuffix * 2) + 1);
    register unsigned int slen, s2len;
    register char *name, **names;
  
    for (d = suffix_file->deps; d != 0; d = d->next)
      {
--- 884,904 ----
  {
    register struct dep *d, *d2, *newd;
    register struct file *f;
!   register char *rulename;
    register unsigned int slen, s2len;
    register char *name, **names;
+   unsigned int namelen;
+ 
+   /* Compute maximum length of all the suffixes.  */
+ 
+   maxsuffix = 0;
+   for (d = suffix_file->deps; d != 0; d = d->next)
+     {
+       namelen = strlen (dep_name (d));
+       if (namelen > maxsuffix)
+ 	maxsuffix = namelen;
+     }
+   rulename = (char *) alloca ((maxsuffix * 2) + 1);
  
    for (d = suffix_file->deps; d != 0; d = d->next)
      {
***************
*** 946,952 ****
  	    {
  	      /* The suffix rule `.X.a:' is converted
  		 to the pattern rule `(%.o): %.X'.  */
! 	      name = savestring ("(%.o)", 4);
  	      newd->name = (char *) xmalloc (1 + s2len + 1);
  	      newd->name[0] = '%';
  	      bcopy (dep_name (d2), newd->name + 1, s2len + 1);
--- 947,953 ----
  	    {
  	      /* The suffix rule `.X.a:' is converted
  		 to the pattern rule `(%.o): %.X'.  */
! 	      name = savestring ("(%.o)", 5);
  	      newd->name = (char *) xmalloc (1 + s2len + 1);
  	      newd->name[0] = '%';
  	      bcopy (dep_name (d2), newd->name + 1, s2len + 1);
***************
*** 1163,1172 ****
    for (s = default_suffix_rules; *s != 0; s += 2)
      {
        register struct file *f = enter_file (s[0]);
!       f->cmds = (struct commands *) xmalloc (sizeof (struct commands));
!       f->cmds->filename = 0;
!       f->cmds->commands = s[1];
!       f->cmds->recursive = 0;
      }
  
    for (s = default_variables; *s != 0; s += 2)
--- 1164,1178 ----
    for (s = default_suffix_rules; *s != 0; s += 2)
      {
        register struct file *f = enter_file (s[0]);
! 
!       /* Don't replace rules already read in from the makefiles */
!       if (f->cmds == 0)
! 	{
! 	  f->cmds = (struct commands *) xmalloc (sizeof (struct commands));
! 	  f->cmds->filename = 0;
! 	  f->cmds->commands = s[1];
! 	  f->cmds->recursive = 0;
! 	}
      }
  
    for (s = default_variables; *s != 0; s += 2)
*** variable.c~	Wed Aug 24 22:30:52 1988
--- variable.c	Mon Oct  3 18:13:28 1988
***************
*** 1384,1391 ****
  		environ[vcnt] = (char *) xmalloc (strlen (v->name)
  						  + strlen (v->value) + 2);
  		sprintf (environ[vcnt], "%s=%s", v->name, v->value);
  	      }
- 	    ++vcnt;
  	  }
        }
  
--- 1384,1391 ----
  		environ[vcnt] = (char *) xmalloc (strlen (v->name)
  						  + strlen (v->value) + 2);
  		sprintf (environ[vcnt], "%s=%s", v->name, v->value);
+ 		++vcnt;
  	      }
  	  }
        }