We already have one vote in favor of importing Gnulib using its provided
bootstrap script. I am not opposed and merely offer the patch
use-system-gnulib.diff as a compromise. The patch name is actually
misleading, as I explained in reply to Colin Frank. Furthermore, I
complicated the patching process by providing the final patch,
ax_func_getopt_long.m4, in a different format: It fails to apply using
`patch -p1 <patchfile' as appropriate for the other patches. So I've
attached a new patch file, use-system-regexp.diff, that replaces both
use-system-gnulib.diff and ax_func_getopt_long.m4. This applies
correctly using `patch -p1'. Apologies for the complication.
One note about Bruno Haible's hash function: In the version that is now
deprecated in Gnulib, hash_pjw, the final value is returned modulus the
key length, whereas in the original version included in this patch, no
modulus is taken (as was the case in the Compilers book).
On 10/13/25 01:21, Andrew L. Moore wrote:
The patch use-system-gnulib.diff depends upon an m4 macro which was
omitted. Please find attached a patch for it below.
On 10/13/25 01:07, Andrew L. Moore wrote:
Please find attached patches that allow building GNU Global v6.6.14 on
Fedora GNU/Linux v42 and v43. The first three are straight forward:
1. When looking for Universal Ctags, use option `--extras'. The code
does this, but configure was using `--extra'.
2. When looking for libsqlite3, add /usr/lib64 to the search path.
3. Address a GNU C v15 compilation error: assignment from incompatible
pointer type 'int (*)(void)'. The fix is to conditionally add
prototypes to dberr masks.
Many modern systems come with Gnulib. So either GNU Global could link
against the system Gnulib, or, alternatively, the Gnulib `bootstrap'
script could be added to the GNU Global distribution. Gnulib bootstrap
downloads Gnulib modules as needed. See:
https://cgit.git.savannah.gnu.org/cgit/gnulib.git/tree/top/bootstrap
One complication is that the function hash_string is no longer
included in Gnulib.
4. So the final patch is an attempt to address these issues in
minimalist (lazy) way: If the system provides regcomp and
getopt_long, then the system-provided functions are used by
default. To override this, use the configure option
`--with-included-regex'. An updated version of the hash_string
function by Bruno Haible is added directly to libutil/strhash.c.
The function is described in the article:
https://www.haible.de/bruno/hashfunc.html
A more correct approach might be to leverage Gnulib's bootstrap script
and update strhash.c to use current Gnulib hash functions. If I had
more time, I would have liked to offer an alternative patch for this.
The current Gnulib does have lots of overhead, so maybe the included
patch will be acceptable compromise.
diff --git a/Makefile.am b/Makefile.am
index 44452dc..6bbf764 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,7 +11,10 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = libglibc libutil libparser libltdl plugin-factory
+SUBDIRS = libutil libparser libltdl plugin-factory
+if LDADD_GNULIB
+ SUBDIRS += libglibc
+endif
if !USE_DB185_COMPAT
SUBDIRS += libdb
endif
diff --git a/configure.ac b/configure.ac
index 25e57ce..bf9eed1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,6 +25,7 @@ AC_INIT([GNU Global],[6.6.14])
AC_DEFINE(COPYRIGHT_YEAR,["1996-2024"],[Copyright Year])
AC_CONFIG_SRCDIR(global/global.c)
AC_CONFIG_HEADERS([config.h:config-h.in])
+AC_CONFIG_LIBOBJ_DIR([libglibc])
AC_CONFIG_MACRO_DIRS([m4])
AC_PREREQ(2.71)
AM_INIT_AUTOMAKE([1.9.3 gnu subdir-objects])
@@ -220,7 +221,39 @@ AC_ARG_WITH(db185-compat,
],[ with_db185_compat=no ])
AM_CONDITIONAL([USE_DB185_COMPAT], [test "$with_db185_compat" != no])
-LDADD='../libparser/libgloparser.a ../libutil/libgloutil.a '$DBLIBRARY' ../libglibc/libgloglibc.a'
+LDADD='../libparser/libgloparser.a ../libutil/libgloutil.a '$DBLIBRARY
+
+AX_FUNC_GETOPT_LONG
+
+AC_MSG_CHECKING([whether included regex is requested])
+AC_ARG_WITH([included-regex],
+ [AS_HELP_STRING([--with-included-regex],
+ [use included GNU regex library])],
+ [], [with_included_regex=check])
+AC_MSG_RESULT([$with_included_regex])
+if test ! ."$with_included_regex" = .'yes'; then
+ AC_CHECK_FUNCS([regcomp],
+ [with_included_regex=no],
+ [with_included_regex=yes
+ AC_MSG_WARN([System regex not found, falling back to included version])])
+fi
+AM_CONDITIONAL([LIBADD_REGEX],
+ [test ."$with_included_regex" = .'yes' \
+ -o ."$ac_cv_func_getopt_long" != .'yes'])
+AM_COND_IF([LIBADD_REGEX],
+ [LDADD="$LDADD ../libglibc/libgloglibc.a"
+ AC_DEFINE([HAVE_REG_SYNTAX_T], [1],
+ [Define to 1 if regex.h defines `reg_syntax_t'.])],
+ [AC_CHECK_TYPES([reg_syntax_t],
+ [AC_DEFINE([HAVE_REG_SYNTAX_T], [1],
+ [Define to 1 if regex.h defines `reg_syntax_t'.])],[],
+ [[#include <sys/types.h>
+#include <regex.h>]])])
+
+AM_CONDITIONAL([LDADD_GNULIB],
+ [test ."$with_included_regex" = .'yes' \
+ -o ."$ac_cv_func_getopt_long" != .'yes'])
+
dnl
dnl Use sqlite3 API.
dnl
diff --git a/libutil/strhash.c b/libutil/strhash.c
index 393a069..879bae5 100644
--- a/libutil/strhash.c
+++ b/libutil/strhash.c
@@ -20,6 +20,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -72,9 +73,27 @@ strhash_close(hash); // free resources.
#define obstack_chunk_alloc check_malloc
#define obstack_chunk_free free
+#define LONGBITS (CHAR_BIT * sizeof(long))
+
+/* Source: https://www.haible.de/bruno/hashfunc.html */
+static unsigned long
+compute_hashval (const void *key, size_t keylen)
+{
+ size_t cnt;
+ unsigned long int hval;
+
+ cnt = 0;
+ hval = keylen;
+ while (cnt < keylen)
+ {
+ hval = (hval << 9) | (hval >> (LONGBITS - 9));
+ hval += (unsigned long int) *(((char *) key) + cnt++);
+ }
+ return hval != 0 ? hval : ~((unsigned long) 0);
+}
/**
- * strhash_open: open string hash table.
+ * strhash_open: open hash table.
*
* @param[in] buckets size of bucket table
* @return sh STRHASH structure
@@ -108,7 +127,8 @@ strhash_open(int buckets)
struct sh_entry *
strhash_assign(STRHASH *sh, const char *name, int force)
{
- struct sh_head *head = &sh->htab[__hash_string(name) % sh->buckets];
+ struct sh_head *head =
+ &sh->htab[compute_hashval(name, strlen(name)) % sh->buckets];
struct sh_entry *entry;
/*
--- a/m4/ax_func_getopt_long.m4~ 2025-10-12 22:31:39.709619482 -0400
+++ b/m4/ax_func_getopt_long.m4 2025-10-12 22:38:44.270423911 -0400
@@ -0,0 +1,66 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_func_getopt_long.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_FUNC_GETOPT_LONG
+#
+# DESCRIPTION
+#
+# Check for getopt_long support.
+#
+# This assume that the standard getopt.h file (from GNU libc) is available
+# as lib/gnugetopt.h. If needed, this file will be linked as getopt.h, but
+# we want to default to the system's getopt.h file. (See
+# http://sources.redhat.com/ml/automake/2000-09/msg00041.html for an
+# explanation about why using the system's getopt.h file is important.)
+#
+# LICENSE
+#
+# Copyright (c) 2008 Alexandre Duret-Lutz <[email protected]>
+#
+# This program 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 2 of the License, or (at your
+# option) any later version.
+#
+# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 6
+
+AU_ALIAS([ADL_FUNC_GETOPT_LONG], [AX_FUNC_GETOPT_LONG])
+AC_DEFUN([AX_FUNC_GETOPT_LONG],
+ [AC_PREREQ(2.49)dnl
+ # clean out junk possibly left behind by a previous configuration
+ rm -f lib/getopt.h
+ # Check for getopt_long support
+ AC_CHECK_HEADERS([getopt.h])
+ AC_CHECK_FUNCS([getopt_long],,
+ [# FreeBSD has a gnugetopt library for this
+ AC_CHECK_LIB([gnugetopt],[getopt_long],
+ [AC_DEFINE([HAVE_GETOPT_LONG], [1], [Define to 1 when getopt_long is available.])],
+ [# use the GNU replacement
+ AC_LIBOBJ(getopt)
+ AC_LIBOBJ(getopt1)
+ #AC_CONFIG_LINKS([lib/getopt.h:lib/getopt.in.h])
+ ])])])