Path: 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: Date: 9 Oct 89 14:02:45 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 803 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 - # 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 - # endif /* USG. */ - - #endif /* USGr3 or DIRENT. */ - - /* Hash table of directories. */ --- 18,24 ---- #include "make.h" + #include "dir.h" + #include /* 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 + #define D_NAMLEN(d) ((d)->d_namlen) + + #else /* Not Xenix */ + + #if defined(USGr3) || defined(DIRENT) + + #include + # 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 + # 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 - #if defined(USGr3) || defined(DIRENT) - - #include - # 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 - # endif /* USG. */ - - #endif /* USGr3 or DIRENT. */ - #ifdef USG #include --- 21,26 ---- #include + #include "dir.h" #ifdef USG #include 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')