Hi, When trying to use the 'fnmatch' module for GNU gettext, I found thst it still depends on the old 'alloca' module that relies on an external function on platforms like HP-UX 10.00 with cc. IMO the better choice is to use the 'alloca-opt' module and hand-optimized code for modules that come from glibc, and the 'allocsa' module for higher-level code.
Furthermore fnmatch_loop.c has a gratuitous limit of 2000 characters for patterns; 2000 is less than PATH_MAX! Here is a proposed patch to fix both. 2006-07-30 Bruno Haible <[EMAIL PROTECTED]> * fnmatch.c (fnmatch): On platforms without alloca, set ALLOCA_LIMIT to 0, so that the memory allocation always uses malloc. * fnmatch_loop.c (EXT): Use malloc as alternative to alloca, when the pattern size is big. On platforms without alloca, set ALLOCA_LIMIT to 0, so that the memory allocation always uses malloc. * modules/fnmatch (Depends-on): Add alloca-opt, remove alloca. *** lib/fnmatch.c.bak 2006-07-11 13:54:17.000000000 +0200 --- lib/fnmatch.c 2006-07-30 20:23:09.000000000 +0200 *************** *** 276,282 **** fnmatch (const char *pattern, const char *string, int flags) { # if HANDLE_MULTIBYTE ! # define ALLOCA_LIMIT 2000 if (__builtin_expect (MB_CUR_MAX, 1) != 1) { mbstate_t ps; --- 276,286 ---- fnmatch (const char *pattern, const char *string, int flags) { # if HANDLE_MULTIBYTE ! # if HAVE_ALLOCA || defined _LIBC ! # define ALLOCA_LIMIT 2000 ! # else ! # define ALLOCA_LIMIT 0 ! # endif if (__builtin_expect (MB_CUR_MAX, 1) != 1) { mbstate_t ps; *** lib/fnmatch_loop.c.bak 2006-07-11 13:54:17.000000000 +0200 --- lib/fnmatch_loop.c 2006-07-30 21:03:04.000000000 +0200 *************** *** 1003,1022 **** struct patternlist { struct patternlist *next; CHAR str[1]; } *list = NULL; struct patternlist **lastp = &list; size_t pattern_len = STRLEN (pattern); const CHAR *p; const CHAR *rs; enum { ALLOCA_LIMIT = 8000 }; /* Parse the pattern. Store the individual parts in the list. */ level = 0; for (startp = p = pattern + 1; ; ++p) if (*p == L_('\0')) /* This is an invalid pattern. */ ! return -1; else if (*p == L_('[')) { /* Handle brackets special. */ --- 1003,1028 ---- struct patternlist { struct patternlist *next; + int malloced; CHAR str[1]; } *list = NULL; struct patternlist **lastp = &list; size_t pattern_len = STRLEN (pattern); const CHAR *p; const CHAR *rs; + #if HAVE_ALLOCA || defined _LIBC enum { ALLOCA_LIMIT = 8000 }; + #else + enum { ALLOCA_LIMIT = 0 }; + #endif + int retval; /* Parse the pattern. Store the individual parts in the list. */ level = 0; for (startp = p = pattern + 1; ; ++p) if (*p == L_('\0')) /* This is an invalid pattern. */ ! goto failed; else if (*p == L_('[')) { /* Handle brackets special. */ *************** *** 1034,1040 **** while (*p != L_(']')) if (*p++ == L_('\0')) /* This is no valid pattern. */ ! return -1; } else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') || *p == L_('!')) && p[1] == L_('(')) --- 1040,1046 ---- while (*p != L_(']')) if (*p++ == L_('\0')) /* This is no valid pattern. */ ! goto failed; } else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') || *p == L_('!')) && p[1] == L_('(')) *************** *** 1057,1067 **** plensize = plen * sizeof (CHAR); \ newpsize = offsetof (struct patternlist, str) + plensize; \ if ((size_t) -1 / sizeof (CHAR) < plen \ ! || newpsize < offsetof (struct patternlist, str) \ ! || ALLOCA_LIMIT <= newpsize) \ ! return -1; \ ! newp = (struct patternlist *) alloca (newpsize); \ ! *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \ newp->next = NULL; \ *lastp = newp; \ lastp = &newp->next --- 1063,1083 ---- plensize = plen * sizeof (CHAR); \ newpsize = offsetof (struct patternlist, str) + plensize; \ if ((size_t) -1 / sizeof (CHAR) < plen \ ! || newpsize < offsetof (struct patternlist, str)) \ ! goto failed; \ ! if (newpsize < ALLOCA_LIMIT) \ ! { \ ! newp = (struct patternlist *) alloca (newpsize); \ ! newp->malloced = 0; \ ! } \ ! else \ ! { \ ! newp = (struct patternlist *) malloc (newpsize); \ ! if (!newp) \ ! goto failed; \ ! newp->malloced = 1; \ ! } \ ! *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \ newp->next = NULL; \ *lastp = newp; \ lastp = &newp->next *************** *** 1085,1096 **** { case L_('*'): if (FCT (p, string, string_end, no_leading_period, flags) == 0) ! return 0; /* FALLTHROUGH */ case L_('+'): do { for (rs = string; rs <= string_end; ++rs) /* First match the prefix with the current pattern with the current pattern. */ --- 1101,1117 ---- { case L_('*'): if (FCT (p, string, string_end, no_leading_period, flags) == 0) ! { ! retval = 0; ! goto done; ! } /* FALLTHROUGH */ case L_('+'): do { + struct patternlist *next; + for (rs = string; rs <= string_end; ++rs) /* First match the prefix with the current pattern with the current pattern. */ *************** *** 1112,1142 **** : rs[-1] == '/' && NO_LEADING_PERIOD (flags), flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0))) ! /* It worked. Signal success. */ ! return 0; } ! while ((list = list->next) != NULL); /* None of the patterns lead to a match. */ return FNM_NOMATCH; case L_('?'): if (FCT (p, string, string_end, no_leading_period, flags) == 0) ! return 0; /* FALLTHROUGH */ case L_('@'): do ! /* I cannot believe it but `strcat' is actually acceptable ! here. Match the entire string with the prefix from the ! pattern list and the rest of the pattern following the ! pattern list. */ ! if (FCT (STRCAT (list->str, p), string, string_end, ! no_leading_period, ! flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) ! /* It worked. Signal success. */ ! return 0; ! while ((list = list->next) != NULL); /* None of the patterns lead to a match. */ return FNM_NOMATCH; --- 1133,1186 ---- : rs[-1] == '/' && NO_LEADING_PERIOD (flags), flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0))) ! { ! /* It worked. Signal success. */ ! retval = 0; ! goto done; ! } ! ! next = list->next; ! if (list->malloced) ! free (list); ! list = next; } ! while (list != NULL); /* None of the patterns lead to a match. */ return FNM_NOMATCH; case L_('?'): if (FCT (p, string, string_end, no_leading_period, flags) == 0) ! { ! retval = 0; ! goto done; ! } /* FALLTHROUGH */ case L_('@'): do ! { ! struct patternlist *next; ! ! /* I cannot believe it but `strcat' is actually acceptable ! here. Match the entire string with the prefix from the ! pattern list and the rest of the pattern following the ! pattern list. */ ! if (FCT (STRCAT (list->str, p), string, string_end, ! no_leading_period, ! flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) ! { ! /* It worked. Signal success. */ ! retval = 0; ! goto done; ! } ! ! next = list->next; ! if (list->malloced) ! free (list); ! list = next; ! } ! while (list != NULL); /* None of the patterns lead to a match. */ return FNM_NOMATCH; *************** *** 1159,1178 **** : rs[-1] == '/' && NO_LEADING_PERIOD (flags), flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)) ! /* This is successful. */ ! return 0; } /* None of the patterns together with the rest of the pattern lead to a match. */ ! return FNM_NOMATCH; default: assert (! "Invalid extended matching operator"); break; } ! return -1; } --- 1203,1237 ---- : rs[-1] == '/' && NO_LEADING_PERIOD (flags), flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)) ! { ! /* This is successful. */ ! retval = 0; ! goto done; ! } } /* None of the patterns together with the rest of the pattern lead to a match. */ ! retval = FNM_NOMATCH; ! goto done; default: assert (! "Invalid extended matching operator"); break; } ! failed: ! retval = -1; ! done: ! while (list != NULL) ! { ! struct patternlist *next = list->next; ! ! if (list->malloced) ! free (list); ! list = next; ! } ! return retval; } *** modules/fnmatch.bak 2005-07-23 00:04:12.000000000 +0200 --- modules/fnmatch 2006-07-30 20:44:18.000000000 +0200 *************** *** 9,15 **** m4/fnmatch.m4 Depends-on: ! alloca stdbool configure.ac: --- 9,15 ---- m4/fnmatch.m4 Depends-on: ! alloca-opt stdbool configure.ac: