Article View: gnu.utils.bug
Article #478Make 3.56: Xenix patches and bug fixes
From: Chip Salzenberg
Date: Mon, 09 Oct 1989 14:02
Date: Mon, 09 Oct 1989 14:02
803 lines
20595 bytes
20595 bytes
Patches to GNU Make 3.56. I really hope that these will be adopted into
the official GNU Make release, since there are a _lot_ of Xenix users out
there, and I'm tired of porting each Make version. (:-))
Features:
Port to SCO Xenix/386.
Create new "dir.h" header, used for opendir() readdir() etc.
Use Doug Gwyn's getcwd() replacement. It's faster, and unlike
the Xenix one, it doesn't break when SIGCLD is being caught.
Support a command prefix (default: "\t" unless "-n" flag specified).
Prefix is printed before each command.
Pass all variables in the child environment only if VARS_IN_ENV is
defined. (Otherwise large variables overwhelm the environment.)
Perhaps the default should be the current behavior; that's a
small change.
Bug fixes:
Fix core dump bug when NO_ARCHIVES is defined --
$@ was being defined to an uninitialized pointer.
Fix handling of multiple job slots --
but it's still not completely right.
Fix creation of MFLAGS and MAKEFLAGS in presence of multiple job slots --
the presence of "-j" lopped off the rest of the flags.
Change update_status to a short, since many compilers don't support
signed bitfields.
Line buffer standard output, so output of multiple makes processes
interleave correctly.
Fix core dump bug when numeric option has the value omitted.
# This file contains patches for GNU Make 3.56.
# (Be sure to use the "-p" option of patch.)
# Patches are enclosed for the following file(s):
# commands.c
# dir.c
# dir.h
# file.c
# file.h
# function.c
# glob.c
# job.c
# main.c
# make.h
# remake.c
# variable.c
Index: commands.c
***************
*** 120,124 ****
/* If the target is an archive member `lib(member)',
then $@ is `lib' and $% is `member'. */
-
if (ar_name (file->name))
{
--- 120,123 ----
***************
*** 129,132 ****
--- 128,132 ----
}
else
+ #endif
{
at = savestring (file->name, strlen (file->name));
***************
*** 133,137 ****
percent = "";
}
- #endif
DEFINE_VARIABLE ("@", 1, at);
--- 133,136 ----
***************
*** 335,353 ****
}
- /* First set the automatic variables according to this file. */
-
- initialize_file_variables (file);
-
- set_file_variables (file);
-
/* Chop the commands up into lines. */
if (cmds->command_lines == 0)
chop_commands (cmds);
if (job_slots > 0)
! /* Wait for a job slot to be freed up. */
! while (job_slots_used == job_slots)
! wait_for_children (1, 0);
/* Start the command sequence, record it in a new
`struct child', and add that to the chain. */
--- 334,355 ----
}
/* Chop the commands up into lines. */
+
if (cmds->command_lines == 0)
chop_commands (cmds);
+ /* Wait for a job slot to be freed up. */
+
if (job_slots > 0)
! {
! while (job_slots_used == job_slots)
! wait_for_children (1, 0);
! }
+ /* Set the automatic variables according to this file. */
+
+ initialize_file_variables (file);
+ set_file_variables (file);
+
/* Start the command sequence, record it in a new
`struct child', and add that to the chain. */
***************
*** 370,383 ****
}
! unblock_children ();
!
! if (status)
{
free (c->commands);
free ((char *) c);
-
file->update_status = (just_print_flag || touch_flag) ? 0 : 1;
}
! else if (job_slots == 1)
{
/* Since there is only one job slot, make things run linearly.
--- 372,387 ----
}
! if (status == 0)
! file->update_status = 0;
! else
{
free (c->commands);
free ((char *) c);
file->update_status = (just_print_flag || touch_flag) ? 0 : 1;
}
!
! unblock_children ();
!
! if (status == 0 && job_slots == 1)
{
/* Since there is only one job slot, make things run linearly.
***************
*** 385,390 ****
while (file->command_state != cs_finished)
wait_for_children (1, 0);
-
}
notice_finished_file (file);
}
--- 389,394 ----
while (file->command_state != cs_finished)
wait_for_children (1, 0);
}
+
notice_finished_file (file);
}
Index: dir.c
***************
*** 18,43 ****
#include "make.h"
- #if defined(USGr3) || defined(DIRENT)
-
- #include <dirent.h>
- # if !defined(d_ino) && !defined(d_fileno)
- #define d_ino d_fileno
- # endif
- #define direct dirent
- #define D_NAMLEN(d) strlen((d)->d_name)
-
- #else /* Not USGr3 and not DIRENT. */
-
- #define D_NAMLEN(d) ((d)->d_namlen)
- # ifdef USG
- #include "ndir.h" /* Get ndir.h from the Emacs distribution. */
- # else /* Not USG. */
- #include <sys/dir.h>
- # endif /* USG. */
-
- #endif /* USGr3 or DIRENT. */
-
-
/* Hash table of directories. */
--- 18,24 ----
#include "make.h"
+ #include "dir.h"
+ #include <errno.h>
/* Hash table of directories. */
***************
*** 385,386 ****
--- 366,556 ----
printf (" impossibilities in %u directories.\n", dirs);
}
+
+ /*
+ getcurdir -- get current working directory name
+ (compatible with POSIX and SVID getcwd())
+
+ last edit: 21-Sep-1987 D A Gwyn
+
+ This public-domain getcurdir() routine can be used to replace the UNIX
+ System V library routine (which uses popen() to capture the output of
+ the "pwd" command). Once that is done, "pwd" can be reimplemented as
+ just puts(getcurdir()).
+
+ This implementation depends on every directory having entries for
+ "." and "..". It also depends on the internals of the readdir()
+ data structures to some degree.
+
+ I considered using chdir() to ascend the hierarchy, followed by a
+ final chdir() to the path being returned by getcurdir() to restore the
+ location, but decided that error recovery was too difficult that way.
+ The algorithm I settled on was inspired by my rewrite of the "pwd"
+ utility, combined with the dotdots[] array trick from the SVR2 shell.
+ */
+
+ char *
+ getcurdir(buf, size) /* returns pointer to CWD pathname */
+ char *buf; /* where to put name (NULL to malloc) */
+ int size; /* size of buf[] or malloc()ed memory */
+ {
+ static char dotdots[] =
+ "../../../../../../../../../../../../../../../../../../../../../../../../../..";
+ char *dotdot; /* -> dotdots[.], right to left */
+ DIR *dirp; /* -> parent directory stream */
+ struct direct *dir; /* -> directory entry */
+ struct stat stat1,
+ stat2; /* info from stat() */
+ struct stat *d = &stat1; /* -> info about "." */
+ struct stat *dd = &stat2; /* -> info about ".." */
+ register char *buffer; /* local copy of buf, or malloc()ed */
+ char *bufend; /* -> buffer[size] */
+ register char *endp; /* -> end of reversed string */
+ register char *dname; /* entry name ("" for root) */
+ int serrno = errno; /* save entry errno */
+
+ if (size == 0)
+ {
+ errno = EINVAL; /* invalid argument */
+ return NULL;
+ }
+
+ if ((buffer = buf) == NULL /* wants us to malloc() the string */
+ && (buffer = (char *) malloc((unsigned) size)) == NULL)
+ {
+ errno = ENOMEM; /* cannot malloc() specified size */
+ return NULL;
+ }
+
+ if (stat(".", dd) != 0) /* prime the pump */
+ goto error; /* errno already set */
+
+ endp = buffer; /* initially, empty string */
+ bufend = &buffer[size];
+
+ for (dotdot = &dotdots[sizeof(dotdots)]; dotdot != dotdots;)
+ {
+ /* include one more "/.." section */
+ /* (first time is actually "..") */
+ dotdot -= 3;
+
+ /* swap stat() info buffers */
+ {
+ register struct stat *temp = d;
+
+ d = dd; /* new current dir is old parent dir */
+ dd = temp;
+ }
+
+ if ((dirp = opendir(dotdot)) == NULL) /* new parent */
+ goto error; /* errno already set */
+
+ if (fstat(dirp->dd_fd, dd) != 0)
+ {
+ serrno = errno; /* set by fstat() */
+ (void) closedir(dirp);
+ errno = serrno; /* in case closedir() clobbered it */
+ goto error;
+ }
+
+ if (d->st_dev == dd->st_dev)
+ {
+ /* not crossing a mount point */
+
+ if (d->st_ino == dd->st_ino)
+ {
+ /* root directory */
+ dname = "";
+ goto append;
+ }
+
+ do
+ {
+ if ((dir = readdir(dirp)) == NULL)
+ {
+ (void) closedir(dirp);
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+ } while (dir->d_ino != d->st_ino);
+ }
+ else
+ { /* crossing a mount point */
+ struct stat t; /* info re. test entry */
+ char name[sizeof(dotdots) + 1 + MAXNAMLEN];
+
+ (void) strcpy(name, dotdot);
+ dname = &name[strlen(name)];
+ *dname++ = '/';
+
+ do
+ {
+ if ((dir = readdir(dirp)) == NULL)
+ {
+ (void) closedir(dirp);
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+
+ (void) strcpy(dname, dir->d_name);
+ /* must fit if MAXNAMLEN is not a lie */
+ } while (stat(name, &t) != 0
+ || t.st_ino != d->st_ino
+ || t.st_dev != d->st_dev);
+ }
+
+ dname = dir->d_name;
+
+ /* append "/" and reversed dname string onto buffer */
+ append:
+ if (endp != buffer /* avoid trailing / in final name */
+ || dname[0] == '\0' /* but allow "/" when CWD is root */
+ )
+ *endp++ = '/';
+
+ {
+ register char *app; /* traverses dname string */
+
+ for (app = dname; *app != '\0'; ++app)
+ ;
+
+ if (app - dname >= bufend - endp)
+ {
+ (void) closedir(dirp);
+ errno = ERANGE; /* won't fit allotted space */
+ goto error;
+ }
+
+ while (app != dname)
+ *endp++ = *--app;
+ }
+
+ (void) closedir(dirp);
+
+ if (dname[0] == '\0')
+ { /* reached root; wrap it up */
+ register char *startp; /* -> buffer[.] */
+
+ *endp = '\0'; /* plant null terminator */
+
+ /* straighten out reversed pathname string */
+ for (startp = buffer; --endp > startp; ++startp)
+ {
+ char temp = *endp;
+
+ *endp = *startp;
+ *startp = temp;
+ }
+
+ errno = serrno; /* restore entry errno */
+ return buffer;
+ }
+ }
+
+ errno = ENOMEM; /* actually, algorithm failure */
+
+ error:
+ if (buf == NULL)
+ free((char *) buffer);
+
+ return NULL;
+ }
Index: dir.h
***************
*** 1,0 ****
--- 1,45 ----
+ /* Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+ This file is part of GNU Make.
+
+ GNU Make is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GNU Make is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Make; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #if defined(M_XENIX)
+
+ #include <sys/ndir.h>
+ #define D_NAMLEN(d) ((d)->d_namlen)
+
+ #else /* Not Xenix */
+
+ #if defined(USGr3) || defined(DIRENT)
+
+ #include <dirent.h>
+ # if !defined(d_ino) && !defined(d_fileno)
+ #define d_ino d_fileno
+ # endif
+ #define direct dirent
+ #define D_NAMLEN(d) strlen((d)->d_name)
+
+ #else /* Not Xenix, not USGr3 and not DIRENT. */
+
+ #define D_NAMLEN(d) ((d)->d_namlen)
+ # ifdef USG
+ #include "ndir.h" /* Get ndir.h from the Emacs distribution. */
+ # else /* Not USG. */
+ #include <sys/dir.h>
+ # endif /* USG. */
+
+ #endif /* USGr3 or DIRENT. */
+
+ #endif /* Xenix */
Index: file.c
***************
*** 225,228 ****
--- 225,229 ----
else if (!silent_flag && !just_print_flag)
{
+ fputs (command_prefix, stdout);
if (!doneany)
{
Index: file.h
***************
*** 51,55 ****
} command_state ENUM_BITFIELD (2);
! int update_status:2; /* Status of the last attempt to update,
or -1 if none has been made. */
unsigned int double_colon:1;/* Nonzero for double-colon entry */
--- 51,55 ----
} command_state ENUM_BITFIELD (2);
! short update_status; /* Status of the last attempt to update,
or -1 if none has been made. */
unsigned int double_colon:1;/* Nonzero for double-colon entry */
Index: function.c
***************
*** 420,428 ****
newlines in its output with spaces, and put
that in the variable output buffer. */
! if (buffer[i - 1] == '\n')
--i;
! for (p = buffer; p < buffer + i; ++p)
! if (*p == '\n')
! *p = ' ';
o = variable_buffer_output (o, buffer, i);
}
--- 420,428 ----
newlines in its output with spaces, and put
that in the variable output buffer. */
! if (i > 0 && buffer[i - 1] == '\n')
--i;
! buffer[i] = '\0';
! for (p = buffer; (p = index(p, '\n')) != NULL; ++p)
! *p = ' ';
o = variable_buffer_output (o, buffer, i);
}
Index: glob.c
***************
*** 21,45 ****
#include <sys/types.h>
- #if defined(USGr3) || defined(DIRENT)
-
- #include <dirent.h>
- # if !defined(d_ino) && !defined(d_fileno)
- #define d_ino d_fileno
- # endif
- #define direct dirent
- #define D_NAMLEN(d) strlen((d)->d_name)
-
- #else /* Not USGr3 and not DIRENT. */
-
- #define D_NAMLEN(d) ((d)->d_namlen)
- # ifdef USG
- #include "ndir.h" /* Get ndir.h from the Emacs distribution. */
- # else /* Not USG. */
- #include <sys/dir.h>
- # endif /* USG. */
-
- #endif /* USGr3 or DIRENT. */
-
#ifdef USG
#include <memory.h>
--- 21,26 ----
#include <sys/types.h>
+ #include "dir.h"
#ifdef USG
#include <memory.h>
Index: job.c
***************
*** 489,493 ****
if (just_print_flag || (!noprint && !silent_flag))
! puts (p);
/* If -n was given, recurse to get the next line in the sequence. */
--- 489,496 ----
if (just_print_flag || (!noprint && !silent_flag))
! {
! fputs (command_prefix, stdout);
! puts (p);
! }
/* If -n was given, recurse to get the next line in the sequence. */
Index: main.c
***************
*** 247,250 ****
--- 247,254 ----
char *program;
+ /* The string to print before each command. */
+
+ char *command_prefix = "\t";
+
/* Value of the MAKELEVEL variable at startup (or 0). */
***************
*** 332,335 ****
--- 336,351 ----
#endif
+ /* Line buffer stdout. */
+
+ #ifdef USGr3
+ setvbuf(stdout, (char *)0, _IOLBF, BUFSIZ);
+ #else
+ #ifdef USG
+ setvbuf(stdout, _IOLBF, (char *)0, BUFSIZ);
+ #else
+ setlinebuf(stdout);
+ #endif
+ #endif
+
/* Figure out where this program lives. */
***************
*** 376,379 ****
--- 392,400 ----
print_version ();
+ /* If we're just printing commands, then we omit the prefix. */
+
+ if (just_print_flag)
+ command_prefix = "";
+
/* Construct the list of include directories to search. */
***************
*** 909,913 ****
break;
case string:
! if (*sw == '\0')
arg = argv[++i];
else
--- 930,934 ----
break;
case string:
! if ((*sw == '\0') && (i + 1) < argc)
arg = argv[++i];
else
***************
*** 943,947 ****
case positive_int:
! if (*sw == '\0')
arg = argv[++i];
else
--- 964,968 ----
case positive_int:
! if ((*sw == '\0') && (i + 1) < argc)
arg = argv[++i];
else
***************
*** 979,983 ****
case floating:
! if (*sw == '\0')
arg = argv[++i];
else
--- 1000,1004 ----
case floating:
! if ((*sw == '\0') && (i + 1) < argc)
arg = argv[++i];
else
***************
*** 1108,1115 ****
i = 0;
- flags[i++] = '-';
for (cs = switches; cs->c != '\0'; ++cs)
! if (cs->toenv)
switch (cs->type)
{
--- 1129,1139 ----
i = 0;
for (cs = switches; cs->c != '\0'; ++cs)
! {
! if (! cs->toenv)
! continue;
! if (i == 0 || flags[i - 1] == ' ')
! flags[i++] = '-';
switch (cs->type)
{
***************
*** 1142,1153 ****
{
strcpy (&flags[i], "j1 ");
! i += 5;
}
else
{
! char *p = &flags[i];
! sprintf (p, "%c%u ", cs->c,
*(unsigned int *) cs->value_ptr);
! i += strlen (p);
}
}
--- 1166,1176 ----
{
strcpy (&flags[i], "j1 ");
! i += strlen (&flags[i]);
}
else
{
! sprintf (&flags[i], "%c%u ", cs->c,
*(unsigned int *) cs->value_ptr);
! i += strlen (&flags[i]);
}
}
***************
*** 1174,1177 ****
--- 1197,1201 ----
break;
}
+ }
if (i == 0)
Index: make.h
***************
*** 89,92 ****
--- 89,93 ----
extern struct dep *copy_dep_chain ();
extern char *find_percent ();
+ extern char *getcurdir ();
#ifndef NO_ARCHIVES
***************
*** 131,142 ****
extern char **environ;
! #ifdef USG
! extern char *getcwd ();
! #define getwd(buf) getcwd (buf, MAXPATHLEN - 2)
! #else /* Not USG. */
! extern char *getwd ();
! #endif /* USG. */
-
extern char *reading_filename;
extern unsigned int *reading_lineno_ptr;
--- 132,137 ----
extern char **environ;
! #define getwd(buf) getcurdir (buf, MAXPATHLEN - 2)
extern char *reading_filename;
extern unsigned int *reading_lineno_ptr;
***************
*** 151,154 ****
--- 146,150 ----
extern char *program;
+ extern char *command_prefix;
extern unsigned int makelevel;
Index: remake.c
***************
*** 578,582 ****
if (!silent_flag)
{
! printf ("touch %s\n", file->name);
fflush (stdout);
}
--- 578,585 ----
if (!silent_flag)
{
! fputs (command_prefix, stdout);
! fputs ("touch ", stdout);
! fputs (file->name, stdout);
! fputc ('\n', stdout);
fflush (stdout);
}
***************
*** 630,633 ****
--- 633,638 ----
struct file *file;
{
+ int has_commands = 0;
+
if (file->cmds == 0 && !(touch_flag && !file->is_target))
{
***************
*** 664,672 ****
}
else
! execute_file_commands (file);
}
! file->command_state = cs_finished;
! notice_finished_file (file);
}
--- 669,683 ----
}
else
! {
! execute_file_commands (file);
! has_commands = 1;
! }
}
! if (!has_commands)
! {
! file->command_state = cs_finished;
! notice_finished_file (file);
! }
}
Index: variable.c
***************
*** 383,389 ****
register char *p = v->name;
! if (v->origin == o_default
! || streq (p, "MAKELEVEL"))
continue;
if (*p != '_' && (*p < 'A' || *p > 'Z')
--- 383,395 ----
register char *p = v->name;
! #ifdef VARS_IN_ENV
! if (v->origin == o_default)
continue;
+ #else
+ if ((v->origin != o_env) && (v->origin != o_env_override))
+ continue;
+ #endif
+ if (streq (p, "MAKELEVEL"))
+ continue;
if (*p != '_' && (*p < 'A' || *p > 'Z')
Technical Details
Message-ID:
<m0gE0aU-0006HMC@ateng.ateng.com>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!ateng.ateng.com!chipShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!ateng.ateng.com!chip From: chip@ateng.ateng.com (Chip Salzenberg) Newsgroups: gnu.utils.bug Subject: Make 3.56: Xenix patches and bug fixes Message-ID: <m0gE0aU-0006HMC@ateng.ateng.com> Date: 9 Oct 89 14:02:45 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 803