From a66668aabccfbae3e1f22eaeb897b9c7a1e02733 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Mon, 22 Feb 1999 07:23:30 +0000 Subject: [PATCH] * New feature: .LIBPATTERNS controls the way -lfoo dependencies are expanded. * A few tweaks to the system glob test, after trying it on a system where it's true. * Installed patches to archive handling for AIX 4.3 big archives. * Fix a memory stomp in target-specific variables. * Fix a memory leak in foreach functions. --- ChangeLog | 31 ++++++++ NEWS | 26 ++++--- arscan.c | 198 +++++++++++++++++++++++++++++++++++---------------- configure.in | 11 +-- default.c | 10 +++ function.c | 1 + make.texinfo | 28 +++++++- read.c | 12 +--- remake.c | 137 +++++++++++++++++++++-------------- variable.c | 13 +++- 10 files changed, 324 insertions(+), 143 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd2d73b1..01108a27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +1999-02-22 Paul D. Smith + + * NEWS: Mention new .LIBPATTERNS feature. + + * make.texinfo (Libraries/Search): Describe the use and + ramifications of the new .LIBPATTERNS variable. + + * remake.c (library_search): Instead of searching only for the + hardcoded expansion "libX.a" for a library reference "-lX", we + obtain a list of patterns from the .LIBPATTERNS variable and + search those in order. + + * default.c: Added a new default variable .LIBPATTERNS. The + default for UNIX is "lib%.so lib%.a". Amiga and DOS values are + also provided. + + * read.c: Remove bogus HAVE_GLOB_H references; always include + vanilla glob.h. + +1999-02-21 Paul D. Smith + + * function.c (expand_function): Set value to 0 to avoid freeing it. + * variable.c (pop_variable_scope): Free the value of the variable. + (try_variable_definition): For simple variables, use + allocated_variable_expand() to avoid stomping on the variable + buffer when we still need it for other things. + + * arscan.c: Modified to support AIX 4.3 big archives. The changes + are based on information provided by Phil Adams + ; thanks! + 1999-02-19 Paul D. Smith * configure.in: Check to see if the GNU glob library is already diff --git a/NEWS b/NEWS index 5bc2974f..fcff5f24 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,21 @@ GNU make NEWS -*-indented-text-*- History of user-visible changes. - 19 May 1998 + 22 Feb 1999 -Copyright (C) 1992,1993,1994,1995,1996,1997,1998 Free Software Foundation, Inc. +Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc. See the end for copying conditions. +All changes mentioned here are more fully described in the GNU make +manual, which is contained in this distribution as the file make.texinfo. + Please send GNU make bug reports to bug-make@gnu.org. +Version 3.78 + +* Make defines a new variable, .LIBPATTERNS. This variable controls how + the link library dependency expansion (dependencies like ``-lfoo'') is + performed. + Version 3.77 * Implement BSD make's "?=" variable assignment operator. The variable @@ -659,17 +668,14 @@ Version 3.05 ---------------------------------------------------------------------- Copyright information: -Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. - Permission is granted to anyone to make or distribute verbatim copies of this document as received, in any medium, provided that the - copyright notice and this permission notice are preserved, - thus giving the recipient permission to redistribute in turn. + copyright notice and this permission notice are preserved, thus + giving the recipient permission to redistribute in turn. - Permission is granted to distribute modified versions - of this document, or of portions of it, - under the above conditions, provided also that they - carry prominent notices stating who last changed them. + Permission is granted to distribute modified versions of this + document, or of portions of it, under the above conditions, provided + also that they carry prominent notices stating who last changed them. Local variables: version-control: never diff --git a/arscan.c b/arscan.c index 558cc52f..09d01ad5 100644 --- a/arscan.c +++ b/arscan.c @@ -213,11 +213,28 @@ ar_scan (archive, function, arg) #endif #endif +/* On AIX, define these symbols to be sure to get both archive formats. + AIX 4.3 introduced the "big" archive format to support 64-bit object + files, so on AIX 4.3 systems we need to support both the "normal" and + "big" archive formats. An archive's format is indicated in the + "fl_magic" field of the "FL_HDR" structure. For a normal archive, + this field will be the string defined by the AIAMAG symbol. For a + "big" archive, it will be the string defined by the AIAMAGBIG symbol + (at least on AIX it works this way). + + Note: we'll define these symbols regardless of which AIX version + we're compiling on, but this is okay since we'll use the new symbols + only if they're present. */ +#ifdef _AIX +# define __AR_SMALL__ +# define __AR_BIG__ +#endif + #include /* Cray's apparently defines this. */ #ifndef AR_HDR_SIZE -#define AR_HDR_SIZE (sizeof (struct ar_hdr)) +# define AR_HDR_SIZE (sizeof (struct ar_hdr)) #endif /* Takes three arguments ARCHIVE, FUNCTION and ARG. @@ -255,6 +272,10 @@ ar_scan (archive, function, arg) { #ifdef AIAMAG FL_HDR fl_header; +#ifdef AIAMAGBIG + int big_archive = 0; + FL_HDR_BIG fl_header_big; +#endif #else int long_name = 0; #endif @@ -276,11 +297,42 @@ ar_scan (archive, function, arg) #ifdef AIAMAG { register int nread = read (desc, (char *) &fl_header, FL_HSZ); - if (nread != FL_HSZ || bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG)) + + if (nread != FL_HSZ) { (void) close (desc); return -2; } +#ifdef AIAMAGBIG + /* If this is a "big" archive, then set the flag and + re-read the header into the "big" structure. */ + if (!bcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG)) + { + big_archive = 1; + + /* seek back to beginning of archive */ + if (lseek (desc, 0, 0) < 0) + { + (void) close (desc); + return -2; + } + + /* re-read the header into the "big" structure */ + nread = read (desc, (char *) &fl_header_big, FL_HSZ_BIG); + if (nread != FL_HSZ_BIG) + { + (void) close (desc); + return -2; + } + } + else +#endif + /* Check to make sure this is a "normal" archive. */ + if (bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG)) + { + (void) close (desc); + return -2; + } } #else { @@ -308,8 +360,18 @@ ar_scan (archive, function, arg) long int member_offset; long int last_member_offset; - sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset); - sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset); +#ifdef AIAMAGBIG + if ( big_archive ) + { + sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset); + sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset); + } + else +#endif + { + sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset); + sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset); + } if (member_offset == 0) { @@ -330,6 +392,9 @@ ar_scan (archive, function, arg) { register int nread; struct ar_hdr member_header; +#ifdef AIAMAGBIG + struct ar_hdr_big member_header_big; +#endif #ifdef AIAMAG char name[256]; int name_len; @@ -352,34 +417,73 @@ ar_scan (archive, function, arg) } #ifdef AIAMAG -#define AR_MEMHDR (AR_HDR_SIZE - sizeof (member_header._ar_name)) - nread = read (desc, (char *) &member_header, AR_MEMHDR); +#define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name)) - if (nread != AR_MEMHDR) +#ifdef AIAMAGBIG + if (big_archive) { - (void) close (desc); - return -2; + nread = read (desc, (char *) &member_header_big, + AR_MEMHDR_SZ(member_header_big) ); + + if (nread != AR_MEMHDR_SZ(member_header_big)) + { + (void) close (desc); + return -2; + } + + sscanf (member_header_big.ar_namlen, "%4d", &name_len); + nread = read (desc, name, name_len); + + if (nread != name_len) + { + (void) close (desc); + return -2; + } + + name[name_len] = 0; + + sscanf (member_header_big.ar_date, "%12ld", &dateval); + sscanf (member_header_big.ar_uid, "%12d", &uidval); + sscanf (member_header_big.ar_gid, "%12d", &gidval); + sscanf (member_header_big.ar_mode, "%12o", &eltmode); + sscanf (member_header_big.ar_size, "%20ld", &eltsize); + + data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big) + + name_len + 2); } - - sscanf (member_header.ar_namlen, "%4d", &name_len); - nread = read (desc, name, name_len); - - if (nread != name_len) + else +#endif { - (void) close (desc); - return -2; + nread = read (desc, (char *) &member_header, + AR_MEMHDR_SZ(member_header) ); + + if (nread != AR_MEMHDR_SZ(member_header)) + { + (void) close (desc); + return -2; + } + + sscanf (member_header.ar_namlen, "%4d", &name_len); + nread = read (desc, name, name_len); + + if (nread != name_len) + { + (void) close (desc); + return -2; + } + + name[name_len] = 0; + + sscanf (member_header.ar_date, "%12ld", &dateval); + sscanf (member_header.ar_uid, "%12d", &uidval); + sscanf (member_header.ar_gid, "%12d", &gidval); + sscanf (member_header.ar_mode, "%12o", &eltmode); + sscanf (member_header.ar_size, "%12ld", &eltsize); + + data_offset = (member_offset + AR_MEMHDR_SZ(member_header) + + name_len + 2); } - - name[name_len] = 0; - - sscanf (member_header.ar_date, "%12ld", &dateval); - sscanf (member_header.ar_uid, "%12d", &uidval); - sscanf (member_header.ar_gid, "%12d", &gidval); - sscanf (member_header.ar_mode, "%12o", &eltmode); - sscanf (member_header.ar_size, "%12ld", &eltsize); - - if ((data_offset = member_offset + AR_MEMHDR + name_len + 2) % 2) - ++data_offset; + data_offset += data_offset % 2; fnval = (*function) (desc, name, 0, @@ -493,7 +597,12 @@ ar_scan (archive, function, arg) /* End of the chain. */ break; - sscanf (member_header.ar_nxtmem, "%12ld", &member_offset); +#ifdef AIAMAGBIG + if (big_archive) + sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset); + else +#endif + sscanf (member_header.ar_nxtmem, "%12ld", &member_offset); if (lseek (desc, member_offset, 0) != member_offset) { @@ -562,37 +671,6 @@ ar_name_equal (name, mem, truncated) if (p != 0) name = p + 1; - /* We no longer use this kludge, since we - now support long archive member names. */ - -#if 0 && !defined (AIAMAG) && !defined (APOLLO) - - { - /* `reallylongname.o' matches `reallylongnam.o'. - If member names have a trailing slash, that's `reallylongna.o'. */ - - struct ar_hdr h; - unsigned int max = sizeof (h.ar_name); - unsigned int namelen, memlen; - - if (strncmp (name, mem, max - 3)) - return 0; - - namelen = strlen (name); - memlen = strlen (mem); - - if (namelen > memlen && memlen >= max - 1 - && name[namelen - 2] == '.' && name[namelen - 1] == 'o' - && mem[memlen - 2] == '.' && mem[memlen - 1] == 'o') - return 1; - - if (namelen != memlen) - return 0; - - return (namelen < max - 3 || !strcmp (name + max - 3, mem + max - 3)); - } - -#else /* AIX or APOLLO. */ #ifndef VMS if (truncated) { @@ -611,8 +689,6 @@ ar_name_equal (name, mem, truncated) #endif /* !VMS */ return !strcmp (name, mem); - -#endif } #ifndef VMS diff --git a/configure.in b/configure.in index be51781e..bc72d7d3 100644 --- a/configure.in +++ b/configure.in @@ -154,17 +154,20 @@ rm -f s.conftest conftoast AC_MSG_CHECKING(if system libc has GNU glob) AC_CACHE_VAL(make_cv_sys_gnu_glob, [ AC_TRY_CPP([ +#include #include #include #define GLOB_INTERFACE_VERSION 1 -#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 +#if defined _LIBC || !defined __GNU_LIBRARY__ || __GNU_LIBRARY__ <= 1 +# error no gnu glob +#else # include -# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION -# error have gnu glob +# if _GNU_GLOB_INTERFACE_VERSION != GLOB_INTERFACE_VERSION +# error no gnu glob # endif #endif - ], make_cv_sys_gnu_glob=no, make_cv_sys_gnu_glob=yes)]) + ], make_cv_sys_gnu_glob=yes, make_cv_sys_gnu_glob=no)]) case "$make_cv_sys_gnu_glob" in yes) AC_MSG_RESULT(yes) ;; no) AC_MSG_RESULT([no; using local copy]) diff --git a/default.c b/default.c index 06f56fad..76a32324 100644 --- a/default.c +++ b/default.c @@ -425,6 +425,16 @@ static char *default_variables[] = "SCCS_OUTPUT_OPTION", "-G$@", #endif +#ifdef _AMIGA + ".LIBPATTERNS", "%.lib", +#else +#ifdef __MSDOS__ + ".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a", +#else + ".LIBPATTERNS", "lib%.so lib%.a", +#endif +#endif + #endif /* !VMS */ 0, 0 }; diff --git a/function.c b/function.c index 13196ebf..a04a4679 100644 --- a/function.c +++ b/function.c @@ -876,6 +876,7 @@ expand_function (o, function, text, end) /* Kill the last space. */ --o; + v->value = 0; pop_variable_scope (); free (var); diff --git a/make.texinfo b/make.texinfo index e7b3bbf3..246707cb 100644 --- a/make.texinfo +++ b/make.texinfo @@ -1971,16 +1971,19 @@ directory search with no extra effort. @cindex @code{VPATH}, and link libraries @cindex search path for dependencies (@code{VPATH}), and link libraries @cindex @code{-l} (library search) +@cindex link libraries, patterns matching +@cindex @code{.LIBPATTERNS}, and link libraries +@vindex .LIBPATTERNS Directory search applies in a special way to libraries used with the linker. This special feature comes into play when you write a dependency whose name is of the form @samp{-l@var{name}}. (You can tell something strange is going on here because the dependency is normally the name of a -file, and the @emph{file name} of the library looks like +file, and the @emph{file name} of a library generally looks like @file{lib@var{name}.a}, not like @samp{-l@var{name}}.)@refill When a dependency's name has the form @samp{-l@var{name}}, @code{make} -handles it specially by searching for the file @file{lib@var{name}.a} in +handles it specially by searching for the file @file{lib@var{name}.so} in the current directory, in directories specified by matching @code{vpath} search paths and the @code{VPATH} search path, and then in the directories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib} @@ -1988,7 +1991,11 @@ directories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib} @code{make} behave as if @var{prefix} is defined to be the root of the DJGPP installation tree). -For example, +If that file is not found, then the file @file{lib@var{name}.a} is +searched for, in the same directories as above. + +For example, if there is a @file{/usr/lib/libcurses.a} library on your +system (and no @file{/usr/lib/libcurses.so} file), then @example @group @@ -2002,6 +2009,21 @@ would cause the command @samp{cc foo.c /usr/lib/libcurses.a -o foo} to be executed when @file{foo} is older than @file{foo.c} or than @file{/usr/lib/libcurses.a}.@refill +Although the default set of files to be searched for is +@file{lib@var{name}.so} and @file{lib@var{name}.a}, this is customizable +via the @code{.LIBPATTERNS} variable. Each word in the value of this +variable is a pattern string. When a dependency like +@samp{-l@var{name}} is seen, @code{make} will replace the percent in +each pattern in the list with @var{name} and perform the above directory +searches using that library filename. If no library is found, the next +word in the list will be used. + +The default value for @code{.LIBPATTERNS} is ``@samp{lib%.so lib%.a}'', +which provides the default behavior described above. + +You can turn off link library expansion completely by setting this +variable to an empty value. + @node Phony Targets, Force Targets, Directory Search, Rules @section Phony Targets @cindex phony targets diff --git a/read.c b/read.c index b5efca2d..3303ba9d 100644 --- a/read.c +++ b/read.c @@ -18,6 +18,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +#include + #include "make.h" #include "dep.h" #include "filedef.h" @@ -26,12 +28,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "variable.h" #include "rule.h" -/* This is POSIX.2, but most systems using -DPOSIX probably don't have it. */ -#ifdef HAVE_GLOB_H -#include -#else -#include "glob/glob.h" -#endif #ifndef WINDOWS32 #ifndef _AMIGA @@ -1564,9 +1560,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started, if (!pattern_matches (pattern, pattern_percent, name)) { /* Give a warning if the rule is meaningless. */ - error (flocp, - "target `%s' doesn't match the target pattern", - name); + error (flocp,"target `%s' doesn't match the target pattern", name); this = 0; } else diff --git a/remake.c b/remake.c index d312321e..fdd868ac 100644 --- a/remake.c +++ b/remake.c @@ -21,6 +21,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "job.h" #include "commands.h" #include "dep.h" +#include "variable.h" + #include #ifdef HAVE_FCNTL_H @@ -1188,82 +1190,111 @@ library_search (lib, mtime_ptr) 0 }; + static char *libpatterns = NULL; + char *libname = &(*lib)[2]; /* Name without the `-l'. */ FILE_TIMESTAMP mtime; - /* Buffer to construct possible names in. */ - char *buf = xmalloc (sizeof (LIBDIR) + 8 + strlen (libname) + 4 + 2 + 1); + /* Loop variables for the libpatterns value. */ + char *p, *p2; + int len; + char *file, **dp; - /* Look first for `libNAME.a' in the current directory. */ - -#ifndef _AMIGA - sprintf (buf, "lib%s.a", libname); -#else - sprintf (buf, "%s.lib", libname); -#endif - mtime = name_mtime (buf); - if (mtime != (FILE_TIMESTAMP) -1) + /* If we don't have libpatterns, get it. */ + if (!libpatterns) { - *lib = buf; - if (mtime_ptr != 0) - *mtime_ptr = mtime; - return 1; + int save = warn_undefined_variables_flag; + warn_undefined_variables_flag = 0; + + libpatterns = strdup (variable_expand ("$(strip $(.LIBPATTERNS))")); + + warn_undefined_variables_flag = save; } - /* Now try VPATH search on that. */ - - file = buf; - if (vpath_search (&file, mtime_ptr)) + /* Loop through all the patterns in .LIBPATTERNS, and search on each one. */ + p2 = libpatterns; + while ((p = find_next_token (&p2, &len)) != 0) { - free (buf); - *lib = file; - return 1; - } + static char *buf = NULL; + static int buflen = 0; + static int libdir_maxlen = -1; + char *libbuf = variable_expand (""); - /* Now try the standard set of directories. */ - -#ifdef __MSDOS__ - { - /* The default library directory is at ${DJDIR}/lib. */ - struct variable *djdir = lookup_variable ("DJDIR", 5); - - if (djdir) + /* Expand the pattern using LIBNAME as a replacement. */ { - size_t djdir_len = strlen (djdir->value); + char c = p[len]; + char *p3, *p4; - if (djdir_len > sizeof(LIBDIR) + 8 + strlen(libname) + 4 + 2) - buf = (char *) xrealloc (djdir_len + 1); - sprintf (buf, "%s/lib/lib%s.a", djdir->value, libname); - mtime = name_mtime (buf); - if (mtime != (FILE_TIMESTAMP) -1) + p[len] = '\0'; + p3 = find_percent (p); + if (!p3) { - *lib = buf; - if (mtime_ptr != 0) - *mtime_ptr = mtime; - return 1; + /* Give a warning if there is no pattern, then remove the + pattern so it's ignored next time. */ + error (NILF, ".LIBPATTERNS element `%s' is not a pattern", p); + for (; len; --len, ++p) + *p = ' '; + *p = c; + continue; } + p4 = variable_buffer_output (libbuf, p, p3-p); + p4 = variable_buffer_output (p4, libname, strlen (libname)); + p4 = variable_buffer_output (p4, p3+1, len - (p3-p)); + p[len] = c; } - } -#endif - for (dp = dirs; *dp != 0; ++dp) - { -#ifndef _AMIGA - sprintf (buf, "%s/lib%s.a", *dp, libname); -#else - sprintf (buf, "%s/%s.lib", *dp, libname); -#endif - mtime = name_mtime (buf); + /* Look first for `libNAME.a' in the current directory. */ + mtime = name_mtime (libbuf); if (mtime != (FILE_TIMESTAMP) -1) { - *lib = buf; + *lib = strdup (libbuf); if (mtime_ptr != 0) *mtime_ptr = mtime; return 1; } + + /* Now try VPATH search on that. */ + + file = libbuf; + if (vpath_search (&file, mtime_ptr)) + { + *lib = file; + return 1; + } + + /* Now try the standard set of directories. */ + + if (!buflen) + { + for (dp = dirs; *dp != 0; ++dp) + { + int l = strlen (*dp); + if (l > libdir_maxlen) + libdir_maxlen = l; + } + buflen = strlen (libbuf); + buf = xmalloc(libdir_maxlen + buflen + 2); + } + else if (buflen < strlen (libbuf)) + { + buflen = strlen (libbuf); + buf = xrealloc (buf, libdir_maxlen + buflen + 2); + } + + for (dp = dirs; *dp != 0; ++dp) + { + sprintf (buf, "%s/%s", *dp, libbuf); + mtime = name_mtime (buf); + if (mtime != (FILE_TIMESTAMP) -1) + { + *lib = strdup (buf); + if (mtime_ptr != 0) + *mtime_ptr = mtime; + return 1; + } + } } - free (buf); return 0; } diff --git a/variable.c b/variable.c index 85987dbf..648f82b9 100644 --- a/variable.c +++ b/variable.c @@ -265,6 +265,8 @@ pop_variable_scope () next = v->next; free (v->name); + if (v->value) + free (v->value); free ((char *) v); } } @@ -687,7 +689,7 @@ try_variable_definition (flocp, line, origin) register char *end; enum { f_bogus, f_simple, f_recursive, f_append, f_conditional } flavor = f_bogus; - char *name, *expanded_name, *value; + char *name, *expanded_name, *value, *alloc_value=NULL; struct variable *v; while (1) @@ -775,8 +777,11 @@ try_variable_definition (flocp, line, origin) /* Should not be possible. */ abort (); case f_simple: - /* A simple variable definition "var := value". Expand the value. */ - value = variable_expand (p); + /* A simple variable definition "var := value". Expand the value. + We have to allocate memory since otherwise it'll clobber the + variable buffer, and we still need that. */ + alloc_value = allocated_variable_expand (p); + value = alloc_value; break; case f_conditional: /* A conditional variable definition "var ?= value". @@ -931,6 +936,8 @@ try_variable_definition (flocp, line, origin) v = define_variable (expanded_name, strlen (expanded_name), value, origin, flavor == f_recursive); + if (alloc_value) + free (alloc_value); free (expanded_name); return v;