From 2db5c7115e5b37734993603c0381aab7e62c4be9 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff <gray@gnu.org.ua> Date: Wed, 23 Feb 2005 15:09:34 +0000 Subject: [PATCH] Updated by gnulib-sync --- lib/setenv.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------------- lib/snprintf.c | 886 +++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/snprintf.h | 223 +++++++++++++++++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- lib/vasprintf.c | 208 ++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ lib/xalloc.h | 94 +++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------- lib/xmalloc.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------- lib/xstrtol.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------- lib/xstrtol.h | 55 ++++++++++++++++++++++++++++++++++++++++--------------- m4/getopt.m4 | 77 +++++++++++++++++++++++++++++++++-------------------------------------------- m4/regex.m4 | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- mailbox/argp-ba.c | 21 ++++++++++----------- mailbox/argp-eexst.c | 29 +++++++++++------------------ mailbox/argp-fmtstream.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- mailbox/argp-fmtstream.h | 57 +++++++++++++++++++++++++++++++++++++-------------------- mailbox/argp-fs-xinl.c | 28 +++++++++++++++------------- mailbox/argp-help.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------- mailbox/argp-namefrob.h | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ mailbox/argp-parse.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------- mailbox/argp-pv.c | 21 ++++++++++----------- mailbox/argp-pvh.c | 25 ++++++++++++------------- mailbox/argp-xinl.c | 29 ++++++++++++++++------------- mailbox/getline.c | 125 ++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------- mailbox/getline.h | 54 +++++++++++++++++++++++++++++------------------------- mailbox/getopt.c | 943 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- mailbox/getopt1.c | 94 ++++++++++++++++++++++++++++++++++++++++------------------------------------------------------ mailbox/md5.c | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- mailbox/md5.h | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- mailbox/regex.c | 3251 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ mailbox/strchrnul.c | 171 +++++++++++++++++++-------------------------------------------------------------------------------------------------------------------------------------------------------- mailbox/strndup.c | 63 ++++++++++++++++++++++++++++++++++++--------------------------- mailbox/strnlen.c | 44 +++++++++++++++++++++++++++++++------------- mailbox/strtok_r.c | 50 +++++++++++++++++++++++++++++++------------------- 32 files changed, 4453 insertions(+), 4413 deletions(-) diff --git a/lib/setenv.c b/lib/setenv.c index ba965fa..320469b 100644 --- a/lib/setenv.c +++ b/lib/setenv.c @@ -1,130 +1,276 @@ -/* Copyright (C) 1992, 1995, 1996, 1997, 2001 Free Software Foundation, Inc. - This file based on setenv.c in the GNU C Library. +/* Copyright (C) 1992,1995-1999,2000-2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if HAVE_CONFIG_H # include <config.h> #endif +#include <alloca.h> #include <errno.h> - -#if HAVE_STDLIB_H -# include <stdlib.h> -#else -#include <sys/types.h> /* For `size_t' */ -#include <stdio.h> /* For `NULL' */ -#endif -#if HAVE_STRING_H -# include <string.h> +#ifndef __set_errno +# define __set_errno(ev) ((errno) = (ev)) #endif -#if HAVE_UNISTD_H + +#include <stdlib.h> +#include <string.h> +#if _LIBC || HAVE_UNISTD_H # include <unistd.h> #endif -#define __environ environ +#if !_LIBC +# include "allocsa.h" +#endif + +#if !_LIBC +# define __environ environ +# ifndef HAVE_ENVIRON_DECL extern char **environ; +# endif +#endif + +#if _LIBC +/* This lock protects against simultaneous modifications of `environ'. */ +# include <bits/libc-lock.h> +__libc_lock_define_initialized (static, envlock) +# define LOCK __libc_lock_lock (envlock) +# define UNLOCK __libc_lock_unlock (envlock) +#else +# define LOCK +# define UNLOCK +#endif + +/* In the GNU C library we must keep the namespace clean. */ +#ifdef _LIBC +# define setenv __setenv +# define clearenv __clearenv +# define tfind __tfind +# define tsearch __tsearch +#endif + +/* In the GNU C library implementation we try to be more clever and + allow arbitrarily many changes of the environment given that the used + values are from a small set. Outside glibc this will eat up all + memory after a while. */ +#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ + && defined __GNUC__) +# define USE_TSEARCH 1 +# include <search.h> +typedef int (*compar_fn_t) (const void *, const void *); + +/* This is a pointer to the root of the search tree with the known + values. */ +static void *known_values; -/* LOCK and UNLOCK are defined as no-ops. This makes the libiberty - * implementation MT-Unsafe. */ -#define LOCK -#define UNLOCK +# define KNOWN_VALUE(Str) \ + ({ \ + void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \ + value != NULL ? *(char **) value : NULL; \ + }) +# define STORE_VALUE(Str) \ + tsearch (Str, &known_values, (compar_fn_t) strcmp) + +#else +# undef USE_TSEARCH + +# define KNOWN_VALUE(Str) NULL +# define STORE_VALUE(Str) do { } while (0) + +#endif -/* Below this point, it's verbatim code from the glibc-2.0 implementation */ /* If this variable is not a null pointer we allocated the current environment. */ static char **last_environ; +/* This function is used by `setenv' and `putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of `putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a `setenv' call since we can never + free the strings. */ int -setenv (name, value, replace) - const char *name; - const char *value; - int replace; +__add_to_environ (const char *name, const char *value, const char *combined, + int replace) { register char **ep; register size_t size; const size_t namelen = strlen (name); - const size_t vallen = strlen (value) + 1; + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; LOCK; + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + size = 0; - if (__environ != NULL) - for (ep = __environ; *ep != NULL; ++ep) - if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') - break; - else - ++size; + if (ep != NULL) + { + for (; *ep != NULL; ++ep) + if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') + break; + else + ++size; + } - if (__environ == NULL || *ep == NULL) + if (ep == NULL || *ep == NULL) { char **new_environ; - if (__environ == last_environ && __environ != NULL) - /* We allocated this space; we can extend it. */ - new_environ = (char **) realloc (last_environ, - (size + 2) * sizeof (char *)); - else - new_environ = (char **) malloc ((size + 2) * sizeof (char *)); +#ifdef USE_TSEARCH + char *new_value; +#endif + /* We allocated this space; we can extend it. */ + new_environ = + (char **) (last_environ == NULL + ? malloc ((size + 2) * sizeof (char *)) + : realloc (last_environ, (size + 2) * sizeof (char *))); if (new_environ == NULL) { UNLOCK; return -1; } - new_environ[size] = malloc (namelen + 1 + vallen); - if (new_environ[size] == NULL) + /* If the whole entry is given add it. */ + if (combined != NULL) + /* We must not add the string to the search tree since it belongs + to the user. */ + new_environ[size] = (char *) combined; + else { - free ((char *) new_environ); - errno = ENOMEM; - UNLOCK; - return -1; + /* See whether the value is already known. */ +#ifdef USE_TSEARCH +# ifdef _LIBC + new_value = (char *) alloca (namelen + 1 + vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + new_value = (char *) allocsa (namelen + 1 + vallen); + if (new_value == NULL) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + new_environ[size] = KNOWN_VALUE (new_value); + if (new_environ[size] == NULL) +#endif + { + new_environ[size] = (char *) malloc (namelen + 1 + vallen); + if (new_environ[size] == NULL) + { +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (new_environ[size], new_value, namelen + 1 + vallen); +#else + memcpy (new_environ[size], name, namelen); + new_environ[size][namelen] = '='; + memcpy (&new_environ[size][namelen + 1], value, vallen); +#endif + /* And save the value now. We cannot do this when we remove + the string since then we cannot decide whether it is a + user string or not. */ + STORE_VALUE (new_environ[size]); + } +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif } if (__environ != last_environ) memcpy ((char *) new_environ, (char *) __environ, size * sizeof (char *)); - memcpy (new_environ[size], name, namelen); - new_environ[size][namelen] = '='; - memcpy (&new_environ[size][namelen + 1], value, vallen); - new_environ[size + 1] = NULL; last_environ = __environ = new_environ; } else if (replace) { - size_t len = strlen (*ep); - if (len + 1 < namelen + 1 + vallen) + char *np; + + /* Use the user string if given. */ + if (combined != NULL) + np = (char *) combined; + else { - /* The existing string is too short; malloc a new one. */ - char *new = malloc (namelen + 1 + vallen); - if (new == NULL) +#ifdef USE_TSEARCH + char *new_value; +# ifdef _LIBC + new_value = alloca (namelen + 1 + vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + new_value = allocsa (namelen + 1 + vallen); + if (new_value == NULL) { + __set_errno (ENOMEM); UNLOCK; return -1; } - *ep = new; + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + np = KNOWN_VALUE (new_value); + if (np == NULL) +#endif + { + np = malloc (namelen + 1 + vallen); + if (np == NULL) + { +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (np, new_value, namelen + 1 + vallen); +#else + memcpy (np, name, namelen); + np[namelen] = '='; + memcpy (&np[namelen + 1], value, vallen); +#endif + /* And remember the value. */ + STORE_VALUE (np); + } +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif } - memcpy (*ep, name, namelen); - (*ep)[namelen] = '='; - memcpy (&(*ep)[namelen + 1], value, vallen); + + *ep = np; } UNLOCK; @@ -132,25 +278,51 @@ setenv (name, value, replace) return 0; } -void -unsetenv (name) - const char *name; +int +setenv (const char *name, const char *value, int replace) { - const size_t len = strlen (name); - char **ep; + return __add_to_environ (name, value, NULL, replace); +} +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +int +clearenv (void) +{ LOCK; - for (ep = __environ; *ep; ++ep) - if (!strncmp (*ep, name, len) && (*ep)[len] == '=') - { - /* Found it. Remove this pointer by moving later ones back. */ - char **dp = ep; - do - dp[0] = dp[1]; - while (*dp++); - /* Continue the loop in case NAME appears again. */ - } + if (__environ == last_environ && __environ != NULL) + { + /* We allocated this environment so we can free it. */ + free (__environ); + last_environ = NULL; + } + + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; UNLOCK; + + return 0; +} + +#ifdef _LIBC +static void +free_mem (void) +{ + /* Remove all traces. */ + clearenv (); + + /* Now remove the search tree. */ + __tdestroy (known_values, free); + known_values = NULL; } +text_set_element (__libc_subfreeres, free_mem); + + +# undef setenv +# undef clearenv +weak_alias (__setenv, setenv) +weak_alias (__clearenv, clearenv) +#endif diff --git a/lib/snprintf.c b/lib/snprintf.c index 57ffb6c..9a4edc1 100644 --- a/lib/snprintf.c +++ b/lib/snprintf.c @@ -1,868 +1,60 @@ - -/* - Unix snprintf implementation. - Version 1.3 +/* Formatted output to strings. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by Simon Josefsson. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, 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 Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 1.3: - * add #include <config.h> ifdef HAVE_CONFIG_H - * cosmetic change, when exponent is 0 print xxxE+00 - instead of xxxE-00 - 1.2: - * put the program under LGPL. - 1.1: - * added changes from Miles Bader - * corrected a bug with %f - * added support for %#g - * added more comments :-) - 1.0: - * supporting must ANSI syntaxic_sugars - 0.0: - * suppot %s %c %d - - THANKS(for the patches and ideas): - Miles Bader - Cyrille Rustom - Jacek Slabocewiz - Mike Parker(mouse) - -*/ - -#include "snprintf.h" - -/* - * Find the nth power of 10 - */ -PRIVATE double -#ifdef __STDC__ -pow_10(int n) -#else -pow_10(n) -int n; -#endif -{ - int i; - double P; - - if (n < 0) - for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;} - else - for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;} - return P; -} - -/* - * Find the integral part of the log in base 10 - * Note: this not a real log10() - I just need and approximation(integerpart) of x in: - 10^x ~= r - * log_10(200) = 2; - * log_10(250) = 2; - */ -PRIVATE int -#ifdef __STDC__ -log_10(double r) -#else -log_10(r) -double r; -#endif -{ - int i = 0; - double result = 1.; - - if (r < 0.) - r = -r; - - if (r < 1.) { - while (result >= r) {result *= .1; i++;} - return (-i); - } else { - while (result <= r) {result *= 10.; i++;} - return (i - 1); - } -} - -/* - * This function return the fraction part of a double - * and set in ip the integral part. - * In many ways it resemble the modf() found on most Un*x - */ -PRIVATE double -#ifdef __STDC__ -integral(double real, double * ip) -#else -integral(real, ip) -double real; -double * ip; -#endif -{ - int j; - double i, s, p; - double real_integral = 0.; - -/* take care of the obvious */ -/* equal to zero ? */ - if (real == 0.) { - *ip = 0.; - return (0.); - } - -/* negative number ? */ - if (real < 0.) - real = -real; - -/* a fraction ? */ - if ( real < 1.) { - *ip = 0.; - return real; - } -/* the real work :-) */ - for (j = log_10(real); j >= 0; j--) { - p = pow_10(j); - s = (real - real_integral)/p; - i = 0.; - while (i + 1. <= s) {i++;} - real_integral += i*p; - } - *ip = real_integral; - return (real - real_integral); -} - -#define PRECISION 1.e-6 -/* - * return an ascii representation of the integral part of the number - * and set fract to be an ascii representation of the fraction part - * the container for the fraction and the integral part or staticly - * declare with fix size - */ -PRIVATE char * -#ifdef __STDC__ -numtoa(double number, int base, int precision, char ** fract) -#else -numtoa(number, base, precision, fract) -double number; -int base; -int precision; -char ** fract; -#endif -{ - register int i, j; - double ip, fp; /* integer and fraction part */ - double fraction; - int digits = MAX_INT - 1; - static char integral_part[MAX_INT]; - static char fraction_part[MAX_FRACT]; - double sign; - int ch; - -/* taking care of the obvious case: 0.0 */ - if (number == 0.) { - integral_part[0] = '0'; - integral_part[1] = '\0'; - fraction_part[0] = '0'; - fraction_part[1] = '\0'; - return integral_part; - } - -/* for negative numbers */ - if ((sign = number) < 0.) { - number = -number; - digits--; /* sign consume one digit */ - } - - fraction = integral(number, &ip); - number = ip; -/* do the integral part */ - if ( ip == 0.) { - integral_part[0] = '0'; - i = 1; - } else { - for ( i = 0; i < digits && number != 0.; ++i) { - number /= base; - fp = integral(number, &ip); - ch = (int)((fp + PRECISION)*base); /* force to round */ - integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10; - if (! isxdigit(integral_part[i])) /* bail out overflow !! */ - break; - number = ip; - } - } - -/* Oh No !! out of bound, ho well fill it up ! */ - if (number != 0.) - for (i = 0; i < digits; ++i) - integral_part[i] = '9'; + GNU General Public License for more details. -/* put the sign ? */ - if (sign < 0.) - integral_part[i++] = '-'; + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - integral_part[i] = '\0'; - -/* reverse every thing */ - for ( i--, j = 0; j < i; j++, i--) - SWAP_INT(integral_part[i], integral_part[j]); - -/* the fractionnal part */ - for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision-- ) { - fraction_part[i] = (int)((fp + PRECISION)*10. + '0'); - if (! isdigit(fraction_part[i])) /* underflow ? */ - break; - fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.); - } - fraction_part[i] = '\0'; - - if (fract != (char **)0) - *fract = fraction_part; - - return integral_part; - -} - -/* for %d and friends, it puts in holder - * the representation with the right padding - */ -PRIVATE void -#ifdef __STDC__ -decimal(struct DATA *p, double d) -#else -decimal(p, d) -struct DATA *p; -double d; +#ifdef HAVE_CONFIG_H +# include <config.h> #endif -{ - char *tmp; - tmp = itoa(d); - p->width -= strlen(tmp); - PAD_RIGHT(p); - PUT_PLUS(d, p); - PUT_SPACE(d, p); - while (*tmp) { /* the integral */ - PUT_CHAR(*tmp, p); - tmp++; - } - PAD_LEFT(p); -} - -/* for %o octal representation */ -PRIVATE void -#ifdef __STDC__ -octal(struct DATA *p, double d) -#else -octal(p, d) -struct DATA *p; -double d; -#endif -{ - char *tmp; - - tmp = otoa(d); - p->width -= strlen(tmp); - PAD_RIGHT(p); - if (p->square == FOUND) /* had prefix '0' for octal */ - PUT_CHAR('0', p); - while (*tmp) { /* octal */ - PUT_CHAR(*tmp, p); - tmp++; - } - PAD_LEFT(p); -} - -/* for %x %X hexadecimal representation */ -PRIVATE void -#ifdef __STDC__ -hexa(struct DATA *p, double d) -#else -hexa(p, d) -struct DATA *p; -double d; -#endif -{ - char *tmp; - - tmp = htoa(d); - p->width -= strlen(tmp); - PAD_RIGHT(p); - if (p->square == FOUND) { /* prefix '0x' for hexa */ - PUT_CHAR('0', p); PUT_CHAR(*p->pf, p); - } - while (*tmp) { /* hexa */ - PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p); - tmp++; - } - PAD_LEFT(p); -} - -/* %s strings */ -PRIVATE void -#ifdef __STDC__ -strings(struct DATA *p, char *tmp) -#else -strings(p, tmp) -struct DATA *p; -char *tmp; -#endif -{ - int i; - - i = strlen(tmp); - if (p->precision != NOT_FOUND) /* the smallest number */ - i = (i < p->precision ? i : p->precision); - p->width -= i; - PAD_RIGHT(p); - while (i-- > 0) { /* put the sting */ - PUT_CHAR(*tmp, p); - tmp++; - } - PAD_LEFT(p); -} - -/* %f or %g floating point representation */ -PRIVATE void -#ifdef __STDC__ -floating(struct DATA *p, double d) -#else -floating(p, d) -struct DATA *p; -double d; -#endif -{ - char *tmp, *tmp2; - int i; - - DEF_PREC(p); - d = ROUND(d, p); - tmp = dtoa(d, p->precision, &tmp2); - /* calculate the padding. 1 for the dot */ - p->width = p->width - - ((d > 0. && p->justify == RIGHT) ? 1:0) - - ((p->space == FOUND) ? 1:0) - - strlen(tmp) - p->precision - 1; - PAD_RIGHT(p); - PUT_PLUS(d, p); - PUT_SPACE(d, p); - while (*tmp) { /* the integral */ - PUT_CHAR(*tmp, p); - tmp++; - } - if (p->precision != 0 || p->square == FOUND) - PUT_CHAR('.', p); /* put the '.' */ - if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ - for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) - tmp2[i] = '\0'; - for (; *tmp2; tmp2++) - PUT_CHAR(*tmp2, p); /* the fraction */ - - PAD_LEFT(p); -} - -/* %e %E %g exponent representation */ -PRIVATE void -#ifdef __STDC__ -exponent(struct DATA *p, double d) -#else -exponent(p, d) -struct DATA *p; -double d; -#endif -{ - char *tmp, *tmp2; - int j, i; - - DEF_PREC(p); - j = log_10(d); - d = d / pow_10(j); /* get the Mantissa */ - d = ROUND(d, p); - tmp = dtoa(d, p->precision, &tmp2); - /* 1 for unit, 1 for the '.', 1 for 'e|E', - * 1 for '+|-', 3 for 'exp' */ - /* calculate how much padding need */ - p->width = p->width - - ((d > 0. && p->justify == RIGHT) ? 1:0) - - ((p->space == FOUND) ? 1:0) - p->precision - 7; - PAD_RIGHT(p); - PUT_PLUS(d, p); - PUT_SPACE(d, p); - while (*tmp) {/* the integral */ - PUT_CHAR(*tmp, p); - tmp++; - } - if (p->precision != 0 || p->square == FOUND) - PUT_CHAR('.', p); /* the '.' */ - if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ - for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) - tmp2[i] = '\0'; - for (; *tmp2; tmp2++) - PUT_CHAR(*tmp2, p); /* the fraction */ - - if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */ - PUT_CHAR('e', p); - } else - PUT_CHAR('E', p); - if (j >= 0) { /* the sign of the exp */ - PUT_CHAR('+', p); - } else { - PUT_CHAR('-', p); - j = -j; - } - tmp = itoa((double)j); - if (j < 9) { /* need to pad the exponent with 0 '000' */ - PUT_CHAR('0', p); PUT_CHAR('0', p); - } else if (j < 99) - PUT_CHAR('0', p); - while (*tmp) { /* the exponent */ - PUT_CHAR(*tmp, p); - tmp++; - } - PAD_LEFT(p); -} - -/* initialize the conversion specifiers */ -PRIVATE void -#ifdef __STDC__ -conv_flag(char * s, struct DATA * p) -#else -conv_flag(s, p) -char * s; -struct DATA * p; -#endif -{ - char number[MAX_FIELD/2]; - int i; - - /* reset the flags. */ - p->precision = p->width = NOT_FOUND; - p->star_w = p->star_p = NOT_FOUND; - p->square = p->space = NOT_FOUND; - p->a_long = p->justify = NOT_FOUND; - p->a_longlong = NOT_FOUND; - p->pad = ' '; - - for(;s && *s ;s++) { - switch(*s) { - case ' ': p->space = FOUND; break; - case '#': p->square = FOUND; break; - case '*': if (p->width == NOT_FOUND) - p->width = p->star_w = FOUND; - else - p->precision = p->star_p = FOUND; - break; - case '+': p->justify = RIGHT; break; - case '-': p->justify = LEFT; break; - case '.': if (p->width == NOT_FOUND) - p->width = 0; - break; - case '0': p->pad = '0'; break; - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': /* gob all the digits */ - for (i = 0; isdigit(*s); i++, s++) - if (i < MAX_FIELD/2 - 1) - number[i] = *s; - number[i] = '\0'; - if (p->width == NOT_FOUND) - p->width = atoi(number); - else - p->precision = atoi(number); - s--; /* went to far go back */ - break; - } - } -} - -PUBLIC int -#ifdef __STDC__ -vsnprintf(char *string, size_t length, const char * format, va_list args) -#else -vsnprintf(string, length, format, args) -char *string; -size_t length; -char * format; -va_list args; -#endif -{ - struct DATA data; - char conv_field[MAX_FIELD]; - double d; /* temporary holder */ - int state; - int i; - - data.length = length - 1; /* leave room for '\0' */ - data.holder = string; - data.pf = format; - data.counter = 0; - - -/* sanity check, the string must be > 1 */ - if (length < 1) - return -1; - - - for (; *data.pf && (data.counter < data.length); data.pf++) { - if ( *data.pf == '%' ) { /* we got a magic % cookie */ - conv_flag((char *)0, &data); /* initialise format flags */ - for (state = 1; *data.pf && state;) { - switch (*(++data.pf)) { - case '\0': /* a NULL here ? ? bail out */ - *data.holder = '\0'; - return data.counter; - break; - case 'f': /* float, double */ - STAR_ARGS(&data); - if (data.a_long == FOUND) - d = va_arg(args, LONG_DOUBLE); - else - d = va_arg(args, double); - floating(&data, d); - state = 0; - break; - case 'g': - case 'G': - STAR_ARGS(&data); - DEF_PREC(&data); - if (data.a_long == FOUND) - d = va_arg(args, LONG_DOUBLE); - else - d = va_arg(args, double); - i = log_10(d); - /* - * for '%g|%G' ANSI: use f if exponent - * is in the range or [-4,p] exclusively - * else use %e|%E - */ - if (-4 < i && i < data.precision) - floating(&data, d); - else - exponent(&data, d); - state = 0; - break; - case 'e': - case 'E': /* Exponent double */ - STAR_ARGS(&data); - if (data.a_long == FOUND) - d = va_arg(args, LONG_DOUBLE); - else - d = va_arg(args, double); - exponent(&data, d); - state = 0; - break; - case 'u': /* unsigned decimal */ - STAR_ARGS(&data); - if (data.a_longlong == FOUND) - d = va_arg(args, unsigned LONG_LONG); - else if (data.a_long == FOUND) - d = va_arg(args, unsigned long); - else - d = va_arg(args, unsigned int); - decimal(&data, d); - state = 0; - break; - case 'd': /* decimal */ - STAR_ARGS(&data); - if (data.a_longlong == FOUND) - d = va_arg(args, LONG_LONG); - else if (data.a_long == FOUND) - d = va_arg(args, long); - else - d = va_arg(args, int); - decimal(&data, d); - state = 0; - break; - case 'o': /* octal */ - STAR_ARGS(&data); - if (data.a_longlong == FOUND) - d = va_arg(args, LONG_LONG); - else if (data.a_long == FOUND) - d = va_arg(args, long); - else - d = va_arg(args, int); - octal(&data, d); - state = 0; - break; - case 'x': - case 'X': /* hexadecimal */ - STAR_ARGS(&data); - if (data.a_longlong == FOUND) - d = va_arg(args, LONG_LONG); - else if (data.a_long == FOUND) - d = va_arg(args, long); - else - d = va_arg(args, int); - hexa(&data, d); - state = 0; - break; - case 'c': /* character */ - d = va_arg(args, int); - PUT_CHAR(d, &data); - state = 0; - break; - case 's': /* string */ - STAR_ARGS(&data); - strings(&data, va_arg(args, char *)); - state = 0; - break; - case 'n': - *(va_arg(args, int *)) = data.counter; /* what's the count ? */ - state = 0; - break; - case 'q': - data.a_longlong = FOUND; - break; - case 'L': - case 'l': - if (data.a_long == FOUND) - data.a_longlong = FOUND; - else - data.a_long = FOUND; - break; - case 'h': - break; - case '%': /* nothing just % */ - PUT_CHAR('%', &data); - state = 0; - break; - case '#': case ' ': case '+': case '*': - case '-': case '.': case '0': case '1': - case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - /* initialize width and precision */ - for (i = 0; isflag(*data.pf); i++, data.pf++) - if (i < MAX_FIELD - 1) - conv_field[i] = *data.pf; - conv_field[i] = '\0'; - conv_flag(conv_field, &data); - data.pf--; /* went to far go back */ - break; - default: - /* is this an error ? maybe bail out */ - state = 0; - break; - } /* end switch */ - } /* end of for state */ - } else { /* not % */ - PUT_CHAR(*data.pf, &data); /* add the char the string */ - } - } - - *data.holder = '\0'; /* the end ye ! */ +#include "snprintf.h" - return data.counter; -} +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> -#ifndef HAVE_SNPRINTF +#include "minmax.h" +#include "vasnprintf.h" -PUBLIC int -#if __STDC__ -snprintf(char *string, size_t length, const char * format, ...) -#else -snprintf(string, length, format, va_alist) -char *string; -size_t length; -char * format; -va_dcl -#endif +/* Print formatted output to string STR. Similar to sprintf, but + additional length SIZE limit how much is written into STR. Returns + string length of formatted string (which may be larger than SIZE). + STR may be NULL, in which case nothing will be written. On error, + return a negative value. */ +int +snprintf (char *str, size_t size, const char *format, ...) { - int rval; + char *output; + size_t len; va_list args; -#if __STDC__ - va_start(args, format); -#else - va_start(args); -#endif - - rval = vsnprintf (string, length, format, args); - - va_end(args); - - return rval; -} - -#endif /* HAVE_SNPRINTF */ - - -#ifdef DRIVER - -#include <stdio.h> - -/* set of small tests for snprintf() */ -int main() -{ - char holder[100]; - int i; + va_start (args, format); + len = size; + output = vasnprintf (str, &len, format, args); + va_end (args); -/* - printf("Suite of test for snprintf:\n"); - printf("a_format\n"); - printf("printf() format\n"); - printf("snprintf() format\n\n"); -*/ -/* Checking the field widths */ - - printf("/%%d/, 336\n"); - snprintf(holder, sizeof holder, "/%d/\n", 336); - printf("/%d/\n", 336); - printf("%s\n", holder); - - printf("/%%2d/, 336\n"); - snprintf(holder, sizeof holder, "/%2d/\n", 336); - printf("/%2d/\n", 336); - printf("%s\n", holder); - - printf("/%%10d/, 336\n"); - snprintf(holder, sizeof holder, "/%10d/\n", 336); - printf("/%10d/\n", 336); - printf("%s\n", holder); - - printf("/%%-10d/, 336\n"); - snprintf(holder, sizeof holder, "/%-10d/\n", 336); - printf("/%-10d/\n", 336); - printf("%s\n", holder); - -/* long long */ - - printf("/%%lld/, 336\n"); - snprintf(holder, sizeof holder, "/%lld/\n", (LONG_LONG)336); - printf("/%lld/\n", (LONG_LONG)336); - printf("%s\n", holder); - - printf("/%%2qd/, 336\n"); - snprintf(holder, sizeof holder, "/%2qd/\n", (LONG_LONG)336); - printf("/%2qd/\n", (LONG_LONG)336); - printf("%s\n", holder); - -/* floating points */ - - printf("/%%f/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%f/\n", 1234.56); - printf("/%f/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%e/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%e/\n", 1234.56); - printf("/%e/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%4.2f/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56); - printf("/%4.2f/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%3.1f/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56); - printf("/%3.1f/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%10.3f/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56); - printf("/%10.3f/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%10.3e/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56); - printf("/%10.3e/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%+4.2f/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56); - printf("/%+4.2f/\n", 1234.56); - printf("%s\n", holder); - - printf("/%%010.2f/, 1234.56\n"); - snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56); - printf("/%010.2f/\n", 1234.56); - printf("%s\n", holder); - -#define BLURB "Outstanding acting !" -/* strings precisions */ - - printf("/%%2s/, \"%s\"\n", BLURB); - snprintf(holder, sizeof holder, "/%2s/\n", BLURB); - printf("/%2s/\n", BLURB); - printf("%s\n", holder); - - printf("/%%22s/ %s\n", BLURB); - snprintf(holder, sizeof holder, "/%22s/\n", BLURB); - printf("/%22s/\n", BLURB); - printf("%s\n", holder); - - printf("/%%22.5s/ %s\n", BLURB); - snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB); - printf("/%22.5s/\n", BLURB); - printf("%s\n", holder); - - printf("/%%-22.5s/ %s\n", BLURB); - snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB); - printf("/%-22.5s/\n", BLURB); - printf("%s\n", holder); - -/* see some flags */ - - printf("%%x %%X %%#x, 31, 31, 31\n"); - snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31); - printf("%x %X %#x\n", 31, 31, 31); - printf("%s\n", holder); - - printf("**%%d**%% d**%% d**, 42, 42, -42\n"); - snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42); - printf("**%d**% d**% d**\n", 42, 42, -42); - printf("%s\n", holder); - -/* other flags */ - - printf("/%%g/, 31.4\n"); - snprintf(holder, sizeof holder, "/%g/\n", 31.4); - printf("/%g/\n", 31.4); - printf("%s\n", holder); - - printf("/%%.6g/, 31.4\n"); - snprintf(holder, sizeof holder, "/%.6g/\n", 31.4); - printf("/%.6g/\n", 31.4); - printf("%s\n", holder); - - printf("/%%.1G/, 31.4\n"); - snprintf(holder, sizeof holder, "/%.1G/\n", 31.4); - printf("/%.1G/\n", 31.4); - printf("%s\n", holder); - - printf("abc%%n\n"); - printf("abc%n", &i); printf("%d\n", i); - snprintf(holder, sizeof holder, "abc%n", &i); - printf("%s", holder); printf("%d\n\n", i); - - printf("%%*.*s --> 10.10\n"); - snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB); - printf("%*.*s\n", 10, 10, BLURB); - printf("%s\n", holder); + if (!output) + return -1; - printf("%%%%%%%%\n"); - snprintf(holder, sizeof holder, "%%%%\n"); - printf("%%%%\n"); - printf("%s\n", holder); + if (str != NULL) + if (len > size - 1) /* equivalent to: (size > 0 && len >= size) */ + str[size - 1] = '\0'; -#define BIG "Hello this is a too big string for the buffer" -/* printf("A buffer to small of 10, trying to put this:\n");*/ - printf("<%%>, %s\n", BIG); - i = snprintf(holder, 10, "%s\n", BIG); - printf("<%s>\n", BIG); - printf("<%s>\n", holder); + if (output != str) + free (output); - return 0; + return len; } -#endif diff --git a/lib/snprintf.h b/lib/snprintf.h index 7a8ad40..a72f74d 100644 --- a/lib/snprintf.h +++ b/lib/snprintf.h @@ -1,218 +1,29 @@ -/* - Unix snprintf implementation. - Version 1.3 +/* Formatted output to strings. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by Simon Josefsson. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, 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 Library General Public License for more details. + GNU General Public License for more details. - You should have received a copy of the GNU Library General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - Revision History: - see header of snprintf.c. +#ifndef SNPRINTF_H +#define SNPRINTF_H -format: - int snprintf(holder, sizeof_holder, format, ...) +/* Get snprintf declaration, if available. */ +#include <stdio.h> -Return values: - (sizeof_holder - 1) - - - THANKS(for the patches and ideas): - Miles Bader - Cyrille Rustom - Jacek Slabocewiz - Mike Parker(mouse) - -Alain Magloire: alainm@rcsm.ee.mcgill.ca -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -#include <stdlib.h> /* for atoi() */ -#include <ctype.h> - - -/* - * For the FLOATING POINT FORMAT : - * the challenge was finding a way to - * manipulate the Real numbers without having - * to resort to mathematical function(it - * would require to link with -lm) and not - * going down to the bit pattern(not portable) - * - * so a number, a real is: - - real = integral + fraction - - integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0 - fraction = b(1)*10^-1 + b(2)*10^-2 + ... - - where: - 0 <= a(i) => 9 - 0 <= b(i) => 9 - - from then it was simple math - */ - -/* - * size of the buffer for the integral part - * and the fraction part - */ -#define MAX_INT 99 + 1 /* 1 for the null */ -#define MAX_FRACT 29 + 1 - -/* - * If the compiler supports (long long) - */ -#ifndef LONG_LONG -# define LONG_LONG long long -/*# define LONG_LONG int64_t*/ -#endif - -/* - * If the compiler supports (long double) - */ -#ifndef LONG_DOUBLE -# define LONG_DOUBLE long double -/*# define LONG_DOUBLE double*/ +#if defined HAVE_DECL_SNPRINTF && !HAVE_DECL_SNPRINTF +int snprintf (char *str, size_t size, const char *format, ...); #endif -/* - * numtoa() uses PRIVATE buffers to store the results, - * So this function is not reentrant - */ -#define itoa(n) numtoa(n, 10, 0, (char **)0) -#define otoa(n) numtoa(n, 8, 0, (char **)0) -#define htoa(n) numtoa(n, 16, 0, (char **)0) -#define dtoa(n, p, f) numtoa(n, 10, p, f) - -#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;} - -/* this struct holds everything we need */ -struct DATA { - int length; - char *holder; - int counter; -#ifdef __STDC__ - const char *pf; -#else - char *pf; -#endif -/* FLAGS */ - int width, precision; - int justify; char pad; - int square, space, star_w, star_p, a_long, a_longlong; -}; - -#define PRIVATE static -#define PUBLIC -/* signature of the functions */ -#ifdef __STDC__ -/* the floating point stuff */ - PRIVATE double pow_10(int); - PRIVATE int log_10(double); - PRIVATE double integral(double, double *); - PRIVATE char * numtoa(double, int, int, char **); - -/* for the format */ - PRIVATE void conv_flag(char *, struct DATA *); - PRIVATE void floating(struct DATA *, double); - PRIVATE void exponent(struct DATA *, double); - PRIVATE void decimal(struct DATA *, double); - PRIVATE void octal(struct DATA *, double); - PRIVATE void hexa(struct DATA *, double); - PRIVATE void strings(struct DATA *, char *); - -#else -/* the floating point stuff */ - PRIVATE double pow_10(); - PRIVATE int log_10(); - PRIVATE double integral(); - PRIVATE char * numtoa(); - -/* for the format */ - PRIVATE void conv_flag(); - PRIVATE void floating(); - PRIVATE void exponent(); - PRIVATE void decimal(); - PRIVATE void octal(); - PRIVATE void hexa(); - PRIVATE void strings(); -#endif - -/* those are defines specific to snprintf to hopefully - * make the code clearer :-) - */ -#define RIGHT 1 -#define LEFT 0 -#define NOT_FOUND -1 -#define FOUND 1 -#define MAX_FIELD 15 - -/* the conversion flags */ -#define isflag(c) ((c) == '#' || (c) == ' ' || \ - (c) == '*' || (c) == '+' || \ - (c) == '-' || (c) == '.' || \ - isdigit(c)) - -/* round off to the precision */ -#define ROUND(d, p) \ - (d < 0.) ? \ - d - pow_10(-(p)->precision) * 0.5 : \ - d + pow_10(-(p)->precision) * 0.5 - -/* set default precision */ -#define DEF_PREC(p) \ - if ((p)->precision == NOT_FOUND) \ - (p)->precision = 6 - -/* put a char */ -#define PUT_CHAR(c, p) \ - if ((p)->counter < (p)->length) { \ - *(p)->holder++ = (c); \ - (p)->counter++; \ - } - -#define PUT_PLUS(d, p) \ - if ((d) > 0. && (p)->justify == RIGHT) \ - PUT_CHAR('+', p) - -#define PUT_SPACE(d, p) \ - if ((p)->space == FOUND && (d) > 0.) \ - PUT_CHAR(' ', p) - -/* pad right */ -#define PAD_RIGHT(p) \ - if ((p)->width > 0 && (p)->justify != LEFT) \ - for (; (p)->width > 0; (p)->width--) \ - PUT_CHAR((p)->pad, p) - -/* pad left */ -#define PAD_LEFT(p) \ - if ((p)->width > 0 && (p)->justify == LEFT) \ - for (; (p)->width > 0; (p)->width--) \ - PUT_CHAR((p)->pad, p) - -/* if width and prec. in the args */ -#define STAR_ARGS(p) \ - if ((p)->star_w == FOUND) \ - (p)->width = va_arg(args, int); \ - if ((p)->star_p == FOUND) \ - (p)->precision = va_arg(args, int) +#endif /* SNPRINTF_H */ diff --git a/lib/vasprintf.c b/lib/vasprintf.c index 3b6aa38..ba94c64 100644 --- a/lib/vasprintf.c +++ b/lib/vasprintf.c @@ -1,194 +1,42 @@ -/* Like vsprintf but provides a pointer to malloc'd storage, which must - be freed by the caller. - Copyright (C) 1994 Free Software Foundation, Inc. +/* Formatted output to strings. + Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc. -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, or (at your option) -any later version. + 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, 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. + 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, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif -#include <stdio.h> -#include <string.h> +/* Specification. */ +#include "vasprintf.h" -#if __STDC__ -# include <stdarg.h> -#else -# include <varargs.h> -#endif - -#ifdef TEST -int global_total_width; -#endif - -unsigned long strtoul (); -char *malloc (); - -static int -int_vasprintf (result, format, args) - char **result; - const char *format; - va_list *args; -{ - const char *p = format; - /* Add one to make sure that it is never zero, which might cause malloc - to return NULL. */ - int total_width = strlen (format) + 1; - va_list ap; - - memcpy (&ap, args, sizeof (va_list)); - - while (*p != '\0') - { - if (*p++ == '%') - { - while (strchr ("-+ #0", *p)) - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - total_width += strtoul (p, &p, 10); - if (*p == '.') - { - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - total_width += strtoul (p, &p, 10); - } - while (strchr ("hlL", *p)) - ++p; - /* Should be big enough for any format specifier except %s. */ - total_width += 30; - switch (*p) - { - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - case 'c': - (void) va_arg (ap, int); - break; - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - (void) va_arg (ap, double); - break; - case 's': - total_width += strlen (va_arg (ap, char *)); - break; - case 'p': - case 'n': - (void) va_arg (ap, char *); - break; - } - } - } -#ifdef TEST - global_total_width = total_width; -#endif - *result = malloc (total_width); - if (*result != NULL) - return vsprintf (*result, format, *args); - else - return 0; -} - -int -vasprintf (result, format, args) - char **result; - const char *format; - va_list args; -{ - return int_vasprintf (result, format, &args); -} - -int -asprintf -#if __STDC__ - (char **result, const char *format, ...) -#else - (result, va_alist) - char **result; - va_dcl -#endif -{ - va_list args; - int done; - -#if __STDC__ - va_start (args, format); -#else - char *format; - va_start (args); - format = va_arg (args, char *); -#endif - done = vasprintf (result, format, args); - va_end (args); +#include <stdlib.h> - return done; -} - -#ifdef TEST -void -checkit -#if __STDC__ - (const char* format, ...) -#else - (va_alist) - va_dcl -#endif -{ - va_list args; - char *result; - -#if __STDC__ - va_start (args, format); -#else - char *format; - va_start (args); - format = va_arg (args, char *); -#endif - vasprintf (&result, format, args); - va_end (args); - if (strlen (result) < global_total_width) - printf ("PASS: "); - else - printf ("FAIL: "); - printf ("%d %s\n", global_total_width, result); -} +#include "vasnprintf.h" int -main () +vasprintf (char **resultp, const char *format, va_list args) { - checkit ("%d", 0x12345678); - checkit ("%200d", 5); - checkit ("%.300d", 6); - checkit ("%100.150d", 7); - checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\ -777777777777777777333333333333366666666666622222222222777777777777733333"); - checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"); + size_t length; + char *result = vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + *resultp = result; + /* Return the number of resulting bytes, excluding the trailing NUL. + If it wouldn't fit in an 'int', vasnprintf() would have returned NULL + and set errno to EOVERFLOW. */ + return length; } -#endif /* TEST */ diff --git a/lib/xalloc.h b/lib/xalloc.h index 8668e19..8d0fcf0 100644 --- a/lib/xalloc.h +++ b/lib/xalloc.h @@ -1,5 +1,7 @@ /* xalloc.h -- malloc with out-of-memory checking - Copyright (C) 1990-1998, 1999 Free Software Foundation, Inc. + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2003, 2004 Free Software Foundation, Inc. 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 @@ -18,14 +20,14 @@ #ifndef XALLOC_H_ # define XALLOC_H_ -# ifndef PARAMS -# if defined PROTOTYPES || (defined __STDC__ && __STDC__) -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif +# include <stddef.h> + + +# ifdef __cplusplus +extern "C" { # endif + # ifndef __attribute__ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ # define __attribute__(x) @@ -36,52 +38,42 @@ # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) # endif -/* Exit value when the requested amount of memory is not available. - It is initialized to EXIT_FAILURE, but the caller may set it to - some other value. */ -extern int xalloc_exit_failure; - -/* If this pointer is non-zero, run the specified function upon each - allocation failure. It is initialized to zero. */ -extern void (*xalloc_fail_func) PARAMS ((void)); - -/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this - message must be non-NULL. It is translated via gettext. - The default value is "Memory exhausted". */ -extern char *const xalloc_msg_memory_exhausted; - -/* This function is always triggered when memory is exhausted. It is - in charge of honoring the three previous items. This is the +/* This function is always triggered when memory is exhausted. + It must be defined by the application, either explicitly + or by using gnulib's xalloc-die module. This is the function to call when one wants the program to die because of a memory allocation failure. */ -extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN; - -void *xmalloc PARAMS ((size_t n)); -void *xcalloc PARAMS ((size_t n, size_t s)); -void *xrealloc PARAMS ((void *p, size_t n)); -char *xstrdup PARAMS ((const char *str)); - -# define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items))) -# define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items))) -# define XREALLOC(Ptr, Type, N_items) \ - ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items))) - -/* Declare and alloc memory for VAR of type TYPE. */ -# define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1) - -/* Free VAR only if non NULL. */ -# define XFREE(Var) \ - do { \ - if (Var) \ - free (Var); \ - } while (0) - -/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */ -# define CCLONE(Src, Num) \ - (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num))) - -/* Return a malloc'ed copy of SRC. */ -# define CLONE(Src) CCLONE (Src, 1) +extern void xalloc_die (void) ATTRIBUTE_NORETURN; + +void *xmalloc (size_t s); +void *xnmalloc (size_t n, size_t s); +void *xzalloc (size_t s); +void *xcalloc (size_t n, size_t s); +void *xrealloc (void *p, size_t s); +void *xnrealloc (void *p, size_t n, size_t s); +void *x2realloc (void *p, size_t *pn); +void *x2nrealloc (void *p, size_t *pn, size_t s); +void *xmemdup (void const *p, size_t s); +char *xstrdup (char const *str); + +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + +# ifdef __cplusplus +} +# endif #endif /* !XALLOC_H_ */ diff --git a/lib/xmalloc.c b/lib/xmalloc.c index a71dc35..13c2490 100644 --- a/lib/xmalloc.c +++ b/lib/xmalloc.c @@ -1,5 +1,7 @@ /* xmalloc.c -- malloc with out of memory checking - Copyright (C) 1990-1997, 98, 99 Free Software Foundation, Inc. + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. 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 @@ -19,64 +21,31 @@ # include <config.h> #endif -#include <sys/types.h> - -#include <mailutils/error.h> - -#if STDC_HEADERS -# include <stdlib.h> -#else -void *calloc (); -void *malloc (); -void *realloc (); -void free (); -#endif - -#if ENABLE_NLS -# include <libintl.h> -# define _(Text) gettext (Text) -#else -# define textdomain(Domain) -# define _(Text) Text -#endif -#define N_(Text) Text - -#include "error.h" #include "xalloc.h" -#ifndef EXIT_FAILURE -# define EXIT_FAILURE 1 -#endif - -#ifndef HAVE_MALLOC -# error "you must run the autoconf test for a properly working malloc -- see malloc.m4" -#endif +#include <stdlib.h> +#include <string.h> -#ifndef HAVE_REALLOC -# error "you must run the autoconf test for a properly working realloc -- see realloc.m4" +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) #endif -/* Exit value when the requested amount of memory is not available. - The caller may set it to some other value. */ -int xalloc_exit_failure = EXIT_FAILURE; - -/* If non NULL, call this function when memory is exhausted. */ -void (*xalloc_fail_func) PARAMS ((void)) = 0; +/* Allocate an array of N objects, each with S bytes of memory, + dynamically, with error checking. S must be nonzero. */ -/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message - before exiting when memory is exhausted. Goes through gettext. */ -char *const xalloc_msg_memory_exhausted = N_("Memory exhausted"); +static inline void * +xnmalloc_inline (size_t n, size_t s) +{ + void *p; + if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0)) + xalloc_die (); + return p; +} -void -xalloc_die (void) +void * +xnmalloc (size_t n, size_t s) { - if (xalloc_fail_func) - (*xalloc_fail_func) (); - mu_error ("%s", _(xalloc_msg_memory_exhausted)); - /* The `noreturn' cannot be given to error, since it may return if - its first argument is 0. To help compilers understand the - xalloc_die does terminate, call exit. */ - exit (xalloc_exit_failure); + return xnmalloc_inline (n, s); } /* Allocate N bytes of memory dynamically, with error checking. */ @@ -84,36 +53,177 @@ xalloc_die (void) void * xmalloc (size_t n) { - void *p; + return xnmalloc_inline (n, 1); +} + +/* Change the size of an allocated block of memory P to an array of N + objects each of S bytes, with error checking. S must be nonzero. */ - p = malloc (n); - if (p == 0) +static inline void * +xnrealloc_inline (void *p, size_t n, size_t s) +{ + if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0)) xalloc_die (); return p; } +void * +xnrealloc (void *p, size_t n, size_t s) +{ + return xnrealloc_inline (p, n, s); +} + /* Change the size of an allocated block of memory P to N bytes, - with error checking. - If P is NULL, run xmalloc. */ + with error checking. */ void * xrealloc (void *p, size_t n) { - p = realloc (p, n); - if (p == 0) - xalloc_die (); - return p; + return xnrealloc_inline (p, n, 1); } -/* Allocate memory for N elements of S bytes, with error checking. */ + +/* If P is null, allocate a block of at least *PN such objects; + otherwise, reallocate P so that it contains more than *PN objects + each of S bytes. *PN must be nonzero unless P is null, and S must + be nonzero. Set *PN to the new number of objects, and return the + pointer to the new block. *PN is never set to zero, and the + returned pointer is never null. + + Repeated reallocations are guaranteed to make progress, either by + allocating an initial block with a nonzero size, or by allocating a + larger block. + + In the following implementation, nonzero sizes are doubled so that + repeated reallocations have O(N log N) overall cost rather than + O(N**2) cost, but the specification for this function does not + guarantee that sizes are doubled. + + Here is an example of use: + + int *p = NULL; + size_t used = 0; + size_t allocated = 0; + + void + append_int (int value) + { + if (used == allocated) + p = x2nrealloc (p, &allocated, sizeof *p); + p[used++] = value; + } + + This causes x2nrealloc to allocate a block of some nonzero size the + first time it is called. + + To have finer-grained control over the initial size, set *PN to a + nonzero value before calling this function with P == NULL. For + example: + + int *p = NULL; + size_t used = 0; + size_t allocated = 0; + size_t allocated1 = 1000; + + void + append_int (int value) + { + if (used == allocated) + { + p = x2nrealloc (p, &allocated1, sizeof *p); + allocated = allocated1; + } + p[used++] = value; + } + + */ + +static inline void * +x2nrealloc_inline (void *p, size_t *pn, size_t s) +{ + size_t n = *pn; + + if (! p) + { + if (! n) + { + /* The approximate size to use for initial small allocation + requests, when the invoking code specifies an old size of + zero. 64 bytes is the largest "small" request for the + GNU C library malloc. */ + enum { DEFAULT_MXFAST = 64 }; + + n = DEFAULT_MXFAST / s; + n += !n; + } + } + else + { + if (SIZE_MAX / 2 / s < n) + xalloc_die (); + n *= 2; + } + + *pn = n; + return xrealloc (p, n * s); +} + +void * +x2nrealloc (void *p, size_t *pn, size_t s) +{ + return x2nrealloc_inline (p, pn, s); +} + +/* If P is null, allocate a block of at least *PN bytes; otherwise, + reallocate P so that it contains more than *PN bytes. *PN must be + nonzero unless P is null. Set *PN to the new block's size, and + return the pointer to the new block. *PN is never set to zero, and + the returned pointer is never null. */ + +void * +x2realloc (void *p, size_t *pn) +{ + return x2nrealloc_inline (p, pn, 1); +} + +/* Allocate S bytes of zeroed memory dynamically, with error checking. + There's no need for xnzalloc (N, S), since it would be equivalent + to xcalloc (N, S). */ + +void * +xzalloc (size_t s) +{ + return memset (xmalloc (s), 0, s); +} + +/* Allocate zeroed memory for N elements of S bytes, with error + checking. S must be nonzero. */ void * xcalloc (size_t n, size_t s) { void *p; - - p = calloc (n, s); - if (p == 0) + /* Test for overflow, since some calloc implementations don't have + proper overflow checks. */ + if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0)) xalloc_die (); return p; } + +/* Clone an object P of size S, with error checking. There's no need + for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any + need for an arithmetic overflow check. */ + +void * +xmemdup (void const *p, size_t s) +{ + return memcpy (xmalloc (s), p, s); +} + +/* Clone STRING. */ + +char * +xstrdup (char const *string) +{ + return xmemdup (string, strlen (string) + 1); +} diff --git a/lib/xstrtol.c b/lib/xstrtol.c index e7b2061..906e4a1 100644 --- a/lib/xstrtol.c +++ b/lib/xstrtol.c @@ -1,5 +1,7 @@ /* A more useful interface to strtol. - Copyright 1995, 1996, 1998, 1999 Free Software Foundation, Inc. + + Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2004 Free + Software Foundation, Inc. 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 @@ -25,48 +27,32 @@ # define __strtol strtol # define __strtol_t long int # define __xstrtol xstrtol +# define STRTOL_T_MINIMUM LONG_MIN +# define STRTOL_T_MAXIMUM LONG_MAX #endif /* Some pre-ANSI implementations (e.g. SunOS 4) need stderr defined if assertion checking is enabled. */ #include <stdio.h> -#if STDC_HEADERS -# include <stdlib.h> -#endif - -#if HAVE_STRING_H -# include <string.h> -#else -# include <strings.h> -# ifndef strchr -# define strchr index -# endif -#endif - #include <assert.h> #include <ctype.h> - #include <errno.h> -#ifndef errno -extern int errno; -#endif - -#if HAVE_LIMITS_H -# include <limits.h> -#endif - -#ifndef CHAR_BIT -# define CHAR_BIT 8 -#endif +#include <limits.h> +#include <stdlib.h> +#include <string.h> /* The extra casts work around common compiler bugs. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) -/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. - It is necessary at least when t == time_t. */ #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ - ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) -#define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t)) + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ + : (t) 0)) +#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) + +#ifndef STRTOL_T_MINIMUM +# define STRTOL_T_MINIMUM TYPE_MINIMUM (__strtol_t) +# define STRTOL_T_MAXIMUM TYPE_MAXIMUM (__strtol_t) +#endif #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) # define IN_CTYPE_DOMAIN(c) 1 @@ -78,36 +64,38 @@ extern int errno; #include "xstrtol.h" -#ifndef strtol -long int strtol (); +#if !HAVE_DECL_STRTOIMAX && !defined strtoimax +intmax_t strtoimax (); #endif -#ifndef strtoul -unsigned long int strtoul (); -#endif - -#ifndef strtoumax +#if !HAVE_DECL_STRTOUMAX && !defined strtoumax uintmax_t strtoumax (); #endif -static int +static strtol_error bkm_scale (__strtol_t *x, int scale_factor) { - __strtol_t product = *x * scale_factor; - if (*x != product / scale_factor) - return 1; - *x = product; - return 0; + if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor) + { + *x = STRTOL_T_MINIMUM; + return LONGINT_OVERFLOW; + } + if (STRTOL_T_MAXIMUM / scale_factor < *x) + { + *x = STRTOL_T_MAXIMUM; + return LONGINT_OVERFLOW; + } + *x *= scale_factor; + return LONGINT_OK; } -static int +static strtol_error bkm_scale_by_power (__strtol_t *x, int base, int power) { + strtol_error err = LONGINT_OK; while (power--) - if (bkm_scale (x, base)) - return 1; - - return 0; + err |= bkm_scale (x, base); + return err; } /* FIXME: comment. */ @@ -119,6 +107,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, char *t_ptr; char **p; __strtol_t tmp; + strtol_error err = LONGINT_OK; assert (0 <= strtol_base && strtol_base <= 36); @@ -127,18 +116,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base, if (! TYPE_SIGNED (__strtol_t)) { const char *q = s; - while (ISSPACE ((unsigned char) *q)) - ++q; - if (*q == '-') + unsigned char ch = *q; + while (ISSPACE (ch)) + ch = *++q; + if (ch == '-') return LONGINT_INVALID; } errno = 0; tmp = __strtol (s, p, strtol_base); - if (errno != 0) - return LONGINT_OVERFLOW; + if (*p == s) - return LONGINT_INVALID; + { + /* If there is no number but there is a valid suffix, assume the + number is 1. The string is invalid otherwise. */ + if (valid_suffixes && **p && strchr (valid_suffixes, **p)) + tmp = 1; + else + return LONGINT_INVALID; + } + else if (errno != 0) + { + if (errno != ERANGE) + return LONGINT_INVALID; + err = LONGINT_OVERFLOW; + } /* Let valid_suffixes == NULL mean `allow any suffix'. */ /* FIXME: update all callers except the ones that allow suffixes @@ -146,34 +148,39 @@ __xstrtol (const char *s, char **ptr, int strtol_base, if (!valid_suffixes) { *val = tmp; - return LONGINT_OK; + return err; } if (**p != '\0') { int base = 1024; int suffixes = 1; - int overflow; + strtol_error overflow; if (!strchr (valid_suffixes, **p)) { *val = tmp; - return LONGINT_INVALID_SUFFIX_CHAR; + return err | LONGINT_INVALID_SUFFIX_CHAR; } if (strchr (valid_suffixes, '0')) { /* The ``valid suffix'' '0' is a special flag meaning that an optional second suffix is allowed, which can change - the base, e.g. "100MD" for 100 megabytes decimal. */ + the base. A suffix "B" (e.g. "100MB") stands for a power + of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for + a power of 1024. If no suffix (e.g. "100M"), assume + power-of-1024. */ switch (p[0][1]) { - case 'B': - suffixes++; + case 'i': + if (p[0][2] == 'B') + suffixes += 2; break; - case 'D': + case 'B': + case 'D': /* 'D' is obsolescent */ base = 1000; suffixes++; break; @@ -194,28 +201,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base, overflow = 0; break; - case 'E': /* Exa */ + case 'E': /* exa or exbi */ overflow = bkm_scale_by_power (&tmp, base, 6); break; - case 'G': /* Giga */ + case 'G': /* giga or gibi */ + case 'g': /* 'g' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 3); break; case 'k': /* kilo */ + case 'K': /* kibi */ overflow = bkm_scale_by_power (&tmp, base, 1); break; - case 'M': /* Mega */ - case 'm': /* 'm' is undocumented; for backward compatibility only */ + case 'M': /* mega or mebi */ + case 'm': /* 'm' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 2); break; - case 'P': /* Peta */ + case 'P': /* peta or pebi */ overflow = bkm_scale_by_power (&tmp, base, 5); break; - case 'T': /* Tera */ + case 'T': /* tera or tebi */ + case 't': /* 't' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 4); break; @@ -223,28 +233,27 @@ __xstrtol (const char *s, char **ptr, int strtol_base, overflow = bkm_scale (&tmp, 2); break; - case 'Y': /* Yotta */ + case 'Y': /* yotta or 2**80 */ overflow = bkm_scale_by_power (&tmp, base, 8); break; - case 'Z': /* Zetta */ + case 'Z': /* zetta or 2**70 */ overflow = bkm_scale_by_power (&tmp, base, 7); break; default: *val = tmp; - return LONGINT_INVALID_SUFFIX_CHAR; - break; + return err | LONGINT_INVALID_SUFFIX_CHAR; } - if (overflow) - return LONGINT_OVERFLOW; - - (*p) += suffixes; + err |= overflow; + *p += suffixes; + if (**p) + err |= LONGINT_INVALID_SUFFIX_CHAR; } *val = tmp; - return LONGINT_OK; + return err; } #ifdef TESTING_XSTRTO @@ -255,7 +264,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, char *program_name; int -main (int argc, char** argv) +main (int argc, char **argv) { strtol_error s_err; int i; diff --git a/lib/xstrtol.h b/lib/xstrtol.h index 7a9a024..0d6b984 100644 --- a/lib/xstrtol.h +++ b/lib/xstrtol.h @@ -1,32 +1,56 @@ +/* A more useful interface to strtol. + + Copyright (C) 1995, 1996, 1998, 1999, 2001, 2002, 2003, 2004 Free + Software Foundation, Inc. + + 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, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #ifndef XSTRTOL_H_ # define XSTRTOL_H_ 1 +# include "exitfail.h" + # if HAVE_INTTYPES_H -# include <inttypes.h> /* for uintmax_t */ +# include <inttypes.h> # endif - -# ifndef PARAMS -# if defined PROTOTYPES || (defined __STDC__ && __STDC__) -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif +# if HAVE_STDINT_H +# include <stdint.h> # endif # ifndef _STRTOL_ERROR enum strtol_error { - LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW + LONGINT_OK = 0, + + /* These two values can be ORed together, to indicate that both + errors occurred. */ + LONGINT_OVERFLOW = 1, + LONGINT_INVALID_SUFFIX_CHAR = 2, + + LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR + | LONGINT_OVERFLOW), + LONGINT_INVALID = 4 }; typedef enum strtol_error strtol_error; # endif # define _DECLARE_XSTRTOL(name, type) \ - strtol_error \ - name PARAMS ((const char *s, char **ptr, int base, \ - type *val, const char *valid_suffixes)); + strtol_error name (const char *, char **, int, type *, const char *); _DECLARE_XSTRTOL (xstrtol, long int) _DECLARE_XSTRTOL (xstrtoul, unsigned long int) +_DECLARE_XSTRTOL (xstrtoimax, intmax_t) _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) # define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \ @@ -34,7 +58,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) { \ switch ((Err)) \ { \ - case LONGINT_OK: \ + default: \ abort (); \ \ case LONGINT_INVALID: \ @@ -43,7 +67,8 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) break; \ \ case LONGINT_INVALID_SUFFIX_CHAR: \ - error ((Exit_code), 0, "invalid character following %s `%s'", \ + case LONGINT_INVALID_SUFFIX_CHAR | LONGINT_OVERFLOW: \ + error ((Exit_code), 0, "invalid character following %s in `%s'", \ (Argument_type_string), (Str)); \ break; \ \ @@ -56,7 +81,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) while (0) # define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \ - _STRTOL_ERROR (2, Str, Argument_type_string, Err) + _STRTOL_ERROR (exit_failure, Str, Argument_type_string, Err) # define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \ _STRTOL_ERROR (0, Str, Argument_type_string, Err) diff --git a/m4/getopt.m4 b/m4/getopt.m4 index 4d58699..85df7a7 100644 --- a/m4/getopt.m4 +++ b/m4/getopt.m4 @@ -1,53 +1,42 @@ -## $Id$ +# getopt.m4 serial 7 +dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. -## Check for getopt_long. This can't be done in AC_CHECK_FUNCS since -## the function can be present in different libraries (namely, libmysqlclient) -## but the necessary header files may be absent, thus AC_CHECK_FUNCS will -## mark function as existent, whereas the compilation will bail out. +# The getopt module assume you want GNU getopt, with getopt_long etc, +# rather than vanilla POSIX getopt. This means your your code should +# always include <getopt.h> for the getopt prototypes. -AH_TEMPLATE(HAVE_GNU_GETOPT, [Define if your system has GNU getopt functions]) +AC_DEFUN([gl_GETOPT_SUBSTITUTE], +[ + GETOPT_H=getopt.h + MU_LIBOBJ([getopt]) + MU_LIBOBJ([getopt1]) + AC_DEFINE([__GETOPT_PREFIX], [[rpl_]], + [Define to rpl_ if the getopt replacement functions and variables + should be used.]) + AC_SUBST([GETOPT_H]) +]) -AC_DEFUN([MU_REPLACE_GNU_GETOPT], +AC_DEFUN([gl_GETOPT], [ - AC_CHECK_HEADER([getopt.h], - mu_cv_have_getopt_h=yes - AC_DEFINE(HAVE_GETOPT_H,1,[Define if the system has getopt.h]), - mu_cv_have_getopt_h=no) - AC_CACHE_CHECK([for GNU getopt], mu_cv_have_gnu_getopt, - [ -AC_TRY_RUN([ -#include <unistd.h> -#ifdef HAVE_GETOPT_H -# include <getopt.h> -#endif + gl_PREREQ_GETOPT -struct option longopt[] = { - "help", no_argument, 0, 'h', - (char*)0 -}; + if test -z "$GETOPT_H"; then + GETOPT_H= + AC_CHECK_HEADERS([getopt.h], [], [GETOPT_H=getopt.h]) + AC_CHECK_FUNCS([getopt_long_only], [], [GETOPT_H=getopt.h]) -main(argc, argv) -int argc; char **argv; -{ - getopt_long_only(argc, argv, "h", longopt, (int*)0); - return 0; -} ], - mu_cv_have_gnu_getopt=yes, - mu_cv_have_gnu_getopt=no, - mu_cv_have_gnu_getopt=no)]) + dnl BSD getopt_long uses an incompatible method to reset option processing, + dnl and (as of 2004-10-15) mishandles optional option-arguments. + AC_CHECK_DECL([optreset], [GETOPT_H=getopt.h], [], [#include <getopt.h>]) - if test x"$mu_cv_have_gnu_getopt" != xyes ; then - mu_cv_have_getopt_h=no - MU_LIBOBJ(getopt) - MU_LIBOBJ(getopt1) - else - AC_DEFINE(HAVE_GNU_GETOPT) - fi - if test "$mu_cv_have_getopt_h" = no; then - MU_HEADER(getopt.h) - fi + if test -n "$GETOPT_H"; then + gl_GETOPT_SUBSTITUTE + fi + fi ]) - - - +# Prerequisites of lib/getopt*. +AC_DEFUN([gl_PREREQ_GETOPT], [:]) diff --git a/m4/regex.m4 b/m4/regex.m4 index 4f3f3cf..2d11f2a 100644 --- a/m4/regex.m4 +++ b/m4/regex.m4 @@ -1,11 +1,23 @@ -#serial 12 +#serial 22 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free +# Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. dnl Initially derived from code in GNU grep. dnl Mostly written by Jim Meyering. -dnl Usage: jm_INCLUDED_REGEX([lib/regex.c]) +AC_DEFUN([gl_REGEX], +[ + gl_INCLUDED_REGEX([lib/regex.c]) +]) + +dnl Usage: gl_INCLUDED_REGEX([lib/regex.c]) dnl -AC_DEFUN([jm_INCLUDED_REGEX], +AC_DEFUN([gl_INCLUDED_REGEX], [ dnl Even packages that don't use regex.c can use this macro. dnl Of course, for them it doesn't do anything. @@ -22,6 +34,7 @@ AC_DEFUN([jm_INCLUDED_REGEX], jm_cv_func_working_re_compile_pattern, AC_TRY_RUN( [#include <stdio.h> +#include <string.h> #include <regex.h> int main () @@ -30,12 +43,14 @@ AC_DEFUN([jm_INCLUDED_REGEX], const char *s; struct re_registers regs; re_set_syntax (RE_SYNTAX_POSIX_EGREP); + memset (®ex, 0, sizeof (regex)); [s = re_compile_pattern ("a[[:@:>@:]]b\n", 9, ®ex);] /* This should fail with _Invalid character class name_ error. */ if (!s) exit (1); /* This should succeed, but doesn't for e.g. glibc-2.1.3. */ + memset (®ex, 0, sizeof (regex)); s = re_compile_pattern ("{1", 2, ®ex); if (s) @@ -43,7 +58,8 @@ AC_DEFUN([jm_INCLUDED_REGEX], /* The following example is derived from a problem report against gawk from Jorge Stolfi <stolfi@ic.unicamp.br>. */ - s = re_compile_pattern ("[[an�]]*n", 7, ®ex); + memset (®ex, 0, sizeof (regex)); + s = re_compile_pattern ("[[an\371]]*n", 7, ®ex); if (s) exit (1); @@ -51,6 +67,16 @@ AC_DEFUN([jm_INCLUDED_REGEX], if (re_match (®ex, "an", 2, 0, ®s) != 2) exit (1); + memset (®ex, 0, sizeof (regex)); + s = re_compile_pattern ("x", 1, ®ex); + if (s) + exit (1); + + /* The version of regex.c in e.g. GNU libc-2.2.93 didn't + work with a negative RANGE argument. */ + if (re_search (®ex, "wxy", 3, 2, -2, ®s) != 1) + exit (1); + exit (0); } ], @@ -67,16 +93,34 @@ AC_DEFUN([jm_INCLUDED_REGEX], ifelse(m4_sysval, 0, [ AC_ARG_WITH(included-regex, - AC_HELP_STRING([--without-included-regex], - [don't compile regex; this is the default on systems with version 2 of the GNU C library (use with caution on other system)]), + [ --without-included-regex don't compile regex; this is the default on + systems with version 2 of the GNU C library + (use with caution on other system)], jm_with_regex=$withval, jm_with_regex=$ac_use_included_regex) if test "$jm_with_regex" = yes; then MU_LIBOBJ(regex) - MU_HEADER(regex.h) - MU_HEADER(posix/regex.h) + gl_PREREQ_REGEX fi ], ) ] ) + +# Prerequisites of lib/regex.c. +AC_DEFUN([gl_PREREQ_REGEX], +[ + dnl FIXME: Maybe provide a btowc replacement someday: Solaris 2.5.1 lacks it. + dnl FIXME: Check for wctype and iswctype, and and add -lw if necessary + dnl to get them. + + dnl Persuade glibc <string.h> to declare mempcpy(). + AC_REQUIRE([AC_GNU_SOURCE]) + + AC_REQUIRE([gl_C_RESTRICT]) + AC_REQUIRE([AC_FUNC_ALLOCA]) + AC_REQUIRE([AC_HEADER_STDC]) + AC_CHECK_HEADERS_ONCE(wchar.h wctype.h) + AC_CHECK_FUNCS_ONCE(isascii mempcpy) + AC_CHECK_FUNCS(btowc) +]) diff --git a/mailbox/argp-ba.c b/mailbox/argp-ba.c index 5657c27..c471228 100644 --- a/mailbox/argp-ba.c +++ b/mailbox/argp-ba.c @@ -3,20 +3,19 @@ This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* If set by the user program, it should point to string that is the bug-reporting address for the program. It will be printed by argp_help if diff --git a/mailbox/argp-eexst.c b/mailbox/argp-eexst.c index 6df99e9..d5cd28c 100644 --- a/mailbox/argp-eexst.c +++ b/mailbox/argp-eexst.c @@ -1,34 +1,27 @@ /* Default definition for ARGP_ERR_EXIT_STATUS - Copyright (C) 1997, 2001 Free Software Foundation, Inc. + Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#ifdef HAVE_SYSEXITS_H #include <sysexits.h> -#endif - -#ifndef EX_USAGE -#define EX_USAGE 64 -#endif #include "argp.h" diff --git a/mailbox/argp-fmtstream.c b/mailbox/argp-fmtstream.c index ee7899b..c88c3db 100644 --- a/mailbox/argp-fmtstream.c +++ b/mailbox/argp-fmtstream.c @@ -1,22 +1,21 @@ /* Word-wrapping and line-truncating streams - Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This package emulates glibc `line_wrap_stream' semantics for systems that don't have that. */ @@ -40,6 +39,12 @@ #define isblank(ch) ((ch)==' ' || (ch)=='\t') #endif +#if defined _LIBC && defined USE_IN_LIBIO +# include <wchar.h> +# include <libio/libioP.h> +# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) +#endif + #define INIT_BUF_SIZE 200 #define PRINTF_SIZE_GUESS 150 @@ -53,8 +58,10 @@ argp_fmtstream_t __argp_make_fmtstream (FILE *stream, size_t lmargin, size_t rmargin, ssize_t wmargin) { - argp_fmtstream_t fs = malloc (sizeof (struct argp_fmtstream)); - if (fs) + argp_fmtstream_t fs; + + fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); + if (fs != NULL) { fs->stream = stream; @@ -64,7 +71,7 @@ __argp_make_fmtstream (FILE *stream, fs->point_col = 0; fs->point_offs = 0; - fs->buf = malloc (INIT_BUF_SIZE); + fs->buf = (char *) malloc (INIT_BUF_SIZE); if (! fs->buf) { free (fs); @@ -79,9 +86,12 @@ __argp_make_fmtstream (FILE *stream, return fs; } +#if 0 +/* Not exported. */ #ifdef weak_alias weak_alias (__argp_make_fmtstream, argp_make_fmtstream) #endif +#endif /* Flush FS to its stream, and free it (but don't close the stream). */ void @@ -89,13 +99,23 @@ __argp_fmtstream_free (argp_fmtstream_t fs) { __argp_fmtstream_update (fs); if (fs->p > fs->buf) - fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); + else +#endif + fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); + } free (fs->buf); free (fs); } +#if 0 +/* Not exported. */ #ifdef weak_alias weak_alias (__argp_fmtstream_free, argp_fmtstream_free) #endif +#endif /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ @@ -129,7 +149,14 @@ __argp_fmtstream_update (argp_fmtstream_t fs) /* No buffer space for spaces. Must flush. */ size_t i; for (i = 0; i < pad; i++) - putc (' ', fs->stream); + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else +#endif + putc_unlocked (' ', fs->stream); + } } fs->point_col = pad; } @@ -245,9 +272,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs) at the end of the buffer, and NEXTLINE is in fact empty (and so we need not be careful to maintain its contents). */ - if (nextline == buf + len + 1 - ? fs->end - nl < fs->wmargin + 1 - : nextline - (nl + 1) < fs->wmargin) + if ((nextline == buf + len + 1 + ? fs->end - nl < fs->wmargin + 1 + : nextline - (nl + 1) < fs->wmargin) + && fs->p > nextline) { /* The margin needs more blanks than we removed. */ if (fs->end - fs->p > fs->wmargin + 1) @@ -262,9 +290,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) else /* Output the first line so we can use the space. */ { - if (nl > fs->buf) - fwrite (fs->buf, 1, nl - fs->buf, fs->stream); - putc ('\n', fs->stream); +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + __fwprintf (fs->stream, L"%.*s\n", + (int) (nl - fs->buf), fs->buf); + else +#endif + { + if (nl > fs->buf) + fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream); + putc_unlocked ('\n', fs->stream); + } len += buf - fs->buf; nl = buf = fs->buf; } @@ -281,7 +317,12 @@ __argp_fmtstream_update (argp_fmtstream_t fs) *nl++ = ' '; else for (i = 0; i < fs->wmargin; ++i) - putc (' ', fs->stream); +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else +#endif + putc_unlocked (' ', fs->stream); /* Copy the tail of the original buffer into the current buffer position. */ @@ -318,7 +359,15 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) /* Flush FS's buffer. */ __argp_fmtstream_update (fs); - wrote = fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + { + __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); + wrote = fs->p - fs->buf; + } + else +#endif + wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); if (wrote == fs->p - fs->buf) { fs->p = fs->buf; @@ -335,12 +384,13 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) if ((size_t) (fs->end - fs->buf) < amount) /* Gotta grow the buffer. */ { - size_t new_size = fs->end - fs->buf + amount; - char *new_buf = realloc (fs->buf, new_size); + size_t old_size = fs->end - fs->buf; + size_t new_size = old_size + amount; + char *new_buf; - if (! new_buf) + if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size))) { - errno = ENOMEM; + __set_errno (ENOMEM); return 0; } @@ -369,19 +419,22 @@ __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) va_start (args, fmt); avail = fs->end - fs->p; - out = vsnprintf (fs->p, avail, fmt, args); + out = __vsnprintf (fs->p, avail, fmt, args); va_end (args); - if (out >= avail) + if ((size_t) out >= avail) size_guess = out + 1; } - while (out >= avail); + while ((size_t) out >= avail); fs->p += out; return out; } +#if 0 +/* Not exported. */ #ifdef weak_alias weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) #endif +#endif #endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ diff --git a/mailbox/argp-fmtstream.h b/mailbox/argp-fmtstream.h index 914d837..e71df10 100644 --- a/mailbox/argp-fmtstream.h +++ b/mailbox/argp-fmtstream.h @@ -1,22 +1,21 @@ /* Word-wrapping and line-truncating streams. - Copyright (C) 1997, 2001 Free Software Foundation, Inc. + Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This package emulates glibc `line_wrap_stream' semantics for systems that don't have that. If the system does have it, it is just a wrapper for @@ -34,6 +33,19 @@ #include <string.h> #include <unistd.h> +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__ +# define __format__ format +# define __printf__ printf +# endif +#endif + #if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) /* line_wrap_stream is available, so use that. */ @@ -82,6 +94,9 @@ typedef FILE *argp_fmtstream_t; #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ /* Guess we have to define our own version. */ +#ifndef __const +#define __const const +#endif struct argp_fmtstream { @@ -122,20 +137,22 @@ extern void __argp_fmtstream_free (argp_fmtstream_t __fs); extern void argp_fmtstream_free (argp_fmtstream_t __fs); extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, - const char *__fmt, ...); + __const char *__fmt, ...) + __attribute__ ((__format__ (printf, 2, 3))); extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, - const char *__fmt, ...); + __const char *__fmt, ...) + __attribute__ ((__format__ (printf, 2, 3))); extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); -extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); -extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); +extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); +extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, - const char *__str, size_t __len); + __const char *__str, size_t __len); extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, - const char *__str, size_t __len); + __const char *__str, size_t __len); /* Access macros for various bits of state. */ #define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) @@ -194,7 +211,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); ARGP_FS_EI size_t __argp_fmtstream_write (argp_fmtstream_t __fs, - const char *__str, size_t __len) + __const char *__str, size_t __len) { if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) { @@ -207,7 +224,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs, } ARGP_FS_EI int -__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str) +__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) { size_t __len = strlen (__str); if (__len) diff --git a/mailbox/argp-fs-xinl.c b/mailbox/argp-fs-xinl.c index 94d5f58..a4d14a2 100644 --- a/mailbox/argp-fs-xinl.c +++ b/mailbox/argp-fs-xinl.c @@ -1,22 +1,21 @@ /* Real definitions for extern inline functions in argp-fmtstream.h - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -24,9 +23,11 @@ #define ARGP_FS_EI #undef __OPTIMIZE__ -#define __OPTIMIZE__ +#define __OPTIMIZE__ 1 #include "argp-fmtstream.h" +#if 0 +/* Not exported. */ /* Add weak aliases. */ #if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) @@ -39,3 +40,4 @@ weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) weak_alias (__argp_fmtstream_point, argp_fmtstream_point) #endif +#endif diff --git a/mailbox/argp-help.c b/mailbox/argp-help.c index 932fe83..4f1fc0e 100644 --- a/mailbox/argp-help.c +++ b/mailbox/argp-help.c @@ -1,22 +1,21 @@ /* Hierarchial argument parsing help output - Copyright (C) 1995,1996,1997,1998,1999,2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 @@ -26,73 +25,35 @@ #include <config.h> #endif -#include <mailutils/nls.h> - -#ifndef alloca -# ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -# else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include <alloca.h> -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -# endif -#endif - +#include <alloca.h> +#include <errno.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stdarg.h> -#ifdef HAVE_MALLOC_H -# include <malloc.h> -#endif #include <ctype.h> - -#ifdef HAVE_STRINGS_H -# include <strings.h> +#include <limits.h> +#ifdef USE_IN_LIBIO +# include <wchar.h> #endif -#ifndef _ -/* This is for other GNU distributions with internationalized messages. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> -# ifdef _LIBC -# undef dgettext -# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) -# endif -# else -# define dgettext(domain, msgid) (msgid) -# endif +#ifdef _LIBC +# include <libintl.h> +# undef dgettext +# define dgettext(domain, msgid) \ + INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) +#else +# include "gettext.h" #endif #include "argp.h" #include "argp-fmtstream.h" #include "argp-namefrob.h" -#ifndef __P -# if defined PROTOTYPES || (defined __STDC__ && __STDC__) -# define __P(Args) Args -# else -# define __P(Args) () -# endif -#endif - -#if !HAVE_DECL_STRCHRNUL -extern char *strchrnul __P((const char *s, int c_in)); -#endif -#if !HAVE_DECL_STRNDUP -extern char *strndup __P((const char *s, size_t n)); +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) #endif - /* User-selectable (using an environment variable) formatting parameters. @@ -267,6 +228,9 @@ fill_in_uparams (const struct argp_state *state) /* Returns true if OPT is an documentation-only entry. */ #define odoc(opt) ((opt)->flags & OPTION_DOC) +/* Returns true if OPT should not be translated */ +#define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS) + /* Returns true if OPT is the end-of-list marker for a list of options. */ #define oend(opt) __option_is_end (opt) @@ -462,6 +426,8 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster) hol->short_options = malloc (num_short_options + 1); assert (hol->entries && hol->short_options); + if (SIZE_MAX <= UINT_MAX) + assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry)); /* Fill in the entries. */ so = hol->short_options; @@ -566,7 +532,8 @@ hol_entry_short_iterate (const struct hol_entry *entry, return val; } -static int +static inline int +__attribute__ ((always_inline)) hol_entry_long_iterate (const struct hol_entry *entry, int (*func)(const struct argp_option *opt, const struct argp_option *real, @@ -590,7 +557,7 @@ hol_entry_long_iterate (const struct hol_entry *entry, } /* Iterator that returns true for the first short option. */ -static int +static inline int until_short (const struct argp_option *opt, const struct argp_option *real, const char *domain, void *cookie) { @@ -712,14 +679,20 @@ static int canon_doc_option (const char **name) { int non_opt; - /* Skip initial whitespace. */ - while (isspace (**name)) - (*name)++; - /* Decide whether this looks like an option (leading `-') or not. */ - non_opt = (**name != '-'); - /* Skip until part of name used for sorting. */ - while (**name && !isalnum (**name)) - (*name)++; + + if (!*name) + non_opt = 1; + else + { + /* Skip initial whitespace. */ + while (isspace (**name)) + (*name)++; + /* Decide whether this looks like an option (leading `-') or not. */ + non_opt = (**name != '-'); + /* Skip until part of name used for sorting. */ + while (**name && !isalnum (**name)) + (*name)++; + } return non_opt; } @@ -772,7 +745,7 @@ hol_entry_cmp (const struct hol_entry *entry1, return doc1 - doc2; else if (!short1 && !short2 && long1 && long2) /* Only long options. */ - return strcasecmp (long1, long2); + return __strcasecmp (long1, long2); else /* Compare short/short, long/short, short/long, using the first character of long options. Entries without *any* valid @@ -853,12 +826,16 @@ hol_append (struct hol *hol, struct hol *more) char *short_options = malloc (hol_so_len + strlen (more->short_options) + 1); - memcpy (entries, hol->entries, - hol->num_entries * sizeof (struct hol_entry)); - memcpy (entries + hol->num_entries, more->entries, - more->num_entries * sizeof (struct hol_entry)); + assert (entries && short_options); + if (SIZE_MAX <= UINT_MAX) + assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry)); - memcpy (short_options, hol->short_options, hol_so_len); + __mempcpy (__mempcpy (entries, hol->entries, + hol->num_entries * sizeof (struct hol_entry)), + more->entries, + more->num_entries * sizeof (struct hol_entry)); + + __mempcpy (short_options, hol->short_options, hol_so_len); /* Fix up the short options pointers from HOL. */ for (e = entries, left = hol->num_entries; left > 0; e++, left--) @@ -1078,9 +1055,8 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, int old_wm = __argp_fmtstream_wmargin (stream); /* PEST is a state block holding some of our variables that we'd like to share with helper functions. */ - /* Some loosing compiler can not handle this ... lets play nice. */ - /* struct pentry_state pest = { entry, stream, hhstate, 1, state }; */ struct pentry_state pest; + pest.entry = entry; pest.stream = stream; pest.hhstate = hhstate; @@ -1120,13 +1096,15 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, { __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) + if (opt->name && *opt->name && ovisible (opt)) { comma (uparams.doc_opt_col, &pest); - /* Calling gettext here isn't quite right, since sorting will + /* Calling dgettext here isn't quite right, since sorting will have been done on the original; but documentation options should be pretty rare anyway... */ __argp_fmtstream_puts (stream, + onotrans (opt) ? + opt->name : dgettext (state->root_argp->argp_domain, opt->name)); } @@ -1406,7 +1384,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, if (fdoc) { const char *cp = fdoc; - nl = strchrnul (cp, '\n'); + nl = __strchrnul (cp, '\n'); if (*nl != '\0') /* This is a `multi-level' args doc; advance to the correct position as determined by our state in LEVELS, and update LEVELS. */ @@ -1414,7 +1392,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, int i; multiple = 1; for (i = 0; i < *our_level; i++) - cp = nl + 1, nl = strchrnul (cp, '\n'); + cp = nl + 1, nl = __strchrnul (cp, '\n'); (*levels)++; } @@ -1482,7 +1460,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state, { if (inp_text_limit) /* Copy INP_TEXT so that it's nul-terminated. */ - inp_text = strndup (inp_text, inp_text_limit); + inp_text = __strndup (inp_text, inp_text_limit); input = __argp_input (argp, state); text = (*argp->help_filter) (post @@ -1556,12 +1534,19 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, if (! stream) return; +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __flockfile (stream); +#endif + if (! uparams.valid) fill_in_uparams (state); fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); if (! fs) { +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif return; } @@ -1669,6 +1654,10 @@ Try `%s --help' or `%s --usage' for more information.\n"), anything = 1; } +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif + if (hol) hol_free (hol); @@ -1680,12 +1669,34 @@ Try `%s --help' or `%s --usage' for more information.\n"), void __argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name) { - _help (argp, 0, stream, flags, name); + struct argp_state state; + memset (&state, 0, sizeof state); + state.root_argp = argp; + _help (argp, &state, stream, flags, name); } #ifdef weak_alias weak_alias (__argp_help, argp_help) #endif +#if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) +char * +__argp_short_program_name (void) +{ +# if HAVE_DECL_PROGRAM_INVOCATION_NAME + char *name = strrchr (program_invocation_name, '/'); + return name ? name + 1 : program_invocation_name; +# else + /* FIXME: What now? Miles suggests that it is better to use NULL, + but currently the value is passed on directly to fputs_unlocked, + so that requires more changes. */ +# if __GNUC__ +# warning No reasonable value to return +# endif /* __GNUC__ */ + return ""; +# endif +} +#endif + /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are from the set ARGP_HELP_*. */ void @@ -1697,7 +1708,7 @@ __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) flags |= ARGP_HELP_LONG_ONLY; _help (state ? state->root_argp : 0, state, stream, flags, - state ? state->name : program_invocation_short_name); + state ? state->name : __argp_short_program_name ()); if (!state || ! (state->flags & ARGP_NO_EXIT)) { @@ -1726,19 +1737,47 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) { va_list ap; - fputs (state ? state->name : program_invocation_short_name, - stream); - putc (':', stream); - putc (' ', stream); +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __flockfile (stream); +#endif va_start (ap, fmt); - vfprintf (stream, fmt, ap); - va_end (ap); - putc ('\n', stream); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + { + char *buf; + + if (__asprintf (&buf, fmt, ap) < 0) + buf = NULL; + + __fwprintf (stream, L"%s: %s\n", + state ? state->name : __argp_short_program_name (), + buf); + + free (buf); + } + else +#endif + { + fputs_unlocked (state + ? state->name : __argp_short_program_name (), + stream); + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + + vfprintf (stream, fmt, ap); + + putc_unlocked ('\n', stream); + } __argp_state_help (state, stream, ARGP_HELP_STD_ERR); + va_end (ap); + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif } } } @@ -1764,29 +1803,88 @@ __argp_failure (const struct argp_state *state, int status, int errnum, if (stream) { - fputs (state ? state->name : program_invocation_short_name, - stream); +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __flockfile (stream); +#endif + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + __fwprintf (stream, L"%s", + state ? state->name : __argp_short_program_name ()); + else +#endif + fputs_unlocked (state + ? state->name : __argp_short_program_name (), + stream); if (fmt) { va_list ap; - putc (':', stream); - putc (' ', stream); - va_start (ap, fmt); - vfprintf (stream, fmt, ap); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + { + char *buf; + + if (__asprintf (&buf, fmt, ap) < 0) + buf = NULL; + + __fwprintf (stream, L": %s", buf); + + free (buf); + } + else +#endif + { + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + + vfprintf (stream, fmt, ap); + } + va_end (ap); } if (errnum) { - putc (':', stream); - putc (' ', stream); - fputs (strerror (errnum), stream); + char buf[200]; + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + __fwprintf (stream, L": %s", + __strerror_r (errnum, buf, sizeof (buf))); + else +#endif + { + char const *s = NULL; + putc_unlocked (':', stream); + putc_unlocked (' ', stream); +#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P) + s = __strerror_r (errnum, buf, sizeof buf); +#elif HAVE_DECL_STRERROR_R + if (__strerror_r (errnum, buf, sizeof buf) == 0) + s = buf; +#endif +#if !_LIBC + if (! s && ! (s = strerror (errnum))) + s = dgettext (state->root_argp->argp_domain, + "Unknown system error"); +#endif + fputs (s, stream); + } } - putc ('\n', stream); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + putwc_unlocked (L'\n', stream); + else +#endif + putc_unlocked ('\n', stream); + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif if (status && (!state || !(state->flags & ARGP_NO_EXIT))) exit (status); diff --git a/mailbox/argp-namefrob.h b/mailbox/argp-namefrob.h index 4ef3714..09cafd0 100644 --- a/mailbox/argp-namefrob.h +++ b/mailbox/argp-namefrob.h @@ -1,22 +1,21 @@ /* Name frobnication for compiling argp outside of glibc - Copyright (C) 1997, 2001 Free Software Foundation, Inc. + Copyright (C) 1997, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !_LIBC /* This code is written for inclusion in gnu-libc, and uses names in the @@ -77,12 +76,81 @@ #undef __argp_fmtstream_wmargin #define __argp_fmtstream_wmargin argp_fmtstream_wmargin +#include "mempcpy.h" +#include "strcase.h" +#include "strchrnul.h" +#include "strndup.h" + /* normal libc functions we call */ +#undef __flockfile +#define __flockfile flockfile +#undef __funlockfile +#define __funlockfile funlockfile +#undef __mempcpy +#define __mempcpy mempcpy #undef __sleep #define __sleep sleep #undef __strcasecmp #define __strcasecmp strcasecmp +#undef __strchrnul +#define __strchrnul strchrnul +#undef __strerror_r +#define __strerror_r strerror_r +#undef __strndup +#define __strndup strndup #undef __vsnprintf #define __vsnprintf vsnprintf +#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED +# define clearerr_unlocked(x) clearerr (x) +#endif +#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED +# define feof_unlocked(x) feof (x) +# endif +#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED +# define ferror_unlocked(x) ferror (x) +# endif +#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED +# define fflush_unlocked(x) fflush (x) +# endif +#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED +# define fgets_unlocked(x,y,z) fgets (x,y,z) +# endif +#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED +# define fputc_unlocked(x,y) fputc (x,y) +# endif +#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED +# define fputs_unlocked(x,y) fputs (x,y) +# endif +#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +# endif +#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +# endif +#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED +# define getc_unlocked(x) getc (x) +# endif +#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED +# define getchar_unlocked() getchar () +# endif +#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED +# define putc_unlocked(x,y) putc (x,y) +# endif +#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED +# define putchar_unlocked(x) putchar (x) +# endif + +extern char *__argp_basename (char *name); + #endif /* !_LIBC */ + +#ifndef __set_errno +#define __set_errno(e) (errno = (e)) +#endif + +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME +# define __argp_short_program_name() (program_invocation_short_name) +#else +extern char *__argp_short_program_name (void); +#endif diff --git a/mailbox/argp-parse.c b/mailbox/argp-parse.c index 75de7ba..beb41d9 100644 --- a/mailbox/argp-parse.c +++ b/mailbox/argp-parse.c @@ -1,72 +1,51 @@ /* Hierarchial argument parsing, layered over getopt - Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif +#include <alloca.h> +#include <stddef.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <limits.h> #include <getopt.h> +#include <getopt_int.h> -#ifdef HAVE_STRINGS_H -# include <strings.h> -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#endif - -#include <mailutils/nls.h> - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> -# ifdef _LIBC -# undef dgettext -# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) -# endif -# else -# define dgettext(domain, msgid) (msgid) -# define gettext(msgid) (msgid) -# endif -#endif -#ifndef N_ -# define N_(msgid) msgid -#endif - -#if _LIBC - 0 -#include <bits/libc-lock.h> +#ifdef _LIBC +# include <libintl.h> +# undef dgettext +# define dgettext(domain, msgid) \ + INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) #else -#ifdef HAVE_CTHREADS_H -#include <cthreads.h> +# include "gettext.h" #endif -#endif /* _LIBC */ +#define N_(msgid) msgid #include "argp.h" #include "argp-namefrob.h" +#define alignof(type) offsetof (struct { char c; type x; }, x) +#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) + /* Getopt return values. */ #define KEY_END (-1) /* The end of the options. */ #define KEY_ARG 1 /* A non-option argument. */ @@ -92,7 +71,7 @@ for one second intervals, decrementing _ARGP_HANG until it's zero. Thus you can force the program to continue by attaching a debugger and setting it to 0 yourself. */ -volatile int _argp_hang; +static volatile int _argp_hang; #define OPT_PROGNAME -2 #define OPT_USAGE -3 @@ -101,11 +80,11 @@ volatile int _argp_hang; static const struct argp_option argp_default_options[] = { {"help", '?', 0, 0, N_("Give this help list"), -1}, - {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message")}, - {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")}, + {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0}, + {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name"), 0}, {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, - N_("Hang for SECS seconds (default 3600)")}, - {0, 0} + N_("Hang for SECS seconds (default 3600)"), 0}, + {NULL, 0, 0, 0, NULL, 0} }; static error_t @@ -122,31 +101,35 @@ argp_default_parser (int key, char *arg, struct argp_state *state) break; case OPT_PROGNAME: /* Set the program name. */ +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME program_invocation_name = arg; - +#endif /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined to be that, so we have to be a bit careful here.] */ - arg = strrchr (arg, '/'); - if (arg) - program_invocation_short_name = arg + 1; - else - program_invocation_short_name = program_invocation_name; /* Update what we use for messages. */ - state->name = program_invocation_short_name; + state->name = strrchr (arg, '/'); + if (state->name) + state->name++; + else + state->name = arg; + +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + program_invocation_short_name = state->name; +#endif if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) == ARGP_PARSE_ARGV0) /* Update what getopt uses too. */ - state->argv[0] = program_invocation_name; + state->argv[0] = arg; break; case OPT_HANG: _argp_hang = atoi (arg ? arg : "3600"); while (_argp_hang-- > 0) - sleep (1); + __sleep (1); break; default: @@ -162,7 +145,7 @@ static const struct argp argp_default_argp = static const struct argp_option argp_version_options[] = { {"version", 'V', 0, 0, N_("Print program version"), -1}, - {0, 0} + {NULL, 0, 0, 0, NULL, 0} }; static error_t @@ -207,42 +190,7 @@ find_long_option (struct option *long_options, const char *name) else return -1; } - -/* If we can, we regulate access to getopt, which is non-reentrant, with a - mutex. Since the case we're trying to guard against is two different - threads interfering, and it's possible that someone might want to call - argp_parse recursively (they're careful), we use a recursive lock if - possible. */ - -#if _LIBC - 0 - -__libc_lock_define_initialized_recursive (static, getopt_lock) -#define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock) -#define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock) - -#else /* !_LIBC */ -#if defined(HAVE_CTHREADS_H) - -static struct mutex getopt_lock = MUTEX_INITIALIZER; -#define LOCK_GETOPT mutex_lock (&getopt_lock) -#define UNLOCK_GETOPT mutex_unlock (&getopt_lock) - -#else /* !HAVE_CTHREADS_H */ - -#define LOCK_GETOPT (void)0 -#define UNLOCK_GETOPT (void)0 -#endif /* HAVE_CTHREADS_H */ -#endif /* _LIBC */ - -/* This hack to allow programs that know what's going on to call argp - recursively. If someday argp is changed not to use the non-reentrant - getopt interface, we can get rid of this shit. XXX */ -void -_argp_unlock_xxx (void) -{ - UNLOCK_GETOPT; -} /* The state of a `group' during parsing. Each group corresponds to a particular argp structure from the tree of such descending from the top @@ -304,6 +252,8 @@ struct parser /* LONG_OPTS is the array of getop long option structures for the union of all the groups of options. */ struct option *long_opts; + /* OPT_DATA is the getopt data used for the re-entrant getopt. */ + struct _getopt_data opt_data; /* States of the various parsing groups. */ struct group *groups; @@ -515,6 +465,12 @@ parser_init (struct parser *parser, const struct argp *argp, error_t err = 0; struct group *group; struct parser_sizes szs; + struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; + char *storage; + size_t glen, gsum; + size_t clen, csum; + size_t llen, lsum; + size_t slen, ssum; szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; szs.long_len = 0; @@ -525,26 +481,33 @@ parser_init (struct parser *parser, const struct argp *argp, calc_sizes (argp, &szs); /* Lengths of the various bits of storage used by PARSER. */ -#define GLEN (szs.num_groups + 1) * sizeof (struct group) -#define CLEN (szs.num_child_inputs * sizeof (void *)) -#define LLEN ((szs.long_len + 1) * sizeof (struct option)) -#define SLEN (szs.short_len + 1) - - parser->storage = malloc (GLEN + CLEN + LLEN + SLEN); + glen = (szs.num_groups + 1) * sizeof (struct group); + clen = szs.num_child_inputs * sizeof (void *); + llen = (szs.long_len + 1) * sizeof (struct option); + slen = szs.short_len + 1; + + /* Sums of previous lengths, properly aligned. There's no need to + align gsum, since struct group is aligned at least as strictly as + void * (since it contains a void * member). And there's no need + to align lsum, since struct option is aligned at least as + strictly as char. */ + gsum = glen; + csum = alignto (gsum + clen, alignof (struct option)); + lsum = csum + llen; + ssum = lsum + slen; + + parser->storage = malloc (ssum); if (! parser->storage) return ENOMEM; - parser->groups = (struct group *) parser->storage; - /* To please Watcom CC - parser->child_inputs = parser->storage + GLEN; - parser->long_opts = parser->storage + GLEN + CLEN; - parser->short_opts = parser->storage + GLEN + CLEN + LLEN; - */ - parser->child_inputs = (void **)((char*) parser->storage + GLEN); - parser->long_opts = (struct option *)((char*) parser->storage + GLEN + CLEN); - parser->short_opts = (char*) parser->storage + GLEN + CLEN + LLEN; - - memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); + storage = parser->storage; + parser->groups = parser->storage; + parser->child_inputs = (void **) (storage + gsum); + parser->long_opts = (struct option *) (storage + csum); + parser->short_opts = storage + lsum; + parser->opt_data = opt_data; + + memset (parser->child_inputs, 0, clen); parser_convert (parser, argp, flags); memset (&parser->state, 0, sizeof (struct argp_state)); @@ -586,19 +549,16 @@ parser_init (struct parser *parser, const struct argp *argp, if (err) return err; - /* Getopt is (currently) non-reentrant. */ - LOCK_GETOPT; - if (parser->state.flags & ARGP_NO_ERRS) { - opterr = 0; + parser->opt_data.opterr = 0; if (parser->state.flags & ARGP_PARSE_ARGV0) /* getopt always skips ARGV[0], so we have to fake it out. As long as OPTERR is 0, then it shouldn't actually try to access it. */ parser->state.argv--, parser->state.argc++; } else - opterr = 1; /* Print error messages. */ + parser->opt_data.opterr = 1; /* Print error messages. */ if (parser->state.argv == argv && argv[0]) /* There's an argv[0]; use it for messages. */ @@ -607,7 +567,7 @@ parser_init (struct parser *parser, const struct argp *argp, parser->state.name = short_name ? short_name + 1 : argv[0]; } else - parser->state.name = program_invocation_short_name; + parser->state.name = __argp_short_program_name (); return 0; } @@ -619,8 +579,6 @@ parser_finalize (struct parser *parser, { struct group *group; - UNLOCK_GETOPT; - if (err == EBADKEY && arg_ebadkey) /* Suppress errors generated by unparsed arguments. */ err = 0; @@ -782,7 +740,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val) for (group = parser->groups; group < parser->egroup; group++) if (group->short_end > short_index) { - err = group_parse (group, &parser->state, opt, optarg); + err = group_parse (group, &parser->state, opt, + parser->opt_data.optarg); break; } } @@ -791,7 +750,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val) the user value in order to preserve the sign. */ err = group_parse (&parser->groups[group_key - 1], &parser->state, - (opt << GROUP_BITS) >> GROUP_BITS, optarg); + (opt << GROUP_BITS) >> GROUP_BITS, + parser->opt_data.optarg); if (err == EBADKEY) /* At least currently, an option not recognized is an error in the @@ -837,15 +797,20 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) if (parser->try_getopt && !parser->state.quoted) /* Give getopt a chance to parse this. */ { - optind = parser->state.next; /* Put it back in OPTIND for getopt. */ - optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ + /* Put it back in OPTIND for getopt. */ + parser->opt_data.optind = parser->state.next; + /* Distinguish KEY_ERR from a real option. */ + parser->opt_data.optopt = KEY_END; if (parser->state.flags & ARGP_LONG_ONLY) - opt = getopt_long_only (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); + opt = _getopt_long_only_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); else - opt = getopt_long (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); - parser->state.next = optind; /* And see what getopt did. */ + opt = _getopt_long_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); + /* And see what getopt did. */ + parser->state.next = parser->opt_data.optind; if (opt == KEY_END) /* Getopt says there are no more options, so stop using @@ -861,7 +826,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) here, whatever happens. */ parser->state.quoted = parser->state.next; } - else if (opt == KEY_ERR && optopt != KEY_END) + else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END) /* KEY_ERR can have the same value as a valid user short option, but in the case of a real error, getopt sets OPTOPT to the offending character, which can never be KEY_END. */ @@ -887,15 +852,15 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) /* A non-option arg; simulate what getopt might have done. */ { opt = KEY_ARG; - optarg = parser->state.argv[parser->state.next++]; + parser->opt_data.optarg = parser->state.argv[parser->state.next++]; } } if (opt == KEY_ARG) /* A non-option argument; try each parser in turn. */ - err = parser_parse_arg (parser, optarg); + err = parser_parse_arg (parser, parser->opt_data.optarg); else - err = parser_parse_opt (parser, opt, optarg); + err = parser_parse_opt (parser, opt, parser->opt_data.optarg); if (err == EBADKEY) *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); diff --git a/mailbox/argp-pv.c b/mailbox/argp-pv.c index 5061074..f93a22e 100644 --- a/mailbox/argp-pv.c +++ b/mailbox/argp-pv.c @@ -3,20 +3,19 @@ This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* If set by the user program to a non-zero value, then a default option --version is added (unless the ARGP_NO_HELP flag is used), which will diff --git a/mailbox/argp-pvh.c b/mailbox/argp-pvh.c index 2d0bd39..5474251 100644 --- a/mailbox/argp-pvh.c +++ b/mailbox/argp-pvh.c @@ -1,22 +1,21 @@ /* Default definition for ARGP_PROGRAM_VERSION_HOOK. - Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -29,4 +28,4 @@ this function with a stream to print the version to and a pointer to the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ -void (*argp_program_version_hook) (FILE *stream, struct argp_state *state); +void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL; diff --git a/mailbox/argp-xinl.c b/mailbox/argp-xinl.c index cbd1388..51d3e20 100644 --- a/mailbox/argp-xinl.c +++ b/mailbox/argp-xinl.c @@ -1,33 +1,36 @@ /* Real definitions for extern inline functions in argp.h - Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif +#if defined _LIBC || defined HAVE_FEATURES_H +# include <features.h> +#endif + #ifndef __USE_EXTERN_INLINES # define __USE_EXTERN_INLINES 1 #endif #define ARGP_EI #undef __OPTIMIZE__ -#define __OPTIMIZE__ +#define __OPTIMIZE__ 1 #include "argp.h" /* Add weak aliases. */ diff --git a/mailbox/getline.c b/mailbox/getline.c index 30fc5e0..746d708 100644 --- a/mailbox/getline.c +++ b/mailbox/getline.c @@ -1,117 +1,44 @@ -/* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* getline.c -- Replacement for GNU C library function getline - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003, 2004 Free + Software Foundation, Inc. - This library is distributed in the hope that it will be useful, + 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, 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 - Lesser General Public License for more details. + 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 Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* First implementation by Alain Magloire */ +/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ -#ifdef HAVE_CONFIG_H +#if HAVE_CONFIG_H # include <config.h> #endif -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -ssize_t -getline (char **lineptr, size_t *n, FILE *stream) -{ - return getdelim (lineptr, n, '\n', stream); -} +#include "getline.h" -#ifndef HAVE_GETDELIM +#if ! (defined __GNU_LIBRARY__ && HAVE_GETDELIM) -/* Default value for line length. */ -static const int line_size = 128; +# include "getndelim2.h" ssize_t -getdelim (char **lineptr, size_t *n, int delim, FILE *stream) +getdelim (char **lineptr, size_t *linesize, int delimiter, FILE *stream) { - int indx = 0; - int c; - - /* Sanity checks. */ - if (lineptr == NULL || n == NULL || stream == NULL) - return -1; - - /* Allocate the line the first time. */ - if (*lineptr == NULL) - { - *lineptr = malloc (line_size); - if (*lineptr == NULL) - return -1; - *n = line_size; - } - - while ((c = getc (stream)) != EOF) - { - /* Check if more memory is needed. */ - if (indx >= *n) - { - *lineptr = realloc (*lineptr, *n + line_size); - if (*lineptr == NULL) - return -1; - *n += line_size; - } - - /* Push the result in the line. */ - (*lineptr)[indx++] = c; - - /* Bail out. */ - if (c == delim) - break; - } - - /* Make room for the null character. */ - if (indx >= *n) - { - *lineptr = realloc (*lineptr, *n + line_size); - if (*lineptr == NULL) - return -1; - *n += line_size; - } - - /* Null terminate the buffer. */ - (*lineptr)[indx++] = 0; - - /* The last line may not have the delimiter, we have to - * return what we got and the error will be seen on the - * next iteration. */ - return (c == EOF && (indx - 1) == 0) ? -1 : indx - 1; + return getndelim2 (lineptr, linesize, 0, GETNLINE_NO_LIMIT, delimiter, EOF, + stream); } +#endif -#endif /* HAVE_GETDELIM */ - - -#ifdef STANDALONE -int main(void) +ssize_t +getline (char **lineptr, size_t *linesize, FILE *stream) { - FILE * fp; - char * line = NULL; - size_t len = 0; - ssize_t read; - fp = fopen("/etc/passwd", "r"); - if (fp == NULL) - exit(EXIT_FAILURE); - while ((read = getline(&line, &len, fp)) != -1) { - printf("Retrieved line of length %zu :\n", read); - printf("%s", line); - } - if (line) - free(line); - return EXIT_SUCCESS; + return getdelim (lineptr, linesize, '\n', stream); } -#endif diff --git a/mailbox/getline.h b/mailbox/getline.h index 77b234f..ee9fc05 100644 --- a/mailbox/getline.h +++ b/mailbox/getline.h @@ -1,35 +1,39 @@ -/* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* Replacement for GNU C library function getline - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + Copyright (C) 1995, 1997, 1999, 2000, 2001, 2002, 2003 Free + Software Foundation, Inc. - This library 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 - Lesser General Public License for more details. +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, or (at your option) +any later version. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +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. -#ifndef _GETLINE_H_ -# define _GETLINE_H_ 1 +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef GETLINE_H_ +# define GETLINE_H_ 1 + +# include <stddef.h> # include <stdio.h> -# ifndef PARAMS -# if defined (__GNUC__) || __STDC__ -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -# endif +/* Get ssize_t. */ +# include <sys/types.h> + +/* glibc2 has these functions declared in <stdio.h>. Avoid redeclarations. */ +# if __GLIBC__ < 2 -extern int getline PARAMS ((char **_lineptr, size_t *_n, FILE *_stream)); +extern ssize_t getline (char **_lineptr, size_t *_linesize, FILE *_stream); -extern int getdelim PARAMS ((char **_lineptr, size_t *_n, int _delimiter, FILE *_stream)); +extern ssize_t getdelim (char **_lineptr, size_t *_linesize, int _delimiter, + FILE *_stream); + +# endif -#endif /* ! _GETLINE_H_ */ +#endif /* not GETLINE_H_ */ diff --git a/mailbox/getopt.c b/mailbox/getopt.c index e852127..ef790b7 100644 --- a/mailbox/getopt.c +++ b/mailbox/getopt.c @@ -1,22 +1,23 @@ /* Getopt for GNU. - NOTE: The canonical source of this file is maintained with the GNU - C Library. Bugs can be reported to bug-glibc@gnu.org. - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 - Free Software Foundation, Inc. - - 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, or (at your option) any - later version. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, 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, write to the Free Software Foundation, + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. @@ -29,35 +30,8 @@ # include <config.h> #endif -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -# ifndef const -# define const -# endif -#endif - #include <stdio.h> -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -# include <gnu-versions.h> -# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE - - /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ @@ -67,40 +41,43 @@ # include <unistd.h> #endif /* GNU C library. */ +#include <string.h> + #ifdef VMS # include <unixlib.h> -# if HAVE_STRING_H - 0 -# include <string.h> -# endif #endif -#ifndef _ -/* This is for other GNU distributions with internationalized messages. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> -# ifndef _ -# define _(msgid) gettext (msgid) -# endif -# else -# define _(msgid) (msgid) -# endif +#ifdef _LIBC +# include <libintl.h> +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif + +#if defined _LIBC && defined USE_IN_LIBIO +# include <wchar.h> #endif -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. +#ifndef attribute_hidden +# define attribute_hidden +#endif + +/* Unlike standard Unix `getopt', functions like `getopt_long' + let the user intersperse the options with the other arguments. - As `getopt' works, it permutes the elements of ARGV so that, + As `getopt_long' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. + Using `getopt' or setting the environment variable POSIXLY_CORRECT + disables permutation. + Then the application's behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" +#include "getopt_int.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, @@ -125,21 +102,6 @@ char *optarg; /* 1003.2 says this must be 1 before any call. */ int optind = 1; -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - /* Callers store zero here to inhibit the error message for unrecognized options. */ @@ -151,57 +113,12 @@ int opterr = 1; int optopt = '?'; -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ +/* Keep a global copy of all internal members of getopt_data. */ -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; +static struct _getopt_data getopt_data; -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -# include <string.h> -# define my_index strchr -#else - -# if HAVE_STRING_H -# include <string.h> -# else -# include <strings.h> -# endif +#ifndef __GNU_LIBRARY__ /* Avoid depending on library functions or files whose names are inconsistent. */ @@ -210,79 +127,34 @@ static char *posixly_correct; extern char *getenv (); #endif -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -# if (!defined __STDC__ || !__STDC__) && !defined strlen -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -# endif /* not __STDC__ */ -#endif /* __GNUC__ */ - #endif /* not __GNU_LIBRARY__ */ -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - #ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +extern int __libc_argc; +extern char **__libc_argv; + /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ +# ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; +# endif -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} -# ifdef text_set_element -text_set_element (__libc_subinit, store_args_and_env); -# endif /* text_set_element */ - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ +# ifdef USE_NONOPTION_FLAGS +# define SWAP_FLAGS(ch1, ch2) \ + if (d->__nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ @@ -296,17 +168,12 @@ text_set_element (__libc_subinit, store_args_and_env); `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ -#if defined __STDC__ && __STDC__ -static void exchange (char **); -#endif - static void -exchange (argv) - char **argv; +exchange (char **argv, struct _getopt_data *d) { - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. @@ -314,23 +181,23 @@ exchange (argv) It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ -#ifdef _LIBC +#if defined _LIBC && defined USE_NONOPTION_FLAGS /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; + d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; + d->__nonoption_flags_max_len), + '\0', top + 1 - d->__nonoption_flags_max_len); + d->__nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } @@ -376,76 +243,71 @@ exchange (argv) /* Update records for the slots the non-options now occupy. */ - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; } /* Initialize the internal data when the first call is made. */ -#if defined __STDC__ && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +_getopt_initialize (int argc, char **argv, const char *optstring, + int posixly_correct, struct _getopt_data *d) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ - first_nonopt = last_nonopt = optind; + d->__first_nonopt = d->__last_nonopt = d->optind; - nextchar = NULL; + d->__nextchar = NULL; - posixly_correct = getenv ("POSIXLY_CORRECT"); + d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { - ordering = RETURN_IN_ORDER; + d->__ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { - ordering = REQUIRE_ORDER; + d->__ordering = REQUIRE_ORDER; ++optstring; } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; else - ordering = PERMUTE; + d->__ordering = PERMUTE; -#ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (!d->__posixly_correct + && argc == __libc_argc && argv == __libc_argv) { - if (nonoption_flags_max_len == 0) + if (d->__nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; + d->__nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; + int len = d->__nonoption_flags_max_len = strlen (orig_str); + if (d->__nonoption_flags_max_len < argc) + d->__nonoption_flags_max_len = argc; __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); + (char *) malloc (d->__nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; + d->__nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); + '\0', d->__nonoption_flags_max_len - len); } } - nonoption_flags_len = nonoption_flags_max_len; + d->__nonoption_flags_len = d->__nonoption_flags_max_len; } else - nonoption_flags_len = 0; + d->__nonoption_flags_len = 0; #endif return optstring; @@ -493,10 +355,6 @@ _getopt_initialize (argc, argv, optstring) `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. @@ -505,73 +363,74 @@ _getopt_initialize (argc, argv, optstring) recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ + long-named options. + + If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT + environment variable were set. */ int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; +_getopt_internal_r (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, int posixly_correct, struct _getopt_data *d) { - int print_errors = opterr; + int print_errors = d->opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; - optarg = NULL; + d->optarg = NULL; - if (optind == 0 || !__getopt_initialized) + if (d->optind == 0 || !d->__initialized) { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; + if (d->optind == 0) + d->optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring, + posixly_correct, d); + d->__initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ -#ifdef _LIBC -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ + || (d->optind < d->__nonoption_flags_len \ + && __getopt_nonoption_flags[d->optind] == '1')) #else -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') #endif - if (nextchar == NULL || *nextchar == '\0') + if (d->__nextchar == NULL || *d->__nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; - if (ordering == PERMUTE) + if (d->__ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; } /* The special ARGV-element `--' means premature end of options. @@ -579,28 +438,29 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ - if (optind != argc && !strcmp (argv[optind], "--")) + if (d->optind != argc && !strcmp (argv[d->optind], "--")) { - optind++; + d->optind++; - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; - optind = argc; + d->optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ - if (optind == argc) + if (d->optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; return -1; } @@ -609,17 +469,17 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) if (NONOPTION_P) { - if (ordering == REQUIRE_ORDER) + if (d->__ordering == REQUIRE_ORDER) return -1; - optarg = argv[optind++]; + d->optarg = argv[d->optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); + d->__nextchar = (argv[d->optind] + 1 + + (longopts != NULL && argv[d->optind][1] == '-')); } /* Decode the current option-ARGV-element. */ @@ -638,8 +498,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) This distinction seems to be the most useful approach. */ if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))))) { char *nameend; const struct option *p; @@ -649,15 +510,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int indfound = -1; int option_index; - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) { - if ((unsigned int) (nameend - nextchar) + if ((unsigned int) (nameend - d->__nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ @@ -683,62 +544,158 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) if (ambig && !exact) { if (print_errors) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; - optind++; + d->optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = nameend + 1; + d->optarg = nameend + 1; else { if (print_errors) { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); - optopt = pfound->val; + d->optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { - if (optind < argc) - optarg = argv[optind++]; + if (d->optind < argc) + d->optarg = argv[d->optind++]; else { if (print_errors) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) @@ -753,23 +710,62 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) { if (print_errors) { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), + argv[0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], d->__nextchar); +#endif + } else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif } - nextchar = (char *) ""; - optind++; - optopt = 0; + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; return '?'; } } @@ -777,26 +773,63 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) /* Look at and handle the next short option-character. */ { - char c = *nextchar++; - char *temp = my_index (optstring, c); + char c = *d->__nextchar++; + char *temp = strchr (optstring, c); /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; + if (*d->__nextchar == '\0') + ++d->optind; if (temp == NULL || c == ':') { if (print_errors) { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (d->__posixly_correct) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: illegal option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); +#endif + } else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); + { +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: invalid option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif } - optopt = c; + d->optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ @@ -811,22 +844,46 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int option_index; /* This is an option that requires an argument. */ - if (*nextchar != '\0') + if (*d->__nextchar != '\0') { - optarg = nextchar; + d->optarg = d->__nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ - optind++; + d->optind++; } - else if (optind == argc) + else if (d->optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); +#endif } - optopt = c; + d->optopt = c; if (optstring[0] == ':') c = ':'; else @@ -834,22 +891,23 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) return c; } else - /* We already incremented `optind' once; + /* We already incremented `d->optind' once; increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; + d->optarg = argv[d->optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; + nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -870,10 +928,35 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) if (ambig && !exact) { if (print_errors) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; return '?'; } if (pfound != NULL) @@ -884,33 +967,87 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = nameend + 1; + d->optarg = nameend + 1; else { if (print_errors) - fprintf (stderr, _("\ + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); + argv[0], pfound->name); +#endif + } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); return '?'; } } else if (pfound->has_arg == 1) { - if (optind < argc) - optarg = argv[optind++]; + if (d->optind < argc) + d->optarg = argv[d->optind++]; else { if (print_errors) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); return optstring[0] == ':' ? ':' : '?'; } } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) @@ -920,7 +1057,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } return pfound->val; } - nextchar = NULL; + d->__nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') @@ -928,35 +1065,59 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') + if (*d->__nextchar != '\0') { - optarg = nextchar; - optind++; + d->optarg = d->__nextchar; + d->optind++; } else - optarg = NULL; - nextchar = NULL; + d->optarg = NULL; + d->__nextchar = NULL; } else { /* This is an option that requires an argument. */ - if (*nextchar != '\0') + if (*d->__nextchar != '\0') { - optarg = nextchar; + d->optarg = d->__nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ - optind++; + d->optind++; } - else if (optind == argc) + else if (d->optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); +#endif } - optopt = c; + d->optopt = c; if (optstring[0] == ':') c = ':'; else @@ -965,8 +1126,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; } } return c; @@ -974,18 +1135,40 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +_getopt_internal (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, int posixly_correct) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, longind, + long_only, posixly_correct, &getopt_data); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +/* glibc gets a LSB-compliant getopt. + Standalone applications get a POSIX-compliant getopt. */ +#if _LIBC +enum { POSIXLY_CORRECT = 0 }; +#else +enum { POSIXLY_CORRECT = 1 }; +#endif + +int +getopt (int argc, char *const *argv, const char *optstring) { - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); + return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, + POSIXLY_CORRECT); } -#endif /* Not ELIDE_CODE. */ #ifdef TEST @@ -993,9 +1176,7 @@ getopt (argc, argv, optstring) the above definition of `getopt'. */ int -main (argc, argv) - int argc; - char **argv; +main (int argc, char **argv) { int c; int digit_optind = 0; diff --git a/mailbox/getopt1.c b/mailbox/getopt1.c index 49ca5b0..a747237 100644 --- a/mailbox/getopt1.c +++ b/mailbox/getopt1.c @@ -1,58 +1,35 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@gnu.org. + This file is part of the GNU C Library. - 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, or (at your option) any - later version. + 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, 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, write to the Free Software Foundation, + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include "getopt.h" - -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif +#ifdef _LIBC +# include <getopt.h> +#else +# include "getopt.h" #endif +#include "getopt_int.h" #include <stdio.h> -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -#include <gnu-versions.h> -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ @@ -64,14 +41,20 @@ #endif int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, + const struct option *long_options, int *opt_index) { - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 0, 0); +} + +int +_getopt_long_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 0, 0, d); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. @@ -80,27 +63,30 @@ getopt_long (argc, argv, options, long_options, opt_index) instead. */ int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +getopt_long_only (int argc, char *__getopt_argv_const *argv, + const char *options, + const struct option *long_options, int *opt_index) { - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 1, 0); } +int +_getopt_long_only_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 1, 0, d); +} -#endif /* Not ELIDE_CODE. */ #ifdef TEST #include <stdio.h> int -main (argc, argv) - int argc; - char **argv; +main (int argc, char **argv) { int c; int digit_optind = 0; diff --git a/mailbox/md5.c b/mailbox/md5.c index 665448d..999e25e 100644 --- a/mailbox/md5.c +++ b/mailbox/md5.c @@ -1,288 +1,447 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ -/* - * Modified (2001-01-31) to work on Sparcs <gray@Mirddin.farlep.net> - */ -#if defined(HAVE_CONFIG_H) +/* md5.c - Functions to compute MD5 message digest of files or memory blocks + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995, 1996, 2001, 2003, 2004 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ + +#ifdef HAVE_CONFIG_H # include <config.h> #endif -#define MD5_CRYPT +#include "md5.h" + +#include <stddef.h> +#include <string.h> + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifdef _LIBC +# include <endian.h> +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_read_ctx __md5_read_ctx +# define md5_stream __md5_stream +# define md5_buffer __md5_buffer +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + +#define BLOCKSIZE 4096 +/* Ensure that BLOCKSIZE is a multiple of 64. */ +#if BLOCKSIZE % 64 != 0 +/* FIXME-someday (soon?): use #error instead of this kludge. */ +"invalid BLOCKSIZE" +#endif -#ifdef MD5_CRYPT -#include <string.h> /* for memcpy() */ -#include <md5.h> +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ void -md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen) +md5_init_ctx (struct md5_ctx *ctx) { - MD5_CTX context; + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; - MD5Init(&context); - MD5Update(&context, input, inlen); - MD5Final(output, &context); + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; } +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. -static void -bytes_encode(unsigned char *output, uint32 *input, unsigned int len) + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); -static void -bytes_decode(uint32 *output, unsigned char *input, unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((uint32)input[j]) | - (((uint32)input[j+1]) << 8) | - (((uint32)input[j+2]) << 16) | - (((uint32)input[j+3]) << 24); + return resbuf; } -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void -MD5Init(struct MD5Context *ctx) +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) { - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void -MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); - while (len >= 64) { - memcpy(ctx->in, buf, 64); - MD5Transform(ctx->buf, (uint32 const *) buf); - buf += 64; - len -= 64; - } + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); - /* Handle any remaining bytes of data. */ + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); - memcpy(ctx->in, buf, len); + return md5_read_ctx (ctx, resbuf); } -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void -MD5Final(unsigned char digest[16], struct MD5Context *ctx) +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (FILE *stream, void *resblock) { - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + + if (sum == BLOCKSIZE) + break; + + if (n == 0) + { + /* Check for the error flag IFF N == 0, so that we don't + exit the loop after a partial read due to e.g., EAGAIN + or EWOULDBLOCK. */ + if (ferror (stream)) + return 1; + goto process_partial_block; + } + + /* We've read at least one byte, so ignore errors. But always + check for EOF, since feof may be true even though N > 0. + Otherwise, we could end up calling fread after EOF. */ + if (feof (stream)) + goto process_partial_block; + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); } - /* Append length in bits and transform */ - bytes_encode((unsigned char*)((uint32 *) ctx->in + 14), ctx->bits, 8); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - bytes_encode(digest,ctx->buf,16); - memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */ + process_partial_block:; + + /* Process any remaining bytes. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; } -#ifndef ASM_MD5 +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (const char *buffer, size_t len, void *resblock) +{ + struct md5_ctx ctx; -/* The four core functions - F1 is optimized somewhat */ + /* Initialize the computation context. */ + md5_init_ctx (&ctx); -/*#define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ); -#if 0 -dump(char *label,unsigned char *p, int len) +void +md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) { - int i; - return; - printf("dump: %s\n", label); - for (i=0; i<len; i++) - printf("%x\n", p[i]); - printf("--\n"); + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } -} + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +# define alignof(type) offsetof (struct { char c; type x; }, x) +# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else #endif + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ void -MD5Transform(uint32 buf[4], uint32 const cin[16]) +md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) { - register uint32 a, b, c, d; - uint32 in[16]; - - bytes_decode(in, (unsigned char *) cin, 64); - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } -#endif -#endif /* MD5_CRYPT */ + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/mailbox/md5.h b/mailbox/md5.h index c4e8c40..661de4b 100644 --- a/mailbox/md5.h +++ b/mailbox/md5.h @@ -1,24 +1,106 @@ -#ifndef MD5_H -#define MD5_H +/* md5.h - Declaration of functions and data types used for MD5 sum + computing library functions. -#ifdef __alpha -typedef unsigned int uint32; -#else -typedef unsigned long uint32; + Copyright (C) 1995, 1996, 1999, 2000, 2003, 2004 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include <stdio.h> + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#if HAVE_STDINT_H || _LIBC +# include <stdint.h> #endif -struct MD5Context { - uint32 buf[4]; - uint32 bits[2]; - unsigned char in[64]; +typedef uint32_t md5_uint32; + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128]; }; -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); -void MD5Transform(uint32 buf[4], uint32 const in[16]); +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void md5_init_ctx (struct md5_ctx *ctx); -typedef struct MD5Context MD5_CTX; +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void md5_process_block (const void *buffer, size_t len, + struct md5_ctx *ctx); -#endif /* !MD5_H */ +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int md5_stream (FILE *stream, void *resblock); + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *md5_buffer (const char *buffer, size_t len, void *resblock); + +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +#endif diff --git a/mailbox/regex.c b/mailbox/regex.c index 358071b..d384070 100644 --- a/mailbox/regex.c +++ b/mailbox/regex.c @@ -2,22 +2,23 @@ version 0.12. (Implements POSIX draft P1003.2/D11.2, except for some of the internationalization features.) - Copyright (C) 1993-1999, 2000, 2001 Free Software Foundation, Inc. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004 Free Software Foundation, Inc. - The GNU C Library is distributed in the hope that it will be useful, + 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, 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* AIX requires this to be the first thing in the file. */ #if defined _AIX && !defined REGEX_MALLOC @@ -31,140 +32,105 @@ # include <config.h> #endif -#ifndef PARAMS -# if defined __GNUC__ || (defined __STDC__ && __STDC__) -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif /* GCC. */ -#endif /* Not PARAMS. */ +#ifndef INSIDE_RECURSION -#if defined STDC_HEADERS && !defined emacs # include <stddef.h> -#else -/* We need this for `regex.h', and perhaps for the Emacs include files. */ -# include <sys/types.h> -#endif -#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) +# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) /* For platform which support the ISO C amendement 1 functionality we support user defined character classes. */ -#if defined _LIBC || WIDE_CHAR_SUPPORT +# if defined _LIBC || WIDE_CHAR_SUPPORT /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ -# include <wchar.h> -# include <wctype.h> -#endif - -/* This is for multi byte string support. */ -#ifdef MBS_SUPPORT -# define CHAR_TYPE wchar_t -# define US_CHAR_TYPE wchar_t/* unsigned character type */ -# define COMPILED_BUFFER_VAR wc_buffer -# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ -# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_TYPE)+1) -# define PUT_CHAR(c) \ - do { \ - if (MB_CUR_MAX == 1) \ - putchar (c); \ - else \ - printf ("%C", (wint_t) c); /* Should we use wide stream?? */ \ - } while (0) -# define TRUE 1 -# define FALSE 0 -#else -# define CHAR_TYPE char -# define US_CHAR_TYPE unsigned char /* unsigned character type */ -# define COMPILED_BUFFER_VAR bufp->buffer -# define OFFSET_ADDRESS_SIZE 2 -# define PUT_CHAR(c) putchar (c) -#endif /* MBS_SUPPORT */ +# include <wchar.h> +# include <wctype.h> +# endif -#ifdef _LIBC +# ifdef _LIBC /* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ +# define regfree(preg) __regfree (preg) +# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) +# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) +# define regerror(errcode, preg, errbuf, errbuf_size) \ __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ +# define re_set_registers(bu, re, nu, st, en) \ __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ +# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ +# define re_match(bufp, string, size, pos, regs) \ __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ +# define re_search(bufp, string, size, startpos, range, regs) \ __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ +# define re_compile_pattern(pattern, length, bufp) \ __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ +# define re_set_syntax(syntax) __re_set_syntax (syntax) +# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) +# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) -# define btowc __btowc +# define btowc __btowc +# define iswctype __iswctype +# define mbrtowc __mbrtowc +# define wcslen __wcslen +# define wcscoll __wcscoll +# define wcrtomb __wcrtomb /* We are also using some library internals. */ -# include <locale/localeinfo.h> -# include <locale/elem-hash.h> -# include <langinfo.h> -# include <locale/coll-lookup.h> -#endif +# include <locale/localeinfo.h> +# include <locale/elem-hash.h> +# include <langinfo.h> +# include <locale/coll-lookup.h> +# endif -/* This is for other GNU distributions with internationalized messages. */ -#if HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> # ifdef _LIBC +# include <libintl.h> # undef gettext # define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) + /* This define is so xgettext can find the internationalizable strings. */ +# define gettext_noop(msgid) msgid +# else +/* This is for other GNU distributions with internationalized messages. */ +# include "gettext.h" # endif -#else -# define gettext(msgid) (msgid) -#endif -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif +/* Support for bounded pointers. */ +# if !defined _LIBC && !defined __BOUNDED_POINTERS__ +# define __bounded /* nothing */ +# define __unbounded /* nothing */ +# define __ptrvalue /* nothing */ +# endif /* The `emacs' switch turns on certain matching commands that make sense only in Emacs. */ -#ifdef emacs +# ifdef emacs -# include "lisp.h" -# include "buffer.h" -# include "syntax.h" +# include "lisp.h" +# include "buffer.h" +# include "syntax.h" -#else /* not emacs */ +# else /* not emacs */ /* If we are not linking with Emacs proper, we can't use the relocating allocator even if config.h says that we can. */ -# undef REL_ALLOC +# undef REL_ALLOC -# if defined STDC_HEADERS || defined _LIBC # include <stdlib.h> -# else -char *malloc (); -char *realloc (); -# endif /* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. If nothing else has been done, use the method below. */ -# ifdef INHIBIT_STRING_HEADER -# if !(defined HAVE_BZERO && defined HAVE_BCOPY) -# if !defined bzero && !defined bcopy -# undef INHIBIT_STRING_HEADER +# ifdef INHIBIT_STRING_HEADER +# if !(defined HAVE_BZERO && defined HAVE_BCOPY) +# if !defined bzero && !defined bcopy +# undef INHIBIT_STRING_HEADER +# endif # endif # endif -# endif /* This is the normal way of making sure we have a bcopy and a bzero. This is used in most programs--a few other programs avoid this by defining INHIBIT_STRING_HEADER. */ -# ifndef INHIBIT_STRING_HEADER -# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC +# ifndef INHIBIT_STRING_HEADER # include <string.h> # ifndef bzero # ifndef _LIBC @@ -173,46 +139,35 @@ char *realloc (); # define bzero(s, n) __bzero (s, n) # endif # endif -# else -# include <strings.h> -# ifndef memcmp -# define memcmp(s1, s2, n) bcmp (s1, s2, n) -# endif -# ifndef memcpy -# define memcpy(d, s, n) (bcopy (s, d, n), (d)) -# endif # endif -# endif /* Define the syntax stuff for \<, \>, etc. */ /* This must be nonzero for the wordchar and notwordchar pattern commands in re_match_2. */ -# ifndef Sword -# define Sword 1 -# endif +# ifndef Sword +# define Sword 1 +# endif -# ifdef SWITCH_ENUM_BUG -# define SWITCH_ENUM_CAST(x) ((int)(x)) -# else -# define SWITCH_ENUM_CAST(x) (x) -# endif +# ifdef SWITCH_ENUM_BUG +# define SWITCH_ENUM_CAST(x) ((int)(x)) +# else +# define SWITCH_ENUM_CAST(x) (x) +# endif -#endif /* not emacs */ +# endif /* not emacs */ -#if defined _LIBC || HAVE_LIMITS_H # include <limits.h> -#endif -#ifndef MB_LEN_MAX -# define MB_LEN_MAX 1 -#endif +# ifndef MB_LEN_MAX +# define MB_LEN_MAX 1 +# endif /* Get the interface, including the syntax bits. */ -#include <regex.h> +# include <regex.h> /* isalpha etc. are used for the character classes. */ -#include <ctype.h> +# include <ctype.h> /* Jim Meyering writes: @@ -226,74 +181,55 @@ char *realloc (); eliminate the && through constant folding." Solaris defines some of these symbols so we must undefine them first. */ -#undef ISASCII -#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) -# define ISASCII(c) 1 -#else -# define ISASCII(c) isascii(c) -#endif - -#ifdef isblank -# define ISBLANK(c) (ISASCII (c) && isblank (c)) -#else -# define ISBLANK(c) ((c) == ' ' || (c) == '\t') -#endif -#ifdef isgraph -# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) -#else -# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) -#endif - -#undef ISPRINT -#define ISPRINT(c) (ISASCII (c) && isprint (c)) -#define ISDIGIT(c) (ISASCII (c) && isdigit (c)) -#define ISALNUM(c) (ISASCII (c) && isalnum (c)) -#define ISALPHA(c) (ISASCII (c) && isalpha (c)) -#define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) -#define ISLOWER(c) (ISASCII (c) && islower (c)) -#define ISPUNCT(c) (ISASCII (c) && ispunct (c)) -#define ISSPACE(c) (ISASCII (c) && isspace (c)) -#define ISUPPER(c) (ISASCII (c) && isupper (c)) -#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) - -#ifdef _tolower -# define TOLOWER(c) _tolower(c) -#else -# define TOLOWER(c) tolower(c) -#endif +# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) +# define IN_CTYPE_DOMAIN(c) 1 +# else +# define IN_CTYPE_DOMAIN(c) isascii(c) +# endif -#ifndef NULL -# define NULL (void *)0 -#endif +# ifdef isblank +# define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c)) +# else +# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c)) +# endif -/* We remove any previous definition of `SIGN_EXTEND_CHAR', - since ours (we hope) works properly with all combinations of - machines, compilers, `char' and `unsigned char' argument types. - (Per Bothner suggested the basic approach.) */ -#undef SIGN_EXTEND_CHAR -#if __STDC__ -# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) -#else /* not __STDC__ */ -/* As in Harbison and Steele. */ -# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) -#endif +# undef ISPRINT +# define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) +# define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) +# define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) +# define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +# define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c)) +# define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) +# define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c)) +# define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) +# define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) +# define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) + +# ifdef _tolower +# define TOLOWER(c) _tolower(c) +# else +# define TOLOWER(c) tolower(c) +# endif -#ifndef emacs +# ifndef emacs /* How many characters in the character set. */ -# define CHAR_SET_SIZE 256 +# define CHAR_SET_SIZE 256 -# ifdef SYNTAX_TABLE +# ifdef SYNTAX_TABLE extern char *re_syntax_table; -# else /* not SYNTAX_TABLE */ +# else /* not SYNTAX_TABLE */ static char re_syntax_table[CHAR_SET_SIZE]; -static void init_syntax_once PARAMS ((void)); - static void -init_syntax_once () +init_syntax_once (void) { register int c; static int done = 0; @@ -311,11 +247,11 @@ init_syntax_once () done = 1; } -# endif /* not SYNTAX_TABLE */ +# endif /* not SYNTAX_TABLE */ -# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] +# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] -#endif /* emacs */ +# endif /* emacs */ /* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we use `alloca' instead of `malloc'. This is because using malloc in @@ -327,104 +263,131 @@ init_syntax_once () not functions -- `alloca'-allocated space disappears at the end of the function it is called in. */ -#ifdef REGEX_MALLOC +# ifdef REGEX_MALLOC -# define REGEX_ALLOCATE malloc -# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) -# define REGEX_FREE free +# define REGEX_ALLOCATE malloc +# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE free -#else /* not REGEX_MALLOC */ +# else /* not REGEX_MALLOC */ /* Emacs already defines alloca, sometimes. */ -# ifndef alloca +# ifndef alloca /* Make alloca work the best possible way. */ -# ifdef __GNUC__ -# define alloca __builtin_alloca -# else /* not __GNUC__ */ -# if HAVE_ALLOCA_H -# include <alloca.h> -# endif /* HAVE_ALLOCA_H */ -# endif /* not __GNUC__ */ +# include <alloca.h> -# endif /* not alloca */ +# endif /* not alloca */ -# define REGEX_ALLOCATE alloca +# define REGEX_ALLOCATE alloca /* Assumes a `char *destination' variable. */ -# define REGEX_REALLOCATE(source, osize, nsize) \ +# define REGEX_REALLOCATE(source, osize, nsize) \ (destination = (char *) alloca (nsize), \ memcpy (destination, source, osize)) /* No need to do anything to free, after alloca. */ -# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ +# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ -#endif /* not REGEX_MALLOC */ +# endif /* not REGEX_MALLOC */ /* Define how to allocate the failure stack. */ -#if defined REL_ALLOC && defined REGEX_MALLOC +# if defined REL_ALLOC && defined REGEX_MALLOC -# define REGEX_ALLOCATE_STACK(size) \ +# define REGEX_ALLOCATE_STACK(size) \ r_alloc (&failure_stack_ptr, (size)) -# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ r_re_alloc (&failure_stack_ptr, (nsize)) -# define REGEX_FREE_STACK(ptr) \ +# define REGEX_FREE_STACK(ptr) \ r_alloc_free (&failure_stack_ptr) -#else /* not using relocating allocator */ +# else /* not using relocating allocator */ -# ifdef REGEX_MALLOC +# ifdef REGEX_MALLOC -# define REGEX_ALLOCATE_STACK malloc -# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) -# define REGEX_FREE_STACK free +# define REGEX_ALLOCATE_STACK malloc +# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE_STACK free -# else /* not REGEX_MALLOC */ +# else /* not REGEX_MALLOC */ -# define REGEX_ALLOCATE_STACK alloca +# define REGEX_ALLOCATE_STACK alloca -# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ REGEX_REALLOCATE (source, osize, nsize) /* No need to explicitly free anything. */ -# define REGEX_FREE_STACK(arg) +# define REGEX_FREE_STACK(arg) -# endif /* not REGEX_MALLOC */ -#endif /* not using relocating allocator */ +# endif /* not REGEX_MALLOC */ +# endif /* not using relocating allocator */ /* True if `size1' is non-NULL and PTR is pointing anywhere inside `string1' or just past its end. This works if PTR is NULL, which is a good thing. */ -#define FIRST_STRING_P(ptr) \ +# define FIRST_STRING_P(ptr) \ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) /* (Re)Allocate N items of type T using malloc, or fail. */ -#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) -#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) -#define RETALLOC_IF(addr, n, t) \ +# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +# define RETALLOC_IF(addr, n, t) \ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) -#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) +# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) -#define BYTEWIDTH 8 /* In bits. */ +# define BYTEWIDTH 8 /* In bits. */ -#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) -#undef MAX -#undef MIN -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) +# undef MAX +# undef MIN +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +# define MIN(a, b) ((a) < (b) ? (a) : (b)) typedef char boolean; -#define false 0 -#define true 1 - -static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp, - const char *string1, int size1, - const char *string2, int size2, - int pos, - struct re_registers *regs, - int stop)); +# define false 0 +# define true 1 + +static reg_errcode_t byte_regex_compile (const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp); + +static int byte_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop); +static int byte_re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, int stop); +static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp); + +#ifdef MBS_SUPPORT +static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp); + + +static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *cstring1, int csize1, + const char *cstring2, int csize2, + int pos, + struct re_registers *regs, + int stop, + wchar_t *string1, int size1, + wchar_t *string2, int size2, + int *mbs_offset1, int *mbs_offset2); +static int wcs_re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, int stop); +static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp); +#endif /* These are the command codes that appear in compiled regular expressions. Some opcodes are followed by argument bytes. A @@ -441,10 +404,10 @@ typedef enum /* Followed by one byte giving n, then by n literal bytes. */ exactn, -#ifdef MBS_SUPPORT +# ifdef MBS_SUPPORT /* Same as exactn, but contains binary data. */ exactn_bin, -#endif +# endif /* Matches any (more or less) character. */ anychar, @@ -570,7 +533,7 @@ typedef enum wordbound, /* Succeeds if at a word boundary. */ notwordbound /* Succeeds if not at a word boundary. */ -#ifdef emacs +# ifdef emacs ,before_dot, /* Succeeds if before point. */ at_dot, /* Succeeds if at point. */ after_dot, /* Succeeds if after point. */ @@ -581,33 +544,75 @@ typedef enum /* Matches any character whose syntax is not that specified. */ notsyntaxspec -#endif /* emacs */ +# endif /* emacs */ } re_opcode_t; +#endif /* not INSIDE_RECURSION */ + +#ifdef BYTE +# define CHAR_T char +# define UCHAR_T unsigned char +# define COMPILED_BUFFER_VAR bufp->buffer +# define OFFSET_ADDRESS_SIZE 2 +# define PREFIX(name) byte_##name +# define ARG_PREFIX(name) name +# define PUT_CHAR(c) putchar (c) +#else +# ifdef WCHAR +# define CHAR_T wchar_t +# define UCHAR_T wchar_t +# define COMPILED_BUFFER_VAR wc_buffer +# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ +# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) +# define PREFIX(name) wcs_##name +# define ARG_PREFIX(name) c##name +/* Should we use wide stream?? */ +# define PUT_CHAR(c) printf ("%C", c); +# define TRUE 1 +# define FALSE 0 +# else +# ifdef MBS_SUPPORT +# define WCHAR +# define INSIDE_RECURSION +# include "regex.c" +# undef INSIDE_RECURSION +# endif +# define BYTE +# define INSIDE_RECURSION +# include "regex.c" +# undef INSIDE_RECURSION +# endif +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifdef INSIDE_RECURSION /* Common operations on the compiled pattern. */ /* Store NUMBER in two contiguous bytes starting at DESTINATION. */ /* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -#ifdef MBS_SUPPORT -# define STORE_NUMBER(destination, number) \ +# ifdef WCHAR +# define STORE_NUMBER(destination, number) \ do { \ - *(destination) = (US_CHAR_TYPE)(number); \ + *(destination) = (UCHAR_T)(number); \ } while (0) -#else -# define STORE_NUMBER(destination, number) \ +# else /* BYTE */ +# define STORE_NUMBER(destination, number) \ do { \ (destination)[0] = (number) & 0377; \ (destination)[1] = (number) >> 8; \ } while (0) -#endif /* MBS_SUPPORT */ +# endif /* WCHAR */ /* Same as STORE_NUMBER, except increment DESTINATION to the byte after where the number is stored. Therefore, DESTINATION must be an lvalue. */ /* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -#define STORE_NUMBER_AND_INCR(destination, number) \ +# define STORE_NUMBER_AND_INCR(destination, number) \ do { \ STORE_NUMBER (destination, number); \ (destination) += OFFSET_ADDRESS_SIZE; \ @@ -617,103 +622,102 @@ typedef enum at SOURCE. */ /* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -#ifdef MBS_SUPPORT -# define EXTRACT_NUMBER(destination, source) \ +# ifdef WCHAR +# define EXTRACT_NUMBER(destination, source) \ do { \ (destination) = *(source); \ } while (0) -#else -# define EXTRACT_NUMBER(destination, source) \ +# else /* BYTE */ +# define EXTRACT_NUMBER(destination, source) \ do { \ (destination) = *(source) & 0377; \ - (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + (destination) += (signed char) (*((source) + 1)) << 8; \ } while (0) -#endif +# endif -#ifdef DEBUG -static void extract_number _RE_ARGS ((int *dest, US_CHAR_TYPE *source)); +# ifdef DEBUG static void -extract_number (dest, source) - int *dest; - US_CHAR_TYPE *source; +PREFIX(extract_number) (int *dest, UCHAR_T *source) { -#ifdef MBS_SUPPORT +# ifdef WCHAR *dest = *source; -#else - int temp = SIGN_EXTEND_CHAR (*(source + 1)); +# else /* BYTE */ + signed char temp = source[1]; *dest = *source & 0377; *dest += temp << 8; -#endif +# endif } -# ifndef EXTRACT_MACROS /* To debug the macros. */ -# undef EXTRACT_NUMBER -# define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) -# endif /* not EXTRACT_MACROS */ +# ifndef EXTRACT_MACROS /* To debug the macros. */ +# undef EXTRACT_NUMBER +# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) +# endif /* not EXTRACT_MACROS */ -#endif /* DEBUG */ +# endif /* DEBUG */ /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. SOURCE must be an lvalue. */ -#define EXTRACT_NUMBER_AND_INCR(destination, source) \ +# define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { \ EXTRACT_NUMBER (destination, source); \ (source) += OFFSET_ADDRESS_SIZE; \ } while (0) -#ifdef DEBUG -static void extract_number_and_incr _RE_ARGS ((int *destination, - US_CHAR_TYPE **source)); +# ifdef DEBUG static void -extract_number_and_incr (destination, source) - int *destination; - US_CHAR_TYPE **source; +PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source) { - extract_number (destination, *source); + PREFIX(extract_number) (destination, *source); *source += OFFSET_ADDRESS_SIZE; } -# ifndef EXTRACT_MACROS -# undef EXTRACT_NUMBER_AND_INCR -# define EXTRACT_NUMBER_AND_INCR(dest, src) \ - extract_number_and_incr (&dest, &src) -# endif /* not EXTRACT_MACROS */ +# ifndef EXTRACT_MACROS +# undef EXTRACT_NUMBER_AND_INCR +# define EXTRACT_NUMBER_AND_INCR(dest, src) \ + PREFIX(extract_number_and_incr) (&dest, &src) +# endif /* not EXTRACT_MACROS */ + +# endif /* DEBUG */ -#endif /* DEBUG */ + /* If DEBUG is defined, Regex prints many voluminous messages about what it is doing (if the variable `debug' is nonzero). If linked with the main program in `iregex.c', you can enter patterns and strings interactively. And if linked with the main program in `main.c' and the other test files, you can run the already-written tests. */ -#ifdef DEBUG +# ifdef DEBUG + +# ifndef DEFINED_ONCE /* We use standard I/O for debugging. */ -# include <stdio.h> +# include <stdio.h> /* It is useful to test things that ``must'' be true when debugging. */ -# include <assert.h> +# include <assert.h> static int debug; -# define DEBUG_STATEMENT(e) e -# define DEBUG_PRINT1(x) if (debug) printf (x) -# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) -# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) -# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) -# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ - if (debug) print_partial_compiled_pattern (s, e) -# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ - if (debug) print_double_string (w, s1, sz1, s2, sz2) +# define DEBUG_STATEMENT(e) e +# define DEBUG_PRINT1(x) if (debug) printf (x) +# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +# endif /* not DEFINED_ONCE */ + +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) PREFIX(print_partial_compiled_pattern) (s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) /* Print the fastmap in human-readable form. */ +# ifndef DEFINED_ONCE void -print_fastmap (fastmap) - char *fastmap; +print_fastmap (char *fastmap) { unsigned was_a_range = 0; unsigned i = 0; @@ -738,20 +742,19 @@ print_fastmap (fastmap) } putchar ('\n'); } +# endif /* not DEFINED_ONCE */ /* Print a compiled pattern string in human-readable form, starting at the START pointer into it and ending just before the pointer END. */ void -print_partial_compiled_pattern (start, end) - US_CHAR_TYPE *start; - US_CHAR_TYPE *end; +PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end) { int mcnt, mcnt2; - US_CHAR_TYPE *p1; - US_CHAR_TYPE *p = start; - US_CHAR_TYPE *pend = end; + UCHAR_T *p1; + UCHAR_T *p = start; + UCHAR_T *pend = end; if (start == NULL) { @@ -762,11 +765,11 @@ print_partial_compiled_pattern (start, end) /* Loop over pattern commands. */ while (p < pend) { -#ifdef _LIBC +# ifdef _LIBC printf ("%td:\t", p - start); -#else +# else printf ("%ld:\t", (long int) (p - start)); -#endif +# endif switch ((re_opcode_t) *p++) { @@ -785,7 +788,7 @@ print_partial_compiled_pattern (start, end) while (--mcnt); break; -#ifdef MBS_SUPPORT +# ifdef MBS_SUPPORT case exactn_bin: mcnt = *p++; printf ("/exactn_bin/%d", mcnt); @@ -795,7 +798,7 @@ print_partial_compiled_pattern (start, end) } while (--mcnt); break; -#endif /* MBS_SUPPORT */ +# endif /* MBS_SUPPORT */ case start_memory: mcnt = *p++; @@ -818,7 +821,7 @@ print_partial_compiled_pattern (start, end) case charset: case charset_not: { -#ifdef MBS_SUPPORT +# ifdef WCHAR int i, length; wchar_t *workp = p; printf ("/charset [%s", @@ -850,19 +853,13 @@ print_partial_compiled_pattern (start, end) { wchar_t range_start = *p++; wchar_t range_end = *p++; - if (MB_CUR_MAX == 1) - printf("%c-%c", (char) range_start, (char) range_end); - else - printf("%C-%C", (wint_t) range_start, (wint_t) range_end); + printf("%C-%C", range_start, range_end); } length = *workp++; /* the length of char */ for (i=0 ; i<length ; i++) - if (MB_CUR_MAX == 1) - putchar (*p++); - else - printf("%C", (wint_t) *p++); + printf("%C", *p++); putchar (']'); -#else +# else register int c, last = -100; register int in_range = 0; @@ -900,7 +897,7 @@ print_partial_compiled_pattern (start, end) putchar (']'); p += 1 + *p; -#endif /* MBS_SUPPORT */ +# endif /* WCHAR */ } break; @@ -913,31 +910,31 @@ print_partial_compiled_pattern (start, end) break; case on_failure_jump: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/on_failure_jump to %td", p + mcnt - start); -#else +# else printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case on_failure_keep_string_jump: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/on_failure_keep_string_jump to %td", p + mcnt - start); -#else +# else printf ("/on_failure_keep_string_jump to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case dummy_failure_jump: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/dummy_failure_jump to %td", p + mcnt - start); -#else +# else printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case push_dummy_failure: @@ -945,70 +942,70 @@ print_partial_compiled_pattern (start, end) break; case maybe_pop_jump: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/maybe_pop_jump to %td", p + mcnt - start); -#else +# else printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case pop_failure_jump: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/pop_failure_jump to %td", p + mcnt - start); -#else +# else printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case jump_past_alt: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/jump_past_alt to %td", p + mcnt - start); -#else +# else printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case jump: - extract_number_and_incr (&mcnt, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt, &p); +# ifdef _LIBC printf ("/jump to %td", p + mcnt - start); -#else +# else printf ("/jump to %ld", (long int) (p + mcnt - start)); -#endif +# endif break; case succeed_n: - extract_number_and_incr (&mcnt, &p); + PREFIX(extract_number_and_incr) (&mcnt, &p); p1 = p + mcnt; - extract_number_and_incr (&mcnt2, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt2, &p); +# ifdef _LIBC printf ("/succeed_n to %td, %d times", p1 - start, mcnt2); -#else +# else printf ("/succeed_n to %ld, %d times", (long int) (p1 - start), mcnt2); -#endif +# endif break; case jump_n: - extract_number_and_incr (&mcnt, &p); + PREFIX(extract_number_and_incr) (&mcnt, &p); p1 = p + mcnt; - extract_number_and_incr (&mcnt2, &p); + PREFIX(extract_number_and_incr) (&mcnt2, &p); printf ("/jump_n to %d, %d times", p1 - start, mcnt2); break; case set_number_at: - extract_number_and_incr (&mcnt, &p); + PREFIX(extract_number_and_incr) (&mcnt, &p); p1 = p + mcnt; - extract_number_and_incr (&mcnt2, &p); -#ifdef _LIBC + PREFIX(extract_number_and_incr) (&mcnt2, &p); +# ifdef _LIBC printf ("/set_number_at location %td to %d", p1 - start, mcnt2); -#else +# else printf ("/set_number_at location %ld to %d", (long int) (p1 - start), mcnt2); -#endif +# endif break; case wordbound: @@ -1027,7 +1024,7 @@ print_partial_compiled_pattern (start, end) printf ("/wordend"); break; -# ifdef emacs +# ifdef emacs case before_dot: printf ("/before_dot"); break; @@ -1051,7 +1048,7 @@ print_partial_compiled_pattern (start, end) mcnt = *p++; printf ("/%d", mcnt); break; -# endif /* emacs */ +# endif /* emacs */ case wordchar: printf ("/wordchar"); @@ -1076,22 +1073,21 @@ print_partial_compiled_pattern (start, end) putchar ('\n'); } -#ifdef _LIBC +# ifdef _LIBC printf ("%td:\tend of pattern.\n", p - start); -#else +# else printf ("%ld:\tend of pattern.\n", (long int) (p - start)); -#endif +# endif } void -print_compiled_pattern (bufp) - struct re_pattern_buffer *bufp; +PREFIX(print_compiled_pattern) (struct re_pattern_buffer *bufp) { - US_CHAR_TYPE *buffer = (US_CHAR_TYPE*) bufp->buffer; + UCHAR_T *buffer = (UCHAR_T*) bufp->buffer; - print_partial_compiled_pattern (buffer, buffer - + bufp->used / sizeof(US_CHAR_TYPE)); + PREFIX(print_partial_compiled_pattern) (buffer, buffer + + bufp->used / sizeof(UCHAR_T)); printf ("%ld bytes used/%ld bytes allocated.\n", bufp->used, bufp->allocated); @@ -1101,11 +1097,11 @@ print_compiled_pattern (bufp) print_fastmap (bufp->fastmap); } -#ifdef _LIBC +# ifdef _LIBC printf ("re_nsub: %Zd\t", bufp->re_nsub); -#else +# else printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); -#endif +# endif printf ("regs_alloc: %d\t", bufp->regs_allocated); printf ("can_be_null: %d\t", bufp->can_be_null); printf ("newline_anchor: %d\n", bufp->newline_anchor); @@ -1118,12 +1114,11 @@ print_compiled_pattern (bufp) void -print_double_string (where, string1, size1, string2, size2) - const CHAR_TYPE *where; - const CHAR_TYPE *string1; - const CHAR_TYPE *string2; - int size1; - int size2; +PREFIX(print_double_string) (const CHAR_T *where, + const CHAR_T *string1, + const CHAR_T *string2, + int size1, + int size2) { int this_char; @@ -1131,6 +1126,8 @@ print_double_string (where, string1, size1, string2, size2) printf ("(null)"); else { + int cnt; + if (FIRST_STRING_P (where)) { for (this_char = where - string1; this_char < size1; this_char++) @@ -1139,34 +1136,48 @@ print_double_string (where, string1, size1, string2, size2) where = string2; } + cnt = 0; for (this_char = where - string2; this_char < size2; this_char++) - PUT_CHAR (string2[this_char]); + { + PUT_CHAR (string2[this_char]); + if (++cnt > 100) + { + fputs ("...", stdout); + break; + } + } } } +# ifndef DEFINED_ONCE void printchar (c) int c; { putc (c, stderr); } +# endif + +# else /* not DEBUG */ -#else /* not DEBUG */ +# ifndef DEFINED_ONCE +# undef assert +# define assert(e) -# undef assert -# define assert(e) +# define DEBUG_STATEMENT(e) +# define DEBUG_PRINT1(x) +# define DEBUG_PRINT2(x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) +# endif /* not DEFINED_ONCE */ +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) -# define DEBUG_STATEMENT(e) -# define DEBUG_PRINT1(x) -# define DEBUG_PRINT2(x1, x2) -# define DEBUG_PRINT3(x1, x2, x3) -# define DEBUG_PRINT4(x1, x2, x3, x4) -# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) -# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) +# endif /* not DEBUG */ -#endif /* not DEBUG */ -#ifdef MBS_SUPPORT + +# ifdef WCHAR /* This convert a multibyte string to a wide character string. And write their correspondances to offset_buffer(see below) and write whether each wchar_t is binary data to is_binary. @@ -1174,83 +1185,75 @@ printchar (c) We assume offset_buffer and is_binary is already allocated enough space. */ -static size_t convert_mbs_to_wcs (CHAR_TYPE *dest, const unsigned char* src, - size_t len, int *offset_buffer, - char *is_binary); static size_t -convert_mbs_to_wcs (dest, src, len, offset_buffer, is_binary) - CHAR_TYPE *dest; - const unsigned char* src; - size_t len; /* the length of multibyte string. */ - - /* It hold correspondances between src(char string) and - dest(wchar_t string) for optimization. - e.g. src = "xxxyzz" - dest = {'X', 'Y', 'Z'} - (each "xxx", "y" and "zz" represent one multibyte character - corresponding to 'X', 'Y' and 'Z'.) - offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} - = {0, 3, 4, 6} - */ - int *offset_buffer; - char *is_binary; +convert_mbs_to_wcs (CHAR_T *dest, + const unsigned char* src, + + /* The length of multibyte string. */ + size_t len, + + /* Correspondences between src(char string) and + dest(wchar_t string) for optimization. E.g.: + src = "xxxyzz" + dest = {'X', 'Y', 'Z'} + (each "xxx", "y" and "zz" represent one + multibyte character corresponding to 'X', + 'Y' and 'Z'.) + offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), + 0+3+1+2("zz")} + = {0, 3, 4, 6} */ + int *offset_buffer, + + char *is_binary) { wchar_t *pdest = dest; const unsigned char *psrc = src; size_t wc_count = 0; - if (MB_CUR_MAX == 1) - { /* We don't need conversion. */ - for ( ; wc_count < len ; ++wc_count) - { - *pdest++ = *psrc++; - is_binary[wc_count] = FALSE; - offset_buffer[wc_count] = wc_count; - } - offset_buffer[wc_count] = wc_count; - } - else + mbstate_t mbs; + int i, consumed; + size_t mb_remain = len; + size_t mb_count = 0; + + /* Initialize the conversion state. */ + memset (&mbs, 0, sizeof (mbstate_t)); + + offset_buffer[0] = 0; + for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, + psrc += consumed) { - /* We need conversion. */ - mbstate_t mbs; - int consumed; - size_t mb_remain = len; - size_t mb_count = 0; - - /* Initialize the conversion state. */ - memset (&mbs, 0, sizeof (mbstate_t)); - - offset_buffer[0] = 0; - for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, - psrc += consumed) - { - consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); + consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); - if (consumed <= 0) - /* failed to convert. maybe src contains binary data. - So we consume 1 byte manualy. */ - { - *pdest = *psrc; - consumed = 1; - is_binary[wc_count] = TRUE; - } - else - is_binary[wc_count] = FALSE; - /* In sjis encoding, we use yen sign as escape character in - place of reverse solidus. So we convert 0x5c(yen sign in - sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse - solidus in UCS2). */ - if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) - *pdest = (wchar_t) *psrc; - - offset_buffer[wc_count + 1] = mb_count += consumed; + if (consumed <= 0) + /* failed to convert. maybe src contains binary data. + So we consume 1 byte manualy. */ + { + *pdest = *psrc; + consumed = 1; + is_binary[wc_count] = TRUE; } + else + is_binary[wc_count] = FALSE; + /* In sjis encoding, we use yen sign as escape character in + place of reverse solidus. So we convert 0x5c(yen sign in + sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse + solidus in UCS2). */ + if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) + *pdest = (wchar_t) *psrc; + + offset_buffer[wc_count + 1] = mb_count += consumed; } + /* Fill remain of the buffer with sentinel. */ + for (i = wc_count + 1 ; i <= len ; i++) + offset_buffer[i] = mb_count + 1; + return wc_count; } -#endif /* MBS_SUPPORT */ +# endif /* WCHAR */ + +#else /* not INSIDE_RECURSION */ /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own @@ -1268,23 +1271,22 @@ reg_syntax_t re_syntax_options; defined in regex.h. We return the old syntax. */ reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; +re_set_syntax (reg_syntax_t syntax) { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; -#ifdef DEBUG +# ifdef DEBUG if (syntax & RE_DEBUG) debug = 1; else if (debug) /* was on but now is not */ debug = 0; -#endif /* DEBUG */ +# endif /* DEBUG */ return ret; } -#ifdef _LIBC +# ifdef _LIBC weak_alias (__re_set_syntax, re_set_syntax) -#endif +# endif /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. @@ -1293,55 +1295,55 @@ weak_alias (__re_set_syntax, re_set_syntax) static const char re_error_msgid[] = { -#define REG_NOERROR_IDX 0 +# define REG_NOERROR_IDX 0 gettext_noop ("Success") /* REG_NOERROR */ "\0" -#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") +# define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") gettext_noop ("No match") /* REG_NOMATCH */ "\0" -#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") +# define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") gettext_noop ("Invalid regular expression") /* REG_BADPAT */ "\0" -#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") +# define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ "\0" -#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") +# define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") gettext_noop ("Invalid character class name") /* REG_ECTYPE */ "\0" -#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") +# define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") gettext_noop ("Trailing backslash") /* REG_EESCAPE */ "\0" -#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") +# define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") gettext_noop ("Invalid back reference") /* REG_ESUBREG */ "\0" -#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") +# define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ "\0" -#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") +# define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ "\0" -#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") +# define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") gettext_noop ("Unmatched \\{") /* REG_EBRACE */ "\0" -#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") +# define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ "\0" -#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") +# define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") gettext_noop ("Invalid range end") /* REG_ERANGE */ "\0" -#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") +# define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") gettext_noop ("Memory exhausted") /* REG_ESPACE */ "\0" -#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") +# define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ "\0" -#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") +# define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") gettext_noop ("Premature end of regular expression") /* REG_EEND */ "\0" -#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") +# define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") gettext_noop ("Regular expression too big") /* REG_ESIZE */ "\0" -#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") +# define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ }; @@ -1366,6 +1368,9 @@ static const size_t re_error_msgid_idx[] = REG_ERPAREN_IDX }; +#endif /* INSIDE_RECURSION */ + +#ifndef DEFINED_ONCE /* Avoiding alloca during matching, to placate r_alloc. */ /* Define MATCH_MAY_ALLOCATE unless we need to make sure that the @@ -1386,24 +1391,25 @@ static const size_t re_error_msgid_idx[] = faith that they will not malloc. */ /* Normally, this is fine. */ -#define MATCH_MAY_ALLOCATE +# define MATCH_MAY_ALLOCATE /* When using GNU C, we are not REALLY using the C alloca, no matter what config.h may say. So don't take precautions for it. */ -#ifdef __GNUC__ -# undef C_ALLOCA -#endif +# ifdef __GNUC__ +# undef C_ALLOCA +# endif /* The match routines may not allocate if (1) they would do it with malloc and (2) it's not safe for them to use malloc. Note that if REL_ALLOC is defined, matching would not use malloc for the failure stack, but we would still use it for the register vectors; so REL_ALLOC should not affect this. */ -#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs -# undef MATCH_MAY_ALLOCATE -#endif - +# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs +# undef MATCH_MAY_ALLOCATE +# endif +#endif /* not DEFINED_ONCE */ +#ifdef INSIDE_RECURSION /* Failure stack declarations and macros; both re_compile_fastmap and re_match_2 use a failure stack. These have to be macros because of REGEX_ALLOCATE_STACK. */ @@ -1412,97 +1418,103 @@ static const size_t re_error_msgid_idx[] = /* Number of failure points for which to initially allocate space when matching. If this number is exceeded, we allocate more space, so it is not a hard limit. */ -#ifndef INIT_FAILURE_ALLOC -# define INIT_FAILURE_ALLOC 5 -#endif +# ifndef INIT_FAILURE_ALLOC +# define INIT_FAILURE_ALLOC 5 +# endif /* Roughly the maximum number of failure points on the stack. Would be exactly that if always used MAX_FAILURE_ITEMS items each time we failed. This is a variable only so users of regex can assign to it; we never change it ourselves. */ -#ifdef INT_IS_16BIT +# ifdef INT_IS_16BIT -# if defined MATCH_MAY_ALLOCATE +# ifndef DEFINED_ONCE +# if defined MATCH_MAY_ALLOCATE /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ long int re_max_failures = 4000; -# else +# else long int re_max_failures = 2000; -# endif +# endif +# endif -union fail_stack_elt +union PREFIX(fail_stack_elt) { - US_CHAR_TYPE *pointer; + UCHAR_T *pointer; long int integer; }; -typedef union fail_stack_elt fail_stack_elt_t; +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); typedef struct { - fail_stack_elt_t *stack; + PREFIX(fail_stack_elt_t) *stack; unsigned long int size; unsigned long int avail; /* Offset of next open position. */ -} fail_stack_type; +} PREFIX(fail_stack_type); -#else /* not INT_IS_16BIT */ +# else /* not INT_IS_16BIT */ -# if defined MATCH_MAY_ALLOCATE +# ifndef DEFINED_ONCE +# if defined MATCH_MAY_ALLOCATE /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ int re_max_failures = 4000; -# else +# else int re_max_failures = 2000; -# endif +# endif +# endif -union fail_stack_elt +union PREFIX(fail_stack_elt) { - US_CHAR_TYPE *pointer; + UCHAR_T *pointer; int integer; }; -typedef union fail_stack_elt fail_stack_elt_t; +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); typedef struct { - fail_stack_elt_t *stack; + PREFIX(fail_stack_elt_t) *stack; unsigned size; unsigned avail; /* Offset of next open position. */ -} fail_stack_type; +} PREFIX(fail_stack_type); -#endif /* INT_IS_16BIT */ +# endif /* INT_IS_16BIT */ -#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) -#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) -#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +# ifndef DEFINED_ONCE +# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +# endif /* Define macros to initialize and free the failure stack. Do `return -2' if the alloc fails. */ -#ifdef MATCH_MAY_ALLOCATE -# define INIT_FAIL_STACK() \ +# ifdef MATCH_MAY_ALLOCATE +# define INIT_FAIL_STACK() \ do { \ - fail_stack.stack = (fail_stack_elt_t *) \ - REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ + REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ \ - if (fail_stack.stack == NULL) \ + if (fail_stack.stack == NULL) \ return -2; \ \ - fail_stack.size = INIT_FAILURE_ALLOC; \ - fail_stack.avail = 0; \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ } while (0) -# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) -#else -# define INIT_FAIL_STACK() \ +# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) +# else +# define INIT_FAIL_STACK() \ do { \ - fail_stack.avail = 0; \ + fail_stack.avail = 0; \ } while (0) -# define RESET_FAIL_STACK() -#endif +# define RESET_FAIL_STACK() +# endif /* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. @@ -1512,13 +1524,13 @@ typedef struct REGEX_REALLOCATE_STACK requires `destination' be declared. */ -#define DOUBLE_FAIL_STACK(fail_stack) \ +# define DOUBLE_FAIL_STACK(fail_stack) \ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ ? 0 \ - : ((fail_stack).stack = (fail_stack_elt_t *) \ + : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ REGEX_REALLOCATE_STACK ((fail_stack).stack, \ - (fail_stack).size * sizeof (fail_stack_elt_t), \ - ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ + ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ \ (fail_stack).stack == NULL \ ? 0 \ @@ -1529,7 +1541,7 @@ typedef struct /* Push pointer POINTER on FAIL_STACK. Return 1 if was able to do so and 0 if ran out of memory allocating space to do so. */ -#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ +# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ ((FAIL_STACK_FULL () \ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ ? 0 \ @@ -1539,35 +1551,35 @@ typedef struct /* Push a pointer value onto the failure stack. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_POINTER(item) \ - fail_stack.stack[fail_stack.avail++].pointer = (US_CHAR_TYPE *) (item) +# define PUSH_FAILURE_POINTER(item) \ + fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) /* This pushes an integer-valued item onto the failure stack. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_INT(item) \ +# define PUSH_FAILURE_INT(item) \ fail_stack.stack[fail_stack.avail++].integer = (item) /* Push a fail_stack_elt_t value onto the failure stack. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_ELT(item) \ +# define PUSH_FAILURE_ELT(item) \ fail_stack.stack[fail_stack.avail++] = (item) /* These three POP... operations complement the three PUSH... operations. All assume that `fail_stack' is nonempty. */ -#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer -#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer -#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] +# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer +# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer +# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] /* Used to omit pushing failure point id's when we're not debugging. */ -#ifdef DEBUG -# define DEBUG_PUSH PUSH_FAILURE_INT -# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () -#else -# define DEBUG_PUSH(item) -# define DEBUG_POP(item_addr) -#endif +# ifdef DEBUG +# define DEBUG_PUSH PUSH_FAILURE_INT +# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () +# else +# define DEBUG_PUSH(item) +# define DEBUG_POP(item_addr) +# endif /* Push the information about the state we will need @@ -1579,7 +1591,7 @@ typedef struct Does `return FAILURE_CODE' if runs out of memory. */ -#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ +# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ do { \ char *destination; \ /* Must be int, so when we don't save any registers, the arithmetic \ @@ -1658,32 +1670,34 @@ typedef struct DEBUG_PUSH (failure_id); \ } while (0) +# ifndef DEFINED_ONCE /* This is the number of items that are pushed and popped on the stack for each register. */ -#define NUM_REG_ITEMS 3 +# define NUM_REG_ITEMS 3 /* Individual items aside from the registers. */ -#ifdef DEBUG -# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ -#else -# define NUM_NONREG_ITEMS 4 -#endif +# ifdef DEBUG +# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +# else +# define NUM_NONREG_ITEMS 4 +# endif /* We push at most this many items on the stack. */ /* We used to use (num_regs - 1), which is the number of registers this regexp will save; but that was changed to 5 to avoid stack overflow for a regexp with lots of parens. */ -#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) +# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) /* We actually push this many items. */ -#define NUM_FAILURE_ITEMS \ +# define NUM_FAILURE_ITEMS \ (((0 \ ? 0 : highest_active_reg - lowest_active_reg + 1) \ * NUM_REG_ITEMS) \ + NUM_NONREG_ITEMS) /* How many items can still be added to the stack without overflowing it. */ -#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) +# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) +# endif /* not DEFINED_ONCE */ /* Pops what PUSH_FAIL_STACK pushes. @@ -1697,11 +1711,11 @@ typedef struct Also assumes the variables `fail_stack' and (if debugging), `bufp', `pend', `string1', `size1', `string2', and `size2'. */ -#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ { \ DEBUG_STATEMENT (unsigned failure_id;) \ active_reg_t this_reg; \ - const US_CHAR_TYPE *string_temp; \ + const UCHAR_T *string_temp; \ \ assert (!FAIL_STACK_EMPTY ()); \ \ @@ -1720,13 +1734,13 @@ typedef struct saved NULL, thus retaining our current position in the string. */ \ string_temp = POP_FAILURE_POINTER (); \ if (string_temp != NULL) \ - str = (const CHAR_TYPE *) string_temp; \ + str = (const CHAR_T *) string_temp; \ \ DEBUG_PRINT2 (" Popping string %p: `", str); \ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ DEBUG_PRINT1 ("'\n"); \ \ - pat = (US_CHAR_TYPE *) POP_FAILURE_POINTER (); \ + pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ \ @@ -1746,10 +1760,10 @@ typedef struct DEBUG_PRINT2 (" info: %p\n", \ reg_info[this_reg].word.pointer); \ \ - regend[this_reg] = (const CHAR_TYPE *) POP_FAILURE_POINTER (); \ + regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ \ - regstart[this_reg] = (const CHAR_TYPE *) POP_FAILURE_POINTER ();\ + regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ } \ else \ @@ -1766,7 +1780,6 @@ typedef struct set_regs_matched_done = 0; \ DEBUG_STATEMENT (nfailure_points_popped++); \ } /* POP_FAILURE_POINT */ - /* Structure for per-register (a.k.a. per-group) information. Other register information, such as the @@ -1784,29 +1797,30 @@ typedef struct typedef union { - fail_stack_elt_t word; + PREFIX(fail_stack_elt_t) word; struct { /* This field is one if this group can match the empty string, zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ -#define MATCH_NULL_UNSET_VALUE 3 +# define MATCH_NULL_UNSET_VALUE 3 unsigned match_null_string_p : 2; unsigned is_active : 1; unsigned matched_something : 1; unsigned ever_matched_something : 1; } bits; -} register_info_type; +} PREFIX(register_info_type); -#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) -#define IS_ACTIVE(R) ((R).bits.is_active) -#define MATCHED_SOMETHING(R) ((R).bits.matched_something) -#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) +# ifndef DEFINED_ONCE +# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +# define IS_ACTIVE(R) ((R).bits.is_active) +# define MATCHED_SOMETHING(R) ((R).bits.matched_something) +# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) /* Call this when have matched a real character; it sets `matched' flags for the subexpressions which we are currently inside. Also records that those subexprs have matched. */ -#define SET_REGS_MATCHED() \ +# define SET_REGS_MATCHED() \ do \ { \ if (!set_regs_matched_done) \ @@ -1822,47 +1836,44 @@ typedef union } \ } \ while (0) +# endif /* not DEFINED_ONCE */ /* Registers are set to a sentinel when they haven't yet matched. */ -static CHAR_TYPE reg_unset_dummy; -#define REG_UNSET_VALUE (®_unset_dummy) -#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) - -/* Subroutine declarations and macros for regex_compile. */ +static CHAR_T PREFIX(reg_unset_dummy); +# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) +# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) -static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size, - reg_syntax_t syntax, - struct re_pattern_buffer *bufp)); -static void store_op1 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, int arg)); -static void store_op2 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, - int arg1, int arg2)); -static void insert_op1 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, - int arg, US_CHAR_TYPE *end)); -static void insert_op2 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, - int arg1, int arg2, US_CHAR_TYPE *end)); -static boolean at_begline_loc_p _RE_ARGS ((const CHAR_TYPE *pattern, - const CHAR_TYPE *p, - reg_syntax_t syntax)); -static boolean at_endline_loc_p _RE_ARGS ((const CHAR_TYPE *p, - const CHAR_TYPE *pend, - reg_syntax_t syntax)); -#ifdef MBS_SUPPORT -static reg_errcode_t compile_range _RE_ARGS ((CHAR_TYPE range_start, - const CHAR_TYPE **p_ptr, - const CHAR_TYPE *pend, - char *translate, - reg_syntax_t syntax, - US_CHAR_TYPE *b, - CHAR_TYPE *char_set)); -static void insert_space _RE_ARGS ((int num, CHAR_TYPE *loc, CHAR_TYPE *end)); -#else -static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, - const CHAR_TYPE **p_ptr, - const CHAR_TYPE *pend, - char *translate, - reg_syntax_t syntax, - US_CHAR_TYPE *b)); -#endif /* MBS_SUPPORT */ +/* Subroutine declarations and macros for regex_compile. */ +static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg); +static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, + int arg1, int arg2); +static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, + int arg, UCHAR_T *end); +static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, + int arg1, int arg2, UCHAR_T *end); +static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern, + const CHAR_T *p, + reg_syntax_t syntax); +static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p, + const CHAR_T *pend, + reg_syntax_t syntax); +# ifdef WCHAR +static reg_errcode_t wcs_compile_range (CHAR_T range_start, + const CHAR_T **p_ptr, + const CHAR_T *pend, + char *translate, + reg_syntax_t syntax, + UCHAR_T *b, + CHAR_T *char_set); +static void insert_space (int num, CHAR_T *loc, CHAR_T *end); +# else /* BYTE */ +static reg_errcode_t byte_compile_range (unsigned int range_start, + const char **p_ptr, + const char *pend, + char *translate, + reg_syntax_t syntax, + unsigned char *b); +# endif /* WCHAR */ /* Fetch the next character in the uncompiled pattern---translating it if necessary. Also cast from a signed character in the constant @@ -1871,31 +1882,31 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, /* ifdef MBS_SUPPORT, we translate only if character <= 0xff, because it is impossible to allocate 4GB array for some encodings which have 4 byte character_set like UCS4. */ -#ifndef PATFETCH -# ifdef MBS_SUPPORT -# define PATFETCH(c) \ +# ifndef PATFETCH +# ifdef WCHAR +# define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ - c = (US_CHAR_TYPE) *p++; \ - if (translate && (c <= 0xff)) c = (US_CHAR_TYPE) translate[c]; \ + c = (UCHAR_T) *p++; \ + if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ } while (0) -# else -# define PATFETCH(c) \ +# else /* BYTE */ +# define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ if (translate) c = (unsigned char) translate[c]; \ } while (0) -# endif /* MBS_SUPPORT */ -#endif +# endif /* WCHAR */ +# endif /* Fetch the next character in the uncompiled pattern, with no translation. */ -#define PATFETCH_RAW(c) \ +# define PATFETCH_RAW(c) \ do {if (p == pend) return REG_EEND; \ - c = (US_CHAR_TYPE) *p++; \ + c = (UCHAR_T) *p++; \ } while (0) /* Go backwards one character in the pattern. */ -#define PATUNFETCH p-- +# define PATUNFETCH p-- /* If `translate' is non-null, return translate[D], else just D. We @@ -1905,80 +1916,80 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, /* ifdef MBS_SUPPORT, we translate only if character <= 0xff, because it is impossible to allocate 4GB array for some encodings which have 4 byte character_set like UCS4. */ -#ifndef TRANSLATE -# ifdef MBS_SUPPORT -# define TRANSLATE(d) \ - ((translate && ((US_CHAR_TYPE) (d)) <= 0xff) \ + +# ifndef TRANSLATE +# ifdef WCHAR +# define TRANSLATE(d) \ + ((translate && ((UCHAR_T) (d)) <= 0xff) \ ? (char) translate[(unsigned char) (d)] : (d)) -#else -# define TRANSLATE(d) \ +# else /* BYTE */ +# define TRANSLATE(d) \ (translate ? (char) translate[(unsigned char) (d)] : (d)) -# endif /* MBS_SUPPORT */ -#endif +# endif /* WCHAR */ +# endif /* Macros for outputting the compiled pattern into `buffer'. */ /* If the buffer isn't allocated when it comes in, use this. */ -#define INIT_BUF_SIZE (32 * sizeof(US_CHAR_TYPE)) +# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) /* Make sure we have at least N more bytes of space in buffer. */ -#ifdef MBS_SUPPORT -# define GET_BUFFER_SPACE(n) \ +# ifdef WCHAR +# define GET_BUFFER_SPACE(n) \ while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ - + (n)*sizeof(CHAR_TYPE)) > bufp->allocated) \ + + (n)*sizeof(CHAR_T)) > bufp->allocated) \ EXTEND_BUFFER () -#else -# define GET_BUFFER_SPACE(n) \ +# else /* BYTE */ +# define GET_BUFFER_SPACE(n) \ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ EXTEND_BUFFER () -#endif /* MBS_SUPPORT */ +# endif /* WCHAR */ /* Make sure we have one more byte of buffer space and then add C to it. */ -#define BUF_PUSH(c) \ +# define BUF_PUSH(c) \ do { \ GET_BUFFER_SPACE (1); \ - *b++ = (US_CHAR_TYPE) (c); \ + *b++ = (UCHAR_T) (c); \ } while (0) /* Ensure we have two more bytes of buffer space and then append C1 and C2. */ -#define BUF_PUSH_2(c1, c2) \ +# define BUF_PUSH_2(c1, c2) \ do { \ GET_BUFFER_SPACE (2); \ - *b++ = (US_CHAR_TYPE) (c1); \ - *b++ = (US_CHAR_TYPE) (c2); \ + *b++ = (UCHAR_T) (c1); \ + *b++ = (UCHAR_T) (c2); \ } while (0) /* As with BUF_PUSH_2, except for three bytes. */ -#define BUF_PUSH_3(c1, c2, c3) \ +# define BUF_PUSH_3(c1, c2, c3) \ do { \ GET_BUFFER_SPACE (3); \ - *b++ = (US_CHAR_TYPE) (c1); \ - *b++ = (US_CHAR_TYPE) (c2); \ - *b++ = (US_CHAR_TYPE) (c3); \ + *b++ = (UCHAR_T) (c1); \ + *b++ = (UCHAR_T) (c2); \ + *b++ = (UCHAR_T) (c3); \ } while (0) /* Store a jump with opcode OP at LOC to location TO. We store a relative address offset by the three bytes the jump itself occupies. */ -#define STORE_JUMP(op, loc, to) \ - store_op1 (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) +# define STORE_JUMP(op, loc, to) \ + PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) /* Likewise, for a two-argument jump. */ -#define STORE_JUMP2(op, loc, to, arg) \ - store_op2 (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) +# define STORE_JUMP2(op, loc, to, arg) \ + PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) /* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ -#define INSERT_JUMP(op, loc, to) \ - insert_op1 (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) +# define INSERT_JUMP(op, loc, to) \ + PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) /* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ -#define INSERT_JUMP2(op, loc, to, arg) \ - insert_op2 (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ +# define INSERT_JUMP2(op, loc, to, arg) \ + PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ arg, b) - /* This is not an arbitrary limit: the arguments which represent offsets into the pattern are two bytes long. So if 2^16 bytes turns out to be too small, many things would have to change. */ @@ -1987,26 +1998,27 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up reallocating to 0 bytes. Such thing is not going to work too well. You have been warned!! */ -#if defined _MSC_VER && !defined WIN32 +# ifndef DEFINED_ONCE +# if defined _MSC_VER && !defined WIN32 /* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. The REALLOC define eliminates a flurry of conversion warnings, but is not required. */ -# define MAX_BUF_SIZE 65500L -# define REALLOC(p,s) realloc ((p), (size_t) (s)) -#else -# define MAX_BUF_SIZE (1L << 16) -# define REALLOC(p,s) realloc ((p), (s)) -#endif +# define MAX_BUF_SIZE 65500L +# define REALLOC(p,s) realloc ((p), (size_t) (s)) +# else +# define MAX_BUF_SIZE (1L << 16) +# define REALLOC(p,s) realloc ((p), (s)) +# endif /* Extend the buffer by twice its current size via realloc and reset the pointers that pointed into the old block to point to the correct places in the new one. If extending the buffer results in it being larger than MAX_BUF_SIZE, then flag memory exhausted. */ -#if __BOUNDED_POINTERS__ -# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) -# define MOVE_BUFFER_POINTER(P) \ +# if __BOUNDED_POINTERS__ +# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) +# define MOVE_BUFFER_POINTER(P) \ (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) -# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ +# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ else \ { \ SET_HIGH_BOUND (b); \ @@ -2018,27 +2030,28 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, if (pending_exact) \ SET_HIGH_BOUND (pending_exact); \ } -#else -# define MOVE_BUFFER_POINTER(P) (P) += incr -# define ELSE_EXTEND_BUFFER_HIGH_BOUND -#endif +# else +# define MOVE_BUFFER_POINTER(P) (P) += incr +# define ELSE_EXTEND_BUFFER_HIGH_BOUND +# endif +# endif /* not DEFINED_ONCE */ -#ifdef MBS_SUPPORT -# define EXTEND_BUFFER() \ +# ifdef WCHAR +# define EXTEND_BUFFER() \ do { \ - US_CHAR_TYPE *old_buffer = COMPILED_BUFFER_VAR; \ + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ int wchar_count; \ - if (bufp->allocated + sizeof(US_CHAR_TYPE) > MAX_BUF_SIZE) \ + if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ if (bufp->allocated > MAX_BUF_SIZE) \ bufp->allocated = MAX_BUF_SIZE; \ /* How many characters the new buffer can have? */ \ - wchar_count = bufp->allocated / sizeof(US_CHAR_TYPE); \ + wchar_count = bufp->allocated / sizeof(UCHAR_T); \ if (wchar_count == 0) wchar_count = 1; \ - /* Truncate the buffer to CHAR_TYPE align. */ \ - bufp->allocated = wchar_count * sizeof(US_CHAR_TYPE); \ - RETALLOC (COMPILED_BUFFER_VAR, wchar_count, US_CHAR_TYPE); \ + /* Truncate the buffer to CHAR_T align. */ \ + bufp->allocated = wchar_count * sizeof(UCHAR_T); \ + RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ if (COMPILED_BUFFER_VAR == NULL) \ return REG_ESPACE; \ @@ -2057,17 +2070,16 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, } \ ELSE_EXTEND_BUFFER_HIGH_BOUND \ } while (0) -#else -# define EXTEND_BUFFER() \ +# else /* BYTE */ +# define EXTEND_BUFFER() \ do { \ - US_CHAR_TYPE *old_buffer = COMPILED_BUFFER_VAR; \ + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ if (bufp->allocated == MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ if (bufp->allocated > MAX_BUF_SIZE) \ bufp->allocated = MAX_BUF_SIZE; \ - bufp->buffer = (US_CHAR_TYPE *) REALLOC (COMPILED_BUFFER_VAR, \ - bufp->allocated); \ + bufp->buffer = REALLOC (COMPILED_BUFFER_VAR, bufp->allocated); \ if (COMPILED_BUFFER_VAR == NULL) \ return REG_ESPACE; \ /* If the buffer moved, move all the pointers into it. */ \ @@ -2085,12 +2097,13 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, } \ ELSE_EXTEND_BUFFER_HIGH_BOUND \ } while (0) -#endif /* MBS_SUPPORT */ +# endif /* WCHAR */ +# ifndef DEFINED_ONCE /* Since we have one byte reserved for the register number argument to {start,stop}_memory, the maximum number of groups we can report things about is what fits in that byte. */ -#define MAX_REGNUM 255 +# define MAX_REGNUM 255 /* But patterns can have more than `MAX_REGNUM' registers. We just ignore the excess. */ @@ -2122,28 +2135,30 @@ typedef struct } compile_stack_type; -#define INIT_COMPILE_STACK_SIZE 32 +# define INIT_COMPILE_STACK_SIZE 32 -#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) -#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) +# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) /* The next available element. */ -#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) +# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) +# endif /* not DEFINED_ONCE */ /* Set the bit for character C in a list. */ -#define SET_LIST_BIT(c) \ +# ifndef DEFINED_ONCE +# define SET_LIST_BIT(c) \ (b[((unsigned char) (c)) / BYTEWIDTH] \ |= 1 << (((unsigned char) c) % BYTEWIDTH)) - +# endif /* DEFINED_ONCE */ /* Get the next unsigned number in the uncompiled pattern. */ -#define GET_UNSIGNED_NUMBER(num) \ +# define GET_UNSIGNED_NUMBER(num) \ { \ while (p != pend) \ { \ PATFETCH (c); \ - if (! ('0' <= c && c <= '9')) \ + if (c < '0' || c > '9') \ break; \ if (num <= RE_DUP_MAX) \ { \ @@ -2154,35 +2169,37 @@ typedef struct } \ } -#if defined _LIBC || WIDE_CHAR_SUPPORT +# ifndef DEFINED_ONCE +# if defined _LIBC || WIDE_CHAR_SUPPORT /* The GNU C library provides support for user-defined character classes and the functions from ISO C amendement 1. */ -# ifdef CHARCLASS_NAME_MAX -# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX -# else +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else /* This shouldn't happen but some implementation might still have this problem. Use a reasonable default value. */ -# define CHAR_CLASS_MAX_LENGTH 256 -# endif +# define CHAR_CLASS_MAX_LENGTH 256 +# endif -# ifdef _LIBC -# define IS_CHAR_CLASS(string) __wctype (string) -# else -# define IS_CHAR_CLASS(string) wctype (string) -# endif -#else -# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ -# define IS_CHAR_CLASS(string) \ +# define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) -#endif +# endif +# endif /* DEFINED_ONCE */ -#ifndef MATCH_MAY_ALLOCATE +# ifndef MATCH_MAY_ALLOCATE /* If we cannot allocate large objects within re_match_2_internal, we make the fail stack and register vectors global. @@ -2191,26 +2208,28 @@ typedef struct The register vectors, we adjust in size each time we compile a regexp, according to the number of registers it needs. */ -static fail_stack_type fail_stack; +static PREFIX(fail_stack_type) fail_stack; /* Size with which the following vectors are currently allocated. That is so we can make them bigger as needed, but never make them smaller. */ +# ifdef DEFINED_ONCE static int regs_allocated_size; static const char ** regstart, ** regend; static const char ** old_regstart, ** old_regend; static const char **best_regstart, **best_regend; -static register_info_type *reg_info; static const char **reg_dummy; -static register_info_type *reg_info_dummy; +# endif /* DEFINED_ONCE */ + +static PREFIX(register_info_type) *PREFIX(reg_info); +static PREFIX(register_info_type) *PREFIX(reg_info_dummy); /* Make the register vectors big enough for NUM_REGS registers, but don't make them smaller. */ -static -regex_grow_registers (num_regs) - int num_regs; +static void +PREFIX(regex_grow_registers) (int num_regs) { if (num_regs > regs_allocated_size) { @@ -2220,19 +2239,21 @@ regex_grow_registers (num_regs) RETALLOC_IF (old_regend, num_regs, const char *); RETALLOC_IF (best_regstart, num_regs, const char *); RETALLOC_IF (best_regend, num_regs, const char *); - RETALLOC_IF (reg_info, num_regs, register_info_type); + RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); RETALLOC_IF (reg_dummy, num_regs, const char *); - RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); + RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); regs_allocated_size = num_regs; } } -#endif /* not MATCH_MAY_ALLOCATE */ +# endif /* not MATCH_MAY_ALLOCATE */ -static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type - compile_stack, - regnum_t regnum)); +# ifndef DEFINED_ONCE +static boolean group_in_compile_stack (compile_stack_type + compile_stack, + regnum_t regnum); +# endif /* not DEFINED_ONCE */ /* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. Returns one of error codes defined in `regex.h', or zero for success. @@ -2253,61 +2274,54 @@ static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type examined nor set. */ /* Return, freeing storage we allocated. */ -#ifdef MBS_SUPPORT -# define FREE_STACK_RETURN(value) \ +# ifdef WCHAR +# define FREE_STACK_RETURN(value) \ return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) -#else -# define FREE_STACK_RETURN(value) \ +# else +# define FREE_STACK_RETURN(value) \ return (free (compile_stack.stack), value) -#endif /* MBS_SUPPORT */ +# endif /* WCHAR */ static reg_errcode_t -#ifdef MBS_SUPPORT -regex_compile (cpattern, csize, syntax, bufp) - const char *cpattern; - size_t csize; -#else -regex_compile (pattern, size, syntax, bufp) - const char *pattern; - size_t size; -#endif /* MBS_SUPPORT */ - reg_syntax_t syntax; - struct re_pattern_buffer *bufp; +PREFIX(regex_compile) (const char *ARG_PREFIX(pattern), + size_t ARG_PREFIX(size), + reg_syntax_t syntax, + struct re_pattern_buffer *bufp) { /* We fetch characters from PATTERN here. Even though PATTERN is `char *' (i.e., signed), we declare these variables as unsigned, so they can be reliably used as array indices. */ - register US_CHAR_TYPE c, c1; + register UCHAR_T c, c1; -#ifdef MBS_SUPPORT +#ifdef WCHAR /* A temporary space to keep wchar_t pattern and compiled pattern. */ - CHAR_TYPE *pattern, *COMPILED_BUFFER_VAR; + CHAR_T *pattern, *COMPILED_BUFFER_VAR; size_t size; - /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ + /* offset buffer for optimization. See convert_mbs_to_wc. */ int *mbs_offset = NULL; /* It hold whether each wchar_t is binary data or not. */ char *is_binary = NULL; /* A flag whether exactn is handling binary data or not. */ char is_exactn_bin = FALSE; -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* A random temporary spot in PATTERN. */ - const CHAR_TYPE *p1; + const CHAR_T *p1; /* Points to the end of the buffer, where we should append. */ - register US_CHAR_TYPE *b; + register UCHAR_T *b; /* Keeps track of unclosed groups. */ compile_stack_type compile_stack; /* Points to the current (ending) position in the pattern. */ -#ifdef MBS_SUPPORT - const CHAR_TYPE *p; - const CHAR_TYPE *pend; -#else - const CHAR_TYPE *p = pattern; - const CHAR_TYPE *pend = pattern + size; -#endif /* MBS_SUPPORT */ +#ifdef WCHAR + const CHAR_T *p; + const CHAR_T *pend; +#else /* BYTE */ + const CHAR_T *p = pattern; + const CHAR_T *pend = pattern + size; +#endif /* WCHAR */ /* How to translate the characters in the pattern. */ RE_TRANSLATE_TYPE translate = bufp->translate; @@ -2316,46 +2330,46 @@ regex_compile (pattern, size, syntax, bufp) command. This makes it possible to tell if a new exact-match character can be added to that command or if the character requires a new `exactn' command. */ - US_CHAR_TYPE *pending_exact = 0; + UCHAR_T *pending_exact = 0; /* Address of start of the most recently finished expression. This tells, e.g., postfix * where to find the start of its operand. Reset at the beginning of groups and alternatives. */ - US_CHAR_TYPE *laststart = 0; + UCHAR_T *laststart = 0; /* Address of beginning of regexp, or inside of last group. */ - US_CHAR_TYPE *begalt; + UCHAR_T *begalt; /* Address of the place where a forward jump should go to the end of the containing expression. Each alternative of an `or' -- except the last -- ends with a forward jump of this sort. */ - US_CHAR_TYPE *fixup_alt_jump = 0; + UCHAR_T *fixup_alt_jump = 0; /* Counts open-groups as they are encountered. Remembered for the matching close-group on the compile stack, so the same register number is put in the stop_memory as the start_memory. */ regnum_t regnum = 0; -#ifdef MBS_SUPPORT +#ifdef WCHAR /* Initialize the wchar_t PATTERN and offset_buffer. */ - p = pend = pattern = TALLOC(csize + 1, CHAR_TYPE); - p[csize] = L'\0'; /* sentinel */ + p = pend = pattern = TALLOC(csize + 1, CHAR_T); mbs_offset = TALLOC(csize + 1, int); is_binary = TALLOC(csize + 1, char); if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) { - if (pattern) free(pattern); - if (mbs_offset) free(mbs_offset); - if (is_binary) free(is_binary); + free(pattern); + free(mbs_offset); + free(is_binary); return REG_ESPACE; } + pattern[csize] = L'\0'; /* sentinel */ size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); pend = p + size; if (size < 0) { - if (pattern) free(pattern); - if (mbs_offset) free(mbs_offset); - if (is_binary) free(is_binary); + free(pattern); + free(mbs_offset); + free(is_binary); return REG_BADPAT; } #endif @@ -2376,10 +2390,10 @@ regex_compile (pattern, size, syntax, bufp) compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); if (compile_stack.stack == NULL) { -#ifdef MBS_SUPPORT - if (pattern) free(pattern); - if (mbs_offset) free(mbs_offset); - if (is_binary) free(is_binary); +#ifdef WCHAR + free(pattern); + free(mbs_offset); + free(is_binary); #endif return REG_ESPACE; } @@ -2411,31 +2425,31 @@ regex_compile (pattern, size, syntax, bufp) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR /* Free bufp->buffer and allocate an array for wchar_t pattern buffer. */ free(bufp->buffer); - COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(US_CHAR_TYPE), - US_CHAR_TYPE); + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), + UCHAR_T); #else - RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, US_CHAR_TYPE); -#endif /* MBS_SUPPORT */ + RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); +#endif /* WCHAR */ } else { /* Caller did not allocate a buffer. Do it for them. */ - COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(US_CHAR_TYPE), - US_CHAR_TYPE); + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), + UCHAR_T); } if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); -#ifdef MBS_SUPPORT +#ifdef WCHAR bufp->buffer = (char*)COMPILED_BUFFER_VAR; -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ bufp->allocated = INIT_BUF_SIZE; } -#ifdef MBS_SUPPORT +#ifdef WCHAR else - COMPILED_BUFFER_VAR = (US_CHAR_TYPE*) bufp->buffer; + COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; #endif begalt = b = COMPILED_BUFFER_VAR; @@ -2454,7 +2468,7 @@ regex_compile (pattern, size, syntax, bufp) /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's come before. */ - || at_begline_loc_p (pattern, p, syntax)) + || PREFIX(at_begline_loc_p) (pattern, p, syntax)) BUF_PUSH (begline); else goto normal_char; @@ -2469,7 +2483,7 @@ regex_compile (pattern, size, syntax, bufp) /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's next. */ - || at_endline_loc_p (p, pend, syntax)) + || PREFIX(at_endline_loc_p) (p, pend, syntax)) BUF_PUSH (endline); else goto normal_char; @@ -2589,7 +2603,7 @@ regex_compile (pattern, size, syntax, bufp) /* On failure, jump from laststart to b + 3, which will be the end of the buffer after this jump is inserted. */ - /* ifdef MBS_SUPPORT, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of 'b + 3'. */ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump @@ -2623,14 +2637,14 @@ regex_compile (pattern, size, syntax, bufp) case '[': { boolean had_char_class = false; -#ifdef MBS_SUPPORT - CHAR_TYPE range_start = 0xffffffff; +#ifdef WCHAR + CHAR_T range_start = 0xffffffff; #else unsigned int range_start = 0xffffffff; #endif if (p == pend) FREE_STACK_RETURN (REG_EBRACK); -#ifdef MBS_SUPPORT +#ifdef WCHAR /* We assume a charset(_not) structure as a wchar_t array. charset[0] = (re_opcode_t) charset(_not) charset[1] = l (= length of char_classes) @@ -2751,7 +2765,7 @@ regex_compile (pattern, size, syntax, bufp) GET_BUFFER_SPACE (2); /* Update the pointer to indicate end of buffer. */ b += 2; - ret = compile_range (range_start, &p, pend, translate, + ret = wcs_compile_range (range_start, &p, pend, translate, syntax, b, laststart); if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); range_start = 0xffffffff; @@ -2766,7 +2780,7 @@ regex_compile (pattern, size, syntax, bufp) GET_BUFFER_SPACE (2); /* Update the pointer to indicate end of buffer. */ b += 2; - ret = compile_range (c, &p, pend, translate, syntax, b, + ret = wcs_compile_range (c, &p, pend, translate, syntax, b, laststart); if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); range_start = 0xffffffff; @@ -2850,8 +2864,8 @@ regex_compile (pattern, size, syntax, bufp) else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' || *p == '.')) { - CHAR_TYPE str[128]; /* Should be large enough. */ - CHAR_TYPE delim = *p; /* '=' or '.' */ + CHAR_T str[128]; /* Should be large enough. */ + CHAR_T delim = *p; /* '=' or '.' */ # ifdef _LIBC uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); @@ -2975,7 +2989,7 @@ regex_compile (pattern, size, syntax, bufp) /* First compare the hashing value. */ if (symb_table[2 * elem] == hash && c1 == extra[symb_table[2 * elem + 1]] - && memcmp (str, + && memcmp (char_str, &extra[symb_table[2 * elem + 1] + 1], c1) == 0) { @@ -2995,7 +3009,7 @@ regex_compile (pattern, size, syntax, bufp) in the table. */ idx += 1 + extra[idx]; /* Adjust for the alignment. */ - idx = (idx + 3) & ~4; + idx = (idx + 3) & ~3; str[0] = (wchar_t) idx + 4; } @@ -3092,7 +3106,7 @@ regex_compile (pattern, size, syntax, bufp) } } -#else /* not MBS_SUPPORT */ +#else /* BYTE */ /* Ensure that we have enough space to push a charset: the opcode, the length count, and the bitset; 34 bytes in all. */ GET_BUFFER_SPACE (34); @@ -3158,8 +3172,8 @@ regex_compile (pattern, size, syntax, bufp) && *p != ']') { reg_errcode_t ret - = compile_range (range_start, &p, pend, translate, - syntax, b); + = byte_compile_range (range_start, &p, pend, translate, + syntax, b); if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); range_start = 0xffffffff; } @@ -3171,7 +3185,7 @@ regex_compile (pattern, size, syntax, bufp) /* Move past the `-'. */ PATFETCH (c1); - ret = compile_range (c, &p, pend, translate, syntax, b); + ret = byte_compile_range (c, &p, pend, translate, syntax, b); if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); range_start = 0xffffffff; } @@ -3225,13 +3239,8 @@ regex_compile (pattern, size, syntax, bufp) for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) { -# ifdef _LIBC - if (__iswctype (__btowc (ch), wt)) - SET_LIST_BIT (ch); -# else if (iswctype (btowc (ch), wt)) SET_LIST_BIT (ch); -# endif if (translate && (is_upper || is_lower) && (ISUPPER (ch) || ISLOWER (ch))) @@ -3590,7 +3599,7 @@ regex_compile (pattern, size, syntax, bufp) while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) b[-1]--; b += b[-1]; -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ } break; @@ -3749,7 +3758,7 @@ regex_compile (pattern, size, syntax, bufp) groups were inside this one. */ if (this_group_regnum <= MAX_REGNUM) { - US_CHAR_TYPE *inner_group_loc + UCHAR_T *inner_group_loc = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; *inner_group_loc = regnum - this_group_regnum; @@ -3823,7 +3832,7 @@ regex_compile (pattern, size, syntax, bufp) /* Place in the uncompiled pattern (i.e., just after the '{') to go back to if the interval is invalid. */ - const CHAR_TYPE *beg_interval = p; + const CHAR_T *beg_interval = p; if (p == pend) goto invalid_interval; @@ -3873,7 +3882,7 @@ regex_compile (pattern, size, syntax, bufp) /* If the upper bound is zero, don't want to succeed at all; jump from `laststart' to `b + 3', which will be the end of the buffer after we insert the jump. */ - /* ifdef MBS_SUPPORT, 'b + 1 + OFFSET_ADDRESS_SIZE' + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of 'b + 3'. */ if (upper_bound == 0) { @@ -3915,10 +3924,10 @@ regex_compile (pattern, size, syntax, bufp) before the `succeed_n'. The `5' is the last two bytes of this `set_number_at', plus 3 bytes of the following `succeed_n'. */ - /* ifdef MBS_SUPPORT, The '1+2*OFFSET_ADDRESS_SIZE' + /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' of the following `succeed_n'. */ - insert_op2 (set_number_at, laststart, 1 + PREFIX(insert_op2) (set_number_at, laststart, 1 + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); b += 1 + 2 * OFFSET_ADDRESS_SIZE; @@ -3949,8 +3958,9 @@ regex_compile (pattern, size, syntax, bufp) We insert this at the beginning of the loop so that if we fail during matching, we'll reinitialize the bounds. */ - insert_op2 (set_number_at, laststart, b - laststart, - upper_bound - 1, b); + PREFIX(insert_op2) (set_number_at, laststart, + b - laststart, + upper_bound - 1, b); b += 1 + 2 * OFFSET_ADDRESS_SIZE; } } @@ -4085,11 +4095,11 @@ regex_compile (pattern, size, syntax, bufp) normal_char: /* If no exactn currently being built. */ if (!pending_exact -#ifdef MBS_SUPPORT +#ifdef WCHAR /* If last exactn handle binary(or character) and new exactn handle character(or binary). */ || is_exactn_bin != is_binary[p - 1 - pattern] -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* If last exactn not at current position. */ || pending_exact + *pending_exact + 1 != b @@ -4111,7 +4121,7 @@ regex_compile (pattern, size, syntax, bufp) laststart = b; -#ifdef MBS_SUPPORT +#ifdef WCHAR /* Is this exactn binary data or character? */ is_exactn_bin = is_binary[p - 1 - pattern]; if (is_exactn_bin) @@ -4120,7 +4130,7 @@ regex_compile (pattern, size, syntax, bufp) BUF_PUSH_2 (exactn, 0); #else BUF_PUSH_2 (exactn, 0); -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ pending_exact = b - 1; } @@ -4144,7 +4154,7 @@ regex_compile (pattern, size, syntax, bufp) if (syntax & RE_NO_POSIX_BACKTRACKING) BUF_PUSH (succeed); -#ifdef MBS_SUPPORT +#ifdef WCHAR free (pattern); free (mbs_offset); free (is_binary); @@ -4152,7 +4162,7 @@ regex_compile (pattern, size, syntax, bufp) free (compile_stack.stack); /* We have succeeded; set the length of the buffer. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; #else bufp->used = b - bufp->buffer; @@ -4162,7 +4172,7 @@ regex_compile (pattern, size, syntax, bufp) if (debug) { DEBUG_PRINT1 ("\nCompiled pattern: \n"); - print_compiled_pattern (bufp); + PREFIX(print_compiled_pattern) (bufp); } #endif /* DEBUG */ @@ -4183,59 +4193,51 @@ regex_compile (pattern, size, syntax, bufp) # ifdef emacs if (! fail_stack.stack) fail_stack.stack - = (fail_stack_elt_t *) xmalloc (fail_stack.size - * sizeof (fail_stack_elt_t)); + = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t))); else fail_stack.stack - = (fail_stack_elt_t *) xrealloc (fail_stack.stack, - (fail_stack.size - * sizeof (fail_stack_elt_t))); + = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, + (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t)))); # else /* not emacs */ if (! fail_stack.stack) fail_stack.stack - = (fail_stack_elt_t *) malloc (fail_stack.size - * sizeof (fail_stack_elt_t)); + = malloc (fail_stack.size * sizeof (PREFIX(fail_stack_elt_t))); else fail_stack.stack - = (fail_stack_elt_t *) realloc (fail_stack.stack, - (fail_stack.size - * sizeof (fail_stack_elt_t))); + = realloc (fail_stack.stack, + fail_stack.size * sizeof (PREFIX(fail_stack_elt_t))); # endif /* not emacs */ } - regex_grow_registers (num_regs); + PREFIX(regex_grow_registers) (num_regs); } #endif /* not MATCH_MAY_ALLOCATE */ return REG_NOERROR; } /* regex_compile */ - + /* Subroutines for `regex_compile'. */ /* Store OP at LOC followed by two-byte integer parameter ARG. */ -/* ifdef MBS_SUPPORT, integer parameter is 1 wchar_t. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ static void -store_op1 (op, loc, arg) - re_opcode_t op; - US_CHAR_TYPE *loc; - int arg; +PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg) { - *loc = (US_CHAR_TYPE) op; + *loc = (UCHAR_T) op; STORE_NUMBER (loc + 1, arg); } /* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ -/* ifdef MBS_SUPPORT, integer parameter is 1 wchar_t. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ static void -store_op2 (op, loc, arg1, arg2) - re_opcode_t op; - US_CHAR_TYPE *loc; - int arg1, arg2; +PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2) { - *loc = (US_CHAR_TYPE) op; + *loc = (UCHAR_T) op; STORE_NUMBER (loc + 1, arg1); STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); } @@ -4243,42 +4245,35 @@ store_op2 (op, loc, arg1, arg2) /* Copy the bytes from LOC to END to open up three bytes of space at LOC for OP followed by two-byte integer parameter ARG. */ -/* ifdef MBS_SUPPORT, integer parameter is 1 wchar_t. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ static void -insert_op1 (op, loc, arg, end) - re_opcode_t op; - US_CHAR_TYPE *loc; - int arg; - US_CHAR_TYPE *end; +PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end) { - register US_CHAR_TYPE *pfrom = end; - register US_CHAR_TYPE *pto = end + 1 + OFFSET_ADDRESS_SIZE; + register UCHAR_T *pfrom = end; + register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; while (pfrom != loc) *--pto = *--pfrom; - store_op1 (op, loc, arg); + PREFIX(store_op1) (op, loc, arg); } /* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ -/* ifdef MBS_SUPPORT, integer parameter is 1 wchar_t. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ static void -insert_op2 (op, loc, arg1, arg2, end) - re_opcode_t op; - US_CHAR_TYPE *loc; - int arg1, arg2; - US_CHAR_TYPE *end; +PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2, + UCHAR_T *end) { - register US_CHAR_TYPE *pfrom = end; - register US_CHAR_TYPE *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; + register UCHAR_T *pfrom = end; + register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; while (pfrom != loc) *--pto = *--pfrom; - store_op2 (op, loc, arg1, arg2); + PREFIX(store_op2) (op, loc, arg1, arg2); } @@ -4287,11 +4282,10 @@ insert_op2 (op, loc, arg1, arg2, end) least one character before the ^. */ static boolean -at_begline_loc_p (pattern, p, syntax) - const CHAR_TYPE *pattern, *p; - reg_syntax_t syntax; +PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p, + reg_syntax_t syntax) { - const CHAR_TYPE *prev = p - 2; + const CHAR_T *prev = p - 2; boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; return @@ -4306,13 +4300,12 @@ at_begline_loc_p (pattern, p, syntax) at least one character after the $, i.e., `P < PEND'. */ static boolean -at_endline_loc_p (p, pend, syntax) - const CHAR_TYPE *p, *pend; - reg_syntax_t syntax; +PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend, + reg_syntax_t syntax) { - const CHAR_TYPE *next = p; + const CHAR_T *next = p; boolean next_backslash = *next == '\\'; - const CHAR_TYPE *next_next = p + 1 < pend ? p + 1 : 0; + const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; return /* Before a subexpression? */ @@ -4323,14 +4316,14 @@ at_endline_loc_p (p, pend, syntax) : next_backslash && next_next && *next_next == '|'); } +#else /* not INSIDE_RECURSION */ /* Returns true if REGNUM is in one of COMPILE_STACK's elements and false if it's not. */ static boolean -group_in_compile_stack (compile_stack, regnum) - compile_stack_type compile_stack; - regnum_t regnum; +group_in_compile_stack (compile_stack_type compile_stack, + regnum_t regnum) { int this_element; @@ -4342,36 +4335,33 @@ group_in_compile_stack (compile_stack, regnum) return false; } +#endif /* not INSIDE_RECURSION */ -#ifdef MBS_SUPPORT +#ifdef INSIDE_RECURSION + +#ifdef WCHAR /* This insert space, which size is "num", into the pattern at "loc". "end" must point the end of the allocated buffer. */ static void -insert_space (num, loc, end) - int num; - CHAR_TYPE *loc; - CHAR_TYPE *end; +insert_space (int num, CHAR_T *loc, CHAR_T *end) { - register CHAR_TYPE *pto = end; - register CHAR_TYPE *pfrom = end - num; + register CHAR_T *pto = end; + register CHAR_T *pfrom = end - num; while (pfrom >= loc) *pto-- = *pfrom--; } -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ -#ifdef MBS_SUPPORT +#ifdef WCHAR static reg_errcode_t -compile_range (range_start_char, p_ptr, pend, translate, syntax, b, - char_set) - CHAR_TYPE range_start_char; - const CHAR_TYPE **p_ptr, *pend; - CHAR_TYPE *char_set, *b; - RE_TRANSLATE_TYPE translate; - reg_syntax_t syntax; +wcs_compile_range (CHAR_T range_start_char, + const CHAR_T **p_ptr, const CHAR_T *pend, + RE_TRANSLATE_TYPE translate, reg_syntax_t syntax, + CHAR_T *b, CHAR_T *char_set) { - const CHAR_TYPE *p = *p_ptr; - CHAR_TYPE range_start, range_end; + const CHAR_T *p = *p_ptr; + CHAR_T range_start, range_end; reg_errcode_t ret; # ifdef _LIBC uint32_t nrules; @@ -4436,7 +4426,7 @@ compile_range (range_start_char, p_ptr, pend, translate, syntax, b, return ret; } -#else +#else /* BYTE */ /* Read the ending character of a range (in a bracket expression) from the uncompiled pattern *P_PTR (which ends at PEND). We assume the starting character is in `P[-2]'. (`P[-1]' is the character `-'.) @@ -4449,12 +4439,10 @@ compile_range (range_start_char, p_ptr, pend, translate, syntax, b, `regex_compile' itself. */ static reg_errcode_t -compile_range (range_start_char, p_ptr, pend, translate, syntax, b) - unsigned int range_start_char; - const char **p_ptr, *pend; - RE_TRANSLATE_TYPE translate; - reg_syntax_t syntax; - unsigned char *b; +byte_compile_range (unsigned int range_start_char, + const char **p_ptr, const char *pend, + RE_TRANSLATE_TYPE translate, reg_syntax_t syntax, + unsigned char *b) { unsigned this_char; const char *p = *p_ptr; @@ -4514,7 +4502,7 @@ compile_range (range_start_char, p_ptr, pend, translate, syntax, b) return ret; } -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible @@ -4529,28 +4517,28 @@ compile_range (range_start_char, p_ptr, pend, translate, syntax, b) Returns 0 if we succeed, -2 if an internal error. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR /* local function for re_compile_fastmap. truncate wchar_t character to char. */ -static unsigned char truncate_wchar (CHAR_TYPE c); static unsigned char -truncate_wchar (c) - CHAR_TYPE c; +truncate_wchar (CHAR_T c) { - unsigned char buf[MB_LEN_MAX]; - int retval = wctomb(buf, c); - return retval > 0 ? buf[0] : (unsigned char)c; + unsigned char buf[MB_CUR_MAX]; + mbstate_t state; + int retval; + memset (&state, '\0', sizeof (state)); + retval = wcrtomb (buf, c, &state); + return retval > 0 ? buf[0] : (unsigned char) c; } -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; +static int +PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp) { int j, k; #ifdef MATCH_MAY_ALLOCATE - fail_stack_type fail_stack; + PREFIX(fail_stack_type) fail_stack; #endif #ifndef REGEX_MALLOC char *destination; @@ -4558,16 +4546,16 @@ re_compile_fastmap (bufp) register char *fastmap = bufp->fastmap; -#ifdef MBS_SUPPORT +#ifdef WCHAR /* We need to cast pattern to (wchar_t*), because we casted this compiled pattern to (char*) in regex_compile. */ - US_CHAR_TYPE *pattern = (US_CHAR_TYPE*)bufp->buffer; - register US_CHAR_TYPE *pend = (US_CHAR_TYPE*) (bufp->buffer + bufp->used); -#else - US_CHAR_TYPE *pattern = bufp->buffer; - register US_CHAR_TYPE *pend = pattern + bufp->used; -#endif /* MBS_SUPPORT */ - US_CHAR_TYPE *p = pattern; + UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; + register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); +#else /* BYTE */ + UCHAR_T *pattern = bufp->buffer; + register UCHAR_T *pend = pattern + bufp->used; +#endif /* WCHAR */ + UCHAR_T *p = pattern; #ifdef REL_ALLOC /* This holds the pointer to the failure stack, when @@ -4630,21 +4618,22 @@ re_compile_fastmap (bufp) /* Following are the cases which match a character. These end with `break'. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR case exactn: fastmap[truncate_wchar(p[1])] = 1; break; - case exactn_bin: - fastmap[p[1]] = 1; - break; -#else +#else /* BYTE */ case exactn: fastmap[p[1]] = 1; break; -#endif /* MBS_SUPPORT */ - - +#endif /* WCHAR */ #ifdef MBS_SUPPORT + case exactn_bin: + fastmap[p[1]] = 1; + break; +#endif + +#ifdef WCHAR /* It is hard to distinguish fastmap from (multi byte) characters which depends on current locale. */ case charset: @@ -4653,7 +4642,7 @@ re_compile_fastmap (bufp) case notwordchar: bufp->can_be_null = 1; goto done; -#else +#else /* BYTE */ case charset: for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) @@ -4684,7 +4673,7 @@ re_compile_fastmap (bufp) if (SYNTAX (j) != Sword) fastmap[j] = 1; break; -#endif +#endif /* WCHAR */ case anychar: { @@ -4859,11 +4848,25 @@ re_compile_fastmap (bufp) done: RESET_FAIL_STACK (); return 0; +} + +#else /* not INSIDE_RECURSION */ + +int +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + return wcs_re_compile_fastmap(bufp); + else +# endif + return byte_re_compile_fastmap(bufp); } /* re_compile_fastmap */ #ifdef _LIBC weak_alias (__re_compile_fastmap, re_compile_fastmap) #endif + /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS @@ -4878,11 +4881,10 @@ weak_alias (__re_compile_fastmap, re_compile_fastmap) freeing the old data. */ void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - unsigned num_regs; - regoff_t *starts, *ends; +re_set_registers (struct re_pattern_buffer *bufp, + struct re_registers *regs, + unsigned int num_regs, + regoff_t *starts, regoff_t *ends) { if (num_regs) { @@ -4908,11 +4910,10 @@ weak_alias (__re_set_registers, re_set_registers) doesn't let you say where to stop matching. */ int -re_search (bufp, string, size, startpos, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, startpos, range; - struct re_registers *regs; +re_search (struct re_pattern_buffer *bufp, + const char *string, + int size, int startpos, int range, + struct re_registers *regs) { return re_search_2 (bufp, NULL, 0, string, size, startpos, range, regs, size); @@ -4944,20 +4945,89 @@ weak_alias (__re_search, re_search) stack overflow). */ int -re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int startpos; - int range; - struct re_registers *regs; - int stop; +re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, + int stop) +{ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, + range, regs, stop); + else +# endif + return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, + range, regs, stop); +} /* re_search_2 */ +#ifdef _LIBC +weak_alias (__re_search_2, re_search_2) +#endif + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef MATCH_MAY_ALLOCATE +# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL +#else +# define FREE_VAR(var) if (var) free (var); var = NULL +#endif + +#ifdef WCHAR +# define MAX_ALLOCA_SIZE 2000 + +# define FREE_WCS_BUFFERS() \ + do { \ + if (size1 > MAX_ALLOCA_SIZE) \ + { \ + free (wcs_string1); \ + free (mbs_offset1); \ + } \ + else \ + { \ + FREE_VAR (wcs_string1); \ + FREE_VAR (mbs_offset1); \ + } \ + if (size2 > MAX_ALLOCA_SIZE) \ + { \ + free (wcs_string2); \ + free (mbs_offset2); \ + } \ + else \ + { \ + FREE_VAR (wcs_string2); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) + +#endif + + +static int +PREFIX(re_search_2) (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, + int stop) { int val; register char *fastmap = bufp->fastmap; register RE_TRANSLATE_TYPE translate = bufp->translate; int total_size = size1 + size2; int endpos = startpos + range; +#ifdef WCHAR + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ + wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; + /* We need the size of wchar_t buffers correspond to csize1, csize2. */ + int wcs_size1 = 0, wcs_size2 = 0; + /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ + int *mbs_offset1 = NULL, *mbs_offset2 = NULL; + /* They hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; +#endif /* WCHAR */ /* Check for out-of-range STARTPOS. */ if (startpos < 0 || startpos > total_size) @@ -4984,22 +5054,97 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) else range = 1; } - -#ifdef emacs - /* In a forward search for something that starts with \=. - don't keep searching past point. */ - if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) + +#ifdef emacs + /* In a forward search for something that starts with \=. + don't keep searching past point. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) + { + range = PT - startpos; + if (range <= 0) + return -1; + } +#endif /* emacs */ + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + +#ifdef WCHAR + /* Allocate wchar_t array for wcs_string1 and wcs_string2 and + fill them with converted string. */ + if (size1 != 0) + { + if (size1 > MAX_ALLOCA_SIZE) + { + wcs_string1 = TALLOC (size1 + 1, CHAR_T); + mbs_offset1 = TALLOC (size1 + 1, int); + is_binary = TALLOC (size1 + 1, char); + } + else + { + wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); + mbs_offset1 = REGEX_TALLOC (size1 + 1, int); + is_binary = REGEX_TALLOC (size1 + 1, char); + } + if (!wcs_string1 || !mbs_offset1 || !is_binary) + { + if (size1 > MAX_ALLOCA_SIZE) + { + free (wcs_string1); + free (mbs_offset1); + free (is_binary); + } + else + { + FREE_VAR (wcs_string1); + FREE_VAR (mbs_offset1); + FREE_VAR (is_binary); + } + return -2; + } + wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, + mbs_offset1, is_binary); + wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ + if (size1 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + } + if (size2 != 0) { - range = PT - startpos; - if (range <= 0) - return -1; + if (size2 > MAX_ALLOCA_SIZE) + { + wcs_string2 = TALLOC (size2 + 1, CHAR_T); + mbs_offset2 = TALLOC (size2 + 1, int); + is_binary = TALLOC (size2 + 1, char); + } + else + { + wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); + mbs_offset2 = REGEX_TALLOC (size2 + 1, int); + is_binary = REGEX_TALLOC (size2 + 1, char); + } + if (!wcs_string2 || !mbs_offset2 || !is_binary) + { + FREE_WCS_BUFFERS (); + if (size2 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + return -2; + } + wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, + mbs_offset2, is_binary); + wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ + if (size2 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); } -#endif /* emacs */ +#endif /* WCHAR */ - /* Update the fastmap now if not correct already. */ - if (fastmap && !bufp->fastmap_accurate) - if (re_compile_fastmap (bufp) == -2) - return -2; /* Loop through the string, looking for a place to start matching. */ for (;;) @@ -5036,7 +5181,7 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) } else /* Searching backwards. */ { - register CHAR_TYPE c = (size1 == 0 || startpos >= size1 + register CHAR_T c = (size1 == 0 || startpos >= size1 ? string2[startpos - size1] : string1[startpos]); @@ -5048,10 +5193,24 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) /* If can't match the null string, and that's all we have left, fail. */ if (range >= 0 && startpos == total_size && fastmap && !bufp->can_be_null) - return -1; + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -1; + } + +#ifdef WCHAR + val = wcs_re_match_2_internal (bufp, string1, size1, string2, + size2, startpos, regs, stop, + wcs_string1, wcs_size1, + wcs_string2, wcs_size2, + mbs_offset1, mbs_offset2); +#else /* BYTE */ + val = byte_re_match_2_internal (bufp, string1, size1, string2, + size2, startpos, regs, stop); +#endif /* BYTE */ - val = re_match_2_internal (bufp, string1, size1, string2, size2, - startpos, regs, stop); #ifndef REGEX_MALLOC # ifdef C_ALLOCA alloca (0); @@ -5059,10 +5218,20 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) #endif if (val >= 0) - return startpos; + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return startpos; + } if (val == -2) - return -2; + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -2; + } advance: if (!range) @@ -5078,13 +5247,13 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) startpos--; } } - return -1; -} /* re_search_2 */ -#ifdef _LIBC -weak_alias (__re_search_2, re_search_2) +#ifdef WCHAR + FREE_WCS_BUFFERS (); #endif - -#ifdef MBS_SUPPORT + return -1; +} + +#ifdef WCHAR /* This converts PTR, a pointer into one of the search wchar_t strings `string1' and `string2' into an multibyte string offset from the beginning of that string. We use mbs_offset to optimize. @@ -5094,14 +5263,14 @@ weak_alias (__re_search_2, re_search_2) ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ + csize1))) -#else +#else /* BYTE */ /* This converts PTR, a pointer into one of the search strings `string1' and `string2' into an offset from the beginning of that string. */ # define POINTER_TO_OFFSET(ptr) \ (FIRST_STRING_P (ptr) \ ? ((regoff_t) ((ptr) - string1)) \ : ((regoff_t) ((ptr) - string2 + size1))) -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* Macros for dealing with the split strings in re_match_2. */ @@ -5120,7 +5289,6 @@ weak_alias (__re_search_2, re_search_2) dend = end_match_2; \ } - /* Test if at very beginning or at very end of the virtual concatenation of `string1' and `string2'. If only one string, it's `string2'. */ #define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) @@ -5131,17 +5299,19 @@ weak_alias (__re_search_2, re_search_2) two special cases to check for: if past the end of string1, look at the first character in string2; and if before the beginning of string2, look at the last character in string1. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR /* Use internationalized API instead of SYNTAX. */ # define WORDCHAR_P(d) \ (iswalnum ((wint_t)((d) == end1 ? *string2 \ - : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0) -#else + : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ + || ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') +#else /* BYTE */ # define WORDCHAR_P(d) \ (SYNTAX ((d) == end1 ? *string2 \ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ == Sword) -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* Disabled due to a compiler bug -- see comment at case wordbound */ #if 0 @@ -5154,8 +5324,7 @@ weak_alias (__re_search_2, re_search_2) /* Free everything we malloc. */ #ifdef MATCH_MAY_ALLOCATE -# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL -# ifdef MBS_SUPPORT +# ifdef WCHAR # define FREE_VARIABLES() \ do { \ REGEX_FREE_STACK (fail_stack.stack); \ @@ -5168,12 +5337,15 @@ weak_alias (__re_search_2, re_search_2) FREE_VAR (reg_info); \ FREE_VAR (reg_dummy); \ FREE_VAR (reg_info_dummy); \ - FREE_VAR (string1); \ - FREE_VAR (string2); \ - FREE_VAR (mbs_offset1); \ - FREE_VAR (mbs_offset2); \ + if (!cant_free_wcs_buf) \ + { \ + FREE_VAR (string1); \ + FREE_VAR (string2); \ + FREE_VAR (mbs_offset1); \ + FREE_VAR (mbs_offset2); \ + } \ } while (0) -# else /* not MBS_SUPPORT */ +# else /* BYTE */ # define FREE_VARIABLES() \ do { \ REGEX_FREE_STACK (fail_stack.stack); \ @@ -5187,20 +5359,22 @@ weak_alias (__re_search_2, re_search_2) FREE_VAR (reg_dummy); \ FREE_VAR (reg_info_dummy); \ } while (0) -# endif /* MBS_SUPPORT */ +# endif /* WCHAR */ #else -# define FREE_VAR(var) if (var) free (var); var = NULL -# ifdef MBS_SUPPORT +# ifdef WCHAR # define FREE_VARIABLES() \ do { \ - FREE_VAR (string1); \ - FREE_VAR (string2); \ - FREE_VAR (mbs_offset1); \ - FREE_VAR (mbs_offset2); \ + if (!cant_free_wcs_buf) \ + { \ + FREE_VAR (string1); \ + FREE_VAR (string2); \ + FREE_VAR (mbs_offset1); \ + FREE_VAR (mbs_offset2); \ + } \ } while (0) -# else +# else /* BYTE */ # define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ -# endif /* MBS_SUPPORT */ +# endif /* WCHAR */ #endif /* not MATCH_MAY_ALLOCATE */ /* These values must meet several constraints. They must not be valid @@ -5213,20 +5387,28 @@ weak_alias (__re_search_2, re_search_2) #define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) #define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) +#else /* not INSIDE_RECURSION */ /* Matching routines. */ #ifndef emacs /* Emacs never uses this. */ /* re_match is like re_match_2 except it takes only a single string. */ int -re_match (bufp, string, size, pos, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, pos; - struct re_registers *regs; +re_match (struct re_pattern_buffer *bufp, + const char *string, + int size, int pos, + struct re_registers *regs) { - int result = re_match_2_internal (bufp, NULL, 0, string, size, - pos, regs, size); + int result; +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size, + NULL, 0, NULL, 0, NULL, NULL); + else +# endif + result = byte_re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size); # ifndef REGEX_MALLOC # ifdef C_ALLOCA alloca (0); @@ -5239,17 +5421,21 @@ weak_alias (__re_match, re_match) # endif #endif /* not emacs */ -static boolean group_match_null_string_p _RE_ARGS ((US_CHAR_TYPE **p, - US_CHAR_TYPE *end, - register_info_type *reg_info)); -static boolean alt_match_null_string_p _RE_ARGS ((US_CHAR_TYPE *p, - US_CHAR_TYPE *end, - register_info_type *reg_info)); -static boolean common_op_match_null_string_p _RE_ARGS ((US_CHAR_TYPE **p, - US_CHAR_TYPE *end, - register_info_type *reg_info)); -static int bcmp_translate _RE_ARGS ((const CHAR_TYPE *s1, const CHAR_TYPE *s2, - int len, char *translate)); +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION +static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, + int len, char *translate); +#else /* not INSIDE_RECURSION */ /* re_match_2 matches the compiled pattern in BUFP against the the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 @@ -5265,16 +5451,23 @@ static int bcmp_translate _RE_ARGS ((const CHAR_TYPE *s1, const CHAR_TYPE *s2, matched substring. */ int -re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int stop; +re_match_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, struct re_registers *regs, + int stop) { - int result = re_match_2_internal (bufp, string1, size1, string2, size2, - pos, regs, stop); + int result; +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop, + NULL, 0, NULL, 0, NULL, NULL); + else +# endif + result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop); + #ifndef REGEX_MALLOC # ifdef C_ALLOCA alloca (0); @@ -5286,9 +5479,11 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) weak_alias (__re_match_2, re_match_2) #endif -#ifdef MBS_SUPPORT +#endif /* not INSIDE_RECURSION */ -static int count_mbs_length PARAMS ((int *, int)); +#ifdef INSIDE_RECURSION + +#ifdef WCHAR /* This check the substring (from 0, to length) of the multibyte string, to which offset_buffer correspond. And count how many wchar_t_characters @@ -5296,11 +5491,9 @@ static int count_mbs_length PARAMS ((int *, int)); See convert_mbs_to_wcs. */ static int -count_mbs_length(offset_buffer, length) - int *offset_buffer; - int length; +count_mbs_length (int *offset_buffer, int length) { - int wcs_size; + int upper, lower; /* Check whether the size is valid. */ if (length < 0) @@ -5309,74 +5502,95 @@ count_mbs_length(offset_buffer, length) if (offset_buffer == NULL) return 0; - for (wcs_size = 0 ; offset_buffer[wcs_size] != -1 ; wcs_size++) + /* If there are no multibyte character, offset_buffer[i] == i. + Optmize for this case. */ + if (offset_buffer[length] == length) + return length; + + /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ + upper = length; + lower = 0; + + while (true) { - if (offset_buffer[wcs_size] == length) - return wcs_size; - if (offset_buffer[wcs_size] > length) - /* It is a fragment of a wide character. */ - return -1; + int middle = (lower + upper) / 2; + if (middle == lower || middle == upper) + break; + if (offset_buffer[middle] > length) + upper = middle; + else if (offset_buffer[middle] < length) + lower = middle; + else + return middle; } - /* We reached at the sentinel. */ return -1; } -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* This is a separate function so that we can force an alloca cleanup afterwards. */ +#ifdef WCHAR static int -#ifdef MBS_SUPPORT -re_match_2_internal (bufp, cstring1, csize1, cstring2, csize2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *cstring1, *cstring2; - int csize1, csize2; -#else -re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; -#endif - int pos; - struct re_registers *regs; - int stop; +wcs_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *cstring1, int csize1, + const char *cstring2, int csize2, + int pos, + struct re_registers *regs, + int stop, + /* string1 == string2 == NULL means + string1/2, size1/2 and mbs_offset1/2 need + setting up in this function. */ + /* We need wchar_t * buffers corresponding to + cstring1, cstring2. */ + wchar_t *string1, int size1, + wchar_t *string2, int size2, + /* Offset buffer for optimization. See + convert_mbs_to_wc. */ + int *mbs_offset1, + int *mbs_offset2) +#else /* BYTE */ +static int +byte_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop) +#endif /* BYTE */ { /* General temporaries. */ int mcnt; - US_CHAR_TYPE *p1; -#ifdef MBS_SUPPORT - /* We need wchar_t* buffers correspond to string1, string2. */ - CHAR_TYPE *string1 = NULL, *string2 = NULL; - /* We need the size of wchar_t buffers correspond to csize1, csize2. */ - int size1 = 0, size2 = 0; - /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ - int *mbs_offset1 = NULL, *mbs_offset2 = NULL; + UCHAR_T *p1; +#ifdef WCHAR /* They hold whether each wchar_t is binary data or not. */ char *is_binary = NULL; -#endif /* MBS_SUPPORT */ + /* If true, we can't free string1/2, mbs_offset1/2. */ + int cant_free_wcs_buf = 1; +#endif /* WCHAR */ /* Just past the end of the corresponding string. */ - const CHAR_TYPE *end1, *end2; + const CHAR_T *end1, *end2; /* Pointers into string1 and string2, just past the last characters in each to consider matching. */ - const CHAR_TYPE *end_match_1, *end_match_2; + const CHAR_T *end_match_1, *end_match_2; /* Where we are in the data, and the end of the current string. */ - const CHAR_TYPE *d, *dend; + const CHAR_T *d, *dend; /* Where we are in the pattern, and the end of the pattern. */ -#ifdef MBS_SUPPORT - US_CHAR_TYPE *pattern, *p; - register US_CHAR_TYPE *pend; -#else - US_CHAR_TYPE *p = bufp->buffer; - register US_CHAR_TYPE *pend = p + bufp->used; -#endif /* MBS_SUPPORT */ +#ifdef WCHAR + UCHAR_T *pattern, *p; + register UCHAR_T *pend; +#else /* BYTE */ + UCHAR_T *p = bufp->buffer; + register UCHAR_T *pend = p + bufp->used; +#endif /* WCHAR */ /* Mark the opcode just after a start_memory, so we can test for an empty subpattern when we get to the stop_memory. */ - US_CHAR_TYPE *just_past_start_mem = 0; + UCHAR_T *just_past_start_mem = 0; /* We use this to map every character in the string. */ RE_TRANSLATE_TYPE translate = bufp->translate; @@ -5391,7 +5605,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) a ``dummy''; if a failure happens and the failure point is a dummy, it gets discarded and the next next one is tried. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ - fail_stack_type fail_stack; + PREFIX(fail_stack_type) fail_stack; #endif #ifdef DEBUG static unsigned failure_id; @@ -5421,7 +5635,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) stopped matching the regnum-th subexpression. (The zeroth register keeps track of what the whole pattern matches.) */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const CHAR_TYPE **regstart, **regend; + const CHAR_T **regstart, **regend; #endif /* If a group that's operated upon by a repetition operator fails to @@ -5430,7 +5644,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) are when we last see its open-group operator. Similarly for a register's end. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const CHAR_TYPE **old_regstart, **old_regend; + const CHAR_T **old_regstart, **old_regend; #endif /* The is_active field of reg_info helps us keep track of which (possibly @@ -5440,7 +5654,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) subexpression. These two fields get reset each time through any loop their register is in. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ - register_info_type *reg_info; + PREFIX(register_info_type) *reg_info; #endif /* The following record the register info as found in the above @@ -5449,7 +5663,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) turn happens only if we have not yet matched the entire string. */ unsigned best_regs_set = false; #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const CHAR_TYPE **best_regstart, **best_regend; + const CHAR_T **best_regstart, **best_regend; #endif /* Logically, this is `best_regend[0]'. But we don't want to have to @@ -5460,15 +5674,15 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) the end of the best match so far in a separate variable. We initialize this to NULL so that when we backtrack the first time and need to test it, it's not garbage. */ - const CHAR_TYPE *match_end = NULL; + const CHAR_T *match_end = NULL; /* This helps SET_REGS_MATCHED avoid doing redundant work. */ int set_regs_matched_done = 0; /* Used when we pop values we don't care about. */ #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - const CHAR_TYPE **reg_dummy; - register_info_type *reg_info_dummy; + const CHAR_T **reg_dummy; + PREFIX(register_info_type) *reg_info_dummy; #endif #ifdef DEBUG @@ -5476,6 +5690,88 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) unsigned num_regs_pushed = 0; #endif + /* Definitions for state transitions. More efficiently for gcc. */ +#ifdef __GNUC__ +# if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED +# define NEXT \ + do \ + { \ + int offset; \ + const void *__unbounded ptr; \ + offset = (p == pend \ + ? 0 : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \ + ptr = &&end_of_pattern + offset; \ + goto *ptr; \ + } \ + while (0) +# define REF(x) \ + &&label_##x - &&end_of_pattern +# define JUMP_TABLE_TYPE const int +# else +# define NEXT \ + do \ + { \ + const void *__unbounded ptr; \ + ptr = (p == pend ? &&end_of_pattern \ + : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \ + goto *ptr; \ + } \ + while (0) +# define REF(x) \ + &&label_##x +# define JUMP_TABLE_TYPE const void *const +# endif +# define CASE(x) label_##x + static JUMP_TABLE_TYPE jmptable[] = + { + REF (no_op), + REF (succeed), + REF (exactn), +# ifdef MBS_SUPPORT + REF (exactn_bin), +# endif + REF (anychar), + REF (charset), + REF (charset_not), + REF (start_memory), + REF (stop_memory), + REF (duplicate), + REF (begline), + REF (endline), + REF (begbuf), + REF (endbuf), + REF (jump), + REF (jump_past_alt), + REF (on_failure_jump), + REF (on_failure_keep_string_jump), + REF (pop_failure_jump), + REF (maybe_pop_jump), + REF (dummy_failure_jump), + REF (push_dummy_failure), + REF (succeed_n), + REF (jump_n), + REF (set_number_at), + REF (wordchar), + REF (notwordchar), + REF (wordbeg), + REF (wordend), + REF (wordbound), + REF (notwordbound) +# ifdef emacs + ,REF (before_dot), + REF (at_dot), + REF (after_dot), + REF (syntaxspec), + REF (notsyntaxspec) +# endif + }; +#else +# define NEXT \ + break +# define CASE(x) \ + case x +#endif + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); INIT_FAIL_STACK (); @@ -5488,15 +5784,15 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) array indexing. We should fix this. */ if (bufp->re_nsub) { - regstart = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - regend = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - old_regstart = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - old_regend = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - best_regstart = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - best_regend = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - reg_info = REGEX_TALLOC (num_regs, register_info_type); - reg_dummy = REGEX_TALLOC (num_regs, const CHAR_TYPE *); - reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + regend = REGEX_TALLOC (num_regs, const CHAR_T *); + old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); + best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); + reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); + reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); + reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); if (!(regstart && regend && old_regstart && old_regend && reg_info && best_regstart && best_regend && reg_dummy && reg_info_dummy)) @@ -5511,14 +5807,14 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) `FREE_VARIABLES' doesn't try to free them. */ regstart = regend = old_regstart = old_regend = best_regstart = best_regend = reg_dummy = NULL; - reg_info = reg_info_dummy = (register_info_type *) NULL; + reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; } #endif /* MATCH_MAY_ALLOCATE */ /* The starting position is bogus. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR if (pos < 0 || pos > csize1 + csize2) -#else +#else /* BYTE */ if (pos < 0 || pos > size1 + size2) #endif { @@ -5526,52 +5822,56 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) return -1; } -#ifdef MBS_SUPPORT +#ifdef WCHAR /* Allocate wchar_t array for string1 and string2 and fill them with converted string. */ - if (csize1 != 0) + if (string1 == NULL && string2 == NULL) { - string1 = REGEX_TALLOC (csize1 + 1, CHAR_TYPE); - mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); - is_binary = REGEX_TALLOC (csize1 + 1, char); - if (!string1 || !mbs_offset1 || !is_binary) + /* We need seting up buffers here. */ + + /* We must free wcs buffers in this function. */ + cant_free_wcs_buf = 0; + + if (csize1 != 0) { - FREE_VAR (string1); - FREE_VAR (mbs_offset1); - FREE_VAR (is_binary); - return -2; + string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); + mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); + is_binary = REGEX_TALLOC (csize1 + 1, char); + if (!string1 || !mbs_offset1 || !is_binary) + { + FREE_VAR (string1); + FREE_VAR (mbs_offset1); + FREE_VAR (is_binary); + return -2; + } } - size1 = convert_mbs_to_wcs(string1, cstring1, csize1, - mbs_offset1, is_binary); - string1[size1] = L'\0'; /* for a sentinel */ - FREE_VAR (is_binary); - } - if (csize2 != 0) - { - string2 = REGEX_TALLOC (csize2 + 1, CHAR_TYPE); - mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); - is_binary = REGEX_TALLOC (csize2 + 1, char); - if (!string2 || !mbs_offset2 || !is_binary) + if (csize2 != 0) { - FREE_VAR (string1); - FREE_VAR (mbs_offset1); - FREE_VAR (string2); - FREE_VAR (mbs_offset2); + string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); + mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); + is_binary = REGEX_TALLOC (csize2 + 1, char); + if (!string2 || !mbs_offset2 || !is_binary) + { + FREE_VAR (string1); + FREE_VAR (mbs_offset1); + FREE_VAR (string2); + FREE_VAR (mbs_offset2); + FREE_VAR (is_binary); + return -2; + } + size2 = convert_mbs_to_wcs(string2, cstring2, csize2, + mbs_offset2, is_binary); + string2[size2] = L'\0'; /* for a sentinel */ FREE_VAR (is_binary); - return -2; } - size2 = convert_mbs_to_wcs(string2, cstring2, csize2, - mbs_offset2, is_binary); - string2[size2] = L'\0'; /* for a sentinel */ - FREE_VAR (is_binary); } /* We need to cast pattern to (wchar_t*), because we casted this compiled pattern to (char*) in regex_compile. */ - p = pattern = (CHAR_TYPE*)bufp->buffer; - pend = (CHAR_TYPE*)(bufp->buffer + bufp->used); + p = pattern = (CHAR_T*)bufp->buffer; + pend = (CHAR_T*)(bufp->buffer + bufp->used); -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* Initialize subexpression text positions to -1 to mark ones that no start_memory/stop_memory has been seen for. Also initialize the @@ -5595,12 +5895,18 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) size2 = size1; string1 = 0; size1 = 0; +#ifdef WCHAR + mbs_offset2 = mbs_offset1; + csize2 = csize1; + mbs_offset1 = NULL; + csize1 = 0; +#endif } end1 = string1 + size1; end2 = string2 + size2; /* Compute where to stop matching, within the two strings. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR if (stop <= csize1) { mcnt = count_mbs_length(mbs_offset1, stop); @@ -5609,6 +5915,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) } else { + if (stop > csize1 + csize2) + stop = csize1 + csize2; end_match_1 = end1; mcnt = count_mbs_length(mbs_offset2, stop-csize1); end_match_2 = string2 + mcnt; @@ -5629,7 +5937,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) end_match_1 = end1; end_match_2 = string2 + stop - size1; } -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ /* `p' scans through the pattern as `d' scans through the data. `dend' is the end of the input string that `d' points within. `d' @@ -5637,7 +5945,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) this happens before fetching; therefore, at the beginning of the loop, `d' can be pointing at the end of a string, but it cannot equal `string2'. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR if (size1 > 0 && pos <= csize1) { mcnt = count_mbs_length(mbs_offset1, pos); @@ -5667,7 +5975,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) d = string2 + pos - size1; dend = end_match_2; } -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ DEBUG_PRINT1 ("The compiled pattern is:\n"); DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); @@ -5686,13 +5994,21 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) DEBUG_PRINT2 ("\n0x%x: ", p); #endif +#ifdef __GNUC__ + NEXT; +#else if (p == pend) - { /* End of pattern means we might have succeeded. */ - DEBUG_PRINT1 ("end of pattern ... "); +#endif + { +#ifdef __GNUC__ + end_of_pattern: +#endif + /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); /* If we haven't matched the entire string, and we want the - longest match, try backtracking. */ - if (d != end_match_2) + longest match, try backtracking. */ + if (d != end_match_2) { /* 1 if this match ends in the same string (string1 or string2) as the best previous match. */ @@ -5708,184 +6024,185 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) else best_match_p = !MATCHING_IN_FIRST_STRING; - DEBUG_PRINT1 ("backtracking.\n"); + DEBUG_PRINT1 ("backtracking.\n"); - if (!FAIL_STACK_EMPTY ()) - { /* More failure points to try. */ + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ - /* If exceeds best match so far, save it. */ - if (!best_regs_set || best_match_p) - { - best_regs_set = true; - match_end = d; + /* If exceeds best match so far, save it. */ + if (!best_regs_set || best_match_p) + { + best_regs_set = true; + match_end = d; - DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); - for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) - { - best_regstart[mcnt] = regstart[mcnt]; - best_regend[mcnt] = regend[mcnt]; - } - } - goto fail; - } + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } - /* If no failure points, don't restore garbage. And if - last match is real best match, don't restore second - best one. */ - else if (best_regs_set && !best_match_p) - { - restore_best_regs: - /* Restore best match. It may happen that `dend == - end_match_1' while the restored d is in string2. - For example, the pattern `x.*y.*z' against the - strings `x-' and `y-z-', if the two strings are - not consecutive in memory. */ - DEBUG_PRINT1 ("Restoring best registers.\n"); - - d = match_end; - dend = ((d >= string1 && d <= end1) - ? end_match_1 : end_match_2); + /* If no failure points, don't restore garbage. And if + last match is real best match, don't restore second + best one. */ + else if (best_regs_set && !best_match_p) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) { regstart[mcnt] = best_regstart[mcnt]; regend[mcnt] = best_regend[mcnt]; } - } - } /* d != end_match_2 */ + } + } /* d != end_match_2 */ succeed_label: - DEBUG_PRINT1 ("Accepting match.\n"); - /* If caller wants register contents data back, do it. */ - if (regs && !bufp->no_sub) + DEBUG_PRINT1 ("Accepting match.\n"); + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) { /* Have the register data arrays been allocated? */ - if (bufp->regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. We need one - extra element beyond `num_regs' for the `-1' marker - GNU code uses. */ - regs->num_regs = MAX (RE_NREGS, num_regs + 1); - regs->start = TALLOC (regs->num_regs, regoff_t); - regs->end = TALLOC (regs->num_regs, regoff_t); - if (regs->start == NULL || regs->end == NULL) + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) { FREE_VARIABLES (); return -2; } - bufp->regs_allocated = REGS_REALLOCATE; - } - else if (bufp->regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (regs->num_regs < num_regs + 1) - { - regs->num_regs = num_regs + 1; - RETALLOC (regs->start, regs->num_regs, regoff_t); - RETALLOC (regs->end, regs->num_regs, regoff_t); - if (regs->start == NULL || regs->end == NULL) + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) { FREE_VARIABLES (); return -2; } - } - } - else + } + } + else { /* These braces fend off a "empty body in an else-statement" warning under GCC when assert expands to nothing. */ assert (bufp->regs_allocated == REGS_FIXED); } - /* Convert the pointer data in `regstart' and `regend' to - indices. Register zero has to be set differently, - since we haven't kept track of any info for it. */ - if (regs->num_regs > 0) - { - regs->start[0] = pos; -#ifdef MBS_SUPPORT + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; +#ifdef WCHAR if (MATCHING_IN_FIRST_STRING) - regs->end[0] = mbs_offset1 != NULL ? - mbs_offset1[d-string1] : 0; + regs->end[0] = (mbs_offset1 != NULL ? + mbs_offset1[d-string1] : 0); else - regs->end[0] = csize1 + (mbs_offset2 != NULL ? - mbs_offset2[d-string2] : 0); + regs->end[0] = csize1 + (mbs_offset2 != NULL + ? mbs_offset2[d-string2] : 0); #else - regs->end[0] = (MATCHING_IN_FIRST_STRING + regs->end[0] = (MATCHING_IN_FIRST_STRING ? ((regoff_t) (d - string1)) - : ((regoff_t) (d - string2 + size1))); -#endif /* MBS_SUPPORT */ - } + : ((regoff_t) (d - string2 + size1))); +#endif /* WCHAR */ + } - /* Go through the first `min (num_regs, regs->num_regs)' - registers, since that is all we initialized. */ + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); mcnt++) { - if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) - regs->start[mcnt] = regs->end[mcnt] = -1; - else - { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { regs->start[mcnt] = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); - regs->end[mcnt] + regs->end[mcnt] = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); - } + } } - /* If the regs structure we return has more elements than - were in the pattern, set the extra elements to -1. If - we (re)allocated the registers, this is the case, - because we always allocate enough to have at least one - -1 at the end. */ - for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) - regs->start[mcnt] = regs->end[mcnt] = -1; + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; } /* regs && !bufp->no_sub */ - DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", - nfailure_points_pushed, nfailure_points_popped, - nfailure_points_pushed - nfailure_points_popped); - DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); -#ifdef MBS_SUPPORT +#ifdef WCHAR if (MATCHING_IN_FIRST_STRING) mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; else mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + - csize1; - mcnt -= pos; + csize1; + mcnt -= pos; #else - mcnt = d - pos - (MATCHING_IN_FIRST_STRING - ? string1 - : string2 - size1); -#endif /* MBS_SUPPORT */ + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 : string2 - size1); +#endif /* WCHAR */ - DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); - FREE_VARIABLES (); - return mcnt; - } + FREE_VARIABLES (); + return mcnt; + } +#ifndef __GNUC__ /* Otherwise match next pattern command. */ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) { +#endif /* Ignore these. Used to ignore the n of succeed_n's which currently have n == 0. */ - case no_op: + CASE (no_op): DEBUG_PRINT1 ("EXECUTING no_op.\n"); - break; + NEXT; - case succeed: + CASE (succeed): DEBUG_PRINT1 ("EXECUTING succeed.\n"); goto succeed_label; /* Match the next n pattern characters exactly. The following byte in the pattern defines n, and the n bytes after that are the characters to match. */ - case exactn: + CASE (exactn): #ifdef MBS_SUPPORT - case exactn_bin: + CASE (exactn_bin): #endif mcnt = *p++; DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); @@ -5897,23 +6214,23 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) do { PREFETCH (); -#ifdef MBS_SUPPORT +#ifdef WCHAR if (*d <= 0xff) { - if ((US_CHAR_TYPE) translate[(unsigned char) *d++] - != (US_CHAR_TYPE) *p++) + if ((UCHAR_T) translate[(unsigned char) *d++] + != (UCHAR_T) *p++) goto fail; } else { - if (*d++ != (CHAR_TYPE) *p++) + if (*d++ != (CHAR_T) *p++) goto fail; } #else - if ((US_CHAR_TYPE) translate[(unsigned char) *d++] - != (US_CHAR_TYPE) *p++) + if ((UCHAR_T) translate[(unsigned char) *d++] + != (UCHAR_T) *p++) goto fail; -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ } while (--mcnt); } @@ -5922,16 +6239,16 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) do { PREFETCH (); - if (*d++ != (CHAR_TYPE) *p++) goto fail; + if (*d++ != (CHAR_T) *p++) goto fail; } while (--mcnt); } SET_REGS_MATCHED (); - break; + NEXT; /* Match any character except possibly a newline or a null. */ - case anychar: + CASE (anychar): DEBUG_PRINT1 ("EXECUTING anychar.\n"); PREFETCH (); @@ -5943,29 +6260,29 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) SET_REGS_MATCHED (); DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); d++; - break; + NEXT; - case charset: - case charset_not: + CASE (charset): + CASE (charset_not): { - register US_CHAR_TYPE c; -#ifdef MBS_SUPPORT + register UCHAR_T c; +#ifdef WCHAR unsigned int i, char_class_length, coll_symbol_length, equiv_class_length, ranges_length, chars_length, length; - CHAR_TYPE *workp, *workp2, *charset_top; + CHAR_T *workp, *workp2, *charset_top; #define WORK_BUFFER_SIZE 128 - CHAR_TYPE str_buf[WORK_BUFFER_SIZE]; + CHAR_T str_buf[WORK_BUFFER_SIZE]; # ifdef _LIBC uint32_t nrules; # endif /* _LIBC */ -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ boolean not = (re_opcode_t) *(p - 1) == charset_not; DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); PREFETCH (); c = TRANSLATE (*d); /* The character to match. */ -#ifdef MBS_SUPPORT +#ifdef WCHAR # ifdef _LIBC nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); # endif /* _LIBC */ @@ -6030,13 +6347,13 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) { for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) { - const CHAR_TYPE *backup_d = d, *backup_dend = dend; - length = wcslen(workp); + const CHAR_T *backup_d = d, *backup_dend = dend; + length = wcslen (workp); /* If wcscoll(the collating symbol, whole string) > 0, any substring of the string never match with the collating symbol. */ - if (wcscoll(workp, d) > 0) + if (wcscoll (workp, d) > 0) { workp += length + 1; continue; @@ -6061,7 +6378,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) str_buf[i] = TRANSLATE(*d); str_buf[i+1] = '\0'; - match = wcscoll(workp, str_buf); + match = wcscoll (workp, str_buf); if (match == 0) goto char_set_matched; @@ -6085,7 +6402,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) # ifdef _LIBC if (nrules != 0) { - const CHAR_TYPE *backup_d = d, *backup_dend = dend; + const CHAR_T *backup_d = d, *backup_dend = dend; /* Try to match the equivalence class against those known to the collate implementation. */ const int32_t *table; @@ -6171,13 +6488,13 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) { for (workp2 = workp + equiv_class_length ; workp < workp2 ;) { - const CHAR_TYPE *backup_d = d, *backup_dend = dend; - length = wcslen(workp); + const CHAR_T *backup_d = d, *backup_dend = dend; + length = wcslen (workp); /* If wcscoll(the collating symbol, whole string) > 0, any substring of the string never match with the collating symbol. */ - if (wcscoll(workp, d) > 0) + if (wcscoll (workp, d) > 0) { workp += length + 1; break; @@ -6202,7 +6519,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) str_buf[i] = TRANSLATE(*d); str_buf[i+1] = '\0'; - match = wcscoll(workp, str_buf); + match = wcscoll (workp, str_buf); if (match == 0) goto char_set_matched; @@ -6225,7 +6542,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) } /* match with char_range? */ -#ifdef _LIBC +# ifdef _LIBC if (nrules != 0) { uint32_t collseqval; @@ -6248,7 +6565,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) } } else -#endif +# endif { /* We set range_start_char at str_buf[0], range_end_char at str_buf[4], and compared char at str_buf[2]. */ @@ -6284,9 +6601,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) range_end_char = str_buf + 4; } - if (wcscoll(range_start_char, str_buf+2) <= 0 && - wcscoll(str_buf+2, range_end_char) <= 0) - + if (wcscoll (range_start_char, str_buf+2) <= 0 + && wcscoll (str_buf+2, range_end_char) <= 0) goto char_set_matched; } } @@ -6311,10 +6627,10 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) if (!not) goto fail; #undef WORK_BUFFER_SIZE -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ SET_REGS_MATCHED (); d++; - break; + NEXT; } @@ -6323,7 +6639,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) number of groups inner to this one in the next. The text matched within the group is recorded (in the internal registers data structure) under the register number. */ - case start_memory: + CASE (start_memory): DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", (long int) *p, (long int) p[1]); @@ -6332,7 +6648,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[*p]) - = group_match_null_string_p (&p1, pend, reg_info); + = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); /* Save the position in the string where we were the last time we were at this open-group operator in case the group is @@ -6366,13 +6682,13 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) p += 2; just_past_start_mem = p; - break; + NEXT; /* The stop_memory opcode represents the end of a group. Its arguments are the same as start_memory's: the register number, and the number of inner groups. */ - case stop_memory: + CASE (stop_memory): DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", (long int) *p, (long int) p[1]); @@ -6408,7 +6724,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) it isn't necessarily one less than now: consider (a(b)c(d(e)f)g). When group 3 ends, after the f), the new highest active register is 1. */ - US_CHAR_TYPE r = *p - 1; + UCHAR_T r = *p - 1; while (r > 0 && !IS_ACTIVE (reg_info[r])) r--; @@ -6505,14 +6821,14 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) /* Move past the register number and the inner group count. */ p += 2; - break; + NEXT; /* \<digit> has been turned into a `duplicate' command which is followed by the numeric value of <digit> as the register number. */ - case duplicate: + CASE (duplicate): { - register const CHAR_TYPE *d2, *dend2; + register const CHAR_T *d2, *dend2; int regno = *p++; /* Get which register to match against. */ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); @@ -6561,8 +6877,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) /* Compare that many; failure if mismatch, else move past them. */ if (translate - ? bcmp_translate (d, d2, mcnt, translate) - : memcmp (d, d2, mcnt*sizeof(US_CHAR_TYPE))) + ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) + : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) goto fail; d += mcnt, d2 += mcnt; @@ -6570,58 +6886,68 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) SET_REGS_MATCHED (); } } - break; + NEXT; /* begline matches the empty string at the beginning of the string (unless `not_bol' is set in `bufp'), and, if `newline_anchor' is set, after newlines. */ - case begline: + CASE (begline): DEBUG_PRINT1 ("EXECUTING begline.\n"); if (AT_STRINGS_BEG (d)) { - if (!bufp->not_bol) break; + if (!bufp->not_bol) + { + NEXT; + } } else if (d[-1] == '\n' && bufp->newline_anchor) { - break; + NEXT; } /* In all other cases, we fail. */ goto fail; /* endline is the dual of begline. */ - case endline: + CASE (endline): DEBUG_PRINT1 ("EXECUTING endline.\n"); if (AT_STRINGS_END (d)) { - if (!bufp->not_eol) break; + if (!bufp->not_eol) + { + NEXT; + } } /* We have to ``prefetch'' the next character. */ else if ((d == end1 ? *string2 : *d) == '\n' && bufp->newline_anchor) { - break; + NEXT; } goto fail; /* Match at the very beginning of the data. */ - case begbuf: + CASE (begbuf): DEBUG_PRINT1 ("EXECUTING begbuf.\n"); if (AT_STRINGS_BEG (d)) - break; + { + NEXT; + } goto fail; /* Match at the very end of the data. */ - case endbuf: + CASE (endbuf): DEBUG_PRINT1 ("EXECUTING endbuf.\n"); if (AT_STRINGS_END (d)) - break; + { + NEXT; + } goto fail; @@ -6641,7 +6967,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) stack at all is that otherwise we would have to change `anychar's code to do something besides goto fail in this case; that seems worse than this. */ - case on_failure_keep_string_jump: + CASE (on_failure_keep_string_jump): DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); @@ -6652,7 +6978,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) #endif PUSH_FAILURE_POINT (p + mcnt, NULL, -2); - break; + NEXT; /* Uses of on_failure_jump: @@ -6667,7 +6993,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) Repeats start with an on_failure_jump that points past both the repetition text and either the following jump or pop_failure_jump back to this on_failure_jump. */ - case on_failure_jump: + CASE (on_failure_jump): on_failure: DEBUG_PRINT1 ("EXECUTING on_failure_jump"); @@ -6709,16 +7035,16 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) DEBUG_PRINT1 (":\n"); PUSH_FAILURE_POINT (p + mcnt, d, -2); - break; + NEXT; /* A smart repeat ends with `maybe_pop_jump'. We change it to either `pop_failure_jump' or `jump'. */ - case maybe_pop_jump: + CASE (maybe_pop_jump): EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); { - register US_CHAR_TYPE *p2 = p; + register UCHAR_T *p2 = p; /* Compare the beginning of the repeat with what in the pattern follows its end. If we can establish that there @@ -6761,7 +7087,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) /* Consider what happens when matching ":\(.*\)" against ":/". I don't really understand this code yet. */ - p[-(1+OFFSET_ADDRESS_SIZE)] = (US_CHAR_TYPE) + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) pop_failure_jump; DEBUG_PRINT1 (" End of pattern: change to `pop_failure_jump'.\n"); @@ -6773,8 +7099,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) #endif || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) { - register US_CHAR_TYPE c - = *p2 == (US_CHAR_TYPE) endline ? '\n' : p2[2]; + register UCHAR_T c + = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn #ifdef MBS_SUPPORT @@ -6782,21 +7108,20 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) #endif ) && p1[3+OFFSET_ADDRESS_SIZE] != c) { - p[-(1+OFFSET_ADDRESS_SIZE)] = (US_CHAR_TYPE) + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) pop_failure_jump; -#ifdef MBS_SUPPORT - if (MB_CUR_MAX != 1) +#ifdef WCHAR DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", (wint_t) c, (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); - else -#endif +#else DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", (char) c, (char) p1[3+OFFSET_ADDRESS_SIZE]); +#endif } -#ifndef MBS_SUPPORT +#ifndef WCHAR else if ((re_opcode_t) p1[3] == charset || (re_opcode_t) p1[3] == charset_not) { @@ -6814,9 +7139,9 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } } -#endif /* not MBS_SUPPORT */ +#endif /* not WCHAR */ } -#ifndef MBS_SUPPORT +#ifndef WCHAR else if ((re_opcode_t) *p2 == charset) { /* We win if the first character of the loop is not part @@ -6865,12 +7190,12 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) } } } -#endif /* not MBS_SUPPORT */ +#endif /* not WCHAR */ } p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ if ((re_opcode_t) p[-1] != pop_failure_jump) { - p[-1] = (US_CHAR_TYPE) jump; + p[-1] = (UCHAR_T) jump; DEBUG_PRINT1 (" Match => jump.\n"); goto unconditional_jump; } @@ -6883,7 +7208,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) points put on by this pop_failure_jump's matching on_failure_jump; we got through the pattern to here from the matching on_failure_jump, so didn't fail. */ - case pop_failure_jump: + CASE (pop_failure_jump): { /* We need to pass separate storage for the lowest and highest registers, even though we don't care about the @@ -6891,8 +7216,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) register from the stack, since lowest will == highest in `pop_failure_point'. */ active_reg_t dummy_low_reg, dummy_high_reg; - US_CHAR_TYPE *pdummy = NULL; - const CHAR_TYPE *sdummy = NULL; + UCHAR_T *pdummy = NULL; + const CHAR_T *sdummy = NULL; DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); POP_FAILURE_POINT (sdummy, pdummy, @@ -6910,7 +7235,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) /* Note fall through. */ /* Unconditionally jump (without popping any failure points). */ - case jump: + CASE (jump): EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); p += mcnt; /* Do the jump. */ @@ -6919,12 +7244,12 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) #else DEBUG_PRINT2 ("(to 0x%x).\n", p); #endif - break; + NEXT; /* We need this opcode so we can detect where alternatives end in `group_match_null_string_p' et al. */ - case jump_past_alt: + CASE (jump_past_alt): DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); goto unconditional_jump; @@ -6934,7 +7259,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) pop_failure_jump, also, and with a pattern of, say, `a+', we are skipping over the on_failure_jump, so we have to push something meaningless for pop_failure_jump to pop. */ - case dummy_failure_jump: + CASE (dummy_failure_jump): DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); /* It doesn't matter what we push for the string here. What the code at `fail' tests is the value for the pattern. */ @@ -6947,16 +7272,16 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) we don't want the failure point for the alternative to be popped. For example, matching `(a|ab)*' against `aab' requires that we match the `ab' alternative. */ - case push_dummy_failure: + CASE (push_dummy_failure): DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); /* See comments just above at `dummy_failure_jump' about the two zeroes. */ PUSH_FAILURE_POINT (NULL, NULL, -2); - break; + NEXT; /* Have to succeed matching what follows at least n times. After that, handle like `on_failure_jump'. */ - case succeed_n: + CASE (succeed_n): EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); @@ -6985,17 +7310,17 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) p + OFFSET_ADDRESS_SIZE); #endif /* _LIBC */ -#ifdef MBS_SUPPORT - p[1] = (US_CHAR_TYPE) no_op; +#ifdef WCHAR + p[1] = (UCHAR_T) no_op; #else - p[2] = (US_CHAR_TYPE) no_op; - p[3] = (US_CHAR_TYPE) no_op; -#endif /* MBS_SUPPORT */ + p[2] = (UCHAR_T) no_op; + p[3] = (UCHAR_T) no_op; +#endif /* WCHAR */ goto on_failure; } - break; + NEXT; - case jump_n: + CASE (jump_n): EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); @@ -7017,9 +7342,9 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) /* If don't have to jump any more, skip over the rest of command. */ else p += 2 * OFFSET_ADDRESS_SIZE; - break; + NEXT; - case set_number_at: + CASE (set_number_at): { DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); @@ -7032,7 +7357,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); #endif STORE_NUMBER (p1, mcnt); - break; + NEXT; } #if 0 @@ -7041,34 +7366,40 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) AT_WORD_BOUNDARY, so this code is disabled. Expanding the macro and introducing temporary variables works around the bug. */ - case wordbound: + CASE (wordbound): DEBUG_PRINT1 ("EXECUTING wordbound.\n"); if (AT_WORD_BOUNDARY (d)) - break; + { + NEXT; + } goto fail; - case notwordbound: + CASE (notwordbound): DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); if (AT_WORD_BOUNDARY (d)) goto fail; - break; + NEXT; #else - case wordbound: + CASE (wordbound): { boolean prevchar, thischar; DEBUG_PRINT1 ("EXECUTING wordbound.\n"); if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) - break; + { + NEXT; + } prevchar = WORDCHAR_P (d - 1); thischar = WORDCHAR_P (d); if (prevchar != thischar) - break; + { + NEXT; + } goto fail; } - case notwordbound: + CASE (notwordbound): { boolean prevchar, thischar; @@ -7080,48 +7411,53 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) thischar = WORDCHAR_P (d); if (prevchar != thischar) goto fail; - break; + NEXT; } #endif - case wordbeg: + CASE (wordbeg): DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); - if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) - break; + if (!AT_STRINGS_END (d) && WORDCHAR_P (d) + && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + { + NEXT; + } goto fail; - case wordend: + CASE (wordend): DEBUG_PRINT1 ("EXECUTING wordend.\n"); if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) - && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) - break; + && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) + { + NEXT; + } goto fail; #ifdef emacs - case before_dot: + CASE (before_dot): DEBUG_PRINT1 ("EXECUTING before_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) >= point) goto fail; - break; + NEXT; - case at_dot: + CASE (at_dot): DEBUG_PRINT1 ("EXECUTING at_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) != point) goto fail; - break; + NEXT; - case after_dot: + CASE (after_dot): DEBUG_PRINT1 ("EXECUTING after_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) <= point) goto fail; - break; + NEXT; - case syntaxspec: + CASE (syntaxspec): DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); mcnt = *p++; goto matchsyntax; - case wordchar: + CASE (wordchar): DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); mcnt = (int) Sword; matchsyntax: @@ -7131,14 +7467,14 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); - break; + NEXT; - case notsyntaxspec: + CASE (notsyntaxspec): DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); mcnt = *p++; goto matchnotsyntax; - case notwordchar: + CASE (notwordchar): DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); mcnt = (int) Sword; matchnotsyntax: @@ -7148,32 +7484,34 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); - break; + NEXT; #else /* not emacs */ - case wordchar: + CASE (wordchar): DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); PREFETCH (); if (!WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; - break; + NEXT; - case notwordchar: + CASE (notwordchar): DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); PREFETCH (); if (WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; - break; + NEXT; #endif /* not emacs */ +#ifndef __GNUC__ default: abort (); } continue; /* Successfully executed one pattern command; keep going. */ +#endif /* We goto here if a matching operation fails. */ @@ -7247,13 +7585,12 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) We don't handle duplicates properly (yet). */ static boolean -group_match_null_string_p (p, end, reg_info) - US_CHAR_TYPE **p, *end; - register_info_type *reg_info; +PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) { int mcnt; /* Point to after the args to the start_memory. */ - US_CHAR_TYPE *p1 = *p + 2; + UCHAR_T *p1 = *p + 2; while (p1 < end) { @@ -7298,7 +7635,7 @@ group_match_null_string_p (p, end, reg_info) is, including the ending `jump_past_alt' and its number. */ - if (!alt_match_null_string_p (p1, p1 + mcnt - + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - (1 + OFFSET_ADDRESS_SIZE), reg_info)) return false; @@ -7330,7 +7667,7 @@ group_match_null_string_p (p, end, reg_info) the length of the alternative. */ EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); - if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) return false; p1 += mcnt; /* Get past the n-th alternative. */ @@ -7345,7 +7682,7 @@ group_match_null_string_p (p, end, reg_info) default: - if (!common_op_match_null_string_p (&p1, end, reg_info)) + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) return false; } } /* while p1 < end */ @@ -7359,12 +7696,11 @@ group_match_null_string_p (p, end, reg_info) byte past the last. The alternative can contain groups. */ static boolean -alt_match_null_string_p (p, end, reg_info) - US_CHAR_TYPE *p, *end; - register_info_type *reg_info; +PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) { int mcnt; - US_CHAR_TYPE *p1 = p; + UCHAR_T *p1 = p; while (p1 < end) { @@ -7381,7 +7717,7 @@ alt_match_null_string_p (p, end, reg_info) break; default: - if (!common_op_match_null_string_p (&p1, end, reg_info)) + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) return false; } } /* while p1 < end */ @@ -7396,14 +7732,13 @@ alt_match_null_string_p (p, end, reg_info) Sets P to one after the op and its arguments, if any. */ static boolean -common_op_match_null_string_p (p, end, reg_info) - US_CHAR_TYPE **p, *end; - register_info_type *reg_info; +PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) { int mcnt; boolean ret; int reg_no; - US_CHAR_TYPE *p1 = *p; + UCHAR_T *p1 = *p; switch ((re_opcode_t) *p1++) { @@ -7426,7 +7761,7 @@ common_op_match_null_string_p (p, end, reg_info) case start_memory: reg_no = *p1; assert (reg_no > 0 && reg_no <= MAX_REGNUM); - ret = group_match_null_string_p (&p1, end, reg_info); + ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); /* Have to set this here in case we're checking a group which contains a group and a back reference to it. */ @@ -7484,27 +7819,29 @@ common_op_match_null_string_p (p, end, reg_info) bytes; nonzero otherwise. */ static int -bcmp_translate (s1, s2, len, translate) - const CHAR_TYPE *s1, *s2; - register int len; - RE_TRANSLATE_TYPE translate; +PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, + register int len, + RE_TRANSLATE_TYPE translate) { - register const US_CHAR_TYPE *p1 = (const US_CHAR_TYPE *) s1; - register const US_CHAR_TYPE *p2 = (const US_CHAR_TYPE *) s2; + register const UCHAR_T *p1 = (const UCHAR_T *) s1; + register const UCHAR_T *p2 = (const UCHAR_T *) s2; while (len) { -#ifdef MBS_SUPPORT +#ifdef WCHAR if (((*p1<=0xff)?translate[*p1++]:*p1++) != ((*p2<=0xff)?translate[*p2++]:*p2++)) return 1; -#else +#else /* BYTE */ if (translate[*p1++] != translate[*p2++]) return 1; -#endif /* MBS_SUPPORT */ +#endif /* WCHAR */ len--; } return 0; } + +#else /* not INSIDE_RECURSION */ + /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it @@ -7517,10 +7854,9 @@ bcmp_translate (s1, s2, len, translate) We call regex_compile to do the actual compilation. */ const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - size_t length; - struct re_pattern_buffer *bufp; +re_compile_pattern (const char *pattern, + size_t length, + struct re_pattern_buffer *bufp) { reg_errcode_t ret; @@ -7536,7 +7872,12 @@ re_compile_pattern (pattern, length, bufp) /* Match anchors at newline. */ bufp->newline_anchor = 1; - ret = regex_compile (pattern, length, re_syntax_options, bufp); +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); + else +# endif + ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); if (!ret) return NULL; @@ -7561,27 +7902,26 @@ char * regcomp/regexec below without link errors. */ weak_function #endif -re_comp (s) - const char *s; +re_comp (const char *s) { reg_errcode_t ret; if (!s) { if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); + return (char *) gettext ("No previous regular expression"); return 0; } if (!re_comp_buf.buffer) { - re_comp_buf.buffer = (unsigned char *) malloc (200); + re_comp_buf.buffer = malloc (200); if (re_comp_buf.buffer == NULL) return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) REG_ESPACE]); re_comp_buf.allocated = 200; - re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + re_comp_buf.fastmap = malloc (1 << BYTEWIDTH); if (re_comp_buf.fastmap == NULL) return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) REG_ESPACE]); @@ -7593,7 +7933,12 @@ re_comp (s) /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; - ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + else +# endif + ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); if (!ret) return NULL; @@ -7607,12 +7952,11 @@ int #ifdef _LIBC weak_function #endif -re_exec (s) - const char *s; +re_exec (const char *s) { const int len = strlen (s); return - 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); + 0 <= re_search (&re_comp_buf, s, len, 0, len, 0); } #endif /* _REGEX_RE_COMP */ @@ -7657,10 +8001,7 @@ re_exec (s) the return codes and their meanings.) */ int -regcomp (preg, pattern, cflags) - regex_t *preg; - const char *pattern; - int cflags; +regcomp (regex_t *preg, const char *pattern, int cflags) { reg_errcode_t ret; reg_syntax_t syntax @@ -7673,15 +8014,14 @@ regcomp (preg, pattern, cflags) preg->used = 0; /* Try to allocate space for the fastmap. */ - preg->fastmap = (char *) malloc (1 << BYTEWIDTH); + preg->fastmap = malloc (1 << BYTEWIDTH); if (cflags & REG_ICASE) { unsigned i; - preg->translate - = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE - * sizeof (*(RE_TRANSLATE_TYPE)0)); + preg->translate = malloc (CHAR_SET_SIZE + * sizeof (*(RE_TRANSLATE_TYPE)0)); if (preg->translate == NULL) return (int) REG_ESPACE; @@ -7707,7 +8047,12 @@ regcomp (preg, pattern, cflags) /* POSIX says a null character in the pattern terminates it, so we can use strlen here in compiling the pattern. */ - ret = regex_compile (pattern, strlen (pattern), syntax, preg); +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); + else +# endif + ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ @@ -7748,12 +8093,8 @@ weak_alias (__regcomp, regcomp) We return 0 if we find a match and REG_NOMATCH if not. */ int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *preg; - const char *string; - size_t nmatch; - regmatch_t pmatch[]; - int eflags; +regexec (const regex_t *preg, const char *string, + size_t nmatch, regmatch_t pmatch[], int eflags) { int ret; struct re_registers regs; @@ -7783,7 +8124,7 @@ regexec (preg, string, nmatch, pmatch, eflags) /* Perform the searching operation. */ ret = re_search (&private_preg, string, len, /* start: */ 0, /* range: */ len, - want_reg_info ? ®s : (struct re_registers *) 0); + want_reg_info ? ®s : 0); /* Copy the register information to the POSIX structure. */ if (want_reg_info) @@ -7815,11 +8156,7 @@ weak_alias (__regexec, regexec) from either regcomp or regexec. We don't use PREG here. */ size_t -regerror (errcode, preg, errbuf, errbuf_size) - int errcode; - const regex_t *preg; - char *errbuf; - size_t errbuf_size; +regerror (int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { const char *msg; size_t msg_size; @@ -7862,8 +8199,7 @@ weak_alias (__regerror, regerror) /* Free dynamically allocated space used by PREG. */ void -regfree (preg) - regex_t *preg; +regfree (regex_t *preg) { if (preg->buffer != NULL) free (preg->buffer); @@ -7886,3 +8222,74 @@ weak_alias (__regfree, regfree) #endif #endif /* not emacs */ + +#endif /* not INSIDE_RECURSION */ + + +#undef STORE_NUMBER +#undef STORE_NUMBER_AND_INCR +#undef EXTRACT_NUMBER +#undef EXTRACT_NUMBER_AND_INCR + +#undef DEBUG_PRINT_COMPILED_PATTERN +#undef DEBUG_PRINT_DOUBLE_STRING + +#undef INIT_FAIL_STACK +#undef RESET_FAIL_STACK +#undef DOUBLE_FAIL_STACK +#undef PUSH_PATTERN_OP +#undef PUSH_FAILURE_POINTER +#undef PUSH_FAILURE_INT +#undef PUSH_FAILURE_ELT +#undef POP_FAILURE_POINTER +#undef POP_FAILURE_INT +#undef POP_FAILURE_ELT +#undef DEBUG_PUSH +#undef DEBUG_POP +#undef PUSH_FAILURE_POINT +#undef POP_FAILURE_POINT + +#undef REG_UNSET_VALUE +#undef REG_UNSET + +#undef PATFETCH +#undef PATFETCH_RAW +#undef PATUNFETCH +#undef TRANSLATE + +#undef INIT_BUF_SIZE +#undef GET_BUFFER_SPACE +#undef BUF_PUSH +#undef BUF_PUSH_2 +#undef BUF_PUSH_3 +#undef STORE_JUMP +#undef STORE_JUMP2 +#undef INSERT_JUMP +#undef INSERT_JUMP2 +#undef EXTEND_BUFFER +#undef GET_UNSIGNED_NUMBER +#undef FREE_STACK_RETURN + +# undef POINTER_TO_OFFSET +# undef MATCHING_IN_FRST_STRING +# undef PREFETCH +# undef AT_STRINGS_BEG +# undef AT_STRINGS_END +# undef WORDCHAR_P +# undef FREE_VAR +# undef FREE_VARIABLES +# undef NO_HIGHEST_ACTIVE_REG +# undef NO_LOWEST_ACTIVE_REG + +# undef CHAR_T +# undef UCHAR_T +# undef COMPILED_BUFFER_VAR +# undef OFFSET_ADDRESS_SIZE +# undef CHAR_CLASS_SIZE +# undef PREFIX +# undef ARG_PREFIX +# undef PUT_CHAR +# undef BYTE +# undef WCHAR + +# define DEFINED_ONCE diff --git a/mailbox/strchrnul.c b/mailbox/strchrnul.c index c85cfc5..be85312 100644 --- a/mailbox/strchrnul.c +++ b/mailbox/strchrnul.c @@ -1,163 +1,30 @@ -/* Copyright (C) 1991,93,94,95,96,97,99,2000, 2001 Free Software Foundation, Inc. - Based on strlen implementation by Torbjorn Granlund (tege@sics.se), - with help from Dan Sahlin (dan@sics.se) and - bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); - adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), - and implemented by Roland McGrath (roland@ai.mit.edu). +/* Searching in a string. + Copyright (C) 2003 Free Software Foundation, Inc. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <string.h> -#include <stdlib.h> +/* Specification. */ +#include "strchrnul.h" /* Find the first occurrence of C in S or the final NUL byte. */ char * -strchrnul (s, c_in) - const char *s; - int c_in; +strchrnul (const char *s, int c_in) { - const char *char_ptr; - const unsigned long int *longword_ptr; - unsigned long int longword, magic_bits, charmask; - unsigned char c; + char c = c_in; + while (*s && (*s != c)) + s++; - c = (unsigned char) c_in; - - /* Handle the first few characters by reading one character at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = s; ((unsigned long int) char_ptr - & (sizeof (longword) - 1)) != 0; - ++char_ptr) - if (*char_ptr == c || *char_ptr == '\0') - return (void *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to 8-byte longwords. */ - - longword_ptr = (unsigned long int *) char_ptr; - - /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits - the "holes." Note that there is a hole just to the left of - each byte, with an extra at the end: - - bits: 01111110 11111110 11111110 11111111 - bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD - - The 1-bits make sure that carries propagate to the next 0-bit. - The 0-bits provide holes for carries to fall into. */ - switch (sizeof (longword)) - { - case 4: magic_bits = 0x7efefeffL; break; - case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; - default: - abort (); - } - - /* Set up a longword, each of whose bytes is C. */ - charmask = c | (c << 8); - charmask |= charmask << 16; - if (sizeof (longword) > 4) - /* Do the shift in two steps to avoid a warning if long has 32 bits. */ - charmask |= (charmask << 16) << 16; - if (sizeof (longword) > 8) - abort (); - - /* Instead of the traditional loop which tests each character, - we will test a longword at a time. The tricky part is testing - if *any of the four* bytes in the longword in question are zero. */ - for (;;) - { - /* We tentatively exit the loop if adding MAGIC_BITS to - LONGWORD fails to change any of the hole bits of LONGWORD. - - 1) Is this safe? Will it catch all the zero bytes? - Suppose there is a byte with all zeros. Any carry bits - propagating from its left will fall into the hole at its - least significant bit and stop. Since there will be no - carry from its most significant bit, the LSB of the - byte to the left will be unchanged, and the zero will be - detected. - - 2) Is this worthwhile? Will it ignore everything except - zero bytes? Suppose every byte of LONGWORD has a bit set - somewhere. There will be a carry into bit 8. If bit 8 - is set, this will carry into bit 16. If bit 8 is clear, - one of bits 9-15 must be set, so there will be a carry - into bit 16. Similarly, there will be a carry into bit - 24. If one of bits 24-30 is set, there will be a carry - into bit 31, so all of the hole bits will be changed. - - The one misfire occurs when bits 24-30 are clear and bit - 31 is set; in this case, the hole at bit 31 is not - changed. If we had access to the processor carry flag, - we could close this loophole by putting the fourth hole - at bit 32! - - So it ignores everything except 128's, when they're aligned - properly. - - 3) But wait! Aren't we looking for C as well as zero? - Good point. So what we do is XOR LONGWORD with a longword, - each of whose bytes is C. This turns each byte that is C - into a zero. */ - - longword = *longword_ptr++; - - /* Add MAGIC_BITS to LONGWORD. */ - if ((((longword + magic_bits) - - /* Set those bits that were unchanged by the addition. */ - ^ ~longword) - - /* Look at only the hole bits. If any of the hole bits - are unchanged, most likely one of the bytes was a - zero. */ - & ~magic_bits) != 0 || - - /* That caught zeroes. Now test for C. */ - ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) - & ~magic_bits) != 0) - { - /* Which of the bytes was C or zero? - If none of them were, it was a misfire; continue the search. */ - - const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); - - if (*cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (sizeof (longword) > 4) - { - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - } - } - } - - /* This should never happen. */ - return NULL; + return (char *) s; } diff --git a/mailbox/strndup.c b/mailbox/strndup.c index b889133..f85627e 100644 --- a/mailbox/strndup.c +++ b/mailbox/strndup.c @@ -1,46 +1,55 @@ -/* Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. +/* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@prep.ai.mit.edu. - The GNU C Library is distributed in the hope that it will be useful, + 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, 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include <stdio.h> -#include <sys/types.h> +#include <stdlib.h> +#include <string.h> + +#ifndef HAVE_DECL_STRNLEN +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_STRNLEN +size_t strnlen (); +#endif + +#undef __strndup +#undef strndup -#if defined _LIBC || defined STDC_HEADERS -# include <stdlib.h> -# include <string.h> -#else -char *malloc (); +#ifndef weak_alias +# define __strndup strndup #endif char * -strndup (s, n) - const char *s; - size_t n; +__strndup (const char *s, size_t n) { size_t len = strnlen (s, n); - char *nouveau = malloc (len + 1); + char *new = malloc (len + 1); - if (nouveau == NULL) + if (new == NULL) return NULL; - nouveau[len] = '\0'; - return (char *) memcpy (nouveau, s, len); + new[len] = '\0'; + return memcpy (new, s, len); } +#ifdef weak_alias +weak_alias (__strndup, strndup) +#endif diff --git a/mailbox/strnlen.c b/mailbox/strnlen.c index ecc9df3..c9f3898 100644 --- a/mailbox/strnlen.c +++ b/mailbox/strnlen.c @@ -1,30 +1,48 @@ /* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2000-2003 Free Software Foundation, Inc. This file is part of the GNU C Library. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif +#undef strnlen #include <string.h> +#undef __strnlen +#undef strnlen + +#ifndef _LIBC +# define strnlen rpl_strnlen +#endif + +#ifndef weak_alias +# define __strnlen strnlen +#endif + /* Find the length of STRING, but scan at most MAXLEN characters. If no '\0' terminator is found in that many characters, return MAXLEN. */ size_t -strnlen (const char *string, size_t maxlen) +__strnlen (const char *string, size_t maxlen) { const char *end = memchr (string, '\0', maxlen); return end ? (size_t) (end - string) : maxlen; } +#ifdef weak_alias +weak_alias (__strnlen, strnlen) +#endif diff --git a/mailbox/strtok_r.c b/mailbox/strtok_r.c index cd9eed3..6b38083 100644 --- a/mailbox/strtok_r.c +++ b/mailbox/strtok_r.c @@ -1,24 +1,37 @@ /* Reentrant string tokenizer. Generic version. - Copyright (C) 1991, 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 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, or (at your option) + any later version. - The GNU C Library is distributed in the hope that it will be useful, + 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 - Library General Public License for more details. + 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif #include <string.h> +#undef strtok_r +#undef __strtok_r + +#ifndef _LIBC +/* Get specification. */ +# include "strtok_r.h" +# define __strtok_r strtok_r +# define __rawmemchr strchr +#endif + /* Parse S into tokens separated by characters in DELIM. If S is NULL, the saved pointer in SAVE_PTR is used as the next starting point. For example: @@ -30,10 +43,7 @@ // s = "abc\0-def\0" */ char * -strtok_r (s, delim, save_ptr) - char *s; - const char *delim; - char **save_ptr; +__strtok_r (char *s, const char *delim, char **save_ptr) { char *token; @@ -53,8 +63,7 @@ strtok_r (s, delim, save_ptr) s = strpbrk (token, delim); if (s == NULL) /* This token finishes the string. */ - /* *save_ptr = __rawmemchr (token, '\0'); */ - *save_ptr = token + strlen (token); + *save_ptr = __rawmemchr (token, '\0'); else { /* Terminate the token and make *SAVE_PTR point past it. */ @@ -63,4 +72,7 @@ strtok_r (s, delim, save_ptr) } return token; } -/* weak_alias (__strtok_r, strtok_r) */ +#ifdef weak_alias +libc_hidden_def (__strtok_r) +weak_alias (__strtok_r, strtok_r) +#endif -- libgit2 0.24.0