Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | From 2a5d7bcf0ff791c95ee1388772408a1bf4454694 Mon Sep 17 00:00:00 2001 |
| 2 | From: Khem Raj <raj.khem@gmail.com> |
| 3 | Date: Wed, 18 Mar 2015 01:33:49 +0000 |
| 4 | Subject: [PATCH 24/27] eglibc: Forward port eglibc options groups support |
| 5 | |
| 6 | Upstream-Status: Pending |
| 7 | |
| 8 | Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| 9 | --- |
| 10 | Makeconfig | 20 +- |
| 11 | Makerules | 19 + |
| 12 | argp/Makefile | 2 + |
| 13 | argp/argp-fmtstream.c | 25 +- |
| 14 | argp/argp-help.c | 13 +- |
| 15 | argp/argp-namefrob.h | 2 + |
| 16 | catgets/Makefile | 17 +- |
| 17 | crypt/Makefile | 20 +- |
| 18 | crypt/crypt-entry.c | 13 + |
| 19 | crypt/crypt_common.c | 42 + |
| 20 | crypt/crypt_util.c | 18 - |
| 21 | csu/Makefile | 2 + |
| 22 | debug/Makefile | 41 +- |
| 23 | debug/segfault.c | 11 +- |
| 24 | debug/tst-chk1.c | 7 + |
| 25 | dlfcn/Makefile | 7 +- |
| 26 | elf/dl-support.c | 3 + |
| 27 | elf/rtld.c | 17 +- |
| 28 | extra-lib.mk | 6 +- |
| 29 | grp/Makefile | 5 + |
| 30 | hesiod/Makefile | 6 +- |
| 31 | iconv/Makefile | 7 + |
| 32 | iconv/gconv_db.c | 3 + |
| 33 | iconv/gconv_trans.c | 7 + |
| 34 | iconv/iconv_prog.c | 8 + |
| 35 | iconvdata/Makefile | 27 +- |
| 36 | include/netdb.h | 4 + |
| 37 | inet/Makefile | 22 +- |
| 38 | intl/Makefile | 3 +- |
| 39 | intl/dcigettext.c | 39 +- |
| 40 | io/Makefile | 18 +- |
| 41 | libidn/Makefile | 5 +- |
| 42 | libidn/toutf8.c | 11 +- |
| 43 | libio/Makefile | 66 +- |
| 44 | libio/__fpurge.c | 2 +- |
| 45 | libio/fileops.c | 10 +- |
| 46 | libio/iofwide.c | 26 + |
| 47 | libio/ioseekoff.c | 2 +- |
| 48 | libio/ioseekpos.c | 2 +- |
| 49 | libio/iosetbuffer.c | 4 + |
| 50 | libio/libioP.h | 18 +- |
| 51 | libio/wdummyfileops.c | 161 + |
| 52 | locale/C-ctype.c | 20 + |
| 53 | locale/Makefile | 41 +- |
| 54 | locale/catnames.c | 48 + |
| 55 | locale/dummy-setlocale.c | 33 + |
| 56 | locale/localeinfo.h | 2 +- |
| 57 | locale/programs/charmap-dir.c | 6 + |
| 58 | locale/programs/ld-collate.c | 17 +- |
| 59 | locale/programs/ld-ctype.c | 27 +- |
| 60 | locale/programs/ld-messages.c | 5 + |
| 61 | locale/programs/ld-time.c | 31 +- |
| 62 | locale/programs/linereader.c | 2 +- |
| 63 | locale/programs/localedef.c | 8 + |
| 64 | locale/programs/locfile.c | 5 +- |
| 65 | locale/programs/locfile.h | 59 +- |
| 66 | locale/setlocale.c | 30 - |
| 67 | locale/xlocale.c | 37 + |
| 68 | localedata/Makefile | 35 +- |
| 69 | login/Makefile | 17 +- |
| 70 | malloc/Makefile | 10 +- |
| 71 | malloc/memusage.c | 7 +- |
| 72 | malloc/memusage.sh | 2 +- |
| 73 | math/Makefile | 6 +- |
| 74 | misc/Makefile | 25 +- |
| 75 | misc/err.c | 11 + |
| 76 | misc/error.c | 5 + |
| 77 | misc/tst-efgcvt.c | 2 +- |
| 78 | nis/Makefile | 31 +- |
| 79 | nptl/Makefile | 28 +- |
| 80 | nptl/pthread_create.c | 5 + |
| 81 | nscd/Makefile | 33 +- |
| 82 | nscd/nis_hash.c | 3 + |
| 83 | nss/Makefile | 67 +- |
| 84 | nss/fixed-nsswitch.conf | 22 + |
| 85 | nss/fixed-nsswitch.functions | 121 + |
| 86 | nss/gen-fixed-nsswitch.c | 803 +++ |
| 87 | nss/getent.c | 46 +- |
| 88 | nss/getnssent_r.c | 9 +- |
| 89 | nss/nsswitch.c | 109 +- |
| 90 | nss/nsswitch.h | 18 +- |
| 91 | posix/Makefile | 94 +- |
| 92 | posix/bug-regex1.c | 3 + |
| 93 | posix/bug-regex6.c | 8 +- |
| 94 | posix/fnmatch.c | 6 +- |
| 95 | posix/fnmatch_loop.c | 23 +- |
| 96 | posix/glob.c | 15 +- |
| 97 | posix/regcomp.c | 98 +- |
| 98 | posix/regex.h | 11 + |
| 99 | posix/regex_internal.c | 45 +- |
| 100 | posix/regex_internal.h | 23 +- |
| 101 | posix/regexec-compat.c | 39 + |
| 102 | posix/regexec.c | 71 +- |
| 103 | posix/xregex.c | 8215 +++++++++++++++++++++++++++++++ |
| 104 | pwd/Makefile | 2 + |
| 105 | resolv/Makefile | 21 +- |
| 106 | stdio-common/Makefile | 35 +- |
| 107 | stdio-common/_i18n_number.h | 13 + |
| 108 | stdio-common/fxprintf.c | 5 + |
| 109 | stdio-common/printf_fp.c | 22 + |
| 110 | stdio-common/printf_fphex.c | 13 + |
| 111 | stdio-common/printf_size.c | 8 + |
| 112 | stdio-common/scanf14.c | 3 + |
| 113 | stdio-common/tst-popen.c | 3 + |
| 114 | stdio-common/tst-sprintf.c | 4 +- |
| 115 | stdio-common/tstdiomisc.c | 5 + |
| 116 | stdio-common/vfprintf.c | 31 +- |
| 117 | stdio-common/vfscanf.c | 53 +- |
| 118 | stdlib/Makefile | 34 +- |
| 119 | stdlib/strtod_l.c | 13 + |
| 120 | stdlib/tst-strtod.c | 5 + |
| 121 | streams/Makefile | 5 +- |
| 122 | string/Makefile | 14 +- |
| 123 | string/strcoll_l.c | 5 + |
| 124 | string/strerror_l.c | 5 + |
| 125 | string/strxfrm_l.c | 5 + |
| 126 | string/test-strcmp.c | 28 - |
| 127 | string/tst-strxfrm.c | 3 + |
| 128 | string/tst-strxfrm2.c | 3 + |
| 129 | sunrpc/Makefile | 44 +- |
| 130 | sysdeps/arm/Makefile | 5 +- |
| 131 | sysdeps/generic/ldsodefs.h | 8 + |
| 132 | sysdeps/gnu/Makefile | 3 +- |
| 133 | sysdeps/ieee754/ldbl-opt/Makefile | 27 +- |
| 134 | sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 40 +- |
| 135 | sysdeps/ieee754/ldbl-opt/nldbl-compat.h | 24 +- |
| 136 | sysdeps/nptl/Makefile | 3 + |
| 137 | sysdeps/nptl/bits/libc-lock.h | 45 + |
| 138 | sysdeps/nptl/bits/libc-lockP.h | 50 +- |
| 139 | sysdeps/nptl/small-macros-fns.c | 72 + |
| 140 | sysdeps/unix/sysv/linux/gethostid.c | 6 + |
| 141 | sysdeps/unix/sysv/linux/libc_fatal.c | 3 + |
| 142 | time/Makefile | 18 +- |
| 143 | time/strftime_l.c | 12 +- |
| 144 | time/strptime_l.c | 14 +- |
| 145 | timezone/Makefile | 2 +- |
| 146 | wcsmbs/Makefile | 27 +- |
| 147 | wcsmbs/wcsmbsload.c | 13 + |
| 148 | wctype/Makefile | 14 +- |
| 149 | 139 files changed, 11363 insertions(+), 583 deletions(-) |
| 150 | create mode 100644 crypt/crypt_common.c |
| 151 | create mode 100644 libio/wdummyfileops.c |
| 152 | create mode 100644 locale/catnames.c |
| 153 | create mode 100644 locale/dummy-setlocale.c |
| 154 | create mode 100644 nscd/nis_hash.c |
| 155 | create mode 100644 nss/fixed-nsswitch.conf |
| 156 | create mode 100644 nss/fixed-nsswitch.functions |
| 157 | create mode 100644 nss/gen-fixed-nsswitch.c |
| 158 | create mode 100644 posix/regexec-compat.c |
| 159 | create mode 100644 posix/xregex.c |
| 160 | create mode 100644 sysdeps/nptl/small-macros-fns.c |
| 161 | |
| 162 | diff --git a/Makeconfig b/Makeconfig |
| 163 | index f136b88..52dae8f 100644 |
| 164 | --- a/Makeconfig |
| 165 | +++ b/Makeconfig |
| 166 | @@ -609,7 +609,7 @@ elf-objpfx = $(common-objpfx)elf/ |
| 167 | # and run on the build system, causes that program with those |
| 168 | # arguments to be run on the host for which the library is built. |
| 169 | ifndef test-wrapper |
| 170 | -test-wrapper = |
| 171 | +test-wrapper = $(cross-test-wrapper) |
| 172 | endif |
| 173 | # Likewise, but the name of the program is preceded by |
| 174 | # <variable>=<value> assignments for environment variables. |
| 175 | @@ -1089,6 +1089,24 @@ libm = $(common-objpfx)math/libm.a |
| 176 | libmvec = $(common-objpfx)mathvec/libmvec.a |
| 177 | endif |
| 178 | |
| 179 | +# Generate a header file that #defines preprocessor symbols indicating |
| 180 | +# which option groups are enabled. Note that the option-groups.config file |
| 181 | +# may not exist at all. |
| 182 | +before-compile += $(common-objpfx)gnu/option-groups.h |
| 183 | +common-generated += gnu/option-groups.h gnu/option-groups.stmp |
| 184 | +headers += gnu/option-groups.h |
| 185 | +$(common-objpfx)gnu/option-groups.h: $(common-objpfx)gnu/option-groups.stmp; @: |
| 186 | +$(common-objpfx)gnu/option-groups.stmp: \ |
| 187 | + $(..)scripts/option-groups.awk \ |
| 188 | + $(..)option-groups.defaults \ |
| 189 | + $(wildcard $(common-objpfx)option-groups.config) |
| 190 | + $(make-target-directory) |
| 191 | + @rm -f ${@:stmp=T} $@ |
| 192 | + LC_ALL=C $(AWK) -f $^ > ${@:stmp=T} |
| 193 | + $(move-if-change) ${@:stmp=T} ${@:stmp=h} |
| 194 | + touch $@ |
| 195 | + |
| 196 | + |
| 197 | # These are the subdirectories containing the library source. The order |
| 198 | # is more or less arbitrary. The sorting step will take care of the |
| 199 | # dependencies. |
| 200 | diff --git a/Makerules b/Makerules |
| 201 | index f9ca3f5..1dd41aa 100644 |
| 202 | --- a/Makerules |
| 203 | +++ b/Makerules |
| 204 | @@ -456,6 +456,25 @@ define sed-remove-objpfx |
| 205 | endef |
| 206 | endif |
| 207 | |
| 208 | +# Include targets in the selected option groups. |
| 209 | +aux += $(aux-y) |
| 210 | +extra-libs += $(extra-libs-y) |
| 211 | +extra-libs-others += $(extra-libs-others-y) |
| 212 | +extra-objs += $(extra-objs-y) |
| 213 | +install-bin += $(install-bin-y) |
| 214 | +install-others += $(install-others-y) |
| 215 | +install-sbin += $(install-sbin-y) |
| 216 | +modules += $(modules-y) |
| 217 | +others += $(others-y) |
| 218 | +others-pie += $(others-pie-y) |
| 219 | +routines += $(routines-y) |
| 220 | +static-only-routines += $(static-only-routines-y) |
| 221 | +sysdep_routines += $(sysdep_routines-y) |
| 222 | +test-srcs += $(test-srcs-y) |
| 223 | +tests += $(tests-y) |
| 224 | +xtests += $(xtests-y) |
| 225 | + |
| 226 | + |
| 227 | # Modify the list of routines we build for different targets |
| 228 | |
| 229 | ifeq (yes,$(build-shared)) |
| 230 | diff --git a/argp/Makefile b/argp/Makefile |
| 231 | index 1a87629..f7c1e40 100644 |
| 232 | --- a/argp/Makefile |
| 233 | +++ b/argp/Makefile |
| 234 | @@ -18,6 +18,8 @@ |
| 235 | # |
| 236 | # Makefile for argp. |
| 237 | # |
| 238 | +include ../option-groups.mak |
| 239 | + |
| 240 | subdir := argp |
| 241 | |
| 242 | include ../Makeconfig |
| 243 | diff --git a/argp/argp-fmtstream.c b/argp/argp-fmtstream.c |
| 244 | index 2b845e0..c344e7b 100644 |
| 245 | --- a/argp/argp-fmtstream.c |
| 246 | +++ b/argp/argp-fmtstream.c |
| 247 | @@ -42,6 +42,7 @@ |
| 248 | #ifdef _LIBC |
| 249 | # include <wchar.h> |
| 250 | # include <libio/libioP.h> |
| 251 | +# include <gnu/option-groups.h> |
| 252 | # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) |
| 253 | #endif |
| 254 | |
| 255 | @@ -100,7 +101,11 @@ __argp_fmtstream_free (argp_fmtstream_t fs) |
| 256 | __argp_fmtstream_update (fs); |
| 257 | if (fs->p > fs->buf) |
| 258 | { |
| 259 | +#ifdef _LIBC |
| 260 | __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); |
| 261 | +#else |
| 262 | + fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); |
| 263 | +#endif |
| 264 | } |
| 265 | free (fs->buf); |
| 266 | free (fs); |
| 267 | @@ -145,9 +150,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) |
| 268 | size_t i; |
| 269 | for (i = 0; i < pad; i++) |
| 270 | { |
| 271 | +#ifdef _LIBC |
| 272 | if (_IO_fwide (fs->stream, 0) > 0) |
| 273 | - putwc_unlocked (L' ', fs->stream); |
| 274 | + { |
| 275 | +#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 276 | + putwc_unlocked (L' ', fs->stream); |
| 277 | +#else |
| 278 | + abort (); |
| 279 | +#endif |
| 280 | + } |
| 281 | else |
| 282 | +#endif |
| 283 | putc_unlocked (' ', fs->stream); |
| 284 | } |
| 285 | } |
| 286 | @@ -308,9 +321,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) |
| 287 | *nl++ = ' '; |
| 288 | else |
| 289 | for (i = 0; i < fs->wmargin; ++i) |
| 290 | +#ifdef _LIBC |
| 291 | if (_IO_fwide (fs->stream, 0) > 0) |
| 292 | - putwc_unlocked (L' ', fs->stream); |
| 293 | + { |
| 294 | +#ifdef OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 295 | + putwc_unlocked (L' ', fs->stream); |
| 296 | +#else |
| 297 | + abort (); |
| 298 | +#endif |
| 299 | + } |
| 300 | else |
| 301 | +#endif |
| 302 | putc_unlocked (' ', fs->stream); |
| 303 | |
| 304 | /* Copy the tail of the original buffer into the current buffer |
| 305 | diff --git a/argp/argp-help.c b/argp/argp-help.c |
| 306 | index b055e45..6b3c4c1 100644 |
| 307 | --- a/argp/argp-help.c |
| 308 | +++ b/argp/argp-help.c |
| 309 | @@ -51,6 +51,7 @@ char *alloca (); |
| 310 | #ifdef _LIBC |
| 311 | # include <../libio/libioP.h> |
| 312 | # include <wchar.h> |
| 313 | +# include <gnu/option-groups.h> |
| 314 | #endif |
| 315 | |
| 316 | #ifndef _ |
| 317 | @@ -1702,7 +1703,7 @@ char *__argp_basename (char *name) |
| 318 | } |
| 319 | |
| 320 | char * |
| 321 | -__argp_short_program_name (void) |
| 322 | +(__argp_short_program_name) (void) |
| 323 | { |
| 324 | # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME |
| 325 | return program_invocation_short_name; |
| 326 | @@ -1873,9 +1874,17 @@ __argp_failure (const struct argp_state *state, int status, int errnum, |
| 327 | #endif |
| 328 | } |
| 329 | |
| 330 | +#ifdef _LIBC |
| 331 | if (_IO_fwide (stream, 0) > 0) |
| 332 | - putwc_unlocked (L'\n', stream); |
| 333 | + { |
| 334 | +#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 335 | + putwc_unlocked (L'\n', stream); |
| 336 | +#else |
| 337 | + abort (); |
| 338 | +#endif |
| 339 | + } |
| 340 | else |
| 341 | +#endif |
| 342 | putc_unlocked ('\n', stream); |
| 343 | |
| 344 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) |
| 345 | diff --git a/argp/argp-namefrob.h b/argp/argp-namefrob.h |
| 346 | index f67c58f..e2002dc 100644 |
| 347 | --- a/argp/argp-namefrob.h |
| 348 | +++ b/argp/argp-namefrob.h |
| 349 | @@ -76,10 +76,12 @@ |
| 350 | #undef __argp_fmtstream_wmargin |
| 351 | #define __argp_fmtstream_wmargin argp_fmtstream_wmargin |
| 352 | |
| 353 | +#if 0 |
| 354 | #include "mempcpy.h" |
| 355 | #include "strcase.h" |
| 356 | #include "strchrnul.h" |
| 357 | #include "strndup.h" |
| 358 | +#endif |
| 359 | |
| 360 | /* normal libc functions we call */ |
| 361 | #undef __flockfile |
| 362 | diff --git a/catgets/Makefile b/catgets/Makefile |
| 363 | index 4624a88..05714fd 100644 |
| 364 | --- a/catgets/Makefile |
| 365 | +++ b/catgets/Makefile |
| 366 | @@ -22,20 +22,23 @@ subdir := catgets |
| 367 | |
| 368 | include ../Makeconfig |
| 369 | |
| 370 | +include ../option-groups.mak |
| 371 | + |
| 372 | headers = nl_types.h |
| 373 | -routines = catgets open_catalog |
| 374 | -others = gencat |
| 375 | -install-bin = gencat |
| 376 | -extra-objs = $(gencat-modules:=.o) |
| 377 | +routines-$(OPTION_EGLIBC_CATGETS) := catgets open_catalog |
| 378 | +others-$(OPTION_EGLIBC_CATGETS) := gencat |
| 379 | +install-bin-$(OPTION_EGLIBC_CATGETS) := gencat |
| 380 | +extra-objs-$(OPTION_EGLIBC_CATGETS) := $(gencat-modules:=.o) |
| 381 | |
| 382 | -tests = tst-catgets |
| 383 | -test-srcs = test-gencat |
| 384 | +tests-$(OPTION_EGLIBC_CATGETS) := tst-catgets |
| 385 | +test-srcs-$(OPTION_EGLIBC_CATGETS) := test-gencat |
| 386 | |
| 387 | +ifeq (y,$(OPTION_EGLIBC_CATGETS)) |
| 388 | ifeq ($(run-built-tests),yes) |
| 389 | tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \ |
| 390 | $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out |
| 391 | endif |
| 392 | - |
| 393 | +endif |
| 394 | gencat-modules = xmalloc |
| 395 | |
| 396 | # To find xmalloc.c |
| 397 | diff --git a/crypt/Makefile b/crypt/Makefile |
| 398 | index 34c4dd7..7c18c88 100644 |
| 399 | --- a/crypt/Makefile |
| 400 | +++ b/crypt/Makefile |
| 401 | @@ -18,21 +18,25 @@ |
| 402 | # |
| 403 | # Sub-makefile for crypt() portion of the library. |
| 404 | # |
| 405 | +include ../option-groups.mak |
| 406 | + |
| 407 | subdir := crypt |
| 408 | |
| 409 | include ../Makeconfig |
| 410 | |
| 411 | headers := crypt.h |
| 412 | |
| 413 | -extra-libs := libcrypt |
| 414 | -extra-libs-others := $(extra-libs) |
| 415 | +extra-libs-$(OPTION_EGLIBC_CRYPT) := libcrypt |
| 416 | +extra-libs-others-y := $(extra-libs-y) |
| 417 | |
| 418 | -libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \ |
| 419 | - crypt_util |
| 420 | +libcrypt-routines :=crypt-entry md5-crypt sha256-crypt sha512-crypt crypt_common |
| 421 | +libcrypt-routines-$(OPTION_EGLIBC_CRYPT_UFC) := crypt crypt_util |
| 422 | +libcrypt-routines += $(libcrypt-routines-y) |
| 423 | |
| 424 | -tests := cert md5c-test sha256c-test sha512c-test badsalttest |
| 425 | +tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test badsalttest |
| 426 | +tests-$(OPTION_EGLIBC_CRYPT_UFC) += cert |
| 427 | |
| 428 | -ifeq ($(crypt-in-libc),yes) |
| 429 | +ifeq ($(crypt-in-libc)$(OPTION_EGLIBC_CRYPT),yesy) |
| 430 | routines += $(libcrypt-routines) |
| 431 | endif |
| 432 | |
| 433 | @@ -44,7 +48,7 @@ LDLIBS-crypt.so = -lfreebl3 |
| 434 | else |
| 435 | libcrypt-routines += md5 sha256 sha512 |
| 436 | |
| 437 | -tests += md5test sha256test sha512test |
| 438 | +tests-$(OPTION_EGLIBC_CRYPT) += md5test sha256test sha512test |
| 439 | |
| 440 | # The test md5test-giant uses up to 400 MB of RSS and runs on a fast |
| 441 | # machine over a minute. |
| 442 | @@ -64,8 +68,10 @@ $(objpfx)sha256test: $(patsubst %, $(objpfx)%.o,$(sha256-routines)) |
| 443 | $(objpfx)sha512test: $(patsubst %, $(objpfx)%.o,$(sha512-routines)) |
| 444 | endif |
| 445 | |
| 446 | +ifeq ($(OPTION_EGLIBC_CRYPT),y) |
| 447 | ifeq (yes,$(build-shared)) |
| 448 | $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.so |
| 449 | else |
| 450 | $(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.a |
| 451 | endif |
| 452 | +endif # eglibc: OPTION_EGLIBC_CRYPT |
| 453 | diff --git a/crypt/crypt-entry.c b/crypt/crypt-entry.c |
| 454 | index 7e655ba..6ae5c2b 100644 |
| 455 | --- a/crypt/crypt-entry.c |
| 456 | +++ b/crypt/crypt-entry.c |
| 457 | @@ -27,6 +27,7 @@ |
| 458 | #include <stdio.h> |
| 459 | #endif |
| 460 | #include <string.h> |
| 461 | +#include <gnu/option-groups.h> |
| 462 | #include <errno.h> |
| 463 | #include <fips-private.h> |
| 464 | |
| 465 | @@ -76,9 +77,11 @@ __crypt_r (key, salt, data) |
| 466 | const char *salt; |
| 467 | struct crypt_data * __restrict data; |
| 468 | { |
| 469 | +#if __OPTION_EGLIBC_CRYPT_UFC |
| 470 | ufc_long res[4]; |
| 471 | char ktab[9]; |
| 472 | ufc_long xx = 25; /* to cope with GCC long long compiler bugs */ |
| 473 | +#endif /*__OPTION_EGLIBC_CRYPT_UFC*/ |
| 474 | |
| 475 | #ifdef _LIBC |
| 476 | /* Try to find out whether we have to use MD5 encryption replacement. */ |
| 477 | @@ -105,6 +108,7 @@ __crypt_r (key, salt, data) |
| 478 | sizeof (struct crypt_data)); |
| 479 | #endif |
| 480 | |
| 481 | +#if __OPTION_EGLIBC_CRYPT_UFC |
| 482 | /* |
| 483 | * Hack DES tables according to salt |
| 484 | */ |
| 485 | @@ -144,6 +148,10 @@ __crypt_r (key, salt, data) |
| 486 | */ |
| 487 | _ufc_output_conversion_r (res[0], res[1], salt, data); |
| 488 | return data->crypt_3_buf; |
| 489 | +#else /* __OPTION_EGLIBC_CRYPT_UFC */ |
| 490 | + __set_errno (ENOSYS); |
| 491 | + return NULL; |
| 492 | +#endif /* __OPTION_EGLIBC_CRYPT_UFC */ |
| 493 | } |
| 494 | weak_alias (__crypt_r, crypt_r) |
| 495 | |
| 496 | @@ -168,7 +176,12 @@ crypt (key, salt) |
| 497 | return __sha512_crypt (key, salt); |
| 498 | #endif |
| 499 | |
| 500 | +#if __OPTION_EGLIBC_CRYPT_UFC |
| 501 | return __crypt_r (key, salt, &_ufc_foobar); |
| 502 | +#else /* __OPTION_EGLIBC_CRYPT_UFC */ |
| 503 | + __set_errno (ENOSYS); |
| 504 | + return NULL; |
| 505 | +#endif /* __OPTION_EGLIBC_CRYPT_UFC */ |
| 506 | } |
| 507 | |
| 508 | |
| 509 | diff --git a/crypt/crypt_common.c b/crypt/crypt_common.c |
| 510 | new file mode 100644 |
| 511 | index 0000000..cce6a31 |
| 512 | --- /dev/null |
| 513 | +++ b/crypt/crypt_common.c |
| 514 | @@ -0,0 +1,42 @@ |
| 515 | +/* |
| 516 | + * crypt: crypt(3) implementation |
| 517 | + * |
| 518 | + * Copyright (C) 1991-2014 Free Software Foundation, Inc. |
| 519 | + * |
| 520 | + * This library is free software; you can redistribute it and/or |
| 521 | + * modify it under the terms of the GNU Lesser General Public |
| 522 | + * License as published by the Free Software Foundation; either |
| 523 | + * version 2.1 of the License, or (at your option) any later version. |
| 524 | + * |
| 525 | + * This library is distributed in the hope that it will be useful, |
| 526 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 527 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 528 | + * Lesser General Public License for more details. |
| 529 | + * |
| 530 | + * You should have received a copy of the GNU Lesser General Public |
| 531 | + * License along with this library; see the file COPYING.LIB. If not, |
| 532 | + * see <http://www.gnu.org/licenses/>. |
| 533 | + * |
| 534 | + * General Support routines |
| 535 | + * |
| 536 | + */ |
| 537 | + |
| 538 | +#include "crypt-private.h" |
| 539 | + |
| 540 | +/* Table with characters for base64 transformation. */ |
| 541 | +static const char b64t[64] = |
| 542 | +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
| 543 | + |
| 544 | +void |
| 545 | +__b64_from_24bit (char **cp, int *buflen, |
| 546 | + unsigned int b2, unsigned int b1, unsigned int b0, |
| 547 | + int n) |
| 548 | +{ |
| 549 | + unsigned int w = (b2 << 16) | (b1 << 8) | b0; |
| 550 | + while (n-- > 0 && (*buflen) > 0) |
| 551 | + { |
| 552 | + *(*cp)++ = b64t[w & 0x3f]; |
| 553 | + --(*buflen); |
| 554 | + w >>= 6; |
| 555 | + } |
| 556 | +} |
| 557 | diff --git a/crypt/crypt_util.c b/crypt/crypt_util.c |
| 558 | index 1597885..9297974 100644 |
| 559 | --- a/crypt/crypt_util.c |
| 560 | +++ b/crypt/crypt_util.c |
| 561 | @@ -242,10 +242,6 @@ static ufc_long eperm32tab[4][256][2]; |
| 562 | */ |
| 563 | static ufc_long efp[16][64][2]; |
| 564 | |
| 565 | -/* Table with characters for base64 transformation. */ |
| 566 | -static const char b64t[64] = |
| 567 | -"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
| 568 | - |
| 569 | /* |
| 570 | * For use by the old, non-reentrant routines |
| 571 | * (crypt/encrypt/setkey) |
| 572 | @@ -949,17 +945,3 @@ setkey(__key) |
| 573 | { |
| 574 | __setkey_r(__key, &_ufc_foobar); |
| 575 | } |
| 576 | - |
| 577 | -void |
| 578 | -__b64_from_24bit (char **cp, int *buflen, |
| 579 | - unsigned int b2, unsigned int b1, unsigned int b0, |
| 580 | - int n) |
| 581 | -{ |
| 582 | - unsigned int w = (b2 << 16) | (b1 << 8) | b0; |
| 583 | - while (n-- > 0 && (*buflen) > 0) |
| 584 | - { |
| 585 | - *(*cp)++ = b64t[w & 0x3f]; |
| 586 | - --(*buflen); |
| 587 | - w >>= 6; |
| 588 | - } |
| 589 | -} |
| 590 | diff --git a/csu/Makefile b/csu/Makefile |
| 591 | index 9f0855a..b1c3363 100644 |
| 592 | --- a/csu/Makefile |
| 593 | +++ b/csu/Makefile |
| 594 | @@ -22,6 +22,8 @@ |
| 595 | # crtn.o, special "initializer" and "finalizer" files used in the link |
| 596 | # to make the .init and .fini sections work right. |
| 597 | |
| 598 | +include ../option-groups.mak |
| 599 | + |
| 600 | subdir := csu |
| 601 | |
| 602 | include ../Makeconfig |
| 603 | diff --git a/debug/Makefile b/debug/Makefile |
| 604 | index 9ff357b..d23d97d 100644 |
| 605 | --- a/debug/Makefile |
| 606 | +++ b/debug/Makefile |
| 607 | @@ -18,6 +18,8 @@ |
| 608 | # |
| 609 | # Sub-makefile for debug portion of the library. |
| 610 | # |
| 611 | +include ../option-groups.mak |
| 612 | + |
| 613 | subdir := debug |
| 614 | |
| 615 | include ../Makeconfig |
| 616 | @@ -27,7 +29,7 @@ headers := execinfo.h |
| 617 | # Note that ptsname_r_chk and getlogin_r are not here, but in |
| 618 | # login/Makefile instead. If that subdir is omitted from the |
| 619 | # build, its _FORTIFY_SOURCE support will be too. |
| 620 | -routines = backtrace backtracesyms backtracesymsfd noophooks \ |
| 621 | +routines = noophooks \ |
| 622 | memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ |
| 623 | strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ |
| 624 | sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ |
| 625 | @@ -36,20 +38,27 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \ |
| 626 | read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ |
| 627 | readlink_chk readlinkat_chk getwd_chk getcwd_chk \ |
| 628 | realpath_chk fread_chk fread_u_chk \ |
| 629 | - wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ |
| 630 | - wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ |
| 631 | - wcpncpy_chk \ |
| 632 | - swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \ |
| 633 | - vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \ |
| 634 | confstr_chk getgroups_chk ttyname_r_chk \ |
| 635 | - gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \ |
| 636 | - wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ |
| 637 | - wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \ |
| 638 | + gethostname_chk getdomainname_chk \ |
| 639 | + asprintf_chk vasprintf_chk dprintf_chk \ |
| 640 | vdprintf_chk obprintf_chk \ |
| 641 | longjmp_chk ____longjmp_chk \ |
| 642 | fdelt_chk poll_chk ppoll_chk \ |
| 643 | stack_chk_fail fortify_fail \ |
| 644 | $(static-only-routines) |
| 645 | +routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd |
| 646 | +routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ |
| 647 | + += wprintf_chk fwprintf_chk \ |
| 648 | + vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk |
| 649 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 650 | + += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ |
| 651 | + wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ |
| 652 | + wcpncpy_chk \ |
| 653 | + swprintf_chk vswprintf_chk \ |
| 654 | + wcrtomb_chk mbsnrtowcs_chk \ |
| 655 | + wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ |
| 656 | + wcstombs_chk |
| 657 | + |
| 658 | static-only-routines := warning-nop stack_chk_fail_local |
| 659 | |
| 660 | CFLAGS-backtrace.c = -fno-omit-frame-pointer |
| 661 | @@ -131,11 +140,15 @@ LDFLAGS-tst-backtrace4 = -rdynamic |
| 662 | LDFLAGS-tst-backtrace5 = -rdynamic |
| 663 | LDFLAGS-tst-backtrace6 = -rdynamic |
| 664 | |
| 665 | -tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ |
| 666 | - tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ |
| 667 | - tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \ |
| 668 | - tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \ |
| 669 | - tst-backtrace5 tst-backtrace6 |
| 670 | +tests = tst-longjmp_chk test-strcpy_chk test-stpcpy_chk tst-longjmp_chk2 |
| 671 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 672 | + += tst-chk1 tst-chk2 tst-chk3 tst-lfschk1 tst-lfschk2 tst-lfschk3 |
| 673 | +tests-$(OPTION_EGLIBC_BACKTRACE) \ |
| 674 | + += backtrace-tst tst-backtrace2 tst-backtrace3 tst-backtrace4 \ |
| 675 | + tst-backtrace5 tst-backtrace6 |
| 676 | +ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_EGLIBC_CXX_TESTS)) |
| 677 | +tests += tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 |
| 678 | +endif |
| 679 | |
| 680 | ifeq (,$(CXX)) |
| 681 | tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \ |
| 682 | diff --git a/debug/segfault.c b/debug/segfault.c |
| 683 | index 3459a2a..ee9a146 100644 |
| 684 | --- a/debug/segfault.c |
| 685 | +++ b/debug/segfault.c |
| 686 | @@ -30,6 +30,7 @@ |
| 687 | #include <unistd.h> |
| 688 | #include <_itoa.h> |
| 689 | #include <ldsodefs.h> |
| 690 | +#include <gnu/option-groups.h> |
| 691 | |
| 692 | /* This file defines macros to access the content of the sigcontext element |
| 693 | passed up by the signal handler. */ |
| 694 | @@ -68,11 +69,13 @@ write_strsignal (int fd, int signal) |
| 695 | static void |
| 696 | catch_segfault (int signal, SIGCONTEXT ctx) |
| 697 | { |
| 698 | - int fd, cnt, i; |
| 699 | - void **arr; |
| 700 | + int fd; |
| 701 | struct sigaction sa; |
| 702 | +#if __OPTION_EGLIBC_BACKTRACE |
| 703 | + int cnt, i; |
| 704 | + void **arr; |
| 705 | uintptr_t pc; |
| 706 | - |
| 707 | +#endif |
| 708 | /* This is the name of the file we are writing to. If none is given |
| 709 | or we cannot write to this file write to stderr. */ |
| 710 | fd = 2; |
| 711 | @@ -91,6 +94,7 @@ catch_segfault (int signal, SIGCONTEXT ctx) |
| 712 | REGISTER_DUMP; |
| 713 | #endif |
| 714 | |
| 715 | +#if __OPTION_EGLIBC_BACKTRACE |
| 716 | WRITE_STRING ("\nBacktrace:\n"); |
| 717 | |
| 718 | /* Get the backtrace. */ |
| 719 | @@ -113,6 +117,7 @@ catch_segfault (int signal, SIGCONTEXT ctx) |
| 720 | |
| 721 | /* Now generate nicely formatted output. */ |
| 722 | __backtrace_symbols_fd (arr + i, cnt - i, fd); |
| 723 | +#endif |
| 724 | |
| 725 | #ifdef HAVE_PROC_SELF |
| 726 | /* Now the link map. */ |
| 727 | diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c |
| 728 | index 53559e6..362d92a 100644 |
| 729 | --- a/debug/tst-chk1.c |
| 730 | +++ b/debug/tst-chk1.c |
| 731 | @@ -31,6 +31,7 @@ |
| 732 | #include <sys/select.h> |
| 733 | #include <sys/socket.h> |
| 734 | #include <sys/un.h> |
| 735 | +#include <gnu/option-groups.h> |
| 736 | |
| 737 | |
| 738 | #define obstack_chunk_alloc malloc |
| 739 | @@ -307,6 +308,7 @@ do_test (void) |
| 740 | snprintf (buf + 8, l0 + 3, "%d", num2); |
| 741 | CHK_FAIL_END |
| 742 | |
| 743 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 744 | CHK_FAIL_START |
| 745 | swprintf (wbuf + 8, 3, L"%d", num1); |
| 746 | CHK_FAIL_END |
| 747 | @@ -314,6 +316,7 @@ do_test (void) |
| 748 | CHK_FAIL_START |
| 749 | swprintf (wbuf + 8, l0 + 3, L"%d", num1); |
| 750 | CHK_FAIL_END |
| 751 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 752 | # endif |
| 753 | |
| 754 | memcpy (buf, str1 + 2, l0 + 9); |
| 755 | @@ -381,6 +384,7 @@ do_test (void) |
| 756 | CHK_FAIL_END |
| 757 | #endif |
| 758 | |
| 759 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 760 | |
| 761 | /* These ops can be done without runtime checking of object size. */ |
| 762 | wmemcpy (wbuf, L"abcdefghij", 10); |
| 763 | @@ -605,6 +609,7 @@ do_test (void) |
| 764 | CHK_FAIL_END |
| 765 | #endif |
| 766 | |
| 767 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 768 | |
| 769 | /* Now checks for %n protection. */ |
| 770 | |
| 771 | @@ -1192,6 +1197,7 @@ do_test (void) |
| 772 | # endif |
| 773 | #endif |
| 774 | |
| 775 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 776 | if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL) |
| 777 | { |
| 778 | assert (MB_CUR_MAX <= 10); |
| 779 | @@ -1348,6 +1354,7 @@ do_test (void) |
| 780 | puts ("cannot set locale"); |
| 781 | ret = 1; |
| 782 | } |
| 783 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 784 | |
| 785 | int fd = posix_openpt (O_RDWR); |
| 786 | if (fd != -1) |
| 787 | diff --git a/dlfcn/Makefile b/dlfcn/Makefile |
| 788 | index 759780d..3827607 100644 |
| 789 | --- a/dlfcn/Makefile |
| 790 | +++ b/dlfcn/Makefile |
| 791 | @@ -15,6 +15,8 @@ |
| 792 | # License along with the GNU C Library; if not, see |
| 793 | # <http://www.gnu.org/licenses/>. |
| 794 | |
| 795 | +include ../option-groups.mak |
| 796 | + |
| 797 | subdir := dlfcn |
| 798 | |
| 799 | include ../Makeconfig |
| 800 | @@ -36,8 +38,11 @@ endif |
| 801 | ifeq (yes,$(build-shared)) |
| 802 | tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \ |
| 803 | bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ |
| 804 | - bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen |
| 805 | + tstatexit bug-dl-leaf tst-rec-dlopen |
| 806 | endif |
| 807 | + |
| 808 | +tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3 |
| 809 | + |
| 810 | modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \ |
| 811 | defaultmod2 errmsg1mod modatexit modcxaatexit \ |
| 812 | bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ |
| 813 | diff --git a/elf/dl-support.c b/elf/dl-support.c |
| 814 | index 4d036f1..c15f405 100644 |
| 815 | --- a/elf/dl-support.c |
| 816 | +++ b/elf/dl-support.c |
| 817 | @@ -19,6 +19,7 @@ |
| 818 | /* This file defines some things that for the dynamic linker are defined in |
| 819 | rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ |
| 820 | |
| 821 | +#include <gnu/option-groups.h> |
| 822 | #include <errno.h> |
| 823 | #include <libintl.h> |
| 824 | #include <stdlib.h> |
| 825 | @@ -42,7 +43,9 @@ char **_dl_argv = &__progname; /* This is checked for some error messages. */ |
| 826 | const char *_dl_platform; |
| 827 | size_t _dl_platformlen; |
| 828 | |
| 829 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 830 | int _dl_debug_mask; |
| 831 | +#endif |
| 832 | int _dl_lazy; |
| 833 | ElfW(Addr) _dl_use_load_bias = -2; |
| 834 | int _dl_dynamic_weak; |
| 835 | diff --git a/elf/rtld.c b/elf/rtld.c |
| 836 | index 6d3add7..fc3a2db 100644 |
| 837 | --- a/elf/rtld.c |
| 838 | +++ b/elf/rtld.c |
| 839 | @@ -16,6 +16,7 @@ |
| 840 | License along with the GNU C Library; if not, see |
| 841 | <http://www.gnu.org/licenses/>. */ |
| 842 | |
| 843 | +#include <gnu/option-groups.h> |
| 844 | #include <errno.h> |
| 845 | #include <dlfcn.h> |
| 846 | #include <fcntl.h> |
| 847 | @@ -2201,6 +2202,7 @@ print_missing_version (int errcode __attribute__ ((unused)), |
| 848 | objname, errstring); |
| 849 | } |
| 850 | |
| 851 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 852 | /* Nonzero if any of the debugging options is enabled. */ |
| 853 | static int any_debug attribute_relro; |
| 854 | |
| 855 | @@ -2310,6 +2312,7 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); |
| 856 | _exit (0); |
| 857 | } |
| 858 | } |
| 859 | +#endif /* __OPTION_EGLIBC_RTLD_DEBUG */ |
| 860 | |
| 861 | static void |
| 862 | process_dl_audit (char *str) |
| 863 | @@ -2349,8 +2352,9 @@ process_envvars (enum mode *modep) |
| 864 | char **runp = _environ; |
| 865 | char *envline; |
| 866 | enum mode mode = normal; |
| 867 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 868 | char *debug_output = NULL; |
| 869 | - |
| 870 | +#endif |
| 871 | /* This is the default place for profiling data file. */ |
| 872 | GLRO(dl_profile_output) |
| 873 | = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0]; |
| 874 | @@ -2377,12 +2381,14 @@ process_envvars (enum mode *modep) |
| 875 | break; |
| 876 | |
| 877 | case 5: |
| 878 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 879 | /* Debugging of the dynamic linker? */ |
| 880 | if (memcmp (envline, "DEBUG", 5) == 0) |
| 881 | { |
| 882 | process_dl_debug (&envline[6]); |
| 883 | break; |
| 884 | } |
| 885 | +#endif |
| 886 | if (memcmp (envline, "AUDIT", 5) == 0) |
| 887 | process_dl_audit (&envline[6]); |
| 888 | break; |
| 889 | @@ -2448,13 +2454,14 @@ process_envvars (enum mode *modep) |
| 890 | break; |
| 891 | } |
| 892 | |
| 893 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 894 | /* Where to place the profiling data file. */ |
| 895 | if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0) |
| 896 | { |
| 897 | debug_output = &envline[13]; |
| 898 | break; |
| 899 | } |
| 900 | - |
| 901 | +#endif |
| 902 | if (!__libc_enable_secure |
| 903 | && memcmp (envline, "DYNAMIC_WEAK", 12) == 0) |
| 904 | GLRO(dl_dynamic_weak) = 1; |
| 905 | @@ -2491,7 +2498,9 @@ process_envvars (enum mode *modep) |
| 906 | { |
| 907 | mode = trace; |
| 908 | GLRO(dl_verbose) = 1; |
| 909 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 910 | GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK; |
| 911 | +#endif |
| 912 | GLRO(dl_trace_prelink) = &envline[17]; |
| 913 | } |
| 914 | break; |
| 915 | @@ -2538,12 +2547,15 @@ process_envvars (enum mode *modep) |
| 916 | if (__access ("/etc/suid-debug", F_OK) != 0) |
| 917 | { |
| 918 | unsetenv ("MALLOC_CHECK_"); |
| 919 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 920 | GLRO(dl_debug_mask) = 0; |
| 921 | +#endif |
| 922 | } |
| 923 | |
| 924 | if (mode != normal) |
| 925 | _exit (5); |
| 926 | } |
| 927 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 928 | /* If we have to run the dynamic linker in debugging mode and the |
| 929 | LD_DEBUG_OUTPUT environment variable is given, we write the debug |
| 930 | messages to this file. */ |
| 931 | @@ -2568,6 +2580,7 @@ process_envvars (enum mode *modep) |
| 932 | /* We use standard output if opening the file failed. */ |
| 933 | GLRO(dl_debug_fd) = STDOUT_FILENO; |
| 934 | } |
| 935 | +#endif /* __OPTION_EGLIBC_RTLD_DEBUG */ |
| 936 | } |
| 937 | |
| 938 | |
| 939 | diff --git a/extra-lib.mk b/extra-lib.mk |
| 940 | index b10748d..d71a06f 100644 |
| 941 | --- a/extra-lib.mk |
| 942 | +++ b/extra-lib.mk |
| 943 | @@ -25,7 +25,9 @@ install-lib := $(install-lib) |
| 944 | extra-objs := $(extra-objs) |
| 945 | |
| 946 | # The modules that go in $(lib). |
| 947 | -all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines) |
| 948 | +all-$(lib)-routines := $($(lib)-routines) \ |
| 949 | + $($(lib)-routines-y) \ |
| 950 | + $($(lib)-sysdep_routines) |
| 951 | |
| 952 | # Add each flavor of library to the lists of things to build and install. |
| 953 | install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o))) |
| 954 | @@ -101,7 +103,7 @@ endif |
| 955 | endif |
| 956 | |
| 957 | # This will define `libof-ROUTINE := LIB' for each of the routines. |
| 958 | -cpp-srcs-left := $($(lib)-routines) $($(lib)-sysdep_routines) |
| 959 | +cpp-srcs-left := $(all-$(lib)-routines) |
| 960 | ifneq (,$(cpp-srcs-left)) |
| 961 | include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left)) |
| 962 | endif |
| 963 | diff --git a/grp/Makefile b/grp/Makefile |
| 964 | index c63b552..7486f32 100644 |
| 965 | --- a/grp/Makefile |
| 966 | +++ b/grp/Makefile |
| 967 | @@ -18,6 +18,8 @@ |
| 968 | # |
| 969 | # Sub-makefile for grp portion of the library. |
| 970 | # |
| 971 | +include ../option-groups.mak |
| 972 | + |
| 973 | subdir := grp |
| 974 | |
| 975 | include ../Makeconfig |
| 976 | @@ -29,6 +31,9 @@ routines := fgetgrent initgroups setgroups \ |
| 977 | getgrent_r getgrgid_r getgrnam_r fgetgrent_r |
| 978 | |
| 979 | tests := testgrp |
| 980 | +ifneq (y,$(OPTION_EGLIBC_NSSWITCH)) |
| 981 | +LDLIBS-testgrp += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs) |
| 982 | +endif |
| 983 | |
| 984 | ifeq (yes,$(build-shared)) |
| 985 | test-srcs := tst_fgetgrent |
| 986 | diff --git a/hesiod/Makefile b/hesiod/Makefile |
| 987 | index ac0bc01..38263b4 100644 |
| 988 | --- a/hesiod/Makefile |
| 989 | +++ b/hesiod/Makefile |
| 990 | @@ -18,12 +18,14 @@ |
| 991 | # |
| 992 | # Sub-makefile for hesiod portion of the library. |
| 993 | # |
| 994 | +include ../option-groups.mak |
| 995 | + |
| 996 | subdir := hesiod |
| 997 | |
| 998 | include ../Makeconfig |
| 999 | |
| 1000 | -extra-libs := libnss_hesiod |
| 1001 | -extra-libs-others = $(extra-libs) |
| 1002 | +extra-libs-$(OPTION_EGLIBC_INET) += libnss_hesiod |
| 1003 | +extra-libs-others-y += $(extra-libs-y) |
| 1004 | |
| 1005 | subdir-dirs = nss_hesiod |
| 1006 | vpath %.c nss_hesiod |
| 1007 | diff --git a/iconv/Makefile b/iconv/Makefile |
| 1008 | index 0d55eda..a1847c6 100644 |
| 1009 | --- a/iconv/Makefile |
| 1010 | +++ b/iconv/Makefile |
| 1011 | @@ -18,6 +18,8 @@ |
| 1012 | # |
| 1013 | # Makefile for iconv. |
| 1014 | # |
| 1015 | +include ../option-groups.mak |
| 1016 | + |
| 1017 | subdir := iconv |
| 1018 | |
| 1019 | include ../Makeconfig |
| 1020 | @@ -39,6 +41,11 @@ CFLAGS-iconv_charmap.c = -I../locale/programs |
| 1021 | CFLAGS-dummy-repertoire.c = -I../locale/programs |
| 1022 | CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \ |
| 1023 | -DDEFAULT_CHARMAP=null_pointer -DNEED_NULL_POINTER |
| 1024 | + |
| 1025 | +ifneq (y,$(OPTION_EGLIBC_SPAWN)) |
| 1026 | +CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS |
| 1027 | +endif |
| 1028 | + |
| 1029 | CFLAGS-linereader.c = -DNO_TRANSLITERATION |
| 1030 | CFLAGS-simple-hash.c = -I../locale |
| 1031 | |
| 1032 | diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c |
| 1033 | index ce46216..ea18964 100644 |
| 1034 | --- a/iconv/gconv_db.c |
| 1035 | +++ b/iconv/gconv_db.c |
| 1036 | @@ -25,6 +25,7 @@ |
| 1037 | #include <sys/param.h> |
| 1038 | #include <bits/libc-lock.h> |
| 1039 | #include <locale/localeinfo.h> |
| 1040 | +#include <gnu/option-groups.h> |
| 1041 | |
| 1042 | #include <dlfcn.h> |
| 1043 | #include <gconv_int.h> |
| 1044 | @@ -828,9 +829,11 @@ free_modules_db (struct gconv_module *node) |
| 1045 | /* Free all resources if necessary. */ |
| 1046 | libc_freeres_fn (free_mem) |
| 1047 | { |
| 1048 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 1049 | /* First free locale memory. This needs to be done before freeing derivations, |
| 1050 | as ctype cleanup functions dereference steps arrays which we free below. */ |
| 1051 | _nl_locale_subfreeres (); |
| 1052 | +#endif |
| 1053 | |
| 1054 | /* finddomain.c has similar problem. */ |
| 1055 | extern void _nl_finddomain_subfreeres (void) attribute_hidden; |
| 1056 | diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c |
| 1057 | index 5d5d4d7..a7d3072 100644 |
| 1058 | --- a/iconv/gconv_trans.c |
| 1059 | +++ b/iconv/gconv_trans.c |
| 1060 | @@ -23,6 +23,7 @@ |
| 1061 | #include <stdint.h> |
| 1062 | #include <string.h> |
| 1063 | #include <stdlib.h> |
| 1064 | +#include <gnu/option-groups.h> |
| 1065 | |
| 1066 | #include <bits/libc-lock.h> |
| 1067 | #include "gconv_int.h" |
| 1068 | @@ -38,15 +39,19 @@ __gconv_transliterate (struct __gconv_step *step, |
| 1069 | unsigned char **outbufstart, size_t *irreversible) |
| 1070 | { |
| 1071 | /* Find out about the locale's transliteration. */ |
| 1072 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 1073 | uint_fast32_t size; |
| 1074 | const uint32_t *from_idx; |
| 1075 | const uint32_t *from_tbl; |
| 1076 | const uint32_t *to_idx; |
| 1077 | const uint32_t *to_tbl; |
| 1078 | +#endif |
| 1079 | const uint32_t *winbuf; |
| 1080 | const uint32_t *winbufend; |
| 1081 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 1082 | uint_fast32_t low; |
| 1083 | uint_fast32_t high; |
| 1084 | +#endif |
| 1085 | |
| 1086 | /* The input buffer. There are actually 4-byte values. */ |
| 1087 | winbuf = (const uint32_t *) *inbufp; |
| 1088 | @@ -58,6 +63,7 @@ __gconv_transliterate (struct __gconv_step *step, |
| 1089 | PTR_DEMANGLE (fct); |
| 1090 | #endif |
| 1091 | |
| 1092 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 1093 | /* If there is no transliteration information in the locale don't do |
| 1094 | anything and return the error. */ |
| 1095 | size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_TAB_SIZE); |
| 1096 | @@ -193,6 +199,7 @@ __gconv_transliterate (struct __gconv_step *step, |
| 1097 | sorted. */ |
| 1098 | break; |
| 1099 | } |
| 1100 | +#endif |
| 1101 | |
| 1102 | /* One last chance: use the default replacement. */ |
| 1103 | if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN) != 0) |
| 1104 | diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c |
| 1105 | index e249bce..403ece5 100644 |
| 1106 | --- a/iconv/iconv_prog.c |
| 1107 | +++ b/iconv/iconv_prog.c |
| 1108 | @@ -35,6 +35,7 @@ |
| 1109 | #ifdef _POSIX_MAPPED_FILES |
| 1110 | # include <sys/mman.h> |
| 1111 | #endif |
| 1112 | +#include <gnu/option-groups.h> |
| 1113 | #include <charmap.h> |
| 1114 | #include <gconv_int.h> |
| 1115 | #include "iconv_prog.h" |
| 1116 | @@ -221,10 +222,17 @@ main (int argc, char *argv[]) |
| 1117 | bool to_wrong = |
| 1118 | (iconv_open (to_code, "UTF-8") == (iconv_t) -1 |
| 1119 | && errno == EINVAL); |
| 1120 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 1121 | const char *from_pretty = |
| 1122 | (from_code[0] ? from_code : nl_langinfo (CODESET)); |
| 1123 | const char *to_pretty = |
| 1124 | (orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET)); |
| 1125 | +#else |
| 1126 | + const char *from_pretty = |
| 1127 | + (from_code[0] ? from_code : "ANSI_X3.4-1968"); |
| 1128 | + const char *to_pretty = |
| 1129 | + (orig_to_code[0] ? orig_to_code : "ANSI_X3.4-1968"); |
| 1130 | +#endif |
| 1131 | |
| 1132 | if (from_wrong) |
| 1133 | { |
| 1134 | diff --git a/iconvdata/Makefile b/iconvdata/Makefile |
| 1135 | index a3d1d09..0832708 100644 |
| 1136 | --- a/iconvdata/Makefile |
| 1137 | +++ b/iconvdata/Makefile |
| 1138 | @@ -18,12 +18,15 @@ |
| 1139 | # |
| 1140 | # Makefile for iconv data and code. |
| 1141 | # |
| 1142 | +include ../option-groups.mak |
| 1143 | + |
| 1144 | subdir := iconvdata |
| 1145 | |
| 1146 | include ../Makeconfig |
| 1147 | |
| 1148 | # Names of all the shared objects which implement the transformations. |
| 1149 | -modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ |
| 1150 | +modules-$(OPTION_EGLIBC_CHARSETS) \ |
| 1151 | + := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ |
| 1152 | ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10 \ |
| 1153 | ISO8859-11 ISO8859-13 ISO8859-14 ISO8859-15 ISO8859-16 \ |
| 1154 | T.61 ISO_6937 SJIS KOI-8 HP-ROMAN8 HP-ROMAN9 EBCDIC-AT-DE \ |
| 1155 | @@ -63,11 +66,13 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ |
| 1156 | MAC-CENTRALEUROPE KOI8-RU ISO8859-9E \ |
| 1157 | CP770 CP771 CP772 CP773 CP774 |
| 1158 | |
| 1159 | -modules.so := $(addsuffix .so, $(modules)) |
| 1160 | +modules.so := $(addsuffix .so, $(modules-y)) |
| 1161 | |
| 1162 | ifeq (yes,$(build-shared)) |
| 1163 | tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ |
| 1164 | - tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 |
| 1165 | + tst-iconv6 bug-iconv5 bug-iconv8 bug-iconv9 |
| 1166 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) += bug-iconv6 tst-iconv7 |
| 1167 | + |
| 1168 | ifeq ($(have-thread-library),yes) |
| 1169 | tests += bug-iconv3 |
| 1170 | endif |
| 1171 | @@ -127,13 +132,13 @@ ifeq (yes,$(build-shared)) |
| 1172 | # Rule to generate the shared objects. |
| 1173 | charmaps = ../localedata/charmaps |
| 1174 | -include $(objpfx)iconv-rules |
| 1175 | -extra-modules-left := $(modules) |
| 1176 | +extra-modules-left := $(modules-y) |
| 1177 | include extra-module.mk |
| 1178 | |
| 1179 | |
| 1180 | extra-objs += $(modules.so) |
| 1181 | -install-others = $(addprefix $(inst_gconvdir)/, $(modules.so)) \ |
| 1182 | - $(inst_gconvdir)/gconv-modules |
| 1183 | +install-others-y += $(addprefix $(inst_gconvdir)/, $(modules.so)) |
| 1184 | +install-others-$(OPTION_EGLIBC_CHARSETS) += $(inst_gconvdir)/gconv-modules |
| 1185 | |
| 1186 | # We can build the conversion tables for numerous charsets automatically. |
| 1187 | |
| 1188 | @@ -201,7 +206,7 @@ before-compile += $(addprefix $(objpfx),$(generated-modules:=.h)) |
| 1189 | ifndef avoid-generated |
| 1190 | $(objpfx)iconv-rules: Makefile |
| 1191 | $(make-target-directory) |
| 1192 | - { echo $(filter-out lib%, $(modules)); \ |
| 1193 | + { echo $(filter-out lib%, $(modules-y)); \ |
| 1194 | echo 8bit $(gen-8bit-modules); \ |
| 1195 | echo 8bit-gap $(gen-8bit-gap-modules); } | \ |
| 1196 | LC_ALL=C \ |
| 1197 | @@ -245,7 +250,7 @@ $(addprefix $(inst_gconvdir)/, $(modules.so)): \ |
| 1198 | $(do-install-program) |
| 1199 | $(inst_gconvdir)/gconv-modules: gconv-modules $(+force) |
| 1200 | $(do-install) |
| 1201 | -ifeq (no,$(cross-compiling)) |
| 1202 | +# eglibc: ifeq (no,$(cross-compiling)) |
| 1203 | # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary |
| 1204 | # if this libc has more gconv modules than the previously installed one. |
| 1205 | if test -f "$(inst_gconvdir)/gconv-modules.cache"; then \ |
| 1206 | @@ -254,9 +259,9 @@ ifeq (no,$(cross-compiling)) |
| 1207 | $(common-objpfx)iconv/iconvconfig \ |
| 1208 | $(addprefix --prefix=,$(install_root)); \ |
| 1209 | fi |
| 1210 | -else |
| 1211 | - @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache' |
| 1212 | -endif |
| 1213 | +# eglibc: else |
| 1214 | +# eglibc: @echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache' |
| 1215 | +# eglibc: endif |
| 1216 | |
| 1217 | endif # build-shared = yes |
| 1218 | |
| 1219 | diff --git a/include/netdb.h b/include/netdb.h |
| 1220 | index e1f051d..f6d15aa 100644 |
| 1221 | --- a/include/netdb.h |
| 1222 | +++ b/include/netdb.h |
| 1223 | @@ -232,6 +232,10 @@ extern enum nss_status _nss_ ## service ## _gethostbyname2_r \ |
| 1224 | (const char *name, int af, struct hostent *host, \ |
| 1225 | char *buffer, size_t buflen, int *errnop, \ |
| 1226 | int *h_errnop); \ |
| 1227 | +extern enum nss_status _nss_ ## service ## _gethostbyname3_r \ |
| 1228 | + (const char *name, int af, struct hostent *result, \ |
| 1229 | + char *buffer, size_t buflen, int *errnop, \ |
| 1230 | + int *h_errnop, int32_t *ttlp, char **canonp); \ |
| 1231 | extern enum nss_status _nss_ ## service ## _gethostbyname_r \ |
| 1232 | (const char *name, struct hostent *host, char *buffer, \ |
| 1233 | size_t buflen, int *errnop, int *h_errnop); \ |
| 1234 | diff --git a/inet/Makefile b/inet/Makefile |
| 1235 | index f1d871f..7cb1709 100644 |
| 1236 | --- a/inet/Makefile |
| 1237 | +++ b/inet/Makefile |
| 1238 | @@ -18,6 +18,8 @@ |
| 1239 | # |
| 1240 | # Sub-makefile for inet portion of the library. |
| 1241 | # |
| 1242 | +include ../option-groups.mak |
| 1243 | + |
| 1244 | subdir := inet |
| 1245 | |
| 1246 | include ../Makeconfig |
| 1247 | @@ -27,7 +29,8 @@ headers := netinet/ether.h netinet/in.h netinet/in_systm.h \ |
| 1248 | netinet/tcp.h netinet/ip.h $(wildcard arpa/*.h protocols/*.h) \ |
| 1249 | aliases.h ifaddrs.h netinet/ip6.h netinet/icmp6.h bits/in.h |
| 1250 | |
| 1251 | -routines := htonl htons \ |
| 1252 | +routines-$(OPTION_EGLIBC_INET) \ |
| 1253 | + += htonl htons \ |
| 1254 | inet_lnaof inet_mkadr \ |
| 1255 | inet_netof inet_ntoa inet_net herrno herrno-loc \ |
| 1256 | gethstbyad gethstbyad_r gethstbynm gethstbynm2 gethstbynm2_r \ |
| 1257 | @@ -39,18 +42,23 @@ routines := htonl htons \ |
| 1258 | getservent_r \ |
| 1259 | ether_aton ether_aton_r ether_hton ether_line \ |
| 1260 | ether_ntoa ether_ntoa_r ether_ntoh \ |
| 1261 | - rcmd rexec ruserpass \ |
| 1262 | getnetgrent_r getnetgrent \ |
| 1263 | - getaliasent_r getaliasent getaliasname getaliasname_r \ |
| 1264 | - in6_addr getnameinfo if_index ifaddrs inet6_option \ |
| 1265 | + in6_addr getnameinfo if_index ifaddrs \ |
| 1266 | getipv4sourcefilter setipv4sourcefilter \ |
| 1267 | - getsourcefilter setsourcefilter inet6_opt inet6_rth |
| 1268 | + getsourcefilter setsourcefilter |
| 1269 | +routines-$(OPTION_EGLIBC_RCMD) \ |
| 1270 | + += rcmd rexec ruserpass |
| 1271 | +routines-$(OPTION_EGLIBC_DB_ALIASES) \ |
| 1272 | + += getaliasent_r getaliasent getaliasname getaliasname_r |
| 1273 | +routines-$(OPTION_EGLIBC_ADVANCED_INET6) \ |
| 1274 | + += inet6_option inet6_opt inet6_rth |
| 1275 | |
| 1276 | -aux := check_pf check_native ifreq |
| 1277 | +aux-$(OPTION_EGLIBC_INET) += check_pf check_native ifreq |
| 1278 | |
| 1279 | tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ |
| 1280 | - tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ |
| 1281 | + tst-gethnm test-ifaddrs bug-if1 tst-ether_line \ |
| 1282 | tst-getni1 tst-getni2 tst-inet6_rth tst-checks |
| 1283 | +tests-$(OPTION_EGLIBC_ADVANCED_INET6) += test-inet6_opt |
| 1284 | |
| 1285 | include ../Rules |
| 1286 | |
| 1287 | diff --git a/intl/Makefile b/intl/Makefile |
| 1288 | index 9ecf8fe..587bc0d 100644 |
| 1289 | --- a/intl/Makefile |
| 1290 | +++ b/intl/Makefile |
| 1291 | @@ -16,6 +16,7 @@ |
| 1292 | # <http://www.gnu.org/licenses/>. |
| 1293 | |
| 1294 | # Makefile for intl subdirectory: message handling code from GNU gettext. |
| 1295 | +include ../option-groups.mak |
| 1296 | |
| 1297 | subdir = intl |
| 1298 | |
| 1299 | @@ -48,7 +49,7 @@ endif |
| 1300 | $(objpfx)plural.o: plural.c |
| 1301 | |
| 1302 | ifeq ($(run-built-tests),yes) |
| 1303 | -ifeq (yes,$(build-shared)) |
| 1304 | +ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared)) |
| 1305 | ifneq ($(strip $(MSGFMT)),:) |
| 1306 | tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \ |
| 1307 | $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \ |
| 1308 | diff --git a/intl/dcigettext.c b/intl/dcigettext.c |
| 1309 | index 8a3f091..e271648 100644 |
| 1310 | --- a/intl/dcigettext.c |
| 1311 | +++ b/intl/dcigettext.c |
| 1312 | @@ -100,11 +100,15 @@ extern int errno; |
| 1313 | # include "libgnuintl.h" |
| 1314 | #endif |
| 1315 | #include "hash-string.h" |
| 1316 | +#ifdef _LIBC |
| 1317 | +# include <gnu/option-groups.h> |
| 1318 | +#endif |
| 1319 | |
| 1320 | /* Handle multi-threaded applications. */ |
| 1321 | #ifdef _LIBC |
| 1322 | # include <bits/libc-lock.h> |
| 1323 | # define gl_rwlock_define_initialized __libc_rwlock_define_initialized |
| 1324 | +# define gl_rwlock_define __libc_rwlock_define |
| 1325 | # define gl_rwlock_rdlock __libc_rwlock_rdlock |
| 1326 | # define gl_rwlock_wrlock __libc_rwlock_wrlock |
| 1327 | # define gl_rwlock_unlock __libc_rwlock_unlock |
| 1328 | @@ -523,8 +527,10 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, |
| 1329 | saved_errno = errno; |
| 1330 | |
| 1331 | #ifdef _LIBC |
| 1332 | - __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) |
| 1333 | - __libc_rwlock_rdlock (__libc_setlocale_lock); |
| 1334 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1335 | + gl_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) |
| 1336 | + gl_rwlock_rdlock (__libc_setlocale_lock); |
| 1337 | +# endif |
| 1338 | #endif |
| 1339 | |
| 1340 | gl_rwlock_rdlock (_nl_state_lock); |
| 1341 | @@ -550,7 +556,11 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, |
| 1342 | #ifdef HAVE_PER_THREAD_LOCALE |
| 1343 | # ifndef IN_LIBGLOCALE |
| 1344 | # ifdef _LIBC |
| 1345 | - localename = strdupa (__current_locale_name (category)); |
| 1346 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1347 | + localename = strdupa (__current_locale_name (category)); |
| 1348 | +# else |
| 1349 | + localename = "C"; |
| 1350 | +# endif |
| 1351 | # else |
| 1352 | categoryname = category_to_name (category); |
| 1353 | # define CATEGORYNAME_INITIALIZED |
| 1354 | @@ -581,10 +591,12 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, |
| 1355 | else |
| 1356 | retval = (char *) (*foundp)->translation; |
| 1357 | |
| 1358 | - gl_rwlock_unlock (_nl_state_lock); |
| 1359 | # ifdef _LIBC |
| 1360 | - __libc_rwlock_unlock (__libc_setlocale_lock); |
| 1361 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1362 | + gl_rwlock_unlock (__libc_setlocale_lock); |
| 1363 | +# endif |
| 1364 | # endif |
| 1365 | + gl_rwlock_unlock (_nl_state_lock); |
| 1366 | __set_errno (saved_errno); |
| 1367 | return retval; |
| 1368 | } |
| 1369 | @@ -838,10 +850,13 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, |
| 1370 | if (plural) |
| 1371 | retval = plural_lookup (domain, n, retval, retlen); |
| 1372 | |
| 1373 | - gl_rwlock_unlock (_nl_state_lock); |
| 1374 | #ifdef _LIBC |
| 1375 | - __libc_rwlock_unlock (__libc_setlocale_lock); |
| 1376 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1377 | + |
| 1378 | + gl_rwlock_unlock (__libc_setlocale_lock); |
| 1379 | +# endif |
| 1380 | #endif |
| 1381 | + gl_rwlock_unlock (_nl_state_lock); |
| 1382 | return retval; |
| 1383 | } |
| 1384 | } |
| 1385 | @@ -850,10 +865,12 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, |
| 1386 | return_untranslated: |
| 1387 | /* Return the untranslated MSGID. */ |
| 1388 | FREE_BLOCKS (block_list); |
| 1389 | - gl_rwlock_unlock (_nl_state_lock); |
| 1390 | #ifdef _LIBC |
| 1391 | - __libc_rwlock_unlock (__libc_setlocale_lock); |
| 1392 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1393 | + gl_rwlock_unlock (__libc_setlocale_lock); |
| 1394 | +# endif |
| 1395 | #endif |
| 1396 | + gl_rwlock_unlock (_nl_state_lock); |
| 1397 | #ifndef _LIBC |
| 1398 | if (!ENABLE_SECURE) |
| 1399 | { |
| 1400 | @@ -1550,7 +1567,11 @@ guess_category_value (int category, const char *categoryname) |
| 1401 | `LC_xxx', and `LANG'. On some systems this can be done by the |
| 1402 | `setlocale' function itself. */ |
| 1403 | # ifdef _LIBC |
| 1404 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1405 | locale = __current_locale_name (category); |
| 1406 | +# else |
| 1407 | + locale = "C"; |
| 1408 | +# endif |
| 1409 | # else |
| 1410 | locale_defaulted = 0; |
| 1411 | # if HAVE_USELOCALE |
| 1412 | diff --git a/io/Makefile b/io/Makefile |
| 1413 | index 613dce0..697439e 100644 |
| 1414 | --- a/io/Makefile |
| 1415 | +++ b/io/Makefile |
| 1416 | @@ -18,6 +18,8 @@ |
| 1417 | # |
| 1418 | # Sub-makefile for I/O portion of the library. |
| 1419 | # |
| 1420 | +include ../option-groups.mak |
| 1421 | + |
| 1422 | subdir := io |
| 1423 | |
| 1424 | include ../Makeconfig |
| 1425 | @@ -36,7 +38,7 @@ routines := \ |
| 1426 | fxstatat fxstatat64 \ |
| 1427 | statfs fstatfs statfs64 fstatfs64 \ |
| 1428 | statvfs fstatvfs statvfs64 fstatvfs64 \ |
| 1429 | - umask chmod fchmod lchmod fchmodat \ |
| 1430 | + umask chmod fchmod fchmodat \ |
| 1431 | mkdir mkdirat \ |
| 1432 | open open_2 open64 open64_2 openat openat_2 openat64 openat64_2 \ |
| 1433 | read write lseek lseek64 access euidaccess faccessat \ |
| 1434 | @@ -49,11 +51,13 @@ routines := \ |
| 1435 | ttyname ttyname_r isatty \ |
| 1436 | link linkat symlink symlinkat readlink readlinkat \ |
| 1437 | unlink unlinkat rmdir \ |
| 1438 | - ftw ftw64 fts poll ppoll \ |
| 1439 | + poll ppoll \ |
| 1440 | posix_fadvise posix_fadvise64 \ |
| 1441 | posix_fallocate posix_fallocate64 \ |
| 1442 | sendfile sendfile64 \ |
| 1443 | utimensat futimens |
| 1444 | +routines-$(OPTION_EGLIBC_BSD) += lchmod |
| 1445 | +routines-$(OPTION_EGLIBC_FTRAVERSE) += ftw ftw64 fts |
| 1446 | |
| 1447 | aux := have_o_cloexec |
| 1448 | |
| 1449 | @@ -64,18 +68,22 @@ static-only-routines = stat fstat lstat stat64 fstat64 lstat64 \ |
| 1450 | fstatat fstatat64 mknod mknodat |
| 1451 | |
| 1452 | others := pwd |
| 1453 | -test-srcs := ftwtest |
| 1454 | +test-srcs-$(OPTION_EGLIBC_FTRAVERSE) := ftwtest |
| 1455 | tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ |
| 1456 | - tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \ |
| 1457 | + tst-fcntl tst-statvfs \ |
| 1458 | tst-openat tst-unlinkat tst-fstatat tst-futimesat \ |
| 1459 | tst-renameat tst-fchownat tst-fchmodat tst-faccessat \ |
| 1460 | tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \ |
| 1461 | - tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \ |
| 1462 | + tst-mknodat tst-mkfifoat tst-ttyname_r \ |
| 1463 | tst-posix_fallocate |
| 1464 | +tests-$(OPTION_EGLIBC_FTRAVERSE) += bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 \ |
| 1465 | + bug-ftw5 |
| 1466 | |
| 1467 | ifeq ($(run-built-tests),yes) |
| 1468 | +ifeq (y,$(OPTION_EGLIBC_FTRAVERSE)) |
| 1469 | tests-special += $(objpfx)ftwtest.out |
| 1470 | endif |
| 1471 | +endif |
| 1472 | |
| 1473 | include ../Rules |
| 1474 | |
| 1475 | diff --git a/libidn/Makefile b/libidn/Makefile |
| 1476 | index 940fa52..43aad0c 100644 |
| 1477 | --- a/libidn/Makefile |
| 1478 | +++ b/libidn/Makefile |
| 1479 | @@ -16,6 +16,7 @@ |
| 1480 | # <http://www.gnu.org/licenses/>. |
| 1481 | |
| 1482 | # Makefile for libidn subdirectory of GNU C Library. |
| 1483 | +include ../option-groups.mak |
| 1484 | |
| 1485 | subdir := libidn |
| 1486 | |
| 1487 | @@ -23,8 +24,8 @@ include ../Makeconfig |
| 1488 | |
| 1489 | routines = idn-stub |
| 1490 | |
| 1491 | -extra-libs = libcidn |
| 1492 | -extra-libs-others = $(extra-libs) |
| 1493 | +extra-libs-$(OPTION_EGLIBC_IDN) = libcidn |
| 1494 | +extra-libs-others-y = $(extra-libs-y) |
| 1495 | |
| 1496 | libcidn-routines := punycode toutf8 nfkc stringprep rfc3454 profiles idna \ |
| 1497 | iconvme |
| 1498 | diff --git a/libidn/toutf8.c b/libidn/toutf8.c |
| 1499 | index c7e67ca..62df478 100644 |
| 1500 | --- a/libidn/toutf8.c |
| 1501 | +++ b/libidn/toutf8.c |
| 1502 | @@ -33,6 +33,11 @@ |
| 1503 | /* Get strlen. */ |
| 1504 | #include <string.h> |
| 1505 | |
| 1506 | +/* Get __OPTION_EGLIBC_LOCALE_CODE. */ |
| 1507 | +#ifdef _LIBC |
| 1508 | +# include <gnu/option-groups.h> |
| 1509 | +#endif |
| 1510 | + |
| 1511 | /* Get iconv_string. */ |
| 1512 | #include "iconvme.h" |
| 1513 | |
| 1514 | @@ -47,7 +52,11 @@ |
| 1515 | #endif |
| 1516 | |
| 1517 | #ifdef _LIBC |
| 1518 | -# define stringprep_locale_charset() nl_langinfo (CODESET) |
| 1519 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 1520 | +# define stringprep_locale_charset() nl_langinfo (CODESET) |
| 1521 | +# else |
| 1522 | +# define stringprep_locale_charset() "ANSI_X3.4-1968" |
| 1523 | +# endif |
| 1524 | #else |
| 1525 | /** |
| 1526 | * stringprep_locale_charset - return charset used in current locale |
| 1527 | diff --git a/libio/Makefile b/libio/Makefile |
| 1528 | index 7b3bcf9..27c9186 100644 |
| 1529 | --- a/libio/Makefile |
| 1530 | +++ b/libio/Makefile |
| 1531 | @@ -18,6 +18,8 @@ |
| 1532 | # |
| 1533 | # Specific makefile for libio. |
| 1534 | # |
| 1535 | +include ../option-groups.mak |
| 1536 | + |
| 1537 | subdir := libio |
| 1538 | |
| 1539 | include ../Makeconfig |
| 1540 | @@ -27,16 +29,13 @@ headers := stdio.h libio.h _G_config.h bits/stdio.h bits/stdio-lock.h \ |
| 1541 | |
| 1542 | routines := \ |
| 1543 | filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ |
| 1544 | - iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc \ |
| 1545 | + iofopncook iofputs iofread iofsetpos ioftell \ |
| 1546 | iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs \ |
| 1547 | ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc \ |
| 1548 | iovsprintf iovsscanf \ |
| 1549 | iofgetpos64 iofopen64 iofsetpos64 \ |
| 1550 | - fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ |
| 1551 | - iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u \ |
| 1552 | - putwchar putwchar_u putchar putchar_u fwprintf swprintf vwprintf \ |
| 1553 | - wprintf wscanf fwscanf vwscanf vswprintf iovswscanf swscanf wgenops \ |
| 1554 | - wstrops wfileops iofwide fwide wmemstream \ |
| 1555 | + putchar putchar_u \ |
| 1556 | + iofwide \ |
| 1557 | \ |
| 1558 | clearerr feof ferror fileno fputc freopen fseek getc getchar \ |
| 1559 | memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \ |
| 1560 | @@ -48,24 +47,49 @@ routines := \ |
| 1561 | \ |
| 1562 | libc_fatal fmemopen oldfmemopen |
| 1563 | |
| 1564 | -tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ |
| 1565 | - tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \ |
| 1566 | - tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf \ |
| 1567 | - tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof \ |
| 1568 | - tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \ |
| 1569 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \ |
| 1570 | + wfiledoalloc \ |
| 1571 | + iowpadn \ |
| 1572 | + swprintf \ |
| 1573 | + vswprintf iovswscanf swscanf wgenops \ |
| 1574 | + wstrops wfileops wmemstream |
| 1575 | +routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += \ |
| 1576 | + wdummyfileops |
| 1577 | +routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += \ |
| 1578 | + fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ |
| 1579 | + iofputws iofputws_u iogetwline ioungetwc putwc putwc_u \ |
| 1580 | + putwchar putwchar_u fwprintf vwprintf \ |
| 1581 | + wprintf wscanf fwscanf vwscanf \ |
| 1582 | + fwide |
| 1583 | + |
| 1584 | +tests = test-fmemopen tst-ext tst-ext2 \ |
| 1585 | + tst-mmap-setvbuf tst-atime tst-eof \ |
| 1586 | + tst-freopen bug-ungetc bug-fseek \ |
| 1587 | tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \ |
| 1588 | - tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \ |
| 1589 | - bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \ |
| 1590 | + tst-mmap2-eofsync tst-mmap-offend bug-fopena+ \ |
| 1591 | + bug-ungetc2 bug-ungetc3 bug-ungetc4 \ |
| 1592 | tst-memstream1 tst-memstream2 \ |
| 1593 | - tst-wmemstream1 tst-wmemstream2 \ |
| 1594 | - bug-memstream1 bug-wmemstream1 \ |
| 1595 | - tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ |
| 1596 | - tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ |
| 1597 | - tst-ftell-append tst-fputws |
| 1598 | + bug-memstream1 tst-popen1 tst-fwrite-error \ |
| 1599 | + tst-ftell-active-handler tst-ftell-append |
| 1600 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 1601 | + += tst-swscanf tst-fgetws tst-setvbuf1 \ |
| 1602 | + tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2 \ |
| 1603 | + tst-widetext tst-fputws |
| 1604 | +tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ |
| 1605 | + += bug-rewind bug-rewind2 bug-ungetwc1 \ |
| 1606 | + bug-wfflush bug-wmemstream1 tst-fopenloc2 \ |
| 1607 | + tst_getwc \ |
| 1608 | + tst_putwc tst_wprintf tst_wprintf2 tst_wscanf \ |
| 1609 | + tst-fgetwc bug-wsetpos tst-fseek tst-ftell-partial-wide |
| 1610 | +tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 1611 | + += tst_swprintf tst_swscanf \ |
| 1612 | + tst-sscanf \ |
| 1613 | + tst-wmemstream1 tst-wmemstream2 |
| 1614 | + |
| 1615 | ifeq (yes,$(build-shared)) |
| 1616 | # Add test-fopenloc only if shared library is enabled since it depends on |
| 1617 | # shared localedata objects. |
| 1618 | -tests += tst-fopenloc |
| 1619 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-fopenloc |
| 1620 | endif |
| 1621 | test-srcs = test-freopen |
| 1622 | |
| 1623 | @@ -164,13 +188,17 @@ shared-only-routines = oldiofopen oldiofdopen oldiofclose oldfileops \ |
| 1624 | oldiofsetpos64 |
| 1625 | |
| 1626 | ifeq ($(run-built-tests),yes) |
| 1627 | +ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)) |
| 1628 | tests-special += $(objpfx)test-freopen.out |
| 1629 | +endif |
| 1630 | +ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) |
| 1631 | ifeq (yes,$(build-shared)) |
| 1632 | # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared |
| 1633 | # library is enabled since they depend on tst-fopenloc.out. |
| 1634 | tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out |
| 1635 | endif |
| 1636 | endif |
| 1637 | +endif |
| 1638 | |
| 1639 | include ../Rules |
| 1640 | |
| 1641 | diff --git a/libio/__fpurge.c b/libio/__fpurge.c |
| 1642 | index 065cf61..e32a3e9 100644 |
| 1643 | --- a/libio/__fpurge.c |
| 1644 | +++ b/libio/__fpurge.c |
| 1645 | @@ -21,7 +21,7 @@ |
| 1646 | void |
| 1647 | __fpurge (FILE *fp) |
| 1648 | { |
| 1649 | - if (fp->_mode > 0) |
| 1650 | + if (_IO_is_wide (fp)) |
| 1651 | { |
| 1652 | /* Wide-char stream. */ |
| 1653 | if (_IO_in_backup (fp)) |
| 1654 | diff --git a/libio/fileops.c b/libio/fileops.c |
| 1655 | index cbcd6f5..19e43c2 100644 |
| 1656 | --- a/libio/fileops.c |
| 1657 | +++ b/libio/fileops.c |
| 1658 | @@ -39,6 +39,7 @@ |
| 1659 | #include <string.h> |
| 1660 | #include <errno.h> |
| 1661 | #include <unistd.h> |
| 1662 | +#include <gnu/option-groups.h> |
| 1663 | #include <stdlib.h> |
| 1664 | #if _LIBC |
| 1665 | # include "../wcsmbs/wcsmbsload.h" |
| 1666 | @@ -173,7 +174,7 @@ _IO_new_file_close_it (_IO_FILE *fp) |
| 1667 | |
| 1668 | /* Free buffer. */ |
| 1669 | #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T |
| 1670 | - if (fp->_mode > 0) |
| 1671 | + if (_IO_is_wide (fp)) |
| 1672 | { |
| 1673 | if (_IO_have_wbackup (fp)) |
| 1674 | _IO_free_wbackup_area (fp); |
| 1675 | @@ -348,6 +349,7 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode, |
| 1676 | cs = strstr (last_recognized + 1, ",ccs="); |
| 1677 | if (cs != NULL) |
| 1678 | { |
| 1679 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 1680 | /* Yep. Load the appropriate conversions and set the orientation |
| 1681 | to wide. */ |
| 1682 | struct gconv_fcts fcts; |
| 1683 | @@ -418,6 +420,12 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode, |
| 1684 | |
| 1685 | /* Set the mode now. */ |
| 1686 | result->_mode = 1; |
| 1687 | +#else |
| 1688 | + /* Treat this as if we couldn't find the given character set. */ |
| 1689 | + (void) _IO_file_close_it (fp); |
| 1690 | + __set_errno (EINVAL); |
| 1691 | + return NULL; |
| 1692 | +#endif |
| 1693 | } |
| 1694 | } |
| 1695 | |
| 1696 | diff --git a/libio/iofwide.c b/libio/iofwide.c |
| 1697 | index 0c175d1..3e9f52b 100644 |
| 1698 | --- a/libio/iofwide.c |
| 1699 | +++ b/libio/iofwide.c |
| 1700 | @@ -26,6 +26,7 @@ |
| 1701 | |
| 1702 | #include <libioP.h> |
| 1703 | #ifdef _LIBC |
| 1704 | +# include <gnu/option-groups.h> |
| 1705 | # include <dlfcn.h> |
| 1706 | # include <wchar.h> |
| 1707 | #endif |
| 1708 | @@ -43,6 +44,8 @@ |
| 1709 | #endif |
| 1710 | |
| 1711 | |
| 1712 | +#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 1713 | + |
| 1714 | /* Prototypes of libio's codecvt functions. */ |
| 1715 | static enum __codecvt_result do_out (struct _IO_codecvt *codecvt, |
| 1716 | __mbstate_t *statep, |
| 1717 | @@ -499,3 +502,26 @@ do_max_length (struct _IO_codecvt *codecvt) |
| 1718 | return MB_CUR_MAX; |
| 1719 | #endif |
| 1720 | } |
| 1721 | + |
| 1722 | +#else |
| 1723 | +/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled. */ |
| 1724 | + |
| 1725 | +#undef _IO_fwide |
| 1726 | +int |
| 1727 | +_IO_fwide (fp, mode) |
| 1728 | + _IO_FILE *fp; |
| 1729 | + int mode; |
| 1730 | +{ |
| 1731 | + /* Die helpfully if the user tries to create a wide stream; I |
| 1732 | + disbelieve that most users check the return value from |
| 1733 | + 'fwide (fp, 1)'. */ |
| 1734 | + assert (mode <= 0); |
| 1735 | + |
| 1736 | + /* We can only make streams byte-oriented, which is trivial. */ |
| 1737 | + if (mode < 0) |
| 1738 | + fp->_mode = -1; |
| 1739 | + |
| 1740 | + return fp->_mode; |
| 1741 | +} |
| 1742 | + |
| 1743 | +#endif |
| 1744 | diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c |
| 1745 | index 11765cf..15d6230 100644 |
| 1746 | --- a/libio/ioseekoff.c |
| 1747 | +++ b/libio/ioseekoff.c |
| 1748 | @@ -60,7 +60,7 @@ _IO_seekoff_unlocked (fp, offset, dir, mode) |
| 1749 | else |
| 1750 | abort (); |
| 1751 | } |
| 1752 | - if (_IO_fwide (fp, 0) < 0) |
| 1753 | + if (! _IO_is_wide (fp)) |
| 1754 | _IO_free_backup_area (fp); |
| 1755 | else |
| 1756 | _IO_free_wbackup_area (fp); |
| 1757 | diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c |
| 1758 | index a7652a1..6938b68 100644 |
| 1759 | --- a/libio/ioseekpos.c |
| 1760 | +++ b/libio/ioseekpos.c |
| 1761 | @@ -35,7 +35,7 @@ _IO_seekpos_unlocked (fp, pos, mode) |
| 1762 | /* If we have a backup buffer, get rid of it, since the __seekoff |
| 1763 | callback may not know to do the right thing about it. |
| 1764 | This may be over-kill, but it'll do for now. TODO */ |
| 1765 | - if (_IO_fwide (fp, 0) <= 0) |
| 1766 | + if (! _IO_is_wide (fp)) |
| 1767 | { |
| 1768 | if (_IO_have_backup (fp)) |
| 1769 | _IO_free_backup_area (fp); |
| 1770 | diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c |
| 1771 | index 0a41c10..3d99fa0 100644 |
| 1772 | --- a/libio/iosetbuffer.c |
| 1773 | +++ b/libio/iosetbuffer.c |
| 1774 | @@ -24,6 +24,8 @@ |
| 1775 | This exception applies to code released by its copyright holders |
| 1776 | in files containing the exception. */ |
| 1777 | |
| 1778 | +#include <gnu/option-groups.h> |
| 1779 | + |
| 1780 | #include "libioP.h" |
| 1781 | |
| 1782 | void |
| 1783 | @@ -38,9 +40,11 @@ _IO_setbuffer (fp, buf, size) |
| 1784 | if (!buf) |
| 1785 | size = 0; |
| 1786 | (void) _IO_SETBUF (fp, buf, size); |
| 1787 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 1788 | if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp)) |
| 1789 | /* We also have to set the buffer using the wide char function. */ |
| 1790 | (void) _IO_WSETBUF (fp, buf, size); |
| 1791 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 1792 | _IO_release_lock (fp); |
| 1793 | } |
| 1794 | libc_hidden_def (_IO_setbuffer) |
| 1795 | diff --git a/libio/libioP.h b/libio/libioP.h |
| 1796 | index 0f16e2d..d2626d6 100644 |
| 1797 | --- a/libio/libioP.h |
| 1798 | +++ b/libio/libioP.h |
| 1799 | @@ -44,6 +44,10 @@ |
| 1800 | /*# include <comthread.h>*/ |
| 1801 | #endif |
| 1802 | |
| 1803 | +#if defined _LIBC |
| 1804 | +# include <gnu/option-groups.h> |
| 1805 | +#endif |
| 1806 | + |
| 1807 | #include <math_ldbl_opt.h> |
| 1808 | |
| 1809 | #include "iolibio.h" |
| 1810 | @@ -523,8 +527,20 @@ extern void _IO_old_init (_IO_FILE *fp, int flags) __THROW; |
| 1811 | |
| 1812 | |
| 1813 | #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T |
| 1814 | + |
| 1815 | +/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0', |
| 1816 | + except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it |
| 1817 | + expands to a constant, allowing the compiler to realize that it can |
| 1818 | + eliminate code that references wide stream handling functions. |
| 1819 | + This, in turn, allows us to omit them. */ |
| 1820 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 1821 | +# define _IO_is_wide(_f) ((_f)->_mode > 0) |
| 1822 | +#else |
| 1823 | +# define _IO_is_wide(_f) (0) |
| 1824 | +#endif |
| 1825 | + |
| 1826 | # define _IO_do_flush(_f) \ |
| 1827 | - ((_f)->_mode <= 0 \ |
| 1828 | + (! _IO_is_wide (_f) \ |
| 1829 | ? _IO_do_write(_f, (_f)->_IO_write_base, \ |
| 1830 | (_f)->_IO_write_ptr-(_f)->_IO_write_base) \ |
| 1831 | : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base, \ |
| 1832 | diff --git a/libio/wdummyfileops.c b/libio/wdummyfileops.c |
| 1833 | new file mode 100644 |
| 1834 | index 0000000..c0150b8 |
| 1835 | --- /dev/null |
| 1836 | +++ b/libio/wdummyfileops.c |
| 1837 | @@ -0,0 +1,161 @@ |
| 1838 | +/* Copyright (C) 2007 Free Software Foundation, Inc. |
| 1839 | + This file is part of the GNU C Library. |
| 1840 | + |
| 1841 | + The GNU C Library is free software; you can redistribute it and/or |
| 1842 | + modify it under the terms of the GNU Lesser General Public |
| 1843 | + License as published by the Free Software Foundation; either |
| 1844 | + version 2.1 of the License, or (at your option) any later version. |
| 1845 | + |
| 1846 | + The GNU C Library is distributed in the hope that it will be useful, |
| 1847 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1848 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 1849 | + Lesser General Public License for more details. |
| 1850 | + |
| 1851 | + You should have received a copy of the GNU Lesser General Public |
| 1852 | + License along with the GNU C Library; if not, write to the Free |
| 1853 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 1854 | + 02111-1307 USA. |
| 1855 | + |
| 1856 | + As a special exception, if you link the code in this file with |
| 1857 | + files compiled with a GNU compiler to produce an executable, |
| 1858 | + that does not cause the resulting executable to be covered by |
| 1859 | + the GNU Lesser General Public License. This exception does not |
| 1860 | + however invalidate any other reasons why the executable file |
| 1861 | + might be covered by the GNU Lesser General Public License. |
| 1862 | + This exception applies to code released by its copyright holders |
| 1863 | + in files containing the exception. */ |
| 1864 | + |
| 1865 | +#include <assert.h> |
| 1866 | +#include <stdio.h> |
| 1867 | +#include <stdlib.h> |
| 1868 | +#include <libioP.h> |
| 1869 | + |
| 1870 | +static void __THROW __attribute__ ((__noreturn__)) |
| 1871 | +_IO_wfile_wide_char_support_disabled (void) |
| 1872 | +{ |
| 1873 | + static const char errstr[] |
| 1874 | + = ("The application tried to use wide character I/O, but libc.so" |
| 1875 | + " was compiled\n" |
| 1876 | + "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n"); |
| 1877 | + __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); |
| 1878 | + abort (); |
| 1879 | +} |
| 1880 | + |
| 1881 | +static void |
| 1882 | +_IO_wfile_disabled_void_int (_IO_FILE *fp, int x) |
| 1883 | +{ |
| 1884 | + _IO_wfile_wide_char_support_disabled (); |
| 1885 | +} |
| 1886 | + |
| 1887 | +static int |
| 1888 | +_IO_wfile_disabled_int_int (_IO_FILE *fp, int x) |
| 1889 | +{ |
| 1890 | + _IO_wfile_wide_char_support_disabled (); |
| 1891 | +} |
| 1892 | + |
| 1893 | +static int |
| 1894 | +_IO_wfile_disabled_int_none (_IO_FILE *fp) |
| 1895 | +{ |
| 1896 | + _IO_wfile_wide_char_support_disabled (); |
| 1897 | +} |
| 1898 | + |
| 1899 | +static _IO_size_t |
| 1900 | +_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n) |
| 1901 | +{ |
| 1902 | + _IO_wfile_wide_char_support_disabled (); |
| 1903 | +} |
| 1904 | + |
| 1905 | +static _IO_size_t |
| 1906 | +_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) |
| 1907 | +{ |
| 1908 | + _IO_wfile_wide_char_support_disabled (); |
| 1909 | +} |
| 1910 | + |
| 1911 | +static _IO_off64_t |
| 1912 | +_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode) |
| 1913 | +{ |
| 1914 | + _IO_wfile_wide_char_support_disabled (); |
| 1915 | +} |
| 1916 | + |
| 1917 | +static _IO_off64_t |
| 1918 | +_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags) |
| 1919 | +{ |
| 1920 | + _IO_wfile_wide_char_support_disabled (); |
| 1921 | +} |
| 1922 | + |
| 1923 | +static _IO_FILE * |
| 1924 | +_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length) |
| 1925 | +{ |
| 1926 | + _IO_wfile_wide_char_support_disabled (); |
| 1927 | +} |
| 1928 | + |
| 1929 | +static _IO_ssize_t |
| 1930 | +_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length) |
| 1931 | +{ |
| 1932 | + _IO_wfile_wide_char_support_disabled (); |
| 1933 | +} |
| 1934 | + |
| 1935 | +static _IO_ssize_t |
| 1936 | +_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length) |
| 1937 | +{ |
| 1938 | + _IO_wfile_wide_char_support_disabled (); |
| 1939 | +} |
| 1940 | + |
| 1941 | +static _IO_off64_t |
| 1942 | +_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode) |
| 1943 | +{ |
| 1944 | + _IO_wfile_wide_char_support_disabled (); |
| 1945 | +} |
| 1946 | + |
| 1947 | +static int |
| 1948 | +_IO_wfile_disabled_close (_IO_FILE *fp) |
| 1949 | +{ |
| 1950 | + _IO_wfile_wide_char_support_disabled (); |
| 1951 | +} |
| 1952 | + |
| 1953 | +static int |
| 1954 | +_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf) |
| 1955 | +{ |
| 1956 | + _IO_wfile_wide_char_support_disabled (); |
| 1957 | +} |
| 1958 | + |
| 1959 | +static int |
| 1960 | +_IO_wfile_disabled_showmanyc (_IO_FILE *fp) |
| 1961 | +{ |
| 1962 | + _IO_wfile_wide_char_support_disabled (); |
| 1963 | +} |
| 1964 | + |
| 1965 | +static void |
| 1966 | +_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale) |
| 1967 | +{ |
| 1968 | + _IO_wfile_wide_char_support_disabled (); |
| 1969 | +} |
| 1970 | + |
| 1971 | +static const struct _IO_jump_t _IO_wfile_jumps_disabled = |
| 1972 | +{ |
| 1973 | + JUMP_INIT_DUMMY, |
| 1974 | + JUMP_INIT(finish, _IO_wfile_disabled_void_int), |
| 1975 | + JUMP_INIT(overflow, _IO_wfile_disabled_int_int), |
| 1976 | + JUMP_INIT(underflow, _IO_wfile_disabled_int_none), |
| 1977 | + JUMP_INIT(uflow, _IO_wfile_disabled_int_none), |
| 1978 | + JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int), |
| 1979 | + JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn), |
| 1980 | + JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn), |
| 1981 | + JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff), |
| 1982 | + JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos), |
| 1983 | + JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf), |
| 1984 | + JUMP_INIT(sync, _IO_wfile_disabled_int_none), |
| 1985 | + JUMP_INIT(doallocate, _IO_wfile_disabled_int_none), |
| 1986 | + JUMP_INIT(read, _IO_wfile_disabled_read), |
| 1987 | + JUMP_INIT(write, _IO_wfile_disabled_write), |
| 1988 | + JUMP_INIT(seek, _IO_wfile_disabled_seek), |
| 1989 | + JUMP_INIT(close, _IO_wfile_disabled_close), |
| 1990 | + JUMP_INIT(stat, _IO_wfile_disabled_stat), |
| 1991 | + JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc), |
| 1992 | + JUMP_INIT(imbue, _IO_wfile_disabled_imbue) |
| 1993 | +}; |
| 1994 | + |
| 1995 | +strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps) |
| 1996 | +libc_hidden_data_def (_IO_wfile_jumps) |
| 1997 | +strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap) |
| 1998 | +strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap) |
| 1999 | diff --git a/locale/C-ctype.c b/locale/C-ctype.c |
| 2000 | index aa5f19f..06be081 100644 |
| 2001 | --- a/locale/C-ctype.c |
| 2002 | +++ b/locale/C-ctype.c |
| 2003 | @@ -19,8 +19,11 @@ |
| 2004 | #include "localeinfo.h" |
| 2005 | #include <endian.h> |
| 2006 | #include <stdint.h> |
| 2007 | +#include <gnu/option-groups.h> |
| 2008 | |
| 2009 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 2010 | #include "C-translit.h" |
| 2011 | +#endif |
| 2012 | |
| 2013 | /* This table's entries are taken from POSIX.2 Table 2-6 |
| 2014 | ``LC_CTYPE Category Definition in the POSIX Locale''. |
| 2015 | @@ -634,6 +637,7 @@ const struct __locale_data _nl_C_LC_CTYPE attribute_hidden = |
| 2016 | { .word = L'7' }, |
| 2017 | { .word = L'8' }, |
| 2018 | { .word = L'9' }, |
| 2019 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 2020 | /* _NL_CTYPE_TRANSLIT_TAB_SIZE */ |
| 2021 | { .word = NTRANSLIT }, |
| 2022 | /* _NL_CTYPE_TRANSLIT_FROM_IDX */ |
| 2023 | @@ -644,6 +648,22 @@ const struct __locale_data _nl_C_LC_CTYPE attribute_hidden = |
| 2024 | { .wstr = translit_to_idx }, |
| 2025 | /* _NL_CTYPE_TRANSLIT_TO_TBL */ |
| 2026 | { .wstr = (uint32_t *) translit_to_tbl }, |
| 2027 | +#else |
| 2028 | + /* If the locale code isn't enabled, we don't have the |
| 2029 | + transliteration code in iconv/gconv_trans.c anyway, so there's |
| 2030 | + no need for the transliteration tables here. We'll fall back |
| 2031 | + on the default missing replacement, '?'. */ |
| 2032 | + /* _NL_CTYPE_TRANSLIT_TAB_SIZE */ |
| 2033 | + { .word = 0 }, |
| 2034 | + /* _NL_CTYPE_TRANSLIT_FROM_IDX */ |
| 2035 | + { .wstr = NULL }, |
| 2036 | + /* _NL_CTYPE_TRANSLIT_FROM_TBL */ |
| 2037 | + { .wstr = NULL }, |
| 2038 | + /* _NL_CTYPE_TRANSLIT_TO_IDX */ |
| 2039 | + { .wstr = NULL }, |
| 2040 | + /* _NL_CTYPE_TRANSLIT_TO_TBL */ |
| 2041 | + { .wstr = NULL }, |
| 2042 | +#endif |
| 2043 | /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN */ |
| 2044 | { .word = 1 }, |
| 2045 | /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING */ |
| 2046 | diff --git a/locale/Makefile b/locale/Makefile |
| 2047 | index f1b4343..599a1a9 100644 |
| 2048 | --- a/locale/Makefile |
| 2049 | +++ b/locale/Makefile |
| 2050 | @@ -18,27 +18,43 @@ |
| 2051 | # |
| 2052 | # Makefile for locales. |
| 2053 | # |
| 2054 | +include ../option-groups.mak |
| 2055 | + |
| 2056 | subdir := locale |
| 2057 | |
| 2058 | include ../Makeconfig |
| 2059 | |
| 2060 | headers = locale.h bits/locale.h langinfo.h xlocale.h |
| 2061 | -routines = setlocale findlocale loadlocale loadarchive \ |
| 2062 | - localeconv nl_langinfo nl_langinfo_l mb_cur_max \ |
| 2063 | - newlocale duplocale freelocale uselocale |
| 2064 | -tests = tst-C-locale tst-locname tst-duplocale |
| 2065 | +# catnames is needed by OPTION_EGLIBC_LOCALE_CODE and by the 'intl' code. |
| 2066 | +# If we put the latter in an option group, too, we can omit catnames |
| 2067 | +# when both option groups are disabled. libstdc++-v3 needs mb_cur_max. |
| 2068 | +routines-y := catnames mb_cur_max |
| 2069 | +routines-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 2070 | + += setlocale findlocale loadlocale loadarchive \ |
| 2071 | + localeconv nl_langinfo nl_langinfo_l \ |
| 2072 | + newlocale duplocale freelocale uselocale |
| 2073 | +ifneq (y,$(OPTION_EGLIBC_LOCALE_CODE)) |
| 2074 | +routines-y += dummy-setlocale |
| 2075 | +endif |
| 2076 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-C-locale tst-locname tst-duplocale |
| 2077 | categories = ctype messages monetary numeric time paper name \ |
| 2078 | address telephone measurement identification collate |
| 2079 | -aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ |
| 2080 | - xlocale localename global-locale coll-lookup |
| 2081 | -others = localedef locale |
| 2082 | +# C-messages belongs in an intl option group. |
| 2083 | +aux-y := C-ctype C-time \ |
| 2084 | + SYS_libc C_name xlocale global-locale coll-lookup |
| 2085 | +aux-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 2086 | + += $(filter-out $(aux-y), \ |
| 2087 | + $(categories:%=lc-%) $(categories:%=C-%)) \ |
| 2088 | + localename |
| 2089 | +others-$(OPTION_EGLIBC_LOCALE_CODE) = localedef locale |
| 2090 | #others-static = localedef locale |
| 2091 | -install-bin = localedef locale |
| 2092 | -extra-objs = $(localedef-modules:=.o) $(localedef-aux:=.o) \ |
| 2093 | +install-bin = $(others-y) |
| 2094 | +extra-objs-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 2095 | + = $(localedef-modules:=.o) $(localedef-aux:=.o) \ |
| 2096 | $(locale-modules:=.o) $(lib-modules:=.o) |
| 2097 | |
| 2098 | -extra-libs = libBrokenLocale |
| 2099 | -extra-libs-others = $(extra-libs) |
| 2100 | +extra-libs-$(OPTION_EGLIBC_LOCALE_CODE) = libBrokenLocale |
| 2101 | +extra-libs-others = $(extra-libs-y) |
| 2102 | |
| 2103 | libBrokenLocale-routines = broken_cur_max |
| 2104 | |
| 2105 | @@ -93,6 +109,9 @@ CPPFLAGS-locale-programs = -DLOCALE_PATH='$(localepath)' \ |
| 2106 | CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts |
| 2107 | CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts |
| 2108 | CFLAGS-charmap-dir.c = -Wno-write-strings |
| 2109 | +ifneq (y,$(OPTION_EGLIBC_SPAWN)) |
| 2110 | +CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS |
| 2111 | +endif |
| 2112 | |
| 2113 | # Set libof-* for each routine. |
| 2114 | cpp-srcs-left := $(localedef-modules) $(localedef-aux) $(locale-modules) \ |
| 2115 | diff --git a/locale/catnames.c b/locale/catnames.c |
| 2116 | new file mode 100644 |
| 2117 | index 0000000..9fad357 |
| 2118 | --- /dev/null |
| 2119 | +++ b/locale/catnames.c |
| 2120 | @@ -0,0 +1,48 @@ |
| 2121 | +/* Copyright (C) 2006 Free Software Foundation, Inc. |
| 2122 | + This file is part of the GNU C Library. |
| 2123 | + |
| 2124 | + The GNU C Library is free software; you can redistribute it and/or |
| 2125 | + modify it under the terms of the GNU Lesser General Public |
| 2126 | + License as published by the Free Software Foundation; either |
| 2127 | + version 2.1 of the License, or (at your option) any later version. |
| 2128 | + |
| 2129 | + The GNU C Library is distributed in the hope that it will be useful, |
| 2130 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2131 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 2132 | + Lesser General Public License for more details. |
| 2133 | + |
| 2134 | + You should have received a copy of the GNU Lesser General Public |
| 2135 | + License along with the GNU C Library; if not, write to the Free |
| 2136 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 2137 | + 02111-1307 USA. */ |
| 2138 | + |
| 2139 | +#include "localeinfo.h" |
| 2140 | + |
| 2141 | +/* Define an array of category names (also the environment variable names). */ |
| 2142 | +const union catnamestr_t _nl_category_names attribute_hidden = |
| 2143 | + { |
| 2144 | + { |
| 2145 | +#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2146 | + category_name, |
| 2147 | +#include "categories.def" |
| 2148 | +#undef DEFINE_CATEGORY |
| 2149 | + } |
| 2150 | + }; |
| 2151 | + |
| 2152 | +const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = |
| 2153 | + { |
| 2154 | +#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2155 | + [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), |
| 2156 | +#include "categories.def" |
| 2157 | +#undef DEFINE_CATEGORY |
| 2158 | + }; |
| 2159 | + |
| 2160 | +/* An array of their lengths, for convenience. */ |
| 2161 | +const uint8_t _nl_category_name_sizes[] attribute_hidden = |
| 2162 | + { |
| 2163 | +#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2164 | + [category] = sizeof (category_name) - 1, |
| 2165 | +#include "categories.def" |
| 2166 | +#undef DEFINE_CATEGORY |
| 2167 | + [LC_ALL] = sizeof ("LC_ALL") - 1 |
| 2168 | + }; |
| 2169 | diff --git a/locale/dummy-setlocale.c b/locale/dummy-setlocale.c |
| 2170 | new file mode 100644 |
| 2171 | index 0000000..219964a |
| 2172 | --- /dev/null |
| 2173 | +++ b/locale/dummy-setlocale.c |
| 2174 | @@ -0,0 +1,33 @@ |
| 2175 | +/* Copyright (C) 2006 Free Software Foundation, Inc. |
| 2176 | + This file is part of the GNU C Library. |
| 2177 | + |
| 2178 | + The GNU C Library is free software; you can redistribute it and/or |
| 2179 | + modify it under the terms of the GNU Lesser General Public |
| 2180 | + License as published by the Free Software Foundation; either |
| 2181 | + version 2.1 of the License, or (at your option) any later version. |
| 2182 | + |
| 2183 | + The GNU C Library is distributed in the hope that it will be useful, |
| 2184 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2185 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 2186 | + Lesser General Public License for more details. |
| 2187 | + |
| 2188 | + You should have received a copy of the GNU Lesser General Public |
| 2189 | + License along with the GNU C Library; if not, write to the Free |
| 2190 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 2191 | + 02111-1307 USA. */ |
| 2192 | + |
| 2193 | +#include <string.h> |
| 2194 | +#include <locale.h> |
| 2195 | + |
| 2196 | +char * |
| 2197 | +setlocale (int category, const char *locale) |
| 2198 | +{ |
| 2199 | + if (! locale |
| 2200 | + || locale[0] == '\0' |
| 2201 | + || strcmp (locale, "C") == 0 |
| 2202 | + || strcmp (locale, "POSIX") == 0) |
| 2203 | + return (char *) "C"; |
| 2204 | + else |
| 2205 | + return NULL; |
| 2206 | +} |
| 2207 | +libc_hidden_def (setlocale) |
| 2208 | diff --git a/locale/localeinfo.h b/locale/localeinfo.h |
| 2209 | index bdab9fe..a7516c0 100644 |
| 2210 | --- a/locale/localeinfo.h |
| 2211 | +++ b/locale/localeinfo.h |
| 2212 | @@ -232,7 +232,7 @@ __libc_tsd_define (extern, __locale_t, LOCALE) |
| 2213 | unused. We can manage this playing some tricks with weak references. |
| 2214 | But with thread-local locale settings, it becomes quite ungainly unless |
| 2215 | we can use __thread variables. So only in that case do we attempt this. */ |
| 2216 | -#ifndef SHARED |
| 2217 | +#if !defined SHARED && !defined IN_GLIBC_LOCALEDEF |
| 2218 | # include <tls.h> |
| 2219 | # define NL_CURRENT_INDIRECT 1 |
| 2220 | #endif |
| 2221 | diff --git a/locale/programs/charmap-dir.c b/locale/programs/charmap-dir.c |
| 2222 | index cf7adea..ef3b811 100644 |
| 2223 | --- a/locale/programs/charmap-dir.c |
| 2224 | +++ b/locale/programs/charmap-dir.c |
| 2225 | @@ -19,7 +19,9 @@ |
| 2226 | #include <error.h> |
| 2227 | #include <fcntl.h> |
| 2228 | #include <libintl.h> |
| 2229 | +#ifndef NO_UNCOMPRESS |
| 2230 | #include <spawn.h> |
| 2231 | +#endif |
| 2232 | #include <stdio.h> |
| 2233 | #include <stdlib.h> |
| 2234 | #include <string.h> |
| 2235 | @@ -156,6 +158,7 @@ charmap_closedir (CHARMAP_DIR *cdir) |
| 2236 | return closedir (dir); |
| 2237 | } |
| 2238 | |
| 2239 | +#ifndef NO_UNCOMPRESS |
| 2240 | /* Creates a subprocess decompressing the given pathname, and returns |
| 2241 | a stream reading its output (the decompressed data). */ |
| 2242 | static |
| 2243 | @@ -204,6 +207,7 @@ fopen_uncompressed (const char *pathname, const char *compressor) |
| 2244 | } |
| 2245 | return NULL; |
| 2246 | } |
| 2247 | +#endif |
| 2248 | |
| 2249 | /* Opens a charmap for reading, given its name (not an alias name). */ |
| 2250 | FILE * |
| 2251 | @@ -226,6 +230,7 @@ charmap_open (const char *directory, const char *name) |
| 2252 | if (stream != NULL) |
| 2253 | return stream; |
| 2254 | |
| 2255 | +#ifndef NO_UNCOMPRESS |
| 2256 | memcpy (p, ".gz", 4); |
| 2257 | stream = fopen_uncompressed (pathname, "gzip"); |
| 2258 | if (stream != NULL) |
| 2259 | @@ -235,6 +240,7 @@ charmap_open (const char *directory, const char *name) |
| 2260 | stream = fopen_uncompressed (pathname, "bzip2"); |
| 2261 | if (stream != NULL) |
| 2262 | return stream; |
| 2263 | +#endif |
| 2264 | |
| 2265 | return NULL; |
| 2266 | } |
| 2267 | diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c |
| 2268 | index a39a94f..16e9039 100644 |
| 2269 | --- a/locale/programs/ld-collate.c |
| 2270 | +++ b/locale/programs/ld-collate.c |
| 2271 | @@ -351,7 +351,7 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen, |
| 2272 | } |
| 2273 | if (wcs != NULL) |
| 2274 | { |
| 2275 | - size_t nwcs = wcslen ((wchar_t *) wcs); |
| 2276 | + size_t nwcs = wcslen_uint32 (wcs); |
| 2277 | uint32_t zero = 0; |
| 2278 | /* Handle <U0000> as a single character. */ |
| 2279 | if (nwcs == 0) |
| 2280 | @@ -1777,8 +1777,7 @@ symbol `%s' has the same encoding as"), (*eptr)->name); |
| 2281 | |
| 2282 | if ((*eptr)->nwcs == runp->nwcs) |
| 2283 | { |
| 2284 | - int c = wmemcmp ((wchar_t *) (*eptr)->wcs, |
| 2285 | - (wchar_t *) runp->wcs, runp->nwcs); |
| 2286 | + int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs); |
| 2287 | |
| 2288 | if (c == 0) |
| 2289 | { |
| 2290 | @@ -2011,9 +2010,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp) |
| 2291 | one consecutive entry. */ |
| 2292 | if (runp->wcnext != NULL |
| 2293 | && runp->nwcs == runp->wcnext->nwcs |
| 2294 | - && wmemcmp ((wchar_t *) runp->wcs, |
| 2295 | - (wchar_t *)runp->wcnext->wcs, |
| 2296 | - runp->nwcs - 1) == 0 |
| 2297 | + && wmemcmp_uint32 (runp->wcs, |
| 2298 | + runp->wcnext->wcs, |
| 2299 | + runp->nwcs - 1) == 0 |
| 2300 | && (runp->wcs[runp->nwcs - 1] |
| 2301 | == runp->wcnext->wcs[runp->nwcs - 1] + 1)) |
| 2302 | { |
| 2303 | @@ -2037,9 +2036,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp) |
| 2304 | runp = runp->wcnext; |
| 2305 | while (runp->wcnext != NULL |
| 2306 | && runp->nwcs == runp->wcnext->nwcs |
| 2307 | - && wmemcmp ((wchar_t *) runp->wcs, |
| 2308 | - (wchar_t *)runp->wcnext->wcs, |
| 2309 | - runp->nwcs - 1) == 0 |
| 2310 | + && wmemcmp_uint32 (runp->wcs, |
| 2311 | + runp->wcnext->wcs, |
| 2312 | + runp->nwcs - 1) == 0 |
| 2313 | && (runp->wcs[runp->nwcs - 1] |
| 2314 | == runp->wcnext->wcs[runp->nwcs - 1] + 1)); |
| 2315 | |
| 2316 | diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c |
| 2317 | index 3f464ef..b7b6b51 100644 |
| 2318 | --- a/locale/programs/ld-ctype.c |
| 2319 | +++ b/locale/programs/ld-ctype.c |
| 2320 | @@ -926,7 +926,7 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap, |
| 2321 | allocate_arrays (ctype, charmap, ctype->repertoire); |
| 2322 | |
| 2323 | default_missing_len = (ctype->default_missing |
| 2324 | - ? wcslen ((wchar_t *) ctype->default_missing) |
| 2325 | + ? wcslen_uint32 (ctype->default_missing) |
| 2326 | : 0); |
| 2327 | |
| 2328 | init_locale_data (&file, nelems); |
| 2329 | @@ -1937,7 +1937,7 @@ read_translit_entry (struct linereader *ldfile, struct locale_ctype_t *ctype, |
| 2330 | ignore = 1; |
| 2331 | else |
| 2332 | /* This value is usable. */ |
| 2333 | - obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4); |
| 2334 | + obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4); |
| 2335 | |
| 2336 | first = 0; |
| 2337 | } |
| 2338 | @@ -2471,8 +2471,8 @@ with character code range values one must use the absolute ellipsis `...'")); |
| 2339 | } |
| 2340 | |
| 2341 | handle_tok_digit: |
| 2342 | - class_bit = _ISwdigit; |
| 2343 | - class256_bit = _ISdigit; |
| 2344 | + class_bit = BITw (tok_digit); |
| 2345 | + class256_bit = BIT (tok_digit); |
| 2346 | handle_digits = 1; |
| 2347 | goto read_charclass; |
| 2348 | |
| 2349 | @@ -3929,8 +3929,7 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap, |
| 2350 | |
| 2351 | while (idx < number) |
| 2352 | { |
| 2353 | - int res = wcscmp ((const wchar_t *) sorted[idx]->from, |
| 2354 | - (const wchar_t *) runp->from); |
| 2355 | + int res = wcscmp_uint32 (sorted[idx]->from, runp->from); |
| 2356 | if (res == 0) |
| 2357 | { |
| 2358 | replace = 1; |
| 2359 | @@ -3967,11 +3966,11 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap, |
| 2360 | for (size_t cnt = 0; cnt < number; ++cnt) |
| 2361 | { |
| 2362 | struct translit_to_t *srunp; |
| 2363 | - from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1; |
| 2364 | + from_len += wcslen_uint32 (sorted[cnt]->from) + 1; |
| 2365 | srunp = sorted[cnt]->to; |
| 2366 | while (srunp != NULL) |
| 2367 | { |
| 2368 | - to_len += wcslen ((const wchar_t *) srunp->str) + 1; |
| 2369 | + to_len += wcslen_uint32 (srunp->str) + 1; |
| 2370 | srunp = srunp->next; |
| 2371 | } |
| 2372 | /* Plus one for the extra NUL character marking the end of |
| 2373 | @@ -3995,18 +3994,18 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap, |
| 2374 | ctype->translit_from_idx[cnt] = from_len; |
| 2375 | ctype->translit_to_idx[cnt] = to_len; |
| 2376 | |
| 2377 | - len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1; |
| 2378 | - wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len], |
| 2379 | - (const wchar_t *) sorted[cnt]->from, len); |
| 2380 | + len = wcslen_uint32 (sorted[cnt]->from) + 1; |
| 2381 | + wmemcpy_uint32 (&ctype->translit_from_tbl[from_len], |
| 2382 | + sorted[cnt]->from, len); |
| 2383 | from_len += len; |
| 2384 | |
| 2385 | ctype->translit_to_idx[cnt] = to_len; |
| 2386 | srunp = sorted[cnt]->to; |
| 2387 | while (srunp != NULL) |
| 2388 | { |
| 2389 | - len = wcslen ((const wchar_t *) srunp->str) + 1; |
| 2390 | - wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len], |
| 2391 | - (const wchar_t *) srunp->str, len); |
| 2392 | + len = wcslen_uint32 (srunp->str) + 1; |
| 2393 | + wmemcpy_uint32 (&ctype->translit_to_tbl[to_len], |
| 2394 | + srunp->str, len); |
| 2395 | to_len += len; |
| 2396 | srunp = srunp->next; |
| 2397 | } |
| 2398 | diff --git a/locale/programs/ld-messages.c b/locale/programs/ld-messages.c |
| 2399 | index ec1a80b..736eed8 100644 |
| 2400 | --- a/locale/programs/ld-messages.c |
| 2401 | +++ b/locale/programs/ld-messages.c |
| 2402 | @@ -25,6 +25,7 @@ |
| 2403 | #include <string.h> |
| 2404 | #include <stdint.h> |
| 2405 | #include <sys/uio.h> |
| 2406 | +#include <gnu/option-groups.h> |
| 2407 | |
| 2408 | #include <assert.h> |
| 2409 | |
| 2410 | @@ -124,6 +125,7 @@ No definition for %s category found"), "LC_MESSAGES")); |
| 2411 | } |
| 2412 | else |
| 2413 | { |
| 2414 | +#if __OPTION_POSIX_REGEXP |
| 2415 | int result; |
| 2416 | regex_t re; |
| 2417 | |
| 2418 | @@ -140,6 +142,7 @@ No definition for %s category found"), "LC_MESSAGES")); |
| 2419 | } |
| 2420 | else if (result != 0) |
| 2421 | regfree (&re); |
| 2422 | +#endif |
| 2423 | } |
| 2424 | |
| 2425 | if (messages->noexpr == NULL) |
| 2426 | @@ -158,6 +161,7 @@ No definition for %s category found"), "LC_MESSAGES")); |
| 2427 | } |
| 2428 | else |
| 2429 | { |
| 2430 | +#if __OPTION_POSIX_REGEXP |
| 2431 | int result; |
| 2432 | regex_t re; |
| 2433 | |
| 2434 | @@ -174,6 +178,7 @@ No definition for %s category found"), "LC_MESSAGES")); |
| 2435 | } |
| 2436 | else if (result != 0) |
| 2437 | regfree (&re); |
| 2438 | +#endif |
| 2439 | } |
| 2440 | } |
| 2441 | |
| 2442 | diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c |
| 2443 | index db490c6..75dc505 100644 |
| 2444 | --- a/locale/programs/ld-time.c |
| 2445 | +++ b/locale/programs/ld-time.c |
| 2446 | @@ -215,8 +215,10 @@ No definition for %s category found"), "LC_TIME")); |
| 2447 | } |
| 2448 | else |
| 2449 | { |
| 2450 | + static const uint32_t wt_fmt_ampm[] |
| 2451 | + = { '%','I',':','%','M',':','%','S',' ','%','p',0 }; |
| 2452 | time->t_fmt_ampm = "%I:%M:%S %p"; |
| 2453 | - time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p"; |
| 2454 | + time->wt_fmt_ampm = wt_fmt_ampm; |
| 2455 | } |
| 2456 | } |
| 2457 | |
| 2458 | @@ -226,7 +228,7 @@ No definition for %s category found"), "LC_TIME")); |
| 2459 | const int days_per_month[12] = { 31, 29, 31, 30, 31, 30, |
| 2460 | 31, 31, 30, 31 ,30, 31 }; |
| 2461 | size_t idx; |
| 2462 | - wchar_t *wstr; |
| 2463 | + uint32_t *wstr; |
| 2464 | |
| 2465 | time->era_entries = |
| 2466 | (struct era_data *) xmalloc (time->num_era |
| 2467 | @@ -464,18 +466,18 @@ No definition for %s category found"), "LC_TIME")); |
| 2468 | } |
| 2469 | |
| 2470 | /* Now generate the wide character name and format. */ |
| 2471 | - wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */ |
| 2472 | - wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end offset */ |
| 2473 | - wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end start */ |
| 2474 | - wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end end */ |
| 2475 | + wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */ |
| 2476 | + wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */ |
| 2477 | + wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */ |
| 2478 | + wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */ |
| 2479 | if (wstr != NULL) |
| 2480 | { |
| 2481 | - time->era_entries[idx].wname = (uint32_t *) wstr + 1; |
| 2482 | - wstr = wcschr (wstr + 1, L':'); /* end name */ |
| 2483 | + time->era_entries[idx].wname = wstr + 1; |
| 2484 | + wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */ |
| 2485 | if (wstr != NULL) |
| 2486 | { |
| 2487 | *wstr = L'\0'; |
| 2488 | - time->era_entries[idx].wformat = (uint32_t *) wstr + 1; |
| 2489 | + time->era_entries[idx].wformat = wstr + 1; |
| 2490 | } |
| 2491 | else |
| 2492 | time->era_entries[idx].wname = |
| 2493 | @@ -530,7 +532,16 @@ No definition for %s category found"), "LC_TIME")); |
| 2494 | if (time->date_fmt == NULL) |
| 2495 | time->date_fmt = "%a %b %e %H:%M:%S %Z %Y"; |
| 2496 | if (time->wdate_fmt == NULL) |
| 2497 | - time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y"; |
| 2498 | + { |
| 2499 | + static const uint32_t wdate_fmt[] = |
| 2500 | + { '%','a',' ', |
| 2501 | + '%','b',' ', |
| 2502 | + '%','e',' ', |
| 2503 | + '%','H',':','%','M',':','%','S',' ', |
| 2504 | + '%','Z',' ', |
| 2505 | + '%','Y',0 }; |
| 2506 | + time->wdate_fmt = wdate_fmt; |
| 2507 | + } |
| 2508 | } |
| 2509 | |
| 2510 | |
| 2511 | diff --git a/locale/programs/linereader.c b/locale/programs/linereader.c |
| 2512 | index 2e05130..653b68c 100644 |
| 2513 | --- a/locale/programs/linereader.c |
| 2514 | +++ b/locale/programs/linereader.c |
| 2515 | @@ -595,7 +595,7 @@ get_string (struct linereader *lr, const struct charmap_t *charmap, |
| 2516 | { |
| 2517 | int return_widestr = lr->return_widestr; |
| 2518 | char *buf; |
| 2519 | - wchar_t *buf2 = NULL; |
| 2520 | + uint32_t *buf2 = NULL; |
| 2521 | size_t bufact; |
| 2522 | size_t bufmax = 56; |
| 2523 | |
| 2524 | diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c |
| 2525 | index 2a0f2aa..583d233 100644 |
| 2526 | --- a/locale/programs/localedef.c |
| 2527 | +++ b/locale/programs/localedef.c |
| 2528 | @@ -114,6 +114,7 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; |
| 2529 | #define OPT_LIST_ARCHIVE 309 |
| 2530 | #define OPT_LITTLE_ENDIAN 400 |
| 2531 | #define OPT_BIG_ENDIAN 401 |
| 2532 | +#define OPT_UINT32_ALIGN 402 |
| 2533 | |
| 2534 | /* Definitions of arguments for argp functions. */ |
| 2535 | static const struct argp_option options[] = |
| 2536 | @@ -150,6 +151,8 @@ static const struct argp_option options[] = |
| 2537 | N_("Generate little-endian output") }, |
| 2538 | { "big-endian", OPT_BIG_ENDIAN, NULL, 0, |
| 2539 | N_("Generate big-endian output") }, |
| 2540 | + { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0, |
| 2541 | + N_("Set the target's uint32_t alignment in bytes (default 4)") }, |
| 2542 | { NULL, 0, NULL, 0, NULL } |
| 2543 | }; |
| 2544 | |
| 2545 | @@ -239,12 +242,14 @@ main (int argc, char *argv[]) |
| 2546 | ctype locale. (P1003.2 4.35.5.2) */ |
| 2547 | setlocale (LC_CTYPE, "POSIX"); |
| 2548 | |
| 2549 | +#ifndef NO_SYSCONF |
| 2550 | /* Look whether the system really allows locale definitions. POSIX |
| 2551 | defines error code 3 for this situation so I think it must be |
| 2552 | a fatal error (see P1003.2 4.35.8). */ |
| 2553 | if (sysconf (_SC_2_LOCALEDEF) < 0) |
| 2554 | WITH_CUR_LOCALE (error (3, 0, _("\ |
| 2555 | FATAL: system does not define `_POSIX2_LOCALEDEF'"))); |
| 2556 | +#endif |
| 2557 | |
| 2558 | /* Process charmap file. */ |
| 2559 | charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1); |
| 2560 | @@ -338,6 +343,9 @@ parse_opt (int key, char *arg, struct argp_state *state) |
| 2561 | case OPT_BIG_ENDIAN: |
| 2562 | set_big_endian (true); |
| 2563 | break; |
| 2564 | + case OPT_UINT32_ALIGN: |
| 2565 | + uint32_align_mask = strtol (arg, NULL, 0) - 1; |
| 2566 | + break; |
| 2567 | case 'c': |
| 2568 | force_output = 1; |
| 2569 | break; |
| 2570 | diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c |
| 2571 | index 33da52e..f790c4c 100644 |
| 2572 | --- a/locale/programs/locfile.c |
| 2573 | +++ b/locale/programs/locfile.c |
| 2574 | @@ -544,6 +544,9 @@ compare_files (const char *filename1, const char *filename2, size_t size, |
| 2575 | machine running localedef. */ |
| 2576 | bool swap_endianness_p; |
| 2577 | |
| 2578 | +/* The target's value of __align__(uint32_t) - 1. */ |
| 2579 | +unsigned int uint32_align_mask = 3; |
| 2580 | + |
| 2581 | /* When called outside a start_locale_structure/end_locale_structure |
| 2582 | or start_locale_prelude/end_locale_prelude block, record that the |
| 2583 | next byte in FILE's obstack will be the first byte of a new element. |
| 2584 | @@ -621,7 +624,7 @@ add_locale_string (struct locale_file *file, const char *string) |
| 2585 | void |
| 2586 | add_locale_wstring (struct locale_file *file, const uint32_t *string) |
| 2587 | { |
| 2588 | - add_locale_uint32_array (file, string, wcslen ((const wchar_t *) string) + 1); |
| 2589 | + add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1); |
| 2590 | } |
| 2591 | |
| 2592 | /* Record that FILE's next element is the 32-bit integer VALUE. */ |
| 2593 | diff --git a/locale/programs/locfile.h b/locale/programs/locfile.h |
| 2594 | index 6fc441b..118b171 100644 |
| 2595 | --- a/locale/programs/locfile.h |
| 2596 | +++ b/locale/programs/locfile.h |
| 2597 | @@ -71,6 +71,8 @@ extern void write_all_categories (struct localedef_t *definitions, |
| 2598 | |
| 2599 | extern bool swap_endianness_p; |
| 2600 | |
| 2601 | +extern unsigned int uint32_align_mask; |
| 2602 | + |
| 2603 | /* Change the output to be big-endian if BIG_ENDIAN is true and |
| 2604 | little-endian otherwise. */ |
| 2605 | static inline void |
| 2606 | @@ -89,7 +91,8 @@ maybe_swap_uint32 (uint32_t value) |
| 2607 | } |
| 2608 | |
| 2609 | /* Likewise, but munge an array of N uint32_ts starting at ARRAY. */ |
| 2610 | -static inline void |
| 2611 | +static void |
| 2612 | +__attribute__ ((unused)) |
| 2613 | maybe_swap_uint32_array (uint32_t *array, size_t n) |
| 2614 | { |
| 2615 | if (swap_endianness_p) |
| 2616 | @@ -99,7 +102,8 @@ maybe_swap_uint32_array (uint32_t *array, size_t n) |
| 2617 | |
| 2618 | /* Like maybe_swap_uint32_array, but the array of N elements is at |
| 2619 | the end of OBSTACK's current object. */ |
| 2620 | -static inline void |
| 2621 | +static void |
| 2622 | +__attribute__ ((unused)) |
| 2623 | maybe_swap_uint32_obstack (struct obstack *obstack, size_t n) |
| 2624 | { |
| 2625 | maybe_swap_uint32_array ((uint32_t *) obstack_next_free (obstack) - n, n); |
| 2626 | @@ -276,4 +280,55 @@ extern void identification_output (struct localedef_t *locale, |
| 2627 | const struct charmap_t *charmap, |
| 2628 | const char *output_path); |
| 2629 | |
| 2630 | +static size_t wcslen_uint32 (const uint32_t *str) __attribute__ ((unused)); |
| 2631 | +static uint32_t * wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused)); |
| 2632 | +static uint32_t * wcschr_uint32 (const uint32_t *s, uint32_t ch) __attribute__ ((unused)); |
| 2633 | +static int wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) __attribute__ ((unused)); |
| 2634 | +static int wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused)); |
| 2635 | + |
| 2636 | +static size_t |
| 2637 | +wcslen_uint32 (const uint32_t *str) |
| 2638 | +{ |
| 2639 | + size_t len = 0; |
| 2640 | + while (str[len] != 0) |
| 2641 | + len++; |
| 2642 | + return len; |
| 2643 | +} |
| 2644 | + |
| 2645 | +static int |
| 2646 | +wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) |
| 2647 | +{ |
| 2648 | + while (n-- != 0) |
| 2649 | + { |
| 2650 | + int diff = *s1++ - *s2++; |
| 2651 | + if (diff != 0) |
| 2652 | + return diff; |
| 2653 | + } |
| 2654 | + return 0; |
| 2655 | +} |
| 2656 | + |
| 2657 | +static int |
| 2658 | +wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) |
| 2659 | +{ |
| 2660 | + while (*s1 != 0 && *s1 == *s2) |
| 2661 | + s1++, s2++; |
| 2662 | + return *s1 - *s2; |
| 2663 | +} |
| 2664 | + |
| 2665 | +static uint32_t * |
| 2666 | +wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) |
| 2667 | +{ |
| 2668 | + return memcpy (s1, s2, n * sizeof (uint32_t)); |
| 2669 | +} |
| 2670 | + |
| 2671 | +static uint32_t * |
| 2672 | +wcschr_uint32 (const uint32_t *s, uint32_t ch) |
| 2673 | +{ |
| 2674 | + do |
| 2675 | + if (*s == ch) |
| 2676 | + return (uint32_t *) s; |
| 2677 | + while (*s++ != 0); |
| 2678 | + return 0; |
| 2679 | +} |
| 2680 | + |
| 2681 | #endif /* locfile.h */ |
| 2682 | diff --git a/locale/setlocale.c b/locale/setlocale.c |
| 2683 | index fa9cb3a..8eee284 100644 |
| 2684 | --- a/locale/setlocale.c |
| 2685 | +++ b/locale/setlocale.c |
| 2686 | @@ -64,36 +64,6 @@ static char *const _nl_current_used[] = |
| 2687 | #endif |
| 2688 | |
| 2689 | |
| 2690 | -/* Define an array of category names (also the environment variable names). */ |
| 2691 | -const union catnamestr_t _nl_category_names attribute_hidden = |
| 2692 | - { |
| 2693 | - { |
| 2694 | -#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2695 | - category_name, |
| 2696 | -#include "categories.def" |
| 2697 | -#undef DEFINE_CATEGORY |
| 2698 | - } |
| 2699 | - }; |
| 2700 | - |
| 2701 | -const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = |
| 2702 | - { |
| 2703 | -#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2704 | - [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), |
| 2705 | -#include "categories.def" |
| 2706 | -#undef DEFINE_CATEGORY |
| 2707 | - }; |
| 2708 | - |
| 2709 | -/* An array of their lengths, for convenience. */ |
| 2710 | -const uint8_t _nl_category_name_sizes[] attribute_hidden = |
| 2711 | - { |
| 2712 | -#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2713 | - [category] = sizeof (category_name) - 1, |
| 2714 | -#include "categories.def" |
| 2715 | -#undef DEFINE_CATEGORY |
| 2716 | - [LC_ALL] = sizeof ("LC_ALL") - 1 |
| 2717 | - }; |
| 2718 | - |
| 2719 | - |
| 2720 | #ifdef NL_CURRENT_INDIRECT |
| 2721 | # define WEAK_POSTLOAD(postload) weak_extern (postload) |
| 2722 | #else |
| 2723 | diff --git a/locale/xlocale.c b/locale/xlocale.c |
| 2724 | index fec4564..f00269c 100644 |
| 2725 | --- a/locale/xlocale.c |
| 2726 | +++ b/locale/xlocale.c |
| 2727 | @@ -18,6 +18,7 @@ |
| 2728 | <http://www.gnu.org/licenses/>. */ |
| 2729 | |
| 2730 | #include <locale.h> |
| 2731 | +#include <gnu/option-groups.h> |
| 2732 | #include "localeinfo.h" |
| 2733 | |
| 2734 | #define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2735 | @@ -25,6 +26,19 @@ extern struct __locale_data _nl_C_##category; |
| 2736 | #include "categories.def" |
| 2737 | #undef DEFINE_CATEGORY |
| 2738 | |
| 2739 | +/* If the locale support code isn't enabled, don't generate strong |
| 2740 | + reference to the C locale_data structures here; let the Makefile |
| 2741 | + decide which ones to include. (In the static linking case, the |
| 2742 | + strong reference to the 'class', 'toupper', and 'tolower' tables |
| 2743 | + will cause C-ctype.o to be brought in, as it should be, even when |
| 2744 | + the reference to _nl_C_LC_CTYPE will be weak.) */ |
| 2745 | +#if ! __OPTION_EGLIBC_LOCALE_CODE |
| 2746 | +# define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2747 | + weak_extern (_nl_C_##category) |
| 2748 | +# include "categories.def" |
| 2749 | +# undef DEFINE_CATEGORY |
| 2750 | +#endif |
| 2751 | + |
| 2752 | /* Defined in locale/C-ctype.c. */ |
| 2753 | extern const char _nl_C_LC_CTYPE_class[] attribute_hidden; |
| 2754 | extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden; |
| 2755 | @@ -52,3 +66,26 @@ const struct __locale_struct _nl_C_locobj attribute_hidden = |
| 2756 | .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128, |
| 2757 | .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128 |
| 2758 | }; |
| 2759 | + |
| 2760 | + |
| 2761 | +#if ! __OPTION_EGLIBC_LOCALE_CODE |
| 2762 | +/* When locale code is enabled, these are each defined in the |
| 2763 | + appropriate lc-CATEGORY.c file, so that static links (when __thread |
| 2764 | + is supported) bring in only those lc-CATEGORY.o files for |
| 2765 | + categories the program actually uses; look for NL_CURRENT_INDIRECT |
| 2766 | + in localeinfo.h. |
| 2767 | + |
| 2768 | + When locale code is disabled, the _nl_C_CATEGORY objects are the |
| 2769 | + only possible referents. At the moment, there isn't a way to get |
| 2770 | + __OPTION_EGLIBC_LOCALE_CODE defined in every compilation unit that |
| 2771 | + #includes localeinfo.h, so we can't just turn off |
| 2772 | + NL_CURRENT_INDIRECT. So we'll define the _nl_current_CATEGORY |
| 2773 | + pointers here. */ |
| 2774 | +#if defined (NL_CURRENT_INDIRECT) |
| 2775 | +#define DEFINE_CATEGORY(category, category_name, items, a) \ |
| 2776 | + __thread struct __locale_data * const *_nl_current_##category \ |
| 2777 | + attribute_hidden = &_nl_C_locobj.__locales[category]; |
| 2778 | +#include "categories.def" |
| 2779 | +#undef DEFINE_CATEGORY |
| 2780 | +#endif |
| 2781 | +#endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 2782 | diff --git a/localedata/Makefile b/localedata/Makefile |
| 2783 | index ebf6ac9..1870753 100644 |
| 2784 | --- a/localedata/Makefile |
| 2785 | +++ b/localedata/Makefile |
| 2786 | @@ -21,12 +21,22 @@ subdir := localedata |
| 2787 | |
| 2788 | include ../Makeconfig |
| 2789 | |
| 2790 | -# List with all available character set descriptions. |
| 2791 | -charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*) |
| 2792 | +include ../option-groups.mak |
| 2793 | |
| 2794 | # List with all available character set descriptions. |
| 2795 | -locales := $(wildcard locales/*) |
| 2796 | - |
| 2797 | +all-charmaps := $(wildcard charmaps/[A-I]*) $(wildcard charmaps/[J-Z]*) |
| 2798 | + |
| 2799 | +all-locales := $(wildcard locales/*) |
| 2800 | + |
| 2801 | +# If the EGLIBC_LOCALES option group is not enabled, trim the |
| 2802 | +# list of charmap and locale source files. |
| 2803 | +ifeq ($(OPTION_EGLIBC_LOCALES),y) |
| 2804 | +charmaps := $(all-charmaps) |
| 2805 | +locales := $(all-locales) |
| 2806 | +else |
| 2807 | +charmaps := |
| 2808 | +locales := locales/POSIX |
| 2809 | +endif |
| 2810 | |
| 2811 | subdir-dirs = tests-mbwc |
| 2812 | vpath %.c tests-mbwc |
| 2813 | @@ -71,14 +81,20 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \ |
| 2814 | tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \ |
| 2815 | tst_wctype tst_wcwidth |
| 2816 | |
| 2817 | -tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \ |
| 2818 | +# Since these tests build their own locale files, they're not |
| 2819 | +# dependent on the OPTION_EGLIBC_LOCALES option group. But they do |
| 2820 | +# need the locale functions to be present. |
| 2821 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 2822 | + += $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \ |
| 2823 | tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \ |
| 2824 | tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \ |
| 2825 | tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \ |
| 2826 | tst-wctype |
| 2827 | +ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) |
| 2828 | tests-static = bug-setlocale1-static |
| 2829 | tests += $(tests-static) |
| 2830 | -ifeq (yes,$(build-shared)) |
| 2831 | +endif |
| 2832 | +ifeq (yesy,$(build-shared)$(OPTION_EGLIBC_LOCALE_CODE)) |
| 2833 | ifneq (no,$(PERL)) |
| 2834 | tests-special += $(objpfx)mtrace-tst-leaks.out |
| 2835 | endif |
| 2836 | @@ -95,6 +111,7 @@ tests: $(objdir)/iconvdata/gconv-modules |
| 2837 | tests-static += tst-langinfo-static |
| 2838 | |
| 2839 | ifeq ($(run-built-tests),yes) |
| 2840 | +ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) |
| 2841 | tests-special += $(objpfx)sort-test.out $(objpfx)tst-fmon.out \ |
| 2842 | $(objpfx)tst-locale.out $(objpfx)tst-rpmatch.out \ |
| 2843 | $(objpfx)tst-trans.out $(objpfx)tst-ctype.out \ |
| 2844 | @@ -109,6 +126,7 @@ LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 \ |
| 2845 | tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8 |
| 2846 | include ../gen-locales.mk |
| 2847 | endif |
| 2848 | +endif |
| 2849 | |
| 2850 | include ../Rules |
| 2851 | |
| 2852 | @@ -191,6 +209,11 @@ endif |
| 2853 | |
| 2854 | include SUPPORTED |
| 2855 | |
| 2856 | +# Only install locale data if OPTION_EGLIBC_LOCALES is selected. |
| 2857 | +ifneq ($(OPTION_EGLIBC_LOCALES),y) |
| 2858 | +SUPPORTED-LOCALES := |
| 2859 | +endif |
| 2860 | + |
| 2861 | INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES)) |
| 2862 | |
| 2863 | # Sometimes the whole collection of locale files should be installed. |
| 2864 | diff --git a/login/Makefile b/login/Makefile |
| 2865 | index 0f4bb22..4036ddb 100644 |
| 2866 | --- a/login/Makefile |
| 2867 | +++ b/login/Makefile |
| 2868 | @@ -18,6 +18,7 @@ |
| 2869 | # |
| 2870 | # Sub-makefile for login portion of the library. |
| 2871 | # |
| 2872 | +include ../option-groups.mak |
| 2873 | |
| 2874 | subdir := login |
| 2875 | |
| 2876 | @@ -25,14 +26,16 @@ include ../Makeconfig |
| 2877 | |
| 2878 | headers := utmp.h bits/utmp.h lastlog.h pty.h |
| 2879 | |
| 2880 | -routines := getlogin getlogin_r setlogin getlogin_r_chk \ |
| 2881 | - getutent getutent_r getutid getutline getutid_r getutline_r \ |
| 2882 | - utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \ |
| 2883 | - ptsname_r_chk |
| 2884 | +routines := getpt grantpt unlockpt ptsname ptsname_r_chk |
| 2885 | +routines-$(OPTION_EGLIBC_UTMP) \ |
| 2886 | + += getutent getutent_r getutid getutline getutid_r getutline_r \ |
| 2887 | + utmp_file utmpname updwtmp |
| 2888 | +routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin getlogin_r getlogin_r_chk |
| 2889 | +routines-$(OPTION_EGLIBC_BSD) += setlogin |
| 2890 | |
| 2891 | CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"' |
| 2892 | |
| 2893 | -others = utmpdump |
| 2894 | +others-$(OPTION_EGLIBC_UTMP) += utmpdump |
| 2895 | |
| 2896 | ifeq (yes,$(build-pt-chown)) |
| 2897 | others += pt_chown |
| 2898 | @@ -46,8 +49,8 @@ vpath %.c programs |
| 2899 | tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin |
| 2900 | |
| 2901 | # Build the -lutil library with these extra functions. |
| 2902 | -extra-libs := libutil |
| 2903 | -extra-libs-others := $(extra-libs) |
| 2904 | +extra-libs-$(OPTION_EGLIBC_UTMP) := libutil |
| 2905 | +extra-libs-others := $(extra-libs-y) |
| 2906 | |
| 2907 | libutil-routines:= login login_tty logout logwtmp openpty forkpty |
| 2908 | |
| 2909 | diff --git a/malloc/Makefile b/malloc/Makefile |
| 2910 | index 67ed293..272ca4d 100644 |
| 2911 | --- a/malloc/Makefile |
| 2912 | +++ b/malloc/Makefile |
| 2913 | @@ -18,6 +18,8 @@ |
| 2914 | # |
| 2915 | # Makefile for malloc routines |
| 2916 | # |
| 2917 | +include ../option-groups.mak |
| 2918 | + |
| 2919 | subdir := malloc |
| 2920 | |
| 2921 | include ../Makeconfig |
| 2922 | @@ -39,9 +41,15 @@ install-lib := libmcheck.a |
| 2923 | non-lib.a := libmcheck.a |
| 2924 | |
| 2925 | # Additional library. |
| 2926 | +ifeq ($(OPTION_EGLIBC_MEMUSAGE),y) |
| 2927 | extra-libs = libmemusage |
| 2928 | extra-libs-others = $(extra-libs) |
| 2929 | |
| 2930 | +ifdef OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE |
| 2931 | +CPPFLAGS-memusage += -D__OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE=$(OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE) |
| 2932 | +endif |
| 2933 | +endif |
| 2934 | + |
| 2935 | libmemusage-routines = memusage |
| 2936 | libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) |
| 2937 | |
| 2938 | @@ -71,7 +79,7 @@ endif |
| 2939 | # Unless we get a test for the availability of libgd which also works |
| 2940 | # for cross-compiling we disable the memusagestat generation in this |
| 2941 | # situation. |
| 2942 | -ifneq ($(cross-compiling),yes) |
| 2943 | +ifeq ($(cross-compiling)$(OPTION_EGLIBC_MEMUSAGE),noy) |
| 2944 | # If the gd library is available we build the `memusagestat' program. |
| 2945 | ifneq ($(LIBGD),no) |
| 2946 | others: $(objpfx)memusage |
| 2947 | diff --git a/malloc/memusage.c b/malloc/memusage.c |
| 2948 | index a57ba8e..732ba9d 100644 |
| 2949 | --- a/malloc/memusage.c |
| 2950 | +++ b/malloc/memusage.c |
| 2951 | @@ -33,6 +33,7 @@ |
| 2952 | #include <stdint.h> |
| 2953 | #include <sys/mman.h> |
| 2954 | #include <sys/time.h> |
| 2955 | +#include <gnu/option-groups.h> |
| 2956 | |
| 2957 | #include <memusage.h> |
| 2958 | |
| 2959 | @@ -93,7 +94,11 @@ static __thread uintptr_t start_sp; |
| 2960 | #define peak_stack peak_use[1] |
| 2961 | #define peak_total peak_use[2] |
| 2962 | |
| 2963 | -#define DEFAULT_BUFFER_SIZE 32768 |
| 2964 | +#ifndef __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE |
| 2965 | +# define DEFAULT_BUFFER_SIZE 32768 |
| 2966 | +#else |
| 2967 | +# define DEFAULT_BUFFER_SIZE __OPTION_EGLIBC_MEMUSAGE_DEFAULT_BUFFER_SIZE |
| 2968 | +#endif |
| 2969 | static size_t buffer_size; |
| 2970 | |
| 2971 | static int fd = -1; |
| 2972 | diff --git a/malloc/memusage.sh b/malloc/memusage.sh |
| 2973 | index 8ab8cc2..d18f446 100755 |
| 2974 | --- a/malloc/memusage.sh |
| 2975 | +++ b/malloc/memusage.sh |
| 2976 | @@ -35,7 +35,7 @@ do_missing_arg() { |
| 2977 | |
| 2978 | # Print help message |
| 2979 | do_help() { |
| 2980 | - echo $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]... |
| 2981 | + printf $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]... |
| 2982 | Profile memory usage of PROGRAM. |
| 2983 | |
| 2984 | -n,--progname=NAME Name of the program file to profile |
| 2985 | diff --git a/math/Makefile b/math/Makefile |
| 2986 | index 6388bae..ed1c511 100644 |
| 2987 | --- a/math/Makefile |
| 2988 | +++ b/math/Makefile |
| 2989 | @@ -21,6 +21,8 @@ subdir := math |
| 2990 | |
| 2991 | include ../Makeconfig |
| 2992 | |
| 2993 | +include ../option-groups.mak |
| 2994 | + |
| 2995 | # Installed header files. |
| 2996 | headers := math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \ |
| 2997 | bits/huge_valf.h bits/huge_vall.h bits/inf.h bits/nan.h \ |
| 2998 | @@ -34,8 +36,8 @@ aux := setfpucw fpu_control |
| 2999 | |
| 3000 | # Build the -lm library. |
| 3001 | |
| 3002 | -extra-libs := libm |
| 3003 | -extra-libs-others = $(extra-libs) |
| 3004 | +extra-libs-$(OPTION_EGLIBC_LIBM) := libm |
| 3005 | +extra-libs-others-$(OPTION_EGLIBC_LIBM) = $(extra-libs-$(OPTION_EGLIBC_LIBM)) |
| 3006 | |
| 3007 | libm-support = s_lib_version s_matherr s_signgam \ |
| 3008 | fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg \ |
| 3009 | diff --git a/misc/Makefile b/misc/Makefile |
| 3010 | index aecb0da..e6b7c23 100644 |
| 3011 | --- a/misc/Makefile |
| 3012 | +++ b/misc/Makefile |
| 3013 | @@ -19,6 +19,10 @@ |
| 3014 | # Sub-makefile for misc portion of the library. |
| 3015 | # |
| 3016 | |
| 3017 | +# Some system-dependent implementations of these functions use option |
| 3018 | +# groups (see sysdeps/unix/sysv/linux/Makefile, for example). |
| 3019 | +include ../option-groups.mak |
| 3020 | + |
| 3021 | subdir := misc |
| 3022 | |
| 3023 | include ../Makeconfig |
| 3024 | @@ -46,40 +50,47 @@ routines := brk sbrk sstk ioctl \ |
| 3025 | select pselect \ |
| 3026 | acct chroot fsync sync fdatasync syncfs reboot \ |
| 3027 | gethostid sethostid \ |
| 3028 | - revoke vhangup \ |
| 3029 | + vhangup \ |
| 3030 | swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \ |
| 3031 | mkostemp mkostemp64 mkstemps mkstemps64 mkostemps mkostemps64 \ |
| 3032 | ualarm usleep \ |
| 3033 | gtty stty \ |
| 3034 | ptrace \ |
| 3035 | - fstab mntent mntent_r \ |
| 3036 | + mntent mntent_r \ |
| 3037 | utimes lutimes futimes futimesat \ |
| 3038 | truncate ftruncate truncate64 ftruncate64 \ |
| 3039 | - chflags fchflags \ |
| 3040 | insremque getttyent getusershell getpass ttyslot \ |
| 3041 | syslog syscall daemon \ |
| 3042 | mmap mmap64 munmap mprotect msync madvise mincore remap_file_pages\ |
| 3043 | mlock munlock mlockall munlockall \ |
| 3044 | - efgcvt efgcvt_r qefgcvt qefgcvt_r \ |
| 3045 | hsearch hsearch_r tsearch lsearch \ |
| 3046 | err error ustat \ |
| 3047 | - getsysstats dirname regexp \ |
| 3048 | + getsysstats dirname \ |
| 3049 | getloadavg getclktck \ |
| 3050 | fgetxattr flistxattr fremovexattr fsetxattr getxattr \ |
| 3051 | listxattr lgetxattr llistxattr lremovexattr lsetxattr \ |
| 3052 | removexattr setxattr getauxval ifunc-impl-list |
| 3053 | |
| 3054 | +routines-$(OPTION_POSIX_REGEXP) += regexp |
| 3055 | +routines-$(OPTION_EGLIBC_FSTAB) += fstab |
| 3056 | +routines-$(OPTION_EGLIBC_BSD) += chflags fchflags revoke |
| 3057 | +routines-$(OPTION_EGLIBC_FCVT) += efgcvt efgcvt_r qefgcvt qefgcvt_r |
| 3058 | + |
| 3059 | generated += tst-error1.mtrace tst-error1-mem.out |
| 3060 | |
| 3061 | aux := init-misc |
| 3062 | install-lib := libg.a |
| 3063 | gpl2lgpl := error.c error.h |
| 3064 | |
| 3065 | -tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ |
| 3066 | - tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 |
| 3067 | +tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \ |
| 3068 | + tst-pselect tst-insremque tst-mntent2 bug-hsearch1 |
| 3069 | +tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += tst-error1 |
| 3070 | +tests-$(OPTION_EGLIBC_FCVT) += tst-efgcvt |
| 3071 | ifeq ($(run-built-tests),yes) |
| 3072 | +ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)) |
| 3073 | tests-special += $(objpfx)tst-error1-mem.out |
| 3074 | endif |
| 3075 | +endif |
| 3076 | |
| 3077 | CFLAGS-select.c = -fexceptions -fasynchronous-unwind-tables |
| 3078 | CFLAGS-tsearch.c = $(uses-callbacks) |
| 3079 | diff --git a/misc/err.c b/misc/err.c |
| 3080 | index 7b98157..efce8d5 100644 |
| 3081 | --- a/misc/err.c |
| 3082 | +++ b/misc/err.c |
| 3083 | @@ -22,6 +22,7 @@ |
| 3084 | #include <errno.h> |
| 3085 | #include <string.h> |
| 3086 | #include <stdio.h> |
| 3087 | +#include <gnu/option-groups.h> |
| 3088 | |
| 3089 | #include <wchar.h> |
| 3090 | #define flockfile(s) _IO_flockfile (s) |
| 3091 | @@ -37,6 +38,7 @@ extern char *__progname; |
| 3092 | va_end (ap); \ |
| 3093 | } |
| 3094 | |
| 3095 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 3096 | static void |
| 3097 | convert_and_print (const char *format, __gnuc_va_list ap) |
| 3098 | { |
| 3099 | @@ -81,6 +83,7 @@ convert_and_print (const char *format, __gnuc_va_list ap) |
| 3100 | |
| 3101 | __vfwprintf (stderr, wformat, ap); |
| 3102 | } |
| 3103 | +#endif |
| 3104 | |
| 3105 | void |
| 3106 | vwarnx (const char *format, __gnuc_va_list ap) |
| 3107 | @@ -88,9 +91,13 @@ vwarnx (const char *format, __gnuc_va_list ap) |
| 3108 | flockfile (stderr); |
| 3109 | if (_IO_fwide (stderr, 0) > 0) |
| 3110 | { |
| 3111 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 3112 | __fwprintf (stderr, L"%s: ", __progname); |
| 3113 | convert_and_print (format, ap); |
| 3114 | putwc_unlocked (L'\n', stderr); |
| 3115 | +#else |
| 3116 | + abort (); |
| 3117 | +#endif |
| 3118 | } |
| 3119 | else |
| 3120 | { |
| 3121 | @@ -111,6 +118,7 @@ vwarn (const char *format, __gnuc_va_list ap) |
| 3122 | flockfile (stderr); |
| 3123 | if (_IO_fwide (stderr, 0) > 0) |
| 3124 | { |
| 3125 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 3126 | __fwprintf (stderr, L"%s: ", __progname); |
| 3127 | if (format) |
| 3128 | { |
| 3129 | @@ -119,6 +127,9 @@ vwarn (const char *format, __gnuc_va_list ap) |
| 3130 | } |
| 3131 | __set_errno (error); |
| 3132 | __fwprintf (stderr, L"%m\n"); |
| 3133 | +#else |
| 3134 | + abort (); |
| 3135 | +#endif |
| 3136 | } |
| 3137 | else |
| 3138 | { |
| 3139 | diff --git a/misc/error.c b/misc/error.c |
| 3140 | index aaa120d..d6cbc82 100644 |
| 3141 | --- a/misc/error.c |
| 3142 | +++ b/misc/error.c |
| 3143 | @@ -35,6 +35,7 @@ |
| 3144 | #endif |
| 3145 | |
| 3146 | #ifdef _LIBC |
| 3147 | +# include <gnu/option-groups.h> |
| 3148 | # include <libintl.h> |
| 3149 | # include <stdbool.h> |
| 3150 | # include <stdint.h> |
| 3151 | @@ -205,6 +206,7 @@ error_tail (int status, int errnum, const char *message, va_list args) |
| 3152 | #if _LIBC |
| 3153 | if (_IO_fwide (stderr, 0) > 0) |
| 3154 | { |
| 3155 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 3156 | size_t len = strlen (message) + 1; |
| 3157 | wchar_t *wmessage = NULL; |
| 3158 | mbstate_t st; |
| 3159 | @@ -265,6 +267,9 @@ error_tail (int status, int errnum, const char *message, va_list args) |
| 3160 | |
| 3161 | if (use_malloc) |
| 3162 | free (wmessage); |
| 3163 | +#else |
| 3164 | + abort (); |
| 3165 | +#endif |
| 3166 | } |
| 3167 | else |
| 3168 | #endif |
| 3169 | diff --git a/misc/tst-efgcvt.c b/misc/tst-efgcvt.c |
| 3170 | index 5083fec..79ed36c 100644 |
| 3171 | --- a/misc/tst-efgcvt.c |
| 3172 | +++ b/misc/tst-efgcvt.c |
| 3173 | @@ -59,7 +59,7 @@ static testcase ecvt_tests[] = |
| 3174 | { 123.01, -4, 3, "" }, |
| 3175 | { 126.71, -4, 3, "" }, |
| 3176 | { 0.0, 4, 1, "0000" }, |
| 3177 | -#if DBL_MANT_DIG == 53 |
| 3178 | +#if DBL_MANT_DIG == 53 && !(defined __powerpc__ && defined __NO_FPRS__ && !defined _SOFT_FLOAT && !defined _SOFT_DOUBLE) |
| 3179 | { 0x1p-1074, 3, -323, "494" }, |
| 3180 | { -0x1p-1074, 3, -323, "494" }, |
| 3181 | #endif |
| 3182 | diff --git a/nis/Makefile b/nis/Makefile |
| 3183 | index 037e674..c967850 100644 |
| 3184 | --- a/nis/Makefile |
| 3185 | +++ b/nis/Makefile |
| 3186 | @@ -18,6 +18,8 @@ |
| 3187 | # |
| 3188 | # Makefile for NIS/NIS+ part. |
| 3189 | # |
| 3190 | +include ../option-groups.mak |
| 3191 | + |
| 3192 | subdir := nis |
| 3193 | |
| 3194 | include ../Makeconfig |
| 3195 | @@ -30,19 +32,26 @@ endif |
| 3196 | |
| 3197 | # These are the databases available for the nis (and perhaps later nisplus) |
| 3198 | # service. This must be a superset of the services in nss. |
| 3199 | -databases = proto service hosts network grp pwd rpc ethers \ |
| 3200 | - spwd netgrp alias publickey |
| 3201 | +databases-y := proto service hosts network grp pwd rpc ethers \ |
| 3202 | + spwd netgrp publickey |
| 3203 | +databases-$(OPTION_EGLIBC_DB_ALIASES) += alias |
| 3204 | |
| 3205 | # Specify rules for the nss_* modules. |
| 3206 | -services := nis nisplus compat |
| 3207 | +# The 'compat' module includes nis support, and the 'nss' directory |
| 3208 | +# includes a bare-bones "files" library, so we'll include 'compat' in |
| 3209 | +# OPTION_EGLIBC_NIS. |
| 3210 | +services-y := |
| 3211 | +services-$(OPTION_EGLIBC_NIS) += nis nisplus compat |
| 3212 | + |
| 3213 | +extra-libs-$(OPTION_EGLIBC_NIS) += libnsl |
| 3214 | +extra-libs-y += $(services-y:%=libnss_%) |
| 3215 | |
| 3216 | -extra-libs = libnsl $(services:%=libnss_%) |
| 3217 | # These libraries will be built in the `others' pass rather than |
| 3218 | # the `lib' pass, because they depend on libc.so being built already. |
| 3219 | -extra-libs-others = $(extra-libs) |
| 3220 | +extra-libs-others-y += $(extra-libs-y) |
| 3221 | |
| 3222 | # The sources are found in the appropriate subdir. |
| 3223 | -subdir-dirs = $(services:%=nss_%) |
| 3224 | +subdir-dirs = $(services-y:%=nss_%) |
| 3225 | vpath %.c $(subdir-dirs) |
| 3226 | |
| 3227 | libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ |
| 3228 | @@ -60,11 +69,11 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ |
| 3229 | libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) |
| 3230 | libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) |
| 3231 | |
| 3232 | -libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \ |
| 3233 | +libnss_nis-routines := $(addprefix nis-,$(databases-y)) nis-initgroups \ |
| 3234 | nss-nis |
| 3235 | libnss_nis-inhibit-o = $(filter-out .os,$(object-suffixes)) |
| 3236 | |
| 3237 | -libnss_nisplus-routines := $(addprefix nisplus-,$(databases)) nisplus-parser \ |
| 3238 | +libnss_nisplus-routines := $(addprefix nisplus-,$(databases-y)) nisplus-parser \ |
| 3239 | nss-nisplus nisplus-initgroups |
| 3240 | libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes)) |
| 3241 | |
| 3242 | @@ -80,12 +89,12 @@ libnsl-libc = $(common-objpfx)linkobj/libc.so |
| 3243 | # Target-specific variable setting to link objects using deprecated |
| 3244 | # RPC interfaces with the version of libc.so that makes them available |
| 3245 | # for new links: |
| 3246 | -$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \ |
| 3247 | +$(services-y:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \ |
| 3248 | libc-for-link = $(libnsl-libc) |
| 3249 | |
| 3250 | |
| 3251 | ifeq ($(build-shared),yes) |
| 3252 | -$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) |
| 3253 | +$(others-y:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) |
| 3254 | else |
| 3255 | -$(others:%=$(objpfx)%): $(objpfx)libnsl.a |
| 3256 | +$(others-y:%=$(objpfx)%): $(objpfx)libnsl.a |
| 3257 | endif |
| 3258 | diff --git a/nptl/Makefile b/nptl/Makefile |
| 3259 | index aaca0a4..596ca3c 100644 |
| 3260 | --- a/nptl/Makefile |
| 3261 | +++ b/nptl/Makefile |
| 3262 | @@ -18,6 +18,8 @@ |
| 3263 | # |
| 3264 | # Sub-makefile for NPTL portion of the library. |
| 3265 | # |
| 3266 | +include ../option-groups.mak |
| 3267 | + |
| 3268 | subdir := nptl |
| 3269 | |
| 3270 | include ../Makeconfig |
| 3271 | @@ -118,7 +120,7 @@ libpthread-routines = nptl-init vars events version pt-interp \ |
| 3272 | pt-raise pt-system \ |
| 3273 | flockfile ftrylockfile funlockfile \ |
| 3274 | sigaction \ |
| 3275 | - herrno res pt-allocrtsig \ |
| 3276 | + pt-allocrtsig \ |
| 3277 | pthread_kill_other_threads \ |
| 3278 | pthread_getaffinity pthread_setaffinity \ |
| 3279 | pthread_attr_getaffinity pthread_attr_setaffinity \ |
| 3280 | @@ -138,8 +140,10 @@ libpthread-routines = nptl-init vars events version pt-interp \ |
| 3281 | # pthread_setgid pthread_setegid pthread_setregid \ |
| 3282 | # pthread_setresgid |
| 3283 | |
| 3284 | +libpthread-routines-$(OPTION_EGLIBC_INET) := herrno res |
| 3285 | libpthread-shared-only-routines = version pt-interp pt-allocrtsig \ |
| 3286 | unwind-forcedunwind |
| 3287 | + |
| 3288 | libpthread-static-only-routines = pthread_atfork |
| 3289 | |
| 3290 | # Since cancellation handling is in large parts handled using exceptions |
| 3291 | @@ -220,7 +224,7 @@ tests = tst-typesizes \ |
| 3292 | tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ |
| 3293 | tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \ |
| 3294 | tst-mutexpi9 \ |
| 3295 | - tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ |
| 3296 | + tst-spin1 tst-spin2 tst-spin3 \ |
| 3297 | tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ |
| 3298 | tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ |
| 3299 | tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ |
| 3300 | @@ -256,14 +260,14 @@ tests = tst-typesizes \ |
| 3301 | tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \ |
| 3302 | tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \ |
| 3303 | tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \ |
| 3304 | - tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \ |
| 3305 | + tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \ |
| 3306 | tst-cancel-self tst-cancel-self-cancelstate \ |
| 3307 | tst-cancel-self-canceltype tst-cancel-self-testcancel \ |
| 3308 | tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ |
| 3309 | tst-flock1 tst-flock2 \ |
| 3310 | tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ |
| 3311 | tst-signal6 tst-signal7 \ |
| 3312 | - tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ |
| 3313 | + tst-exec2 tst-exec3 tst-exec4 \ |
| 3314 | tst-exit1 tst-exit2 tst-exit3 \ |
| 3315 | tst-stdio1 tst-stdio2 \ |
| 3316 | tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \ |
| 3317 | @@ -271,13 +275,12 @@ tests = tst-typesizes \ |
| 3318 | tst-unload \ |
| 3319 | tst-dlsym1 \ |
| 3320 | tst-sysconf \ |
| 3321 | - tst-locale1 tst-locale2 \ |
| 3322 | + tst-locale2 \ |
| 3323 | tst-umask1 \ |
| 3324 | tst-popen1 \ |
| 3325 | tst-clock1 \ |
| 3326 | tst-context1 \ |
| 3327 | tst-sched1 \ |
| 3328 | - tst-backtrace1 \ |
| 3329 | tst-abstime \ |
| 3330 | tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ |
| 3331 | tst-getpid3 \ |
| 3332 | @@ -288,9 +291,16 @@ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ |
| 3333 | tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 |
| 3334 | test-srcs = tst-oddstacklimit |
| 3335 | |
| 3336 | -# Test expected to fail on most targets (except x86_64) due to bug |
| 3337 | -# 18435 - pthread_once hangs when init routine throws an exception. |
| 3338 | -test-xfail-tst-once5 = yes |
| 3339 | +# This test uses the posix_spawn functions. |
| 3340 | +tests-$(OPTION_EGLIBC_SPAWN) += tst-exec1 |
| 3341 | + |
| 3342 | +# This test uses the 'backtrace' functions. |
| 3343 | +tests-$(OPTION_EGLIBC_BACKTRACE) += tst-backtrace1 |
| 3344 | + |
| 3345 | +# This test is written in C++. |
| 3346 | +tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24 |
| 3347 | + |
| 3348 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1 |
| 3349 | |
| 3350 | # Files which must not be linked with libpthread. |
| 3351 | tests-nolibpthread = tst-unload |
| 3352 | diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c |
| 3353 | index d10f4ea..14257ce 100644 |
| 3354 | --- a/nptl/pthread_create.c |
| 3355 | +++ b/nptl/pthread_create.c |
| 3356 | @@ -33,6 +33,7 @@ |
| 3357 | #include <default-sched.h> |
| 3358 | #include <futex-internal.h> |
| 3359 | |
| 3360 | +#include <gnu/option-groups.h> |
| 3361 | #include <shlib-compat.h> |
| 3362 | |
| 3363 | #include <stap-probe.h> |
| 3364 | @@ -262,8 +263,10 @@ START_THREAD_DEFN |
| 3365 | THREAD_SETMEM (pd, cpuclock_offset, now); |
| 3366 | #endif |
| 3367 | |
| 3368 | +#if __OPTION_EGLIBC_INET |
| 3369 | /* Initialize resolver state pointer. */ |
| 3370 | __resp = &pd->res; |
| 3371 | +#endif |
| 3372 | |
| 3373 | /* Initialize pointers to locale data. */ |
| 3374 | __ctype_init (); |
| 3375 | @@ -346,8 +349,10 @@ START_THREAD_DEFN |
| 3376 | /* Run the destructor for the thread-local data. */ |
| 3377 | __nptl_deallocate_tsd (); |
| 3378 | |
| 3379 | +#if __OPTION_EGLIBC_INET |
| 3380 | /* Clean up any state libc stored in thread-local variables. */ |
| 3381 | __libc_thread_freeres (); |
| 3382 | +#endif |
| 3383 | |
| 3384 | /* If this is the last thread we terminate the process now. We |
| 3385 | do not notify the debugger, it might just irritate it if there |
| 3386 | diff --git a/nscd/Makefile b/nscd/Makefile |
| 3387 | index ede941d..f4f3f8d 100644 |
| 3388 | --- a/nscd/Makefile |
| 3389 | +++ b/nscd/Makefile |
| 3390 | @@ -18,14 +18,17 @@ |
| 3391 | # |
| 3392 | # Sub-makefile for nscd portion of the library. |
| 3393 | # |
| 3394 | +include ../option-groups.mak |
| 3395 | + |
| 3396 | subdir := nscd |
| 3397 | |
| 3398 | include ../Makeconfig |
| 3399 | |
| 3400 | ifneq ($(use-nscd),no) |
| 3401 | -routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ |
| 3402 | +routines-$(OPTION_EGLIBC_INET) += \ |
| 3403 | + nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ |
| 3404 | nscd_initgroups nscd_getserv_r nscd_netgroup |
| 3405 | -aux := nscd_helper |
| 3406 | +aux-$(OPTION_EGLIBC_INET) += nscd_helper |
| 3407 | endif |
| 3408 | |
| 3409 | # To find xmalloc.c |
| 3410 | @@ -37,14 +40,18 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \ |
| 3411 | dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ |
| 3412 | xmalloc xstrdup aicache initgrcache gai res_hconf \ |
| 3413 | netgroupcache |
| 3414 | - |
| 3415 | +ifneq (y,$(OPTION_EGLIBC_NIS)) |
| 3416 | +# If we haven't build libnsl.so, then we'll need to include our |
| 3417 | +# own copy of nis_hash. |
| 3418 | +nscd-modules += nis_hash |
| 3419 | +endif |
| 3420 | ifeq ($(build-nscd)$(have-thread-library),yesyes) |
| 3421 | |
| 3422 | -others += nscd |
| 3423 | -others-pie += nscd |
| 3424 | -install-sbin := nscd |
| 3425 | +others-$(OPTION_EGLIBC_INET) += nscd |
| 3426 | +others-pie-$(OPTION_EGLIBC_INET) += nscd |
| 3427 | +install-sbin-$(OPTION_EGLIBC_INET) += nscd |
| 3428 | |
| 3429 | -extra-objs = $(nscd-modules:=.o) |
| 3430 | +extra-objs-$(OPTION_EGLIBC_INET) += $(nscd-modules:=.o) |
| 3431 | |
| 3432 | endif |
| 3433 | |
| 3434 | @@ -100,7 +107,15 @@ include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left)) |
| 3435 | $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o) |
| 3436 | |
| 3437 | ifeq ($(build-shared),yes) |
| 3438 | -$(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so |
| 3439 | +$(objpfx)nscd: $(shared-thread-library) |
| 3440 | +else |
| 3441 | +$(objpfx)nscd: $(static-thread-library) |
| 3442 | +endif |
| 3443 | + |
| 3444 | +ifeq (y,$(OPTION_EGLIBC_NIS)) |
| 3445 | +ifeq ($(build-shared),yes) |
| 3446 | +$(objpfx)nscd: $(common-objpfx)nis/libnsl.so |
| 3447 | else |
| 3448 | -$(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a |
| 3449 | +$(objpfx)nscd: $(common-objpfx)nis/libnsl.a |
| 3450 | +endif |
| 3451 | endif |
| 3452 | diff --git a/nscd/nis_hash.c b/nscd/nis_hash.c |
| 3453 | new file mode 100644 |
| 3454 | index 0000000..d244c41 |
| 3455 | --- /dev/null |
| 3456 | +++ b/nscd/nis_hash.c |
| 3457 | @@ -0,0 +1,3 @@ |
| 3458 | +/* If OPTION_EGLIBC_NIS is disabled, nscd can't get this from libnsl.so; |
| 3459 | + we need our own copy. */ |
| 3460 | +#include "../nis/nis_hash.c" |
| 3461 | diff --git a/nss/Makefile b/nss/Makefile |
| 3462 | index 65ab7b5..19f0aef 100644 |
| 3463 | --- a/nss/Makefile |
| 3464 | +++ b/nss/Makefile |
| 3465 | @@ -18,28 +18,35 @@ |
| 3466 | # |
| 3467 | # Makefile for name service switch. |
| 3468 | # |
| 3469 | +include ../option-groups.mak |
| 3470 | + |
| 3471 | subdir := nss |
| 3472 | |
| 3473 | include ../Makeconfig |
| 3474 | |
| 3475 | headers := nss.h |
| 3476 | |
| 3477 | -# This is the trivial part which goes into libc itself. |
| 3478 | -routines = nsswitch getnssent getnssent_r digits_dots \ |
| 3479 | - $(addsuffix -lookup,$(databases)) |
| 3480 | - |
| 3481 | # These are the databases that go through nss dispatch. |
| 3482 | # Caution: if you add a database here, you must add its real name |
| 3483 | # in databases.def, too. |
| 3484 | -databases = proto service hosts network grp pwd ethers \ |
| 3485 | - spwd netgrp alias sgrp |
| 3486 | +databases-y = grp pwd spwd sgrp |
| 3487 | +databases-$(OPTION_EGLIBC_INET) \ |
| 3488 | + += proto service hosts network ethers \ |
| 3489 | + netgrp |
| 3490 | +databases-$(OPTION_EGLIBC_DB_ALIASES) += alias |
| 3491 | + |
| 3492 | +routines-$(OPTION_EGLIBC_INET) += digits_dots |
| 3493 | |
| 3494 | ifneq (,$(filter sunrpc,$(subdirs))) |
| 3495 | -databases += key rpc |
| 3496 | +databases-$(OPTION_EGLIBC_INET) += key rpc |
| 3497 | have-sunrpc := 1 |
| 3498 | else |
| 3499 | have-sunrpc := 0 |
| 3500 | endif |
| 3501 | +# This is the trivial part which goes into libc itself. |
| 3502 | +routines-y += nsswitch getnssent getnssent_r \ |
| 3503 | + $(addsuffix -lookup,$(databases-y)) |
| 3504 | + |
| 3505 | CPPFLAGS-getent.c = -DHAVE_SUNRPC=$(have-sunrpc) |
| 3506 | |
| 3507 | others := getent makedb |
| 3508 | @@ -47,8 +54,9 @@ install-bin := getent makedb |
| 3509 | makedb-modules = xmalloc hash-string |
| 3510 | extra-objs += $(makedb-modules:=.o) |
| 3511 | |
| 3512 | -tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent |
| 3513 | -xtests = bug-erange |
| 3514 | +tests = tst-nss-test1 tst-nss-getpwent |
| 3515 | +tests-$(OPTION_EGLIBC_INET) += test-netdb test-digits-dots |
| 3516 | +xtests-$(OPTION_EGLIBC_INET) += bug-erange |
| 3517 | |
| 3518 | # Specify rules for the nss_* modules. We have some services. |
| 3519 | services := files db |
| 3520 | @@ -63,7 +71,7 @@ subdir-dirs = $(services:%=nss_%) |
| 3521 | vpath %.c $(subdir-dirs) ../locale/programs ../intl |
| 3522 | |
| 3523 | |
| 3524 | -libnss_files-routines := $(addprefix files-,$(databases)) \ |
| 3525 | +libnss_files-routines := $(addprefix files-,$(databases-y)) \ |
| 3526 | files-initgroups files-have_o_cloexec files-init |
| 3527 | |
| 3528 | libnss_db-dbs := $(addprefix db-,\ |
| 3529 | @@ -86,6 +94,45 @@ tests-static = tst-nss-static |
| 3530 | tests += $(tests-static) |
| 3531 | endif |
| 3532 | |
| 3533 | +ifneq ($(OPTION_EGLIBC_NSSWITCH),y) |
| 3534 | + |
| 3535 | +ifndef OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG |
| 3536 | +$(error OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG variable left unset) |
| 3537 | +endif |
| 3538 | + |
| 3539 | +ifndef OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS |
| 3540 | +$(error OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS variable left unset) |
| 3541 | +endif |
| 3542 | + |
| 3543 | +ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG))) |
| 3544 | +$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed config file) |
| 3545 | +$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)) |
| 3546 | +endif |
| 3547 | + |
| 3548 | +ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS))) |
| 3549 | +$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed functions file) |
| 3550 | +$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)) |
| 3551 | +endif |
| 3552 | + |
| 3553 | +before-compile := $(objpfx)fixed-nsswitch.h |
| 3554 | +generated := fixed-nsswitch.h |
| 3555 | +$(objpfx)fixed-nsswitch.h $(objfpx)fixed-nsswitch-libs: \ |
| 3556 | + $(objpfx)gen-fixed-nsswitch \ |
| 3557 | + $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG) |
| 3558 | + $< $(objpfx)fixed-nsswitch.h \ |
| 3559 | + $(objpfx)fixed-nsswitch-libs \ |
| 3560 | + $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG) |
| 3561 | + |
| 3562 | +$(objpfx)gen-fixed-nsswitch: gen-fixed-nsswitch.c \ |
| 3563 | + $(common-objpfx)option-groups.config \ |
| 3564 | + $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS) |
| 3565 | + $(native-compile) |
| 3566 | +gen-fixed-nsswitch-CFLAGS = \ |
| 3567 | + -g3 -O -Wall \ |
| 3568 | + -I $(objpfx) \ |
| 3569 | + -DFIXED_FUNCTIONS='"$(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)"' |
| 3570 | +endif |
| 3571 | + |
| 3572 | include ../Rules |
| 3573 | |
| 3574 | ifeq (yes,$(have-selinux)) |
| 3575 | diff --git a/nss/fixed-nsswitch.conf b/nss/fixed-nsswitch.conf |
| 3576 | new file mode 100644 |
| 3577 | index 0000000..91bb675 |
| 3578 | --- /dev/null |
| 3579 | +++ b/nss/fixed-nsswitch.conf |
| 3580 | @@ -0,0 +1,22 @@ |
| 3581 | +# /etc/nsswitch.conf |
| 3582 | +# |
| 3583 | +# Example configuration for fixed name service. |
| 3584 | +# See the description of OPTION_EGLIBC_NSSWITCH in option-groups.def |
| 3585 | +# for details. |
| 3586 | +# |
| 3587 | + |
| 3588 | +aliases: files |
| 3589 | + |
| 3590 | +passwd: files |
| 3591 | +group: files |
| 3592 | +shadow: files |
| 3593 | + |
| 3594 | +hosts: files dns |
| 3595 | +networks: files dns |
| 3596 | + |
| 3597 | +protocols: files |
| 3598 | +services: files |
| 3599 | +ethers: files |
| 3600 | +rpc: files |
| 3601 | + |
| 3602 | +netgroup: files |
| 3603 | diff --git a/nss/fixed-nsswitch.functions b/nss/fixed-nsswitch.functions |
| 3604 | new file mode 100644 |
| 3605 | index 0000000..2f3fa83 |
| 3606 | --- /dev/null |
| 3607 | +++ b/nss/fixed-nsswitch.functions |
| 3608 | @@ -0,0 +1,121 @@ |
| 3609 | +/* List of functions defined for fixed NSS in GNU C Library. |
| 3610 | + Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. |
| 3611 | + This file is part of the GNU C Library. |
| 3612 | + |
| 3613 | + The GNU C Library is free software; you can redistribute it and/or |
| 3614 | + modify it under the terms of the GNU Lesser General Public |
| 3615 | + License as published by the Free Software Foundation; either |
| 3616 | + version 2.1 of the License, or (at your option) any later version. |
| 3617 | + |
| 3618 | + The GNU C Library is distributed in the hope that it will be useful, |
| 3619 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 3620 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 3621 | + Lesser General Public License for more details. |
| 3622 | + |
| 3623 | + You should have received a copy of the GNU Lesser General Public |
| 3624 | + License along with the GNU C Library; if not, write to the Free |
| 3625 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 3626 | + 02111-1307 USA. */ |
| 3627 | + |
| 3628 | +/* When OPTION_EGLIBC_NSSWITCH is disabled (see option-groups.def), |
| 3629 | + EGLIBC does not use the 'dlopen' and 'dlsym' functions to look for |
| 3630 | + database query functions in the individual name service libraries. |
| 3631 | + Instead, it uses a set of functions chosen at compile time, as |
| 3632 | + directed by the OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS file. This |
| 3633 | + file is a sample of what you might use there. |
| 3634 | + |
| 3635 | + This file is C source code; it should only contain invocations of |
| 3636 | + the following macros: |
| 3637 | + |
| 3638 | + - DEFINE_ENT (DATABASE, SERVICE, X) |
| 3639 | + |
| 3640 | + Declare the 'setXent', 'getXent_r', and 'endXent' functions that |
| 3641 | + query DATABASE using the service library 'libnss_SERVICE.so.2'. |
| 3642 | + DATABASE should be the full name of the database as it appears in |
| 3643 | + 'nsswitch.conf', like 'passwd' or 'aliases'. |
| 3644 | + |
| 3645 | + (The non-reentrant 'getXent' functions are implemented in terms |
| 3646 | + of the reentrant 'getXent_r' functions, so there is no need to |
| 3647 | + refer to them explicitly here.) |
| 3648 | + |
| 3649 | + - DEFINE_GETBY (DATABASE, SERVICE, X, KEY) |
| 3650 | + |
| 3651 | + Declare the 'getXbyKEY_r' functions that query DATABASE using |
| 3652 | + SERVICE. DATABASE and SERVICE are as described above. |
| 3653 | + |
| 3654 | + (The non-reentrant 'getXbyKEY' functions are implemented in terms |
| 3655 | + of the reentrant 'getXbyKEY_r' functions, so there is no need to |
| 3656 | + refer to them explicitly here.) |
| 3657 | + |
| 3658 | + Use the special key 'name3' for the service library function that |
| 3659 | + implements the 'getaddrinfo' function. |
| 3660 | + |
| 3661 | + - DEFINE_GET (DATABASE, SERVICE, QUERY) |
| 3662 | + |
| 3663 | + Declare the 'getQUERY_r' functions that query DATABASE using |
| 3664 | + SERVICE. This is used for functions like 'getpwnam'. |
| 3665 | + |
| 3666 | + (The non-reentrant 'getQUERY' functions are implemented in terms |
| 3667 | + of the reentrant 'getQUERY_r' functions, so there is no need to |
| 3668 | + refer to them explicitly here.) |
| 3669 | + |
| 3670 | + This sample file only includes functions that consult the files in |
| 3671 | + '/etc', and the Domain Name System (DNS). */ |
| 3672 | + |
| 3673 | +/* aliases */ |
| 3674 | +DEFINE_ENT (aliases, files, alias) |
| 3675 | +DEFINE_GETBY (aliases, files, alias, name) |
| 3676 | + |
| 3677 | +/* ethers */ |
| 3678 | +DEFINE_ENT (ethers, files, ether) |
| 3679 | + |
| 3680 | +/* group */ |
| 3681 | +DEFINE_ENT (group, files, gr) |
| 3682 | +DEFINE_GET (group, files, grgid) |
| 3683 | +DEFINE_GET (group, files, grnam) |
| 3684 | + |
| 3685 | +/* hosts */ |
| 3686 | +DEFINE_ENT (hosts, files, host) |
| 3687 | +DEFINE_GETBY (hosts, files, host, addr) |
| 3688 | +DEFINE_GETBY (hosts, files, host, name) |
| 3689 | +DEFINE_GETBY (hosts, files, host, name2) |
| 3690 | +DEFINE_GET (hosts, files, hostton) |
| 3691 | +DEFINE_GET (hosts, files, ntohost) |
| 3692 | +DEFINE_GETBY (hosts, dns, host, addr) |
| 3693 | +DEFINE_GETBY (hosts, dns, host, name) |
| 3694 | +DEFINE_GETBY (hosts, dns, host, name2) |
| 3695 | +DEFINE_GETBY (hosts, dns, host, name3) |
| 3696 | + |
| 3697 | +/* netgroup */ |
| 3698 | +DEFINE_ENT (netgroup, files, netgr) |
| 3699 | + |
| 3700 | +/* networks */ |
| 3701 | +DEFINE_ENT (networks, files, net) |
| 3702 | +DEFINE_GETBY (networks, files, net, name) |
| 3703 | +DEFINE_GETBY (networks, files, net, addr) |
| 3704 | +DEFINE_GETBY (networks, dns, net, name) |
| 3705 | +DEFINE_GETBY (networks, dns, net, addr) |
| 3706 | + |
| 3707 | +/* protocols */ |
| 3708 | +DEFINE_ENT (protocols, files, proto) |
| 3709 | +DEFINE_GETBY (protocols, files, proto, name) |
| 3710 | +DEFINE_GETBY (protocols, files, proto, number) |
| 3711 | + |
| 3712 | +/* passwd */ |
| 3713 | +DEFINE_ENT (passwd, files, pw) |
| 3714 | +DEFINE_GET (passwd, files, pwnam) |
| 3715 | +DEFINE_GET (passwd, files, pwuid) |
| 3716 | + |
| 3717 | +/* rpc */ |
| 3718 | +DEFINE_ENT (rpc, files, rpc) |
| 3719 | +DEFINE_GETBY (rpc, files, rpc, name) |
| 3720 | +DEFINE_GETBY (rpc, files, rpc, number) |
| 3721 | + |
| 3722 | +/* services */ |
| 3723 | +DEFINE_ENT (services, files, serv) |
| 3724 | +DEFINE_GETBY (services, files, serv, name) |
| 3725 | +DEFINE_GETBY (services, files, serv, port) |
| 3726 | + |
| 3727 | +/* shadow */ |
| 3728 | +DEFINE_ENT (shadow, files, sp) |
| 3729 | +DEFINE_GET (shadow, files, spnam) |
| 3730 | diff --git a/nss/gen-fixed-nsswitch.c b/nss/gen-fixed-nsswitch.c |
| 3731 | new file mode 100644 |
| 3732 | index 0000000..6e1c98c |
| 3733 | --- /dev/null |
| 3734 | +++ b/nss/gen-fixed-nsswitch.c |
| 3735 | @@ -0,0 +1,803 @@ |
| 3736 | +/* gen-fixed-nsswitch.c --- generate fixed name service data structures |
| 3737 | + Copyright (C) 1996-1999, 2001-2006, 2007 Free Software Foundation, Inc. |
| 3738 | + This file is part of the GNU C Library. |
| 3739 | + |
| 3740 | + The GNU C Library is free software; you can redistribute it and/or |
| 3741 | + modify it under the terms of the GNU Lesser General Public |
| 3742 | + License as published by the Free Software Foundation; either |
| 3743 | + version 2.1 of the License, or (at your option) any later version. |
| 3744 | + |
| 3745 | + The GNU C Library is distributed in the hope that it will be useful, |
| 3746 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 3747 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 3748 | + Lesser General Public License for more details. |
| 3749 | + |
| 3750 | + You should have received a copy of the GNU Lesser General Public |
| 3751 | + License along with the GNU C Library; if not, write to the Free |
| 3752 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 3753 | + 02111-1307 USA. */ |
| 3754 | + |
| 3755 | +#define _GNU_SOURCE |
| 3756 | + |
| 3757 | +#include <stdlib.h> |
| 3758 | +#include <stdio.h> |
| 3759 | +#include <errno.h> |
| 3760 | +#include <string.h> |
| 3761 | +#include <stdarg.h> |
| 3762 | +#include <assert.h> |
| 3763 | +#include <ctype.h> |
| 3764 | + |
| 3765 | +#include "gnu/lib-names.h" |
| 3766 | +#include "nss.h" |
| 3767 | + |
| 3768 | +/* Provide a fallback definition to allow this file to be compiled outside |
| 3769 | + libc. */ |
| 3770 | +#ifndef internal_function |
| 3771 | +# define internal_function |
| 3772 | +#endif |
| 3773 | + |
| 3774 | + |
| 3775 | +/* Simple utilities. */ |
| 3776 | + |
| 3777 | +void __attribute__ ((noreturn)) |
| 3778 | +error (const char *message) |
| 3779 | +{ |
| 3780 | + fprintf (stderr, "%s\n", message); |
| 3781 | + exit (1); |
| 3782 | +} |
| 3783 | + |
| 3784 | + |
| 3785 | +void * |
| 3786 | +check_alloc (void *p) |
| 3787 | +{ |
| 3788 | + if (p) |
| 3789 | + return p; |
| 3790 | + else |
| 3791 | + error ("out of memory"); |
| 3792 | +} |
| 3793 | + |
| 3794 | +void * |
| 3795 | +xmalloc (size_t size) |
| 3796 | +{ |
| 3797 | + return check_alloc (malloc (size)); |
| 3798 | +} |
| 3799 | + |
| 3800 | + |
| 3801 | +/* Format ARGS according to FORMAT, and return the result as a |
| 3802 | + malloc'ed string. */ |
| 3803 | +char * |
| 3804 | +saprintf (const char *format, ...) |
| 3805 | +{ |
| 3806 | + va_list args; |
| 3807 | + size_t len; |
| 3808 | + char *buf; |
| 3809 | + |
| 3810 | + va_start (args, format); |
| 3811 | + len = vsnprintf (NULL, 0, format, args); |
| 3812 | + va_end (args); |
| 3813 | + |
| 3814 | + buf = xmalloc (len + 1); |
| 3815 | + va_start (args, format); |
| 3816 | + assert (len == vsnprintf (buf, len + 1, format, args)); |
| 3817 | + va_end (args); |
| 3818 | + |
| 3819 | + return buf; |
| 3820 | +} |
| 3821 | + |
| 3822 | + |
| 3823 | + |
| 3824 | +/* Data structures representing the configuration file in memory. */ |
| 3825 | + |
| 3826 | +/* These are copied from nsswitch.h. |
| 3827 | + |
| 3828 | + We could simply #include that file, but this program runs on the |
| 3829 | + build machine and links against the build machine's libraries, |
| 3830 | + whereas that header is meant for use by target code; it uses |
| 3831 | + 'libc_hidden_proto', 'internal_function', and related hair. Since |
| 3832 | + we've copied the parsing code, we might as well copy the data |
| 3833 | + structure definitions as well. */ |
| 3834 | + |
| 3835 | +/* Actions performed after lookup finished. */ |
| 3836 | +typedef enum |
| 3837 | +{ |
| 3838 | + NSS_ACTION_CONTINUE, |
| 3839 | + NSS_ACTION_RETURN |
| 3840 | +} lookup_actions; |
| 3841 | + |
| 3842 | + |
| 3843 | +typedef struct service_library |
| 3844 | +{ |
| 3845 | + /* Name of service (`files', `dns', `nis', ...). */ |
| 3846 | + const char *name; |
| 3847 | + /* Pointer to the loaded shared library. */ |
| 3848 | + void *lib_handle; |
| 3849 | + /* And the link to the next entry. */ |
| 3850 | + struct service_library *next; |
| 3851 | +} service_library; |
| 3852 | + |
| 3853 | + |
| 3854 | +/* For mapping a function name to a function pointer. It is known in |
| 3855 | + nsswitch.c:nss_lookup_function that a string pointer for the lookup key |
| 3856 | + is the first member. */ |
| 3857 | +typedef struct |
| 3858 | +{ |
| 3859 | + const char *fct_name; |
| 3860 | + void *fct_ptr; |
| 3861 | +} known_function; |
| 3862 | + |
| 3863 | + |
| 3864 | +typedef struct service_user |
| 3865 | +{ |
| 3866 | + /* And the link to the next entry. */ |
| 3867 | + struct service_user *next; |
| 3868 | + /* Action according to result. */ |
| 3869 | + lookup_actions actions[5]; |
| 3870 | + /* Link to the underlying library object. */ |
| 3871 | + service_library *library; |
| 3872 | + /* Collection of known functions. |
| 3873 | + |
| 3874 | + With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a |
| 3875 | + 'tsearch'-style tree. |
| 3876 | + |
| 3877 | + With OPTION_EGLIBC_NSSWITCH disabled, this is an array of |
| 3878 | + pointers to known_function structures, NULL-terminated. */ |
| 3879 | + union |
| 3880 | + { |
| 3881 | + void *tree; |
| 3882 | + const known_function **array; |
| 3883 | + } known; |
| 3884 | + /* Name of the service (`files', `dns', `nis', ...). */ |
| 3885 | + const char *name; |
| 3886 | +} service_user; |
| 3887 | + |
| 3888 | +/* To access the action based on the status value use this macro. */ |
| 3889 | +#define nss_next_action(ni, status) ((ni)->actions[2 + status]) |
| 3890 | + |
| 3891 | + |
| 3892 | +typedef struct name_database_entry |
| 3893 | +{ |
| 3894 | + /* And the link to the next entry. */ |
| 3895 | + struct name_database_entry *next; |
| 3896 | + /* List of service to be used. */ |
| 3897 | + service_user *service; |
| 3898 | + /* Name of the database. */ |
| 3899 | + const char *name; |
| 3900 | +} name_database_entry; |
| 3901 | + |
| 3902 | + |
| 3903 | +typedef struct name_database |
| 3904 | +{ |
| 3905 | + /* List of all known databases. */ |
| 3906 | + name_database_entry *entry; |
| 3907 | + /* List of libraries with service implementation. */ |
| 3908 | + service_library *library; |
| 3909 | +} name_database; |
| 3910 | + |
| 3911 | + |
| 3912 | + |
| 3913 | +/* Gathering the contents of the FIXED_FUNCTIONS file. */ |
| 3914 | + |
| 3915 | +/* It should be possible to generate this list automatically by |
| 3916 | + looking at the services and databases used in the nsswitch.conf |
| 3917 | + file, and having a hard-coded set of queries supported on each |
| 3918 | + database. */ |
| 3919 | + |
| 3920 | +/* We #include the FIXED_FUNCTIONS file several times to build an |
| 3921 | + array of function structures holding its data. */ |
| 3922 | +enum function_kind { |
| 3923 | + fk_end = 0, /* Last entry. */ |
| 3924 | + fk_setent, /* Like setpwent. */ |
| 3925 | + fk_getent, /* Like getpwent. */ |
| 3926 | + fk_endent, /* Like endpwent. */ |
| 3927 | + fk_getby, /* Like gethostbyname. */ |
| 3928 | + fk_get /* Like getpwnam. */ |
| 3929 | +}; |
| 3930 | + |
| 3931 | + |
| 3932 | +struct function { |
| 3933 | + /* What kind of function this is. */ |
| 3934 | + enum function_kind kind; |
| 3935 | + |
| 3936 | + /* The database and service of the function being hardwired in. */ |
| 3937 | + char *database, *service; |
| 3938 | + |
| 3939 | + /* The kind of entry being queried, for 'fk_setent', 'fk_getent', |
| 3940 | + 'fk_endent', and 'fk_getby' functions. */ |
| 3941 | + char *entry; |
| 3942 | + |
| 3943 | + /* The key, for 'fk_getby' entries. */ |
| 3944 | + char *key; |
| 3945 | + |
| 3946 | + /* The value and key, for 'fk_get' entries. */ |
| 3947 | + char *value_and_key; |
| 3948 | +}; |
| 3949 | + |
| 3950 | + |
| 3951 | +const struct function functions[] = |
| 3952 | + { |
| 3953 | + |
| 3954 | +#define DEFINE_ENT(database, service, entry) \ |
| 3955 | + { fk_setent, #database, #service, #entry }, \ |
| 3956 | + { fk_getent, #database, #service, #entry }, \ |
| 3957 | + { fk_endent, #database, #service, #entry }, |
| 3958 | +#define DEFINE_GETBY(database, service, entry, key) \ |
| 3959 | + { fk_getby, #database, #service, #entry, #key }, |
| 3960 | +#define DEFINE_GET(database, service, value_and_key) \ |
| 3961 | + { fk_get, #database, #service, NULL, NULL, #value_and_key }, |
| 3962 | + |
| 3963 | +#include FIXED_FUNCTIONS |
| 3964 | + |
| 3965 | +#undef DEFINE_ENT |
| 3966 | +#undef DEFINE_GETBY |
| 3967 | +#undef DEFINE_GET |
| 3968 | + |
| 3969 | + { fk_end } |
| 3970 | + }; |
| 3971 | + |
| 3972 | + |
| 3973 | +/* Parsing the config file. Functions copied from nsswitch.c. */ |
| 3974 | + |
| 3975 | +#define __strchrnul strchrnul |
| 3976 | +#define __getline getline |
| 3977 | +#define __strncasecmp strncasecmp |
| 3978 | + |
| 3979 | +/* Prototypes for the local functions. */ |
| 3980 | +static name_database *nss_parse_file (const char *fname) internal_function; |
| 3981 | +static name_database_entry *nss_getline (char *line) internal_function; |
| 3982 | +static service_user *nss_parse_service_list (const char *line) |
| 3983 | + internal_function; |
| 3984 | + |
| 3985 | +static name_database * |
| 3986 | +internal_function |
| 3987 | +nss_parse_file (const char *fname) |
| 3988 | +{ |
| 3989 | + FILE *fp; |
| 3990 | + name_database *result; |
| 3991 | + name_database_entry *last; |
| 3992 | + char *line; |
| 3993 | + size_t len; |
| 3994 | + |
| 3995 | + /* Open the configuration file. */ |
| 3996 | + fp = fopen (fname, "rc"); |
| 3997 | + if (fp == NULL) |
| 3998 | + return NULL; |
| 3999 | + |
| 4000 | + // /* No threads use this stream. */ |
| 4001 | + // __fsetlocking (fp, FSETLOCKING_BYCALLER); |
| 4002 | + |
| 4003 | + result = (name_database *) xmalloc (sizeof (name_database)); |
| 4004 | + |
| 4005 | + result->entry = NULL; |
| 4006 | + result->library = NULL; |
| 4007 | + last = NULL; |
| 4008 | + line = NULL; |
| 4009 | + len = 0; |
| 4010 | + do |
| 4011 | + { |
| 4012 | + name_database_entry *this; |
| 4013 | + ssize_t n; |
| 4014 | + |
| 4015 | + n = __getline (&line, &len, fp); |
| 4016 | + if (n < 0) |
| 4017 | + break; |
| 4018 | + if (line[n - 1] == '\n') |
| 4019 | + line[n - 1] = '\0'; |
| 4020 | + |
| 4021 | + /* Because the file format does not know any form of quoting we |
| 4022 | + can search forward for the next '#' character and if found |
| 4023 | + make it terminating the line. */ |
| 4024 | + *__strchrnul (line, '#') = '\0'; |
| 4025 | + |
| 4026 | + /* If the line is blank it is ignored. */ |
| 4027 | + if (line[0] == '\0') |
| 4028 | + continue; |
| 4029 | + |
| 4030 | + /* Each line completely specifies the actions for a database. */ |
| 4031 | + this = nss_getline (line); |
| 4032 | + if (this != NULL) |
| 4033 | + { |
| 4034 | + if (last != NULL) |
| 4035 | + last->next = this; |
| 4036 | + else |
| 4037 | + result->entry = this; |
| 4038 | + |
| 4039 | + last = this; |
| 4040 | + } |
| 4041 | + } |
| 4042 | + while (!feof_unlocked (fp)); |
| 4043 | + |
| 4044 | + /* Free the buffer. */ |
| 4045 | + free (line); |
| 4046 | + /* Close configuration file. */ |
| 4047 | + fclose (fp); |
| 4048 | + |
| 4049 | + return result; |
| 4050 | +} |
| 4051 | + |
| 4052 | + |
| 4053 | +/* Read the source names: |
| 4054 | + `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*' |
| 4055 | + */ |
| 4056 | +static service_user * |
| 4057 | +internal_function |
| 4058 | +nss_parse_service_list (const char *line) |
| 4059 | +{ |
| 4060 | + service_user *result = NULL, **nextp = &result; |
| 4061 | + |
| 4062 | + while (1) |
| 4063 | + { |
| 4064 | + service_user *new_service; |
| 4065 | + const char *name; |
| 4066 | + |
| 4067 | + while (isspace (line[0])) |
| 4068 | + ++line; |
| 4069 | + if (line[0] == '\0') |
| 4070 | + /* No source specified. */ |
| 4071 | + return result; |
| 4072 | + |
| 4073 | + /* Read <source> identifier. */ |
| 4074 | + name = line; |
| 4075 | + while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') |
| 4076 | + ++line; |
| 4077 | + if (name == line) |
| 4078 | + return result; |
| 4079 | + |
| 4080 | + |
| 4081 | + new_service = (service_user *) xmalloc (sizeof (*new_service)); |
| 4082 | + new_service->name = (char *) xmalloc (line - name + 1); |
| 4083 | + |
| 4084 | + *((char *) __mempcpy ((char *) new_service->name, name, line - name)) |
| 4085 | + = '\0'; |
| 4086 | + |
| 4087 | + /* Set default actions. */ |
| 4088 | + new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; |
| 4089 | + new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; |
| 4090 | + new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; |
| 4091 | + new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; |
| 4092 | + new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; |
| 4093 | + new_service->library = NULL; |
| 4094 | + new_service->known.tree = NULL; |
| 4095 | + new_service->next = NULL; |
| 4096 | + |
| 4097 | + while (isspace (line[0])) |
| 4098 | + ++line; |
| 4099 | + |
| 4100 | + if (line[0] == '[') |
| 4101 | + { |
| 4102 | + /* Read criterions. */ |
| 4103 | + do |
| 4104 | + ++line; |
| 4105 | + while (line[0] != '\0' && isspace (line[0])); |
| 4106 | + |
| 4107 | + do |
| 4108 | + { |
| 4109 | + int not; |
| 4110 | + enum nss_status status; |
| 4111 | + lookup_actions action; |
| 4112 | + |
| 4113 | + /* Grok ! before name to mean all statii but that one. */ |
| 4114 | + not = line[0] == '!'; |
| 4115 | + if (not) |
| 4116 | + ++line; |
| 4117 | + |
| 4118 | + /* Read status name. */ |
| 4119 | + name = line; |
| 4120 | + while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' |
| 4121 | + && line[0] != ']') |
| 4122 | + ++line; |
| 4123 | + |
| 4124 | + /* Compare with known statii. */ |
| 4125 | + if (line - name == 7) |
| 4126 | + { |
| 4127 | + if (__strncasecmp (name, "SUCCESS", 7) == 0) |
| 4128 | + status = NSS_STATUS_SUCCESS; |
| 4129 | + else if (__strncasecmp (name, "UNAVAIL", 7) == 0) |
| 4130 | + status = NSS_STATUS_UNAVAIL; |
| 4131 | + else |
| 4132 | + return result; |
| 4133 | + } |
| 4134 | + else if (line - name == 8) |
| 4135 | + { |
| 4136 | + if (__strncasecmp (name, "NOTFOUND", 8) == 0) |
| 4137 | + status = NSS_STATUS_NOTFOUND; |
| 4138 | + else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) |
| 4139 | + status = NSS_STATUS_TRYAGAIN; |
| 4140 | + else |
| 4141 | + return result; |
| 4142 | + } |
| 4143 | + else |
| 4144 | + return result; |
| 4145 | + |
| 4146 | + while (isspace (line[0])) |
| 4147 | + ++line; |
| 4148 | + if (line[0] != '=') |
| 4149 | + return result; |
| 4150 | + do |
| 4151 | + ++line; |
| 4152 | + while (isspace (line[0])); |
| 4153 | + |
| 4154 | + name = line; |
| 4155 | + while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' |
| 4156 | + && line[0] != ']') |
| 4157 | + ++line; |
| 4158 | + |
| 4159 | + if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) |
| 4160 | + action = NSS_ACTION_RETURN; |
| 4161 | + else if (line - name == 8 |
| 4162 | + && __strncasecmp (name, "CONTINUE", 8) == 0) |
| 4163 | + action = NSS_ACTION_CONTINUE; |
| 4164 | + else |
| 4165 | + return result; |
| 4166 | + |
| 4167 | + if (not) |
| 4168 | + { |
| 4169 | + /* Save the current action setting for this status, |
| 4170 | + set them all to the given action, and reset this one. */ |
| 4171 | + const lookup_actions save = new_service->actions[2 + status]; |
| 4172 | + new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; |
| 4173 | + new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; |
| 4174 | + new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; |
| 4175 | + new_service->actions[2 + NSS_STATUS_SUCCESS] = action; |
| 4176 | + new_service->actions[2 + status] = save; |
| 4177 | + } |
| 4178 | + else |
| 4179 | + new_service->actions[2 + status] = action; |
| 4180 | + |
| 4181 | + /* Skip white spaces. */ |
| 4182 | + while (isspace (line[0])) |
| 4183 | + ++line; |
| 4184 | + } |
| 4185 | + while (line[0] != ']'); |
| 4186 | + |
| 4187 | + /* Skip the ']'. */ |
| 4188 | + ++line; |
| 4189 | + } |
| 4190 | + |
| 4191 | + *nextp = new_service; |
| 4192 | + nextp = &new_service->next; |
| 4193 | + } |
| 4194 | +} |
| 4195 | + |
| 4196 | +static name_database_entry * |
| 4197 | +internal_function |
| 4198 | +nss_getline (char *line) |
| 4199 | +{ |
| 4200 | + const char *name; |
| 4201 | + name_database_entry *result; |
| 4202 | + size_t len; |
| 4203 | + |
| 4204 | + /* Ignore leading white spaces. ATTENTION: this is different from |
| 4205 | + what is implemented in Solaris. The Solaris man page says a line |
| 4206 | + beginning with a white space character is ignored. We regard |
| 4207 | + this as just another misfeature in Solaris. */ |
| 4208 | + while (isspace (line[0])) |
| 4209 | + ++line; |
| 4210 | + |
| 4211 | + /* Recognize `<database> ":"'. */ |
| 4212 | + name = line; |
| 4213 | + while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') |
| 4214 | + ++line; |
| 4215 | + if (line[0] == '\0' || name == line) |
| 4216 | + /* Syntax error. */ |
| 4217 | + return NULL; |
| 4218 | + *line++ = '\0'; |
| 4219 | + |
| 4220 | + len = strlen (name) + 1; |
| 4221 | + |
| 4222 | + result = (name_database_entry *) xmalloc (sizeof (*result)); |
| 4223 | + result->name = (char *) xmalloc (len); |
| 4224 | + |
| 4225 | + /* Save the database name. */ |
| 4226 | + memcpy ((char *) result->name, name, len); |
| 4227 | + |
| 4228 | + /* Parse the list of services. */ |
| 4229 | + result->service = nss_parse_service_list (line); |
| 4230 | + |
| 4231 | + result->next = NULL; |
| 4232 | + return result; |
| 4233 | +} |
| 4234 | + |
| 4235 | + |
| 4236 | + |
| 4237 | +/* Generating code for statically initialized nsswitch structures. */ |
| 4238 | + |
| 4239 | + |
| 4240 | +/* Return the service-neutral suffix of the name of the service |
| 4241 | + library function referred to by the function F. The result is |
| 4242 | + allocated with malloc. */ |
| 4243 | +char * |
| 4244 | +known_function_suffix (const struct function *f) |
| 4245 | +{ |
| 4246 | + switch (f->kind) |
| 4247 | + { |
| 4248 | + case fk_setent: |
| 4249 | + return saprintf ("set%sent", f->entry); |
| 4250 | + |
| 4251 | + case fk_getent: |
| 4252 | + return saprintf ("get%sent_r", f->entry); |
| 4253 | + |
| 4254 | + case fk_endent: |
| 4255 | + return saprintf ("end%sent", f->entry); |
| 4256 | + |
| 4257 | + case fk_getby: |
| 4258 | + return saprintf ("get%sby%s_r", f->entry, f->key); |
| 4259 | + |
| 4260 | + case fk_get: |
| 4261 | + return saprintf ("get%s_r", f->value_and_key); |
| 4262 | + |
| 4263 | + default: |
| 4264 | + abort (); |
| 4265 | + } |
| 4266 | +} |
| 4267 | + |
| 4268 | + |
| 4269 | +/* Return the name of the service library function referred to by the |
| 4270 | + function F. The result is allocated with malloc. */ |
| 4271 | +char * |
| 4272 | +known_function_name (const struct function *f) |
| 4273 | +{ |
| 4274 | + return saprintf ("_nss_%s_%s", f->service, known_function_suffix (f)); |
| 4275 | +} |
| 4276 | + |
| 4277 | + |
| 4278 | +/* Write initialized known_function structures to OUT for |
| 4279 | + all the functions we'll use. */ |
| 4280 | +void |
| 4281 | +generate_known_functions (FILE *out) |
| 4282 | +{ |
| 4283 | + int i; |
| 4284 | + |
| 4285 | + /* First, generate weak references to the functions. The service |
| 4286 | + libraries depend on libc, and if these references weren't weak, |
| 4287 | + we'd be making libc depend circularly on the service |
| 4288 | + libraries. */ |
| 4289 | + for (i = 0; functions[i].kind; i++) |
| 4290 | + { |
| 4291 | + char *name = known_function_name (&functions[i]); |
| 4292 | + fprintf (out, "typeof (%s) %s __attribute__ ((weak));\n", |
| 4293 | + name, name); |
| 4294 | + } |
| 4295 | + fputs ("\n", out); |
| 4296 | + |
| 4297 | + /* Then, a table mapping names to functions. */ |
| 4298 | + fputs ("static const known_function fixed_known_functions[] = {\n", |
| 4299 | + out); |
| 4300 | + for (i = 0; functions[i].kind; i++) |
| 4301 | + { |
| 4302 | + const struct function *f = &functions[i]; |
| 4303 | + char *suffix = known_function_suffix (f); |
| 4304 | + |
| 4305 | + fprintf (out, " /* %2d */ { \"%s\", _nss_%s_%s },\n", |
| 4306 | + i, suffix, f->service, suffix); |
| 4307 | + } |
| 4308 | + fputs ("};\n", out); |
| 4309 | + fputs ("\n", out); |
| 4310 | +} |
| 4311 | + |
| 4312 | + |
| 4313 | +/* Print code to OUT for an initialized array of pointers to the |
| 4314 | + 'known_function' structures needed for USER, which is for |
| 4315 | + DATABASE. Return its name, allocated with malloc. */ |
| 4316 | +char * |
| 4317 | +generate_known_function_list (FILE *out, |
| 4318 | + const name_database_entry *database, |
| 4319 | + const service_user *user) |
| 4320 | +{ |
| 4321 | + char *list_name = saprintf ("fixed_%s_%s_known_funcs", |
| 4322 | + database->name, user->name); |
| 4323 | + fprintf (out, "static const known_function *%s[] = {\n", |
| 4324 | + list_name); |
| 4325 | + int i; |
| 4326 | + for (i = 0; functions[i].kind; i++) |
| 4327 | + if (strcmp (functions[i].database, database->name) == 0 |
| 4328 | + && strcmp (functions[i].service, user->name) == 0) |
| 4329 | + fprintf (out, " &fixed_known_functions[%d], /* %s */\n", |
| 4330 | + i, known_function_name (&functions[i])); |
| 4331 | + fputs (" NULL\n", out); |
| 4332 | + fputs ("};\n", out); |
| 4333 | + fputs ("\n", out); |
| 4334 | + |
| 4335 | + return list_name; |
| 4336 | +} |
| 4337 | + |
| 4338 | + |
| 4339 | +/* Return the name of the status value STATUS, as a statically |
| 4340 | + allocated string. */ |
| 4341 | +const char * |
| 4342 | +lookup_status_name (enum nss_status status) |
| 4343 | +{ |
| 4344 | + switch (status) |
| 4345 | + { |
| 4346 | + case NSS_STATUS_TRYAGAIN: return "NSS_STATUS_TRYAGAIN"; |
| 4347 | + case NSS_STATUS_UNAVAIL: return "NSS_STATUS_UNAVAIL"; |
| 4348 | + case NSS_STATUS_NOTFOUND: return "NSS_STATUS_NOTFOUND"; |
| 4349 | + case NSS_STATUS_SUCCESS: return "NSS_STATUS_SUCCESS"; |
| 4350 | + case NSS_STATUS_RETURN: return "NSS_STATUS_RETURN"; |
| 4351 | + default: abort (); |
| 4352 | + }; |
| 4353 | +} |
| 4354 | + |
| 4355 | + |
| 4356 | +/* Return the name of ACTION as a statically allocated string. */ |
| 4357 | +const char * |
| 4358 | +lookup_action_name (lookup_actions action) |
| 4359 | +{ |
| 4360 | + switch (action) |
| 4361 | + { |
| 4362 | + case NSS_ACTION_CONTINUE: return "NSS_ACTION_CONTINUE"; |
| 4363 | + case NSS_ACTION_RETURN: return "NSS_ACTION_RETURN"; |
| 4364 | + default: abort (); |
| 4365 | + } |
| 4366 | +} |
| 4367 | + |
| 4368 | + |
| 4369 | +/* Print code to OUT for the list of service_user structures starting |
| 4370 | + with USER, which are all for DATABASE. Return the name of the |
| 4371 | + first structure in that list, or zero if USER is NULL. */ |
| 4372 | +char * |
| 4373 | +generate_service_user_list (FILE *out, |
| 4374 | + name_database_entry *database, |
| 4375 | + service_user *user) |
| 4376 | +{ |
| 4377 | + if (user) |
| 4378 | + { |
| 4379 | + /* Generate the tail of the list. */ |
| 4380 | + char *next_name = generate_service_user_list (out, database, user->next); |
| 4381 | + /* Generate our known function list. */ |
| 4382 | + char *known_function_list_name = |
| 4383 | + generate_known_function_list (out, database, user); |
| 4384 | + |
| 4385 | + char *name = saprintf ("fixed_%s_%s_user", database->name, user->name); |
| 4386 | + |
| 4387 | + fprintf (out, "static const service_user %s = {\n", name); |
| 4388 | + if (next_name) |
| 4389 | + fprintf (out, " (service_user *) &%s,\n", next_name); |
| 4390 | + else |
| 4391 | + fprintf (out, " NULL, /* no next entry */\n"); |
| 4392 | + fputs (" {\n", out); |
| 4393 | + int i; |
| 4394 | + for (i = 0; i < sizeof (user->actions) / sizeof (user->actions[0]); i++) |
| 4395 | + fprintf (out, " %s, /* %s */\n", |
| 4396 | + lookup_action_name (user->actions[i]), |
| 4397 | + lookup_status_name (i - 2)); |
| 4398 | + fputs (" },\n", out); |
| 4399 | + fprintf (out, " NULL, /* we never need the service library */\n"); |
| 4400 | + fprintf (out, " { .array = %s },\n", known_function_list_name); |
| 4401 | + fprintf (out, " \"%s\"\n", user->name); |
| 4402 | + fputs ("};\n", out); |
| 4403 | + fputs ("\n", out); |
| 4404 | + |
| 4405 | + return name; |
| 4406 | + } |
| 4407 | + else |
| 4408 | + return NULL; |
| 4409 | +} |
| 4410 | + |
| 4411 | + |
| 4412 | +/* Print code to OUT for the list of name_database_entry structures |
| 4413 | + starting with DATABASE. Return the name of the first structure |
| 4414 | + in that list, or zero if DATABASE is NULL. */ |
| 4415 | +char * |
| 4416 | +generate_name_database_entries (FILE *out, name_database_entry *database) |
| 4417 | +{ |
| 4418 | + if (database) |
| 4419 | + { |
| 4420 | + char *next_name = generate_name_database_entries (out, database->next); |
| 4421 | + char *service_user_name |
| 4422 | + = generate_service_user_list (out, database, database->service); |
| 4423 | + char *name = saprintf ("fixed_%s_name_database", database->name); |
| 4424 | + |
| 4425 | + fprintf (out, "static const name_database_entry %s = {\n", name); |
| 4426 | + |
| 4427 | + if (next_name) |
| 4428 | + fprintf (out, " (name_database_entry *) &%s,\n", next_name); |
| 4429 | + else |
| 4430 | + fprintf (out, " NULL,\n"); |
| 4431 | + |
| 4432 | + if (service_user_name) |
| 4433 | + fprintf (out, " (service_user *) &%s,\n", service_user_name); |
| 4434 | + else |
| 4435 | + fprintf (out, " NULL,\n"); |
| 4436 | + |
| 4437 | + fprintf (out, " \"%s\"\n", database->name); |
| 4438 | + fprintf (out, "};\n"); |
| 4439 | + fputs ("\n", out); |
| 4440 | + |
| 4441 | + return name; |
| 4442 | + } |
| 4443 | + else |
| 4444 | + return NULL; |
| 4445 | +} |
| 4446 | + |
| 4447 | + |
| 4448 | +void |
| 4449 | +generate_name_database (FILE *out, name_database *service_table) |
| 4450 | +{ |
| 4451 | + /* Produce a linked list of the known name_database_entry |
| 4452 | + structures. */ |
| 4453 | + char *entries = generate_name_database_entries (out, service_table->entry); |
| 4454 | + |
| 4455 | + /* Now produce the main structure that points to them all. */ |
| 4456 | + fprintf (out, "static const name_database fixed_name_database = {\n"); |
| 4457 | + if (entries) |
| 4458 | + fprintf (out, " (name_database_entry *) &%s,\n", entries); |
| 4459 | + else |
| 4460 | + fprintf (out, " NULL,\n"); |
| 4461 | + fputs (" NULL /* we don't need the libraries */\n" |
| 4462 | + "};\n", |
| 4463 | + out); |
| 4464 | +} |
| 4465 | + |
| 4466 | + |
| 4467 | + |
| 4468 | +/* Generating the list of service libraries we generate references to. */ |
| 4469 | + |
| 4470 | +/* String with revision number of the shared object files. */ |
| 4471 | +static const char *const nss_shlib_revision = LIBNSS_FILES_SO + 15; |
| 4472 | + |
| 4473 | +void |
| 4474 | +generate_service_lib_list (FILE *out, name_database *service_table) |
| 4475 | +{ |
| 4476 | + int i, j; |
| 4477 | + int printed_any = 0; |
| 4478 | + |
| 4479 | + for (i = 0; functions[i].kind; i++) |
| 4480 | + { |
| 4481 | + /* Mention each service library only once. */ |
| 4482 | + for (j = 0; j < i; j++) |
| 4483 | + if (strcmp (functions[i].service, functions[j].service) == 0) |
| 4484 | + break; |
| 4485 | + |
| 4486 | + if (j >= i) |
| 4487 | + { |
| 4488 | + if (printed_any) |
| 4489 | + putc (' ', out); |
| 4490 | + fprintf (out, "-lnss_%s", |
| 4491 | + functions[i].service, |
| 4492 | + nss_shlib_revision); |
| 4493 | + printed_any = 1; |
| 4494 | + } |
| 4495 | + } |
| 4496 | +} |
| 4497 | + |
| 4498 | + |
| 4499 | +/* Main. */ |
| 4500 | + |
| 4501 | +int |
| 4502 | +main (int argc, char **argv) |
| 4503 | +{ |
| 4504 | + if (argc != 4) |
| 4505 | + { |
| 4506 | + fprintf (stderr, "usage: gen-fixed-nsswitch HEADER SERVLIBS CONFIG\n"); |
| 4507 | + exit (1); |
| 4508 | + } |
| 4509 | + |
| 4510 | + name_database *service_table = nss_parse_file (argv[3]); |
| 4511 | + |
| 4512 | + FILE *header = fopen (argv[1], "w"); |
| 4513 | + if (! header) |
| 4514 | + { |
| 4515 | + fprintf (stderr, |
| 4516 | + "gen-fixed-nsswitch: couldn't open output file %s: %s\n", |
| 4517 | + argv[1], strerror (errno)); |
| 4518 | + exit (1); |
| 4519 | + } |
| 4520 | + fputs ("/* Generated by nss/gen-fixed-nsswitch.c. */\n", header); |
| 4521 | + fputs ("\n", header); |
| 4522 | + generate_known_functions (header); |
| 4523 | + generate_name_database (header, service_table); |
| 4524 | + fclose (header); |
| 4525 | + |
| 4526 | + FILE *service_lib_list = fopen (argv[2], "w"); |
| 4527 | + if (! service_lib_list) |
| 4528 | + { |
| 4529 | + fprintf (stderr, |
| 4530 | + "gen-fixed-nsswitch: couldn't open output file %s: %s\n", |
| 4531 | + argv[2], strerror (errno)); |
| 4532 | + exit (1); |
| 4533 | + } |
| 4534 | + generate_service_lib_list (service_lib_list, service_table); |
| 4535 | + fclose (service_lib_list); |
| 4536 | + |
| 4537 | + return 0; |
| 4538 | +} |
| 4539 | diff --git a/nss/getent.c b/nss/getent.c |
| 4540 | index 34df848..674c8ee 100644 |
| 4541 | --- a/nss/getent.c |
| 4542 | +++ b/nss/getent.c |
| 4543 | @@ -39,6 +39,7 @@ |
| 4544 | #include <netinet/ether.h> |
| 4545 | #include <netinet/in.h> |
| 4546 | #include <sys/socket.h> |
| 4547 | +#include <gnu/option-groups.h> |
| 4548 | |
| 4549 | /* Get libc version number. */ |
| 4550 | #include <version.h> |
| 4551 | @@ -91,6 +92,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ |
| 4552 | fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk"); |
| 4553 | } |
| 4554 | |
| 4555 | +#if __OPTION_EGLIBC_DB_ALIASES |
| 4556 | /* This is for aliases */ |
| 4557 | static void |
| 4558 | print_aliases (struct aliasent *alias) |
| 4559 | @@ -135,7 +137,9 @@ aliases_keys (int number, char *key[]) |
| 4560 | |
| 4561 | return result; |
| 4562 | } |
| 4563 | +#endif /* __OPTION_EGLIBC_DB_ALIASES */ |
| 4564 | |
| 4565 | +#if __OPTION_EGLIBC_INET |
| 4566 | /* This is for ethers */ |
| 4567 | static int |
| 4568 | ethers_keys (int number, char *key[]) |
| 4569 | @@ -179,6 +183,7 @@ ethers_keys (int number, char *key[]) |
| 4570 | |
| 4571 | return result; |
| 4572 | } |
| 4573 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4574 | |
| 4575 | /* This is for group */ |
| 4576 | static void |
| 4577 | @@ -301,6 +306,7 @@ gshadow_keys (int number, char *key[]) |
| 4578 | return result; |
| 4579 | } |
| 4580 | |
| 4581 | +#if __OPTION_EGLIBC_INET |
| 4582 | /* This is for hosts */ |
| 4583 | static void |
| 4584 | print_hosts (struct hostent *host) |
| 4585 | @@ -598,6 +604,7 @@ networks_keys (int number, char *key[]) |
| 4586 | |
| 4587 | return result; |
| 4588 | } |
| 4589 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4590 | |
| 4591 | /* Now is all for passwd */ |
| 4592 | static void |
| 4593 | @@ -650,6 +657,7 @@ passwd_keys (int number, char *key[]) |
| 4594 | return result; |
| 4595 | } |
| 4596 | |
| 4597 | +#if __OPTION_EGLIBC_INET |
| 4598 | /* This is for protocols */ |
| 4599 | static void |
| 4600 | print_protocols (struct protoent *proto) |
| 4601 | @@ -807,6 +815,7 @@ services_keys (int number, char *key[]) |
| 4602 | |
| 4603 | return result; |
| 4604 | } |
| 4605 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4606 | |
| 4607 | /* This is for shadow */ |
| 4608 | static void |
| 4609 | @@ -873,23 +882,36 @@ struct |
| 4610 | } databases[] = |
| 4611 | { |
| 4612 | #define D(name) { #name, name ## _keys }, |
| 4613 | -D(ahosts) |
| 4614 | -D(ahostsv4) |
| 4615 | -D(ahostsv6) |
| 4616 | -D(aliases) |
| 4617 | -D(ethers) |
| 4618 | + |
| 4619 | +#if __OPTION_EGLIBC_INET |
| 4620 | +# define DN(name) D(name) |
| 4621 | +#else |
| 4622 | +# define DN(name) |
| 4623 | +#endif |
| 4624 | + |
| 4625 | +#if __OPTION_EGLIBC_DB_ALIASES |
| 4626 | +# define DA(name) D(name) |
| 4627 | +#else |
| 4628 | +# define DA(name) |
| 4629 | +#endif |
| 4630 | + |
| 4631 | +DN(ahosts) |
| 4632 | +DN(ahostsv4) |
| 4633 | +DN(ahostsv6) |
| 4634 | +DA(aliases) |
| 4635 | +DN(ethers) |
| 4636 | D(group) |
| 4637 | D(gshadow) |
| 4638 | -D(hosts) |
| 4639 | -D(initgroups) |
| 4640 | -D(netgroup) |
| 4641 | -D(networks) |
| 4642 | +DN(hosts) |
| 4643 | +DN(initgroups) |
| 4644 | +DN(netgroup) |
| 4645 | +DN(networks) |
| 4646 | D(passwd) |
| 4647 | -D(protocols) |
| 4648 | +DN(protocols) |
| 4649 | #if HAVE_SUNRPC |
| 4650 | -D(rpc) |
| 4651 | +DN(rpc) |
| 4652 | #endif |
| 4653 | -D(services) |
| 4654 | +DN(services) |
| 4655 | D(shadow) |
| 4656 | #undef D |
| 4657 | { NULL, NULL } |
| 4658 | diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c |
| 4659 | index f5b9036..f09f7fe 100644 |
| 4660 | --- a/nss/getnssent_r.c |
| 4661 | +++ b/nss/getnssent_r.c |
| 4662 | @@ -16,6 +16,7 @@ |
| 4663 | <http://www.gnu.org/licenses/>. */ |
| 4664 | |
| 4665 | #include <errno.h> |
| 4666 | +#include <gnu/option-groups.h> |
| 4667 | #include <netdb.h> |
| 4668 | #include "nsswitch.h" |
| 4669 | |
| 4670 | @@ -59,11 +60,13 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct, |
| 4671 | } fct; |
| 4672 | int no_more; |
| 4673 | |
| 4674 | +#if __OPTION_EGLIBC_INET |
| 4675 | if (res && __res_maybe_init (&_res, 0) == -1) |
| 4676 | { |
| 4677 | __set_h_errno (NETDB_INTERNAL); |
| 4678 | return; |
| 4679 | } |
| 4680 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4681 | |
| 4682 | /* Cycle through the services and run their `setXXent' functions until |
| 4683 | we find an available service. */ |
| 4684 | @@ -101,11 +104,13 @@ __nss_endent (const char *func_name, db_lookup_function lookup_fct, |
| 4685 | } fct; |
| 4686 | int no_more; |
| 4687 | |
| 4688 | +#if __OPTION_EGLIBC_INET |
| 4689 | if (res && __res_maybe_init (&_res, 0) == -1) |
| 4690 | { |
| 4691 | __set_h_errno (NETDB_INTERNAL); |
| 4692 | return; |
| 4693 | } |
| 4694 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4695 | |
| 4696 | /* Cycle through all the services and run their endXXent functions. */ |
| 4697 | no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1); |
| 4698 | @@ -141,12 +146,14 @@ __nss_getent_r (const char *getent_func_name, |
| 4699 | int no_more; |
| 4700 | enum nss_status status; |
| 4701 | |
| 4702 | +#if __OPTION_EGLIBC_INET |
| 4703 | if (res && __res_maybe_init (&_res, 0) == -1) |
| 4704 | { |
| 4705 | *h_errnop = NETDB_INTERNAL; |
| 4706 | *result = NULL; |
| 4707 | return errno; |
| 4708 | } |
| 4709 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4710 | |
| 4711 | /* Initialize status to return if no more functions are found. */ |
| 4712 | status = NSS_STATUS_NOTFOUND; |
| 4713 | @@ -161,7 +168,7 @@ __nss_getent_r (const char *getent_func_name, |
| 4714 | int is_last_nip = *nip == *last_nip; |
| 4715 | |
| 4716 | status = DL_CALL_FCT (fct.f, |
| 4717 | - (resbuf, buffer, buflen, &errno, &h_errno)); |
| 4718 | + (resbuf, buffer, buflen, &errno, h_errnop)); |
| 4719 | |
| 4720 | /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the |
| 4721 | provided buffer is too small. In this case we should give |
| 4722 | diff --git a/nss/nsswitch.c b/nss/nsswitch.c |
| 4723 | index 9712623..c81e207 100644 |
| 4724 | --- a/nss/nsswitch.c |
| 4725 | +++ b/nss/nsswitch.c |
| 4726 | @@ -26,6 +26,7 @@ |
| 4727 | #include <stdio_ext.h> |
| 4728 | #include <stdlib.h> |
| 4729 | #include <string.h> |
| 4730 | +#include <gnu/option-groups.h> |
| 4731 | |
| 4732 | #include <aliases.h> |
| 4733 | #include <grp.h> |
| 4734 | @@ -41,6 +42,15 @@ |
| 4735 | #include "../nscd/nscd_proto.h" |
| 4736 | #include <sysdep.h> |
| 4737 | |
| 4738 | +/* When OPTION_EGLIBC_NSSWITCH is disabled, we use fixed tables of |
| 4739 | + databases and services, generated at library build time. Thus: |
| 4740 | + - We can't reconfigure individual databases, so we don't need a |
| 4741 | + name-to-database map. |
| 4742 | + - We never add databases or service libraries, or look up functions |
| 4743 | + at runtime, so there's no need for a lock to protect our tables. |
| 4744 | + See ../option-groups.def for the details. */ |
| 4745 | +#if __OPTION_EGLIBC_NSSWITCH |
| 4746 | + |
| 4747 | /* Prototypes for the local functions. */ |
| 4748 | static name_database *nss_parse_file (const char *fname) internal_function; |
| 4749 | static name_database_entry *nss_getline (char *line) internal_function; |
| 4750 | @@ -79,6 +89,9 @@ bool __nss_database_custom[NSS_DBSIDX_max]; |
| 4751 | |
| 4752 | __libc_lock_define_initialized (static, lock) |
| 4753 | |
| 4754 | +#define lock_nsswitch __libc_lock_lock (lock) |
| 4755 | +#define unlock_nsswitch __libc_lock_unlock (lock) |
| 4756 | + |
| 4757 | #if !defined DO_STATIC_NSS || defined SHARED |
| 4758 | /* String with revision number of the shared object files. */ |
| 4759 | static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15; |
| 4760 | @@ -93,6 +106,20 @@ static name_database *service_table; |
| 4761 | __libc_freeres. */ |
| 4762 | static name_database_entry *defconfig_entries; |
| 4763 | |
| 4764 | +#else /* __OPTION_EGLIBC_NSSWITCH */ |
| 4765 | + |
| 4766 | +/* Bring in the statically initialized service table we generated at |
| 4767 | + build time. */ |
| 4768 | +#include "fixed-nsswitch.h" |
| 4769 | + |
| 4770 | +const static name_database *service_table = &fixed_name_database; |
| 4771 | + |
| 4772 | +/* Nothing ever changes, so there's no need to lock anything. */ |
| 4773 | +#define lock_nsswitch (0) |
| 4774 | +#define unlock_nsswitch (0) |
| 4775 | + |
| 4776 | +#endif /* __OPTION_EGLIBC_NSSWITCH */ |
| 4777 | + |
| 4778 | |
| 4779 | #ifdef USE_NSCD |
| 4780 | /* Nonzero if this is the nscd process. */ |
| 4781 | @@ -109,20 +136,22 @@ __nss_database_lookup (const char *database, const char *alternate_name, |
| 4782 | const char *defconfig, service_user **ni) |
| 4783 | { |
| 4784 | /* Prevent multiple threads to change the service table. */ |
| 4785 | - __libc_lock_lock (lock); |
| 4786 | + lock_nsswitch; |
| 4787 | |
| 4788 | /* Reconsider database variable in case some other thread called |
| 4789 | `__nss_configure_lookup' while we waited for the lock. */ |
| 4790 | if (*ni != NULL) |
| 4791 | { |
| 4792 | - __libc_lock_unlock (lock); |
| 4793 | + unlock_nsswitch; |
| 4794 | return 0; |
| 4795 | } |
| 4796 | |
| 4797 | +#if __OPTION_EGLIBC_NSSWITCH |
| 4798 | /* Are we initialized yet? */ |
| 4799 | if (service_table == NULL) |
| 4800 | /* Read config file. */ |
| 4801 | service_table = nss_parse_file (_PATH_NSSWITCH_CONF); |
| 4802 | +#endif |
| 4803 | |
| 4804 | /* Test whether configuration data is available. */ |
| 4805 | if (service_table != NULL) |
| 4806 | @@ -144,6 +173,7 @@ __nss_database_lookup (const char *database, const char *alternate_name, |
| 4807 | *ni = entry->service; |
| 4808 | } |
| 4809 | |
| 4810 | +#if __OPTION_EGLIBC_NSSWITCH |
| 4811 | /* No configuration data is available, either because nsswitch.conf |
| 4812 | doesn't exist or because it doesn't have a line for this database. |
| 4813 | |
| 4814 | @@ -166,13 +196,23 @@ __nss_database_lookup (const char *database, const char *alternate_name, |
| 4815 | { |
| 4816 | entry->next = defconfig_entries; |
| 4817 | entry->service = *ni; |
| 4818 | - entry->name[0] = '\0'; |
| 4819 | + entry->name = ""; |
| 4820 | defconfig_entries = entry; |
| 4821 | } |
| 4822 | } |
| 4823 | } |
| 4824 | +#else |
| 4825 | + /* Without the dynamic behavior, we can't process defconfig. The |
| 4826 | + databases the user specified at library build time are all you |
| 4827 | + get. */ |
| 4828 | + if (*ni == NULL) |
| 4829 | + { |
| 4830 | + unlock_nsswitch; |
| 4831 | + return -1; |
| 4832 | + } |
| 4833 | +#endif |
| 4834 | |
| 4835 | - __libc_lock_unlock (lock); |
| 4836 | + unlock_nsswitch; |
| 4837 | |
| 4838 | return *ni != NULL ? 0 : -1; |
| 4839 | } |
| 4840 | @@ -252,6 +292,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, |
| 4841 | libc_hidden_def (__nss_next2) |
| 4842 | |
| 4843 | |
| 4844 | +#if __OPTION_EGLIBC_NSSWITCH |
| 4845 | int |
| 4846 | attribute_compat_text_section |
| 4847 | __nss_next (service_user **ni, const char *fct_name, void **fctp, int status, |
| 4848 | @@ -300,13 +341,13 @@ __nss_configure_lookup (const char *dbname, const char *service_line) |
| 4849 | } |
| 4850 | |
| 4851 | /* Prevent multiple threads to change the service table. */ |
| 4852 | - __libc_lock_lock (lock); |
| 4853 | + lock_nsswitch; |
| 4854 | |
| 4855 | /* Install new rules. */ |
| 4856 | *databases[cnt].dbp = new_db; |
| 4857 | __nss_database_custom[cnt] = true; |
| 4858 | |
| 4859 | - __libc_lock_unlock (lock); |
| 4860 | + unlock_nsswitch; |
| 4861 | |
| 4862 | return 0; |
| 4863 | } |
| 4864 | @@ -402,7 +443,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name) |
| 4865 | void **found, *result; |
| 4866 | |
| 4867 | /* We now modify global data. Protect it. */ |
| 4868 | - __libc_lock_lock (lock); |
| 4869 | + lock_nsswitch; |
| 4870 | |
| 4871 | /* Search the tree of functions previously requested. Data in the |
| 4872 | tree are `known_function' structures, whose first member is a |
| 4873 | @@ -413,7 +454,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name) |
| 4874 | enough to a pointer to our structure to use as a lookup key that |
| 4875 | will be passed to `known_compare' (above). */ |
| 4876 | |
| 4877 | - found = __tsearch (&fct_name, &ni->known, &known_compare); |
| 4878 | + found = __tsearch (&fct_name, &ni->known.tree, &known_compare); |
| 4879 | if (found == NULL) |
| 4880 | /* This means out-of-memory. */ |
| 4881 | result = NULL; |
| 4882 | @@ -440,7 +481,7 @@ __nss_lookup_function (service_user *ni, const char *fct_name) |
| 4883 | #endif |
| 4884 | /* Oops. We can't instantiate this node properly. |
| 4885 | Remove it from the tree. */ |
| 4886 | - __tdelete (&fct_name, &ni->known, &known_compare); |
| 4887 | + __tdelete (&fct_name, &ni->known.tree, &known_compare); |
| 4888 | free (known); |
| 4889 | result = NULL; |
| 4890 | } |
| 4891 | @@ -520,13 +561,43 @@ __nss_lookup_function (service_user *ni, const char *fct_name) |
| 4892 | } |
| 4893 | |
| 4894 | /* Remove the lock. */ |
| 4895 | - __libc_lock_unlock (lock); |
| 4896 | + unlock_nsswitch; |
| 4897 | |
| 4898 | return result; |
| 4899 | } |
| 4900 | libc_hidden_def (__nss_lookup_function) |
| 4901 | |
| 4902 | |
| 4903 | +#else /* below if ! __OPTION_EGLIBC_NSSWITCH */ |
| 4904 | + |
| 4905 | + |
| 4906 | +int |
| 4907 | +__nss_configure_lookup (const char *dbname, const char *service_line) |
| 4908 | +{ |
| 4909 | + /* We can't dynamically configure lookup without |
| 4910 | + OPTION_EGLIBC_NSSWITCH. */ |
| 4911 | + __set_errno (EINVAL); |
| 4912 | + return -1; |
| 4913 | +} |
| 4914 | + |
| 4915 | + |
| 4916 | +void * |
| 4917 | +__nss_lookup_function (service_user *ni, const char *fct_name) |
| 4918 | +{ |
| 4919 | + int i; |
| 4920 | + const known_function **known = ni->known.array; |
| 4921 | + |
| 4922 | + for (i = 0; known[i]; i++) |
| 4923 | + if (strcmp (fct_name, known[i]->fct_name) == 0) |
| 4924 | + return known[i]->fct_ptr; |
| 4925 | + |
| 4926 | + return NULL; |
| 4927 | +} |
| 4928 | +libc_hidden_def (__nss_lookup_function) |
| 4929 | +#endif |
| 4930 | + |
| 4931 | + |
| 4932 | +#if __OPTION_EGLIBC_NSSWITCH |
| 4933 | static name_database * |
| 4934 | internal_function |
| 4935 | nss_parse_file (const char *fname) |
| 4936 | @@ -632,8 +703,10 @@ nss_parse_service_list (const char *line) |
| 4937 | + (line - name + 1)); |
| 4938 | if (new_service == NULL) |
| 4939 | return result; |
| 4940 | + new_service->name = (char *) (new_service + 1); |
| 4941 | |
| 4942 | - *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; |
| 4943 | + *((char *) __mempcpy ((char *) new_service->name, name, line - name)) |
| 4944 | + = '\0'; |
| 4945 | |
| 4946 | /* Set default actions. */ |
| 4947 | new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; |
| 4948 | @@ -642,7 +715,7 @@ nss_parse_service_list (const char *line) |
| 4949 | new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; |
| 4950 | new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; |
| 4951 | new_service->library = NULL; |
| 4952 | - new_service->known = NULL; |
| 4953 | + new_service->known.tree = NULL; |
| 4954 | new_service->next = NULL; |
| 4955 | |
| 4956 | while (isspace (line[0])) |
| 4957 | @@ -778,9 +851,10 @@ nss_getline (char *line) |
| 4958 | result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); |
| 4959 | if (result == NULL) |
| 4960 | return NULL; |
| 4961 | + result->name = (char *) (result + 1); |
| 4962 | |
| 4963 | /* Save the database name. */ |
| 4964 | - memcpy (result->name, name, len); |
| 4965 | + memcpy ((char *) result->name, name, len); |
| 4966 | |
| 4967 | /* Parse the list of services. */ |
| 4968 | result->service = nss_parse_service_list (line); |
| 4969 | @@ -816,6 +890,7 @@ nss_new_service (name_database *database, const char *name) |
| 4970 | return *currentp; |
| 4971 | } |
| 4972 | #endif |
| 4973 | +#endif /* __OPTION_EGLIBC_NSSWITCH */ |
| 4974 | |
| 4975 | |
| 4976 | #if defined SHARED && defined USE_NSCD |
| 4977 | @@ -834,6 +909,7 @@ nss_load_all_libraries (const char *service, const char *def) |
| 4978 | } |
| 4979 | |
| 4980 | |
| 4981 | +#if __OPTION_EGLIBC_INET |
| 4982 | /* Called by nscd and nscd alone. */ |
| 4983 | void |
| 4984 | __nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) |
| 4985 | @@ -857,8 +933,10 @@ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) |
| 4986 | __nss_not_use_nscd_services = -1; |
| 4987 | __nss_not_use_nscd_netgroup = -1; |
| 4988 | } |
| 4989 | +#endif /* __OPTION_EGLIBC_INET */ |
| 4990 | #endif |
| 4991 | |
| 4992 | +#if __OPTION_EGLIBC_NSSWITCH |
| 4993 | static void |
| 4994 | free_database_entries (name_database_entry *entry) |
| 4995 | { |
| 4996 | @@ -871,8 +949,8 @@ free_database_entries (name_database_entry *entry) |
| 4997 | { |
| 4998 | service_user *olds = service; |
| 4999 | |
| 5000 | - if (service->known != NULL) |
| 5001 | - __tdestroy (service->known, free); |
| 5002 | + if (service->known.tree != NULL) |
| 5003 | + __tdestroy (service->known.tree, free); |
| 5004 | |
| 5005 | service = service->next; |
| 5006 | free (olds); |
| 5007 | @@ -926,3 +1004,4 @@ libc_freeres_fn (free_mem) |
| 5008 | |
| 5009 | free (top); |
| 5010 | } |
| 5011 | +#endif /* __OPTION_EGLIBC_NSSWITCH */ |
| 5012 | diff --git a/nss/nsswitch.h b/nss/nsswitch.h |
| 5013 | index a5318fa..1730977 100644 |
| 5014 | --- a/nss/nsswitch.h |
| 5015 | +++ b/nss/nsswitch.h |
| 5016 | @@ -65,10 +65,20 @@ typedef struct service_user |
| 5017 | lookup_actions actions[5]; |
| 5018 | /* Link to the underlying library object. */ |
| 5019 | service_library *library; |
| 5020 | - /* Collection of known functions. */ |
| 5021 | - void *known; |
| 5022 | + /* Collection of known functions. |
| 5023 | + |
| 5024 | + With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a |
| 5025 | + 'tsearch'-style tree. |
| 5026 | + |
| 5027 | + With OPTION_EGLIBC_NSSWITCH disabled, this is an array of |
| 5028 | + pointers to known_function structures, NULL-terminated. */ |
| 5029 | + union |
| 5030 | + { |
| 5031 | + void *tree; |
| 5032 | + const known_function **array; |
| 5033 | + } known; |
| 5034 | /* Name of the service (`files', `dns', `nis', ...). */ |
| 5035 | - char name[0]; |
| 5036 | + const char *name; |
| 5037 | } service_user; |
| 5038 | |
| 5039 | /* To access the action based on the status value use this macro. */ |
| 5040 | @@ -82,7 +92,7 @@ typedef struct name_database_entry |
| 5041 | /* List of service to be used. */ |
| 5042 | service_user *service; |
| 5043 | /* Name of the database. */ |
| 5044 | - char name[0]; |
| 5045 | + const char *name; |
| 5046 | } name_database_entry; |
| 5047 | |
| 5048 | |
| 5049 | diff --git a/posix/Makefile b/posix/Makefile |
| 5050 | index 15e8818..609ed03 100644 |
| 5051 | --- a/posix/Makefile |
| 5052 | +++ b/posix/Makefile |
| 5053 | @@ -18,6 +18,8 @@ |
| 5054 | # |
| 5055 | # Sub-makefile for POSIX portion of the library. |
| 5056 | # |
| 5057 | +include ../option-groups.mak |
| 5058 | + |
| 5059 | subdir := posix |
| 5060 | |
| 5061 | include ../Makeconfig |
| 5062 | @@ -43,13 +45,24 @@ routines := \ |
| 5063 | getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \ |
| 5064 | getresuid getresgid setresuid setresgid \ |
| 5065 | pathconf sysconf fpathconf \ |
| 5066 | - glob glob64 fnmatch regex \ |
| 5067 | + glob glob64 fnmatch \ |
| 5068 | confstr \ |
| 5069 | getopt getopt1 getopt_init \ |
| 5070 | sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \ |
| 5071 | sched_primin sched_rr_gi sched_getaffinity sched_setaffinity \ |
| 5072 | - getaddrinfo gai_strerror wordexp \ |
| 5073 | pread pwrite pread64 pwrite64 \ |
| 5074 | + posix_madvise \ |
| 5075 | + get_child_max sched_cpucount sched_cpualloc sched_cpufree |
| 5076 | + |
| 5077 | +routines-$(OPTION_EGLIBC_INET) += getaddrinfo gai_strerror |
| 5078 | + |
| 5079 | +ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC)) |
| 5080 | +routines-$(OPTION_POSIX_REGEXP) += regex |
| 5081 | +else |
| 5082 | +routines-$(OPTION_POSIX_REGEXP) += xregex |
| 5083 | +endif |
| 5084 | + |
| 5085 | +routines-$(OPTION_EGLIBC_SPAWN) += \ |
| 5086 | spawn_faction_init spawn_faction_destroy spawn_faction_addclose \ |
| 5087 | spawn_faction_addopen spawn_faction_adddup2 \ |
| 5088 | spawnattr_init spawnattr_destroy \ |
| 5089 | @@ -61,37 +74,54 @@ routines := \ |
| 5090 | posix_madvise \ |
| 5091 | get_child_max sched_cpucount sched_cpualloc sched_cpufree |
| 5092 | |
| 5093 | +routines-$(OPTION_EGLIBC_WORDEXP) += wordexp |
| 5094 | + |
| 5095 | aux := init-posix environ |
| 5096 | -tests := tstgetopt testfnm runtests runptests \ |
| 5097 | +tests := tstgetopt testfnm runtests \ |
| 5098 | tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \ |
| 5099 | - tst-mmap tst-getaddrinfo tst-truncate \ |
| 5100 | - tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \ |
| 5101 | - tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \ |
| 5102 | - tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \ |
| 5103 | - bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \ |
| 5104 | - bug-regex13 bug-regex14 bug-regex15 bug-regex16 \ |
| 5105 | - bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ |
| 5106 | - bug-regex21 bug-regex22 bug-regex23 bug-regex24 \ |
| 5107 | - bug-regex25 bug-regex26 bug-regex27 bug-regex28 \ |
| 5108 | + tst-mmap tst-truncate \ |
| 5109 | + tst-truncate64 tst-fork tst-dir \ |
| 5110 | + tst-chmod bug-regex2 bug-regex3 bug-regex4 \ |
| 5111 | + tst-gnuglob bug-regex6 bug-regex7 \ |
| 5112 | + bug-regex8 bug-regex9 bug-regex10 bug-regex12 \ |
| 5113 | + bug-regex14 bug-regex15 \ |
| 5114 | + bug-regex21 bug-regex24 \ |
| 5115 | + bug-regex27 bug-regex28 \ |
| 5116 | bug-regex29 bug-regex30 bug-regex31 bug-regex32 \ |
| 5117 | - bug-regex33 tst-nice tst-nanosleep tst-regex2 \ |
| 5118 | - transbug tst-rxspencer tst-pcre tst-boost \ |
| 5119 | - bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \ |
| 5120 | - tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \ |
| 5121 | + tst-nice tst-nanosleep \ |
| 5122 | + transbug \ |
| 5123 | + tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \ |
| 5124 | + bug-glob1 bug-glob2 bug-glob3 tst-sysconf \ |
| 5125 | tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \ |
| 5126 | tst-execv1 tst-execv2 tst-execl1 tst-execl2 \ |
| 5127 | tst-execve1 tst-execve2 tst-execle1 tst-execle2 \ |
| 5128 | - tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \ |
| 5129 | - tst-rfc3484-3 \ |
| 5130 | - tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \ |
| 5131 | + tst-execvp3 tst-execvp4 \ |
| 5132 | + tst-fnmatch2 tst-cpucount tst-cpuset \ |
| 5133 | bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ |
| 5134 | bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ |
| 5135 | tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ |
| 5136 | tst-fnmatch3 bug-regex36 tst-getaddrinfo5 |
| 5137 | -xtests := bug-ga2 |
| 5138 | + |
| 5139 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 5140 | + += tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \ |
| 5141 | + bug-regex23 bug-regex25 bug-regex32 bug-regex33 |
| 5142 | +tests-$(OPTION_EGLIBC_INET) \ |
| 5143 | + += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \ |
| 5144 | + tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 tst-getaddrinfo3 |
| 5145 | +tests-$(OPTION_POSIX_REGEXP_GLIBC) \ |
| 5146 | + += runptests bug-regex11 bug-regex13 bug-regex16 \ |
| 5147 | + tst-regex2 tst-rxspencer tst-pcre tst-boost |
| 5148 | +ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP_GLIBC)) |
| 5149 | +tests += tst-regex bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ |
| 5150 | + bug-regex22 bug-regex26 |
| 5151 | +endif |
| 5152 | +xtests-$(OPTION_EGLIBC_INET) += bug-ga2 |
| 5153 | + |
| 5154 | ifeq (yes,$(build-shared)) |
| 5155 | test-srcs := globtest |
| 5156 | -tests += wordexp-test tst-exec tst-spawn |
| 5157 | +tests += tst-exec |
| 5158 | +tests-$(OPTION_EGLIBC_SPAWN) += tst-spawn |
| 5159 | +tests-$(OPTION_EGLIBC_WORDEXP) += wordexp-test |
| 5160 | endif |
| 5161 | tests-static = tst-exec-static tst-spawn-static |
| 5162 | tests += $(tests-static) |
| 5163 | @@ -117,7 +147,10 @@ generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \ |
| 5164 | |
| 5165 | ifeq ($(run-built-tests),yes) |
| 5166 | ifeq (yes,$(build-shared)) |
| 5167 | -tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out |
| 5168 | +tests-special += $(objpfx)globtest.out |
| 5169 | +ifeq (y,$(OPTION_EGLIBC_WORDEXP)) |
| 5170 | +tests-special += $(objpfx)wordexp-tst.out |
| 5171 | +endif |
| 5172 | endif |
| 5173 | endif |
| 5174 | |
| 5175 | @@ -125,12 +158,16 @@ endif |
| 5176 | # XXX Please note that for now we ignore the result of this test. |
| 5177 | tests-special += $(objpfx)annexc.out |
| 5178 | ifeq ($(run-built-tests),yes) |
| 5179 | -tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \ |
| 5180 | +tests-special += $(objpfx)bug-regex2-mem.out \ |
| 5181 | $(objpfx)bug-regex21-mem.out $(objpfx)bug-regex31-mem.out \ |
| 5182 | - $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \ |
| 5183 | - $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \ |
| 5184 | + $(objpfx)tst-getconf.out \ |
| 5185 | $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \ |
| 5186 | $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out |
| 5187 | +ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC)) |
| 5188 | +tests-special += $(objpfx)bug-regex14-mem.out $(objpfx)tst-rxspencer-no-utf8-mem.out \ |
| 5189 | + $(objpfx)tst-pcre-mem.out $(objpfx)tst-boost-mem.out |
| 5190 | +endif |
| 5191 | + |
| 5192 | xtests-special += $(objpfx)bug-ga2-mem.out |
| 5193 | endif |
| 5194 | |
| 5195 | @@ -143,6 +180,8 @@ $(objpfx)globtest.out: globtest.sh $(objpfx)globtest |
| 5196 | $(SHELL) $< $(common-objpfx) '$(test-via-rtld-prefix)' \ |
| 5197 | '$(test-program-prefix)' '$(test-wrapper-env)'; \ |
| 5198 | $(evaluate-test) |
| 5199 | +LDLIBS-globtest += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs) |
| 5200 | + |
| 5201 | $(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test |
| 5202 | $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \ |
| 5203 | '$(run-program-env)' '$(test-program-prefix-after-env)'; \ |
| 5204 | @@ -205,7 +244,10 @@ tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); |
| 5205 | tst-chmod-ARGS = $(objdir) |
| 5206 | tst-vfork3-ARGS = --test-dir=$(objpfx) |
| 5207 | |
| 5208 | -tst-rxspencer-ARGS = --utf8 rxspencer/tests |
| 5209 | +tst-rxspencer-ARGS = rxspencer/tests |
| 5210 | +ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) |
| 5211 | +tst-rxspencer-ARGS += --utf8 |
| 5212 | +endif |
| 5213 | tst-rxspencer-no-utf8-ARGS = rxspencer/tests |
| 5214 | tst-pcre-ARGS = PCRE.tests |
| 5215 | tst-boost-ARGS = BOOST.tests |
| 5216 | diff --git a/posix/bug-regex1.c b/posix/bug-regex1.c |
| 5217 | index 38eb543..17cd1a0 100644 |
| 5218 | --- a/posix/bug-regex1.c |
| 5219 | +++ b/posix/bug-regex1.c |
| 5220 | @@ -4,6 +4,7 @@ |
| 5221 | #include <string.h> |
| 5222 | #include <regex.h> |
| 5223 | #include <wchar.h> |
| 5224 | +#include <gnu/option-groups.h> |
| 5225 | |
| 5226 | int |
| 5227 | main (void) |
| 5228 | @@ -17,7 +18,9 @@ main (void) |
| 5229 | memset (®ex, '\0', sizeof (regex)); |
| 5230 | |
| 5231 | setlocale (LC_ALL, "de_DE.ISO-8859-1"); |
| 5232 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 5233 | fwide (stdout, -1); |
| 5234 | +#endif |
| 5235 | |
| 5236 | re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_DEBUG); |
| 5237 | |
| 5238 | diff --git a/posix/bug-regex6.c b/posix/bug-regex6.c |
| 5239 | index efcc890..3b270c7 100644 |
| 5240 | --- a/posix/bug-regex6.c |
| 5241 | +++ b/posix/bug-regex6.c |
| 5242 | @@ -22,6 +22,7 @@ |
| 5243 | #include <string.h> |
| 5244 | #include <sys/types.h> |
| 5245 | #include <regex.h> |
| 5246 | +#include <gnu/option-groups.h> |
| 5247 | |
| 5248 | |
| 5249 | int |
| 5250 | @@ -30,7 +31,12 @@ main (int argc, char *argv[]) |
| 5251 | regex_t re; |
| 5252 | regmatch_t mat[10]; |
| 5253 | int i, j, ret = 0; |
| 5254 | - const char *locales[] = { "C", "de_DE.UTF-8" }; |
| 5255 | + const char *locales[] = { |
| 5256 | + "C", |
| 5257 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 5258 | + "de_DE.UTF-8" |
| 5259 | +#endif |
| 5260 | + }; |
| 5261 | const char *string = "http://www.regex.com/pattern/matching.html#intro"; |
| 5262 | regmatch_t expect[10] = { |
| 5263 | { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 }, |
| 5264 | diff --git a/posix/fnmatch.c b/posix/fnmatch.c |
| 5265 | index fd85efa..01cc9fe 100644 |
| 5266 | --- a/posix/fnmatch.c |
| 5267 | +++ b/posix/fnmatch.c |
| 5268 | @@ -30,6 +30,10 @@ |
| 5269 | #include <ctype.h> |
| 5270 | #include <string.h> |
| 5271 | |
| 5272 | +#if defined _LIBC |
| 5273 | +# include <gnu/option-groups.h> |
| 5274 | +#endif |
| 5275 | + |
| 5276 | #if defined STDC_HEADERS || defined _LIBC |
| 5277 | # include <stdlib.h> |
| 5278 | #endif |
| 5279 | @@ -131,7 +135,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); |
| 5280 | # define ISWCTYPE(WC, WT) iswctype (WC, WT) |
| 5281 | # endif |
| 5282 | |
| 5283 | -# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC |
| 5284 | +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS && _LIBC && __OPTION_EGLIBC_LOCALE_CODE) |
| 5285 | /* In this case we are implementing the multibyte character handling. */ |
| 5286 | # define HANDLE_MULTIBYTE 1 |
| 5287 | # endif |
| 5288 | diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c |
| 5289 | index f46c9df..74e1754 100644 |
| 5290 | --- a/posix/fnmatch_loop.c |
| 5291 | +++ b/posix/fnmatch_loop.c |
| 5292 | @@ -15,6 +15,8 @@ |
| 5293 | License along with the GNU C Library; if not, see |
| 5294 | <http://www.gnu.org/licenses/>. */ |
| 5295 | |
| 5296 | +#include <gnu/option-groups.h> |
| 5297 | + |
| 5298 | #include <stdint.h> |
| 5299 | |
| 5300 | struct STRUCT |
| 5301 | @@ -54,10 +56,15 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) |
| 5302 | const char *collseq = (const char *) |
| 5303 | _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); |
| 5304 | # else |
| 5305 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 5306 | const UCHAR *collseq = (const UCHAR *) |
| 5307 | _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); |
| 5308 | -# endif |
| 5309 | -#endif |
| 5310 | +# define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)]) |
| 5311 | +# else |
| 5312 | +# define COLLSEQ_BYTE_LOOKUP(ix) (ix) |
| 5313 | +# endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 5314 | +# endif /* WIDE_CHAR_VERSION */ |
| 5315 | +#endif /* _LIBC */ |
| 5316 | |
| 5317 | while ((c = *p++) != L('\0')) |
| 5318 | { |
| 5319 | @@ -277,7 +284,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) |
| 5320 | /* Leave room for the null. */ |
| 5321 | CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; |
| 5322 | size_t c1 = 0; |
| 5323 | -#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) |
| 5324 | +#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) |
| 5325 | wctype_t wt; |
| 5326 | #endif |
| 5327 | const CHAR *startp = p; |
| 5328 | @@ -307,7 +314,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) |
| 5329 | } |
| 5330 | str[c1] = L('\0'); |
| 5331 | |
| 5332 | -#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) |
| 5333 | +#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) |
| 5334 | wt = IS_CHAR_CLASS (str); |
| 5335 | if (wt == 0) |
| 5336 | /* Invalid character class name. */ |
| 5337 | @@ -680,8 +687,10 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) |
| 5338 | else |
| 5339 | lcollseq = __collseq_table_lookup (collseq, cold); |
| 5340 | # else |
| 5341 | - fcollseq = collseq[fn]; |
| 5342 | - lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; |
| 5343 | + fcollseq = COLLSEQ_BYTE_LOOKUP (fn); |
| 5344 | + lcollseq = (is_seqval |
| 5345 | + ? cold |
| 5346 | + : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold)); |
| 5347 | # endif |
| 5348 | |
| 5349 | is_seqval = 0; |
| 5350 | @@ -857,7 +866,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) |
| 5351 | goto matched; |
| 5352 | } |
| 5353 | # else |
| 5354 | - hcollseq = collseq[cend]; |
| 5355 | + hcollseq = COLLSEQ_BYTE_LOOKUP (cend); |
| 5356 | # endif |
| 5357 | } |
| 5358 | |
| 5359 | diff --git a/posix/glob.c b/posix/glob.c |
| 5360 | index d65e55d..1ac00a1 100644 |
| 5361 | --- a/posix/glob.c |
| 5362 | +++ b/posix/glob.c |
| 5363 | @@ -25,6 +25,9 @@ |
| 5364 | #include <sys/types.h> |
| 5365 | #include <sys/stat.h> |
| 5366 | #include <stddef.h> |
| 5367 | +#ifdef _LIBC |
| 5368 | +# include <gnu/option-groups.h> |
| 5369 | +#endif |
| 5370 | |
| 5371 | /* Outcomment the following line for production quality code. */ |
| 5372 | /* #define NDEBUG 1 */ |
| 5373 | @@ -607,6 +610,7 @@ glob (pattern, flags, errfunc, pglob) |
| 5374 | if (home_dir == NULL || home_dir[0] == '\0') |
| 5375 | home_dir = "c:/users/default"; /* poor default */ |
| 5376 | # else |
| 5377 | +# if ! _LIBC || __OPTION_EGLIBC_GETLOGIN |
| 5378 | if (home_dir == NULL || home_dir[0] == '\0') |
| 5379 | { |
| 5380 | int success; |
| 5381 | @@ -623,19 +627,19 @@ glob (pattern, flags, errfunc, pglob) |
| 5382 | if (success) |
| 5383 | { |
| 5384 | struct passwd *p; |
| 5385 | -# if defined HAVE_GETPWNAM_R || defined _LIBC |
| 5386 | +# if defined HAVE_GETPWNAM_R || defined _LIBC |
| 5387 | long int pwbuflen = GETPW_R_SIZE_MAX (); |
| 5388 | char *pwtmpbuf; |
| 5389 | struct passwd pwbuf; |
| 5390 | int malloc_pwtmpbuf = 0; |
| 5391 | int save = errno; |
| 5392 | |
| 5393 | -# ifndef _LIBC |
| 5394 | +# ifndef _LIBC |
| 5395 | if (pwbuflen == -1) |
| 5396 | /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. |
| 5397 | Try a moderate value. */ |
| 5398 | pwbuflen = 1024; |
| 5399 | -# endif |
| 5400 | +# endif |
| 5401 | if (__libc_use_alloca (alloca_used + pwbuflen)) |
| 5402 | pwtmpbuf = alloca_account (pwbuflen, alloca_used); |
| 5403 | else |
| 5404 | @@ -682,9 +686,9 @@ glob (pattern, flags, errfunc, pglob) |
| 5405 | } |
| 5406 | __set_errno (save); |
| 5407 | } |
| 5408 | -# else |
| 5409 | +# else |
| 5410 | p = getpwnam (name); |
| 5411 | -# endif |
| 5412 | +# endif |
| 5413 | if (p != NULL) |
| 5414 | { |
| 5415 | if (!malloc_pwtmpbuf) |
| 5416 | @@ -713,6 +717,7 @@ glob (pattern, flags, errfunc, pglob) |
| 5417 | } |
| 5418 | } |
| 5419 | } |
| 5420 | +# endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */ |
| 5421 | if (home_dir == NULL || home_dir[0] == '\0') |
| 5422 | { |
| 5423 | if (flags & GLOB_TILDE_CHECK) |
| 5424 | diff --git a/posix/regcomp.c b/posix/regcomp.c |
| 5425 | index bf8aa16..6a41251 100644 |
| 5426 | --- a/posix/regcomp.c |
| 5427 | +++ b/posix/regcomp.c |
| 5428 | @@ -18,6 +18,7 @@ |
| 5429 | <http://www.gnu.org/licenses/>. */ |
| 5430 | |
| 5431 | #include <stdint.h> |
| 5432 | +#include <gnu/option-groups.h> |
| 5433 | |
| 5434 | #ifdef _LIBC |
| 5435 | # include <locale/weight.h> |
| 5436 | @@ -309,7 +310,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, |
| 5437 | { |
| 5438 | re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; |
| 5439 | int node_cnt; |
| 5440 | - int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); |
| 5441 | + int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE)); |
| 5442 | for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) |
| 5443 | { |
| 5444 | int node = init_state->nodes.elems[node_cnt]; |
| 5445 | @@ -319,9 +320,9 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, |
| 5446 | { |
| 5447 | re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); |
| 5448 | #ifdef RE_ENABLE_I18N |
| 5449 | - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) |
| 5450 | + if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1) |
| 5451 | { |
| 5452 | - unsigned char *buf = alloca (dfa->mb_cur_max), *p; |
| 5453 | + unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p; |
| 5454 | wchar_t wc; |
| 5455 | mbstate_t state; |
| 5456 | |
| 5457 | @@ -352,7 +353,11 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, |
| 5458 | re_set_fastmap (fastmap, icase, ch); |
| 5459 | } |
| 5460 | } |
| 5461 | -#ifdef RE_ENABLE_I18N |
| 5462 | + |
| 5463 | + /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current |
| 5464 | + locale is always C, which has no rules and no multi-byte |
| 5465 | + characters. */ |
| 5466 | +#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE |
| 5467 | else if (type == COMPLEX_BRACKET) |
| 5468 | { |
| 5469 | re_charset_t *cset = dfa->nodes[node].opr.mbcset; |
| 5470 | @@ -380,7 +385,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, |
| 5471 | i.e. where we would not find an invalid sequence. This only |
| 5472 | applies to multibyte character sets; for single byte character |
| 5473 | sets, the SIMPLE_BRACKET again suffices. */ |
| 5474 | - if (dfa->mb_cur_max > 1 |
| 5475 | + if (dfa_mb_cur_max (dfa) > 1 |
| 5476 | && (cset->nchar_classes || cset->non_match || cset->nranges |
| 5477 | # ifdef _LIBC |
| 5478 | || cset->nequiv_classes |
| 5479 | @@ -408,7 +413,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, |
| 5480 | memset (&state, '\0', sizeof (state)); |
| 5481 | if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) |
| 5482 | re_set_fastmap (fastmap, icase, *(unsigned char *) buf); |
| 5483 | - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) |
| 5484 | + if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1) |
| 5485 | { |
| 5486 | if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state) |
| 5487 | != (size_t) -1) |
| 5488 | @@ -417,7 +422,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, |
| 5489 | } |
| 5490 | } |
| 5491 | } |
| 5492 | -#endif /* RE_ENABLE_I18N */ |
| 5493 | +#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ |
| 5494 | else if (type == OP_PERIOD |
| 5495 | #ifdef RE_ENABLE_I18N |
| 5496 | || type == OP_UTF8_PERIOD |
| 5497 | @@ -860,11 +865,15 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) |
| 5498 | |
| 5499 | dfa->mb_cur_max = MB_CUR_MAX; |
| 5500 | #ifdef _LIBC |
| 5501 | - if (dfa->mb_cur_max == 6 |
| 5502 | + if (dfa_mb_cur_max (dfa) == 6 |
| 5503 | && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) |
| 5504 | dfa->is_utf8 = 1; |
| 5505 | +# if __OPTION_EGLIBC_LOCALE_CODE |
| 5506 | dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) |
| 5507 | != 0); |
| 5508 | +# else |
| 5509 | + dfa->map_notascii = 0; |
| 5510 | +# endif |
| 5511 | #else |
| 5512 | # ifdef HAVE_LANGINFO_CODESET |
| 5513 | codeset_name = nl_langinfo (CODESET); |
| 5514 | @@ -890,7 +899,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) |
| 5515 | #endif |
| 5516 | |
| 5517 | #ifdef RE_ENABLE_I18N |
| 5518 | - if (dfa->mb_cur_max > 1) |
| 5519 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5520 | { |
| 5521 | if (dfa->is_utf8) |
| 5522 | dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; |
| 5523 | @@ -1788,7 +1797,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) |
| 5524 | token->word_char = 0; |
| 5525 | #ifdef RE_ENABLE_I18N |
| 5526 | token->mb_partial = 0; |
| 5527 | - if (input->mb_cur_max > 1 && |
| 5528 | + if (string_mb_cur_max (input) > 1 && |
| 5529 | !re_string_first_byte (input, re_string_cur_idx (input))) |
| 5530 | { |
| 5531 | token->type = CHARACTER; |
| 5532 | @@ -1809,7 +1818,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) |
| 5533 | token->opr.c = c2; |
| 5534 | token->type = CHARACTER; |
| 5535 | #ifdef RE_ENABLE_I18N |
| 5536 | - if (input->mb_cur_max > 1) |
| 5537 | + if (string_mb_cur_max (input) > 1) |
| 5538 | { |
| 5539 | wint_t wc = re_string_wchar_at (input, |
| 5540 | re_string_cur_idx (input) + 1); |
| 5541 | @@ -1923,7 +1932,7 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) |
| 5542 | |
| 5543 | token->type = CHARACTER; |
| 5544 | #ifdef RE_ENABLE_I18N |
| 5545 | - if (input->mb_cur_max > 1) |
| 5546 | + if (string_mb_cur_max (input) > 1) |
| 5547 | { |
| 5548 | wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); |
| 5549 | token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; |
| 5550 | @@ -2023,7 +2032,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) |
| 5551 | token->opr.c = c; |
| 5552 | |
| 5553 | #ifdef RE_ENABLE_I18N |
| 5554 | - if (input->mb_cur_max > 1 && |
| 5555 | + if (string_mb_cur_max (input) > 1 && |
| 5556 | !re_string_first_byte (input, re_string_cur_idx (input))) |
| 5557 | { |
| 5558 | token->type = CHARACTER; |
| 5559 | @@ -2246,7 +2255,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, |
| 5560 | return NULL; |
| 5561 | } |
| 5562 | #ifdef RE_ENABLE_I18N |
| 5563 | - if (dfa->mb_cur_max > 1) |
| 5564 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5565 | { |
| 5566 | while (!re_string_eoi (regexp) |
| 5567 | && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) |
| 5568 | @@ -2384,7 +2393,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, |
| 5569 | *err = REG_ESPACE; |
| 5570 | return NULL; |
| 5571 | } |
| 5572 | - if (dfa->mb_cur_max > 1) |
| 5573 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5574 | dfa->has_mb_node = 1; |
| 5575 | break; |
| 5576 | case OP_WORD: |
| 5577 | @@ -2690,7 +2699,7 @@ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, |
| 5578 | However, for !_LIBC we have no collation elements: if the |
| 5579 | character set is single byte, the single byte character set |
| 5580 | that we build below suffices. parse_bracket_exp passes |
| 5581 | - no MBCSET if dfa->mb_cur_max == 1. */ |
| 5582 | + no MBCSET if dfa_mb_cur_max (dfa) == 1. */ |
| 5583 | if (mbcset) |
| 5584 | { |
| 5585 | /* Check the space of the arrays. */ |
| 5586 | @@ -2786,7 +2795,13 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5587 | reg_syntax_t syntax, reg_errcode_t *err) |
| 5588 | { |
| 5589 | #ifdef _LIBC |
| 5590 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 5591 | const unsigned char *collseqmb; |
| 5592 | +# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)]) |
| 5593 | +#else |
| 5594 | +# define COLLSEQMB_LOOKUP(ix) (ix) |
| 5595 | +#endif |
| 5596 | + |
| 5597 | const char *collseqwc; |
| 5598 | uint32_t nrules; |
| 5599 | int32_t table_size; |
| 5600 | @@ -2834,18 +2849,20 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5601 | if (MB_CUR_MAX == 1) |
| 5602 | */ |
| 5603 | if (nrules == 0) |
| 5604 | - return collseqmb[br_elem->opr.ch]; |
| 5605 | + return COLLSEQMB_LOOKUP (br_elem->opr.ch); |
| 5606 | else |
| 5607 | { |
| 5608 | wint_t wc = __btowc (br_elem->opr.ch); |
| 5609 | return __collseq_table_lookup (collseqwc, wc); |
| 5610 | } |
| 5611 | } |
| 5612 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 5613 | else if (br_elem->type == MB_CHAR) |
| 5614 | { |
| 5615 | if (nrules != 0) |
| 5616 | return __collseq_table_lookup (collseqwc, br_elem->opr.wch); |
| 5617 | } |
| 5618 | +#endif |
| 5619 | else if (br_elem->type == COLL_SYM) |
| 5620 | { |
| 5621 | size_t sym_name_len = strlen ((char *) br_elem->opr.name); |
| 5622 | @@ -2876,11 +2893,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5623 | { |
| 5624 | /* No valid character. Match it as a single byte |
| 5625 | character. */ |
| 5626 | - return collseqmb[br_elem->opr.name[0]]; |
| 5627 | + return COLLSEQMB_LOOKUP (br_elem->opr.name[0]); |
| 5628 | } |
| 5629 | } |
| 5630 | else if (sym_name_len == 1) |
| 5631 | - return collseqmb[br_elem->opr.name[0]]; |
| 5632 | + return COLLSEQMB_LOOKUP (br_elem->opr.name[0]); |
| 5633 | } |
| 5634 | return UINT_MAX; |
| 5635 | } |
| 5636 | @@ -2920,7 +2937,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5637 | However, if we have no collation elements, and the character set |
| 5638 | is single byte, the single byte character set that we |
| 5639 | build below suffices. */ |
| 5640 | - if (nrules > 0 || dfa->mb_cur_max > 1) |
| 5641 | + if (nrules > 0 || dfa_mb_cur_max (dfa) > 1) |
| 5642 | { |
| 5643 | /* Check the space of the arrays. */ |
| 5644 | if (BE (*range_alloc == mbcset->nranges, 0)) |
| 5645 | @@ -2957,7 +2974,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5646 | if (MB_CUR_MAX == 1) |
| 5647 | */ |
| 5648 | if (nrules == 0) |
| 5649 | - ch_collseq = collseqmb[ch]; |
| 5650 | + ch_collseq = COLLSEQMB_LOOKUP (ch); |
| 5651 | else |
| 5652 | ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); |
| 5653 | if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) |
| 5654 | @@ -3035,7 +3052,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5655 | re_bitset_ptr_t sbcset; |
| 5656 | #ifdef RE_ENABLE_I18N |
| 5657 | re_charset_t *mbcset; |
| 5658 | - int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; |
| 5659 | + int coll_sym_alloc = 0, range_alloc = 0; |
| 5660 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 5661 | + int mbchar_alloc = 0; |
| 5662 | +#endif |
| 5663 | int equiv_class_alloc = 0, char_class_alloc = 0; |
| 5664 | #endif /* not RE_ENABLE_I18N */ |
| 5665 | int non_match = 0; |
| 5666 | @@ -3043,9 +3063,15 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5667 | int token_len; |
| 5668 | int first_round = 1; |
| 5669 | #ifdef _LIBC |
| 5670 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 5671 | collseqmb = (const unsigned char *) |
| 5672 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); |
| 5673 | nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 5674 | +#else |
| 5675 | + /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the |
| 5676 | + compiler can't figure that out. */ |
| 5677 | + nrules = 0; |
| 5678 | +#endif |
| 5679 | if (nrules) |
| 5680 | { |
| 5681 | /* |
| 5682 | @@ -3175,7 +3201,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5683 | #else |
| 5684 | # ifdef RE_ENABLE_I18N |
| 5685 | *err = build_range_exp (sbcset, |
| 5686 | - dfa->mb_cur_max > 1 ? mbcset : NULL, |
| 5687 | + dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL, |
| 5688 | &range_alloc, &start_elem, &end_elem); |
| 5689 | # else |
| 5690 | *err = build_range_exp (sbcset, &start_elem, &end_elem); |
| 5691 | @@ -3191,7 +3217,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5692 | case SB_CHAR: |
| 5693 | bitset_set (sbcset, start_elem.opr.ch); |
| 5694 | break; |
| 5695 | -#ifdef RE_ENABLE_I18N |
| 5696 | +#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE |
| 5697 | case MB_CHAR: |
| 5698 | /* Check whether the array has enough space. */ |
| 5699 | if (BE (mbchar_alloc == mbcset->nmbchars, 0)) |
| 5700 | @@ -3209,7 +3235,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5701 | } |
| 5702 | mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; |
| 5703 | break; |
| 5704 | -#endif /* RE_ENABLE_I18N */ |
| 5705 | +#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ |
| 5706 | case EQUIV_CLASS: |
| 5707 | *err = build_equiv_class (sbcset, |
| 5708 | #ifdef RE_ENABLE_I18N |
| 5709 | @@ -3259,11 +3285,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, |
| 5710 | |
| 5711 | #ifdef RE_ENABLE_I18N |
| 5712 | /* Ensure only single byte characters are set. */ |
| 5713 | - if (dfa->mb_cur_max > 1) |
| 5714 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5715 | bitset_mask (sbcset, dfa->sb_char); |
| 5716 | |
| 5717 | if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes |
| 5718 | - || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes |
| 5719 | + || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes |
| 5720 | || mbcset->non_match))) |
| 5721 | { |
| 5722 | bin_tree_t *mbc_tree; |
| 5723 | @@ -3332,7 +3358,7 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, |
| 5724 | re_token_t *token, int token_len, re_dfa_t *dfa, |
| 5725 | reg_syntax_t syntax, int accept_hyphen) |
| 5726 | { |
| 5727 | -#ifdef RE_ENABLE_I18N |
| 5728 | +#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE |
| 5729 | int cur_char_size; |
| 5730 | cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); |
| 5731 | if (cur_char_size > 1) |
| 5732 | @@ -3342,7 +3368,7 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, |
| 5733 | re_string_skip_bytes (regexp, cur_char_size); |
| 5734 | return REG_NOERROR; |
| 5735 | } |
| 5736 | -#endif /* RE_ENABLE_I18N */ |
| 5737 | +#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ |
| 5738 | re_string_skip_bytes (regexp, token_len); /* Skip a token. */ |
| 5739 | if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS |
| 5740 | || token->type == OP_OPEN_EQUIV_CLASS) |
| 5741 | @@ -3422,7 +3448,9 @@ build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, |
| 5742 | build_equiv_class (bitset_t sbcset, const unsigned char *name) |
| 5743 | #endif /* not RE_ENABLE_I18N */ |
| 5744 | { |
| 5745 | -#ifdef _LIBC |
| 5746 | + /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale |
| 5747 | + is supported; it has no collation rules. */ |
| 5748 | +#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE |
| 5749 | uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 5750 | if (nrules != 0) |
| 5751 | { |
| 5752 | @@ -3492,7 +3520,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) |
| 5753 | mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; |
| 5754 | } |
| 5755 | else |
| 5756 | -#endif /* _LIBC */ |
| 5757 | +#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ |
| 5758 | { |
| 5759 | if (BE (strlen ((const char *) name) != 1, 0)) |
| 5760 | return REG_ECOLLATE; |
| 5761 | @@ -3526,7 +3554,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, |
| 5762 | && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) |
| 5763 | name = "alpha"; |
| 5764 | |
| 5765 | -#ifdef RE_ENABLE_I18N |
| 5766 | +#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE |
| 5767 | /* Check the space of the arrays. */ |
| 5768 | if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) |
| 5769 | { |
| 5770 | @@ -3542,7 +3570,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, |
| 5771 | *char_class_alloc = new_char_class_alloc; |
| 5772 | } |
| 5773 | mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); |
| 5774 | -#endif /* RE_ENABLE_I18N */ |
| 5775 | +#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */ |
| 5776 | |
| 5777 | #define BUILD_CHARCLASS_LOOP(ctype_func) \ |
| 5778 | do { \ |
| 5779 | @@ -3653,7 +3681,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, |
| 5780 | |
| 5781 | #ifdef RE_ENABLE_I18N |
| 5782 | /* Ensure only single byte characters are set. */ |
| 5783 | - if (dfa->mb_cur_max > 1) |
| 5784 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5785 | bitset_mask (sbcset, dfa->sb_char); |
| 5786 | #endif |
| 5787 | |
| 5788 | @@ -3665,7 +3693,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, |
| 5789 | goto build_word_op_espace; |
| 5790 | |
| 5791 | #ifdef RE_ENABLE_I18N |
| 5792 | - if (dfa->mb_cur_max > 1) |
| 5793 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5794 | { |
| 5795 | bin_tree_t *mbc_tree; |
| 5796 | /* Build a tree for complex bracket. */ |
| 5797 | diff --git a/posix/regex.h b/posix/regex.h |
| 5798 | index 5b1981e..2941f94 100644 |
| 5799 | --- a/posix/regex.h |
| 5800 | +++ b/posix/regex.h |
| 5801 | @@ -21,6 +21,7 @@ |
| 5802 | #define _REGEX_H 1 |
| 5803 | |
| 5804 | #include <sys/types.h> |
| 5805 | +#include <gnu/option-groups.h> |
| 5806 | |
| 5807 | /* Allow the use in C++ code. */ |
| 5808 | #ifdef __cplusplus |
| 5809 | @@ -156,6 +157,8 @@ typedef unsigned long int reg_syntax_t; |
| 5810 | treated as 'a\{1'. */ |
| 5811 | # define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) |
| 5812 | |
| 5813 | +/* EGLIBC: Old regex implementation does not support these. */ |
| 5814 | +# if __OPTION_POSIX_REGEXP_GLIBC |
| 5815 | /* If this bit is set, then ignore case when matching. |
| 5816 | If not set, then case is significant. */ |
| 5817 | # define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) |
| 5818 | @@ -172,6 +175,7 @@ typedef unsigned long int reg_syntax_t; |
| 5819 | /* If this bit is set, then no_sub will be set to 1 during |
| 5820 | re_compile_pattern. */ |
| 5821 | # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) |
| 5822 | +# endif /* __OPTION_POSIX_REGEXP_GLIBC */ |
| 5823 | #endif |
| 5824 | |
| 5825 | /* This global variable defines the particular regexp syntax to use (for |
| 5826 | @@ -231,8 +235,13 @@ extern reg_syntax_t re_syntax_options; |
| 5827 | (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ |
| 5828 | | RE_INTERVALS | RE_NO_EMPTY_RANGES) |
| 5829 | |
| 5830 | +#if __OPTION_POSIX_REGEXP_GLIBC |
| 5831 | #define RE_SYNTAX_POSIX_BASIC \ |
| 5832 | (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) |
| 5833 | +#else |
| 5834 | +#define RE_SYNTAX_POSIX_BASIC \ |
| 5835 | + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) |
| 5836 | +#endif |
| 5837 | |
| 5838 | /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes |
| 5839 | RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this |
| 5840 | @@ -298,9 +307,11 @@ extern reg_syntax_t re_syntax_options; |
| 5841 | /* Like REG_NOTBOL, except for the end-of-line. */ |
| 5842 | #define REG_NOTEOL (1 << 1) |
| 5843 | |
| 5844 | +#if __OPTION_POSIX_REGEXP_GLIBC |
| 5845 | /* Use PMATCH[0] to delimit the start and end of the search in the |
| 5846 | buffer. */ |
| 5847 | #define REG_STARTEND (1 << 2) |
| 5848 | +#endif |
| 5849 | |
| 5850 | |
| 5851 | /* If any error codes are removed, changed, or added, update the |
| 5852 | diff --git a/posix/regex_internal.c b/posix/regex_internal.c |
| 5853 | index 8597d7e..d53b2a8 100644 |
| 5854 | --- a/posix/regex_internal.c |
| 5855 | +++ b/posix/regex_internal.c |
| 5856 | @@ -43,8 +43,8 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, |
| 5857 | int init_buf_len; |
| 5858 | |
| 5859 | /* Ensure at least one character fits into the buffers. */ |
| 5860 | - if (init_len < dfa->mb_cur_max) |
| 5861 | - init_len = dfa->mb_cur_max; |
| 5862 | + if (init_len < dfa_mb_cur_max (dfa)) |
| 5863 | + init_len = dfa_mb_cur_max (dfa); |
| 5864 | init_buf_len = (len + 1 < init_len) ? len + 1: init_len; |
| 5865 | re_string_construct_common (str, len, pstr, trans, icase, dfa); |
| 5866 | |
| 5867 | @@ -55,7 +55,7 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, |
| 5868 | pstr->word_char = dfa->word_char; |
| 5869 | pstr->word_ops_used = dfa->word_ops_used; |
| 5870 | pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; |
| 5871 | - pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; |
| 5872 | + pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len; |
| 5873 | pstr->valid_raw_len = pstr->valid_len; |
| 5874 | return REG_NOERROR; |
| 5875 | } |
| 5876 | @@ -82,7 +82,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len, |
| 5877 | if (icase) |
| 5878 | { |
| 5879 | #ifdef RE_ENABLE_I18N |
| 5880 | - if (dfa->mb_cur_max > 1) |
| 5881 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5882 | { |
| 5883 | while (1) |
| 5884 | { |
| 5885 | @@ -91,7 +91,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len, |
| 5886 | return ret; |
| 5887 | if (pstr->valid_raw_len >= len) |
| 5888 | break; |
| 5889 | - if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) |
| 5890 | + if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa)) |
| 5891 | break; |
| 5892 | ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); |
| 5893 | if (BE (ret != REG_NOERROR, 0)) |
| 5894 | @@ -105,7 +105,7 @@ re_string_construct (re_string_t *pstr, const char *str, int len, |
| 5895 | else |
| 5896 | { |
| 5897 | #ifdef RE_ENABLE_I18N |
| 5898 | - if (dfa->mb_cur_max > 1) |
| 5899 | + if (dfa_mb_cur_max (dfa) > 1) |
| 5900 | build_wcs_buffer (pstr); |
| 5901 | else |
| 5902 | #endif /* RE_ENABLE_I18N */ |
| 5903 | @@ -130,7 +130,7 @@ internal_function __attribute_warn_unused_result__ |
| 5904 | re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) |
| 5905 | { |
| 5906 | #ifdef RE_ENABLE_I18N |
| 5907 | - if (pstr->mb_cur_max > 1) |
| 5908 | + if (string_mb_cur_max (pstr) > 1) |
| 5909 | { |
| 5910 | wint_t *new_wcs; |
| 5911 | |
| 5912 | @@ -177,7 +177,7 @@ re_string_construct_common (const char *str, int len, re_string_t *pstr, |
| 5913 | pstr->trans = trans; |
| 5914 | pstr->icase = icase ? 1 : 0; |
| 5915 | pstr->mbs_allocated = (trans != NULL || icase); |
| 5916 | - pstr->mb_cur_max = dfa->mb_cur_max; |
| 5917 | + pstr->mb_cur_max = dfa_mb_cur_max (dfa); |
| 5918 | pstr->is_utf8 = dfa->is_utf8; |
| 5919 | pstr->map_notascii = dfa->map_notascii; |
| 5920 | pstr->stop = pstr->len; |
| 5921 | @@ -203,7 +203,7 @@ build_wcs_buffer (re_string_t *pstr) |
| 5922 | { |
| 5923 | #ifdef _LIBC |
| 5924 | unsigned char buf[MB_LEN_MAX]; |
| 5925 | - assert (MB_LEN_MAX >= pstr->mb_cur_max); |
| 5926 | + assert (MB_LEN_MAX >= string_mb_cur_max (pstr)); |
| 5927 | #else |
| 5928 | unsigned char buf[64]; |
| 5929 | #endif |
| 5930 | @@ -226,7 +226,7 @@ build_wcs_buffer (re_string_t *pstr) |
| 5931 | { |
| 5932 | int i, ch; |
| 5933 | |
| 5934 | - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) |
| 5935 | + for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i) |
| 5936 | { |
| 5937 | ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; |
| 5938 | buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; |
| 5939 | @@ -275,7 +275,7 @@ build_wcs_upper_buffer (re_string_t *pstr) |
| 5940 | size_t mbclen; |
| 5941 | #ifdef _LIBC |
| 5942 | char buf[MB_LEN_MAX]; |
| 5943 | - assert (MB_LEN_MAX >= pstr->mb_cur_max); |
| 5944 | + assert (MB_LEN_MAX >= string_mb_cur_max (pstr)); |
| 5945 | #else |
| 5946 | char buf[64]; |
| 5947 | #endif |
| 5948 | @@ -369,7 +369,7 @@ build_wcs_upper_buffer (re_string_t *pstr) |
| 5949 | { |
| 5950 | int i, ch; |
| 5951 | |
| 5952 | - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) |
| 5953 | + for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i) |
| 5954 | { |
| 5955 | ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; |
| 5956 | buf[i] = pstr->trans[ch]; |
| 5957 | @@ -567,8 +567,9 @@ re_string_translate_buffer (re_string_t *pstr) |
| 5958 | } |
| 5959 | |
| 5960 | /* This function re-construct the buffers. |
| 5961 | - Concretely, convert to wide character in case of pstr->mb_cur_max > 1, |
| 5962 | - convert to upper case in case of REG_ICASE, apply translation. */ |
| 5963 | + Concretely, convert to wide character in case of |
| 5964 | + string_mb_cur_max (pstr) > 1, convert to upper case in case of |
| 5965 | + REG_ICASE, apply translation. */ |
| 5966 | |
| 5967 | static reg_errcode_t |
| 5968 | internal_function __attribute_warn_unused_result__ |
| 5969 | @@ -579,7 +580,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) |
| 5970 | { |
| 5971 | /* Reset buffer. */ |
| 5972 | #ifdef RE_ENABLE_I18N |
| 5973 | - if (pstr->mb_cur_max > 1) |
| 5974 | + if (string_mb_cur_max (pstr) > 1) |
| 5975 | memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); |
| 5976 | #endif /* RE_ENABLE_I18N */ |
| 5977 | pstr->len = pstr->raw_len; |
| 5978 | @@ -670,7 +671,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) |
| 5979 | pstr->tip_context = re_string_context_at (pstr, offset - 1, |
| 5980 | eflags); |
| 5981 | #ifdef RE_ENABLE_I18N |
| 5982 | - if (pstr->mb_cur_max > 1) |
| 5983 | + if (string_mb_cur_max (pstr) > 1) |
| 5984 | memmove (pstr->wcs, pstr->wcs + offset, |
| 5985 | (pstr->valid_len - offset) * sizeof (wint_t)); |
| 5986 | #endif /* RE_ENABLE_I18N */ |
| 5987 | @@ -699,7 +700,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) |
| 5988 | #endif |
| 5989 | pstr->valid_len = 0; |
| 5990 | #ifdef RE_ENABLE_I18N |
| 5991 | - if (pstr->mb_cur_max > 1) |
| 5992 | + if (string_mb_cur_max (pstr) > 1) |
| 5993 | { |
| 5994 | int wcs_idx; |
| 5995 | wint_t wc = WEOF; |
| 5996 | @@ -711,7 +712,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) |
| 5997 | /* Special case UTF-8. Multi-byte chars start with any |
| 5998 | byte other than 0x80 - 0xbf. */ |
| 5999 | raw = pstr->raw_mbs + pstr->raw_mbs_idx; |
| 6000 | - end = raw + (offset - pstr->mb_cur_max); |
| 6001 | + end = raw + (offset - string_mb_cur_max (pstr)); |
| 6002 | if (end < pstr->raw_mbs) |
| 6003 | end = pstr->raw_mbs; |
| 6004 | p = raw + offset - 1; |
| 6005 | @@ -803,7 +804,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags) |
| 6006 | |
| 6007 | /* Then build the buffers. */ |
| 6008 | #ifdef RE_ENABLE_I18N |
| 6009 | - if (pstr->mb_cur_max > 1) |
| 6010 | + if (string_mb_cur_max (pstr) > 1) |
| 6011 | { |
| 6012 | if (pstr->icase) |
| 6013 | { |
| 6014 | @@ -841,7 +842,7 @@ re_string_peek_byte_case (const re_string_t *pstr, int idx) |
| 6015 | return re_string_peek_byte (pstr, idx); |
| 6016 | |
| 6017 | #ifdef RE_ENABLE_I18N |
| 6018 | - if (pstr->mb_cur_max > 1 |
| 6019 | + if (string_mb_cur_max (pstr) > 1 |
| 6020 | && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) |
| 6021 | return re_string_peek_byte (pstr, idx); |
| 6022 | #endif |
| 6023 | @@ -930,7 +931,7 @@ re_string_context_at (const re_string_t *input, int idx, int eflags) |
| 6024 | return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF |
| 6025 | : CONTEXT_NEWLINE | CONTEXT_ENDBUF); |
| 6026 | #ifdef RE_ENABLE_I18N |
| 6027 | - if (input->mb_cur_max > 1) |
| 6028 | + if (string_mb_cur_max (input) > 1) |
| 6029 | { |
| 6030 | wint_t wc; |
| 6031 | int wc_idx = idx; |
| 6032 | @@ -1444,7 +1445,7 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) |
| 6033 | dfa->nodes[dfa->nodes_len].constraint = 0; |
| 6034 | #ifdef RE_ENABLE_I18N |
| 6035 | dfa->nodes[dfa->nodes_len].accept_mb = |
| 6036 | - (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; |
| 6037 | + (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET; |
| 6038 | #endif |
| 6039 | dfa->nexts[dfa->nodes_len] = -1; |
| 6040 | re_node_set_init_empty (dfa->edests + dfa->nodes_len); |
| 6041 | diff --git a/posix/regex_internal.h b/posix/regex_internal.h |
| 6042 | index 154e969..c43909a 100644 |
| 6043 | --- a/posix/regex_internal.h |
| 6044 | +++ b/posix/regex_internal.h |
| 6045 | @@ -26,6 +26,10 @@ |
| 6046 | #include <stdlib.h> |
| 6047 | #include <string.h> |
| 6048 | |
| 6049 | +#if defined _LIBC |
| 6050 | +# include <gnu/option-groups.h> |
| 6051 | +#endif |
| 6052 | + |
| 6053 | #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC |
| 6054 | # include <langinfo.h> |
| 6055 | #endif |
| 6056 | @@ -369,6 +373,13 @@ struct re_string_t |
| 6057 | }; |
| 6058 | typedef struct re_string_t re_string_t; |
| 6059 | |
| 6060 | +/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1; |
| 6061 | + help the compiler make use of that fact. */ |
| 6062 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 6063 | +# define string_mb_cur_max(str) ((str)->mb_cur_max + 0) |
| 6064 | +#else |
| 6065 | +# define string_mb_cur_max(str) (1) |
| 6066 | +#endif |
| 6067 | |
| 6068 | struct re_dfa_t; |
| 6069 | typedef struct re_dfa_t re_dfa_t; |
| 6070 | @@ -654,6 +665,14 @@ struct re_dfa_t |
| 6071 | __libc_lock_define (, lock) |
| 6072 | }; |
| 6073 | |
| 6074 | +/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1; |
| 6075 | + help the compiler make use of that fact. */ |
| 6076 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 6077 | +# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0) |
| 6078 | +#else |
| 6079 | +# define dfa_mb_cur_max(dfa) (1) |
| 6080 | +#endif |
| 6081 | + |
| 6082 | #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) |
| 6083 | #define re_node_set_remove(set,id) \ |
| 6084 | (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) |
| 6085 | @@ -714,7 +733,7 @@ internal_function __attribute__ ((pure, unused)) |
| 6086 | re_string_char_size_at (const re_string_t *pstr, int idx) |
| 6087 | { |
| 6088 | int byte_idx; |
| 6089 | - if (pstr->mb_cur_max == 1) |
| 6090 | + if (string_mb_cur_max (pstr) == 1) |
| 6091 | return 1; |
| 6092 | for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) |
| 6093 | if (pstr->wcs[idx + byte_idx] != WEOF) |
| 6094 | @@ -726,7 +745,7 @@ static wint_t |
| 6095 | internal_function __attribute__ ((pure, unused)) |
| 6096 | re_string_wchar_at (const re_string_t *pstr, int idx) |
| 6097 | { |
| 6098 | - if (pstr->mb_cur_max == 1) |
| 6099 | + if (string_mb_cur_max (pstr) == 1) |
| 6100 | return (wint_t) pstr->mbs[idx]; |
| 6101 | return (wint_t) pstr->wcs[idx]; |
| 6102 | } |
| 6103 | diff --git a/posix/regexec-compat.c b/posix/regexec-compat.c |
| 6104 | new file mode 100644 |
| 6105 | index 0000000..0f9b7c7 |
| 6106 | --- /dev/null |
| 6107 | +++ b/posix/regexec-compat.c |
| 6108 | @@ -0,0 +1,39 @@ |
| 6109 | +/* Extended regular expression matching and search library. |
| 6110 | + Copyright (C) 2008 Free Software Foundation, Inc. |
| 6111 | + This file is part of the GNU C Library. |
| 6112 | + Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. |
| 6113 | + |
| 6114 | + The GNU C Library is free software; you can redistribute it and/or |
| 6115 | + modify it under the terms of the GNU Lesser General Public |
| 6116 | + License as published by the Free Software Foundation; either |
| 6117 | + version 2.1 of the License, or (at your option) any later version. |
| 6118 | + |
| 6119 | + The GNU C Library is distributed in the hope that it will be useful, |
| 6120 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 6121 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 6122 | + Lesser General Public License for more details. |
| 6123 | + |
| 6124 | + You should have received a copy of the GNU Lesser General Public |
| 6125 | + License along with the GNU C Library; if not, write to the Free |
| 6126 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 6127 | + 02111-1307 USA. */ |
| 6128 | + |
| 6129 | +#ifdef _LIBC |
| 6130 | +# include <shlib-compat.h> |
| 6131 | +versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); |
| 6132 | + |
| 6133 | +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) |
| 6134 | +__typeof__ (__regexec) __compat_regexec; |
| 6135 | + |
| 6136 | +int |
| 6137 | +attribute_compat_text_section |
| 6138 | +__compat_regexec (const regex_t *__restrict preg, |
| 6139 | + const char *__restrict string, size_t nmatch, |
| 6140 | + regmatch_t pmatch[], int eflags) |
| 6141 | +{ |
| 6142 | + return regexec (preg, string, nmatch, pmatch, |
| 6143 | + eflags & (REG_NOTBOL | REG_NOTEOL)); |
| 6144 | +} |
| 6145 | +compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); |
| 6146 | +# endif |
| 6147 | +#endif |
| 6148 | diff --git a/posix/regexec.c b/posix/regexec.c |
| 6149 | index 70cd606..e3b49e4 100644 |
| 6150 | --- a/posix/regexec.c |
| 6151 | +++ b/posix/regexec.c |
| 6152 | @@ -18,6 +18,7 @@ |
| 6153 | <http://www.gnu.org/licenses/>. */ |
| 6154 | |
| 6155 | #include <stdint.h> |
| 6156 | +#include <gnu/option-groups.h> |
| 6157 | |
| 6158 | static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, |
| 6159 | int n) internal_function; |
| 6160 | @@ -186,11 +187,11 @@ static int build_trtable (const re_dfa_t *dfa, |
| 6161 | static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6162 | const re_string_t *input, int idx) |
| 6163 | internal_function; |
| 6164 | -# ifdef _LIBC |
| 6165 | +# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE |
| 6166 | static unsigned int find_collation_sequence_value (const unsigned char *mbs, |
| 6167 | size_t name_len) |
| 6168 | internal_function; |
| 6169 | -# endif /* _LIBC */ |
| 6170 | +# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ |
| 6171 | #endif /* RE_ENABLE_I18N */ |
| 6172 | static int group_nodes_into_DFAstates (const re_dfa_t *dfa, |
| 6173 | const re_dfastate_t *state, |
| 6174 | @@ -255,25 +256,9 @@ regexec (preg, string, nmatch, pmatch, eflags) |
| 6175 | return err != REG_NOERROR; |
| 6176 | } |
| 6177 | |
| 6178 | -#ifdef _LIBC |
| 6179 | -# include <shlib-compat.h> |
| 6180 | -versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); |
| 6181 | - |
| 6182 | -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) |
| 6183 | -__typeof__ (__regexec) __compat_regexec; |
| 6184 | - |
| 6185 | -int |
| 6186 | -attribute_compat_text_section |
| 6187 | -__compat_regexec (const regex_t *__restrict preg, |
| 6188 | - const char *__restrict string, size_t nmatch, |
| 6189 | - regmatch_t pmatch[], int eflags) |
| 6190 | -{ |
| 6191 | - return regexec (preg, string, nmatch, pmatch, |
| 6192 | - eflags & (REG_NOTBOL | REG_NOTEOL)); |
| 6193 | -} |
| 6194 | -compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); |
| 6195 | -# endif |
| 6196 | -#endif |
| 6197 | +/* EGLIBC: The code that used to be here was move to a separate file |
| 6198 | + so that it can be shared with xregex.c. */ |
| 6199 | +#include "regexec-compat.c" |
| 6200 | |
| 6201 | /* Entry points for GNU code. */ |
| 6202 | |
| 6203 | @@ -728,7 +713,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, |
| 6204 | incr = (range < 0) ? -1 : 1; |
| 6205 | left_lim = (range < 0) ? start + range : start; |
| 6206 | right_lim = (range < 0) ? start : start + range; |
| 6207 | - sb = dfa->mb_cur_max == 1; |
| 6208 | + sb = dfa_mb_cur_max (dfa) == 1; |
| 6209 | match_kind = |
| 6210 | (fastmap |
| 6211 | ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) |
| 6212 | @@ -3448,7 +3433,7 @@ out_free: |
| 6213 | if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) |
| 6214 | goto out_free; |
| 6215 | |
| 6216 | - if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) |
| 6217 | + if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1) |
| 6218 | need_word_trtable = 1; |
| 6219 | |
| 6220 | dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, |
| 6221 | @@ -3590,7 +3575,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, |
| 6222 | else if (type == OP_PERIOD) |
| 6223 | { |
| 6224 | #ifdef RE_ENABLE_I18N |
| 6225 | - if (dfa->mb_cur_max > 1) |
| 6226 | + if (dfa_mb_cur_max (dfa) > 1) |
| 6227 | bitset_merge (accepts, dfa->sb_char); |
| 6228 | else |
| 6229 | #endif |
| 6230 | @@ -3641,7 +3626,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, |
| 6231 | continue; |
| 6232 | } |
| 6233 | #ifdef RE_ENABLE_I18N |
| 6234 | - if (dfa->mb_cur_max > 1) |
| 6235 | + if (dfa_mb_cur_max (dfa) > 1) |
| 6236 | for (j = 0; j < BITSET_WORDS; ++j) |
| 6237 | any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); |
| 6238 | else |
| 6239 | @@ -3660,7 +3645,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, |
| 6240 | continue; |
| 6241 | } |
| 6242 | #ifdef RE_ENABLE_I18N |
| 6243 | - if (dfa->mb_cur_max > 1) |
| 6244 | + if (dfa_mb_cur_max (dfa) > 1) |
| 6245 | for (j = 0; j < BITSET_WORDS; ++j) |
| 6246 | any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); |
| 6247 | else |
| 6248 | @@ -3836,12 +3821,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6249 | if (node->type == COMPLEX_BRACKET) |
| 6250 | { |
| 6251 | const re_charset_t *cset = node->opr.mbcset; |
| 6252 | -# ifdef _LIBC |
| 6253 | - const unsigned char *pin |
| 6254 | - = ((const unsigned char *) re_string_get_buffer (input) + str_idx); |
| 6255 | - int j; |
| 6256 | - uint32_t nrules; |
| 6257 | -# endif /* _LIBC */ |
| 6258 | int match_len = 0; |
| 6259 | wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) |
| 6260 | ? re_string_wchar_at (input, str_idx) : 0); |
| 6261 | @@ -3853,6 +3832,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6262 | match_len = char_len; |
| 6263 | goto check_node_accept_bytes_match; |
| 6264 | } |
| 6265 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 6266 | /* match with character_class? */ |
| 6267 | for (i = 0; i < cset->nchar_classes; ++i) |
| 6268 | { |
| 6269 | @@ -3863,14 +3843,22 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6270 | goto check_node_accept_bytes_match; |
| 6271 | } |
| 6272 | } |
| 6273 | +#endif |
| 6274 | + |
| 6275 | + /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C |
| 6276 | + locale is supported; it has no collation rules. */ |
| 6277 | +# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE |
| 6278 | + const unsigned char *pin |
| 6279 | + = ((const unsigned char *) re_string_get_buffer (input) + str_idx); |
| 6280 | + int j; |
| 6281 | + uint32_t nrules; |
| 6282 | |
| 6283 | -# ifdef _LIBC |
| 6284 | nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 6285 | if (nrules != 0) |
| 6286 | { |
| 6287 | unsigned int in_collseq = 0; |
| 6288 | const int32_t *table, *indirect; |
| 6289 | - const unsigned char *weights, *extra; |
| 6290 | + const unsigned char *weights, *extra = NULL; |
| 6291 | const char *collseqwc; |
| 6292 | |
| 6293 | /* match with collating_symbol? */ |
| 6294 | @@ -3955,8 +3943,12 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6295 | } |
| 6296 | } |
| 6297 | else |
| 6298 | -# endif /* _LIBC */ |
| 6299 | +# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ |
| 6300 | { |
| 6301 | + /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is |
| 6302 | + disabled, there can be no multibyte range endpoints, and |
| 6303 | + cset->nranges is always zero. */ |
| 6304 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 6305 | /* match with range expression? */ |
| 6306 | #if __GNUC__ >= 2 |
| 6307 | wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; |
| 6308 | @@ -3975,6 +3967,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6309 | goto check_node_accept_bytes_match; |
| 6310 | } |
| 6311 | } |
| 6312 | +#endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 6313 | } |
| 6314 | check_node_accept_bytes_match: |
| 6315 | if (!cset->non_match) |
| 6316 | @@ -3990,7 +3983,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, |
| 6317 | return 0; |
| 6318 | } |
| 6319 | |
| 6320 | -# ifdef _LIBC |
| 6321 | +# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE |
| 6322 | static unsigned int |
| 6323 | internal_function |
| 6324 | find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) |
| 6325 | @@ -4048,7 +4041,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) |
| 6326 | return UINT_MAX; |
| 6327 | } |
| 6328 | } |
| 6329 | -# endif /* _LIBC */ |
| 6330 | +# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */ |
| 6331 | #endif /* RE_ENABLE_I18N */ |
| 6332 | |
| 6333 | /* Check whether the node accepts the byte which is IDX-th |
| 6334 | @@ -4139,7 +4132,7 @@ extend_buffers (re_match_context_t *mctx, int min_len) |
| 6335 | if (pstr->icase) |
| 6336 | { |
| 6337 | #ifdef RE_ENABLE_I18N |
| 6338 | - if (pstr->mb_cur_max > 1) |
| 6339 | + if (string_mb_cur_max (pstr) > 1) |
| 6340 | { |
| 6341 | ret = build_wcs_upper_buffer (pstr); |
| 6342 | if (BE (ret != REG_NOERROR, 0)) |
| 6343 | @@ -4152,7 +4145,7 @@ extend_buffers (re_match_context_t *mctx, int min_len) |
| 6344 | else |
| 6345 | { |
| 6346 | #ifdef RE_ENABLE_I18N |
| 6347 | - if (pstr->mb_cur_max > 1) |
| 6348 | + if (string_mb_cur_max (pstr) > 1) |
| 6349 | build_wcs_buffer (pstr); |
| 6350 | else |
| 6351 | #endif /* RE_ENABLE_I18N */ |
| 6352 | diff --git a/posix/xregex.c b/posix/xregex.c |
| 6353 | new file mode 100644 |
| 6354 | index 0000000..d3f7ace |
| 6355 | --- /dev/null |
| 6356 | +++ b/posix/xregex.c |
| 6357 | @@ -0,0 +1,8215 @@ |
| 6358 | +/* Extended regular expression matching and search library, |
| 6359 | + version 0.12. |
| 6360 | + (Implements POSIX draft P1003.2/D11.2, except for some of the |
| 6361 | + internationalization features.) |
| 6362 | + |
| 6363 | + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, |
| 6364 | + 2002, 2005 Free Software Foundation, Inc. |
| 6365 | + This file is part of the GNU C Library. |
| 6366 | + |
| 6367 | + The GNU C Library is free software; you can redistribute it and/or |
| 6368 | + modify it under the terms of the GNU Lesser General Public |
| 6369 | + License as published by the Free Software Foundation; either |
| 6370 | + version 2.1 of the License, or (at your option) any later version. |
| 6371 | + |
| 6372 | + The GNU C Library is distributed in the hope that it will be useful, |
| 6373 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 6374 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 6375 | + Lesser General Public License for more details. |
| 6376 | + |
| 6377 | + You should have received a copy of the GNU Lesser General Public |
| 6378 | + License along with the GNU C Library; if not, write to the Free |
| 6379 | + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 6380 | + 02110-1301 USA. */ |
| 6381 | + |
| 6382 | +/* AIX requires this to be the first thing in the file. */ |
| 6383 | +#if defined _AIX && !defined __GNUC__ && !defined REGEX_MALLOC |
| 6384 | + #pragma alloca |
| 6385 | +#endif |
| 6386 | + |
| 6387 | +#undef _GNU_SOURCE |
| 6388 | +#define _GNU_SOURCE |
| 6389 | + |
| 6390 | +#ifndef INSIDE_RECURSION |
| 6391 | +# ifdef HAVE_CONFIG_H |
| 6392 | +# include <config.h> |
| 6393 | +# endif |
| 6394 | +#endif |
| 6395 | + |
| 6396 | +/*#include <ansidecl.h>*/ |
| 6397 | + |
| 6398 | + |
| 6399 | +#ifndef INSIDE_RECURSION |
| 6400 | + |
| 6401 | +# if defined STDC_HEADERS && !defined emacs |
| 6402 | +# include <stddef.h> |
| 6403 | +# else |
| 6404 | +/* We need this for `regex.h', and perhaps for the Emacs include files. */ |
| 6405 | +# include <sys/types.h> |
| 6406 | +# endif |
| 6407 | + |
| 6408 | +# if (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_BTOWC) |
| 6409 | +# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) |
| 6410 | +# else |
| 6411 | +# define WIDE_CHAR_SUPPORT 0 |
| 6412 | +# endif |
| 6413 | +/* For platform which support the ISO C amendement 1 functionality we |
| 6414 | + support user defined character classes. */ |
| 6415 | +# if WIDE_CHAR_SUPPORT |
| 6416 | +/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ |
| 6417 | +# include <wchar.h> |
| 6418 | +# include <wctype.h> |
| 6419 | +# endif |
| 6420 | + |
| 6421 | +# ifdef _LIBC |
| 6422 | +/* We have to keep the namespace clean. */ |
| 6423 | +# define regfree(preg) __regfree (preg) |
| 6424 | +# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) |
| 6425 | +# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) |
| 6426 | +# define regerror(errcode, preg, errbuf, errbuf_size) \ |
| 6427 | + __regerror(errcode, preg, errbuf, errbuf_size) |
| 6428 | +# define re_set_registers(bu, re, nu, st, en) \ |
| 6429 | + __re_set_registers (bu, re, nu, st, en) |
| 6430 | +# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ |
| 6431 | + __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) |
| 6432 | +# define re_match(bufp, string, size, pos, regs) \ |
| 6433 | + __re_match (bufp, string, size, pos, regs) |
| 6434 | +# define re_search(bufp, string, size, startpos, range, regs) \ |
| 6435 | + __re_search (bufp, string, size, startpos, range, regs) |
| 6436 | +# define re_compile_pattern(pattern, length, bufp) \ |
| 6437 | + __re_compile_pattern (pattern, length, bufp) |
| 6438 | +# define re_set_syntax(syntax) __re_set_syntax (syntax) |
| 6439 | +# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ |
| 6440 | + __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) |
| 6441 | +# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) |
| 6442 | + |
| 6443 | +# define btowc __btowc |
| 6444 | + |
| 6445 | +/* We are also using some library internals. */ |
| 6446 | +# include <locale/localeinfo.h> |
| 6447 | +# include <locale/elem-hash.h> |
| 6448 | +# include <langinfo.h> |
| 6449 | +# include <locale/coll-lookup.h> |
| 6450 | +# endif |
| 6451 | + |
| 6452 | +/* This is for other GNU distributions with internationalized messages. */ |
| 6453 | +# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC |
| 6454 | +# include <libintl.h> |
| 6455 | +# ifdef _LIBC |
| 6456 | +# undef gettext |
| 6457 | +# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) |
| 6458 | +# endif |
| 6459 | +# else |
| 6460 | +# define gettext(msgid) (msgid) |
| 6461 | +# endif |
| 6462 | + |
| 6463 | +# ifndef gettext_noop |
| 6464 | +/* This define is so xgettext can find the internationalizable |
| 6465 | + strings. */ |
| 6466 | +# define gettext_noop(String) String |
| 6467 | +# endif |
| 6468 | + |
| 6469 | +/* The `emacs' switch turns on certain matching commands |
| 6470 | + that make sense only in Emacs. */ |
| 6471 | +# ifdef emacs |
| 6472 | + |
| 6473 | +# include "lisp.h" |
| 6474 | +# include "buffer.h" |
| 6475 | +# include "syntax.h" |
| 6476 | + |
| 6477 | +# else /* not emacs */ |
| 6478 | + |
| 6479 | +/* If we are not linking with Emacs proper, |
| 6480 | + we can't use the relocating allocator |
| 6481 | + even if config.h says that we can. */ |
| 6482 | +# undef REL_ALLOC |
| 6483 | + |
| 6484 | +# if defined STDC_HEADERS || defined _LIBC |
| 6485 | +# include <stdlib.h> |
| 6486 | +# else |
| 6487 | +char *malloc (); |
| 6488 | +char *realloc (); |
| 6489 | +# endif |
| 6490 | + |
| 6491 | +/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. |
| 6492 | + If nothing else has been done, use the method below. */ |
| 6493 | +# ifdef INHIBIT_STRING_HEADER |
| 6494 | +# if !(defined HAVE_BZERO && defined HAVE_BCOPY) |
| 6495 | +# if !defined bzero && !defined bcopy |
| 6496 | +# undef INHIBIT_STRING_HEADER |
| 6497 | +# endif |
| 6498 | +# endif |
| 6499 | +# endif |
| 6500 | + |
| 6501 | +/* This is the normal way of making sure we have a bcopy and a bzero. |
| 6502 | + This is used in most programs--a few other programs avoid this |
| 6503 | + by defining INHIBIT_STRING_HEADER. */ |
| 6504 | +# ifndef INHIBIT_STRING_HEADER |
| 6505 | +# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC |
| 6506 | +# include <string.h> |
| 6507 | +# ifndef bzero |
| 6508 | +# ifndef _LIBC |
| 6509 | +# define bzero(s, n) (memset (s, '\0', n), (s)) |
| 6510 | +# else |
| 6511 | +# define bzero(s, n) __bzero (s, n) |
| 6512 | +# endif |
| 6513 | +# endif |
| 6514 | +# else |
| 6515 | +# include <strings.h> |
| 6516 | +# ifndef memcmp |
| 6517 | +# define memcmp(s1, s2, n) bcmp (s1, s2, n) |
| 6518 | +# endif |
| 6519 | +# ifndef memcpy |
| 6520 | +# define memcpy(d, s, n) (bcopy (s, d, n), (d)) |
| 6521 | +# endif |
| 6522 | +# endif |
| 6523 | +# endif |
| 6524 | + |
| 6525 | +/* Define the syntax stuff for \<, \>, etc. */ |
| 6526 | + |
| 6527 | +/* This must be nonzero for the wordchar and notwordchar pattern |
| 6528 | + commands in re_match_2. */ |
| 6529 | +# ifndef Sword |
| 6530 | +# define Sword 1 |
| 6531 | +# endif |
| 6532 | + |
| 6533 | +# ifdef SWITCH_ENUM_BUG |
| 6534 | +# define SWITCH_ENUM_CAST(x) ((int)(x)) |
| 6535 | +# else |
| 6536 | +# define SWITCH_ENUM_CAST(x) (x) |
| 6537 | +# endif |
| 6538 | + |
| 6539 | +# endif /* not emacs */ |
| 6540 | + |
| 6541 | +# if defined _LIBC || HAVE_LIMITS_H |
| 6542 | +# include <limits.h> |
| 6543 | +# endif |
| 6544 | + |
| 6545 | +# ifndef MB_LEN_MAX |
| 6546 | +# define MB_LEN_MAX 1 |
| 6547 | +# endif |
| 6548 | + |
| 6549 | +/* Get the interface, including the syntax bits. */ |
| 6550 | +# include "regex.h" |
| 6551 | + |
| 6552 | +/* isalpha etc. are used for the character classes. */ |
| 6553 | +# include <ctype.h> |
| 6554 | + |
| 6555 | +/* Jim Meyering writes: |
| 6556 | + |
| 6557 | + "... Some ctype macros are valid only for character codes that |
| 6558 | + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when |
| 6559 | + using /bin/cc or gcc but without giving an ansi option). So, all |
| 6560 | + ctype uses should be through macros like ISPRINT... If |
| 6561 | + STDC_HEADERS is defined, then autoconf has verified that the ctype |
| 6562 | + macros don't need to be guarded with references to isascii. ... |
| 6563 | + Defining isascii to 1 should let any compiler worth its salt |
| 6564 | + eliminate the && through constant folding." |
| 6565 | + Solaris defines some of these symbols so we must undefine them first. */ |
| 6566 | + |
| 6567 | +# undef ISASCII |
| 6568 | +# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) |
| 6569 | +# define ISASCII(c) 1 |
| 6570 | +# else |
| 6571 | +# define ISASCII(c) isascii(c) |
| 6572 | +# endif |
| 6573 | + |
| 6574 | +# ifdef isblank |
| 6575 | +# define ISBLANK(c) (ISASCII (c) && isblank (c)) |
| 6576 | +# else |
| 6577 | +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') |
| 6578 | +# endif |
| 6579 | +# ifdef isgraph |
| 6580 | +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) |
| 6581 | +# else |
| 6582 | +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) |
| 6583 | +# endif |
| 6584 | + |
| 6585 | +# undef ISPRINT |
| 6586 | +# define ISPRINT(c) (ISASCII (c) && isprint (c)) |
| 6587 | +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) |
| 6588 | +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) |
| 6589 | +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) |
| 6590 | +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) |
| 6591 | +# define ISLOWER(c) (ISASCII (c) && islower (c)) |
| 6592 | +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) |
| 6593 | +# define ISSPACE(c) (ISASCII (c) && isspace (c)) |
| 6594 | +# define ISUPPER(c) (ISASCII (c) && isupper (c)) |
| 6595 | +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) |
| 6596 | + |
| 6597 | +# ifdef _tolower |
| 6598 | +# define TOLOWER(c) _tolower(c) |
| 6599 | +# else |
| 6600 | +# define TOLOWER(c) tolower(c) |
| 6601 | +# endif |
| 6602 | + |
| 6603 | +# ifndef NULL |
| 6604 | +# define NULL (void *)0 |
| 6605 | +# endif |
| 6606 | + |
| 6607 | +/* We remove any previous definition of `SIGN_EXTEND_CHAR', |
| 6608 | + since ours (we hope) works properly with all combinations of |
| 6609 | + machines, compilers, `char' and `unsigned char' argument types. |
| 6610 | + (Per Bothner suggested the basic approach.) */ |
| 6611 | +# undef SIGN_EXTEND_CHAR |
| 6612 | +# if __STDC__ |
| 6613 | +# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) |
| 6614 | +# else /* not __STDC__ */ |
| 6615 | +/* As in Harbison and Steele. */ |
| 6616 | +# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) |
| 6617 | +# endif |
| 6618 | + |
| 6619 | +# ifndef emacs |
| 6620 | +/* How many characters in the character set. */ |
| 6621 | +# define CHAR_SET_SIZE 256 |
| 6622 | + |
| 6623 | +# ifdef SYNTAX_TABLE |
| 6624 | + |
| 6625 | +extern char *re_syntax_table; |
| 6626 | + |
| 6627 | +# else /* not SYNTAX_TABLE */ |
| 6628 | + |
| 6629 | +static char re_syntax_table[CHAR_SET_SIZE]; |
| 6630 | + |
| 6631 | +static void init_syntax_once (void); |
| 6632 | + |
| 6633 | +static void |
| 6634 | +init_syntax_once (void) |
| 6635 | +{ |
| 6636 | + register int c; |
| 6637 | + static int done = 0; |
| 6638 | + |
| 6639 | + if (done) |
| 6640 | + return; |
| 6641 | + bzero (re_syntax_table, sizeof re_syntax_table); |
| 6642 | + |
| 6643 | + for (c = 0; c < CHAR_SET_SIZE; ++c) |
| 6644 | + if (ISALNUM (c)) |
| 6645 | + re_syntax_table[c] = Sword; |
| 6646 | + |
| 6647 | + re_syntax_table['_'] = Sword; |
| 6648 | + |
| 6649 | + done = 1; |
| 6650 | +} |
| 6651 | + |
| 6652 | +# endif /* not SYNTAX_TABLE */ |
| 6653 | + |
| 6654 | +# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] |
| 6655 | + |
| 6656 | +# endif /* emacs */ |
| 6657 | + |
| 6658 | +/* Integer type for pointers. */ |
| 6659 | +# if !defined _LIBC && !defined HAVE_UINTPTR_T |
| 6660 | +typedef unsigned long int uintptr_t; |
| 6661 | +# endif |
| 6662 | + |
| 6663 | +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we |
| 6664 | + use `alloca' instead of `malloc'. This is because using malloc in |
| 6665 | + re_search* or re_match* could cause memory leaks when C-g is used in |
| 6666 | + Emacs; also, malloc is slower and causes storage fragmentation. On |
| 6667 | + the other hand, malloc is more portable, and easier to debug. |
| 6668 | + |
| 6669 | + Because we sometimes use alloca, some routines have to be macros, |
| 6670 | + not functions -- `alloca'-allocated space disappears at the end of the |
| 6671 | + function it is called in. */ |
| 6672 | + |
| 6673 | +# ifdef REGEX_MALLOC |
| 6674 | + |
| 6675 | +# define REGEX_ALLOCATE malloc |
| 6676 | +# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) |
| 6677 | +# define REGEX_FREE free |
| 6678 | + |
| 6679 | +# else /* not REGEX_MALLOC */ |
| 6680 | + |
| 6681 | +/* Emacs already defines alloca, sometimes. */ |
| 6682 | +# ifndef alloca |
| 6683 | + |
| 6684 | +/* Make alloca work the best possible way. */ |
| 6685 | +# ifdef __GNUC__ |
| 6686 | +# define alloca __builtin_alloca |
| 6687 | +# else /* not __GNUC__ */ |
| 6688 | +# if HAVE_ALLOCA_H |
| 6689 | +# include <alloca.h> |
| 6690 | +# endif /* HAVE_ALLOCA_H */ |
| 6691 | +# endif /* not __GNUC__ */ |
| 6692 | + |
| 6693 | +# endif /* not alloca */ |
| 6694 | + |
| 6695 | +# define REGEX_ALLOCATE alloca |
| 6696 | + |
| 6697 | +/* Assumes a `char *destination' variable. */ |
| 6698 | +# define REGEX_REALLOCATE(source, osize, nsize) \ |
| 6699 | + (destination = (char *) alloca (nsize), \ |
| 6700 | + memcpy (destination, source, osize)) |
| 6701 | + |
| 6702 | +/* No need to do anything to free, after alloca. */ |
| 6703 | +# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ |
| 6704 | + |
| 6705 | +# endif /* not REGEX_MALLOC */ |
| 6706 | + |
| 6707 | +/* Define how to allocate the failure stack. */ |
| 6708 | + |
| 6709 | +# if defined REL_ALLOC && defined REGEX_MALLOC |
| 6710 | + |
| 6711 | +# define REGEX_ALLOCATE_STACK(size) \ |
| 6712 | + r_alloc (&failure_stack_ptr, (size)) |
| 6713 | +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ |
| 6714 | + r_re_alloc (&failure_stack_ptr, (nsize)) |
| 6715 | +# define REGEX_FREE_STACK(ptr) \ |
| 6716 | + r_alloc_free (&failure_stack_ptr) |
| 6717 | + |
| 6718 | +# else /* not using relocating allocator */ |
| 6719 | + |
| 6720 | +# ifdef REGEX_MALLOC |
| 6721 | + |
| 6722 | +# define REGEX_ALLOCATE_STACK malloc |
| 6723 | +# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) |
| 6724 | +# define REGEX_FREE_STACK free |
| 6725 | + |
| 6726 | +# else /* not REGEX_MALLOC */ |
| 6727 | + |
| 6728 | +# define REGEX_ALLOCATE_STACK alloca |
| 6729 | + |
| 6730 | +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ |
| 6731 | + REGEX_REALLOCATE (source, osize, nsize) |
| 6732 | +/* No need to explicitly free anything. */ |
| 6733 | +# define REGEX_FREE_STACK(arg) |
| 6734 | + |
| 6735 | +# endif /* not REGEX_MALLOC */ |
| 6736 | +# endif /* not using relocating allocator */ |
| 6737 | + |
| 6738 | + |
| 6739 | +/* True if `size1' is non-NULL and PTR is pointing anywhere inside |
| 6740 | + `string1' or just past its end. This works if PTR is NULL, which is |
| 6741 | + a good thing. */ |
| 6742 | +# define FIRST_STRING_P(ptr) \ |
| 6743 | + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) |
| 6744 | + |
| 6745 | +/* (Re)Allocate N items of type T using malloc, or fail. */ |
| 6746 | +# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) |
| 6747 | +# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) |
| 6748 | +# define RETALLOC_IF(addr, n, t) \ |
| 6749 | + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) |
| 6750 | +# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) |
| 6751 | + |
| 6752 | +# define BYTEWIDTH 8 /* In bits. */ |
| 6753 | + |
| 6754 | +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) |
| 6755 | + |
| 6756 | +# undef MAX |
| 6757 | +# undef MIN |
| 6758 | +# define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| 6759 | +# define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| 6760 | + |
| 6761 | +typedef char boolean; |
| 6762 | +# define false 0 |
| 6763 | +# define true 1 |
| 6764 | + |
| 6765 | +static reg_errcode_t byte_regex_compile (const char *pattern, size_t size, |
| 6766 | + reg_syntax_t syntax, |
| 6767 | + struct re_pattern_buffer *bufp); |
| 6768 | + |
| 6769 | +static int byte_re_match_2_internal (struct re_pattern_buffer *bufp, |
| 6770 | + const char *string1, int size1, |
| 6771 | + const char *string2, int size2, |
| 6772 | + int pos, |
| 6773 | + struct re_registers *regs, |
| 6774 | + int stop); |
| 6775 | +static int byte_re_search_2 (struct re_pattern_buffer *bufp, |
| 6776 | + const char *string1, int size1, |
| 6777 | + const char *string2, int size2, |
| 6778 | + int startpos, int range, |
| 6779 | + struct re_registers *regs, int stop); |
| 6780 | +static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp); |
| 6781 | + |
| 6782 | +#ifdef MBS_SUPPORT |
| 6783 | +static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size, |
| 6784 | + reg_syntax_t syntax, |
| 6785 | + struct re_pattern_buffer *bufp); |
| 6786 | + |
| 6787 | + |
| 6788 | +static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp, |
| 6789 | + const char *cstring1, int csize1, |
| 6790 | + const char *cstring2, int csize2, |
| 6791 | + int pos, |
| 6792 | + struct re_registers *regs, |
| 6793 | + int stop, |
| 6794 | + wchar_t *string1, int size1, |
| 6795 | + wchar_t *string2, int size2, |
| 6796 | + int *mbs_offset1, int *mbs_offset2); |
| 6797 | +static int wcs_re_search_2 (struct re_pattern_buffer *bufp, |
| 6798 | + const char *string1, int size1, |
| 6799 | + const char *string2, int size2, |
| 6800 | + int startpos, int range, |
| 6801 | + struct re_registers *regs, int stop); |
| 6802 | +static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp); |
| 6803 | +#endif |
| 6804 | + |
| 6805 | +/* These are the command codes that appear in compiled regular |
| 6806 | + expressions. Some opcodes are followed by argument bytes. A |
| 6807 | + command code can specify any interpretation whatsoever for its |
| 6808 | + arguments. Zero bytes may appear in the compiled regular expression. */ |
| 6809 | + |
| 6810 | +typedef enum |
| 6811 | +{ |
| 6812 | + no_op = 0, |
| 6813 | + |
| 6814 | + /* Succeed right away--no more backtracking. */ |
| 6815 | + succeed, |
| 6816 | + |
| 6817 | + /* Followed by one byte giving n, then by n literal bytes. */ |
| 6818 | + exactn, |
| 6819 | + |
| 6820 | +# ifdef MBS_SUPPORT |
| 6821 | + /* Same as exactn, but contains binary data. */ |
| 6822 | + exactn_bin, |
| 6823 | +# endif |
| 6824 | + |
| 6825 | + /* Matches any (more or less) character. */ |
| 6826 | + anychar, |
| 6827 | + |
| 6828 | + /* Matches any one char belonging to specified set. First |
| 6829 | + following byte is number of bitmap bytes. Then come bytes |
| 6830 | + for a bitmap saying which chars are in. Bits in each byte |
| 6831 | + are ordered low-bit-first. A character is in the set if its |
| 6832 | + bit is 1. A character too large to have a bit in the map is |
| 6833 | + automatically not in the set. */ |
| 6834 | + /* ifdef MBS_SUPPORT, following element is length of character |
| 6835 | + classes, length of collating symbols, length of equivalence |
| 6836 | + classes, length of character ranges, and length of characters. |
| 6837 | + Next, character class element, collating symbols elements, |
| 6838 | + equivalence class elements, range elements, and character |
| 6839 | + elements follow. |
| 6840 | + See regex_compile function. */ |
| 6841 | + charset, |
| 6842 | + |
| 6843 | + /* Same parameters as charset, but match any character that is |
| 6844 | + not one of those specified. */ |
| 6845 | + charset_not, |
| 6846 | + |
| 6847 | + /* Start remembering the text that is matched, for storing in a |
| 6848 | + register. Followed by one byte with the register number, in |
| 6849 | + the range 0 to one less than the pattern buffer's re_nsub |
| 6850 | + field. Then followed by one byte with the number of groups |
| 6851 | + inner to this one. (This last has to be part of the |
| 6852 | + start_memory only because we need it in the on_failure_jump |
| 6853 | + of re_match_2.) */ |
| 6854 | + start_memory, |
| 6855 | + |
| 6856 | + /* Stop remembering the text that is matched and store it in a |
| 6857 | + memory register. Followed by one byte with the register |
| 6858 | + number, in the range 0 to one less than `re_nsub' in the |
| 6859 | + pattern buffer, and one byte with the number of inner groups, |
| 6860 | + just like `start_memory'. (We need the number of inner |
| 6861 | + groups here because we don't have any easy way of finding the |
| 6862 | + corresponding start_memory when we're at a stop_memory.) */ |
| 6863 | + stop_memory, |
| 6864 | + |
| 6865 | + /* Match a duplicate of something remembered. Followed by one |
| 6866 | + byte containing the register number. */ |
| 6867 | + duplicate, |
| 6868 | + |
| 6869 | + /* Fail unless at beginning of line. */ |
| 6870 | + begline, |
| 6871 | + |
| 6872 | + /* Fail unless at end of line. */ |
| 6873 | + endline, |
| 6874 | + |
| 6875 | + /* Succeeds if at beginning of buffer (if emacs) or at beginning |
| 6876 | + of string to be matched (if not). */ |
| 6877 | + begbuf, |
| 6878 | + |
| 6879 | + /* Analogously, for end of buffer/string. */ |
| 6880 | + endbuf, |
| 6881 | + |
| 6882 | + /* Followed by two byte relative address to which to jump. */ |
| 6883 | + jump, |
| 6884 | + |
| 6885 | + /* Same as jump, but marks the end of an alternative. */ |
| 6886 | + jump_past_alt, |
| 6887 | + |
| 6888 | + /* Followed by two-byte relative address of place to resume at |
| 6889 | + in case of failure. */ |
| 6890 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6891 | + on_failure_jump, |
| 6892 | + |
| 6893 | + /* Like on_failure_jump, but pushes a placeholder instead of the |
| 6894 | + current string position when executed. */ |
| 6895 | + on_failure_keep_string_jump, |
| 6896 | + |
| 6897 | + /* Throw away latest failure point and then jump to following |
| 6898 | + two-byte relative address. */ |
| 6899 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6900 | + pop_failure_jump, |
| 6901 | + |
| 6902 | + /* Change to pop_failure_jump if know won't have to backtrack to |
| 6903 | + match; otherwise change to jump. This is used to jump |
| 6904 | + back to the beginning of a repeat. If what follows this jump |
| 6905 | + clearly won't match what the repeat does, such that we can be |
| 6906 | + sure that there is no use backtracking out of repetitions |
| 6907 | + already matched, then we change it to a pop_failure_jump. |
| 6908 | + Followed by two-byte address. */ |
| 6909 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6910 | + maybe_pop_jump, |
| 6911 | + |
| 6912 | + /* Jump to following two-byte address, and push a dummy failure |
| 6913 | + point. This failure point will be thrown away if an attempt |
| 6914 | + is made to use it for a failure. A `+' construct makes this |
| 6915 | + before the first repeat. Also used as an intermediary kind |
| 6916 | + of jump when compiling an alternative. */ |
| 6917 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6918 | + dummy_failure_jump, |
| 6919 | + |
| 6920 | + /* Push a dummy failure point and continue. Used at the end of |
| 6921 | + alternatives. */ |
| 6922 | + push_dummy_failure, |
| 6923 | + |
| 6924 | + /* Followed by two-byte relative address and two-byte number n. |
| 6925 | + After matching N times, jump to the address upon failure. */ |
| 6926 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6927 | + succeed_n, |
| 6928 | + |
| 6929 | + /* Followed by two-byte relative address, and two-byte number n. |
| 6930 | + Jump to the address N times, then fail. */ |
| 6931 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6932 | + jump_n, |
| 6933 | + |
| 6934 | + /* Set the following two-byte relative address to the |
| 6935 | + subsequent two-byte number. The address *includes* the two |
| 6936 | + bytes of number. */ |
| 6937 | + /* ifdef MBS_SUPPORT, the size of address is 1. */ |
| 6938 | + set_number_at, |
| 6939 | + |
| 6940 | + wordchar, /* Matches any word-constituent character. */ |
| 6941 | + notwordchar, /* Matches any char that is not a word-constituent. */ |
| 6942 | + |
| 6943 | + wordbeg, /* Succeeds if at word beginning. */ |
| 6944 | + wordend, /* Succeeds if at word end. */ |
| 6945 | + |
| 6946 | + wordbound, /* Succeeds if at a word boundary. */ |
| 6947 | + notwordbound /* Succeeds if not at a word boundary. */ |
| 6948 | + |
| 6949 | +# ifdef emacs |
| 6950 | + ,before_dot, /* Succeeds if before point. */ |
| 6951 | + at_dot, /* Succeeds if at point. */ |
| 6952 | + after_dot, /* Succeeds if after point. */ |
| 6953 | + |
| 6954 | + /* Matches any character whose syntax is specified. Followed by |
| 6955 | + a byte which contains a syntax code, e.g., Sword. */ |
| 6956 | + syntaxspec, |
| 6957 | + |
| 6958 | + /* Matches any character whose syntax is not that specified. */ |
| 6959 | + notsyntaxspec |
| 6960 | +# endif /* emacs */ |
| 6961 | +} re_opcode_t; |
| 6962 | +#endif /* not INSIDE_RECURSION */ |
| 6963 | + |
| 6964 | + |
| 6965 | +#ifdef BYTE |
| 6966 | +# define CHAR_T char |
| 6967 | +# define UCHAR_T unsigned char |
| 6968 | +# define COMPILED_BUFFER_VAR bufp->buffer |
| 6969 | +# define OFFSET_ADDRESS_SIZE 2 |
| 6970 | +# define PREFIX(name) byte_##name |
| 6971 | +# define ARG_PREFIX(name) name |
| 6972 | +# define PUT_CHAR(c) putchar (c) |
| 6973 | +# include <locale/weight.h> |
| 6974 | +# define FINDIDX findidx |
| 6975 | +#else |
| 6976 | +# ifdef WCHAR |
| 6977 | +# define CHAR_T wchar_t |
| 6978 | +# define UCHAR_T wchar_t |
| 6979 | +# define COMPILED_BUFFER_VAR wc_buffer |
| 6980 | +# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ |
| 6981 | +# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) |
| 6982 | +# define PREFIX(name) wcs_##name |
| 6983 | +# define ARG_PREFIX(name) c##name |
| 6984 | +/* Should we use wide stream?? */ |
| 6985 | +# define PUT_CHAR(c) printf ("%C", c); |
| 6986 | +# define TRUE 1 |
| 6987 | +# define FALSE 0 |
| 6988 | +# define findidx findidxwc |
| 6989 | +# include <locale/weightwc.h> |
| 6990 | +# undef findidx |
| 6991 | +# define FINDIDX findidxwc |
| 6992 | +# else |
| 6993 | +# ifdef MBS_SUPPORT |
| 6994 | +# define WCHAR |
| 6995 | +# define INSIDE_RECURSION |
| 6996 | +# include "xregex.c" |
| 6997 | +# undef INSIDE_RECURSION |
| 6998 | +# endif |
| 6999 | +# define BYTE |
| 7000 | +# define INSIDE_RECURSION |
| 7001 | +# include "xregex.c" |
| 7002 | +# undef INSIDE_RECURSION |
| 7003 | +# endif |
| 7004 | +#endif |
| 7005 | + |
| 7006 | +#ifdef INSIDE_RECURSION |
| 7007 | +/* Common operations on the compiled pattern. */ |
| 7008 | + |
| 7009 | +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ |
| 7010 | +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ |
| 7011 | + |
| 7012 | +# ifdef WCHAR |
| 7013 | +# define STORE_NUMBER(destination, number) \ |
| 7014 | + do { \ |
| 7015 | + *(destination) = (UCHAR_T)(number); \ |
| 7016 | + } while (0) |
| 7017 | +# else /* BYTE */ |
| 7018 | +# define STORE_NUMBER(destination, number) \ |
| 7019 | + do { \ |
| 7020 | + (destination)[0] = (number) & 0377; \ |
| 7021 | + (destination)[1] = (number) >> 8; \ |
| 7022 | + } while (0) |
| 7023 | +# endif /* WCHAR */ |
| 7024 | + |
| 7025 | +/* Same as STORE_NUMBER, except increment DESTINATION to |
| 7026 | + the byte after where the number is stored. Therefore, DESTINATION |
| 7027 | + must be an lvalue. */ |
| 7028 | +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ |
| 7029 | + |
| 7030 | +# define STORE_NUMBER_AND_INCR(destination, number) \ |
| 7031 | + do { \ |
| 7032 | + STORE_NUMBER (destination, number); \ |
| 7033 | + (destination) += OFFSET_ADDRESS_SIZE; \ |
| 7034 | + } while (0) |
| 7035 | + |
| 7036 | +/* Put into DESTINATION a number stored in two contiguous bytes starting |
| 7037 | + at SOURCE. */ |
| 7038 | +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ |
| 7039 | + |
| 7040 | +# ifdef WCHAR |
| 7041 | +# define EXTRACT_NUMBER(destination, source) \ |
| 7042 | + do { \ |
| 7043 | + (destination) = *(source); \ |
| 7044 | + } while (0) |
| 7045 | +# else /* BYTE */ |
| 7046 | +# define EXTRACT_NUMBER(destination, source) \ |
| 7047 | + do { \ |
| 7048 | + (destination) = *(source) & 0377; \ |
| 7049 | + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ |
| 7050 | + } while (0) |
| 7051 | +# endif |
| 7052 | + |
| 7053 | +# ifdef DEBUG |
| 7054 | +static void PREFIX(extract_number) (int *dest, UCHAR_T *source); |
| 7055 | +static void |
| 7056 | +PREFIX(extract_number) (int *dest, UCHAR_T *source) |
| 7057 | +{ |
| 7058 | +# ifdef WCHAR |
| 7059 | + *dest = *source; |
| 7060 | +# else /* BYTE */ |
| 7061 | + int temp = SIGN_EXTEND_CHAR (*(source + 1)); |
| 7062 | + *dest = *source & 0377; |
| 7063 | + *dest += temp << 8; |
| 7064 | +# endif |
| 7065 | +} |
| 7066 | + |
| 7067 | +# ifndef EXTRACT_MACROS /* To debug the macros. */ |
| 7068 | +# undef EXTRACT_NUMBER |
| 7069 | +# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) |
| 7070 | +# endif /* not EXTRACT_MACROS */ |
| 7071 | + |
| 7072 | +# endif /* DEBUG */ |
| 7073 | + |
| 7074 | +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. |
| 7075 | + SOURCE must be an lvalue. */ |
| 7076 | + |
| 7077 | +# define EXTRACT_NUMBER_AND_INCR(destination, source) \ |
| 7078 | + do { \ |
| 7079 | + EXTRACT_NUMBER (destination, source); \ |
| 7080 | + (source) += OFFSET_ADDRESS_SIZE; \ |
| 7081 | + } while (0) |
| 7082 | + |
| 7083 | +# ifdef DEBUG |
| 7084 | +static void PREFIX(extract_number_and_incr) (int *destination, |
| 7085 | + UCHAR_T **source); |
| 7086 | +static void |
| 7087 | +PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source) |
| 7088 | +{ |
| 7089 | + PREFIX(extract_number) (destination, *source); |
| 7090 | + *source += OFFSET_ADDRESS_SIZE; |
| 7091 | +} |
| 7092 | + |
| 7093 | +# ifndef EXTRACT_MACROS |
| 7094 | +# undef EXTRACT_NUMBER_AND_INCR |
| 7095 | +# define EXTRACT_NUMBER_AND_INCR(dest, src) \ |
| 7096 | + PREFIX(extract_number_and_incr) (&dest, &src) |
| 7097 | +# endif /* not EXTRACT_MACROS */ |
| 7098 | + |
| 7099 | +# endif /* DEBUG */ |
| 7100 | + |
| 7101 | + |
| 7102 | + |
| 7103 | +/* If DEBUG is defined, Regex prints many voluminous messages about what |
| 7104 | + it is doing (if the variable `debug' is nonzero). If linked with the |
| 7105 | + main program in `iregex.c', you can enter patterns and strings |
| 7106 | + interactively. And if linked with the main program in `main.c' and |
| 7107 | + the other test files, you can run the already-written tests. */ |
| 7108 | + |
| 7109 | +# ifdef DEBUG |
| 7110 | + |
| 7111 | +# ifndef DEFINED_ONCE |
| 7112 | + |
| 7113 | +/* We use standard I/O for debugging. */ |
| 7114 | +# include <stdio.h> |
| 7115 | + |
| 7116 | +/* It is useful to test things that ``must'' be true when debugging. */ |
| 7117 | +# include <assert.h> |
| 7118 | + |
| 7119 | +static int debug; |
| 7120 | + |
| 7121 | +# define DEBUG_STATEMENT(e) e |
| 7122 | +# define DEBUG_PRINT1(x) if (debug) printf (x) |
| 7123 | +# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) |
| 7124 | +# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) |
| 7125 | +# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) |
| 7126 | +# endif /* not DEFINED_ONCE */ |
| 7127 | + |
| 7128 | +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ |
| 7129 | + if (debug) PREFIX(print_partial_compiled_pattern) (s, e) |
| 7130 | +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ |
| 7131 | + if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) |
| 7132 | + |
| 7133 | + |
| 7134 | +/* Print the fastmap in human-readable form. */ |
| 7135 | + |
| 7136 | +# ifndef DEFINED_ONCE |
| 7137 | +void |
| 7138 | +print_fastmap (char *fastmap) |
| 7139 | +{ |
| 7140 | + unsigned was_a_range = 0; |
| 7141 | + unsigned i = 0; |
| 7142 | + |
| 7143 | + while (i < (1 << BYTEWIDTH)) |
| 7144 | + { |
| 7145 | + if (fastmap[i++]) |
| 7146 | + { |
| 7147 | + was_a_range = 0; |
| 7148 | + putchar (i - 1); |
| 7149 | + while (i < (1 << BYTEWIDTH) && fastmap[i]) |
| 7150 | + { |
| 7151 | + was_a_range = 1; |
| 7152 | + i++; |
| 7153 | + } |
| 7154 | + if (was_a_range) |
| 7155 | + { |
| 7156 | + printf ("-"); |
| 7157 | + putchar (i - 1); |
| 7158 | + } |
| 7159 | + } |
| 7160 | + } |
| 7161 | + putchar ('\n'); |
| 7162 | +} |
| 7163 | +# endif /* not DEFINED_ONCE */ |
| 7164 | + |
| 7165 | + |
| 7166 | +/* Print a compiled pattern string in human-readable form, starting at |
| 7167 | + the START pointer into it and ending just before the pointer END. */ |
| 7168 | + |
| 7169 | +void |
| 7170 | +PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end) |
| 7171 | +{ |
| 7172 | + int mcnt, mcnt2; |
| 7173 | + UCHAR_T *p1; |
| 7174 | + UCHAR_T *p = start; |
| 7175 | + UCHAR_T *pend = end; |
| 7176 | + |
| 7177 | + if (start == NULL) |
| 7178 | + { |
| 7179 | + printf ("(null)\n"); |
| 7180 | + return; |
| 7181 | + } |
| 7182 | + |
| 7183 | + /* Loop over pattern commands. */ |
| 7184 | + while (p < pend) |
| 7185 | + { |
| 7186 | +# ifdef _LIBC |
| 7187 | + printf ("%td:\t", p - start); |
| 7188 | +# else |
| 7189 | + printf ("%ld:\t", (long int) (p - start)); |
| 7190 | +# endif |
| 7191 | + |
| 7192 | + switch ((re_opcode_t) *p++) |
| 7193 | + { |
| 7194 | + case no_op: |
| 7195 | + printf ("/no_op"); |
| 7196 | + break; |
| 7197 | + |
| 7198 | + case exactn: |
| 7199 | + mcnt = *p++; |
| 7200 | + printf ("/exactn/%d", mcnt); |
| 7201 | + do |
| 7202 | + { |
| 7203 | + putchar ('/'); |
| 7204 | + PUT_CHAR (*p++); |
| 7205 | + } |
| 7206 | + while (--mcnt); |
| 7207 | + break; |
| 7208 | + |
| 7209 | +# ifdef MBS_SUPPORT |
| 7210 | + case exactn_bin: |
| 7211 | + mcnt = *p++; |
| 7212 | + printf ("/exactn_bin/%d", mcnt); |
| 7213 | + do |
| 7214 | + { |
| 7215 | + printf("/%lx", (long int) *p++); |
| 7216 | + } |
| 7217 | + while (--mcnt); |
| 7218 | + break; |
| 7219 | +# endif /* MBS_SUPPORT */ |
| 7220 | + |
| 7221 | + case start_memory: |
| 7222 | + mcnt = *p++; |
| 7223 | + printf ("/start_memory/%d/%ld", mcnt, (long int) *p++); |
| 7224 | + break; |
| 7225 | + |
| 7226 | + case stop_memory: |
| 7227 | + mcnt = *p++; |
| 7228 | + printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++); |
| 7229 | + break; |
| 7230 | + |
| 7231 | + case duplicate: |
| 7232 | + printf ("/duplicate/%ld", (long int) *p++); |
| 7233 | + break; |
| 7234 | + |
| 7235 | + case anychar: |
| 7236 | + printf ("/anychar"); |
| 7237 | + break; |
| 7238 | + |
| 7239 | + case charset: |
| 7240 | + case charset_not: |
| 7241 | + { |
| 7242 | +# ifdef WCHAR |
| 7243 | + int i, length; |
| 7244 | + wchar_t *workp = p; |
| 7245 | + printf ("/charset [%s", |
| 7246 | + (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); |
| 7247 | + p += 5; |
| 7248 | + length = *workp++; /* the length of char_classes */ |
| 7249 | + for (i=0 ; i<length ; i++) |
| 7250 | + printf("[:%lx:]", (long int) *p++); |
| 7251 | + length = *workp++; /* the length of collating_symbol */ |
| 7252 | + for (i=0 ; i<length ;) |
| 7253 | + { |
| 7254 | + printf("[."); |
| 7255 | + while(*p != 0) |
| 7256 | + PUT_CHAR((i++,*p++)); |
| 7257 | + i++,p++; |
| 7258 | + printf(".]"); |
| 7259 | + } |
| 7260 | + length = *workp++; /* the length of equivalence_class */ |
| 7261 | + for (i=0 ; i<length ;) |
| 7262 | + { |
| 7263 | + printf("[="); |
| 7264 | + while(*p != 0) |
| 7265 | + PUT_CHAR((i++,*p++)); |
| 7266 | + i++,p++; |
| 7267 | + printf("=]"); |
| 7268 | + } |
| 7269 | + length = *workp++; /* the length of char_range */ |
| 7270 | + for (i=0 ; i<length ; i++) |
| 7271 | + { |
| 7272 | + wchar_t range_start = *p++; |
| 7273 | + wchar_t range_end = *p++; |
| 7274 | + printf("%C-%C", range_start, range_end); |
| 7275 | + } |
| 7276 | + length = *workp++; /* the length of char */ |
| 7277 | + for (i=0 ; i<length ; i++) |
| 7278 | + printf("%C", *p++); |
| 7279 | + putchar (']'); |
| 7280 | +# else |
| 7281 | + register int c, last = -100; |
| 7282 | + register int in_range = 0; |
| 7283 | + |
| 7284 | + printf ("/charset [%s", |
| 7285 | + (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); |
| 7286 | + |
| 7287 | + assert (p + *p < pend); |
| 7288 | + |
| 7289 | + for (c = 0; c < 256; c++) |
| 7290 | + if (c / 8 < *p |
| 7291 | + && (p[1 + (c/8)] & (1 << (c % 8)))) |
| 7292 | + { |
| 7293 | + /* Are we starting a range? */ |
| 7294 | + if (last + 1 == c && ! in_range) |
| 7295 | + { |
| 7296 | + putchar ('-'); |
| 7297 | + in_range = 1; |
| 7298 | + } |
| 7299 | + /* Have we broken a range? */ |
| 7300 | + else if (last + 1 != c && in_range) |
| 7301 | + { |
| 7302 | + putchar (last); |
| 7303 | + in_range = 0; |
| 7304 | + } |
| 7305 | + |
| 7306 | + if (! in_range) |
| 7307 | + putchar (c); |
| 7308 | + |
| 7309 | + last = c; |
| 7310 | + } |
| 7311 | + |
| 7312 | + if (in_range) |
| 7313 | + putchar (last); |
| 7314 | + |
| 7315 | + putchar (']'); |
| 7316 | + |
| 7317 | + p += 1 + *p; |
| 7318 | +# endif /* WCHAR */ |
| 7319 | + } |
| 7320 | + break; |
| 7321 | + |
| 7322 | + case begline: |
| 7323 | + printf ("/begline"); |
| 7324 | + break; |
| 7325 | + |
| 7326 | + case endline: |
| 7327 | + printf ("/endline"); |
| 7328 | + break; |
| 7329 | + |
| 7330 | + case on_failure_jump: |
| 7331 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7332 | +# ifdef _LIBC |
| 7333 | + printf ("/on_failure_jump to %td", p + mcnt - start); |
| 7334 | +# else |
| 7335 | + printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start)); |
| 7336 | +# endif |
| 7337 | + break; |
| 7338 | + |
| 7339 | + case on_failure_keep_string_jump: |
| 7340 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7341 | +# ifdef _LIBC |
| 7342 | + printf ("/on_failure_keep_string_jump to %td", p + mcnt - start); |
| 7343 | +# else |
| 7344 | + printf ("/on_failure_keep_string_jump to %ld", |
| 7345 | + (long int) (p + mcnt - start)); |
| 7346 | +# endif |
| 7347 | + break; |
| 7348 | + |
| 7349 | + case dummy_failure_jump: |
| 7350 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7351 | +# ifdef _LIBC |
| 7352 | + printf ("/dummy_failure_jump to %td", p + mcnt - start); |
| 7353 | +# else |
| 7354 | + printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start)); |
| 7355 | +# endif |
| 7356 | + break; |
| 7357 | + |
| 7358 | + case push_dummy_failure: |
| 7359 | + printf ("/push_dummy_failure"); |
| 7360 | + break; |
| 7361 | + |
| 7362 | + case maybe_pop_jump: |
| 7363 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7364 | +# ifdef _LIBC |
| 7365 | + printf ("/maybe_pop_jump to %td", p + mcnt - start); |
| 7366 | +# else |
| 7367 | + printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start)); |
| 7368 | +# endif |
| 7369 | + break; |
| 7370 | + |
| 7371 | + case pop_failure_jump: |
| 7372 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7373 | +# ifdef _LIBC |
| 7374 | + printf ("/pop_failure_jump to %td", p + mcnt - start); |
| 7375 | +# else |
| 7376 | + printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start)); |
| 7377 | +# endif |
| 7378 | + break; |
| 7379 | + |
| 7380 | + case jump_past_alt: |
| 7381 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7382 | +# ifdef _LIBC |
| 7383 | + printf ("/jump_past_alt to %td", p + mcnt - start); |
| 7384 | +# else |
| 7385 | + printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start)); |
| 7386 | +# endif |
| 7387 | + break; |
| 7388 | + |
| 7389 | + case jump: |
| 7390 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7391 | +# ifdef _LIBC |
| 7392 | + printf ("/jump to %td", p + mcnt - start); |
| 7393 | +# else |
| 7394 | + printf ("/jump to %ld", (long int) (p + mcnt - start)); |
| 7395 | +# endif |
| 7396 | + break; |
| 7397 | + |
| 7398 | + case succeed_n: |
| 7399 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7400 | + p1 = p + mcnt; |
| 7401 | + PREFIX(extract_number_and_incr) (&mcnt2, &p); |
| 7402 | +# ifdef _LIBC |
| 7403 | + printf ("/succeed_n to %td, %d times", p1 - start, mcnt2); |
| 7404 | +# else |
| 7405 | + printf ("/succeed_n to %ld, %d times", |
| 7406 | + (long int) (p1 - start), mcnt2); |
| 7407 | +# endif |
| 7408 | + break; |
| 7409 | + |
| 7410 | + case jump_n: |
| 7411 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7412 | + p1 = p + mcnt; |
| 7413 | + PREFIX(extract_number_and_incr) (&mcnt2, &p); |
| 7414 | + printf ("/jump_n to %d, %d times", p1 - start, mcnt2); |
| 7415 | + break; |
| 7416 | + |
| 7417 | + case set_number_at: |
| 7418 | + PREFIX(extract_number_and_incr) (&mcnt, &p); |
| 7419 | + p1 = p + mcnt; |
| 7420 | + PREFIX(extract_number_and_incr) (&mcnt2, &p); |
| 7421 | +# ifdef _LIBC |
| 7422 | + printf ("/set_number_at location %td to %d", p1 - start, mcnt2); |
| 7423 | +# else |
| 7424 | + printf ("/set_number_at location %ld to %d", |
| 7425 | + (long int) (p1 - start), mcnt2); |
| 7426 | +# endif |
| 7427 | + break; |
| 7428 | + |
| 7429 | + case wordbound: |
| 7430 | + printf ("/wordbound"); |
| 7431 | + break; |
| 7432 | + |
| 7433 | + case notwordbound: |
| 7434 | + printf ("/notwordbound"); |
| 7435 | + break; |
| 7436 | + |
| 7437 | + case wordbeg: |
| 7438 | + printf ("/wordbeg"); |
| 7439 | + break; |
| 7440 | + |
| 7441 | + case wordend: |
| 7442 | + printf ("/wordend"); |
| 7443 | + break; |
| 7444 | + |
| 7445 | +# ifdef emacs |
| 7446 | + case before_dot: |
| 7447 | + printf ("/before_dot"); |
| 7448 | + break; |
| 7449 | + |
| 7450 | + case at_dot: |
| 7451 | + printf ("/at_dot"); |
| 7452 | + break; |
| 7453 | + |
| 7454 | + case after_dot: |
| 7455 | + printf ("/after_dot"); |
| 7456 | + break; |
| 7457 | + |
| 7458 | + case syntaxspec: |
| 7459 | + printf ("/syntaxspec"); |
| 7460 | + mcnt = *p++; |
| 7461 | + printf ("/%d", mcnt); |
| 7462 | + break; |
| 7463 | + |
| 7464 | + case notsyntaxspec: |
| 7465 | + printf ("/notsyntaxspec"); |
| 7466 | + mcnt = *p++; |
| 7467 | + printf ("/%d", mcnt); |
| 7468 | + break; |
| 7469 | +# endif /* emacs */ |
| 7470 | + |
| 7471 | + case wordchar: |
| 7472 | + printf ("/wordchar"); |
| 7473 | + break; |
| 7474 | + |
| 7475 | + case notwordchar: |
| 7476 | + printf ("/notwordchar"); |
| 7477 | + break; |
| 7478 | + |
| 7479 | + case begbuf: |
| 7480 | + printf ("/begbuf"); |
| 7481 | + break; |
| 7482 | + |
| 7483 | + case endbuf: |
| 7484 | + printf ("/endbuf"); |
| 7485 | + break; |
| 7486 | + |
| 7487 | + default: |
| 7488 | + printf ("?%ld", (long int) *(p-1)); |
| 7489 | + } |
| 7490 | + |
| 7491 | + putchar ('\n'); |
| 7492 | + } |
| 7493 | + |
| 7494 | +# ifdef _LIBC |
| 7495 | + printf ("%td:\tend of pattern.\n", p - start); |
| 7496 | +# else |
| 7497 | + printf ("%ld:\tend of pattern.\n", (long int) (p - start)); |
| 7498 | +# endif |
| 7499 | +} |
| 7500 | + |
| 7501 | + |
| 7502 | +void |
| 7503 | +PREFIX(print_compiled_pattern) (struct re_pattern_buffer *bufp) |
| 7504 | +{ |
| 7505 | + UCHAR_T *buffer = (UCHAR_T*) bufp->buffer; |
| 7506 | + |
| 7507 | + PREFIX(print_partial_compiled_pattern) (buffer, buffer |
| 7508 | + + bufp->used / sizeof(UCHAR_T)); |
| 7509 | + printf ("%ld bytes used/%ld bytes allocated.\n", |
| 7510 | + bufp->used, bufp->allocated); |
| 7511 | + |
| 7512 | + if (bufp->fastmap_accurate && bufp->fastmap) |
| 7513 | + { |
| 7514 | + printf ("fastmap: "); |
| 7515 | + print_fastmap (bufp->fastmap); |
| 7516 | + } |
| 7517 | + |
| 7518 | +# ifdef _LIBC |
| 7519 | + printf ("re_nsub: %Zd\t", bufp->re_nsub); |
| 7520 | +# else |
| 7521 | + printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); |
| 7522 | +# endif |
| 7523 | + printf ("regs_alloc: %d\t", bufp->regs_allocated); |
| 7524 | + printf ("can_be_null: %d\t", bufp->can_be_null); |
| 7525 | + printf ("newline_anchor: %d\n", bufp->newline_anchor); |
| 7526 | + printf ("no_sub: %d\t", bufp->no_sub); |
| 7527 | + printf ("not_bol: %d\t", bufp->not_bol); |
| 7528 | + printf ("not_eol: %d\t", bufp->not_eol); |
| 7529 | + printf ("syntax: %lx\n", bufp->syntax); |
| 7530 | + /* Perhaps we should print the translate table? */ |
| 7531 | +} |
| 7532 | + |
| 7533 | + |
| 7534 | +void |
| 7535 | +PREFIX(print_double_string) (const CHAR_T *where, const CHAR_T *string1, |
| 7536 | + int size1, const CHAR_T *string2, int size2) |
| 7537 | +{ |
| 7538 | + int this_char; |
| 7539 | + |
| 7540 | + if (where == NULL) |
| 7541 | + printf ("(null)"); |
| 7542 | + else |
| 7543 | + { |
| 7544 | + int cnt; |
| 7545 | + |
| 7546 | + if (FIRST_STRING_P (where)) |
| 7547 | + { |
| 7548 | + for (this_char = where - string1; this_char < size1; this_char++) |
| 7549 | + PUT_CHAR (string1[this_char]); |
| 7550 | + |
| 7551 | + where = string2; |
| 7552 | + } |
| 7553 | + |
| 7554 | + cnt = 0; |
| 7555 | + for (this_char = where - string2; this_char < size2; this_char++) |
| 7556 | + { |
| 7557 | + PUT_CHAR (string2[this_char]); |
| 7558 | + if (++cnt > 100) |
| 7559 | + { |
| 7560 | + fputs ("...", stdout); |
| 7561 | + break; |
| 7562 | + } |
| 7563 | + } |
| 7564 | + } |
| 7565 | +} |
| 7566 | + |
| 7567 | +# ifndef DEFINED_ONCE |
| 7568 | +void |
| 7569 | +printchar (int c) |
| 7570 | +{ |
| 7571 | + putc (c, stderr); |
| 7572 | +} |
| 7573 | +# endif |
| 7574 | + |
| 7575 | +# else /* not DEBUG */ |
| 7576 | + |
| 7577 | +# ifndef DEFINED_ONCE |
| 7578 | +# undef assert |
| 7579 | +# define assert(e) |
| 7580 | + |
| 7581 | +# define DEBUG_STATEMENT(e) |
| 7582 | +# define DEBUG_PRINT1(x) |
| 7583 | +# define DEBUG_PRINT2(x1, x2) |
| 7584 | +# define DEBUG_PRINT3(x1, x2, x3) |
| 7585 | +# define DEBUG_PRINT4(x1, x2, x3, x4) |
| 7586 | +# endif /* not DEFINED_ONCE */ |
| 7587 | +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) |
| 7588 | +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) |
| 7589 | + |
| 7590 | +# endif /* not DEBUG */ |
| 7591 | + |
| 7592 | + |
| 7593 | + |
| 7594 | +# ifdef WCHAR |
| 7595 | +/* This convert a multibyte string to a wide character string. |
| 7596 | + And write their correspondances to offset_buffer(see below) |
| 7597 | + and write whether each wchar_t is binary data to is_binary. |
| 7598 | + This assume invalid multibyte sequences as binary data. |
| 7599 | + We assume offset_buffer and is_binary is already allocated |
| 7600 | + enough space. */ |
| 7601 | + |
| 7602 | +static size_t convert_mbs_to_wcs (CHAR_T *dest, const unsigned char* src, |
| 7603 | + size_t len, int *offset_buffer, |
| 7604 | + char *is_binary); |
| 7605 | +static size_t |
| 7606 | +convert_mbs_to_wcs (CHAR_T *dest, const unsigned char*src, size_t len, |
| 7607 | + int *offset_buffer, char *is_binary) |
| 7608 | + /* It hold correspondances between src(char string) and |
| 7609 | + dest(wchar_t string) for optimization. |
| 7610 | + e.g. src = "xxxyzz" |
| 7611 | + dest = {'X', 'Y', 'Z'} |
| 7612 | + (each "xxx", "y" and "zz" represent one multibyte character |
| 7613 | + corresponding to 'X', 'Y' and 'Z'.) |
| 7614 | + offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} |
| 7615 | + = {0, 3, 4, 6} |
| 7616 | + */ |
| 7617 | +{ |
| 7618 | + wchar_t *pdest = dest; |
| 7619 | + const unsigned char *psrc = src; |
| 7620 | + size_t wc_count = 0; |
| 7621 | + |
| 7622 | + mbstate_t mbs; |
| 7623 | + int i, consumed; |
| 7624 | + size_t mb_remain = len; |
| 7625 | + size_t mb_count = 0; |
| 7626 | + |
| 7627 | + /* Initialize the conversion state. */ |
| 7628 | + memset (&mbs, 0, sizeof (mbstate_t)); |
| 7629 | + |
| 7630 | + offset_buffer[0] = 0; |
| 7631 | + for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, |
| 7632 | + psrc += consumed) |
| 7633 | + { |
| 7634 | +#ifdef _LIBC |
| 7635 | + consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs); |
| 7636 | +#else |
| 7637 | + consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); |
| 7638 | +#endif |
| 7639 | + |
| 7640 | + if (consumed <= 0) |
| 7641 | + /* failed to convert. maybe src contains binary data. |
| 7642 | + So we consume 1 byte manualy. */ |
| 7643 | + { |
| 7644 | + *pdest = *psrc; |
| 7645 | + consumed = 1; |
| 7646 | + is_binary[wc_count] = TRUE; |
| 7647 | + } |
| 7648 | + else |
| 7649 | + is_binary[wc_count] = FALSE; |
| 7650 | + /* In sjis encoding, we use yen sign as escape character in |
| 7651 | + place of reverse solidus. So we convert 0x5c(yen sign in |
| 7652 | + sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse |
| 7653 | + solidus in UCS2). */ |
| 7654 | + if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) |
| 7655 | + *pdest = (wchar_t) *psrc; |
| 7656 | + |
| 7657 | + offset_buffer[wc_count + 1] = mb_count += consumed; |
| 7658 | + } |
| 7659 | + |
| 7660 | + /* Fill remain of the buffer with sentinel. */ |
| 7661 | + for (i = wc_count + 1 ; i <= len ; i++) |
| 7662 | + offset_buffer[i] = mb_count + 1; |
| 7663 | + |
| 7664 | + return wc_count; |
| 7665 | +} |
| 7666 | + |
| 7667 | +# endif /* WCHAR */ |
| 7668 | + |
| 7669 | +#else /* not INSIDE_RECURSION */ |
| 7670 | + |
| 7671 | +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can |
| 7672 | + also be assigned to arbitrarily: each pattern buffer stores its own |
| 7673 | + syntax, so it can be changed between regex compilations. */ |
| 7674 | +/* This has no initializer because initialized variables in Emacs |
| 7675 | + become read-only after dumping. */ |
| 7676 | +reg_syntax_t re_syntax_options; |
| 7677 | + |
| 7678 | + |
| 7679 | +/* Specify the precise syntax of regexps for compilation. This provides |
| 7680 | + for compatibility for various utilities which historically have |
| 7681 | + different, incompatible syntaxes. |
| 7682 | + |
| 7683 | + The argument SYNTAX is a bit mask comprised of the various bits |
| 7684 | + defined in regex.h. We return the old syntax. */ |
| 7685 | + |
| 7686 | +reg_syntax_t |
| 7687 | +re_set_syntax (reg_syntax_t syntax) |
| 7688 | +{ |
| 7689 | + reg_syntax_t ret = re_syntax_options; |
| 7690 | + |
| 7691 | + re_syntax_options = syntax; |
| 7692 | +# ifdef DEBUG |
| 7693 | + if (syntax & RE_DEBUG) |
| 7694 | + debug = 1; |
| 7695 | + else if (debug) /* was on but now is not */ |
| 7696 | + debug = 0; |
| 7697 | +# endif /* DEBUG */ |
| 7698 | + return ret; |
| 7699 | +} |
| 7700 | +# ifdef _LIBC |
| 7701 | +weak_alias (__re_set_syntax, re_set_syntax) |
| 7702 | +# endif |
| 7703 | + |
| 7704 | +/* This table gives an error message for each of the error codes listed |
| 7705 | + in regex.h. Obviously the order here has to be same as there. |
| 7706 | + POSIX doesn't require that we do anything for REG_NOERROR, |
| 7707 | + but why not be nice? */ |
| 7708 | + |
| 7709 | +static const char *re_error_msgid[] = |
| 7710 | + { |
| 7711 | + gettext_noop ("Success"), /* REG_NOERROR */ |
| 7712 | + gettext_noop ("No match"), /* REG_NOMATCH */ |
| 7713 | + gettext_noop ("Invalid regular expression"), /* REG_BADPAT */ |
| 7714 | + gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */ |
| 7715 | + gettext_noop ("Invalid character class name"), /* REG_ECTYPE */ |
| 7716 | + gettext_noop ("Trailing backslash"), /* REG_EESCAPE */ |
| 7717 | + gettext_noop ("Invalid back reference"), /* REG_ESUBREG */ |
| 7718 | + gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */ |
| 7719 | + gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */ |
| 7720 | + gettext_noop ("Unmatched \\{"), /* REG_EBRACE */ |
| 7721 | + gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */ |
| 7722 | + gettext_noop ("Invalid range end"), /* REG_ERANGE */ |
| 7723 | + gettext_noop ("Memory exhausted"), /* REG_ESPACE */ |
| 7724 | + gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */ |
| 7725 | + gettext_noop ("Premature end of regular expression"), /* REG_EEND */ |
| 7726 | + gettext_noop ("Regular expression too big"), /* REG_ESIZE */ |
| 7727 | + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ |
| 7728 | + }; |
| 7729 | + |
| 7730 | +#endif /* INSIDE_RECURSION */ |
| 7731 | + |
| 7732 | +#ifndef DEFINED_ONCE |
| 7733 | +/* Avoiding alloca during matching, to placate r_alloc. */ |
| 7734 | + |
| 7735 | +/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the |
| 7736 | + searching and matching functions should not call alloca. On some |
| 7737 | + systems, alloca is implemented in terms of malloc, and if we're |
| 7738 | + using the relocating allocator routines, then malloc could cause a |
| 7739 | + relocation, which might (if the strings being searched are in the |
| 7740 | + ralloc heap) shift the data out from underneath the regexp |
| 7741 | + routines. |
| 7742 | + |
| 7743 | + Here's another reason to avoid allocation: Emacs |
| 7744 | + processes input from X in a signal handler; processing X input may |
| 7745 | + call malloc; if input arrives while a matching routine is calling |
| 7746 | + malloc, then we're scrod. But Emacs can't just block input while |
| 7747 | + calling matching routines; then we don't notice interrupts when |
| 7748 | + they come in. So, Emacs blocks input around all regexp calls |
| 7749 | + except the matching calls, which it leaves unprotected, in the |
| 7750 | + faith that they will not malloc. */ |
| 7751 | + |
| 7752 | +/* Normally, this is fine. */ |
| 7753 | +# define MATCH_MAY_ALLOCATE |
| 7754 | + |
| 7755 | +/* When using GNU C, we are not REALLY using the C alloca, no matter |
| 7756 | + what config.h may say. So don't take precautions for it. */ |
| 7757 | +# ifdef __GNUC__ |
| 7758 | +# undef C_ALLOCA |
| 7759 | +# endif |
| 7760 | + |
| 7761 | +/* The match routines may not allocate if (1) they would do it with malloc |
| 7762 | + and (2) it's not safe for them to use malloc. |
| 7763 | + Note that if REL_ALLOC is defined, matching would not use malloc for the |
| 7764 | + failure stack, but we would still use it for the register vectors; |
| 7765 | + so REL_ALLOC should not affect this. */ |
| 7766 | +# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs |
| 7767 | +# undef MATCH_MAY_ALLOCATE |
| 7768 | +# endif |
| 7769 | +#endif /* not DEFINED_ONCE */ |
| 7770 | + |
| 7771 | +#ifdef INSIDE_RECURSION |
| 7772 | +/* Failure stack declarations and macros; both re_compile_fastmap and |
| 7773 | + re_match_2 use a failure stack. These have to be macros because of |
| 7774 | + REGEX_ALLOCATE_STACK. */ |
| 7775 | + |
| 7776 | + |
| 7777 | +/* Number of failure points for which to initially allocate space |
| 7778 | + when matching. If this number is exceeded, we allocate more |
| 7779 | + space, so it is not a hard limit. */ |
| 7780 | +# ifndef INIT_FAILURE_ALLOC |
| 7781 | +# define INIT_FAILURE_ALLOC 5 |
| 7782 | +# endif |
| 7783 | + |
| 7784 | +/* Roughly the maximum number of failure points on the stack. Would be |
| 7785 | + exactly that if always used MAX_FAILURE_ITEMS items each time we failed. |
| 7786 | + This is a variable only so users of regex can assign to it; we never |
| 7787 | + change it ourselves. */ |
| 7788 | + |
| 7789 | + |
| 7790 | +# ifndef DEFINED_ONCE |
| 7791 | + |
| 7792 | +# ifdef INT_IS_16BIT |
| 7793 | +# define RE_M_F_TYPE long int |
| 7794 | +# else |
| 7795 | +# define RE_M_F_TYPE int |
| 7796 | +# endif /* INT_IS_16BIT */ |
| 7797 | + |
| 7798 | +# ifdef MATCH_MAY_ALLOCATE |
| 7799 | +/* 4400 was enough to cause a crash on Alpha OSF/1, |
| 7800 | + whose default stack limit is 2mb. */ |
| 7801 | +# define RE_M_F_DEFAULT 4000 |
| 7802 | +# else |
| 7803 | +# define RE_M_F_DEFAULT 2000 |
| 7804 | +# endif /* MATCH_MAY_ALLOCATE */ |
| 7805 | + |
| 7806 | +# include <shlib-compat.h> |
| 7807 | + |
| 7808 | +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) |
| 7809 | +link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") |
| 7810 | +RE_M_F_TYPE re_max_failures = RE_M_F_DEFAULT; |
| 7811 | +# else |
| 7812 | +RE_M_F_TYPE re_max_failures attribute_hidden = RE_M_F_DEFAULT; |
| 7813 | +# endif /* SHLIB_COMPAT */ |
| 7814 | + |
| 7815 | +# undef RE_M_F_TYPE |
| 7816 | +# undef RE_M_F_DEFAULT |
| 7817 | + |
| 7818 | +# endif /* DEFINED_ONCE */ |
| 7819 | + |
| 7820 | +# ifdef INT_IS_16BIT |
| 7821 | + |
| 7822 | +union PREFIX(fail_stack_elt) |
| 7823 | +{ |
| 7824 | + UCHAR_T *pointer; |
| 7825 | + long int integer; |
| 7826 | +}; |
| 7827 | + |
| 7828 | +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); |
| 7829 | + |
| 7830 | +typedef struct |
| 7831 | +{ |
| 7832 | + PREFIX(fail_stack_elt_t) *stack; |
| 7833 | + unsigned long int size; |
| 7834 | + unsigned long int avail; /* Offset of next open position. */ |
| 7835 | +} PREFIX(fail_stack_type); |
| 7836 | + |
| 7837 | +# else /* not INT_IS_16BIT */ |
| 7838 | + |
| 7839 | +union PREFIX(fail_stack_elt) |
| 7840 | +{ |
| 7841 | + UCHAR_T *pointer; |
| 7842 | + int integer; |
| 7843 | +}; |
| 7844 | + |
| 7845 | +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); |
| 7846 | + |
| 7847 | +typedef struct |
| 7848 | +{ |
| 7849 | + PREFIX(fail_stack_elt_t) *stack; |
| 7850 | + unsigned size; |
| 7851 | + unsigned avail; /* Offset of next open position. */ |
| 7852 | +} PREFIX(fail_stack_type); |
| 7853 | + |
| 7854 | +# endif /* INT_IS_16BIT */ |
| 7855 | + |
| 7856 | +# ifndef DEFINED_ONCE |
| 7857 | +# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) |
| 7858 | +# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) |
| 7859 | +# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) |
| 7860 | +# endif |
| 7861 | + |
| 7862 | + |
| 7863 | +/* Define macros to initialize and free the failure stack. |
| 7864 | + Do `return -2' if the alloc fails. */ |
| 7865 | + |
| 7866 | +# ifdef MATCH_MAY_ALLOCATE |
| 7867 | +# define INIT_FAIL_STACK() \ |
| 7868 | + do { \ |
| 7869 | + fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ |
| 7870 | + REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ |
| 7871 | + \ |
| 7872 | + if (fail_stack.stack == NULL) \ |
| 7873 | + return -2; \ |
| 7874 | + \ |
| 7875 | + fail_stack.size = INIT_FAILURE_ALLOC; \ |
| 7876 | + fail_stack.avail = 0; \ |
| 7877 | + } while (0) |
| 7878 | + |
| 7879 | +# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) |
| 7880 | +# else |
| 7881 | +# define INIT_FAIL_STACK() \ |
| 7882 | + do { \ |
| 7883 | + fail_stack.avail = 0; \ |
| 7884 | + } while (0) |
| 7885 | + |
| 7886 | +# define RESET_FAIL_STACK() |
| 7887 | +# endif |
| 7888 | + |
| 7889 | + |
| 7890 | +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. |
| 7891 | + |
| 7892 | + Return 1 if succeeds, and 0 if either ran out of memory |
| 7893 | + allocating space for it or it was already too large. |
| 7894 | + |
| 7895 | + REGEX_REALLOCATE_STACK requires `destination' be declared. */ |
| 7896 | + |
| 7897 | +# define DOUBLE_FAIL_STACK(fail_stack) \ |
| 7898 | + ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ |
| 7899 | + ? 0 \ |
| 7900 | + : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ |
| 7901 | + REGEX_REALLOCATE_STACK ((fail_stack).stack, \ |
| 7902 | + (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ |
| 7903 | + ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ |
| 7904 | + \ |
| 7905 | + (fail_stack).stack == NULL \ |
| 7906 | + ? 0 \ |
| 7907 | + : ((fail_stack).size <<= 1, \ |
| 7908 | + 1))) |
| 7909 | + |
| 7910 | + |
| 7911 | +/* Push pointer POINTER on FAIL_STACK. |
| 7912 | + Return 1 if was able to do so and 0 if ran out of memory allocating |
| 7913 | + space to do so. */ |
| 7914 | +# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ |
| 7915 | + ((FAIL_STACK_FULL () \ |
| 7916 | + && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ |
| 7917 | + ? 0 \ |
| 7918 | + : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ |
| 7919 | + 1)) |
| 7920 | + |
| 7921 | +/* Push a pointer value onto the failure stack. |
| 7922 | + Assumes the variable `fail_stack'. Probably should only |
| 7923 | + be called from within `PUSH_FAILURE_POINT'. */ |
| 7924 | +# define PUSH_FAILURE_POINTER(item) \ |
| 7925 | + fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) |
| 7926 | + |
| 7927 | +/* This pushes an integer-valued item onto the failure stack. |
| 7928 | + Assumes the variable `fail_stack'. Probably should only |
| 7929 | + be called from within `PUSH_FAILURE_POINT'. */ |
| 7930 | +# define PUSH_FAILURE_INT(item) \ |
| 7931 | + fail_stack.stack[fail_stack.avail++].integer = (item) |
| 7932 | + |
| 7933 | +/* Push a fail_stack_elt_t value onto the failure stack. |
| 7934 | + Assumes the variable `fail_stack'. Probably should only |
| 7935 | + be called from within `PUSH_FAILURE_POINT'. */ |
| 7936 | +# define PUSH_FAILURE_ELT(item) \ |
| 7937 | + fail_stack.stack[fail_stack.avail++] = (item) |
| 7938 | + |
| 7939 | +/* These three POP... operations complement the three PUSH... operations. |
| 7940 | + All assume that `fail_stack' is nonempty. */ |
| 7941 | +# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer |
| 7942 | +# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer |
| 7943 | +# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] |
| 7944 | + |
| 7945 | +/* Used to omit pushing failure point id's when we're not debugging. */ |
| 7946 | +# ifdef DEBUG |
| 7947 | +# define DEBUG_PUSH PUSH_FAILURE_INT |
| 7948 | +# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () |
| 7949 | +# else |
| 7950 | +# define DEBUG_PUSH(item) |
| 7951 | +# define DEBUG_POP(item_addr) |
| 7952 | +# endif |
| 7953 | + |
| 7954 | + |
| 7955 | +/* Push the information about the state we will need |
| 7956 | + if we ever fail back to it. |
| 7957 | + |
| 7958 | + Requires variables fail_stack, regstart, regend, reg_info, and |
| 7959 | + num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' |
| 7960 | + be declared. |
| 7961 | + |
| 7962 | + Does `return FAILURE_CODE' if runs out of memory. */ |
| 7963 | + |
| 7964 | +# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ |
| 7965 | + do { \ |
| 7966 | + char *destination; \ |
| 7967 | + /* Must be int, so when we don't save any registers, the arithmetic \ |
| 7968 | + of 0 + -1 isn't done as unsigned. */ \ |
| 7969 | + /* Can't be int, since there is not a shred of a guarantee that int \ |
| 7970 | + is wide enough to hold a value of something to which pointer can \ |
| 7971 | + be assigned */ \ |
| 7972 | + active_reg_t this_reg; \ |
| 7973 | + \ |
| 7974 | + DEBUG_STATEMENT (failure_id++); \ |
| 7975 | + DEBUG_STATEMENT (nfailure_points_pushed++); \ |
| 7976 | + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ |
| 7977 | + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ |
| 7978 | + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ |
| 7979 | + \ |
| 7980 | + DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ |
| 7981 | + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ |
| 7982 | + \ |
| 7983 | + /* Ensure we have enough space allocated for what we will push. */ \ |
| 7984 | + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ |
| 7985 | + { \ |
| 7986 | + if (!DOUBLE_FAIL_STACK (fail_stack)) \ |
| 7987 | + return failure_code; \ |
| 7988 | + \ |
| 7989 | + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ |
| 7990 | + (fail_stack).size); \ |
| 7991 | + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ |
| 7992 | + } \ |
| 7993 | + \ |
| 7994 | + /* Push the info, starting with the registers. */ \ |
| 7995 | + DEBUG_PRINT1 ("\n"); \ |
| 7996 | + \ |
| 7997 | + if (1) \ |
| 7998 | + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ |
| 7999 | + this_reg++) \ |
| 8000 | + { \ |
| 8001 | + DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ |
| 8002 | + DEBUG_STATEMENT (num_regs_pushed++); \ |
| 8003 | + \ |
| 8004 | + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ |
| 8005 | + PUSH_FAILURE_POINTER (regstart[this_reg]); \ |
| 8006 | + \ |
| 8007 | + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ |
| 8008 | + PUSH_FAILURE_POINTER (regend[this_reg]); \ |
| 8009 | + \ |
| 8010 | + DEBUG_PRINT2 (" info: %p\n ", \ |
| 8011 | + reg_info[this_reg].word.pointer); \ |
| 8012 | + DEBUG_PRINT2 (" match_null=%d", \ |
| 8013 | + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ |
| 8014 | + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ |
| 8015 | + DEBUG_PRINT2 (" matched_something=%d", \ |
| 8016 | + MATCHED_SOMETHING (reg_info[this_reg])); \ |
| 8017 | + DEBUG_PRINT2 (" ever_matched=%d", \ |
| 8018 | + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ |
| 8019 | + DEBUG_PRINT1 ("\n"); \ |
| 8020 | + PUSH_FAILURE_ELT (reg_info[this_reg].word); \ |
| 8021 | + } \ |
| 8022 | + \ |
| 8023 | + DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ |
| 8024 | + PUSH_FAILURE_INT (lowest_active_reg); \ |
| 8025 | + \ |
| 8026 | + DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ |
| 8027 | + PUSH_FAILURE_INT (highest_active_reg); \ |
| 8028 | + \ |
| 8029 | + DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ |
| 8030 | + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ |
| 8031 | + PUSH_FAILURE_POINTER (pattern_place); \ |
| 8032 | + \ |
| 8033 | + DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ |
| 8034 | + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ |
| 8035 | + size2); \ |
| 8036 | + DEBUG_PRINT1 ("'\n"); \ |
| 8037 | + PUSH_FAILURE_POINTER (string_place); \ |
| 8038 | + \ |
| 8039 | + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ |
| 8040 | + DEBUG_PUSH (failure_id); \ |
| 8041 | + } while (0) |
| 8042 | + |
| 8043 | +# ifndef DEFINED_ONCE |
| 8044 | +/* This is the number of items that are pushed and popped on the stack |
| 8045 | + for each register. */ |
| 8046 | +# define NUM_REG_ITEMS 3 |
| 8047 | + |
| 8048 | +/* Individual items aside from the registers. */ |
| 8049 | +# ifdef DEBUG |
| 8050 | +# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ |
| 8051 | +# else |
| 8052 | +# define NUM_NONREG_ITEMS 4 |
| 8053 | +# endif |
| 8054 | + |
| 8055 | +/* We push at most this many items on the stack. */ |
| 8056 | +/* We used to use (num_regs - 1), which is the number of registers |
| 8057 | + this regexp will save; but that was changed to 5 |
| 8058 | + to avoid stack overflow for a regexp with lots of parens. */ |
| 8059 | +# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) |
| 8060 | + |
| 8061 | +/* We actually push this many items. */ |
| 8062 | +# define NUM_FAILURE_ITEMS \ |
| 8063 | + (((0 \ |
| 8064 | + ? 0 : highest_active_reg - lowest_active_reg + 1) \ |
| 8065 | + * NUM_REG_ITEMS) \ |
| 8066 | + + NUM_NONREG_ITEMS) |
| 8067 | + |
| 8068 | +/* How many items can still be added to the stack without overflowing it. */ |
| 8069 | +# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) |
| 8070 | +# endif /* not DEFINED_ONCE */ |
| 8071 | + |
| 8072 | + |
| 8073 | +/* Pops what PUSH_FAIL_STACK pushes. |
| 8074 | + |
| 8075 | + We restore into the parameters, all of which should be lvalues: |
| 8076 | + STR -- the saved data position. |
| 8077 | + PAT -- the saved pattern position. |
| 8078 | + LOW_REG, HIGH_REG -- the highest and lowest active registers. |
| 8079 | + REGSTART, REGEND -- arrays of string positions. |
| 8080 | + REG_INFO -- array of information about each subexpression. |
| 8081 | + |
| 8082 | + Also assumes the variables `fail_stack' and (if debugging), `bufp', |
| 8083 | + `pend', `string1', `size1', `string2', and `size2'. */ |
| 8084 | +# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ |
| 8085 | +{ \ |
| 8086 | + DEBUG_STATEMENT (unsigned failure_id;) \ |
| 8087 | + active_reg_t this_reg; \ |
| 8088 | + const UCHAR_T *string_temp; \ |
| 8089 | + \ |
| 8090 | + assert (!FAIL_STACK_EMPTY ()); \ |
| 8091 | + \ |
| 8092 | + /* Remove failure points and point to how many regs pushed. */ \ |
| 8093 | + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ |
| 8094 | + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ |
| 8095 | + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ |
| 8096 | + \ |
| 8097 | + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ |
| 8098 | + \ |
| 8099 | + DEBUG_POP (&failure_id); \ |
| 8100 | + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ |
| 8101 | + \ |
| 8102 | + /* If the saved string location is NULL, it came from an \ |
| 8103 | + on_failure_keep_string_jump opcode, and we want to throw away the \ |
| 8104 | + saved NULL, thus retaining our current position in the string. */ \ |
| 8105 | + string_temp = POP_FAILURE_POINTER (); \ |
| 8106 | + if (string_temp != NULL) \ |
| 8107 | + str = (const CHAR_T *) string_temp; \ |
| 8108 | + \ |
| 8109 | + DEBUG_PRINT2 (" Popping string %p: `", str); \ |
| 8110 | + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ |
| 8111 | + DEBUG_PRINT1 ("'\n"); \ |
| 8112 | + \ |
| 8113 | + pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ |
| 8114 | + DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ |
| 8115 | + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ |
| 8116 | + \ |
| 8117 | + /* Restore register info. */ \ |
| 8118 | + high_reg = (active_reg_t) POP_FAILURE_INT (); \ |
| 8119 | + DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ |
| 8120 | + \ |
| 8121 | + low_reg = (active_reg_t) POP_FAILURE_INT (); \ |
| 8122 | + DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ |
| 8123 | + \ |
| 8124 | + if (1) \ |
| 8125 | + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ |
| 8126 | + { \ |
| 8127 | + DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ |
| 8128 | + \ |
| 8129 | + reg_info[this_reg].word = POP_FAILURE_ELT (); \ |
| 8130 | + DEBUG_PRINT2 (" info: %p\n", \ |
| 8131 | + reg_info[this_reg].word.pointer); \ |
| 8132 | + \ |
| 8133 | + regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ |
| 8134 | + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ |
| 8135 | + \ |
| 8136 | + regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ |
| 8137 | + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ |
| 8138 | + } \ |
| 8139 | + else \ |
| 8140 | + { \ |
| 8141 | + for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ |
| 8142 | + { \ |
| 8143 | + reg_info[this_reg].word.integer = 0; \ |
| 8144 | + regend[this_reg] = 0; \ |
| 8145 | + regstart[this_reg] = 0; \ |
| 8146 | + } \ |
| 8147 | + highest_active_reg = high_reg; \ |
| 8148 | + } \ |
| 8149 | + \ |
| 8150 | + set_regs_matched_done = 0; \ |
| 8151 | + DEBUG_STATEMENT (nfailure_points_popped++); \ |
| 8152 | +} /* POP_FAILURE_POINT */ |
| 8153 | + |
| 8154 | +/* Structure for per-register (a.k.a. per-group) information. |
| 8155 | + Other register information, such as the |
| 8156 | + starting and ending positions (which are addresses), and the list of |
| 8157 | + inner groups (which is a bits list) are maintained in separate |
| 8158 | + variables. |
| 8159 | + |
| 8160 | + We are making a (strictly speaking) nonportable assumption here: that |
| 8161 | + the compiler will pack our bit fields into something that fits into |
| 8162 | + the type of `word', i.e., is something that fits into one item on the |
| 8163 | + failure stack. */ |
| 8164 | + |
| 8165 | + |
| 8166 | +/* Declarations and macros for re_match_2. */ |
| 8167 | + |
| 8168 | +typedef union |
| 8169 | +{ |
| 8170 | + PREFIX(fail_stack_elt_t) word; |
| 8171 | + struct |
| 8172 | + { |
| 8173 | + /* This field is one if this group can match the empty string, |
| 8174 | + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ |
| 8175 | +# define MATCH_NULL_UNSET_VALUE 3 |
| 8176 | + unsigned match_null_string_p : 2; |
| 8177 | + unsigned is_active : 1; |
| 8178 | + unsigned matched_something : 1; |
| 8179 | + unsigned ever_matched_something : 1; |
| 8180 | + } bits; |
| 8181 | +} PREFIX(register_info_type); |
| 8182 | + |
| 8183 | +# ifndef DEFINED_ONCE |
| 8184 | +# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) |
| 8185 | +# define IS_ACTIVE(R) ((R).bits.is_active) |
| 8186 | +# define MATCHED_SOMETHING(R) ((R).bits.matched_something) |
| 8187 | +# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) |
| 8188 | + |
| 8189 | + |
| 8190 | +/* Call this when have matched a real character; it sets `matched' flags |
| 8191 | + for the subexpressions which we are currently inside. Also records |
| 8192 | + that those subexprs have matched. */ |
| 8193 | +# define SET_REGS_MATCHED() \ |
| 8194 | + do \ |
| 8195 | + { \ |
| 8196 | + if (!set_regs_matched_done) \ |
| 8197 | + { \ |
| 8198 | + active_reg_t r; \ |
| 8199 | + set_regs_matched_done = 1; \ |
| 8200 | + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ |
| 8201 | + { \ |
| 8202 | + MATCHED_SOMETHING (reg_info[r]) \ |
| 8203 | + = EVER_MATCHED_SOMETHING (reg_info[r]) \ |
| 8204 | + = 1; \ |
| 8205 | + } \ |
| 8206 | + } \ |
| 8207 | + } \ |
| 8208 | + while (0) |
| 8209 | +# endif /* not DEFINED_ONCE */ |
| 8210 | + |
| 8211 | +/* Registers are set to a sentinel when they haven't yet matched. */ |
| 8212 | +static CHAR_T PREFIX(reg_unset_dummy); |
| 8213 | +# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) |
| 8214 | +# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) |
| 8215 | + |
| 8216 | +/* Subroutine declarations and macros for regex_compile. */ |
| 8217 | +static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg); |
| 8218 | +static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, |
| 8219 | + int arg1, int arg2); |
| 8220 | +static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, |
| 8221 | + int arg, UCHAR_T *end); |
| 8222 | +static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, |
| 8223 | + int arg1, int arg2, UCHAR_T *end); |
| 8224 | +static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern, |
| 8225 | + const CHAR_T *p, |
| 8226 | + reg_syntax_t syntax); |
| 8227 | +static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p, |
| 8228 | + const CHAR_T *pend, |
| 8229 | + reg_syntax_t syntax); |
| 8230 | +# ifdef WCHAR |
| 8231 | +static reg_errcode_t wcs_compile_range (CHAR_T range_start, |
| 8232 | + const CHAR_T **p_ptr, |
| 8233 | + const CHAR_T *pend, |
| 8234 | + char *translate, |
| 8235 | + reg_syntax_t syntax, |
| 8236 | + UCHAR_T *b, |
| 8237 | + CHAR_T *char_set); |
| 8238 | +static void insert_space (int num, CHAR_T *loc, CHAR_T *end); |
| 8239 | +# else /* BYTE */ |
| 8240 | +static reg_errcode_t byte_compile_range (unsigned int range_start, |
| 8241 | + const char **p_ptr, |
| 8242 | + const char *pend, |
| 8243 | + RE_TRANSLATE_TYPE translate, |
| 8244 | + reg_syntax_t syntax, |
| 8245 | + unsigned char *b); |
| 8246 | +# endif /* WCHAR */ |
| 8247 | + |
| 8248 | +/* Fetch the next character in the uncompiled pattern---translating it |
| 8249 | + if necessary. Also cast from a signed character in the constant |
| 8250 | + string passed to us by the user to an unsigned char that we can use |
| 8251 | + as an array index (in, e.g., `translate'). */ |
| 8252 | +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, |
| 8253 | + because it is impossible to allocate 4GB array for some encodings |
| 8254 | + which have 4 byte character_set like UCS4. */ |
| 8255 | +# ifndef PATFETCH |
| 8256 | +# ifdef WCHAR |
| 8257 | +# define PATFETCH(c) \ |
| 8258 | + do {if (p == pend) return REG_EEND; \ |
| 8259 | + c = (UCHAR_T) *p++; \ |
| 8260 | + if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ |
| 8261 | + } while (0) |
| 8262 | +# else /* BYTE */ |
| 8263 | +# define PATFETCH(c) \ |
| 8264 | + do {if (p == pend) return REG_EEND; \ |
| 8265 | + c = (unsigned char) *p++; \ |
| 8266 | + if (translate) c = (unsigned char) translate[c]; \ |
| 8267 | + } while (0) |
| 8268 | +# endif /* WCHAR */ |
| 8269 | +# endif |
| 8270 | + |
| 8271 | +/* Fetch the next character in the uncompiled pattern, with no |
| 8272 | + translation. */ |
| 8273 | +# define PATFETCH_RAW(c) \ |
| 8274 | + do {if (p == pend) return REG_EEND; \ |
| 8275 | + c = (UCHAR_T) *p++; \ |
| 8276 | + } while (0) |
| 8277 | + |
| 8278 | +/* Go backwards one character in the pattern. */ |
| 8279 | +# define PATUNFETCH p-- |
| 8280 | + |
| 8281 | + |
| 8282 | +/* If `translate' is non-null, return translate[D], else just D. We |
| 8283 | + cast the subscript to translate because some data is declared as |
| 8284 | + `char *', to avoid warnings when a string constant is passed. But |
| 8285 | + when we use a character as a subscript we must make it unsigned. */ |
| 8286 | +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, |
| 8287 | + because it is impossible to allocate 4GB array for some encodings |
| 8288 | + which have 4 byte character_set like UCS4. */ |
| 8289 | + |
| 8290 | +# ifndef TRANSLATE |
| 8291 | +# ifdef WCHAR |
| 8292 | +# define TRANSLATE(d) \ |
| 8293 | + ((translate && ((UCHAR_T) (d)) <= 0xff) \ |
| 8294 | + ? (char) translate[(unsigned char) (d)] : (d)) |
| 8295 | +# else /* BYTE */ |
| 8296 | +# define TRANSLATE(d) \ |
| 8297 | + (translate ? (char) translate[(unsigned char) (d)] : (char) (d)) |
| 8298 | +# endif /* WCHAR */ |
| 8299 | +# endif |
| 8300 | + |
| 8301 | + |
| 8302 | +/* Macros for outputting the compiled pattern into `buffer'. */ |
| 8303 | + |
| 8304 | +/* If the buffer isn't allocated when it comes in, use this. */ |
| 8305 | +# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) |
| 8306 | + |
| 8307 | +/* Make sure we have at least N more bytes of space in buffer. */ |
| 8308 | +# ifdef WCHAR |
| 8309 | +# define GET_BUFFER_SPACE(n) \ |
| 8310 | + while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ |
| 8311 | + + (n)*sizeof(CHAR_T)) > bufp->allocated) \ |
| 8312 | + EXTEND_BUFFER () |
| 8313 | +# else /* BYTE */ |
| 8314 | +# define GET_BUFFER_SPACE(n) \ |
| 8315 | + while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ |
| 8316 | + EXTEND_BUFFER () |
| 8317 | +# endif /* WCHAR */ |
| 8318 | + |
| 8319 | +/* Make sure we have one more byte of buffer space and then add C to it. */ |
| 8320 | +# define BUF_PUSH(c) \ |
| 8321 | + do { \ |
| 8322 | + GET_BUFFER_SPACE (1); \ |
| 8323 | + *b++ = (UCHAR_T) (c); \ |
| 8324 | + } while (0) |
| 8325 | + |
| 8326 | + |
| 8327 | +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ |
| 8328 | +# define BUF_PUSH_2(c1, c2) \ |
| 8329 | + do { \ |
| 8330 | + GET_BUFFER_SPACE (2); \ |
| 8331 | + *b++ = (UCHAR_T) (c1); \ |
| 8332 | + *b++ = (UCHAR_T) (c2); \ |
| 8333 | + } while (0) |
| 8334 | + |
| 8335 | + |
| 8336 | +/* As with BUF_PUSH_2, except for three bytes. */ |
| 8337 | +# define BUF_PUSH_3(c1, c2, c3) \ |
| 8338 | + do { \ |
| 8339 | + GET_BUFFER_SPACE (3); \ |
| 8340 | + *b++ = (UCHAR_T) (c1); \ |
| 8341 | + *b++ = (UCHAR_T) (c2); \ |
| 8342 | + *b++ = (UCHAR_T) (c3); \ |
| 8343 | + } while (0) |
| 8344 | + |
| 8345 | +/* Store a jump with opcode OP at LOC to location TO. We store a |
| 8346 | + relative address offset by the three bytes the jump itself occupies. */ |
| 8347 | +# define STORE_JUMP(op, loc, to) \ |
| 8348 | + PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) |
| 8349 | + |
| 8350 | +/* Likewise, for a two-argument jump. */ |
| 8351 | +# define STORE_JUMP2(op, loc, to, arg) \ |
| 8352 | + PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) |
| 8353 | + |
| 8354 | +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ |
| 8355 | +# define INSERT_JUMP(op, loc, to) \ |
| 8356 | + PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) |
| 8357 | + |
| 8358 | +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ |
| 8359 | +# define INSERT_JUMP2(op, loc, to, arg) \ |
| 8360 | + PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ |
| 8361 | + arg, b) |
| 8362 | + |
| 8363 | +/* This is not an arbitrary limit: the arguments which represent offsets |
| 8364 | + into the pattern are two bytes long. So if 2^16 bytes turns out to |
| 8365 | + be too small, many things would have to change. */ |
| 8366 | +/* Any other compiler which, like MSC, has allocation limit below 2^16 |
| 8367 | + bytes will have to use approach similar to what was done below for |
| 8368 | + MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up |
| 8369 | + reallocating to 0 bytes. Such thing is not going to work too well. |
| 8370 | + You have been warned!! */ |
| 8371 | +# ifndef DEFINED_ONCE |
| 8372 | +# if defined _MSC_VER && !defined WIN32 |
| 8373 | +/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. |
| 8374 | + The REALLOC define eliminates a flurry of conversion warnings, |
| 8375 | + but is not required. */ |
| 8376 | +# define MAX_BUF_SIZE 65500L |
| 8377 | +# define REALLOC(p,s) realloc ((p), (size_t) (s)) |
| 8378 | +# else |
| 8379 | +# define MAX_BUF_SIZE (1L << 16) |
| 8380 | +# define REALLOC(p,s) realloc ((p), (s)) |
| 8381 | +# endif |
| 8382 | + |
| 8383 | +/* Extend the buffer by twice its current size via realloc and |
| 8384 | + reset the pointers that pointed into the old block to point to the |
| 8385 | + correct places in the new one. If extending the buffer results in it |
| 8386 | + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ |
| 8387 | +# ifndef __BOUNDED_POINTERS__ |
| 8388 | +# define __BOUNDED_POINTERS__ 0 |
| 8389 | +# endif |
| 8390 | +# if __BOUNDED_POINTERS__ |
| 8391 | +# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) |
| 8392 | +# define MOVE_BUFFER_POINTER(P) \ |
| 8393 | + (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) |
| 8394 | +# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ |
| 8395 | + else \ |
| 8396 | + { \ |
| 8397 | + SET_HIGH_BOUND (b); \ |
| 8398 | + SET_HIGH_BOUND (begalt); \ |
| 8399 | + if (fixup_alt_jump) \ |
| 8400 | + SET_HIGH_BOUND (fixup_alt_jump); \ |
| 8401 | + if (laststart) \ |
| 8402 | + SET_HIGH_BOUND (laststart); \ |
| 8403 | + if (pending_exact) \ |
| 8404 | + SET_HIGH_BOUND (pending_exact); \ |
| 8405 | + } |
| 8406 | +# else |
| 8407 | +# define MOVE_BUFFER_POINTER(P) (P) += incr |
| 8408 | +# define ELSE_EXTEND_BUFFER_HIGH_BOUND |
| 8409 | +# endif |
| 8410 | +# endif /* not DEFINED_ONCE */ |
| 8411 | + |
| 8412 | +# ifdef WCHAR |
| 8413 | +# define EXTEND_BUFFER() \ |
| 8414 | + do { \ |
| 8415 | + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ |
| 8416 | + int wchar_count; \ |
| 8417 | + if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ |
| 8418 | + return REG_ESIZE; \ |
| 8419 | + bufp->allocated <<= 1; \ |
| 8420 | + if (bufp->allocated > MAX_BUF_SIZE) \ |
| 8421 | + bufp->allocated = MAX_BUF_SIZE; \ |
| 8422 | + /* How many characters the new buffer can have? */ \ |
| 8423 | + wchar_count = bufp->allocated / sizeof(UCHAR_T); \ |
| 8424 | + if (wchar_count == 0) wchar_count = 1; \ |
| 8425 | + /* Truncate the buffer to CHAR_T align. */ \ |
| 8426 | + bufp->allocated = wchar_count * sizeof(UCHAR_T); \ |
| 8427 | + RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ |
| 8428 | + bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ |
| 8429 | + if (COMPILED_BUFFER_VAR == NULL) \ |
| 8430 | + return REG_ESPACE; \ |
| 8431 | + /* If the buffer moved, move all the pointers into it. */ \ |
| 8432 | + if (old_buffer != COMPILED_BUFFER_VAR) \ |
| 8433 | + { \ |
| 8434 | + int incr = COMPILED_BUFFER_VAR - old_buffer; \ |
| 8435 | + MOVE_BUFFER_POINTER (b); \ |
| 8436 | + MOVE_BUFFER_POINTER (begalt); \ |
| 8437 | + if (fixup_alt_jump) \ |
| 8438 | + MOVE_BUFFER_POINTER (fixup_alt_jump); \ |
| 8439 | + if (laststart) \ |
| 8440 | + MOVE_BUFFER_POINTER (laststart); \ |
| 8441 | + if (pending_exact) \ |
| 8442 | + MOVE_BUFFER_POINTER (pending_exact); \ |
| 8443 | + } \ |
| 8444 | + ELSE_EXTEND_BUFFER_HIGH_BOUND \ |
| 8445 | + } while (0) |
| 8446 | +# else /* BYTE */ |
| 8447 | +# define EXTEND_BUFFER() \ |
| 8448 | + do { \ |
| 8449 | + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ |
| 8450 | + if (bufp->allocated == MAX_BUF_SIZE) \ |
| 8451 | + return REG_ESIZE; \ |
| 8452 | + bufp->allocated <<= 1; \ |
| 8453 | + if (bufp->allocated > MAX_BUF_SIZE) \ |
| 8454 | + bufp->allocated = MAX_BUF_SIZE; \ |
| 8455 | + bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \ |
| 8456 | + bufp->allocated); \ |
| 8457 | + if (COMPILED_BUFFER_VAR == NULL) \ |
| 8458 | + return REG_ESPACE; \ |
| 8459 | + /* If the buffer moved, move all the pointers into it. */ \ |
| 8460 | + if (old_buffer != COMPILED_BUFFER_VAR) \ |
| 8461 | + { \ |
| 8462 | + int incr = COMPILED_BUFFER_VAR - old_buffer; \ |
| 8463 | + MOVE_BUFFER_POINTER (b); \ |
| 8464 | + MOVE_BUFFER_POINTER (begalt); \ |
| 8465 | + if (fixup_alt_jump) \ |
| 8466 | + MOVE_BUFFER_POINTER (fixup_alt_jump); \ |
| 8467 | + if (laststart) \ |
| 8468 | + MOVE_BUFFER_POINTER (laststart); \ |
| 8469 | + if (pending_exact) \ |
| 8470 | + MOVE_BUFFER_POINTER (pending_exact); \ |
| 8471 | + } \ |
| 8472 | + ELSE_EXTEND_BUFFER_HIGH_BOUND \ |
| 8473 | + } while (0) |
| 8474 | +# endif /* WCHAR */ |
| 8475 | + |
| 8476 | +# ifndef DEFINED_ONCE |
| 8477 | +/* Since we have one byte reserved for the register number argument to |
| 8478 | + {start,stop}_memory, the maximum number of groups we can report |
| 8479 | + things about is what fits in that byte. */ |
| 8480 | +# define MAX_REGNUM 255 |
| 8481 | + |
| 8482 | +/* But patterns can have more than `MAX_REGNUM' registers. We just |
| 8483 | + ignore the excess. */ |
| 8484 | +typedef unsigned regnum_t; |
| 8485 | + |
| 8486 | + |
| 8487 | +/* Macros for the compile stack. */ |
| 8488 | + |
| 8489 | +/* Since offsets can go either forwards or backwards, this type needs to |
| 8490 | + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ |
| 8491 | +/* int may be not enough when sizeof(int) == 2. */ |
| 8492 | +typedef long pattern_offset_t; |
| 8493 | + |
| 8494 | +typedef struct |
| 8495 | +{ |
| 8496 | + pattern_offset_t begalt_offset; |
| 8497 | + pattern_offset_t fixup_alt_jump; |
| 8498 | + pattern_offset_t inner_group_offset; |
| 8499 | + pattern_offset_t laststart_offset; |
| 8500 | + regnum_t regnum; |
| 8501 | +} compile_stack_elt_t; |
| 8502 | + |
| 8503 | + |
| 8504 | +typedef struct |
| 8505 | +{ |
| 8506 | + compile_stack_elt_t *stack; |
| 8507 | + unsigned size; |
| 8508 | + unsigned avail; /* Offset of next open position. */ |
| 8509 | +} compile_stack_type; |
| 8510 | + |
| 8511 | + |
| 8512 | +# define INIT_COMPILE_STACK_SIZE 32 |
| 8513 | + |
| 8514 | +# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) |
| 8515 | +# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) |
| 8516 | + |
| 8517 | +/* The next available element. */ |
| 8518 | +# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) |
| 8519 | + |
| 8520 | +# endif /* not DEFINED_ONCE */ |
| 8521 | + |
| 8522 | +/* Set the bit for character C in a list. */ |
| 8523 | +# ifndef DEFINED_ONCE |
| 8524 | +# define SET_LIST_BIT(c) \ |
| 8525 | + (b[((unsigned char) (c)) / BYTEWIDTH] \ |
| 8526 | + |= 1 << (((unsigned char) c) % BYTEWIDTH)) |
| 8527 | +# endif /* DEFINED_ONCE */ |
| 8528 | + |
| 8529 | +/* Get the next unsigned number in the uncompiled pattern. */ |
| 8530 | +# define GET_UNSIGNED_NUMBER(num) \ |
| 8531 | + { \ |
| 8532 | + while (p != pend) \ |
| 8533 | + { \ |
| 8534 | + PATFETCH (c); \ |
| 8535 | + if (c < '0' || c > '9') \ |
| 8536 | + break; \ |
| 8537 | + if (num <= RE_DUP_MAX) \ |
| 8538 | + { \ |
| 8539 | + if (num < 0) \ |
| 8540 | + num = 0; \ |
| 8541 | + num = num * 10 + c - '0'; \ |
| 8542 | + } \ |
| 8543 | + } \ |
| 8544 | + } |
| 8545 | + |
| 8546 | +# ifndef DEFINED_ONCE |
| 8547 | +# if WIDE_CHAR_SUPPORT |
| 8548 | +/* The GNU C library provides support for user-defined character classes |
| 8549 | + and the functions from ISO C amendement 1. */ |
| 8550 | +# ifdef CHARCLASS_NAME_MAX |
| 8551 | +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX |
| 8552 | +# else |
| 8553 | +/* This shouldn't happen but some implementation might still have this |
| 8554 | + problem. Use a reasonable default value. */ |
| 8555 | +# define CHAR_CLASS_MAX_LENGTH 256 |
| 8556 | +# endif |
| 8557 | + |
| 8558 | +# ifdef _LIBC |
| 8559 | +# define IS_CHAR_CLASS(string) __wctype (string) |
| 8560 | +# else |
| 8561 | +# define IS_CHAR_CLASS(string) wctype (string) |
| 8562 | +# endif |
| 8563 | +# else |
| 8564 | +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ |
| 8565 | + |
| 8566 | +# define IS_CHAR_CLASS(string) \ |
| 8567 | + (STREQ (string, "alpha") || STREQ (string, "upper") \ |
| 8568 | + || STREQ (string, "lower") || STREQ (string, "digit") \ |
| 8569 | + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ |
| 8570 | + || STREQ (string, "space") || STREQ (string, "print") \ |
| 8571 | + || STREQ (string, "punct") || STREQ (string, "graph") \ |
| 8572 | + || STREQ (string, "cntrl") || STREQ (string, "blank")) |
| 8573 | +# endif |
| 8574 | +# endif /* DEFINED_ONCE */ |
| 8575 | + |
| 8576 | +# ifndef MATCH_MAY_ALLOCATE |
| 8577 | + |
| 8578 | +/* If we cannot allocate large objects within re_match_2_internal, |
| 8579 | + we make the fail stack and register vectors global. |
| 8580 | + The fail stack, we grow to the maximum size when a regexp |
| 8581 | + is compiled. |
| 8582 | + The register vectors, we adjust in size each time we |
| 8583 | + compile a regexp, according to the number of registers it needs. */ |
| 8584 | + |
| 8585 | +static PREFIX(fail_stack_type) fail_stack; |
| 8586 | + |
| 8587 | +/* Size with which the following vectors are currently allocated. |
| 8588 | + That is so we can make them bigger as needed, |
| 8589 | + but never make them smaller. */ |
| 8590 | +# ifdef DEFINED_ONCE |
| 8591 | +static int regs_allocated_size; |
| 8592 | + |
| 8593 | +static const char ** regstart, ** regend; |
| 8594 | +static const char ** old_regstart, ** old_regend; |
| 8595 | +static const char **best_regstart, **best_regend; |
| 8596 | +static const char **reg_dummy; |
| 8597 | +# endif /* DEFINED_ONCE */ |
| 8598 | + |
| 8599 | +static PREFIX(register_info_type) *PREFIX(reg_info); |
| 8600 | +static PREFIX(register_info_type) *PREFIX(reg_info_dummy); |
| 8601 | + |
| 8602 | +/* Make the register vectors big enough for NUM_REGS registers, |
| 8603 | + but don't make them smaller. */ |
| 8604 | + |
| 8605 | +static void |
| 8606 | +PREFIX(regex_grow_registers) (int num_regs) |
| 8607 | +{ |
| 8608 | + if (num_regs > regs_allocated_size) |
| 8609 | + { |
| 8610 | + RETALLOC_IF (regstart, num_regs, const char *); |
| 8611 | + RETALLOC_IF (regend, num_regs, const char *); |
| 8612 | + RETALLOC_IF (old_regstart, num_regs, const char *); |
| 8613 | + RETALLOC_IF (old_regend, num_regs, const char *); |
| 8614 | + RETALLOC_IF (best_regstart, num_regs, const char *); |
| 8615 | + RETALLOC_IF (best_regend, num_regs, const char *); |
| 8616 | + RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); |
| 8617 | + RETALLOC_IF (reg_dummy, num_regs, const char *); |
| 8618 | + RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); |
| 8619 | + |
| 8620 | + regs_allocated_size = num_regs; |
| 8621 | + } |
| 8622 | +} |
| 8623 | + |
| 8624 | +# endif /* not MATCH_MAY_ALLOCATE */ |
| 8625 | + |
| 8626 | +# ifndef DEFINED_ONCE |
| 8627 | +static boolean group_in_compile_stack (compile_stack_type compile_stack, |
| 8628 | + regnum_t regnum); |
| 8629 | +# endif /* not DEFINED_ONCE */ |
| 8630 | + |
| 8631 | +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. |
| 8632 | + Returns one of error codes defined in `regex.h', or zero for success. |
| 8633 | + |
| 8634 | + Assumes the `allocated' (and perhaps `buffer') and `translate' |
| 8635 | + fields are set in BUFP on entry. |
| 8636 | + |
| 8637 | + If it succeeds, results are put in BUFP (if it returns an error, the |
| 8638 | + contents of BUFP are undefined): |
| 8639 | + `buffer' is the compiled pattern; |
| 8640 | + `syntax' is set to SYNTAX; |
| 8641 | + `used' is set to the length of the compiled pattern; |
| 8642 | + `fastmap_accurate' is zero; |
| 8643 | + `re_nsub' is the number of subexpressions in PATTERN; |
| 8644 | + `not_bol' and `not_eol' are zero; |
| 8645 | + |
| 8646 | + The `fastmap' and `newline_anchor' fields are neither |
| 8647 | + examined nor set. */ |
| 8648 | + |
| 8649 | +/* Return, freeing storage we allocated. */ |
| 8650 | +# ifdef WCHAR |
| 8651 | +# define FREE_STACK_RETURN(value) \ |
| 8652 | + return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) |
| 8653 | +# else |
| 8654 | +# define FREE_STACK_RETURN(value) \ |
| 8655 | + return (free (compile_stack.stack), value) |
| 8656 | +# endif /* WCHAR */ |
| 8657 | + |
| 8658 | +static reg_errcode_t |
| 8659 | +PREFIX(regex_compile) (const char *ARG_PREFIX(pattern), |
| 8660 | + size_t ARG_PREFIX(size), reg_syntax_t syntax, |
| 8661 | + struct re_pattern_buffer *bufp) |
| 8662 | +{ |
| 8663 | + /* We fetch characters from PATTERN here. Even though PATTERN is |
| 8664 | + `char *' (i.e., signed), we declare these variables as unsigned, so |
| 8665 | + they can be reliably used as array indices. */ |
| 8666 | + register UCHAR_T c, c1; |
| 8667 | + |
| 8668 | +#ifdef WCHAR |
| 8669 | + /* A temporary space to keep wchar_t pattern and compiled pattern. */ |
| 8670 | + CHAR_T *pattern, *COMPILED_BUFFER_VAR; |
| 8671 | + size_t size; |
| 8672 | + /* offset buffer for optimization. See convert_mbs_to_wc. */ |
| 8673 | + int *mbs_offset = NULL; |
| 8674 | + /* It hold whether each wchar_t is binary data or not. */ |
| 8675 | + char *is_binary = NULL; |
| 8676 | + /* A flag whether exactn is handling binary data or not. */ |
| 8677 | + char is_exactn_bin = FALSE; |
| 8678 | +#endif /* WCHAR */ |
| 8679 | + |
| 8680 | + /* A random temporary spot in PATTERN. */ |
| 8681 | + const CHAR_T *p1; |
| 8682 | + |
| 8683 | + /* Points to the end of the buffer, where we should append. */ |
| 8684 | + register UCHAR_T *b; |
| 8685 | + |
| 8686 | + /* Keeps track of unclosed groups. */ |
| 8687 | + compile_stack_type compile_stack; |
| 8688 | + |
| 8689 | + /* Points to the current (ending) position in the pattern. */ |
| 8690 | +#ifdef WCHAR |
| 8691 | + const CHAR_T *p; |
| 8692 | + const CHAR_T *pend; |
| 8693 | +#else /* BYTE */ |
| 8694 | + const CHAR_T *p = pattern; |
| 8695 | + const CHAR_T *pend = pattern + size; |
| 8696 | +#endif /* WCHAR */ |
| 8697 | + |
| 8698 | + /* How to translate the characters in the pattern. */ |
| 8699 | + RE_TRANSLATE_TYPE translate = bufp->translate; |
| 8700 | + |
| 8701 | + /* Address of the count-byte of the most recently inserted `exactn' |
| 8702 | + command. This makes it possible to tell if a new exact-match |
| 8703 | + character can be added to that command or if the character requires |
| 8704 | + a new `exactn' command. */ |
| 8705 | + UCHAR_T *pending_exact = 0; |
| 8706 | + |
| 8707 | + /* Address of start of the most recently finished expression. |
| 8708 | + This tells, e.g., postfix * where to find the start of its |
| 8709 | + operand. Reset at the beginning of groups and alternatives. */ |
| 8710 | + UCHAR_T *laststart = 0; |
| 8711 | + |
| 8712 | + /* Address of beginning of regexp, or inside of last group. */ |
| 8713 | + UCHAR_T *begalt; |
| 8714 | + |
| 8715 | + /* Address of the place where a forward jump should go to the end of |
| 8716 | + the containing expression. Each alternative of an `or' -- except the |
| 8717 | + last -- ends with a forward jump of this sort. */ |
| 8718 | + UCHAR_T *fixup_alt_jump = 0; |
| 8719 | + |
| 8720 | + /* Counts open-groups as they are encountered. Remembered for the |
| 8721 | + matching close-group on the compile stack, so the same register |
| 8722 | + number is put in the stop_memory as the start_memory. */ |
| 8723 | + regnum_t regnum = 0; |
| 8724 | + |
| 8725 | +#ifdef WCHAR |
| 8726 | + /* Initialize the wchar_t PATTERN and offset_buffer. */ |
| 8727 | + p = pend = pattern = TALLOC(csize + 1, CHAR_T); |
| 8728 | + mbs_offset = TALLOC(csize + 1, int); |
| 8729 | + is_binary = TALLOC(csize + 1, char); |
| 8730 | + if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) |
| 8731 | + { |
| 8732 | + free(pattern); |
| 8733 | + free(mbs_offset); |
| 8734 | + free(is_binary); |
| 8735 | + return REG_ESPACE; |
| 8736 | + } |
| 8737 | + pattern[csize] = L'\0'; /* sentinel */ |
| 8738 | + size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); |
| 8739 | + pend = p + size; |
| 8740 | + if (size < 0) |
| 8741 | + { |
| 8742 | + free(pattern); |
| 8743 | + free(mbs_offset); |
| 8744 | + free(is_binary); |
| 8745 | + return REG_BADPAT; |
| 8746 | + } |
| 8747 | +#endif |
| 8748 | + |
| 8749 | +#ifdef DEBUG |
| 8750 | + DEBUG_PRINT1 ("\nCompiling pattern: "); |
| 8751 | + if (debug) |
| 8752 | + { |
| 8753 | + unsigned debug_count; |
| 8754 | + |
| 8755 | + for (debug_count = 0; debug_count < size; debug_count++) |
| 8756 | + PUT_CHAR (pattern[debug_count]); |
| 8757 | + putchar ('\n'); |
| 8758 | + } |
| 8759 | +#endif /* DEBUG */ |
| 8760 | + |
| 8761 | + /* Initialize the compile stack. */ |
| 8762 | + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); |
| 8763 | + if (compile_stack.stack == NULL) |
| 8764 | + { |
| 8765 | +#ifdef WCHAR |
| 8766 | + free(pattern); |
| 8767 | + free(mbs_offset); |
| 8768 | + free(is_binary); |
| 8769 | +#endif |
| 8770 | + return REG_ESPACE; |
| 8771 | + } |
| 8772 | + |
| 8773 | + compile_stack.size = INIT_COMPILE_STACK_SIZE; |
| 8774 | + compile_stack.avail = 0; |
| 8775 | + |
| 8776 | + /* Initialize the pattern buffer. */ |
| 8777 | + bufp->syntax = syntax; |
| 8778 | + bufp->fastmap_accurate = 0; |
| 8779 | + bufp->not_bol = bufp->not_eol = 0; |
| 8780 | + |
| 8781 | + /* Set `used' to zero, so that if we return an error, the pattern |
| 8782 | + printer (for debugging) will think there's no pattern. We reset it |
| 8783 | + at the end. */ |
| 8784 | + bufp->used = 0; |
| 8785 | + |
| 8786 | + /* Always count groups, whether or not bufp->no_sub is set. */ |
| 8787 | + bufp->re_nsub = 0; |
| 8788 | + |
| 8789 | +#if !defined emacs && !defined SYNTAX_TABLE |
| 8790 | + /* Initialize the syntax table. */ |
| 8791 | + init_syntax_once (); |
| 8792 | +#endif |
| 8793 | + |
| 8794 | + if (bufp->allocated == 0) |
| 8795 | + { |
| 8796 | + if (bufp->buffer) |
| 8797 | + { /* If zero allocated, but buffer is non-null, try to realloc |
| 8798 | + enough space. This loses if buffer's address is bogus, but |
| 8799 | + that is the user's responsibility. */ |
| 8800 | +#ifdef WCHAR |
| 8801 | + /* Free bufp->buffer and allocate an array for wchar_t pattern |
| 8802 | + buffer. */ |
| 8803 | + free(bufp->buffer); |
| 8804 | + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), |
| 8805 | + UCHAR_T); |
| 8806 | +#else |
| 8807 | + RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); |
| 8808 | +#endif /* WCHAR */ |
| 8809 | + } |
| 8810 | + else |
| 8811 | + { /* Caller did not allocate a buffer. Do it for them. */ |
| 8812 | + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), |
| 8813 | + UCHAR_T); |
| 8814 | + } |
| 8815 | + |
| 8816 | + if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); |
| 8817 | +#ifdef WCHAR |
| 8818 | + bufp->buffer = (char*)COMPILED_BUFFER_VAR; |
| 8819 | +#endif /* WCHAR */ |
| 8820 | + bufp->allocated = INIT_BUF_SIZE; |
| 8821 | + } |
| 8822 | +#ifdef WCHAR |
| 8823 | + else |
| 8824 | + COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; |
| 8825 | +#endif |
| 8826 | + |
| 8827 | + begalt = b = COMPILED_BUFFER_VAR; |
| 8828 | + |
| 8829 | + /* Loop through the uncompiled pattern until we're at the end. */ |
| 8830 | + while (p != pend) |
| 8831 | + { |
| 8832 | + PATFETCH (c); |
| 8833 | + |
| 8834 | + switch (c) |
| 8835 | + { |
| 8836 | + case '^': |
| 8837 | + { |
| 8838 | + if ( /* If at start of pattern, it's an operator. */ |
| 8839 | + p == pattern + 1 |
| 8840 | + /* If context independent, it's an operator. */ |
| 8841 | + || syntax & RE_CONTEXT_INDEP_ANCHORS |
| 8842 | + /* Otherwise, depends on what's come before. */ |
| 8843 | + || PREFIX(at_begline_loc_p) (pattern, p, syntax)) |
| 8844 | + BUF_PUSH (begline); |
| 8845 | + else |
| 8846 | + goto normal_char; |
| 8847 | + } |
| 8848 | + break; |
| 8849 | + |
| 8850 | + |
| 8851 | + case '$': |
| 8852 | + { |
| 8853 | + if ( /* If at end of pattern, it's an operator. */ |
| 8854 | + p == pend |
| 8855 | + /* If context independent, it's an operator. */ |
| 8856 | + || syntax & RE_CONTEXT_INDEP_ANCHORS |
| 8857 | + /* Otherwise, depends on what's next. */ |
| 8858 | + || PREFIX(at_endline_loc_p) (p, pend, syntax)) |
| 8859 | + BUF_PUSH (endline); |
| 8860 | + else |
| 8861 | + goto normal_char; |
| 8862 | + } |
| 8863 | + break; |
| 8864 | + |
| 8865 | + |
| 8866 | + case '+': |
| 8867 | + case '?': |
| 8868 | + if ((syntax & RE_BK_PLUS_QM) |
| 8869 | + || (syntax & RE_LIMITED_OPS)) |
| 8870 | + goto normal_char; |
| 8871 | + handle_plus: |
| 8872 | + case '*': |
| 8873 | + /* If there is no previous pattern... */ |
| 8874 | + if (!laststart) |
| 8875 | + { |
| 8876 | + if (syntax & RE_CONTEXT_INVALID_OPS) |
| 8877 | + FREE_STACK_RETURN (REG_BADRPT); |
| 8878 | + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) |
| 8879 | + goto normal_char; |
| 8880 | + } |
| 8881 | + |
| 8882 | + { |
| 8883 | + /* Are we optimizing this jump? */ |
| 8884 | + boolean keep_string_p = false; |
| 8885 | + |
| 8886 | + /* 1 means zero (many) matches is allowed. */ |
| 8887 | + char zero_times_ok = 0, many_times_ok = 0; |
| 8888 | + |
| 8889 | + /* If there is a sequence of repetition chars, collapse it |
| 8890 | + down to just one (the right one). We can't combine |
| 8891 | + interval operators with these because of, e.g., `a{2}*', |
| 8892 | + which should only match an even number of `a's. */ |
| 8893 | + |
| 8894 | + for (;;) |
| 8895 | + { |
| 8896 | + zero_times_ok |= c != '+'; |
| 8897 | + many_times_ok |= c != '?'; |
| 8898 | + |
| 8899 | + if (p == pend) |
| 8900 | + break; |
| 8901 | + |
| 8902 | + PATFETCH (c); |
| 8903 | + |
| 8904 | + if (c == '*' |
| 8905 | + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) |
| 8906 | + ; |
| 8907 | + |
| 8908 | + else if (syntax & RE_BK_PLUS_QM && c == '\\') |
| 8909 | + { |
| 8910 | + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); |
| 8911 | + |
| 8912 | + PATFETCH (c1); |
| 8913 | + if (!(c1 == '+' || c1 == '?')) |
| 8914 | + { |
| 8915 | + PATUNFETCH; |
| 8916 | + PATUNFETCH; |
| 8917 | + break; |
| 8918 | + } |
| 8919 | + |
| 8920 | + c = c1; |
| 8921 | + } |
| 8922 | + else |
| 8923 | + { |
| 8924 | + PATUNFETCH; |
| 8925 | + break; |
| 8926 | + } |
| 8927 | + |
| 8928 | + /* If we get here, we found another repeat character. */ |
| 8929 | + } |
| 8930 | + |
| 8931 | + /* Star, etc. applied to an empty pattern is equivalent |
| 8932 | + to an empty pattern. */ |
| 8933 | + if (!laststart) |
| 8934 | + break; |
| 8935 | + |
| 8936 | + /* Now we know whether or not zero matches is allowed |
| 8937 | + and also whether or not two or more matches is allowed. */ |
| 8938 | + if (many_times_ok) |
| 8939 | + { /* More than one repetition is allowed, so put in at the |
| 8940 | + end a backward relative jump from `b' to before the next |
| 8941 | + jump we're going to put in below (which jumps from |
| 8942 | + laststart to after this jump). |
| 8943 | + |
| 8944 | + But if we are at the `*' in the exact sequence `.*\n', |
| 8945 | + insert an unconditional jump backwards to the ., |
| 8946 | + instead of the beginning of the loop. This way we only |
| 8947 | + push a failure point once, instead of every time |
| 8948 | + through the loop. */ |
| 8949 | + assert (p - 1 > pattern); |
| 8950 | + |
| 8951 | + /* Allocate the space for the jump. */ |
| 8952 | + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); |
| 8953 | + |
| 8954 | + /* We know we are not at the first character of the pattern, |
| 8955 | + because laststart was nonzero. And we've already |
| 8956 | + incremented `p', by the way, to be the character after |
| 8957 | + the `*'. Do we have to do something analogous here |
| 8958 | + for null bytes, because of RE_DOT_NOT_NULL? */ |
| 8959 | + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') |
| 8960 | + && zero_times_ok |
| 8961 | + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') |
| 8962 | + && !(syntax & RE_DOT_NEWLINE)) |
| 8963 | + { /* We have .*\n. */ |
| 8964 | + STORE_JUMP (jump, b, laststart); |
| 8965 | + keep_string_p = true; |
| 8966 | + } |
| 8967 | + else |
| 8968 | + /* Anything else. */ |
| 8969 | + STORE_JUMP (maybe_pop_jump, b, laststart - |
| 8970 | + (1 + OFFSET_ADDRESS_SIZE)); |
| 8971 | + |
| 8972 | + /* We've added more stuff to the buffer. */ |
| 8973 | + b += 1 + OFFSET_ADDRESS_SIZE; |
| 8974 | + } |
| 8975 | + |
| 8976 | + /* On failure, jump from laststart to b + 3, which will be the |
| 8977 | + end of the buffer after this jump is inserted. */ |
| 8978 | + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of |
| 8979 | + 'b + 3'. */ |
| 8980 | + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); |
| 8981 | + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump |
| 8982 | + : on_failure_jump, |
| 8983 | + laststart, b + 1 + OFFSET_ADDRESS_SIZE); |
| 8984 | + pending_exact = 0; |
| 8985 | + b += 1 + OFFSET_ADDRESS_SIZE; |
| 8986 | + |
| 8987 | + if (!zero_times_ok) |
| 8988 | + { |
| 8989 | + /* At least one repetition is required, so insert a |
| 8990 | + `dummy_failure_jump' before the initial |
| 8991 | + `on_failure_jump' instruction of the loop. This |
| 8992 | + effects a skip over that instruction the first time |
| 8993 | + we hit that loop. */ |
| 8994 | + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); |
| 8995 | + INSERT_JUMP (dummy_failure_jump, laststart, laststart + |
| 8996 | + 2 + 2 * OFFSET_ADDRESS_SIZE); |
| 8997 | + b += 1 + OFFSET_ADDRESS_SIZE; |
| 8998 | + } |
| 8999 | + } |
| 9000 | + break; |
| 9001 | + |
| 9002 | + |
| 9003 | + case '.': |
| 9004 | + laststart = b; |
| 9005 | + BUF_PUSH (anychar); |
| 9006 | + break; |
| 9007 | + |
| 9008 | + |
| 9009 | + case '[': |
| 9010 | + { |
| 9011 | + boolean had_char_class = false; |
| 9012 | +#ifdef WCHAR |
| 9013 | + CHAR_T range_start = 0xffffffff; |
| 9014 | +#else |
| 9015 | + unsigned int range_start = 0xffffffff; |
| 9016 | +#endif |
| 9017 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9018 | + |
| 9019 | +#ifdef WCHAR |
| 9020 | + /* We assume a charset(_not) structure as a wchar_t array. |
| 9021 | + charset[0] = (re_opcode_t) charset(_not) |
| 9022 | + charset[1] = l (= length of char_classes) |
| 9023 | + charset[2] = m (= length of collating_symbols) |
| 9024 | + charset[3] = n (= length of equivalence_classes) |
| 9025 | + charset[4] = o (= length of char_ranges) |
| 9026 | + charset[5] = p (= length of chars) |
| 9027 | + |
| 9028 | + charset[6] = char_class (wctype_t) |
| 9029 | + charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t) |
| 9030 | + ... |
| 9031 | + charset[l+5] = char_class (wctype_t) |
| 9032 | + |
| 9033 | + charset[l+6] = collating_symbol (wchar_t) |
| 9034 | + ... |
| 9035 | + charset[l+m+5] = collating_symbol (wchar_t) |
| 9036 | + ifdef _LIBC we use the index if |
| 9037 | + _NL_COLLATE_SYMB_EXTRAMB instead of |
| 9038 | + wchar_t string. |
| 9039 | + |
| 9040 | + charset[l+m+6] = equivalence_classes (wchar_t) |
| 9041 | + ... |
| 9042 | + charset[l+m+n+5] = equivalence_classes (wchar_t) |
| 9043 | + ifdef _LIBC we use the index in |
| 9044 | + _NL_COLLATE_WEIGHT instead of |
| 9045 | + wchar_t string. |
| 9046 | + |
| 9047 | + charset[l+m+n+6] = range_start |
| 9048 | + charset[l+m+n+7] = range_end |
| 9049 | + ... |
| 9050 | + charset[l+m+n+2o+4] = range_start |
| 9051 | + charset[l+m+n+2o+5] = range_end |
| 9052 | + ifdef _LIBC we use the value looked up |
| 9053 | + in _NL_COLLATE_COLLSEQ instead of |
| 9054 | + wchar_t character. |
| 9055 | + |
| 9056 | + charset[l+m+n+2o+6] = char |
| 9057 | + ... |
| 9058 | + charset[l+m+n+2o+p+5] = char |
| 9059 | + |
| 9060 | + */ |
| 9061 | + |
| 9062 | + /* We need at least 6 spaces: the opcode, the length of |
| 9063 | + char_classes, the length of collating_symbols, the length of |
| 9064 | + equivalence_classes, the length of char_ranges, the length of |
| 9065 | + chars. */ |
| 9066 | + GET_BUFFER_SPACE (6); |
| 9067 | + |
| 9068 | + /* Save b as laststart. And We use laststart as the pointer |
| 9069 | + to the first element of the charset here. |
| 9070 | + In other words, laststart[i] indicates charset[i]. */ |
| 9071 | + laststart = b; |
| 9072 | + |
| 9073 | + /* We test `*p == '^' twice, instead of using an if |
| 9074 | + statement, so we only need one BUF_PUSH. */ |
| 9075 | + BUF_PUSH (*p == '^' ? charset_not : charset); |
| 9076 | + if (*p == '^') |
| 9077 | + p++; |
| 9078 | + |
| 9079 | + /* Push the length of char_classes, the length of |
| 9080 | + collating_symbols, the length of equivalence_classes, the |
| 9081 | + length of char_ranges and the length of chars. */ |
| 9082 | + BUF_PUSH_3 (0, 0, 0); |
| 9083 | + BUF_PUSH_2 (0, 0); |
| 9084 | + |
| 9085 | + /* Remember the first position in the bracket expression. */ |
| 9086 | + p1 = p; |
| 9087 | + |
| 9088 | + /* charset_not matches newline according to a syntax bit. */ |
| 9089 | + if ((re_opcode_t) b[-6] == charset_not |
| 9090 | + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) |
| 9091 | + { |
| 9092 | + BUF_PUSH('\n'); |
| 9093 | + laststart[5]++; /* Update the length of characters */ |
| 9094 | + } |
| 9095 | + |
| 9096 | + /* Read in characters and ranges, setting map bits. */ |
| 9097 | + for (;;) |
| 9098 | + { |
| 9099 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9100 | + |
| 9101 | + PATFETCH (c); |
| 9102 | + |
| 9103 | + /* \ might escape characters inside [...] and [^...]. */ |
| 9104 | + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') |
| 9105 | + { |
| 9106 | + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); |
| 9107 | + |
| 9108 | + PATFETCH (c1); |
| 9109 | + BUF_PUSH(c1); |
| 9110 | + laststart[5]++; /* Update the length of chars */ |
| 9111 | + range_start = c1; |
| 9112 | + continue; |
| 9113 | + } |
| 9114 | + |
| 9115 | + /* Could be the end of the bracket expression. If it's |
| 9116 | + not (i.e., when the bracket expression is `[]' so |
| 9117 | + far), the ']' character bit gets set way below. */ |
| 9118 | + if (c == ']' && p != p1 + 1) |
| 9119 | + break; |
| 9120 | + |
| 9121 | + /* Look ahead to see if it's a range when the last thing |
| 9122 | + was a character class. */ |
| 9123 | + if (had_char_class && c == '-' && *p != ']') |
| 9124 | + FREE_STACK_RETURN (REG_ERANGE); |
| 9125 | + |
| 9126 | + /* Look ahead to see if it's a range when the last thing |
| 9127 | + was a character: if this is a hyphen not at the |
| 9128 | + beginning or the end of a list, then it's the range |
| 9129 | + operator. */ |
| 9130 | + if (c == '-' |
| 9131 | + && !(p - 2 >= pattern && p[-2] == '[') |
| 9132 | + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') |
| 9133 | + && *p != ']') |
| 9134 | + { |
| 9135 | + reg_errcode_t ret; |
| 9136 | + /* Allocate the space for range_start and range_end. */ |
| 9137 | + GET_BUFFER_SPACE (2); |
| 9138 | + /* Update the pointer to indicate end of buffer. */ |
| 9139 | + b += 2; |
| 9140 | + ret = wcs_compile_range (range_start, &p, pend, translate, |
| 9141 | + syntax, b, laststart); |
| 9142 | + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); |
| 9143 | + range_start = 0xffffffff; |
| 9144 | + } |
| 9145 | + else if (p[0] == '-' && p[1] != ']') |
| 9146 | + { /* This handles ranges made up of characters only. */ |
| 9147 | + reg_errcode_t ret; |
| 9148 | + |
| 9149 | + /* Move past the `-'. */ |
| 9150 | + PATFETCH (c1); |
| 9151 | + /* Allocate the space for range_start and range_end. */ |
| 9152 | + GET_BUFFER_SPACE (2); |
| 9153 | + /* Update the pointer to indicate end of buffer. */ |
| 9154 | + b += 2; |
| 9155 | + ret = wcs_compile_range (c, &p, pend, translate, syntax, b, |
| 9156 | + laststart); |
| 9157 | + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); |
| 9158 | + range_start = 0xffffffff; |
| 9159 | + } |
| 9160 | + |
| 9161 | + /* See if we're at the beginning of a possible character |
| 9162 | + class. */ |
| 9163 | + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') |
| 9164 | + { /* Leave room for the null. */ |
| 9165 | + char str[CHAR_CLASS_MAX_LENGTH + 1]; |
| 9166 | + |
| 9167 | + PATFETCH (c); |
| 9168 | + c1 = 0; |
| 9169 | + |
| 9170 | + /* If pattern is `[[:'. */ |
| 9171 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9172 | + |
| 9173 | + for (;;) |
| 9174 | + { |
| 9175 | + PATFETCH (c); |
| 9176 | + if ((c == ':' && *p == ']') || p == pend) |
| 9177 | + break; |
| 9178 | + if (c1 < CHAR_CLASS_MAX_LENGTH) |
| 9179 | + str[c1++] = c; |
| 9180 | + else |
| 9181 | + /* This is in any case an invalid class name. */ |
| 9182 | + str[0] = '\0'; |
| 9183 | + } |
| 9184 | + str[c1] = '\0'; |
| 9185 | + |
| 9186 | + /* If isn't a word bracketed by `[:' and `:]': |
| 9187 | + undo the ending character, the letters, and leave |
| 9188 | + the leading `:' and `[' (but store them as character). */ |
| 9189 | + if (c == ':' && *p == ']') |
| 9190 | + { |
| 9191 | + wctype_t wt; |
| 9192 | + uintptr_t alignedp; |
| 9193 | + |
| 9194 | + /* Query the character class as wctype_t. */ |
| 9195 | + wt = IS_CHAR_CLASS (str); |
| 9196 | + if (wt == 0) |
| 9197 | + FREE_STACK_RETURN (REG_ECTYPE); |
| 9198 | + |
| 9199 | + /* Throw away the ] at the end of the character |
| 9200 | + class. */ |
| 9201 | + PATFETCH (c); |
| 9202 | + |
| 9203 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9204 | + |
| 9205 | + /* Allocate the space for character class. */ |
| 9206 | + GET_BUFFER_SPACE(CHAR_CLASS_SIZE); |
| 9207 | + /* Update the pointer to indicate end of buffer. */ |
| 9208 | + b += CHAR_CLASS_SIZE; |
| 9209 | + /* Move data which follow character classes |
| 9210 | + not to violate the data. */ |
| 9211 | + insert_space(CHAR_CLASS_SIZE, |
| 9212 | + laststart + 6 + laststart[1], |
| 9213 | + b - 1); |
| 9214 | + alignedp = ((uintptr_t)(laststart + 6 + laststart[1]) |
| 9215 | + + __alignof__(wctype_t) - 1) |
| 9216 | + & ~(uintptr_t)(__alignof__(wctype_t) - 1); |
| 9217 | + /* Store the character class. */ |
| 9218 | + *((wctype_t*)alignedp) = wt; |
| 9219 | + /* Update length of char_classes */ |
| 9220 | + laststart[1] += CHAR_CLASS_SIZE; |
| 9221 | + |
| 9222 | + had_char_class = true; |
| 9223 | + } |
| 9224 | + else |
| 9225 | + { |
| 9226 | + c1++; |
| 9227 | + while (c1--) |
| 9228 | + PATUNFETCH; |
| 9229 | + BUF_PUSH ('['); |
| 9230 | + BUF_PUSH (':'); |
| 9231 | + laststart[5] += 2; /* Update the length of characters */ |
| 9232 | + range_start = ':'; |
| 9233 | + had_char_class = false; |
| 9234 | + } |
| 9235 | + } |
| 9236 | + else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' |
| 9237 | + || *p == '.')) |
| 9238 | + { |
| 9239 | + CHAR_T str[128]; /* Should be large enough. */ |
| 9240 | + CHAR_T delim = *p; /* '=' or '.' */ |
| 9241 | +# ifdef _LIBC |
| 9242 | + uint32_t nrules = |
| 9243 | + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 9244 | +# endif |
| 9245 | + PATFETCH (c); |
| 9246 | + c1 = 0; |
| 9247 | + |
| 9248 | + /* If pattern is `[[=' or '[[.'. */ |
| 9249 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9250 | + |
| 9251 | + for (;;) |
| 9252 | + { |
| 9253 | + PATFETCH (c); |
| 9254 | + if ((c == delim && *p == ']') || p == pend) |
| 9255 | + break; |
| 9256 | + if (c1 < sizeof (str) - 1) |
| 9257 | + str[c1++] = c; |
| 9258 | + else |
| 9259 | + /* This is in any case an invalid class name. */ |
| 9260 | + str[0] = '\0'; |
| 9261 | + } |
| 9262 | + str[c1] = '\0'; |
| 9263 | + |
| 9264 | + if (c == delim && *p == ']' && str[0] != '\0') |
| 9265 | + { |
| 9266 | + unsigned int i, offset; |
| 9267 | + /* If we have no collation data we use the default |
| 9268 | + collation in which each character is in a class |
| 9269 | + by itself. It also means that ASCII is the |
| 9270 | + character set and therefore we cannot have character |
| 9271 | + with more than one byte in the multibyte |
| 9272 | + representation. */ |
| 9273 | + |
| 9274 | + /* If not defined _LIBC, we push the name and |
| 9275 | + `\0' for the sake of matching performance. */ |
| 9276 | + int datasize = c1 + 1; |
| 9277 | + |
| 9278 | +# ifdef _LIBC |
| 9279 | + int32_t idx = 0; |
| 9280 | + if (nrules == 0) |
| 9281 | +# endif |
| 9282 | + { |
| 9283 | + if (c1 != 1) |
| 9284 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9285 | + } |
| 9286 | +# ifdef _LIBC |
| 9287 | + else |
| 9288 | + { |
| 9289 | + const int32_t *table; |
| 9290 | + const int32_t *weights; |
| 9291 | + const int32_t *extra; |
| 9292 | + const int32_t *indirect; |
| 9293 | + wint_t *cp; |
| 9294 | + |
| 9295 | + if(delim == '=') |
| 9296 | + { |
| 9297 | + /* We push the index for equivalence class. */ |
| 9298 | + cp = (wint_t*)str; |
| 9299 | + |
| 9300 | + table = (const int32_t *) |
| 9301 | + _NL_CURRENT (LC_COLLATE, |
| 9302 | + _NL_COLLATE_TABLEWC); |
| 9303 | + weights = (const int32_t *) |
| 9304 | + _NL_CURRENT (LC_COLLATE, |
| 9305 | + _NL_COLLATE_WEIGHTWC); |
| 9306 | + extra = (const wint_t *) |
| 9307 | + _NL_CURRENT (LC_COLLATE, |
| 9308 | + _NL_COLLATE_EXTRAWC); |
| 9309 | + indirect = (const int32_t *) |
| 9310 | + _NL_CURRENT (LC_COLLATE, |
| 9311 | + _NL_COLLATE_INDIRECTWC); |
| 9312 | + |
| 9313 | + idx = FINDIDX (table, indirect, extra, &cp, 1); |
| 9314 | + if (idx == 0 || cp < (wint_t*) str + c1) |
| 9315 | + /* This is no valid character. */ |
| 9316 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9317 | + |
| 9318 | + str[0] = (wchar_t)idx; |
| 9319 | + } |
| 9320 | + else /* delim == '.' */ |
| 9321 | + { |
| 9322 | + /* We push collation sequence value |
| 9323 | + for collating symbol. */ |
| 9324 | + int32_t table_size; |
| 9325 | + const int32_t *symb_table; |
| 9326 | + const unsigned char *extra; |
| 9327 | + int32_t idx; |
| 9328 | + int32_t elem; |
| 9329 | + int32_t second; |
| 9330 | + int32_t hash; |
| 9331 | + char char_str[c1]; |
| 9332 | + |
| 9333 | + /* We have to convert the name to a single-byte |
| 9334 | + string. This is possible since the names |
| 9335 | + consist of ASCII characters and the internal |
| 9336 | + representation is UCS4. */ |
| 9337 | + for (i = 0; i < c1; ++i) |
| 9338 | + char_str[i] = str[i]; |
| 9339 | + |
| 9340 | + table_size = |
| 9341 | + _NL_CURRENT_WORD (LC_COLLATE, |
| 9342 | + _NL_COLLATE_SYMB_HASH_SIZEMB); |
| 9343 | + symb_table = (const int32_t *) |
| 9344 | + _NL_CURRENT (LC_COLLATE, |
| 9345 | + _NL_COLLATE_SYMB_TABLEMB); |
| 9346 | + extra = (const unsigned char *) |
| 9347 | + _NL_CURRENT (LC_COLLATE, |
| 9348 | + _NL_COLLATE_SYMB_EXTRAMB); |
| 9349 | + |
| 9350 | + /* Locate the character in the hashing table. */ |
| 9351 | + hash = elem_hash (char_str, c1); |
| 9352 | + |
| 9353 | + idx = 0; |
| 9354 | + elem = hash % table_size; |
| 9355 | + second = hash % (table_size - 2); |
| 9356 | + while (symb_table[2 * elem] != 0) |
| 9357 | + { |
| 9358 | + /* First compare the hashing value. */ |
| 9359 | + if (symb_table[2 * elem] == hash |
| 9360 | + && c1 == extra[symb_table[2 * elem + 1]] |
| 9361 | + && memcmp (char_str, |
| 9362 | + &extra[symb_table[2 * elem + 1] |
| 9363 | + + 1], c1) == 0) |
| 9364 | + { |
| 9365 | + /* Yep, this is the entry. */ |
| 9366 | + idx = symb_table[2 * elem + 1]; |
| 9367 | + idx += 1 + extra[idx]; |
| 9368 | + break; |
| 9369 | + } |
| 9370 | + |
| 9371 | + /* Next entry. */ |
| 9372 | + elem += second; |
| 9373 | + } |
| 9374 | + |
| 9375 | + if (symb_table[2 * elem] != 0) |
| 9376 | + { |
| 9377 | + /* Compute the index of the byte sequence |
| 9378 | + in the table. */ |
| 9379 | + idx += 1 + extra[idx]; |
| 9380 | + /* Adjust for the alignment. */ |
| 9381 | + idx = (idx + 3) & ~3; |
| 9382 | + |
| 9383 | + str[0] = (wchar_t) idx + 4; |
| 9384 | + } |
| 9385 | + else if (symb_table[2 * elem] == 0 && c1 == 1) |
| 9386 | + { |
| 9387 | + /* No valid character. Match it as a |
| 9388 | + single byte character. */ |
| 9389 | + had_char_class = false; |
| 9390 | + BUF_PUSH(str[0]); |
| 9391 | + /* Update the length of characters */ |
| 9392 | + laststart[5]++; |
| 9393 | + range_start = str[0]; |
| 9394 | + |
| 9395 | + /* Throw away the ] at the end of the |
| 9396 | + collating symbol. */ |
| 9397 | + PATFETCH (c); |
| 9398 | + /* exit from the switch block. */ |
| 9399 | + continue; |
| 9400 | + } |
| 9401 | + else |
| 9402 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9403 | + } |
| 9404 | + datasize = 1; |
| 9405 | + } |
| 9406 | +# endif |
| 9407 | + /* Throw away the ] at the end of the equivalence |
| 9408 | + class (or collating symbol). */ |
| 9409 | + PATFETCH (c); |
| 9410 | + |
| 9411 | + /* Allocate the space for the equivalence class |
| 9412 | + (or collating symbol) (and '\0' if needed). */ |
| 9413 | + GET_BUFFER_SPACE(datasize); |
| 9414 | + /* Update the pointer to indicate end of buffer. */ |
| 9415 | + b += datasize; |
| 9416 | + |
| 9417 | + if (delim == '=') |
| 9418 | + { /* equivalence class */ |
| 9419 | + /* Calculate the offset of char_ranges, |
| 9420 | + which is next to equivalence_classes. */ |
| 9421 | + offset = laststart[1] + laststart[2] |
| 9422 | + + laststart[3] +6; |
| 9423 | + /* Insert space. */ |
| 9424 | + insert_space(datasize, laststart + offset, b - 1); |
| 9425 | + |
| 9426 | + /* Write the equivalence_class and \0. */ |
| 9427 | + for (i = 0 ; i < datasize ; i++) |
| 9428 | + laststart[offset + i] = str[i]; |
| 9429 | + |
| 9430 | + /* Update the length of equivalence_classes. */ |
| 9431 | + laststart[3] += datasize; |
| 9432 | + had_char_class = true; |
| 9433 | + } |
| 9434 | + else /* delim == '.' */ |
| 9435 | + { /* collating symbol */ |
| 9436 | + /* Calculate the offset of the equivalence_classes, |
| 9437 | + which is next to collating_symbols. */ |
| 9438 | + offset = laststart[1] + laststart[2] + 6; |
| 9439 | + /* Insert space and write the collationg_symbol |
| 9440 | + and \0. */ |
| 9441 | + insert_space(datasize, laststart + offset, b-1); |
| 9442 | + for (i = 0 ; i < datasize ; i++) |
| 9443 | + laststart[offset + i] = str[i]; |
| 9444 | + |
| 9445 | + /* In re_match_2_internal if range_start < -1, we |
| 9446 | + assume -range_start is the offset of the |
| 9447 | + collating symbol which is specified as |
| 9448 | + the character of the range start. So we assign |
| 9449 | + -(laststart[1] + laststart[2] + 6) to |
| 9450 | + range_start. */ |
| 9451 | + range_start = -(laststart[1] + laststart[2] + 6); |
| 9452 | + /* Update the length of collating_symbol. */ |
| 9453 | + laststart[2] += datasize; |
| 9454 | + had_char_class = false; |
| 9455 | + } |
| 9456 | + } |
| 9457 | + else |
| 9458 | + { |
| 9459 | + c1++; |
| 9460 | + while (c1--) |
| 9461 | + PATUNFETCH; |
| 9462 | + BUF_PUSH ('['); |
| 9463 | + BUF_PUSH (delim); |
| 9464 | + laststart[5] += 2; /* Update the length of characters */ |
| 9465 | + range_start = delim; |
| 9466 | + had_char_class = false; |
| 9467 | + } |
| 9468 | + } |
| 9469 | + else |
| 9470 | + { |
| 9471 | + had_char_class = false; |
| 9472 | + BUF_PUSH(c); |
| 9473 | + laststart[5]++; /* Update the length of characters */ |
| 9474 | + range_start = c; |
| 9475 | + } |
| 9476 | + } |
| 9477 | + |
| 9478 | +#else /* BYTE */ |
| 9479 | + /* Ensure that we have enough space to push a charset: the |
| 9480 | + opcode, the length count, and the bitset; 34 bytes in all. */ |
| 9481 | + GET_BUFFER_SPACE (34); |
| 9482 | + |
| 9483 | + laststart = b; |
| 9484 | + |
| 9485 | + /* We test `*p == '^' twice, instead of using an if |
| 9486 | + statement, so we only need one BUF_PUSH. */ |
| 9487 | + BUF_PUSH (*p == '^' ? charset_not : charset); |
| 9488 | + if (*p == '^') |
| 9489 | + p++; |
| 9490 | + |
| 9491 | + /* Remember the first position in the bracket expression. */ |
| 9492 | + p1 = p; |
| 9493 | + |
| 9494 | + /* Push the number of bytes in the bitmap. */ |
| 9495 | + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); |
| 9496 | + |
| 9497 | + /* Clear the whole map. */ |
| 9498 | + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); |
| 9499 | + |
| 9500 | + /* charset_not matches newline according to a syntax bit. */ |
| 9501 | + if ((re_opcode_t) b[-2] == charset_not |
| 9502 | + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) |
| 9503 | + SET_LIST_BIT ('\n'); |
| 9504 | + |
| 9505 | + /* Read in characters and ranges, setting map bits. */ |
| 9506 | + for (;;) |
| 9507 | + { |
| 9508 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9509 | + |
| 9510 | + PATFETCH (c); |
| 9511 | + |
| 9512 | + /* \ might escape characters inside [...] and [^...]. */ |
| 9513 | + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') |
| 9514 | + { |
| 9515 | + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); |
| 9516 | + |
| 9517 | + PATFETCH (c1); |
| 9518 | + SET_LIST_BIT (c1); |
| 9519 | + range_start = c1; |
| 9520 | + continue; |
| 9521 | + } |
| 9522 | + |
| 9523 | + /* Could be the end of the bracket expression. If it's |
| 9524 | + not (i.e., when the bracket expression is `[]' so |
| 9525 | + far), the ']' character bit gets set way below. */ |
| 9526 | + if (c == ']' && p != p1 + 1) |
| 9527 | + break; |
| 9528 | + |
| 9529 | + /* Look ahead to see if it's a range when the last thing |
| 9530 | + was a character class. */ |
| 9531 | + if (had_char_class && c == '-' && *p != ']') |
| 9532 | + FREE_STACK_RETURN (REG_ERANGE); |
| 9533 | + |
| 9534 | + /* Look ahead to see if it's a range when the last thing |
| 9535 | + was a character: if this is a hyphen not at the |
| 9536 | + beginning or the end of a list, then it's the range |
| 9537 | + operator. */ |
| 9538 | + if (c == '-' |
| 9539 | + && !(p - 2 >= pattern && p[-2] == '[') |
| 9540 | + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') |
| 9541 | + && *p != ']') |
| 9542 | + { |
| 9543 | + reg_errcode_t ret |
| 9544 | + = byte_compile_range (range_start, &p, pend, translate, |
| 9545 | + syntax, b); |
| 9546 | + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); |
| 9547 | + range_start = 0xffffffff; |
| 9548 | + } |
| 9549 | + |
| 9550 | + else if (p[0] == '-' && p[1] != ']') |
| 9551 | + { /* This handles ranges made up of characters only. */ |
| 9552 | + reg_errcode_t ret; |
| 9553 | + |
| 9554 | + /* Move past the `-'. */ |
| 9555 | + PATFETCH (c1); |
| 9556 | + |
| 9557 | + ret = byte_compile_range (c, &p, pend, translate, syntax, b); |
| 9558 | + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); |
| 9559 | + range_start = 0xffffffff; |
| 9560 | + } |
| 9561 | + |
| 9562 | + /* See if we're at the beginning of a possible character |
| 9563 | + class. */ |
| 9564 | + |
| 9565 | + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') |
| 9566 | + { /* Leave room for the null. */ |
| 9567 | + char str[CHAR_CLASS_MAX_LENGTH + 1]; |
| 9568 | + |
| 9569 | + PATFETCH (c); |
| 9570 | + c1 = 0; |
| 9571 | + |
| 9572 | + /* If pattern is `[[:'. */ |
| 9573 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9574 | + |
| 9575 | + for (;;) |
| 9576 | + { |
| 9577 | + PATFETCH (c); |
| 9578 | + if ((c == ':' && *p == ']') || p == pend) |
| 9579 | + break; |
| 9580 | + if (((int) c1) < CHAR_CLASS_MAX_LENGTH) |
| 9581 | + str[c1++] = c; |
| 9582 | + else |
| 9583 | + /* This is in any case an invalid class name. */ |
| 9584 | + str[0] = '\0'; |
| 9585 | + } |
| 9586 | + str[c1] = '\0'; |
| 9587 | + |
| 9588 | + /* If isn't a word bracketed by `[:' and `:]': |
| 9589 | + undo the ending character, the letters, and leave |
| 9590 | + the leading `:' and `[' (but set bits for them). */ |
| 9591 | + if (c == ':' && *p == ']') |
| 9592 | + { |
| 9593 | +# if WIDE_CHAR_SUPPORT |
| 9594 | + boolean is_lower = STREQ (str, "lower"); |
| 9595 | + boolean is_upper = STREQ (str, "upper"); |
| 9596 | + wctype_t wt; |
| 9597 | + int ch; |
| 9598 | + |
| 9599 | + wt = IS_CHAR_CLASS (str); |
| 9600 | + if (wt == 0) |
| 9601 | + FREE_STACK_RETURN (REG_ECTYPE); |
| 9602 | + |
| 9603 | + /* Throw away the ] at the end of the character |
| 9604 | + class. */ |
| 9605 | + PATFETCH (c); |
| 9606 | + |
| 9607 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9608 | + |
| 9609 | + for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) |
| 9610 | + { |
| 9611 | +# ifdef _LIBC |
| 9612 | + if (__iswctype (__btowc (ch), wt)) |
| 9613 | + SET_LIST_BIT (ch); |
| 9614 | +# else |
| 9615 | + if (iswctype (btowc (ch), wt)) |
| 9616 | + SET_LIST_BIT (ch); |
| 9617 | +# endif |
| 9618 | + |
| 9619 | + if (translate && (is_upper || is_lower) |
| 9620 | + && (ISUPPER (ch) || ISLOWER (ch))) |
| 9621 | + SET_LIST_BIT (ch); |
| 9622 | + } |
| 9623 | + |
| 9624 | + had_char_class = true; |
| 9625 | +# else |
| 9626 | + int ch; |
| 9627 | + boolean is_alnum = STREQ (str, "alnum"); |
| 9628 | + boolean is_alpha = STREQ (str, "alpha"); |
| 9629 | + boolean is_blank = STREQ (str, "blank"); |
| 9630 | + boolean is_cntrl = STREQ (str, "cntrl"); |
| 9631 | + boolean is_digit = STREQ (str, "digit"); |
| 9632 | + boolean is_graph = STREQ (str, "graph"); |
| 9633 | + boolean is_lower = STREQ (str, "lower"); |
| 9634 | + boolean is_print = STREQ (str, "print"); |
| 9635 | + boolean is_punct = STREQ (str, "punct"); |
| 9636 | + boolean is_space = STREQ (str, "space"); |
| 9637 | + boolean is_upper = STREQ (str, "upper"); |
| 9638 | + boolean is_xdigit = STREQ (str, "xdigit"); |
| 9639 | + |
| 9640 | + if (!IS_CHAR_CLASS (str)) |
| 9641 | + FREE_STACK_RETURN (REG_ECTYPE); |
| 9642 | + |
| 9643 | + /* Throw away the ] at the end of the character |
| 9644 | + class. */ |
| 9645 | + PATFETCH (c); |
| 9646 | + |
| 9647 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9648 | + |
| 9649 | + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) |
| 9650 | + { |
| 9651 | + /* This was split into 3 if's to |
| 9652 | + avoid an arbitrary limit in some compiler. */ |
| 9653 | + if ( (is_alnum && ISALNUM (ch)) |
| 9654 | + || (is_alpha && ISALPHA (ch)) |
| 9655 | + || (is_blank && ISBLANK (ch)) |
| 9656 | + || (is_cntrl && ISCNTRL (ch))) |
| 9657 | + SET_LIST_BIT (ch); |
| 9658 | + if ( (is_digit && ISDIGIT (ch)) |
| 9659 | + || (is_graph && ISGRAPH (ch)) |
| 9660 | + || (is_lower && ISLOWER (ch)) |
| 9661 | + || (is_print && ISPRINT (ch))) |
| 9662 | + SET_LIST_BIT (ch); |
| 9663 | + if ( (is_punct && ISPUNCT (ch)) |
| 9664 | + || (is_space && ISSPACE (ch)) |
| 9665 | + || (is_upper && ISUPPER (ch)) |
| 9666 | + || (is_xdigit && ISXDIGIT (ch))) |
| 9667 | + SET_LIST_BIT (ch); |
| 9668 | + if ( translate && (is_upper || is_lower) |
| 9669 | + && (ISUPPER (ch) || ISLOWER (ch))) |
| 9670 | + SET_LIST_BIT (ch); |
| 9671 | + } |
| 9672 | + had_char_class = true; |
| 9673 | +# endif /* libc || wctype.h */ |
| 9674 | + } |
| 9675 | + else |
| 9676 | + { |
| 9677 | + c1++; |
| 9678 | + while (c1--) |
| 9679 | + PATUNFETCH; |
| 9680 | + SET_LIST_BIT ('['); |
| 9681 | + SET_LIST_BIT (':'); |
| 9682 | + range_start = ':'; |
| 9683 | + had_char_class = false; |
| 9684 | + } |
| 9685 | + } |
| 9686 | + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=') |
| 9687 | + { |
| 9688 | + unsigned char str[MB_LEN_MAX + 1]; |
| 9689 | +# ifdef _LIBC |
| 9690 | + uint32_t nrules = |
| 9691 | + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 9692 | +# endif |
| 9693 | + |
| 9694 | + PATFETCH (c); |
| 9695 | + c1 = 0; |
| 9696 | + |
| 9697 | + /* If pattern is `[[='. */ |
| 9698 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9699 | + |
| 9700 | + for (;;) |
| 9701 | + { |
| 9702 | + PATFETCH (c); |
| 9703 | + if ((c == '=' && *p == ']') || p == pend) |
| 9704 | + break; |
| 9705 | + if (c1 < MB_LEN_MAX) |
| 9706 | + str[c1++] = c; |
| 9707 | + else |
| 9708 | + /* This is in any case an invalid class name. */ |
| 9709 | + str[0] = '\0'; |
| 9710 | + } |
| 9711 | + str[c1] = '\0'; |
| 9712 | + |
| 9713 | + if (c == '=' && *p == ']' && str[0] != '\0') |
| 9714 | + { |
| 9715 | + /* If we have no collation data we use the default |
| 9716 | + collation in which each character is in a class |
| 9717 | + by itself. It also means that ASCII is the |
| 9718 | + character set and therefore we cannot have character |
| 9719 | + with more than one byte in the multibyte |
| 9720 | + representation. */ |
| 9721 | +# ifdef _LIBC |
| 9722 | + if (nrules == 0) |
| 9723 | +# endif |
| 9724 | + { |
| 9725 | + if (c1 != 1) |
| 9726 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9727 | + |
| 9728 | + /* Throw away the ] at the end of the equivalence |
| 9729 | + class. */ |
| 9730 | + PATFETCH (c); |
| 9731 | + |
| 9732 | + /* Set the bit for the character. */ |
| 9733 | + SET_LIST_BIT (str[0]); |
| 9734 | + } |
| 9735 | +# ifdef _LIBC |
| 9736 | + else |
| 9737 | + { |
| 9738 | + /* Try to match the byte sequence in `str' against |
| 9739 | + those known to the collate implementation. |
| 9740 | + First find out whether the bytes in `str' are |
| 9741 | + actually from exactly one character. */ |
| 9742 | + const int32_t *table; |
| 9743 | + const unsigned char *weights; |
| 9744 | + const unsigned char *extra; |
| 9745 | + const int32_t *indirect; |
| 9746 | + int32_t idx; |
| 9747 | + const unsigned char *cp = str; |
| 9748 | + int ch; |
| 9749 | + |
| 9750 | + table = (const int32_t *) |
| 9751 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); |
| 9752 | + weights = (const unsigned char *) |
| 9753 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); |
| 9754 | + extra = (const unsigned char *) |
| 9755 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); |
| 9756 | + indirect = (const int32_t *) |
| 9757 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); |
| 9758 | + idx = FINDIDX (table, indirect, extra, &cp, 1); |
| 9759 | + if (idx == 0 || cp < str + c1) |
| 9760 | + /* This is no valid character. */ |
| 9761 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9762 | + |
| 9763 | + /* Throw away the ] at the end of the equivalence |
| 9764 | + class. */ |
| 9765 | + PATFETCH (c); |
| 9766 | + |
| 9767 | + /* Now we have to go throught the whole table |
| 9768 | + and find all characters which have the same |
| 9769 | + first level weight. |
| 9770 | + |
| 9771 | + XXX Note that this is not entirely correct. |
| 9772 | + we would have to match multibyte sequences |
| 9773 | + but this is not possible with the current |
| 9774 | + implementation. */ |
| 9775 | + for (ch = 1; ch < 256; ++ch) |
| 9776 | + /* XXX This test would have to be changed if we |
| 9777 | + would allow matching multibyte sequences. */ |
| 9778 | + if (table[ch] > 0) |
| 9779 | + { |
| 9780 | + int32_t idx2 = table[ch]; |
| 9781 | + size_t len = weights[idx2]; |
| 9782 | + |
| 9783 | + /* Test whether the lenghts match. */ |
| 9784 | + if (weights[idx] == len) |
| 9785 | + { |
| 9786 | + /* They do. New compare the bytes of |
| 9787 | + the weight. */ |
| 9788 | + size_t cnt = 0; |
| 9789 | + |
| 9790 | + while (cnt < len |
| 9791 | + && (weights[idx + 1 + cnt] |
| 9792 | + == weights[idx2 + 1 + cnt])) |
| 9793 | + ++cnt; |
| 9794 | + |
| 9795 | + if (cnt == len) |
| 9796 | + /* They match. Mark the character as |
| 9797 | + acceptable. */ |
| 9798 | + SET_LIST_BIT (ch); |
| 9799 | + } |
| 9800 | + } |
| 9801 | + } |
| 9802 | +# endif |
| 9803 | + had_char_class = true; |
| 9804 | + } |
| 9805 | + else |
| 9806 | + { |
| 9807 | + c1++; |
| 9808 | + while (c1--) |
| 9809 | + PATUNFETCH; |
| 9810 | + SET_LIST_BIT ('['); |
| 9811 | + SET_LIST_BIT ('='); |
| 9812 | + range_start = '='; |
| 9813 | + had_char_class = false; |
| 9814 | + } |
| 9815 | + } |
| 9816 | + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.') |
| 9817 | + { |
| 9818 | + unsigned char str[128]; /* Should be large enough. */ |
| 9819 | +# ifdef _LIBC |
| 9820 | + uint32_t nrules = |
| 9821 | + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 9822 | +# endif |
| 9823 | + |
| 9824 | + PATFETCH (c); |
| 9825 | + c1 = 0; |
| 9826 | + |
| 9827 | + /* If pattern is `[[.'. */ |
| 9828 | + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); |
| 9829 | + |
| 9830 | + for (;;) |
| 9831 | + { |
| 9832 | + PATFETCH (c); |
| 9833 | + if ((c == '.' && *p == ']') || p == pend) |
| 9834 | + break; |
| 9835 | + if (c1 < sizeof (str)) |
| 9836 | + str[c1++] = c; |
| 9837 | + else |
| 9838 | + /* This is in any case an invalid class name. */ |
| 9839 | + str[0] = '\0'; |
| 9840 | + } |
| 9841 | + str[c1] = '\0'; |
| 9842 | + |
| 9843 | + if (c == '.' && *p == ']' && str[0] != '\0') |
| 9844 | + { |
| 9845 | + /* If we have no collation data we use the default |
| 9846 | + collation in which each character is the name |
| 9847 | + for its own class which contains only the one |
| 9848 | + character. It also means that ASCII is the |
| 9849 | + character set and therefore we cannot have character |
| 9850 | + with more than one byte in the multibyte |
| 9851 | + representation. */ |
| 9852 | +# ifdef _LIBC |
| 9853 | + if (nrules == 0) |
| 9854 | +# endif |
| 9855 | + { |
| 9856 | + if (c1 != 1) |
| 9857 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9858 | + |
| 9859 | + /* Throw away the ] at the end of the equivalence |
| 9860 | + class. */ |
| 9861 | + PATFETCH (c); |
| 9862 | + |
| 9863 | + /* Set the bit for the character. */ |
| 9864 | + SET_LIST_BIT (str[0]); |
| 9865 | + range_start = ((const unsigned char *) str)[0]; |
| 9866 | + } |
| 9867 | +# ifdef _LIBC |
| 9868 | + else |
| 9869 | + { |
| 9870 | + /* Try to match the byte sequence in `str' against |
| 9871 | + those known to the collate implementation. |
| 9872 | + First find out whether the bytes in `str' are |
| 9873 | + actually from exactly one character. */ |
| 9874 | + int32_t table_size; |
| 9875 | + const int32_t *symb_table; |
| 9876 | + const unsigned char *extra; |
| 9877 | + int32_t idx; |
| 9878 | + int32_t elem; |
| 9879 | + int32_t second; |
| 9880 | + int32_t hash; |
| 9881 | + |
| 9882 | + table_size = |
| 9883 | + _NL_CURRENT_WORD (LC_COLLATE, |
| 9884 | + _NL_COLLATE_SYMB_HASH_SIZEMB); |
| 9885 | + symb_table = (const int32_t *) |
| 9886 | + _NL_CURRENT (LC_COLLATE, |
| 9887 | + _NL_COLLATE_SYMB_TABLEMB); |
| 9888 | + extra = (const unsigned char *) |
| 9889 | + _NL_CURRENT (LC_COLLATE, |
| 9890 | + _NL_COLLATE_SYMB_EXTRAMB); |
| 9891 | + |
| 9892 | + /* Locate the character in the hashing table. */ |
| 9893 | + hash = elem_hash ((const char *) str, c1); |
| 9894 | + |
| 9895 | + idx = 0; |
| 9896 | + elem = hash % table_size; |
| 9897 | + second = hash % (table_size - 2); |
| 9898 | + while (symb_table[2 * elem] != 0) |
| 9899 | + { |
| 9900 | + /* First compare the hashing value. */ |
| 9901 | + if (symb_table[2 * elem] == hash |
| 9902 | + && c1 == extra[symb_table[2 * elem + 1]] |
| 9903 | + && memcmp (str, |
| 9904 | + &extra[symb_table[2 * elem + 1] |
| 9905 | + + 1], |
| 9906 | + c1) == 0) |
| 9907 | + { |
| 9908 | + /* Yep, this is the entry. */ |
| 9909 | + idx = symb_table[2 * elem + 1]; |
| 9910 | + idx += 1 + extra[idx]; |
| 9911 | + break; |
| 9912 | + } |
| 9913 | + |
| 9914 | + /* Next entry. */ |
| 9915 | + elem += second; |
| 9916 | + } |
| 9917 | + |
| 9918 | + if (symb_table[2 * elem] == 0) |
| 9919 | + /* This is no valid character. */ |
| 9920 | + FREE_STACK_RETURN (REG_ECOLLATE); |
| 9921 | + |
| 9922 | + /* Throw away the ] at the end of the equivalence |
| 9923 | + class. */ |
| 9924 | + PATFETCH (c); |
| 9925 | + |
| 9926 | + /* Now add the multibyte character(s) we found |
| 9927 | + to the accept list. |
| 9928 | + |
| 9929 | + XXX Note that this is not entirely correct. |
| 9930 | + we would have to match multibyte sequences |
| 9931 | + but this is not possible with the current |
| 9932 | + implementation. Also, we have to match |
| 9933 | + collating symbols, which expand to more than |
| 9934 | + one file, as a whole and not allow the |
| 9935 | + individual bytes. */ |
| 9936 | + c1 = extra[idx++]; |
| 9937 | + if (c1 == 1) |
| 9938 | + range_start = extra[idx]; |
| 9939 | + while (c1-- > 0) |
| 9940 | + { |
| 9941 | + SET_LIST_BIT (extra[idx]); |
| 9942 | + ++idx; |
| 9943 | + } |
| 9944 | + } |
| 9945 | +# endif |
| 9946 | + had_char_class = false; |
| 9947 | + } |
| 9948 | + else |
| 9949 | + { |
| 9950 | + c1++; |
| 9951 | + while (c1--) |
| 9952 | + PATUNFETCH; |
| 9953 | + SET_LIST_BIT ('['); |
| 9954 | + SET_LIST_BIT ('.'); |
| 9955 | + range_start = '.'; |
| 9956 | + had_char_class = false; |
| 9957 | + } |
| 9958 | + } |
| 9959 | + else |
| 9960 | + { |
| 9961 | + had_char_class = false; |
| 9962 | + SET_LIST_BIT (c); |
| 9963 | + range_start = c; |
| 9964 | + } |
| 9965 | + } |
| 9966 | + |
| 9967 | + /* Discard any (non)matching list bytes that are all 0 at the |
| 9968 | + end of the map. Decrease the map-length byte too. */ |
| 9969 | + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) |
| 9970 | + b[-1]--; |
| 9971 | + b += b[-1]; |
| 9972 | +#endif /* WCHAR */ |
| 9973 | + } |
| 9974 | + break; |
| 9975 | + |
| 9976 | + |
| 9977 | + case '(': |
| 9978 | + if (syntax & RE_NO_BK_PARENS) |
| 9979 | + goto handle_open; |
| 9980 | + else |
| 9981 | + goto normal_char; |
| 9982 | + |
| 9983 | + |
| 9984 | + case ')': |
| 9985 | + if (syntax & RE_NO_BK_PARENS) |
| 9986 | + goto handle_close; |
| 9987 | + else |
| 9988 | + goto normal_char; |
| 9989 | + |
| 9990 | + |
| 9991 | + case '\n': |
| 9992 | + if (syntax & RE_NEWLINE_ALT) |
| 9993 | + goto handle_alt; |
| 9994 | + else |
| 9995 | + goto normal_char; |
| 9996 | + |
| 9997 | + |
| 9998 | + case '|': |
| 9999 | + if (syntax & RE_NO_BK_VBAR) |
| 10000 | + goto handle_alt; |
| 10001 | + else |
| 10002 | + goto normal_char; |
| 10003 | + |
| 10004 | + |
| 10005 | + case '{': |
| 10006 | + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) |
| 10007 | + goto handle_interval; |
| 10008 | + else |
| 10009 | + goto normal_char; |
| 10010 | + |
| 10011 | + |
| 10012 | + case '\\': |
| 10013 | + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); |
| 10014 | + |
| 10015 | + /* Do not translate the character after the \, so that we can |
| 10016 | + distinguish, e.g., \B from \b, even if we normally would |
| 10017 | + translate, e.g., B to b. */ |
| 10018 | + PATFETCH_RAW (c); |
| 10019 | + |
| 10020 | + switch (c) |
| 10021 | + { |
| 10022 | + case '(': |
| 10023 | + if (syntax & RE_NO_BK_PARENS) |
| 10024 | + goto normal_backslash; |
| 10025 | + |
| 10026 | + handle_open: |
| 10027 | + bufp->re_nsub++; |
| 10028 | + regnum++; |
| 10029 | + |
| 10030 | + if (COMPILE_STACK_FULL) |
| 10031 | + { |
| 10032 | + RETALLOC (compile_stack.stack, compile_stack.size << 1, |
| 10033 | + compile_stack_elt_t); |
| 10034 | + if (compile_stack.stack == NULL) return REG_ESPACE; |
| 10035 | + |
| 10036 | + compile_stack.size <<= 1; |
| 10037 | + } |
| 10038 | + |
| 10039 | + /* These are the values to restore when we hit end of this |
| 10040 | + group. They are all relative offsets, so that if the |
| 10041 | + whole pattern moves because of realloc, they will still |
| 10042 | + be valid. */ |
| 10043 | + COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR; |
| 10044 | + COMPILE_STACK_TOP.fixup_alt_jump |
| 10045 | + = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0; |
| 10046 | + COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR; |
| 10047 | + COMPILE_STACK_TOP.regnum = regnum; |
| 10048 | + |
| 10049 | + /* We will eventually replace the 0 with the number of |
| 10050 | + groups inner to this one. But do not push a |
| 10051 | + start_memory for groups beyond the last one we can |
| 10052 | + represent in the compiled pattern. */ |
| 10053 | + if (regnum <= MAX_REGNUM) |
| 10054 | + { |
| 10055 | + COMPILE_STACK_TOP.inner_group_offset = b |
| 10056 | + - COMPILED_BUFFER_VAR + 2; |
| 10057 | + BUF_PUSH_3 (start_memory, regnum, 0); |
| 10058 | + } |
| 10059 | + |
| 10060 | + compile_stack.avail++; |
| 10061 | + |
| 10062 | + fixup_alt_jump = 0; |
| 10063 | + laststart = 0; |
| 10064 | + begalt = b; |
| 10065 | + /* If we've reached MAX_REGNUM groups, then this open |
| 10066 | + won't actually generate any code, so we'll have to |
| 10067 | + clear pending_exact explicitly. */ |
| 10068 | + pending_exact = 0; |
| 10069 | + break; |
| 10070 | + |
| 10071 | + |
| 10072 | + case ')': |
| 10073 | + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; |
| 10074 | + |
| 10075 | + if (COMPILE_STACK_EMPTY) |
| 10076 | + { |
| 10077 | + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) |
| 10078 | + goto normal_backslash; |
| 10079 | + else |
| 10080 | + FREE_STACK_RETURN (REG_ERPAREN); |
| 10081 | + } |
| 10082 | + |
| 10083 | + handle_close: |
| 10084 | + if (fixup_alt_jump) |
| 10085 | + { /* Push a dummy failure point at the end of the |
| 10086 | + alternative for a possible future |
| 10087 | + `pop_failure_jump' to pop. See comments at |
| 10088 | + `push_dummy_failure' in `re_match_2'. */ |
| 10089 | + BUF_PUSH (push_dummy_failure); |
| 10090 | + |
| 10091 | + /* We allocated space for this jump when we assigned |
| 10092 | + to `fixup_alt_jump', in the `handle_alt' case below. */ |
| 10093 | + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); |
| 10094 | + } |
| 10095 | + |
| 10096 | + /* See similar code for backslashed left paren above. */ |
| 10097 | + if (COMPILE_STACK_EMPTY) |
| 10098 | + { |
| 10099 | + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) |
| 10100 | + goto normal_char; |
| 10101 | + else |
| 10102 | + FREE_STACK_RETURN (REG_ERPAREN); |
| 10103 | + } |
| 10104 | + |
| 10105 | + /* Since we just checked for an empty stack above, this |
| 10106 | + ``can't happen''. */ |
| 10107 | + assert (compile_stack.avail != 0); |
| 10108 | + { |
| 10109 | + /* We don't just want to restore into `regnum', because |
| 10110 | + later groups should continue to be numbered higher, |
| 10111 | + as in `(ab)c(de)' -- the second group is #2. */ |
| 10112 | + regnum_t this_group_regnum; |
| 10113 | + |
| 10114 | + compile_stack.avail--; |
| 10115 | + begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset; |
| 10116 | + fixup_alt_jump |
| 10117 | + = COMPILE_STACK_TOP.fixup_alt_jump |
| 10118 | + ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1 |
| 10119 | + : 0; |
| 10120 | + laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset; |
| 10121 | + this_group_regnum = COMPILE_STACK_TOP.regnum; |
| 10122 | + /* If we've reached MAX_REGNUM groups, then this open |
| 10123 | + won't actually generate any code, so we'll have to |
| 10124 | + clear pending_exact explicitly. */ |
| 10125 | + pending_exact = 0; |
| 10126 | + |
| 10127 | + /* We're at the end of the group, so now we know how many |
| 10128 | + groups were inside this one. */ |
| 10129 | + if (this_group_regnum <= MAX_REGNUM) |
| 10130 | + { |
| 10131 | + UCHAR_T *inner_group_loc |
| 10132 | + = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; |
| 10133 | + |
| 10134 | + *inner_group_loc = regnum - this_group_regnum; |
| 10135 | + BUF_PUSH_3 (stop_memory, this_group_regnum, |
| 10136 | + regnum - this_group_regnum); |
| 10137 | + } |
| 10138 | + } |
| 10139 | + break; |
| 10140 | + |
| 10141 | + |
| 10142 | + case '|': /* `\|'. */ |
| 10143 | + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) |
| 10144 | + goto normal_backslash; |
| 10145 | + handle_alt: |
| 10146 | + if (syntax & RE_LIMITED_OPS) |
| 10147 | + goto normal_char; |
| 10148 | + |
| 10149 | + /* Insert before the previous alternative a jump which |
| 10150 | + jumps to this alternative if the former fails. */ |
| 10151 | + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); |
| 10152 | + INSERT_JUMP (on_failure_jump, begalt, |
| 10153 | + b + 2 + 2 * OFFSET_ADDRESS_SIZE); |
| 10154 | + pending_exact = 0; |
| 10155 | + b += 1 + OFFSET_ADDRESS_SIZE; |
| 10156 | + |
| 10157 | + /* The alternative before this one has a jump after it |
| 10158 | + which gets executed if it gets matched. Adjust that |
| 10159 | + jump so it will jump to this alternative's analogous |
| 10160 | + jump (put in below, which in turn will jump to the next |
| 10161 | + (if any) alternative's such jump, etc.). The last such |
| 10162 | + jump jumps to the correct final destination. A picture: |
| 10163 | + _____ _____ |
| 10164 | + | | | | |
| 10165 | + | v | v |
| 10166 | + a | b | c |
| 10167 | + |
| 10168 | + If we are at `b', then fixup_alt_jump right now points to a |
| 10169 | + three-byte space after `a'. We'll put in the jump, set |
| 10170 | + fixup_alt_jump to right after `b', and leave behind three |
| 10171 | + bytes which we'll fill in when we get to after `c'. */ |
| 10172 | + |
| 10173 | + if (fixup_alt_jump) |
| 10174 | + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); |
| 10175 | + |
| 10176 | + /* Mark and leave space for a jump after this alternative, |
| 10177 | + to be filled in later either by next alternative or |
| 10178 | + when know we're at the end of a series of alternatives. */ |
| 10179 | + fixup_alt_jump = b; |
| 10180 | + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); |
| 10181 | + b += 1 + OFFSET_ADDRESS_SIZE; |
| 10182 | + |
| 10183 | + laststart = 0; |
| 10184 | + begalt = b; |
| 10185 | + break; |
| 10186 | + |
| 10187 | + |
| 10188 | + case '{': |
| 10189 | + /* If \{ is a literal. */ |
| 10190 | + if (!(syntax & RE_INTERVALS) |
| 10191 | + /* If we're at `\{' and it's not the open-interval |
| 10192 | + operator. */ |
| 10193 | + || (syntax & RE_NO_BK_BRACES)) |
| 10194 | + goto normal_backslash; |
| 10195 | + |
| 10196 | + handle_interval: |
| 10197 | + { |
| 10198 | + /* If got here, then the syntax allows intervals. */ |
| 10199 | + |
| 10200 | + /* At least (most) this many matches must be made. */ |
| 10201 | + int lower_bound = -1, upper_bound = -1; |
| 10202 | + |
| 10203 | + /* Place in the uncompiled pattern (i.e., just after |
| 10204 | + the '{') to go back to if the interval is invalid. */ |
| 10205 | + const CHAR_T *beg_interval = p; |
| 10206 | + |
| 10207 | + if (p == pend) |
| 10208 | + goto invalid_interval; |
| 10209 | + |
| 10210 | + GET_UNSIGNED_NUMBER (lower_bound); |
| 10211 | + |
| 10212 | + if (c == ',') |
| 10213 | + { |
| 10214 | + GET_UNSIGNED_NUMBER (upper_bound); |
| 10215 | + if (upper_bound < 0) |
| 10216 | + upper_bound = RE_DUP_MAX; |
| 10217 | + } |
| 10218 | + else |
| 10219 | + /* Interval such as `{1}' => match exactly once. */ |
| 10220 | + upper_bound = lower_bound; |
| 10221 | + |
| 10222 | + if (! (0 <= lower_bound && lower_bound <= upper_bound)) |
| 10223 | + goto invalid_interval; |
| 10224 | + |
| 10225 | + if (!(syntax & RE_NO_BK_BRACES)) |
| 10226 | + { |
| 10227 | + if (c != '\\' || p == pend) |
| 10228 | + goto invalid_interval; |
| 10229 | + PATFETCH (c); |
| 10230 | + } |
| 10231 | + |
| 10232 | + if (c != '}') |
| 10233 | + goto invalid_interval; |
| 10234 | + |
| 10235 | + /* If it's invalid to have no preceding re. */ |
| 10236 | + if (!laststart) |
| 10237 | + { |
| 10238 | + if (syntax & RE_CONTEXT_INVALID_OPS |
| 10239 | + && !(syntax & RE_INVALID_INTERVAL_ORD)) |
| 10240 | + FREE_STACK_RETURN (REG_BADRPT); |
| 10241 | + else if (syntax & RE_CONTEXT_INDEP_OPS) |
| 10242 | + laststart = b; |
| 10243 | + else |
| 10244 | + goto unfetch_interval; |
| 10245 | + } |
| 10246 | + |
| 10247 | + /* We just parsed a valid interval. */ |
| 10248 | + |
| 10249 | + if (RE_DUP_MAX < upper_bound) |
| 10250 | + FREE_STACK_RETURN (REG_BADBR); |
| 10251 | + |
| 10252 | + /* If the upper bound is zero, don't want to succeed at |
| 10253 | + all; jump from `laststart' to `b + 3', which will be |
| 10254 | + the end of the buffer after we insert the jump. */ |
| 10255 | + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' |
| 10256 | + instead of 'b + 3'. */ |
| 10257 | + if (upper_bound == 0) |
| 10258 | + { |
| 10259 | + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); |
| 10260 | + INSERT_JUMP (jump, laststart, b + 1 |
| 10261 | + + OFFSET_ADDRESS_SIZE); |
| 10262 | + b += 1 + OFFSET_ADDRESS_SIZE; |
| 10263 | + } |
| 10264 | + |
| 10265 | + /* Otherwise, we have a nontrivial interval. When |
| 10266 | + we're all done, the pattern will look like: |
| 10267 | + set_number_at <jump count> <upper bound> |
| 10268 | + set_number_at <succeed_n count> <lower bound> |
| 10269 | + succeed_n <after jump addr> <succeed_n count> |
| 10270 | + <body of loop> |
| 10271 | + jump_n <succeed_n addr> <jump count> |
| 10272 | + (The upper bound and `jump_n' are omitted if |
| 10273 | + `upper_bound' is 1, though.) */ |
| 10274 | + else |
| 10275 | + { /* If the upper bound is > 1, we need to insert |
| 10276 | + more at the end of the loop. */ |
| 10277 | + unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE + |
| 10278 | + (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE); |
| 10279 | + |
| 10280 | + GET_BUFFER_SPACE (nbytes); |
| 10281 | + |
| 10282 | + /* Initialize lower bound of the `succeed_n', even |
| 10283 | + though it will be set during matching by its |
| 10284 | + attendant `set_number_at' (inserted next), |
| 10285 | + because `re_compile_fastmap' needs to know. |
| 10286 | + Jump to the `jump_n' we might insert below. */ |
| 10287 | + INSERT_JUMP2 (succeed_n, laststart, |
| 10288 | + b + 1 + 2 * OFFSET_ADDRESS_SIZE |
| 10289 | + + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE) |
| 10290 | + , lower_bound); |
| 10291 | + b += 1 + 2 * OFFSET_ADDRESS_SIZE; |
| 10292 | + |
| 10293 | + /* Code to initialize the lower bound. Insert |
| 10294 | + before the `succeed_n'. The `5' is the last two |
| 10295 | + bytes of this `set_number_at', plus 3 bytes of |
| 10296 | + the following `succeed_n'. */ |
| 10297 | + /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' |
| 10298 | + is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' |
| 10299 | + of the following `succeed_n'. */ |
| 10300 | + PREFIX(insert_op2) (set_number_at, laststart, 1 |
| 10301 | + + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); |
| 10302 | + b += 1 + 2 * OFFSET_ADDRESS_SIZE; |
| 10303 | + |
| 10304 | + if (upper_bound > 1) |
| 10305 | + { /* More than one repetition is allowed, so |
| 10306 | + append a backward jump to the `succeed_n' |
| 10307 | + that starts this interval. |
| 10308 | + |
| 10309 | + When we've reached this during matching, |
| 10310 | + we'll have matched the interval once, so |
| 10311 | + jump back only `upper_bound - 1' times. */ |
| 10312 | + STORE_JUMP2 (jump_n, b, laststart |
| 10313 | + + 2 * OFFSET_ADDRESS_SIZE + 1, |
| 10314 | + upper_bound - 1); |
| 10315 | + b += 1 + 2 * OFFSET_ADDRESS_SIZE; |
| 10316 | + |
| 10317 | + /* The location we want to set is the second |
| 10318 | + parameter of the `jump_n'; that is `b-2' as |
| 10319 | + an absolute address. `laststart' will be |
| 10320 | + the `set_number_at' we're about to insert; |
| 10321 | + `laststart+3' the number to set, the source |
| 10322 | + for the relative address. But we are |
| 10323 | + inserting into the middle of the pattern -- |
| 10324 | + so everything is getting moved up by 5. |
| 10325 | + Conclusion: (b - 2) - (laststart + 3) + 5, |
| 10326 | + i.e., b - laststart. |
| 10327 | + |
| 10328 | + We insert this at the beginning of the loop |
| 10329 | + so that if we fail during matching, we'll |
| 10330 | + reinitialize the bounds. */ |
| 10331 | + PREFIX(insert_op2) (set_number_at, laststart, |
| 10332 | + b - laststart, |
| 10333 | + upper_bound - 1, b); |
| 10334 | + b += 1 + 2 * OFFSET_ADDRESS_SIZE; |
| 10335 | + } |
| 10336 | + } |
| 10337 | + pending_exact = 0; |
| 10338 | + break; |
| 10339 | + |
| 10340 | + invalid_interval: |
| 10341 | + if (!(syntax & RE_INVALID_INTERVAL_ORD)) |
| 10342 | + FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR); |
| 10343 | + unfetch_interval: |
| 10344 | + /* Match the characters as literals. */ |
| 10345 | + p = beg_interval; |
| 10346 | + c = '{'; |
| 10347 | + if (syntax & RE_NO_BK_BRACES) |
| 10348 | + goto normal_char; |
| 10349 | + else |
| 10350 | + goto normal_backslash; |
| 10351 | + } |
| 10352 | + |
| 10353 | +#ifdef emacs |
| 10354 | + /* There is no way to specify the before_dot and after_dot |
| 10355 | + operators. rms says this is ok. --karl */ |
| 10356 | + case '=': |
| 10357 | + BUF_PUSH (at_dot); |
| 10358 | + break; |
| 10359 | + |
| 10360 | + case 's': |
| 10361 | + laststart = b; |
| 10362 | + PATFETCH (c); |
| 10363 | + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); |
| 10364 | + break; |
| 10365 | + |
| 10366 | + case 'S': |
| 10367 | + laststart = b; |
| 10368 | + PATFETCH (c); |
| 10369 | + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); |
| 10370 | + break; |
| 10371 | +#endif /* emacs */ |
| 10372 | + |
| 10373 | + |
| 10374 | + case 'w': |
| 10375 | + if (syntax & RE_NO_GNU_OPS) |
| 10376 | + goto normal_char; |
| 10377 | + laststart = b; |
| 10378 | + BUF_PUSH (wordchar); |
| 10379 | + break; |
| 10380 | + |
| 10381 | + |
| 10382 | + case 'W': |
| 10383 | + if (syntax & RE_NO_GNU_OPS) |
| 10384 | + goto normal_char; |
| 10385 | + laststart = b; |
| 10386 | + BUF_PUSH (notwordchar); |
| 10387 | + break; |
| 10388 | + |
| 10389 | + |
| 10390 | + case '<': |
| 10391 | + if (syntax & RE_NO_GNU_OPS) |
| 10392 | + goto normal_char; |
| 10393 | + BUF_PUSH (wordbeg); |
| 10394 | + break; |
| 10395 | + |
| 10396 | + case '>': |
| 10397 | + if (syntax & RE_NO_GNU_OPS) |
| 10398 | + goto normal_char; |
| 10399 | + BUF_PUSH (wordend); |
| 10400 | + break; |
| 10401 | + |
| 10402 | + case 'b': |
| 10403 | + if (syntax & RE_NO_GNU_OPS) |
| 10404 | + goto normal_char; |
| 10405 | + BUF_PUSH (wordbound); |
| 10406 | + break; |
| 10407 | + |
| 10408 | + case 'B': |
| 10409 | + if (syntax & RE_NO_GNU_OPS) |
| 10410 | + goto normal_char; |
| 10411 | + BUF_PUSH (notwordbound); |
| 10412 | + break; |
| 10413 | + |
| 10414 | + case '`': |
| 10415 | + if (syntax & RE_NO_GNU_OPS) |
| 10416 | + goto normal_char; |
| 10417 | + BUF_PUSH (begbuf); |
| 10418 | + break; |
| 10419 | + |
| 10420 | + case '\'': |
| 10421 | + if (syntax & RE_NO_GNU_OPS) |
| 10422 | + goto normal_char; |
| 10423 | + BUF_PUSH (endbuf); |
| 10424 | + break; |
| 10425 | + |
| 10426 | + case '1': case '2': case '3': case '4': case '5': |
| 10427 | + case '6': case '7': case '8': case '9': |
| 10428 | + if (syntax & RE_NO_BK_REFS) |
| 10429 | + goto normal_char; |
| 10430 | + |
| 10431 | + c1 = c - '0'; |
| 10432 | + |
| 10433 | + if (c1 > regnum) |
| 10434 | + FREE_STACK_RETURN (REG_ESUBREG); |
| 10435 | + |
| 10436 | + /* Can't back reference to a subexpression if inside of it. */ |
| 10437 | + if (group_in_compile_stack (compile_stack, (regnum_t) c1)) |
| 10438 | + goto normal_char; |
| 10439 | + |
| 10440 | + laststart = b; |
| 10441 | + BUF_PUSH_2 (duplicate, c1); |
| 10442 | + break; |
| 10443 | + |
| 10444 | + |
| 10445 | + case '+': |
| 10446 | + case '?': |
| 10447 | + if (syntax & RE_BK_PLUS_QM) |
| 10448 | + goto handle_plus; |
| 10449 | + else |
| 10450 | + goto normal_backslash; |
| 10451 | + |
| 10452 | + default: |
| 10453 | + normal_backslash: |
| 10454 | + /* You might think it would be useful for \ to mean |
| 10455 | + not to translate; but if we don't translate it |
| 10456 | + it will never match anything. */ |
| 10457 | + c = TRANSLATE (c); |
| 10458 | + goto normal_char; |
| 10459 | + } |
| 10460 | + break; |
| 10461 | + |
| 10462 | + |
| 10463 | + default: |
| 10464 | + /* Expects the character in `c'. */ |
| 10465 | + normal_char: |
| 10466 | + /* If no exactn currently being built. */ |
| 10467 | + if (!pending_exact |
| 10468 | +#ifdef WCHAR |
| 10469 | + /* If last exactn handle binary(or character) and |
| 10470 | + new exactn handle character(or binary). */ |
| 10471 | + || is_exactn_bin != is_binary[p - 1 - pattern] |
| 10472 | +#endif /* WCHAR */ |
| 10473 | + |
| 10474 | + /* If last exactn not at current position. */ |
| 10475 | + || pending_exact + *pending_exact + 1 != b |
| 10476 | + |
| 10477 | + /* We have only one byte following the exactn for the count. */ |
| 10478 | + || *pending_exact == (1 << BYTEWIDTH) - 1 |
| 10479 | + |
| 10480 | + /* If followed by a repetition operator. */ |
| 10481 | + || *p == '*' || *p == '^' |
| 10482 | + || ((syntax & RE_BK_PLUS_QM) |
| 10483 | + ? *p == '\\' && (p[1] == '+' || p[1] == '?') |
| 10484 | + : (*p == '+' || *p == '?')) |
| 10485 | + || ((syntax & RE_INTERVALS) |
| 10486 | + && ((syntax & RE_NO_BK_BRACES) |
| 10487 | + ? *p == '{' |
| 10488 | + : (p[0] == '\\' && p[1] == '{')))) |
| 10489 | + { |
| 10490 | + /* Start building a new exactn. */ |
| 10491 | + |
| 10492 | + laststart = b; |
| 10493 | + |
| 10494 | +#ifdef WCHAR |
| 10495 | + /* Is this exactn binary data or character? */ |
| 10496 | + is_exactn_bin = is_binary[p - 1 - pattern]; |
| 10497 | + if (is_exactn_bin) |
| 10498 | + BUF_PUSH_2 (exactn_bin, 0); |
| 10499 | + else |
| 10500 | + BUF_PUSH_2 (exactn, 0); |
| 10501 | +#else |
| 10502 | + BUF_PUSH_2 (exactn, 0); |
| 10503 | +#endif /* WCHAR */ |
| 10504 | + pending_exact = b - 1; |
| 10505 | + } |
| 10506 | + |
| 10507 | + BUF_PUSH (c); |
| 10508 | + (*pending_exact)++; |
| 10509 | + break; |
| 10510 | + } /* switch (c) */ |
| 10511 | + } /* while p != pend */ |
| 10512 | + |
| 10513 | + |
| 10514 | + /* Through the pattern now. */ |
| 10515 | + |
| 10516 | + if (fixup_alt_jump) |
| 10517 | + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); |
| 10518 | + |
| 10519 | + if (!COMPILE_STACK_EMPTY) |
| 10520 | + FREE_STACK_RETURN (REG_EPAREN); |
| 10521 | + |
| 10522 | + /* If we don't want backtracking, force success |
| 10523 | + the first time we reach the end of the compiled pattern. */ |
| 10524 | + if (syntax & RE_NO_POSIX_BACKTRACKING) |
| 10525 | + BUF_PUSH (succeed); |
| 10526 | + |
| 10527 | +#ifdef WCHAR |
| 10528 | + free (pattern); |
| 10529 | + free (mbs_offset); |
| 10530 | + free (is_binary); |
| 10531 | +#endif |
| 10532 | + free (compile_stack.stack); |
| 10533 | + |
| 10534 | + /* We have succeeded; set the length of the buffer. */ |
| 10535 | +#ifdef WCHAR |
| 10536 | + bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; |
| 10537 | +#else |
| 10538 | + bufp->used = b - bufp->buffer; |
| 10539 | +#endif |
| 10540 | + |
| 10541 | +#ifdef DEBUG |
| 10542 | + if (debug) |
| 10543 | + { |
| 10544 | + DEBUG_PRINT1 ("\nCompiled pattern: \n"); |
| 10545 | + PREFIX(print_compiled_pattern) (bufp); |
| 10546 | + } |
| 10547 | +#endif /* DEBUG */ |
| 10548 | + |
| 10549 | +#ifndef MATCH_MAY_ALLOCATE |
| 10550 | + /* Initialize the failure stack to the largest possible stack. This |
| 10551 | + isn't necessary unless we're trying to avoid calling alloca in |
| 10552 | + the search and match routines. */ |
| 10553 | + { |
| 10554 | + int num_regs = bufp->re_nsub + 1; |
| 10555 | + |
| 10556 | + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size |
| 10557 | + is strictly greater than re_max_failures, the largest possible stack |
| 10558 | + is 2 * re_max_failures failure points. */ |
| 10559 | + if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) |
| 10560 | + { |
| 10561 | + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); |
| 10562 | + |
| 10563 | +# ifdef emacs |
| 10564 | + if (! fail_stack.stack) |
| 10565 | + fail_stack.stack |
| 10566 | + = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size |
| 10567 | + * sizeof (PREFIX(fail_stack_elt_t))); |
| 10568 | + else |
| 10569 | + fail_stack.stack |
| 10570 | + = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, |
| 10571 | + (fail_stack.size |
| 10572 | + * sizeof (PREFIX(fail_stack_elt_t)))); |
| 10573 | +# else /* not emacs */ |
| 10574 | + if (! fail_stack.stack) |
| 10575 | + fail_stack.stack |
| 10576 | + = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size |
| 10577 | + * sizeof (PREFIX(fail_stack_elt_t))); |
| 10578 | + else |
| 10579 | + fail_stack.stack |
| 10580 | + = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack, |
| 10581 | + (fail_stack.size |
| 10582 | + * sizeof (PREFIX(fail_stack_elt_t)))); |
| 10583 | +# endif /* not emacs */ |
| 10584 | + } |
| 10585 | + |
| 10586 | + PREFIX(regex_grow_registers) (num_regs); |
| 10587 | + } |
| 10588 | +#endif /* not MATCH_MAY_ALLOCATE */ |
| 10589 | + |
| 10590 | + return REG_NOERROR; |
| 10591 | +} /* regex_compile */ |
| 10592 | + |
| 10593 | +/* Subroutines for `regex_compile'. */ |
| 10594 | + |
| 10595 | +/* Store OP at LOC followed by two-byte integer parameter ARG. */ |
| 10596 | +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ |
| 10597 | + |
| 10598 | +static void |
| 10599 | +PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg) |
| 10600 | +{ |
| 10601 | + *loc = (UCHAR_T) op; |
| 10602 | + STORE_NUMBER (loc + 1, arg); |
| 10603 | +} |
| 10604 | + |
| 10605 | + |
| 10606 | +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ |
| 10607 | +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ |
| 10608 | + |
| 10609 | +static void |
| 10610 | +PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2) |
| 10611 | +{ |
| 10612 | + *loc = (UCHAR_T) op; |
| 10613 | + STORE_NUMBER (loc + 1, arg1); |
| 10614 | + STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); |
| 10615 | +} |
| 10616 | + |
| 10617 | + |
| 10618 | +/* Copy the bytes from LOC to END to open up three bytes of space at LOC |
| 10619 | + for OP followed by two-byte integer parameter ARG. */ |
| 10620 | +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ |
| 10621 | + |
| 10622 | +static void |
| 10623 | +PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end) |
| 10624 | +{ |
| 10625 | + register UCHAR_T *pfrom = end; |
| 10626 | + register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; |
| 10627 | + |
| 10628 | + while (pfrom != loc) |
| 10629 | + *--pto = *--pfrom; |
| 10630 | + |
| 10631 | + PREFIX(store_op1) (op, loc, arg); |
| 10632 | +} |
| 10633 | + |
| 10634 | + |
| 10635 | +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ |
| 10636 | +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ |
| 10637 | + |
| 10638 | +static void |
| 10639 | +PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, |
| 10640 | + int arg2, UCHAR_T *end) |
| 10641 | +{ |
| 10642 | + register UCHAR_T *pfrom = end; |
| 10643 | + register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; |
| 10644 | + |
| 10645 | + while (pfrom != loc) |
| 10646 | + *--pto = *--pfrom; |
| 10647 | + |
| 10648 | + PREFIX(store_op2) (op, loc, arg1, arg2); |
| 10649 | +} |
| 10650 | + |
| 10651 | + |
| 10652 | +/* P points to just after a ^ in PATTERN. Return true if that ^ comes |
| 10653 | + after an alternative or a begin-subexpression. We assume there is at |
| 10654 | + least one character before the ^. */ |
| 10655 | + |
| 10656 | +static boolean |
| 10657 | +PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p, |
| 10658 | + reg_syntax_t syntax) |
| 10659 | +{ |
| 10660 | + const CHAR_T *prev = p - 2; |
| 10661 | + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; |
| 10662 | + |
| 10663 | + return |
| 10664 | + /* After a subexpression? */ |
| 10665 | + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) |
| 10666 | + /* After an alternative? */ |
| 10667 | + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); |
| 10668 | +} |
| 10669 | + |
| 10670 | + |
| 10671 | +/* The dual of at_begline_loc_p. This one is for $. We assume there is |
| 10672 | + at least one character after the $, i.e., `P < PEND'. */ |
| 10673 | + |
| 10674 | +static boolean |
| 10675 | +PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend, |
| 10676 | + reg_syntax_t syntax) |
| 10677 | +{ |
| 10678 | + const CHAR_T *next = p; |
| 10679 | + boolean next_backslash = *next == '\\'; |
| 10680 | + const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; |
| 10681 | + |
| 10682 | + return |
| 10683 | + /* Before a subexpression? */ |
| 10684 | + (syntax & RE_NO_BK_PARENS ? *next == ')' |
| 10685 | + : next_backslash && next_next && *next_next == ')') |
| 10686 | + /* Before an alternative? */ |
| 10687 | + || (syntax & RE_NO_BK_VBAR ? *next == '|' |
| 10688 | + : next_backslash && next_next && *next_next == '|'); |
| 10689 | +} |
| 10690 | + |
| 10691 | +#else /* not INSIDE_RECURSION */ |
| 10692 | + |
| 10693 | +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and |
| 10694 | + false if it's not. */ |
| 10695 | + |
| 10696 | +static boolean |
| 10697 | +group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum) |
| 10698 | +{ |
| 10699 | + int this_element; |
| 10700 | + |
| 10701 | + for (this_element = compile_stack.avail - 1; |
| 10702 | + this_element >= 0; |
| 10703 | + this_element--) |
| 10704 | + if (compile_stack.stack[this_element].regnum == regnum) |
| 10705 | + return true; |
| 10706 | + |
| 10707 | + return false; |
| 10708 | +} |
| 10709 | +#endif /* not INSIDE_RECURSION */ |
| 10710 | + |
| 10711 | +#ifdef INSIDE_RECURSION |
| 10712 | + |
| 10713 | +#ifdef WCHAR |
| 10714 | +/* This insert space, which size is "num", into the pattern at "loc". |
| 10715 | + "end" must point the end of the allocated buffer. */ |
| 10716 | +static void |
| 10717 | +insert_space (int num, CHAR_T *loc, CHAR_T *end) |
| 10718 | +{ |
| 10719 | + register CHAR_T *pto = end; |
| 10720 | + register CHAR_T *pfrom = end - num; |
| 10721 | + |
| 10722 | + while (pfrom >= loc) |
| 10723 | + *pto-- = *pfrom--; |
| 10724 | +} |
| 10725 | +#endif /* WCHAR */ |
| 10726 | + |
| 10727 | +#ifdef WCHAR |
| 10728 | +static reg_errcode_t |
| 10729 | +wcs_compile_range (CHAR_T range_start_char, const CHAR_T **p_ptr, |
| 10730 | + const CHAR_T *pend, RE_TRANSLATE_TYPE translate, |
| 10731 | + reg_syntax_t syntax, CHAR_T *b, CHAR_T *char_set) |
| 10732 | +{ |
| 10733 | + const CHAR_T *p = *p_ptr; |
| 10734 | + CHAR_T range_start, range_end; |
| 10735 | + reg_errcode_t ret; |
| 10736 | +# ifdef _LIBC |
| 10737 | + uint32_t nrules; |
| 10738 | + uint32_t start_val, end_val; |
| 10739 | +# endif |
| 10740 | + if (p == pend) |
| 10741 | + return REG_ERANGE; |
| 10742 | + |
| 10743 | +# ifdef _LIBC |
| 10744 | + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 10745 | + if (nrules != 0) |
| 10746 | + { |
| 10747 | + const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, |
| 10748 | + _NL_COLLATE_COLLSEQWC); |
| 10749 | + const unsigned char *extra = (const unsigned char *) |
| 10750 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); |
| 10751 | + |
| 10752 | + if (range_start_char < -1) |
| 10753 | + { |
| 10754 | + /* range_start is a collating symbol. */ |
| 10755 | + int32_t *wextra; |
| 10756 | + /* Retreive the index and get collation sequence value. */ |
| 10757 | + wextra = (int32_t*)(extra + char_set[-range_start_char]); |
| 10758 | + start_val = wextra[1 + *wextra]; |
| 10759 | + } |
| 10760 | + else |
| 10761 | + start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char)); |
| 10762 | + |
| 10763 | + end_val = collseq_table_lookup (collseq, TRANSLATE (p[0])); |
| 10764 | + |
| 10765 | + /* Report an error if the range is empty and the syntax prohibits |
| 10766 | + this. */ |
| 10767 | + ret = ((syntax & RE_NO_EMPTY_RANGES) |
| 10768 | + && (start_val > end_val))? REG_ERANGE : REG_NOERROR; |
| 10769 | + |
| 10770 | + /* Insert space to the end of the char_ranges. */ |
| 10771 | + insert_space(2, b - char_set[5] - 2, b - 1); |
| 10772 | + *(b - char_set[5] - 2) = (wchar_t)start_val; |
| 10773 | + *(b - char_set[5] - 1) = (wchar_t)end_val; |
| 10774 | + char_set[4]++; /* ranges_index */ |
| 10775 | + } |
| 10776 | + else |
| 10777 | +# endif |
| 10778 | + { |
| 10779 | + range_start = (range_start_char >= 0)? TRANSLATE (range_start_char): |
| 10780 | + range_start_char; |
| 10781 | + range_end = TRANSLATE (p[0]); |
| 10782 | + /* Report an error if the range is empty and the syntax prohibits |
| 10783 | + this. */ |
| 10784 | + ret = ((syntax & RE_NO_EMPTY_RANGES) |
| 10785 | + && (range_start > range_end))? REG_ERANGE : REG_NOERROR; |
| 10786 | + |
| 10787 | + /* Insert space to the end of the char_ranges. */ |
| 10788 | + insert_space(2, b - char_set[5] - 2, b - 1); |
| 10789 | + *(b - char_set[5] - 2) = range_start; |
| 10790 | + *(b - char_set[5] - 1) = range_end; |
| 10791 | + char_set[4]++; /* ranges_index */ |
| 10792 | + } |
| 10793 | + /* Have to increment the pointer into the pattern string, so the |
| 10794 | + caller isn't still at the ending character. */ |
| 10795 | + (*p_ptr)++; |
| 10796 | + |
| 10797 | + return ret; |
| 10798 | +} |
| 10799 | +#else /* BYTE */ |
| 10800 | +/* Read the ending character of a range (in a bracket expression) from the |
| 10801 | + uncompiled pattern *P_PTR (which ends at PEND). We assume the |
| 10802 | + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) |
| 10803 | + Then we set the translation of all bits between the starting and |
| 10804 | + ending characters (inclusive) in the compiled pattern B. |
| 10805 | + |
| 10806 | + Return an error code. |
| 10807 | + |
| 10808 | + We use these short variable names so we can use the same macros as |
| 10809 | + `regex_compile' itself. */ |
| 10810 | + |
| 10811 | +static reg_errcode_t |
| 10812 | +byte_compile_range (unsigned int range_start_char, const char **p_ptr, |
| 10813 | + const char *pend, RE_TRANSLATE_TYPE translate, |
| 10814 | + reg_syntax_t syntax, unsigned char *b) |
| 10815 | +{ |
| 10816 | + unsigned this_char; |
| 10817 | + const char *p = *p_ptr; |
| 10818 | + reg_errcode_t ret; |
| 10819 | +# if _LIBC |
| 10820 | + const unsigned char *collseq; |
| 10821 | + unsigned int start_colseq; |
| 10822 | + unsigned int end_colseq; |
| 10823 | +# else |
| 10824 | + unsigned end_char; |
| 10825 | +# endif |
| 10826 | + |
| 10827 | + if (p == pend) |
| 10828 | + return REG_ERANGE; |
| 10829 | + |
| 10830 | + /* Have to increment the pointer into the pattern string, so the |
| 10831 | + caller isn't still at the ending character. */ |
| 10832 | + (*p_ptr)++; |
| 10833 | + |
| 10834 | + /* Report an error if the range is empty and the syntax prohibits this. */ |
| 10835 | + ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; |
| 10836 | + |
| 10837 | +# if _LIBC |
| 10838 | + collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, |
| 10839 | + _NL_COLLATE_COLLSEQMB); |
| 10840 | + |
| 10841 | + start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)]; |
| 10842 | + end_colseq = collseq[(unsigned char) TRANSLATE (p[0])]; |
| 10843 | + for (this_char = 0; this_char <= (unsigned char) -1; ++this_char) |
| 10844 | + { |
| 10845 | + unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)]; |
| 10846 | + |
| 10847 | + if (start_colseq <= this_colseq && this_colseq <= end_colseq) |
| 10848 | + { |
| 10849 | + SET_LIST_BIT (TRANSLATE (this_char)); |
| 10850 | + ret = REG_NOERROR; |
| 10851 | + } |
| 10852 | + } |
| 10853 | +# else |
| 10854 | + /* Here we see why `this_char' has to be larger than an `unsigned |
| 10855 | + char' -- we would otherwise go into an infinite loop, since all |
| 10856 | + characters <= 0xff. */ |
| 10857 | + range_start_char = TRANSLATE (range_start_char); |
| 10858 | + /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE, |
| 10859 | + and some compilers cast it to int implicitly, so following for_loop |
| 10860 | + may fall to (almost) infinite loop. |
| 10861 | + e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff. |
| 10862 | + To avoid this, we cast p[0] to unsigned int and truncate it. */ |
| 10863 | + end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1)); |
| 10864 | + |
| 10865 | + for (this_char = range_start_char; this_char <= end_char; ++this_char) |
| 10866 | + { |
| 10867 | + SET_LIST_BIT (TRANSLATE (this_char)); |
| 10868 | + ret = REG_NOERROR; |
| 10869 | + } |
| 10870 | +# endif |
| 10871 | + |
| 10872 | + return ret; |
| 10873 | +} |
| 10874 | +#endif /* WCHAR */ |
| 10875 | + |
| 10876 | +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in |
| 10877 | + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible |
| 10878 | + characters can start a string that matches the pattern. This fastmap |
| 10879 | + is used by re_search to skip quickly over impossible starting points. |
| 10880 | + |
| 10881 | + The caller must supply the address of a (1 << BYTEWIDTH)-byte data |
| 10882 | + area as BUFP->fastmap. |
| 10883 | + |
| 10884 | + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in |
| 10885 | + the pattern buffer. |
| 10886 | + |
| 10887 | + Returns 0 if we succeed, -2 if an internal error. */ |
| 10888 | + |
| 10889 | +#ifdef WCHAR |
| 10890 | +/* local function for re_compile_fastmap. |
| 10891 | + truncate wchar_t character to char. */ |
| 10892 | +static unsigned char truncate_wchar (CHAR_T c); |
| 10893 | + |
| 10894 | +static unsigned char |
| 10895 | +truncate_wchar (CHAR_T c) |
| 10896 | +{ |
| 10897 | + unsigned char buf[MB_CUR_MAX]; |
| 10898 | + mbstate_t state; |
| 10899 | + int retval; |
| 10900 | + memset (&state, '\0', sizeof (state)); |
| 10901 | +# ifdef _LIBC |
| 10902 | + retval = __wcrtomb (buf, c, &state); |
| 10903 | +# else |
| 10904 | + retval = wcrtomb (buf, c, &state); |
| 10905 | +# endif |
| 10906 | + return retval > 0 ? buf[0] : (unsigned char) c; |
| 10907 | +} |
| 10908 | +#endif /* WCHAR */ |
| 10909 | + |
| 10910 | +static int |
| 10911 | +PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp) |
| 10912 | +{ |
| 10913 | + int j, k; |
| 10914 | +#ifdef MATCH_MAY_ALLOCATE |
| 10915 | + PREFIX(fail_stack_type) fail_stack; |
| 10916 | +#endif |
| 10917 | +#ifndef REGEX_MALLOC |
| 10918 | + char *destination; |
| 10919 | +#endif |
| 10920 | + |
| 10921 | + register char *fastmap = bufp->fastmap; |
| 10922 | + |
| 10923 | +#ifdef WCHAR |
| 10924 | + /* We need to cast pattern to (wchar_t*), because we casted this compiled |
| 10925 | + pattern to (char*) in regex_compile. */ |
| 10926 | + UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; |
| 10927 | + register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); |
| 10928 | +#else /* BYTE */ |
| 10929 | + UCHAR_T *pattern = bufp->buffer; |
| 10930 | + register UCHAR_T *pend = pattern + bufp->used; |
| 10931 | +#endif /* WCHAR */ |
| 10932 | + UCHAR_T *p = pattern; |
| 10933 | + |
| 10934 | +#ifdef REL_ALLOC |
| 10935 | + /* This holds the pointer to the failure stack, when |
| 10936 | + it is allocated relocatably. */ |
| 10937 | + fail_stack_elt_t *failure_stack_ptr; |
| 10938 | +#endif |
| 10939 | + |
| 10940 | + /* Assume that each path through the pattern can be null until |
| 10941 | + proven otherwise. We set this false at the bottom of switch |
| 10942 | + statement, to which we get only if a particular path doesn't |
| 10943 | + match the empty string. */ |
| 10944 | + boolean path_can_be_null = true; |
| 10945 | + |
| 10946 | + /* We aren't doing a `succeed_n' to begin with. */ |
| 10947 | + boolean succeed_n_p = false; |
| 10948 | + |
| 10949 | + assert (fastmap != NULL && p != NULL); |
| 10950 | + |
| 10951 | + INIT_FAIL_STACK (); |
| 10952 | + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ |
| 10953 | + bufp->fastmap_accurate = 1; /* It will be when we're done. */ |
| 10954 | + bufp->can_be_null = 0; |
| 10955 | + |
| 10956 | + while (1) |
| 10957 | + { |
| 10958 | + if (p == pend || *p == (UCHAR_T) succeed) |
| 10959 | + { |
| 10960 | + /* We have reached the (effective) end of pattern. */ |
| 10961 | + if (!FAIL_STACK_EMPTY ()) |
| 10962 | + { |
| 10963 | + bufp->can_be_null |= path_can_be_null; |
| 10964 | + |
| 10965 | + /* Reset for next path. */ |
| 10966 | + path_can_be_null = true; |
| 10967 | + |
| 10968 | + p = fail_stack.stack[--fail_stack.avail].pointer; |
| 10969 | + |
| 10970 | + continue; |
| 10971 | + } |
| 10972 | + else |
| 10973 | + break; |
| 10974 | + } |
| 10975 | + |
| 10976 | + /* We should never be about to go beyond the end of the pattern. */ |
| 10977 | + assert (p < pend); |
| 10978 | + |
| 10979 | + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) |
| 10980 | + { |
| 10981 | + |
| 10982 | + /* I guess the idea here is to simply not bother with a fastmap |
| 10983 | + if a backreference is used, since it's too hard to figure out |
| 10984 | + the fastmap for the corresponding group. Setting |
| 10985 | + `can_be_null' stops `re_search_2' from using the fastmap, so |
| 10986 | + that is all we do. */ |
| 10987 | + case duplicate: |
| 10988 | + bufp->can_be_null = 1; |
| 10989 | + goto done; |
| 10990 | + |
| 10991 | + |
| 10992 | + /* Following are the cases which match a character. These end |
| 10993 | + with `break'. */ |
| 10994 | + |
| 10995 | +#ifdef WCHAR |
| 10996 | + case exactn: |
| 10997 | + fastmap[truncate_wchar(p[1])] = 1; |
| 10998 | + break; |
| 10999 | +#else /* BYTE */ |
| 11000 | + case exactn: |
| 11001 | + fastmap[p[1]] = 1; |
| 11002 | + break; |
| 11003 | +#endif /* WCHAR */ |
| 11004 | +#ifdef MBS_SUPPORT |
| 11005 | + case exactn_bin: |
| 11006 | + fastmap[p[1]] = 1; |
| 11007 | + break; |
| 11008 | +#endif |
| 11009 | + |
| 11010 | +#ifdef WCHAR |
| 11011 | + /* It is hard to distinguish fastmap from (multi byte) characters |
| 11012 | + which depends on current locale. */ |
| 11013 | + case charset: |
| 11014 | + case charset_not: |
| 11015 | + case wordchar: |
| 11016 | + case notwordchar: |
| 11017 | + bufp->can_be_null = 1; |
| 11018 | + goto done; |
| 11019 | +#else /* BYTE */ |
| 11020 | + case charset: |
| 11021 | + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) |
| 11022 | + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) |
| 11023 | + fastmap[j] = 1; |
| 11024 | + break; |
| 11025 | + |
| 11026 | + |
| 11027 | + case charset_not: |
| 11028 | + /* Chars beyond end of map must be allowed. */ |
| 11029 | + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) |
| 11030 | + fastmap[j] = 1; |
| 11031 | + |
| 11032 | + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) |
| 11033 | + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) |
| 11034 | + fastmap[j] = 1; |
| 11035 | + break; |
| 11036 | + |
| 11037 | + |
| 11038 | + case wordchar: |
| 11039 | + for (j = 0; j < (1 << BYTEWIDTH); j++) |
| 11040 | + if (SYNTAX (j) == Sword) |
| 11041 | + fastmap[j] = 1; |
| 11042 | + break; |
| 11043 | + |
| 11044 | + |
| 11045 | + case notwordchar: |
| 11046 | + for (j = 0; j < (1 << BYTEWIDTH); j++) |
| 11047 | + if (SYNTAX (j) != Sword) |
| 11048 | + fastmap[j] = 1; |
| 11049 | + break; |
| 11050 | +#endif /* WCHAR */ |
| 11051 | + |
| 11052 | + case anychar: |
| 11053 | + { |
| 11054 | + int fastmap_newline = fastmap['\n']; |
| 11055 | + |
| 11056 | + /* `.' matches anything ... */ |
| 11057 | + for (j = 0; j < (1 << BYTEWIDTH); j++) |
| 11058 | + fastmap[j] = 1; |
| 11059 | + |
| 11060 | + /* ... except perhaps newline. */ |
| 11061 | + if (!(bufp->syntax & RE_DOT_NEWLINE)) |
| 11062 | + fastmap['\n'] = fastmap_newline; |
| 11063 | + |
| 11064 | + /* Return if we have already set `can_be_null'; if we have, |
| 11065 | + then the fastmap is irrelevant. Something's wrong here. */ |
| 11066 | + else if (bufp->can_be_null) |
| 11067 | + goto done; |
| 11068 | + |
| 11069 | + /* Otherwise, have to check alternative paths. */ |
| 11070 | + break; |
| 11071 | + } |
| 11072 | + |
| 11073 | +#ifdef emacs |
| 11074 | + case syntaxspec: |
| 11075 | + k = *p++; |
| 11076 | + for (j = 0; j < (1 << BYTEWIDTH); j++) |
| 11077 | + if (SYNTAX (j) == (enum syntaxcode) k) |
| 11078 | + fastmap[j] = 1; |
| 11079 | + break; |
| 11080 | + |
| 11081 | + |
| 11082 | + case notsyntaxspec: |
| 11083 | + k = *p++; |
| 11084 | + for (j = 0; j < (1 << BYTEWIDTH); j++) |
| 11085 | + if (SYNTAX (j) != (enum syntaxcode) k) |
| 11086 | + fastmap[j] = 1; |
| 11087 | + break; |
| 11088 | + |
| 11089 | + |
| 11090 | + /* All cases after this match the empty string. These end with |
| 11091 | + `continue'. */ |
| 11092 | + |
| 11093 | + |
| 11094 | + case before_dot: |
| 11095 | + case at_dot: |
| 11096 | + case after_dot: |
| 11097 | + continue; |
| 11098 | +#endif /* emacs */ |
| 11099 | + |
| 11100 | + |
| 11101 | + case no_op: |
| 11102 | + case begline: |
| 11103 | + case endline: |
| 11104 | + case begbuf: |
| 11105 | + case endbuf: |
| 11106 | + case wordbound: |
| 11107 | + case notwordbound: |
| 11108 | + case wordbeg: |
| 11109 | + case wordend: |
| 11110 | + case push_dummy_failure: |
| 11111 | + continue; |
| 11112 | + |
| 11113 | + |
| 11114 | + case jump_n: |
| 11115 | + case pop_failure_jump: |
| 11116 | + case maybe_pop_jump: |
| 11117 | + case jump: |
| 11118 | + case jump_past_alt: |
| 11119 | + case dummy_failure_jump: |
| 11120 | + EXTRACT_NUMBER_AND_INCR (j, p); |
| 11121 | + p += j; |
| 11122 | + if (j > 0) |
| 11123 | + continue; |
| 11124 | + |
| 11125 | + /* Jump backward implies we just went through the body of a |
| 11126 | + loop and matched nothing. Opcode jumped to should be |
| 11127 | + `on_failure_jump' or `succeed_n'. Just treat it like an |
| 11128 | + ordinary jump. For a * loop, it has pushed its failure |
| 11129 | + point already; if so, discard that as redundant. */ |
| 11130 | + if ((re_opcode_t) *p != on_failure_jump |
| 11131 | + && (re_opcode_t) *p != succeed_n) |
| 11132 | + continue; |
| 11133 | + |
| 11134 | + p++; |
| 11135 | + EXTRACT_NUMBER_AND_INCR (j, p); |
| 11136 | + p += j; |
| 11137 | + |
| 11138 | + /* If what's on the stack is where we are now, pop it. */ |
| 11139 | + if (!FAIL_STACK_EMPTY () |
| 11140 | + && fail_stack.stack[fail_stack.avail - 1].pointer == p) |
| 11141 | + fail_stack.avail--; |
| 11142 | + |
| 11143 | + continue; |
| 11144 | + |
| 11145 | + |
| 11146 | + case on_failure_jump: |
| 11147 | + case on_failure_keep_string_jump: |
| 11148 | + handle_on_failure_jump: |
| 11149 | + EXTRACT_NUMBER_AND_INCR (j, p); |
| 11150 | + |
| 11151 | + /* For some patterns, e.g., `(a?)?', `p+j' here points to the |
| 11152 | + end of the pattern. We don't want to push such a point, |
| 11153 | + since when we restore it above, entering the switch will |
| 11154 | + increment `p' past the end of the pattern. We don't need |
| 11155 | + to push such a point since we obviously won't find any more |
| 11156 | + fastmap entries beyond `pend'. Such a pattern can match |
| 11157 | + the null string, though. */ |
| 11158 | + if (p + j < pend) |
| 11159 | + { |
| 11160 | + if (!PUSH_PATTERN_OP (p + j, fail_stack)) |
| 11161 | + { |
| 11162 | + RESET_FAIL_STACK (); |
| 11163 | + return -2; |
| 11164 | + } |
| 11165 | + } |
| 11166 | + else |
| 11167 | + bufp->can_be_null = 1; |
| 11168 | + |
| 11169 | + if (succeed_n_p) |
| 11170 | + { |
| 11171 | + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ |
| 11172 | + succeed_n_p = false; |
| 11173 | + } |
| 11174 | + |
| 11175 | + continue; |
| 11176 | + |
| 11177 | + |
| 11178 | + case succeed_n: |
| 11179 | + /* Get to the number of times to succeed. */ |
| 11180 | + p += OFFSET_ADDRESS_SIZE; |
| 11181 | + |
| 11182 | + /* Increment p past the n for when k != 0. */ |
| 11183 | + EXTRACT_NUMBER_AND_INCR (k, p); |
| 11184 | + if (k == 0) |
| 11185 | + { |
| 11186 | + p -= 2 * OFFSET_ADDRESS_SIZE; |
| 11187 | + succeed_n_p = true; /* Spaghetti code alert. */ |
| 11188 | + goto handle_on_failure_jump; |
| 11189 | + } |
| 11190 | + continue; |
| 11191 | + |
| 11192 | + |
| 11193 | + case set_number_at: |
| 11194 | + p += 2 * OFFSET_ADDRESS_SIZE; |
| 11195 | + continue; |
| 11196 | + |
| 11197 | + |
| 11198 | + case start_memory: |
| 11199 | + case stop_memory: |
| 11200 | + p += 2; |
| 11201 | + continue; |
| 11202 | + |
| 11203 | + |
| 11204 | + default: |
| 11205 | + abort (); /* We have listed all the cases. */ |
| 11206 | + } /* switch *p++ */ |
| 11207 | + |
| 11208 | + /* Getting here means we have found the possible starting |
| 11209 | + characters for one path of the pattern -- and that the empty |
| 11210 | + string does not match. We need not follow this path further. |
| 11211 | + Instead, look at the next alternative (remembered on the |
| 11212 | + stack), or quit if no more. The test at the top of the loop |
| 11213 | + does these things. */ |
| 11214 | + path_can_be_null = false; |
| 11215 | + p = pend; |
| 11216 | + } /* while p */ |
| 11217 | + |
| 11218 | + /* Set `can_be_null' for the last path (also the first path, if the |
| 11219 | + pattern is empty). */ |
| 11220 | + bufp->can_be_null |= path_can_be_null; |
| 11221 | + |
| 11222 | + done: |
| 11223 | + RESET_FAIL_STACK (); |
| 11224 | + return 0; |
| 11225 | +} |
| 11226 | + |
| 11227 | +#else /* not INSIDE_RECURSION */ |
| 11228 | + |
| 11229 | +int |
| 11230 | +re_compile_fastmap (struct re_pattern_buffer *bufp) |
| 11231 | +{ |
| 11232 | +# ifdef MBS_SUPPORT |
| 11233 | + if (MB_CUR_MAX != 1) |
| 11234 | + return wcs_re_compile_fastmap(bufp); |
| 11235 | + else |
| 11236 | +# endif |
| 11237 | + return byte_re_compile_fastmap(bufp); |
| 11238 | +} /* re_compile_fastmap */ |
| 11239 | +#ifdef _LIBC |
| 11240 | +weak_alias (__re_compile_fastmap, re_compile_fastmap) |
| 11241 | +#endif |
| 11242 | + |
| 11243 | + |
| 11244 | +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and |
| 11245 | + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use |
| 11246 | + this memory for recording register information. STARTS and ENDS |
| 11247 | + must be allocated using the malloc library routine, and must each |
| 11248 | + be at least NUM_REGS * sizeof (regoff_t) bytes long. |
| 11249 | + |
| 11250 | + If NUM_REGS == 0, then subsequent matches should allocate their own |
| 11251 | + register data. |
| 11252 | + |
| 11253 | + Unless this function is called, the first search or match using |
| 11254 | + PATTERN_BUFFER will allocate its own register data, without |
| 11255 | + freeing the old data. */ |
| 11256 | + |
| 11257 | +void |
| 11258 | +re_set_registers (struct re_pattern_buffer *bufp, |
| 11259 | + struct re_registers *regs, unsigned num_regs, |
| 11260 | + regoff_t *starts, regoff_t *ends) |
| 11261 | +{ |
| 11262 | + if (num_regs) |
| 11263 | + { |
| 11264 | + bufp->regs_allocated = REGS_REALLOCATE; |
| 11265 | + regs->num_regs = num_regs; |
| 11266 | + regs->start = starts; |
| 11267 | + regs->end = ends; |
| 11268 | + } |
| 11269 | + else |
| 11270 | + { |
| 11271 | + bufp->regs_allocated = REGS_UNALLOCATED; |
| 11272 | + regs->num_regs = 0; |
| 11273 | + regs->start = regs->end = (regoff_t *) 0; |
| 11274 | + } |
| 11275 | +} |
| 11276 | +#ifdef _LIBC |
| 11277 | +weak_alias (__re_set_registers, re_set_registers) |
| 11278 | +#endif |
| 11279 | + |
| 11280 | +/* Searching routines. */ |
| 11281 | + |
| 11282 | +/* Like re_search_2, below, but only one string is specified, and |
| 11283 | + doesn't let you say where to stop matching. */ |
| 11284 | + |
| 11285 | +int |
| 11286 | +re_search (struct re_pattern_buffer *bufp, const char *string, int size, |
| 11287 | + int startpos, int range, struct re_registers *regs) |
| 11288 | +{ |
| 11289 | + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, |
| 11290 | + regs, size); |
| 11291 | +} |
| 11292 | +#ifdef _LIBC |
| 11293 | +weak_alias (__re_search, re_search) |
| 11294 | +#endif |
| 11295 | + |
| 11296 | + |
| 11297 | +/* Using the compiled pattern in BUFP->buffer, first tries to match the |
| 11298 | + virtual concatenation of STRING1 and STRING2, starting first at index |
| 11299 | + STARTPOS, then at STARTPOS + 1, and so on. |
| 11300 | + |
| 11301 | + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. |
| 11302 | + |
| 11303 | + RANGE is how far to scan while trying to match. RANGE = 0 means try |
| 11304 | + only at STARTPOS; in general, the last start tried is STARTPOS + |
| 11305 | + RANGE. |
| 11306 | + |
| 11307 | + In REGS, return the indices of the virtual concatenation of STRING1 |
| 11308 | + and STRING2 that matched the entire BUFP->buffer and its contained |
| 11309 | + subexpressions. |
| 11310 | + |
| 11311 | + Do not consider matching one past the index STOP in the virtual |
| 11312 | + concatenation of STRING1 and STRING2. |
| 11313 | + |
| 11314 | + We return either the position in the strings at which the match was |
| 11315 | + found, -1 if no match, or -2 if error (such as failure |
| 11316 | + stack overflow). */ |
| 11317 | + |
| 11318 | +int |
| 11319 | +re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, |
| 11320 | + const char *string2, int size2, int startpos, int range, |
| 11321 | + struct re_registers *regs, int stop) |
| 11322 | +{ |
| 11323 | +# ifdef MBS_SUPPORT |
| 11324 | + if (MB_CUR_MAX != 1) |
| 11325 | + return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, |
| 11326 | + range, regs, stop); |
| 11327 | + else |
| 11328 | +# endif |
| 11329 | + return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, |
| 11330 | + range, regs, stop); |
| 11331 | +} /* re_search_2 */ |
| 11332 | +#ifdef _LIBC |
| 11333 | +weak_alias (__re_search_2, re_search_2) |
| 11334 | +#endif |
| 11335 | + |
| 11336 | +#endif /* not INSIDE_RECURSION */ |
| 11337 | + |
| 11338 | +#ifdef INSIDE_RECURSION |
| 11339 | + |
| 11340 | +#ifdef MATCH_MAY_ALLOCATE |
| 11341 | +# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL |
| 11342 | +#else |
| 11343 | +# define FREE_VAR(var) if (var) free (var); var = NULL |
| 11344 | +#endif |
| 11345 | + |
| 11346 | +#ifdef WCHAR |
| 11347 | +# define MAX_ALLOCA_SIZE 2000 |
| 11348 | + |
| 11349 | +# define FREE_WCS_BUFFERS() \ |
| 11350 | + do { \ |
| 11351 | + if (size1 > MAX_ALLOCA_SIZE) \ |
| 11352 | + { \ |
| 11353 | + free (wcs_string1); \ |
| 11354 | + free (mbs_offset1); \ |
| 11355 | + } \ |
| 11356 | + else \ |
| 11357 | + { \ |
| 11358 | + FREE_VAR (wcs_string1); \ |
| 11359 | + FREE_VAR (mbs_offset1); \ |
| 11360 | + } \ |
| 11361 | + if (size2 > MAX_ALLOCA_SIZE) \ |
| 11362 | + { \ |
| 11363 | + free (wcs_string2); \ |
| 11364 | + free (mbs_offset2); \ |
| 11365 | + } \ |
| 11366 | + else \ |
| 11367 | + { \ |
| 11368 | + FREE_VAR (wcs_string2); \ |
| 11369 | + FREE_VAR (mbs_offset2); \ |
| 11370 | + } \ |
| 11371 | + } while (0) |
| 11372 | + |
| 11373 | +#endif |
| 11374 | + |
| 11375 | + |
| 11376 | +static int |
| 11377 | +PREFIX(re_search_2) (struct re_pattern_buffer *bufp, const char *string1, |
| 11378 | + int size1, const char *string2, int size2, |
| 11379 | + int startpos, int range, |
| 11380 | + struct re_registers *regs, int stop) |
| 11381 | +{ |
| 11382 | + int val; |
| 11383 | + register char *fastmap = bufp->fastmap; |
| 11384 | + register RE_TRANSLATE_TYPE translate = bufp->translate; |
| 11385 | + int total_size = size1 + size2; |
| 11386 | + int endpos = startpos + range; |
| 11387 | +#ifdef WCHAR |
| 11388 | + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ |
| 11389 | + wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; |
| 11390 | + /* We need the size of wchar_t buffers correspond to csize1, csize2. */ |
| 11391 | + int wcs_size1 = 0, wcs_size2 = 0; |
| 11392 | + /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ |
| 11393 | + int *mbs_offset1 = NULL, *mbs_offset2 = NULL; |
| 11394 | + /* They hold whether each wchar_t is binary data or not. */ |
| 11395 | + char *is_binary = NULL; |
| 11396 | +#endif /* WCHAR */ |
| 11397 | + |
| 11398 | + /* Check for out-of-range STARTPOS. */ |
| 11399 | + if (startpos < 0 || startpos > total_size) |
| 11400 | + return -1; |
| 11401 | + |
| 11402 | + /* Fix up RANGE if it might eventually take us outside |
| 11403 | + the virtual concatenation of STRING1 and STRING2. |
| 11404 | + Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ |
| 11405 | + if (endpos < 0) |
| 11406 | + range = 0 - startpos; |
| 11407 | + else if (endpos > total_size) |
| 11408 | + range = total_size - startpos; |
| 11409 | + |
| 11410 | + /* If the search isn't to be a backwards one, don't waste time in a |
| 11411 | + search for a pattern that must be anchored. */ |
| 11412 | + if (bufp->used > 0 && range > 0 |
| 11413 | + && ((re_opcode_t) bufp->buffer[0] == begbuf |
| 11414 | + /* `begline' is like `begbuf' if it cannot match at newlines. */ |
| 11415 | + || ((re_opcode_t) bufp->buffer[0] == begline |
| 11416 | + && !bufp->newline_anchor))) |
| 11417 | + { |
| 11418 | + if (startpos > 0) |
| 11419 | + return -1; |
| 11420 | + else |
| 11421 | + range = 1; |
| 11422 | + } |
| 11423 | + |
| 11424 | +#ifdef emacs |
| 11425 | + /* In a forward search for something that starts with \=. |
| 11426 | + don't keep searching past point. */ |
| 11427 | + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) |
| 11428 | + { |
| 11429 | + range = PT - startpos; |
| 11430 | + if (range <= 0) |
| 11431 | + return -1; |
| 11432 | + } |
| 11433 | +#endif /* emacs */ |
| 11434 | + |
| 11435 | + /* Update the fastmap now if not correct already. */ |
| 11436 | + if (fastmap && !bufp->fastmap_accurate) |
| 11437 | + if (re_compile_fastmap (bufp) == -2) |
| 11438 | + return -2; |
| 11439 | + |
| 11440 | +#ifdef WCHAR |
| 11441 | + /* Allocate wchar_t array for wcs_string1 and wcs_string2 and |
| 11442 | + fill them with converted string. */ |
| 11443 | + if (size1 != 0) |
| 11444 | + { |
| 11445 | + if (size1 > MAX_ALLOCA_SIZE) |
| 11446 | + { |
| 11447 | + wcs_string1 = TALLOC (size1 + 1, CHAR_T); |
| 11448 | + mbs_offset1 = TALLOC (size1 + 1, int); |
| 11449 | + is_binary = TALLOC (size1 + 1, char); |
| 11450 | + } |
| 11451 | + else |
| 11452 | + { |
| 11453 | + wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); |
| 11454 | + mbs_offset1 = REGEX_TALLOC (size1 + 1, int); |
| 11455 | + is_binary = REGEX_TALLOC (size1 + 1, char); |
| 11456 | + } |
| 11457 | + if (!wcs_string1 || !mbs_offset1 || !is_binary) |
| 11458 | + { |
| 11459 | + if (size1 > MAX_ALLOCA_SIZE) |
| 11460 | + { |
| 11461 | + free (wcs_string1); |
| 11462 | + free (mbs_offset1); |
| 11463 | + free (is_binary); |
| 11464 | + } |
| 11465 | + else |
| 11466 | + { |
| 11467 | + FREE_VAR (wcs_string1); |
| 11468 | + FREE_VAR (mbs_offset1); |
| 11469 | + FREE_VAR (is_binary); |
| 11470 | + } |
| 11471 | + return -2; |
| 11472 | + } |
| 11473 | + wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, |
| 11474 | + mbs_offset1, is_binary); |
| 11475 | + wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ |
| 11476 | + if (size1 > MAX_ALLOCA_SIZE) |
| 11477 | + free (is_binary); |
| 11478 | + else |
| 11479 | + FREE_VAR (is_binary); |
| 11480 | + } |
| 11481 | + if (size2 != 0) |
| 11482 | + { |
| 11483 | + if (size2 > MAX_ALLOCA_SIZE) |
| 11484 | + { |
| 11485 | + wcs_string2 = TALLOC (size2 + 1, CHAR_T); |
| 11486 | + mbs_offset2 = TALLOC (size2 + 1, int); |
| 11487 | + is_binary = TALLOC (size2 + 1, char); |
| 11488 | + } |
| 11489 | + else |
| 11490 | + { |
| 11491 | + wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); |
| 11492 | + mbs_offset2 = REGEX_TALLOC (size2 + 1, int); |
| 11493 | + is_binary = REGEX_TALLOC (size2 + 1, char); |
| 11494 | + } |
| 11495 | + if (!wcs_string2 || !mbs_offset2 || !is_binary) |
| 11496 | + { |
| 11497 | + FREE_WCS_BUFFERS (); |
| 11498 | + if (size2 > MAX_ALLOCA_SIZE) |
| 11499 | + free (is_binary); |
| 11500 | + else |
| 11501 | + FREE_VAR (is_binary); |
| 11502 | + return -2; |
| 11503 | + } |
| 11504 | + wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, |
| 11505 | + mbs_offset2, is_binary); |
| 11506 | + wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ |
| 11507 | + if (size2 > MAX_ALLOCA_SIZE) |
| 11508 | + free (is_binary); |
| 11509 | + else |
| 11510 | + FREE_VAR (is_binary); |
| 11511 | + } |
| 11512 | +#endif /* WCHAR */ |
| 11513 | + |
| 11514 | + |
| 11515 | + /* Loop through the string, looking for a place to start matching. */ |
| 11516 | + for (;;) |
| 11517 | + { |
| 11518 | + /* If a fastmap is supplied, skip quickly over characters that |
| 11519 | + cannot be the start of a match. If the pattern can match the |
| 11520 | + null string, however, we don't need to skip characters; we want |
| 11521 | + the first null string. */ |
| 11522 | + if (fastmap && startpos < total_size && !bufp->can_be_null) |
| 11523 | + { |
| 11524 | + if (range > 0) /* Searching forwards. */ |
| 11525 | + { |
| 11526 | + register const char *d; |
| 11527 | + register int lim = 0; |
| 11528 | + int irange = range; |
| 11529 | + |
| 11530 | + if (startpos < size1 && startpos + range >= size1) |
| 11531 | + lim = range - (size1 - startpos); |
| 11532 | + |
| 11533 | + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; |
| 11534 | + |
| 11535 | + /* Written out as an if-else to avoid testing `translate' |
| 11536 | + inside the loop. */ |
| 11537 | + if (translate) |
| 11538 | + while (range > lim |
| 11539 | + && !fastmap[(unsigned char) |
| 11540 | + translate[(unsigned char) *d++]]) |
| 11541 | + range--; |
| 11542 | + else |
| 11543 | + while (range > lim && !fastmap[(unsigned char) *d++]) |
| 11544 | + range--; |
| 11545 | + |
| 11546 | + startpos += irange - range; |
| 11547 | + } |
| 11548 | + else /* Searching backwards. */ |
| 11549 | + { |
| 11550 | + register CHAR_T c = (size1 == 0 || startpos >= size1 |
| 11551 | + ? string2[startpos - size1] |
| 11552 | + : string1[startpos]); |
| 11553 | + |
| 11554 | + if (!fastmap[(unsigned char) TRANSLATE (c)]) |
| 11555 | + goto advance; |
| 11556 | + } |
| 11557 | + } |
| 11558 | + |
| 11559 | + /* If can't match the null string, and that's all we have left, fail. */ |
| 11560 | + if (range >= 0 && startpos == total_size && fastmap |
| 11561 | + && !bufp->can_be_null) |
| 11562 | + { |
| 11563 | +#ifdef WCHAR |
| 11564 | + FREE_WCS_BUFFERS (); |
| 11565 | +#endif |
| 11566 | + return -1; |
| 11567 | + } |
| 11568 | + |
| 11569 | +#ifdef WCHAR |
| 11570 | + val = wcs_re_match_2_internal (bufp, string1, size1, string2, |
| 11571 | + size2, startpos, regs, stop, |
| 11572 | + wcs_string1, wcs_size1, |
| 11573 | + wcs_string2, wcs_size2, |
| 11574 | + mbs_offset1, mbs_offset2); |
| 11575 | +#else /* BYTE */ |
| 11576 | + val = byte_re_match_2_internal (bufp, string1, size1, string2, |
| 11577 | + size2, startpos, regs, stop); |
| 11578 | +#endif /* BYTE */ |
| 11579 | + |
| 11580 | +#ifndef REGEX_MALLOC |
| 11581 | +# ifdef C_ALLOCA |
| 11582 | + alloca (0); |
| 11583 | +# endif |
| 11584 | +#endif |
| 11585 | + |
| 11586 | + if (val >= 0) |
| 11587 | + { |
| 11588 | +#ifdef WCHAR |
| 11589 | + FREE_WCS_BUFFERS (); |
| 11590 | +#endif |
| 11591 | + return startpos; |
| 11592 | + } |
| 11593 | + |
| 11594 | + if (val == -2) |
| 11595 | + { |
| 11596 | +#ifdef WCHAR |
| 11597 | + FREE_WCS_BUFFERS (); |
| 11598 | +#endif |
| 11599 | + return -2; |
| 11600 | + } |
| 11601 | + |
| 11602 | + advance: |
| 11603 | + if (!range) |
| 11604 | + break; |
| 11605 | + else if (range > 0) |
| 11606 | + { |
| 11607 | + range--; |
| 11608 | + startpos++; |
| 11609 | + } |
| 11610 | + else |
| 11611 | + { |
| 11612 | + range++; |
| 11613 | + startpos--; |
| 11614 | + } |
| 11615 | + } |
| 11616 | +#ifdef WCHAR |
| 11617 | + FREE_WCS_BUFFERS (); |
| 11618 | +#endif |
| 11619 | + return -1; |
| 11620 | +} |
| 11621 | + |
| 11622 | +#ifdef WCHAR |
| 11623 | +/* This converts PTR, a pointer into one of the search wchar_t strings |
| 11624 | + `string1' and `string2' into an multibyte string offset from the |
| 11625 | + beginning of that string. We use mbs_offset to optimize. |
| 11626 | + See convert_mbs_to_wcs. */ |
| 11627 | +# define POINTER_TO_OFFSET(ptr) \ |
| 11628 | + (FIRST_STRING_P (ptr) \ |
| 11629 | + ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ |
| 11630 | + : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ |
| 11631 | + + csize1))) |
| 11632 | +#else /* BYTE */ |
| 11633 | +/* This converts PTR, a pointer into one of the search strings `string1' |
| 11634 | + and `string2' into an offset from the beginning of that string. */ |
| 11635 | +# define POINTER_TO_OFFSET(ptr) \ |
| 11636 | + (FIRST_STRING_P (ptr) \ |
| 11637 | + ? ((regoff_t) ((ptr) - string1)) \ |
| 11638 | + : ((regoff_t) ((ptr) - string2 + size1))) |
| 11639 | +#endif /* WCHAR */ |
| 11640 | + |
| 11641 | +/* Macros for dealing with the split strings in re_match_2. */ |
| 11642 | + |
| 11643 | +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) |
| 11644 | + |
| 11645 | +/* Call before fetching a character with *d. This switches over to |
| 11646 | + string2 if necessary. */ |
| 11647 | +#define PREFETCH() \ |
| 11648 | + while (d == dend) \ |
| 11649 | + { \ |
| 11650 | + /* End of string2 => fail. */ \ |
| 11651 | + if (dend == end_match_2) \ |
| 11652 | + goto fail; \ |
| 11653 | + /* End of string1 => advance to string2. */ \ |
| 11654 | + d = string2; \ |
| 11655 | + dend = end_match_2; \ |
| 11656 | + } |
| 11657 | + |
| 11658 | +/* Test if at very beginning or at very end of the virtual concatenation |
| 11659 | + of `string1' and `string2'. If only one string, it's `string2'. */ |
| 11660 | +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) |
| 11661 | +#define AT_STRINGS_END(d) ((d) == end2) |
| 11662 | + |
| 11663 | + |
| 11664 | +/* Test if D points to a character which is word-constituent. We have |
| 11665 | + two special cases to check for: if past the end of string1, look at |
| 11666 | + the first character in string2; and if before the beginning of |
| 11667 | + string2, look at the last character in string1. */ |
| 11668 | +#ifdef WCHAR |
| 11669 | +/* Use internationalized API instead of SYNTAX. */ |
| 11670 | +# define WORDCHAR_P(d) \ |
| 11671 | + (iswalnum ((wint_t)((d) == end1 ? *string2 \ |
| 11672 | + : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ |
| 11673 | + || ((d) == end1 ? *string2 \ |
| 11674 | + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') |
| 11675 | +#else /* BYTE */ |
| 11676 | +# define WORDCHAR_P(d) \ |
| 11677 | + (SYNTAX ((d) == end1 ? *string2 \ |
| 11678 | + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ |
| 11679 | + == Sword) |
| 11680 | +#endif /* WCHAR */ |
| 11681 | + |
| 11682 | +/* Disabled due to a compiler bug -- see comment at case wordbound */ |
| 11683 | +#if 0 |
| 11684 | +/* Test if the character before D and the one at D differ with respect |
| 11685 | + to being word-constituent. */ |
| 11686 | +#define AT_WORD_BOUNDARY(d) \ |
| 11687 | + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ |
| 11688 | + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) |
| 11689 | +#endif |
| 11690 | + |
| 11691 | +/* Free everything we malloc. */ |
| 11692 | +#ifdef MATCH_MAY_ALLOCATE |
| 11693 | +# ifdef WCHAR |
| 11694 | +# define FREE_VARIABLES() \ |
| 11695 | + do { \ |
| 11696 | + REGEX_FREE_STACK (fail_stack.stack); \ |
| 11697 | + FREE_VAR (regstart); \ |
| 11698 | + FREE_VAR (regend); \ |
| 11699 | + FREE_VAR (old_regstart); \ |
| 11700 | + FREE_VAR (old_regend); \ |
| 11701 | + FREE_VAR (best_regstart); \ |
| 11702 | + FREE_VAR (best_regend); \ |
| 11703 | + FREE_VAR (reg_info); \ |
| 11704 | + FREE_VAR (reg_dummy); \ |
| 11705 | + FREE_VAR (reg_info_dummy); \ |
| 11706 | + if (!cant_free_wcs_buf) \ |
| 11707 | + { \ |
| 11708 | + FREE_VAR (string1); \ |
| 11709 | + FREE_VAR (string2); \ |
| 11710 | + FREE_VAR (mbs_offset1); \ |
| 11711 | + FREE_VAR (mbs_offset2); \ |
| 11712 | + } \ |
| 11713 | + } while (0) |
| 11714 | +# else /* BYTE */ |
| 11715 | +# define FREE_VARIABLES() \ |
| 11716 | + do { \ |
| 11717 | + REGEX_FREE_STACK (fail_stack.stack); \ |
| 11718 | + FREE_VAR (regstart); \ |
| 11719 | + FREE_VAR (regend); \ |
| 11720 | + FREE_VAR (old_regstart); \ |
| 11721 | + FREE_VAR (old_regend); \ |
| 11722 | + FREE_VAR (best_regstart); \ |
| 11723 | + FREE_VAR (best_regend); \ |
| 11724 | + FREE_VAR (reg_info); \ |
| 11725 | + FREE_VAR (reg_dummy); \ |
| 11726 | + FREE_VAR (reg_info_dummy); \ |
| 11727 | + } while (0) |
| 11728 | +# endif /* WCHAR */ |
| 11729 | +#else |
| 11730 | +# ifdef WCHAR |
| 11731 | +# define FREE_VARIABLES() \ |
| 11732 | + do { \ |
| 11733 | + if (!cant_free_wcs_buf) \ |
| 11734 | + { \ |
| 11735 | + FREE_VAR (string1); \ |
| 11736 | + FREE_VAR (string2); \ |
| 11737 | + FREE_VAR (mbs_offset1); \ |
| 11738 | + FREE_VAR (mbs_offset2); \ |
| 11739 | + } \ |
| 11740 | + } while (0) |
| 11741 | +# else /* BYTE */ |
| 11742 | +# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ |
| 11743 | +# endif /* WCHAR */ |
| 11744 | +#endif /* not MATCH_MAY_ALLOCATE */ |
| 11745 | + |
| 11746 | +/* These values must meet several constraints. They must not be valid |
| 11747 | + register values; since we have a limit of 255 registers (because |
| 11748 | + we use only one byte in the pattern for the register number), we can |
| 11749 | + use numbers larger than 255. They must differ by 1, because of |
| 11750 | + NUM_FAILURE_ITEMS above. And the value for the lowest register must |
| 11751 | + be larger than the value for the highest register, so we do not try |
| 11752 | + to actually save any registers when none are active. */ |
| 11753 | +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) |
| 11754 | +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) |
| 11755 | + |
| 11756 | +#else /* not INSIDE_RECURSION */ |
| 11757 | +/* Matching routines. */ |
| 11758 | + |
| 11759 | +#ifndef emacs /* Emacs never uses this. */ |
| 11760 | +/* re_match is like re_match_2 except it takes only a single string. */ |
| 11761 | + |
| 11762 | +int |
| 11763 | +re_match (struct re_pattern_buffer *bufp, const char *string, |
| 11764 | + int size, int pos, struct re_registers *regs) |
| 11765 | +{ |
| 11766 | + int result; |
| 11767 | +# ifdef MBS_SUPPORT |
| 11768 | + if (MB_CUR_MAX != 1) |
| 11769 | + result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, |
| 11770 | + pos, regs, size, |
| 11771 | + NULL, 0, NULL, 0, NULL, NULL); |
| 11772 | + else |
| 11773 | +# endif |
| 11774 | + result = byte_re_match_2_internal (bufp, NULL, 0, string, size, |
| 11775 | + pos, regs, size); |
| 11776 | +# ifndef REGEX_MALLOC |
| 11777 | +# ifdef C_ALLOCA |
| 11778 | + alloca (0); |
| 11779 | +# endif |
| 11780 | +# endif |
| 11781 | + return result; |
| 11782 | +} |
| 11783 | +# ifdef _LIBC |
| 11784 | +weak_alias (__re_match, re_match) |
| 11785 | +# endif |
| 11786 | +#endif /* not emacs */ |
| 11787 | + |
| 11788 | +#endif /* not INSIDE_RECURSION */ |
| 11789 | + |
| 11790 | +#ifdef INSIDE_RECURSION |
| 11791 | +static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p, |
| 11792 | + UCHAR_T *end, |
| 11793 | + PREFIX(register_info_type) *reg_info); |
| 11794 | +static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p, |
| 11795 | + UCHAR_T *end, |
| 11796 | + PREFIX(register_info_type) *reg_info); |
| 11797 | +static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p, |
| 11798 | + UCHAR_T *end, |
| 11799 | + PREFIX(register_info_type) *reg_info); |
| 11800 | +static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, |
| 11801 | + register int len, |
| 11802 | + RE_TRANSLATE_TYPE translate); |
| 11803 | +#else /* not INSIDE_RECURSION */ |
| 11804 | + |
| 11805 | +/* re_match_2 matches the compiled pattern in BUFP against the |
| 11806 | + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 |
| 11807 | + and SIZE2, respectively). We start matching at POS, and stop |
| 11808 | + matching at STOP. |
| 11809 | + |
| 11810 | + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we |
| 11811 | + store offsets for the substring each group matched in REGS. See the |
| 11812 | + documentation for exactly how many groups we fill. |
| 11813 | + |
| 11814 | + We return -1 if no match, -2 if an internal error (such as the |
| 11815 | + failure stack overflowing). Otherwise, we return the length of the |
| 11816 | + matched substring. */ |
| 11817 | + |
| 11818 | +int |
| 11819 | +re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, |
| 11820 | + const char *string2, int size2, int pos, |
| 11821 | + struct re_registers *regs, int stop) |
| 11822 | +{ |
| 11823 | + int result; |
| 11824 | +# ifdef MBS_SUPPORT |
| 11825 | + if (MB_CUR_MAX != 1) |
| 11826 | + result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, |
| 11827 | + pos, regs, stop, |
| 11828 | + NULL, 0, NULL, 0, NULL, NULL); |
| 11829 | + else |
| 11830 | +# endif |
| 11831 | + result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, |
| 11832 | + pos, regs, stop); |
| 11833 | + |
| 11834 | +#ifndef REGEX_MALLOC |
| 11835 | +# ifdef C_ALLOCA |
| 11836 | + alloca (0); |
| 11837 | +# endif |
| 11838 | +#endif |
| 11839 | + return result; |
| 11840 | +} |
| 11841 | +#ifdef _LIBC |
| 11842 | +weak_alias (__re_match_2, re_match_2) |
| 11843 | +#endif |
| 11844 | + |
| 11845 | +#endif /* not INSIDE_RECURSION */ |
| 11846 | + |
| 11847 | +#ifdef INSIDE_RECURSION |
| 11848 | + |
| 11849 | +#ifdef WCHAR |
| 11850 | +static int count_mbs_length (int *, int); |
| 11851 | + |
| 11852 | +/* This check the substring (from 0, to length) of the multibyte string, |
| 11853 | + to which offset_buffer correspond. And count how many wchar_t_characters |
| 11854 | + the substring occupy. We use offset_buffer to optimization. |
| 11855 | + See convert_mbs_to_wcs. */ |
| 11856 | + |
| 11857 | +static int |
| 11858 | +count_mbs_length(int *offset_buffer, int length) |
| 11859 | +{ |
| 11860 | + int upper, lower; |
| 11861 | + |
| 11862 | + /* Check whether the size is valid. */ |
| 11863 | + if (length < 0) |
| 11864 | + return -1; |
| 11865 | + |
| 11866 | + if (offset_buffer == NULL) |
| 11867 | + return 0; |
| 11868 | + |
| 11869 | + /* If there are no multibyte character, offset_buffer[i] == i. |
| 11870 | + Optmize for this case. */ |
| 11871 | + if (offset_buffer[length] == length) |
| 11872 | + return length; |
| 11873 | + |
| 11874 | + /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ |
| 11875 | + upper = length; |
| 11876 | + lower = 0; |
| 11877 | + |
| 11878 | + while (true) |
| 11879 | + { |
| 11880 | + int middle = (lower + upper) / 2; |
| 11881 | + if (middle == lower || middle == upper) |
| 11882 | + break; |
| 11883 | + if (offset_buffer[middle] > length) |
| 11884 | + upper = middle; |
| 11885 | + else if (offset_buffer[middle] < length) |
| 11886 | + lower = middle; |
| 11887 | + else |
| 11888 | + return middle; |
| 11889 | + } |
| 11890 | + |
| 11891 | + return -1; |
| 11892 | +} |
| 11893 | +#endif /* WCHAR */ |
| 11894 | + |
| 11895 | +/* This is a separate function so that we can force an alloca cleanup |
| 11896 | + afterwards. */ |
| 11897 | +#ifdef WCHAR |
| 11898 | +static int |
| 11899 | +wcs_re_match_2_internal (struct re_pattern_buffer *bufp, |
| 11900 | + const char *cstring1, int csize1, |
| 11901 | + const char *cstring2, int csize2, |
| 11902 | + int pos, |
| 11903 | + struct re_registers *regs, |
| 11904 | + int stop, |
| 11905 | + /* string1 == string2 == NULL means string1/2, size1/2 and |
| 11906 | + mbs_offset1/2 need seting up in this function. */ |
| 11907 | + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ |
| 11908 | + wchar_t *string1, int size1, |
| 11909 | + wchar_t *string2, int size2, |
| 11910 | + /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ |
| 11911 | + int *mbs_offset1, int *mbs_offset2) |
| 11912 | +#else /* BYTE */ |
| 11913 | +static int |
| 11914 | +byte_re_match_2_internal (struct re_pattern_buffer *bufp, |
| 11915 | + const char *string1, int size1, |
| 11916 | + const char *string2, int size2, |
| 11917 | + int pos, |
| 11918 | + struct re_registers *regs, int stop) |
| 11919 | +#endif /* BYTE */ |
| 11920 | +{ |
| 11921 | + /* General temporaries. */ |
| 11922 | + int mcnt; |
| 11923 | + UCHAR_T *p1; |
| 11924 | +#ifdef WCHAR |
| 11925 | + /* They hold whether each wchar_t is binary data or not. */ |
| 11926 | + char *is_binary = NULL; |
| 11927 | + /* If true, we can't free string1/2, mbs_offset1/2. */ |
| 11928 | + int cant_free_wcs_buf = 1; |
| 11929 | +#endif /* WCHAR */ |
| 11930 | + |
| 11931 | + /* Just past the end of the corresponding string. */ |
| 11932 | + const CHAR_T *end1, *end2; |
| 11933 | + |
| 11934 | + /* Pointers into string1 and string2, just past the last characters in |
| 11935 | + each to consider matching. */ |
| 11936 | + const CHAR_T *end_match_1, *end_match_2; |
| 11937 | + |
| 11938 | + /* Where we are in the data, and the end of the current string. */ |
| 11939 | + const CHAR_T *d, *dend; |
| 11940 | + |
| 11941 | + /* Where we are in the pattern, and the end of the pattern. */ |
| 11942 | +#ifdef WCHAR |
| 11943 | + UCHAR_T *pattern, *p; |
| 11944 | + register UCHAR_T *pend; |
| 11945 | +#else /* BYTE */ |
| 11946 | + UCHAR_T *p = bufp->buffer; |
| 11947 | + register UCHAR_T *pend = p + bufp->used; |
| 11948 | +#endif /* WCHAR */ |
| 11949 | + |
| 11950 | + /* Mark the opcode just after a start_memory, so we can test for an |
| 11951 | + empty subpattern when we get to the stop_memory. */ |
| 11952 | + UCHAR_T *just_past_start_mem = 0; |
| 11953 | + |
| 11954 | + /* We use this to map every character in the string. */ |
| 11955 | + RE_TRANSLATE_TYPE translate = bufp->translate; |
| 11956 | + |
| 11957 | + /* Failure point stack. Each place that can handle a failure further |
| 11958 | + down the line pushes a failure point on this stack. It consists of |
| 11959 | + restart, regend, and reg_info for all registers corresponding to |
| 11960 | + the subexpressions we're currently inside, plus the number of such |
| 11961 | + registers, and, finally, two char *'s. The first char * is where |
| 11962 | + to resume scanning the pattern; the second one is where to resume |
| 11963 | + scanning the strings. If the latter is zero, the failure point is |
| 11964 | + a ``dummy''; if a failure happens and the failure point is a dummy, |
| 11965 | + it gets discarded and the next next one is tried. */ |
| 11966 | +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ |
| 11967 | + PREFIX(fail_stack_type) fail_stack; |
| 11968 | +#endif |
| 11969 | +#ifdef DEBUG |
| 11970 | + static unsigned failure_id; |
| 11971 | + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; |
| 11972 | +#endif |
| 11973 | + |
| 11974 | +#ifdef REL_ALLOC |
| 11975 | + /* This holds the pointer to the failure stack, when |
| 11976 | + it is allocated relocatably. */ |
| 11977 | + fail_stack_elt_t *failure_stack_ptr; |
| 11978 | +#endif |
| 11979 | + |
| 11980 | + /* We fill all the registers internally, independent of what we |
| 11981 | + return, for use in backreferences. The number here includes |
| 11982 | + an element for register zero. */ |
| 11983 | + size_t num_regs = bufp->re_nsub + 1; |
| 11984 | + |
| 11985 | + /* The currently active registers. */ |
| 11986 | + active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; |
| 11987 | + active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; |
| 11988 | + |
| 11989 | + /* Information on the contents of registers. These are pointers into |
| 11990 | + the input strings; they record just what was matched (on this |
| 11991 | + attempt) by a subexpression part of the pattern, that is, the |
| 11992 | + regnum-th regstart pointer points to where in the pattern we began |
| 11993 | + matching and the regnum-th regend points to right after where we |
| 11994 | + stopped matching the regnum-th subexpression. (The zeroth register |
| 11995 | + keeps track of what the whole pattern matches.) */ |
| 11996 | +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ |
| 11997 | + const CHAR_T **regstart, **regend; |
| 11998 | +#endif |
| 11999 | + |
| 12000 | + /* If a group that's operated upon by a repetition operator fails to |
| 12001 | + match anything, then the register for its start will need to be |
| 12002 | + restored because it will have been set to wherever in the string we |
| 12003 | + are when we last see its open-group operator. Similarly for a |
| 12004 | + register's end. */ |
| 12005 | +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ |
| 12006 | + const CHAR_T **old_regstart, **old_regend; |
| 12007 | +#endif |
| 12008 | + |
| 12009 | + /* The is_active field of reg_info helps us keep track of which (possibly |
| 12010 | + nested) subexpressions we are currently in. The matched_something |
| 12011 | + field of reg_info[reg_num] helps us tell whether or not we have |
| 12012 | + matched any of the pattern so far this time through the reg_num-th |
| 12013 | + subexpression. These two fields get reset each time through any |
| 12014 | + loop their register is in. */ |
| 12015 | +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ |
| 12016 | + PREFIX(register_info_type) *reg_info; |
| 12017 | +#endif |
| 12018 | + |
| 12019 | + /* The following record the register info as found in the above |
| 12020 | + variables when we find a match better than any we've seen before. |
| 12021 | + This happens as we backtrack through the failure points, which in |
| 12022 | + turn happens only if we have not yet matched the entire string. */ |
| 12023 | + unsigned best_regs_set = false; |
| 12024 | +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ |
| 12025 | + const CHAR_T **best_regstart, **best_regend; |
| 12026 | +#endif |
| 12027 | + |
| 12028 | + /* Logically, this is `best_regend[0]'. But we don't want to have to |
| 12029 | + allocate space for that if we're not allocating space for anything |
| 12030 | + else (see below). Also, we never need info about register 0 for |
| 12031 | + any of the other register vectors, and it seems rather a kludge to |
| 12032 | + treat `best_regend' differently than the rest. So we keep track of |
| 12033 | + the end of the best match so far in a separate variable. We |
| 12034 | + initialize this to NULL so that when we backtrack the first time |
| 12035 | + and need to test it, it's not garbage. */ |
| 12036 | + const CHAR_T *match_end = NULL; |
| 12037 | + |
| 12038 | + /* This helps SET_REGS_MATCHED avoid doing redundant work. */ |
| 12039 | + int set_regs_matched_done = 0; |
| 12040 | + |
| 12041 | + /* Used when we pop values we don't care about. */ |
| 12042 | +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ |
| 12043 | + const CHAR_T **reg_dummy; |
| 12044 | + PREFIX(register_info_type) *reg_info_dummy; |
| 12045 | +#endif |
| 12046 | + |
| 12047 | +#ifdef DEBUG |
| 12048 | + /* Counts the total number of registers pushed. */ |
| 12049 | + unsigned num_regs_pushed = 0; |
| 12050 | +#endif |
| 12051 | + |
| 12052 | + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); |
| 12053 | + |
| 12054 | + INIT_FAIL_STACK (); |
| 12055 | + |
| 12056 | +#ifdef MATCH_MAY_ALLOCATE |
| 12057 | + /* Do not bother to initialize all the register variables if there are |
| 12058 | + no groups in the pattern, as it takes a fair amount of time. If |
| 12059 | + there are groups, we include space for register 0 (the whole |
| 12060 | + pattern), even though we never use it, since it simplifies the |
| 12061 | + array indexing. We should fix this. */ |
| 12062 | + if (bufp->re_nsub) |
| 12063 | + { |
| 12064 | + regstart = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12065 | + regend = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12066 | + old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12067 | + old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12068 | + best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12069 | + best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12070 | + reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); |
| 12071 | + reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); |
| 12072 | + reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); |
| 12073 | + |
| 12074 | + if (!(regstart && regend && old_regstart && old_regend && reg_info |
| 12075 | + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) |
| 12076 | + { |
| 12077 | + FREE_VARIABLES (); |
| 12078 | + return -2; |
| 12079 | + } |
| 12080 | + } |
| 12081 | + else |
| 12082 | + { |
| 12083 | + /* We must initialize all our variables to NULL, so that |
| 12084 | + `FREE_VARIABLES' doesn't try to free them. */ |
| 12085 | + regstart = regend = old_regstart = old_regend = best_regstart |
| 12086 | + = best_regend = reg_dummy = NULL; |
| 12087 | + reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; |
| 12088 | + } |
| 12089 | +#endif /* MATCH_MAY_ALLOCATE */ |
| 12090 | + |
| 12091 | + /* The starting position is bogus. */ |
| 12092 | +#ifdef WCHAR |
| 12093 | + if (pos < 0 || pos > csize1 + csize2) |
| 12094 | +#else /* BYTE */ |
| 12095 | + if (pos < 0 || pos > size1 + size2) |
| 12096 | +#endif |
| 12097 | + { |
| 12098 | + FREE_VARIABLES (); |
| 12099 | + return -1; |
| 12100 | + } |
| 12101 | + |
| 12102 | +#ifdef WCHAR |
| 12103 | + /* Allocate wchar_t array for string1 and string2 and |
| 12104 | + fill them with converted string. */ |
| 12105 | + if (string1 == NULL && string2 == NULL) |
| 12106 | + { |
| 12107 | + /* We need seting up buffers here. */ |
| 12108 | + |
| 12109 | + /* We must free wcs buffers in this function. */ |
| 12110 | + cant_free_wcs_buf = 0; |
| 12111 | + |
| 12112 | + if (csize1 != 0) |
| 12113 | + { |
| 12114 | + string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); |
| 12115 | + mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); |
| 12116 | + is_binary = REGEX_TALLOC (csize1 + 1, char); |
| 12117 | + if (!string1 || !mbs_offset1 || !is_binary) |
| 12118 | + { |
| 12119 | + FREE_VAR (string1); |
| 12120 | + FREE_VAR (mbs_offset1); |
| 12121 | + FREE_VAR (is_binary); |
| 12122 | + return -2; |
| 12123 | + } |
| 12124 | + } |
| 12125 | + if (csize2 != 0) |
| 12126 | + { |
| 12127 | + string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); |
| 12128 | + mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); |
| 12129 | + is_binary = REGEX_TALLOC (csize2 + 1, char); |
| 12130 | + if (!string2 || !mbs_offset2 || !is_binary) |
| 12131 | + { |
| 12132 | + FREE_VAR (string1); |
| 12133 | + FREE_VAR (mbs_offset1); |
| 12134 | + FREE_VAR (string2); |
| 12135 | + FREE_VAR (mbs_offset2); |
| 12136 | + FREE_VAR (is_binary); |
| 12137 | + return -2; |
| 12138 | + } |
| 12139 | + size2 = convert_mbs_to_wcs(string2, cstring2, csize2, |
| 12140 | + mbs_offset2, is_binary); |
| 12141 | + string2[size2] = L'\0'; /* for a sentinel */ |
| 12142 | + FREE_VAR (is_binary); |
| 12143 | + } |
| 12144 | + } |
| 12145 | + |
| 12146 | + /* We need to cast pattern to (wchar_t*), because we casted this compiled |
| 12147 | + pattern to (char*) in regex_compile. */ |
| 12148 | + p = pattern = (CHAR_T*)bufp->buffer; |
| 12149 | + pend = (CHAR_T*)(bufp->buffer + bufp->used); |
| 12150 | + |
| 12151 | +#endif /* WCHAR */ |
| 12152 | + |
| 12153 | + /* Initialize subexpression text positions to -1 to mark ones that no |
| 12154 | + start_memory/stop_memory has been seen for. Also initialize the |
| 12155 | + register information struct. */ |
| 12156 | + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) |
| 12157 | + { |
| 12158 | + regstart[mcnt] = regend[mcnt] |
| 12159 | + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; |
| 12160 | + |
| 12161 | + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; |
| 12162 | + IS_ACTIVE (reg_info[mcnt]) = 0; |
| 12163 | + MATCHED_SOMETHING (reg_info[mcnt]) = 0; |
| 12164 | + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; |
| 12165 | + } |
| 12166 | + |
| 12167 | + /* We move `string1' into `string2' if the latter's empty -- but not if |
| 12168 | + `string1' is null. */ |
| 12169 | + if (size2 == 0 && string1 != NULL) |
| 12170 | + { |
| 12171 | + string2 = string1; |
| 12172 | + size2 = size1; |
| 12173 | + string1 = 0; |
| 12174 | + size1 = 0; |
| 12175 | +#ifdef WCHAR |
| 12176 | + mbs_offset2 = mbs_offset1; |
| 12177 | + csize2 = csize1; |
| 12178 | + mbs_offset1 = NULL; |
| 12179 | + csize1 = 0; |
| 12180 | +#endif |
| 12181 | + } |
| 12182 | + end1 = string1 + size1; |
| 12183 | + end2 = string2 + size2; |
| 12184 | + |
| 12185 | + /* Compute where to stop matching, within the two strings. */ |
| 12186 | +#ifdef WCHAR |
| 12187 | + if (stop <= csize1) |
| 12188 | + { |
| 12189 | + mcnt = count_mbs_length(mbs_offset1, stop); |
| 12190 | + end_match_1 = string1 + mcnt; |
| 12191 | + end_match_2 = string2; |
| 12192 | + } |
| 12193 | + else |
| 12194 | + { |
| 12195 | + if (stop > csize1 + csize2) |
| 12196 | + stop = csize1 + csize2; |
| 12197 | + end_match_1 = end1; |
| 12198 | + mcnt = count_mbs_length(mbs_offset2, stop-csize1); |
| 12199 | + end_match_2 = string2 + mcnt; |
| 12200 | + } |
| 12201 | + if (mcnt < 0) |
| 12202 | + { /* count_mbs_length return error. */ |
| 12203 | + FREE_VARIABLES (); |
| 12204 | + return -1; |
| 12205 | + } |
| 12206 | +#else |
| 12207 | + if (stop <= size1) |
| 12208 | + { |
| 12209 | + end_match_1 = string1 + stop; |
| 12210 | + end_match_2 = string2; |
| 12211 | + } |
| 12212 | + else |
| 12213 | + { |
| 12214 | + end_match_1 = end1; |
| 12215 | + end_match_2 = string2 + stop - size1; |
| 12216 | + } |
| 12217 | +#endif /* WCHAR */ |
| 12218 | + |
| 12219 | + /* `p' scans through the pattern as `d' scans through the data. |
| 12220 | + `dend' is the end of the input string that `d' points within. `d' |
| 12221 | + is advanced into the following input string whenever necessary, but |
| 12222 | + this happens before fetching; therefore, at the beginning of the |
| 12223 | + loop, `d' can be pointing at the end of a string, but it cannot |
| 12224 | + equal `string2'. */ |
| 12225 | +#ifdef WCHAR |
| 12226 | + if (size1 > 0 && pos <= csize1) |
| 12227 | + { |
| 12228 | + mcnt = count_mbs_length(mbs_offset1, pos); |
| 12229 | + d = string1 + mcnt; |
| 12230 | + dend = end_match_1; |
| 12231 | + } |
| 12232 | + else |
| 12233 | + { |
| 12234 | + mcnt = count_mbs_length(mbs_offset2, pos-csize1); |
| 12235 | + d = string2 + mcnt; |
| 12236 | + dend = end_match_2; |
| 12237 | + } |
| 12238 | + |
| 12239 | + if (mcnt < 0) |
| 12240 | + { /* count_mbs_length return error. */ |
| 12241 | + FREE_VARIABLES (); |
| 12242 | + return -1; |
| 12243 | + } |
| 12244 | +#else |
| 12245 | + if (size1 > 0 && pos <= size1) |
| 12246 | + { |
| 12247 | + d = string1 + pos; |
| 12248 | + dend = end_match_1; |
| 12249 | + } |
| 12250 | + else |
| 12251 | + { |
| 12252 | + d = string2 + pos - size1; |
| 12253 | + dend = end_match_2; |
| 12254 | + } |
| 12255 | +#endif /* WCHAR */ |
| 12256 | + |
| 12257 | + DEBUG_PRINT1 ("The compiled pattern is:\n"); |
| 12258 | + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); |
| 12259 | + DEBUG_PRINT1 ("The string to match is: `"); |
| 12260 | + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); |
| 12261 | + DEBUG_PRINT1 ("'\n"); |
| 12262 | + |
| 12263 | + /* This loops over pattern commands. It exits by returning from the |
| 12264 | + function if the match is complete, or it drops through if the match |
| 12265 | + fails at this starting point in the input data. */ |
| 12266 | + for (;;) |
| 12267 | + { |
| 12268 | +#ifdef _LIBC |
| 12269 | + DEBUG_PRINT2 ("\n%p: ", p); |
| 12270 | +#else |
| 12271 | + DEBUG_PRINT2 ("\n0x%x: ", p); |
| 12272 | +#endif |
| 12273 | + |
| 12274 | + if (p == pend) |
| 12275 | + { /* End of pattern means we might have succeeded. */ |
| 12276 | + DEBUG_PRINT1 ("end of pattern ... "); |
| 12277 | + |
| 12278 | + /* If we haven't matched the entire string, and we want the |
| 12279 | + longest match, try backtracking. */ |
| 12280 | + if (d != end_match_2) |
| 12281 | + { |
| 12282 | + /* 1 if this match ends in the same string (string1 or string2) |
| 12283 | + as the best previous match. */ |
| 12284 | + boolean same_str_p = (FIRST_STRING_P (match_end) |
| 12285 | + == MATCHING_IN_FIRST_STRING); |
| 12286 | + /* 1 if this match is the best seen so far. */ |
| 12287 | + boolean best_match_p; |
| 12288 | + |
| 12289 | + /* AIX compiler got confused when this was combined |
| 12290 | + with the previous declaration. */ |
| 12291 | + if (same_str_p) |
| 12292 | + best_match_p = d > match_end; |
| 12293 | + else |
| 12294 | + best_match_p = !MATCHING_IN_FIRST_STRING; |
| 12295 | + |
| 12296 | + DEBUG_PRINT1 ("backtracking.\n"); |
| 12297 | + |
| 12298 | + if (!FAIL_STACK_EMPTY ()) |
| 12299 | + { /* More failure points to try. */ |
| 12300 | + |
| 12301 | + /* If exceeds best match so far, save it. */ |
| 12302 | + if (!best_regs_set || best_match_p) |
| 12303 | + { |
| 12304 | + best_regs_set = true; |
| 12305 | + match_end = d; |
| 12306 | + |
| 12307 | + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); |
| 12308 | + |
| 12309 | + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) |
| 12310 | + { |
| 12311 | + best_regstart[mcnt] = regstart[mcnt]; |
| 12312 | + best_regend[mcnt] = regend[mcnt]; |
| 12313 | + } |
| 12314 | + } |
| 12315 | + goto fail; |
| 12316 | + } |
| 12317 | + |
| 12318 | + /* If no failure points, don't restore garbage. And if |
| 12319 | + last match is real best match, don't restore second |
| 12320 | + best one. */ |
| 12321 | + else if (best_regs_set && !best_match_p) |
| 12322 | + { |
| 12323 | + restore_best_regs: |
| 12324 | + /* Restore best match. It may happen that `dend == |
| 12325 | + end_match_1' while the restored d is in string2. |
| 12326 | + For example, the pattern `x.*y.*z' against the |
| 12327 | + strings `x-' and `y-z-', if the two strings are |
| 12328 | + not consecutive in memory. */ |
| 12329 | + DEBUG_PRINT1 ("Restoring best registers.\n"); |
| 12330 | + |
| 12331 | + d = match_end; |
| 12332 | + dend = ((d >= string1 && d <= end1) |
| 12333 | + ? end_match_1 : end_match_2); |
| 12334 | + |
| 12335 | + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) |
| 12336 | + { |
| 12337 | + regstart[mcnt] = best_regstart[mcnt]; |
| 12338 | + regend[mcnt] = best_regend[mcnt]; |
| 12339 | + } |
| 12340 | + } |
| 12341 | + } /* d != end_match_2 */ |
| 12342 | + |
| 12343 | + succeed_label: |
| 12344 | + DEBUG_PRINT1 ("Accepting match.\n"); |
| 12345 | + /* If caller wants register contents data back, do it. */ |
| 12346 | + if (regs && !bufp->no_sub) |
| 12347 | + { |
| 12348 | + /* Have the register data arrays been allocated? */ |
| 12349 | + if (bufp->regs_allocated == REGS_UNALLOCATED) |
| 12350 | + { /* No. So allocate them with malloc. We need one |
| 12351 | + extra element beyond `num_regs' for the `-1' marker |
| 12352 | + GNU code uses. */ |
| 12353 | + regs->num_regs = MAX (RE_NREGS, num_regs + 1); |
| 12354 | + regs->start = TALLOC (regs->num_regs, regoff_t); |
| 12355 | + regs->end = TALLOC (regs->num_regs, regoff_t); |
| 12356 | + if (regs->start == NULL || regs->end == NULL) |
| 12357 | + { |
| 12358 | + FREE_VARIABLES (); |
| 12359 | + return -2; |
| 12360 | + } |
| 12361 | + bufp->regs_allocated = REGS_REALLOCATE; |
| 12362 | + } |
| 12363 | + else if (bufp->regs_allocated == REGS_REALLOCATE) |
| 12364 | + { /* Yes. If we need more elements than were already |
| 12365 | + allocated, reallocate them. If we need fewer, just |
| 12366 | + leave it alone. */ |
| 12367 | + if (regs->num_regs < num_regs + 1) |
| 12368 | + { |
| 12369 | + regs->num_regs = num_regs + 1; |
| 12370 | + RETALLOC (regs->start, regs->num_regs, regoff_t); |
| 12371 | + RETALLOC (regs->end, regs->num_regs, regoff_t); |
| 12372 | + if (regs->start == NULL || regs->end == NULL) |
| 12373 | + { |
| 12374 | + FREE_VARIABLES (); |
| 12375 | + return -2; |
| 12376 | + } |
| 12377 | + } |
| 12378 | + } |
| 12379 | + else |
| 12380 | + { |
| 12381 | + /* These braces fend off a "empty body in an else-statement" |
| 12382 | + warning under GCC when assert expands to nothing. */ |
| 12383 | + assert (bufp->regs_allocated == REGS_FIXED); |
| 12384 | + } |
| 12385 | + |
| 12386 | + /* Convert the pointer data in `regstart' and `regend' to |
| 12387 | + indices. Register zero has to be set differently, |
| 12388 | + since we haven't kept track of any info for it. */ |
| 12389 | + if (regs->num_regs > 0) |
| 12390 | + { |
| 12391 | + regs->start[0] = pos; |
| 12392 | +#ifdef WCHAR |
| 12393 | + if (MATCHING_IN_FIRST_STRING) |
| 12394 | + regs->end[0] = mbs_offset1 != NULL ? |
| 12395 | + mbs_offset1[d-string1] : 0; |
| 12396 | + else |
| 12397 | + regs->end[0] = csize1 + (mbs_offset2 != NULL ? |
| 12398 | + mbs_offset2[d-string2] : 0); |
| 12399 | +#else |
| 12400 | + regs->end[0] = (MATCHING_IN_FIRST_STRING |
| 12401 | + ? ((regoff_t) (d - string1)) |
| 12402 | + : ((regoff_t) (d - string2 + size1))); |
| 12403 | +#endif /* WCHAR */ |
| 12404 | + } |
| 12405 | + |
| 12406 | + /* Go through the first `min (num_regs, regs->num_regs)' |
| 12407 | + registers, since that is all we initialized. */ |
| 12408 | + for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); |
| 12409 | + mcnt++) |
| 12410 | + { |
| 12411 | + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) |
| 12412 | + regs->start[mcnt] = regs->end[mcnt] = -1; |
| 12413 | + else |
| 12414 | + { |
| 12415 | + regs->start[mcnt] |
| 12416 | + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); |
| 12417 | + regs->end[mcnt] |
| 12418 | + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); |
| 12419 | + } |
| 12420 | + } |
| 12421 | + |
| 12422 | + /* If the regs structure we return has more elements than |
| 12423 | + were in the pattern, set the extra elements to -1. If |
| 12424 | + we (re)allocated the registers, this is the case, |
| 12425 | + because we always allocate enough to have at least one |
| 12426 | + -1 at the end. */ |
| 12427 | + for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) |
| 12428 | + regs->start[mcnt] = regs->end[mcnt] = -1; |
| 12429 | + } /* regs && !bufp->no_sub */ |
| 12430 | + |
| 12431 | + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", |
| 12432 | + nfailure_points_pushed, nfailure_points_popped, |
| 12433 | + nfailure_points_pushed - nfailure_points_popped); |
| 12434 | + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); |
| 12435 | + |
| 12436 | +#ifdef WCHAR |
| 12437 | + if (MATCHING_IN_FIRST_STRING) |
| 12438 | + mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; |
| 12439 | + else |
| 12440 | + mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + |
| 12441 | + csize1; |
| 12442 | + mcnt -= pos; |
| 12443 | +#else |
| 12444 | + mcnt = d - pos - (MATCHING_IN_FIRST_STRING |
| 12445 | + ? string1 |
| 12446 | + : string2 - size1); |
| 12447 | +#endif /* WCHAR */ |
| 12448 | + |
| 12449 | + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); |
| 12450 | + |
| 12451 | + FREE_VARIABLES (); |
| 12452 | + return mcnt; |
| 12453 | + } |
| 12454 | + |
| 12455 | + /* Otherwise match next pattern command. */ |
| 12456 | + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) |
| 12457 | + { |
| 12458 | + /* Ignore these. Used to ignore the n of succeed_n's which |
| 12459 | + currently have n == 0. */ |
| 12460 | + case no_op: |
| 12461 | + DEBUG_PRINT1 ("EXECUTING no_op.\n"); |
| 12462 | + break; |
| 12463 | + |
| 12464 | + case succeed: |
| 12465 | + DEBUG_PRINT1 ("EXECUTING succeed.\n"); |
| 12466 | + goto succeed_label; |
| 12467 | + |
| 12468 | + /* Match the next n pattern characters exactly. The following |
| 12469 | + byte in the pattern defines n, and the n bytes after that |
| 12470 | + are the characters to match. */ |
| 12471 | + case exactn: |
| 12472 | +#ifdef MBS_SUPPORT |
| 12473 | + case exactn_bin: |
| 12474 | +#endif |
| 12475 | + mcnt = *p++; |
| 12476 | + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); |
| 12477 | + |
| 12478 | + /* This is written out as an if-else so we don't waste time |
| 12479 | + testing `translate' inside the loop. */ |
| 12480 | + if (translate) |
| 12481 | + { |
| 12482 | + do |
| 12483 | + { |
| 12484 | + PREFETCH (); |
| 12485 | +#ifdef WCHAR |
| 12486 | + if (*d <= 0xff) |
| 12487 | + { |
| 12488 | + if ((UCHAR_T) translate[(unsigned char) *d++] |
| 12489 | + != (UCHAR_T) *p++) |
| 12490 | + goto fail; |
| 12491 | + } |
| 12492 | + else |
| 12493 | + { |
| 12494 | + if (*d++ != (CHAR_T) *p++) |
| 12495 | + goto fail; |
| 12496 | + } |
| 12497 | +#else |
| 12498 | + if ((UCHAR_T) translate[(unsigned char) *d++] |
| 12499 | + != (UCHAR_T) *p++) |
| 12500 | + goto fail; |
| 12501 | +#endif /* WCHAR */ |
| 12502 | + } |
| 12503 | + while (--mcnt); |
| 12504 | + } |
| 12505 | + else |
| 12506 | + { |
| 12507 | + do |
| 12508 | + { |
| 12509 | + PREFETCH (); |
| 12510 | + if (*d++ != (CHAR_T) *p++) goto fail; |
| 12511 | + } |
| 12512 | + while (--mcnt); |
| 12513 | + } |
| 12514 | + SET_REGS_MATCHED (); |
| 12515 | + break; |
| 12516 | + |
| 12517 | + |
| 12518 | + /* Match any character except possibly a newline or a null. */ |
| 12519 | + case anychar: |
| 12520 | + DEBUG_PRINT1 ("EXECUTING anychar.\n"); |
| 12521 | + |
| 12522 | + PREFETCH (); |
| 12523 | + |
| 12524 | + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') |
| 12525 | + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) |
| 12526 | + goto fail; |
| 12527 | + |
| 12528 | + SET_REGS_MATCHED (); |
| 12529 | + DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); |
| 12530 | + d++; |
| 12531 | + break; |
| 12532 | + |
| 12533 | + |
| 12534 | + case charset: |
| 12535 | + case charset_not: |
| 12536 | + { |
| 12537 | + register UCHAR_T c; |
| 12538 | +#ifdef WCHAR |
| 12539 | + unsigned int i, char_class_length, coll_symbol_length, |
| 12540 | + equiv_class_length, ranges_length, chars_length, length; |
| 12541 | + CHAR_T *workp, *workp2, *charset_top; |
| 12542 | +#define WORK_BUFFER_SIZE 128 |
| 12543 | + CHAR_T str_buf[WORK_BUFFER_SIZE]; |
| 12544 | +# ifdef _LIBC |
| 12545 | + uint32_t nrules; |
| 12546 | +# endif /* _LIBC */ |
| 12547 | +#endif /* WCHAR */ |
| 12548 | + boolean negate = (re_opcode_t) *(p - 1) == charset_not; |
| 12549 | + |
| 12550 | + DEBUG_PRINT2 ("EXECUTING charset%s.\n", negate ? "_not" : ""); |
| 12551 | + PREFETCH (); |
| 12552 | + c = TRANSLATE (*d); /* The character to match. */ |
| 12553 | +#ifdef WCHAR |
| 12554 | +# ifdef _LIBC |
| 12555 | + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); |
| 12556 | +# endif /* _LIBC */ |
| 12557 | + charset_top = p - 1; |
| 12558 | + char_class_length = *p++; |
| 12559 | + coll_symbol_length = *p++; |
| 12560 | + equiv_class_length = *p++; |
| 12561 | + ranges_length = *p++; |
| 12562 | + chars_length = *p++; |
| 12563 | + /* p points charset[6], so the address of the next instruction |
| 12564 | + (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'], |
| 12565 | + where l=length of char_classes, m=length of collating_symbol, |
| 12566 | + n=equivalence_class, o=length of char_range, |
| 12567 | + p'=length of character. */ |
| 12568 | + workp = p; |
| 12569 | + /* Update p to indicate the next instruction. */ |
| 12570 | + p += char_class_length + coll_symbol_length+ equiv_class_length + |
| 12571 | + 2*ranges_length + chars_length; |
| 12572 | + |
| 12573 | + /* match with char_class? */ |
| 12574 | + for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE) |
| 12575 | + { |
| 12576 | + wctype_t wctype; |
| 12577 | + uintptr_t alignedp = ((uintptr_t)workp |
| 12578 | + + __alignof__(wctype_t) - 1) |
| 12579 | + & ~(uintptr_t)(__alignof__(wctype_t) - 1); |
| 12580 | + wctype = *((wctype_t*)alignedp); |
| 12581 | + workp += CHAR_CLASS_SIZE; |
| 12582 | +# ifdef _LIBC |
| 12583 | + if (__iswctype((wint_t)c, wctype)) |
| 12584 | + goto char_set_matched; |
| 12585 | +# else |
| 12586 | + if (iswctype((wint_t)c, wctype)) |
| 12587 | + goto char_set_matched; |
| 12588 | +# endif |
| 12589 | + } |
| 12590 | + |
| 12591 | + /* match with collating_symbol? */ |
| 12592 | +# ifdef _LIBC |
| 12593 | + if (nrules != 0) |
| 12594 | + { |
| 12595 | + const unsigned char *extra = (const unsigned char *) |
| 12596 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); |
| 12597 | + |
| 12598 | + for (workp2 = workp + coll_symbol_length ; workp < workp2 ; |
| 12599 | + workp++) |
| 12600 | + { |
| 12601 | + int32_t *wextra; |
| 12602 | + wextra = (int32_t*)(extra + *workp++); |
| 12603 | + for (i = 0; i < *wextra; ++i) |
| 12604 | + if (TRANSLATE(d[i]) != wextra[1 + i]) |
| 12605 | + break; |
| 12606 | + |
| 12607 | + if (i == *wextra) |
| 12608 | + { |
| 12609 | + /* Update d, however d will be incremented at |
| 12610 | + char_set_matched:, we decrement d here. */ |
| 12611 | + d += i - 1; |
| 12612 | + goto char_set_matched; |
| 12613 | + } |
| 12614 | + } |
| 12615 | + } |
| 12616 | + else /* (nrules == 0) */ |
| 12617 | +# endif |
| 12618 | + /* If we can't look up collation data, we use wcscoll |
| 12619 | + instead. */ |
| 12620 | + { |
| 12621 | + for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) |
| 12622 | + { |
| 12623 | + const CHAR_T *backup_d = d, *backup_dend = dend; |
| 12624 | +# ifdef _LIBC |
| 12625 | + length = __wcslen (workp); |
| 12626 | +# else |
| 12627 | + length = wcslen (workp); |
| 12628 | +# endif |
| 12629 | + |
| 12630 | + /* If wcscoll(the collating symbol, whole string) > 0, |
| 12631 | + any substring of the string never match with the |
| 12632 | + collating symbol. */ |
| 12633 | +# ifdef _LIBC |
| 12634 | + if (__wcscoll (workp, d) > 0) |
| 12635 | +# else |
| 12636 | + if (wcscoll (workp, d) > 0) |
| 12637 | +# endif |
| 12638 | + { |
| 12639 | + workp += length + 1; |
| 12640 | + continue; |
| 12641 | + } |
| 12642 | + |
| 12643 | + /* First, we compare the collating symbol with |
| 12644 | + the first character of the string. |
| 12645 | + If it don't match, we add the next character to |
| 12646 | + the compare buffer in turn. */ |
| 12647 | + for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++) |
| 12648 | + { |
| 12649 | + int match; |
| 12650 | + if (d == dend) |
| 12651 | + { |
| 12652 | + if (dend == end_match_2) |
| 12653 | + break; |
| 12654 | + d = string2; |
| 12655 | + dend = end_match_2; |
| 12656 | + } |
| 12657 | + |
| 12658 | + /* add next character to the compare buffer. */ |
| 12659 | + str_buf[i] = TRANSLATE(*d); |
| 12660 | + str_buf[i+1] = '\0'; |
| 12661 | + |
| 12662 | +# ifdef _LIBC |
| 12663 | + match = __wcscoll (workp, str_buf); |
| 12664 | +# else |
| 12665 | + match = wcscoll (workp, str_buf); |
| 12666 | +# endif |
| 12667 | + if (match == 0) |
| 12668 | + goto char_set_matched; |
| 12669 | + |
| 12670 | + if (match < 0) |
| 12671 | + /* (str_buf > workp) indicate (str_buf + X > workp), |
| 12672 | + because for all X (str_buf + X > str_buf). |
| 12673 | + So we don't need continue this loop. */ |
| 12674 | + break; |
| 12675 | + |
| 12676 | + /* Otherwise(str_buf < workp), |
| 12677 | + (str_buf+next_character) may equals (workp). |
| 12678 | + So we continue this loop. */ |
| 12679 | + } |
| 12680 | + /* not matched */ |
| 12681 | + d = backup_d; |
| 12682 | + dend = backup_dend; |
| 12683 | + workp += length + 1; |
| 12684 | + } |
| 12685 | + } |
| 12686 | + /* match with equivalence_class? */ |
| 12687 | +# ifdef _LIBC |
| 12688 | + if (nrules != 0) |
| 12689 | + { |
| 12690 | + const CHAR_T *backup_d = d, *backup_dend = dend; |
| 12691 | + /* Try to match the equivalence class against |
| 12692 | + those known to the collate implementation. */ |
| 12693 | + const int32_t *table; |
| 12694 | + const int32_t *weights; |
| 12695 | + const int32_t *extra; |
| 12696 | + const int32_t *indirect; |
| 12697 | + int32_t idx, idx2; |
| 12698 | + wint_t *cp; |
| 12699 | + size_t len; |
| 12700 | + |
| 12701 | + table = (const int32_t *) |
| 12702 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); |
| 12703 | + weights = (const wint_t *) |
| 12704 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); |
| 12705 | + extra = (const wint_t *) |
| 12706 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); |
| 12707 | + indirect = (const int32_t *) |
| 12708 | + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); |
| 12709 | + |
| 12710 | + /* Write 1 collating element to str_buf, and |
| 12711 | + get its index. */ |
| 12712 | + idx2 = 0; |
| 12713 | + |
| 12714 | + for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++) |
| 12715 | + { |
| 12716 | + cp = (wint_t*)str_buf; |
| 12717 | + if (d == dend) |
| 12718 | + { |
| 12719 | + if (dend == end_match_2) |
| 12720 | + break; |
| 12721 | + d = string2; |
| 12722 | + dend = end_match_2; |
| 12723 | + } |
| 12724 | + str_buf[i] = TRANSLATE(*(d+i)); |
| 12725 | + str_buf[i+1] = '\0'; /* sentinel */ |
| 12726 | + idx2 = FINDIDX (table, indirect, extra, &cp, 1); |
| 12727 | + } |
| 12728 | + |
| 12729 | + /* Update d, however d will be incremented at |
| 12730 | + char_set_matched:, we decrement d here. */ |
| 12731 | + d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1); |
| 12732 | + if (d >= dend) |
| 12733 | + { |
| 12734 | + if (dend == end_match_2) |
| 12735 | + d = dend; |
| 12736 | + else |
| 12737 | + { |
| 12738 | + d = string2; |
| 12739 | + dend = end_match_2; |
| 12740 | + } |
| 12741 | + } |
| 12742 | + |
| 12743 | + len = weights[idx2]; |
| 12744 | + |
| 12745 | + for (workp2 = workp + equiv_class_length ; workp < workp2 ; |
| 12746 | + workp++) |
| 12747 | + { |
| 12748 | + idx = (int32_t)*workp; |
| 12749 | + /* We already checked idx != 0 in regex_compile. */ |
| 12750 | + |
| 12751 | + if (idx2 != 0 && len == weights[idx]) |
| 12752 | + { |
| 12753 | + int cnt = 0; |
| 12754 | + while (cnt < len && (weights[idx + 1 + cnt] |
| 12755 | + == weights[idx2 + 1 + cnt])) |
| 12756 | + ++cnt; |
| 12757 | + |
| 12758 | + if (cnt == len) |
| 12759 | + goto char_set_matched; |
| 12760 | + } |
| 12761 | + } |
| 12762 | + /* not matched */ |
| 12763 | + d = backup_d; |
| 12764 | + dend = backup_dend; |
| 12765 | + } |
| 12766 | + else /* (nrules == 0) */ |
| 12767 | +# endif |
| 12768 | + /* If we can't look up collation data, we use wcscoll |
| 12769 | + instead. */ |
| 12770 | + { |
| 12771 | + for (workp2 = workp + equiv_class_length ; workp < workp2 ;) |
| 12772 | + { |
| 12773 | + const CHAR_T *backup_d = d, *backup_dend = dend; |
| 12774 | +# ifdef _LIBC |
| 12775 | + length = __wcslen (workp); |
| 12776 | +# else |
| 12777 | + length = wcslen (workp); |
| 12778 | +# endif |
| 12779 | + |
| 12780 | + /* If wcscoll(the collating symbol, whole string) > 0, |
| 12781 | + any substring of the string never match with the |
| 12782 | + collating symbol. */ |
| 12783 | +# ifdef _LIBC |
| 12784 | + if (__wcscoll (workp, d) > 0) |
| 12785 | +# else |
| 12786 | + if (wcscoll (workp, d) > 0) |
| 12787 | +# endif |
| 12788 | + { |
| 12789 | + workp += length + 1; |
| 12790 | + break; |
| 12791 | + } |
| 12792 | + |
| 12793 | + /* First, we compare the equivalence class with |
| 12794 | + the first character of the string. |
| 12795 | + If it don't match, we add the next character to |
| 12796 | + the compare buffer in turn. */ |
| 12797 | + for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++) |
| 12798 | + { |
| 12799 | + int match; |
| 12800 | + if (d == dend) |
| 12801 | + { |
| 12802 | + if (dend == end_match_2) |
| 12803 | + break; |
| 12804 | + d = string2; |
| 12805 | + dend = end_match_2; |
| 12806 | + } |
| 12807 | + |
| 12808 | + /* add next character to the compare buffer. */ |
| 12809 | + str_buf[i] = TRANSLATE(*d); |
| 12810 | + str_buf[i+1] = '\0'; |
| 12811 | + |
| 12812 | +# ifdef _LIBC |
| 12813 | + match = __wcscoll (workp, str_buf); |
| 12814 | +# else |
| 12815 | + match = wcscoll (workp, str_buf); |
| 12816 | +# endif |
| 12817 | + |
| 12818 | + if (match == 0) |
| 12819 | + goto char_set_matched; |
| 12820 | + |
| 12821 | + if (match < 0) |
| 12822 | + /* (str_buf > workp) indicate (str_buf + X > workp), |
| 12823 | + because for all X (str_buf + X > str_buf). |
| 12824 | + So we don't need continue this loop. */ |
| 12825 | + break; |
| 12826 | + |
| 12827 | + /* Otherwise(str_buf < workp), |
| 12828 | + (str_buf+next_character) may equals (workp). |
| 12829 | + So we continue this loop. */ |
| 12830 | + } |
| 12831 | + /* not matched */ |
| 12832 | + d = backup_d; |
| 12833 | + dend = backup_dend; |
| 12834 | + workp += length + 1; |
| 12835 | + } |
| 12836 | + } |
| 12837 | + |
| 12838 | + /* match with char_range? */ |
| 12839 | +# ifdef _LIBC |
| 12840 | + if (nrules != 0) |
| 12841 | + { |
| 12842 | + uint32_t collseqval; |
| 12843 | + const char *collseq = (const char *) |
| 12844 | + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); |
| 12845 | + |
| 12846 | + collseqval = collseq_table_lookup (collseq, c); |
| 12847 | + |
| 12848 | + for (; workp < p - chars_length ;) |
| 12849 | + { |
| 12850 | + uint32_t start_val, end_val; |
| 12851 | + |
| 12852 | + /* We already compute the collation sequence value |
| 12853 | + of the characters (or collating symbols). */ |
| 12854 | + start_val = (uint32_t) *workp++; /* range_start */ |
| 12855 | + end_val = (uint32_t) *workp++; /* range_end */ |
| 12856 | + |
| 12857 | + if (start_val <= collseqval && collseqval <= end_val) |
| 12858 | + goto char_set_matched; |
| 12859 | + } |
| 12860 | + } |
| 12861 | + else |
| 12862 | +# endif |
| 12863 | + { |
| 12864 | + /* We set range_start_char at str_buf[0], range_end_char |
| 12865 | + at str_buf[4], and compared char at str_buf[2]. */ |
| 12866 | + str_buf[1] = 0; |
| 12867 | + str_buf[2] = c; |
| 12868 | + str_buf[3] = 0; |
| 12869 | + str_buf[5] = 0; |
| 12870 | + for (; workp < p - chars_length ;) |
| 12871 | + { |
| 12872 | + wchar_t *range_start_char, *range_end_char; |
| 12873 | + |
| 12874 | + /* match if (range_start_char <= c <= range_end_char). */ |
| 12875 | + |
| 12876 | + /* If range_start(or end) < 0, we assume -range_start(end) |
| 12877 | + is the offset of the collating symbol which is specified |
| 12878 | + as the character of the range start(end). */ |
| 12879 | + |
| 12880 | + /* range_start */ |
| 12881 | + if (*workp < 0) |
| 12882 | + range_start_char = charset_top - (*workp++); |
| 12883 | + else |
| 12884 | + { |
| 12885 | + str_buf[0] = *workp++; |
| 12886 | + range_start_char = str_buf; |
| 12887 | + } |
| 12888 | + |
| 12889 | + /* range_end */ |
| 12890 | + if (*workp < 0) |
| 12891 | + range_end_char = charset_top - (*workp++); |
| 12892 | + else |
| 12893 | + { |
| 12894 | + str_buf[4] = *workp++; |
| 12895 | + range_end_char = str_buf + 4; |
| 12896 | + } |
| 12897 | + |
| 12898 | +# ifdef _LIBC |
| 12899 | + if (__wcscoll (range_start_char, str_buf+2) <= 0 |
| 12900 | + && __wcscoll (str_buf+2, range_end_char) <= 0) |
| 12901 | +# else |
| 12902 | + if (wcscoll (range_start_char, str_buf+2) <= 0 |
| 12903 | + && wcscoll (str_buf+2, range_end_char) <= 0) |
| 12904 | +# endif |
| 12905 | + goto char_set_matched; |
| 12906 | + } |
| 12907 | + } |
| 12908 | + |
| 12909 | + /* match with char? */ |
| 12910 | + for (; workp < p ; workp++) |
| 12911 | + if (c == *workp) |
| 12912 | + goto char_set_matched; |
| 12913 | + |
| 12914 | + negate = !negate; |
| 12915 | + |
| 12916 | + char_set_matched: |
| 12917 | + if (negate) goto fail; |
| 12918 | +#else |
| 12919 | + /* Cast to `unsigned' instead of `unsigned char' in case the |
| 12920 | + bit list is a full 32 bytes long. */ |
| 12921 | + if (c < (unsigned) (*p * BYTEWIDTH) |
| 12922 | + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) |
| 12923 | + negate = !negate; |
| 12924 | + |
| 12925 | + p += 1 + *p; |
| 12926 | + |
| 12927 | + if (!negate) goto fail; |
| 12928 | +#undef WORK_BUFFER_SIZE |
| 12929 | +#endif /* WCHAR */ |
| 12930 | + SET_REGS_MATCHED (); |
| 12931 | + d++; |
| 12932 | + break; |
| 12933 | + } |
| 12934 | + |
| 12935 | + |
| 12936 | + /* The beginning of a group is represented by start_memory. |
| 12937 | + The arguments are the register number in the next byte, and the |
| 12938 | + number of groups inner to this one in the next. The text |
| 12939 | + matched within the group is recorded (in the internal |
| 12940 | + registers data structure) under the register number. */ |
| 12941 | + case start_memory: |
| 12942 | + DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", |
| 12943 | + (long int) *p, (long int) p[1]); |
| 12944 | + |
| 12945 | + /* Find out if this group can match the empty string. */ |
| 12946 | + p1 = p; /* To send to group_match_null_string_p. */ |
| 12947 | + |
| 12948 | + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) |
| 12949 | + REG_MATCH_NULL_STRING_P (reg_info[*p]) |
| 12950 | + = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); |
| 12951 | + |
| 12952 | + /* Save the position in the string where we were the last time |
| 12953 | + we were at this open-group operator in case the group is |
| 12954 | + operated upon by a repetition operator, e.g., with `(a*)*b' |
| 12955 | + against `ab'; then we want to ignore where we are now in |
| 12956 | + the string in case this attempt to match fails. */ |
| 12957 | + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) |
| 12958 | + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] |
| 12959 | + : regstart[*p]; |
| 12960 | + DEBUG_PRINT2 (" old_regstart: %d\n", |
| 12961 | + POINTER_TO_OFFSET (old_regstart[*p])); |
| 12962 | + |
| 12963 | + regstart[*p] = d; |
| 12964 | + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); |
| 12965 | + |
| 12966 | + IS_ACTIVE (reg_info[*p]) = 1; |
| 12967 | + MATCHED_SOMETHING (reg_info[*p]) = 0; |
| 12968 | + |
| 12969 | + /* Clear this whenever we change the register activity status. */ |
| 12970 | + set_regs_matched_done = 0; |
| 12971 | + |
| 12972 | + /* This is the new highest active register. */ |
| 12973 | + highest_active_reg = *p; |
| 12974 | + |
| 12975 | + /* If nothing was active before, this is the new lowest active |
| 12976 | + register. */ |
| 12977 | + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) |
| 12978 | + lowest_active_reg = *p; |
| 12979 | + |
| 12980 | + /* Move past the register number and inner group count. */ |
| 12981 | + p += 2; |
| 12982 | + just_past_start_mem = p; |
| 12983 | + |
| 12984 | + break; |
| 12985 | + |
| 12986 | + |
| 12987 | + /* The stop_memory opcode represents the end of a group. Its |
| 12988 | + arguments are the same as start_memory's: the register |
| 12989 | + number, and the number of inner groups. */ |
| 12990 | + case stop_memory: |
| 12991 | + DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", |
| 12992 | + (long int) *p, (long int) p[1]); |
| 12993 | + |
| 12994 | + /* We need to save the string position the last time we were at |
| 12995 | + this close-group operator in case the group is operated |
| 12996 | + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' |
| 12997 | + against `aba'; then we want to ignore where we are now in |
| 12998 | + the string in case this attempt to match fails. */ |
| 12999 | + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) |
| 13000 | + ? REG_UNSET (regend[*p]) ? d : regend[*p] |
| 13001 | + : regend[*p]; |
| 13002 | + DEBUG_PRINT2 (" old_regend: %d\n", |
| 13003 | + POINTER_TO_OFFSET (old_regend[*p])); |
| 13004 | + |
| 13005 | + regend[*p] = d; |
| 13006 | + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); |
| 13007 | + |
| 13008 | + /* This register isn't active anymore. */ |
| 13009 | + IS_ACTIVE (reg_info[*p]) = 0; |
| 13010 | + |
| 13011 | + /* Clear this whenever we change the register activity status. */ |
| 13012 | + set_regs_matched_done = 0; |
| 13013 | + |
| 13014 | + /* If this was the only register active, nothing is active |
| 13015 | + anymore. */ |
| 13016 | + if (lowest_active_reg == highest_active_reg) |
| 13017 | + { |
| 13018 | + lowest_active_reg = NO_LOWEST_ACTIVE_REG; |
| 13019 | + highest_active_reg = NO_HIGHEST_ACTIVE_REG; |
| 13020 | + } |
| 13021 | + else |
| 13022 | + { /* We must scan for the new highest active register, since |
| 13023 | + it isn't necessarily one less than now: consider |
| 13024 | + (a(b)c(d(e)f)g). When group 3 ends, after the f), the |
| 13025 | + new highest active register is 1. */ |
| 13026 | + UCHAR_T r = *p - 1; |
| 13027 | + while (r > 0 && !IS_ACTIVE (reg_info[r])) |
| 13028 | + r--; |
| 13029 | + |
| 13030 | + /* If we end up at register zero, that means that we saved |
| 13031 | + the registers as the result of an `on_failure_jump', not |
| 13032 | + a `start_memory', and we jumped to past the innermost |
| 13033 | + `stop_memory'. For example, in ((.)*) we save |
| 13034 | + registers 1 and 2 as a result of the *, but when we pop |
| 13035 | + back to the second ), we are at the stop_memory 1. |
| 13036 | + Thus, nothing is active. */ |
| 13037 | + if (r == 0) |
| 13038 | + { |
| 13039 | + lowest_active_reg = NO_LOWEST_ACTIVE_REG; |
| 13040 | + highest_active_reg = NO_HIGHEST_ACTIVE_REG; |
| 13041 | + } |
| 13042 | + else |
| 13043 | + highest_active_reg = r; |
| 13044 | + } |
| 13045 | + |
| 13046 | + /* If just failed to match something this time around with a |
| 13047 | + group that's operated on by a repetition operator, try to |
| 13048 | + force exit from the ``loop'', and restore the register |
| 13049 | + information for this group that we had before trying this |
| 13050 | + last match. */ |
| 13051 | + if ((!MATCHED_SOMETHING (reg_info[*p]) |
| 13052 | + || just_past_start_mem == p - 1) |
| 13053 | + && (p + 2) < pend) |
| 13054 | + { |
| 13055 | + boolean is_a_jump_n = false; |
| 13056 | + |
| 13057 | + p1 = p + 2; |
| 13058 | + mcnt = 0; |
| 13059 | + switch ((re_opcode_t) *p1++) |
| 13060 | + { |
| 13061 | + case jump_n: |
| 13062 | + is_a_jump_n = true; |
| 13063 | + case pop_failure_jump: |
| 13064 | + case maybe_pop_jump: |
| 13065 | + case jump: |
| 13066 | + case dummy_failure_jump: |
| 13067 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 13068 | + if (is_a_jump_n) |
| 13069 | + p1 += OFFSET_ADDRESS_SIZE; |
| 13070 | + break; |
| 13071 | + |
| 13072 | + default: |
| 13073 | + /* do nothing */ ; |
| 13074 | + } |
| 13075 | + p1 += mcnt; |
| 13076 | + |
| 13077 | + /* If the next operation is a jump backwards in the pattern |
| 13078 | + to an on_failure_jump right before the start_memory |
| 13079 | + corresponding to this stop_memory, exit from the loop |
| 13080 | + by forcing a failure after pushing on the stack the |
| 13081 | + on_failure_jump's jump in the pattern, and d. */ |
| 13082 | + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump |
| 13083 | + && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory |
| 13084 | + && p1[2+OFFSET_ADDRESS_SIZE] == *p) |
| 13085 | + { |
| 13086 | + /* If this group ever matched anything, then restore |
| 13087 | + what its registers were before trying this last |
| 13088 | + failed match, e.g., with `(a*)*b' against `ab' for |
| 13089 | + regstart[1], and, e.g., with `((a*)*(b*)*)*' |
| 13090 | + against `aba' for regend[3]. |
| 13091 | + |
| 13092 | + Also restore the registers for inner groups for, |
| 13093 | + e.g., `((a*)(b*))*' against `aba' (register 3 would |
| 13094 | + otherwise get trashed). */ |
| 13095 | + |
| 13096 | + if (EVER_MATCHED_SOMETHING (reg_info[*p])) |
| 13097 | + { |
| 13098 | + unsigned r; |
| 13099 | + |
| 13100 | + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; |
| 13101 | + |
| 13102 | + /* Restore this and inner groups' (if any) registers. */ |
| 13103 | + for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); |
| 13104 | + r++) |
| 13105 | + { |
| 13106 | + regstart[r] = old_regstart[r]; |
| 13107 | + |
| 13108 | + /* xx why this test? */ |
| 13109 | + if (old_regend[r] >= regstart[r]) |
| 13110 | + regend[r] = old_regend[r]; |
| 13111 | + } |
| 13112 | + } |
| 13113 | + p1++; |
| 13114 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 13115 | + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); |
| 13116 | + |
| 13117 | + goto fail; |
| 13118 | + } |
| 13119 | + } |
| 13120 | + |
| 13121 | + /* Move past the register number and the inner group count. */ |
| 13122 | + p += 2; |
| 13123 | + break; |
| 13124 | + |
| 13125 | + |
| 13126 | + /* \<digit> has been turned into a `duplicate' command which is |
| 13127 | + followed by the numeric value of <digit> as the register number. */ |
| 13128 | + case duplicate: |
| 13129 | + { |
| 13130 | + register const CHAR_T *d2, *dend2; |
| 13131 | + int regno = *p++; /* Get which register to match against. */ |
| 13132 | + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); |
| 13133 | + |
| 13134 | + /* Can't back reference a group which we've never matched. */ |
| 13135 | + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) |
| 13136 | + goto fail; |
| 13137 | + |
| 13138 | + /* Where in input to try to start matching. */ |
| 13139 | + d2 = regstart[regno]; |
| 13140 | + |
| 13141 | + /* Where to stop matching; if both the place to start and |
| 13142 | + the place to stop matching are in the same string, then |
| 13143 | + set to the place to stop, otherwise, for now have to use |
| 13144 | + the end of the first string. */ |
| 13145 | + |
| 13146 | + dend2 = ((FIRST_STRING_P (regstart[regno]) |
| 13147 | + == FIRST_STRING_P (regend[regno])) |
| 13148 | + ? regend[regno] : end_match_1); |
| 13149 | + for (;;) |
| 13150 | + { |
| 13151 | + /* If necessary, advance to next segment in register |
| 13152 | + contents. */ |
| 13153 | + while (d2 == dend2) |
| 13154 | + { |
| 13155 | + if (dend2 == end_match_2) break; |
| 13156 | + if (dend2 == regend[regno]) break; |
| 13157 | + |
| 13158 | + /* End of string1 => advance to string2. */ |
| 13159 | + d2 = string2; |
| 13160 | + dend2 = regend[regno]; |
| 13161 | + } |
| 13162 | + /* At end of register contents => success */ |
| 13163 | + if (d2 == dend2) break; |
| 13164 | + |
| 13165 | + /* If necessary, advance to next segment in data. */ |
| 13166 | + PREFETCH (); |
| 13167 | + |
| 13168 | + /* How many characters left in this segment to match. */ |
| 13169 | + mcnt = dend - d; |
| 13170 | + |
| 13171 | + /* Want how many consecutive characters we can match in |
| 13172 | + one shot, so, if necessary, adjust the count. */ |
| 13173 | + if (mcnt > dend2 - d2) |
| 13174 | + mcnt = dend2 - d2; |
| 13175 | + |
| 13176 | + /* Compare that many; failure if mismatch, else move |
| 13177 | + past them. */ |
| 13178 | + if (translate |
| 13179 | + ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) |
| 13180 | + : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) |
| 13181 | + goto fail; |
| 13182 | + d += mcnt, d2 += mcnt; |
| 13183 | + |
| 13184 | + /* Do this because we've match some characters. */ |
| 13185 | + SET_REGS_MATCHED (); |
| 13186 | + } |
| 13187 | + } |
| 13188 | + break; |
| 13189 | + |
| 13190 | + |
| 13191 | + /* begline matches the empty string at the beginning of the string |
| 13192 | + (unless `not_bol' is set in `bufp'), and, if |
| 13193 | + `newline_anchor' is set, after newlines. */ |
| 13194 | + case begline: |
| 13195 | + DEBUG_PRINT1 ("EXECUTING begline.\n"); |
| 13196 | + |
| 13197 | + if (AT_STRINGS_BEG (d)) |
| 13198 | + { |
| 13199 | + if (!bufp->not_bol) break; |
| 13200 | + } |
| 13201 | + else if (d[-1] == '\n' && bufp->newline_anchor) |
| 13202 | + { |
| 13203 | + break; |
| 13204 | + } |
| 13205 | + /* In all other cases, we fail. */ |
| 13206 | + goto fail; |
| 13207 | + |
| 13208 | + |
| 13209 | + /* endline is the dual of begline. */ |
| 13210 | + case endline: |
| 13211 | + DEBUG_PRINT1 ("EXECUTING endline.\n"); |
| 13212 | + |
| 13213 | + if (AT_STRINGS_END (d)) |
| 13214 | + { |
| 13215 | + if (!bufp->not_eol) break; |
| 13216 | + } |
| 13217 | + |
| 13218 | + /* We have to ``prefetch'' the next character. */ |
| 13219 | + else if ((d == end1 ? *string2 : *d) == '\n' |
| 13220 | + && bufp->newline_anchor) |
| 13221 | + { |
| 13222 | + break; |
| 13223 | + } |
| 13224 | + goto fail; |
| 13225 | + |
| 13226 | + |
| 13227 | + /* Match at the very beginning of the data. */ |
| 13228 | + case begbuf: |
| 13229 | + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); |
| 13230 | + if (AT_STRINGS_BEG (d)) |
| 13231 | + break; |
| 13232 | + goto fail; |
| 13233 | + |
| 13234 | + |
| 13235 | + /* Match at the very end of the data. */ |
| 13236 | + case endbuf: |
| 13237 | + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); |
| 13238 | + if (AT_STRINGS_END (d)) |
| 13239 | + break; |
| 13240 | + goto fail; |
| 13241 | + |
| 13242 | + |
| 13243 | + /* on_failure_keep_string_jump is used to optimize `.*\n'. It |
| 13244 | + pushes NULL as the value for the string on the stack. Then |
| 13245 | + `pop_failure_point' will keep the current value for the |
| 13246 | + string, instead of restoring it. To see why, consider |
| 13247 | + matching `foo\nbar' against `.*\n'. The .* matches the foo; |
| 13248 | + then the . fails against the \n. But the next thing we want |
| 13249 | + to do is match the \n against the \n; if we restored the |
| 13250 | + string value, we would be back at the foo. |
| 13251 | + |
| 13252 | + Because this is used only in specific cases, we don't need to |
| 13253 | + check all the things that `on_failure_jump' does, to make |
| 13254 | + sure the right things get saved on the stack. Hence we don't |
| 13255 | + share its code. The only reason to push anything on the |
| 13256 | + stack at all is that otherwise we would have to change |
| 13257 | + `anychar's code to do something besides goto fail in this |
| 13258 | + case; that seems worse than this. */ |
| 13259 | + case on_failure_keep_string_jump: |
| 13260 | + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); |
| 13261 | + |
| 13262 | + EXTRACT_NUMBER_AND_INCR (mcnt, p); |
| 13263 | +#ifdef _LIBC |
| 13264 | + DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); |
| 13265 | +#else |
| 13266 | + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); |
| 13267 | +#endif |
| 13268 | + |
| 13269 | + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); |
| 13270 | + break; |
| 13271 | + |
| 13272 | + |
| 13273 | + /* Uses of on_failure_jump: |
| 13274 | + |
| 13275 | + Each alternative starts with an on_failure_jump that points |
| 13276 | + to the beginning of the next alternative. Each alternative |
| 13277 | + except the last ends with a jump that in effect jumps past |
| 13278 | + the rest of the alternatives. (They really jump to the |
| 13279 | + ending jump of the following alternative, because tensioning |
| 13280 | + these jumps is a hassle.) |
| 13281 | + |
| 13282 | + Repeats start with an on_failure_jump that points past both |
| 13283 | + the repetition text and either the following jump or |
| 13284 | + pop_failure_jump back to this on_failure_jump. */ |
| 13285 | + case on_failure_jump: |
| 13286 | + on_failure: |
| 13287 | + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); |
| 13288 | + |
| 13289 | + EXTRACT_NUMBER_AND_INCR (mcnt, p); |
| 13290 | +#ifdef _LIBC |
| 13291 | + DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); |
| 13292 | +#else |
| 13293 | + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); |
| 13294 | +#endif |
| 13295 | + |
| 13296 | + /* If this on_failure_jump comes right before a group (i.e., |
| 13297 | + the original * applied to a group), save the information |
| 13298 | + for that group and all inner ones, so that if we fail back |
| 13299 | + to this point, the group's information will be correct. |
| 13300 | + For example, in \(a*\)*\1, we need the preceding group, |
| 13301 | + and in \(zz\(a*\)b*\)\2, we need the inner group. */ |
| 13302 | + |
| 13303 | + /* We can't use `p' to check ahead because we push |
| 13304 | + a failure point to `p + mcnt' after we do this. */ |
| 13305 | + p1 = p; |
| 13306 | + |
| 13307 | + /* We need to skip no_op's before we look for the |
| 13308 | + start_memory in case this on_failure_jump is happening as |
| 13309 | + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 |
| 13310 | + against aba. */ |
| 13311 | + while (p1 < pend && (re_opcode_t) *p1 == no_op) |
| 13312 | + p1++; |
| 13313 | + |
| 13314 | + if (p1 < pend && (re_opcode_t) *p1 == start_memory) |
| 13315 | + { |
| 13316 | + /* We have a new highest active register now. This will |
| 13317 | + get reset at the start_memory we are about to get to, |
| 13318 | + but we will have saved all the registers relevant to |
| 13319 | + this repetition op, as described above. */ |
| 13320 | + highest_active_reg = *(p1 + 1) + *(p1 + 2); |
| 13321 | + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) |
| 13322 | + lowest_active_reg = *(p1 + 1); |
| 13323 | + } |
| 13324 | + |
| 13325 | + DEBUG_PRINT1 (":\n"); |
| 13326 | + PUSH_FAILURE_POINT (p + mcnt, d, -2); |
| 13327 | + break; |
| 13328 | + |
| 13329 | + |
| 13330 | + /* A smart repeat ends with `maybe_pop_jump'. |
| 13331 | + We change it to either `pop_failure_jump' or `jump'. */ |
| 13332 | + case maybe_pop_jump: |
| 13333 | + EXTRACT_NUMBER_AND_INCR (mcnt, p); |
| 13334 | + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); |
| 13335 | + { |
| 13336 | + register UCHAR_T *p2 = p; |
| 13337 | + |
| 13338 | + /* Compare the beginning of the repeat with what in the |
| 13339 | + pattern follows its end. If we can establish that there |
| 13340 | + is nothing that they would both match, i.e., that we |
| 13341 | + would have to backtrack because of (as in, e.g., `a*a') |
| 13342 | + then we can change to pop_failure_jump, because we'll |
| 13343 | + never have to backtrack. |
| 13344 | + |
| 13345 | + This is not true in the case of alternatives: in |
| 13346 | + `(a|ab)*' we do need to backtrack to the `ab' alternative |
| 13347 | + (e.g., if the string was `ab'). But instead of trying to |
| 13348 | + detect that here, the alternative has put on a dummy |
| 13349 | + failure point which is what we will end up popping. */ |
| 13350 | + |
| 13351 | + /* Skip over open/close-group commands. |
| 13352 | + If what follows this loop is a ...+ construct, |
| 13353 | + look at what begins its body, since we will have to |
| 13354 | + match at least one of that. */ |
| 13355 | + while (1) |
| 13356 | + { |
| 13357 | + if (p2 + 2 < pend |
| 13358 | + && ((re_opcode_t) *p2 == stop_memory |
| 13359 | + || (re_opcode_t) *p2 == start_memory)) |
| 13360 | + p2 += 3; |
| 13361 | + else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend |
| 13362 | + && (re_opcode_t) *p2 == dummy_failure_jump) |
| 13363 | + p2 += 2 + 2 * OFFSET_ADDRESS_SIZE; |
| 13364 | + else |
| 13365 | + break; |
| 13366 | + } |
| 13367 | + |
| 13368 | + p1 = p + mcnt; |
| 13369 | + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding |
| 13370 | + to the `maybe_finalize_jump' of this case. Examine what |
| 13371 | + follows. */ |
| 13372 | + |
| 13373 | + /* If we're at the end of the pattern, we can change. */ |
| 13374 | + if (p2 == pend) |
| 13375 | + { |
| 13376 | + /* Consider what happens when matching ":\(.*\)" |
| 13377 | + against ":/". I don't really understand this code |
| 13378 | + yet. */ |
| 13379 | + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) |
| 13380 | + pop_failure_jump; |
| 13381 | + DEBUG_PRINT1 |
| 13382 | + (" End of pattern: change to `pop_failure_jump'.\n"); |
| 13383 | + } |
| 13384 | + |
| 13385 | + else if ((re_opcode_t) *p2 == exactn |
| 13386 | +#ifdef MBS_SUPPORT |
| 13387 | + || (re_opcode_t) *p2 == exactn_bin |
| 13388 | +#endif |
| 13389 | + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) |
| 13390 | + { |
| 13391 | + register UCHAR_T c |
| 13392 | + = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; |
| 13393 | + |
| 13394 | + if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn |
| 13395 | +#ifdef MBS_SUPPORT |
| 13396 | + || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin |
| 13397 | +#endif |
| 13398 | + ) && p1[3+OFFSET_ADDRESS_SIZE] != c) |
| 13399 | + { |
| 13400 | + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) |
| 13401 | + pop_failure_jump; |
| 13402 | +#ifdef WCHAR |
| 13403 | + DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", |
| 13404 | + (wint_t) c, |
| 13405 | + (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); |
| 13406 | +#else |
| 13407 | + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", |
| 13408 | + (char) c, |
| 13409 | + (char) p1[3+OFFSET_ADDRESS_SIZE]); |
| 13410 | +#endif |
| 13411 | + } |
| 13412 | + |
| 13413 | +#ifndef WCHAR |
| 13414 | + else if ((re_opcode_t) p1[3] == charset |
| 13415 | + || (re_opcode_t) p1[3] == charset_not) |
| 13416 | + { |
| 13417 | + int negate = (re_opcode_t) p1[3] == charset_not; |
| 13418 | + |
| 13419 | + if (c < (unsigned) (p1[4] * BYTEWIDTH) |
| 13420 | + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) |
| 13421 | + negate = !negate; |
| 13422 | + |
| 13423 | + /* `negate' is equal to 1 if c would match, which means |
| 13424 | + that we can't change to pop_failure_jump. */ |
| 13425 | + if (!negate) |
| 13426 | + { |
| 13427 | + p[-3] = (unsigned char) pop_failure_jump; |
| 13428 | + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); |
| 13429 | + } |
| 13430 | + } |
| 13431 | +#endif /* not WCHAR */ |
| 13432 | + } |
| 13433 | +#ifndef WCHAR |
| 13434 | + else if ((re_opcode_t) *p2 == charset) |
| 13435 | + { |
| 13436 | + /* We win if the first character of the loop is not part |
| 13437 | + of the charset. */ |
| 13438 | + if ((re_opcode_t) p1[3] == exactn |
| 13439 | + && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] |
| 13440 | + && (p2[2 + p1[5] / BYTEWIDTH] |
| 13441 | + & (1 << (p1[5] % BYTEWIDTH))))) |
| 13442 | + { |
| 13443 | + p[-3] = (unsigned char) pop_failure_jump; |
| 13444 | + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); |
| 13445 | + } |
| 13446 | + |
| 13447 | + else if ((re_opcode_t) p1[3] == charset_not) |
| 13448 | + { |
| 13449 | + int idx; |
| 13450 | + /* We win if the charset_not inside the loop |
| 13451 | + lists every character listed in the charset after. */ |
| 13452 | + for (idx = 0; idx < (int) p2[1]; idx++) |
| 13453 | + if (! (p2[2 + idx] == 0 |
| 13454 | + || (idx < (int) p1[4] |
| 13455 | + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) |
| 13456 | + break; |
| 13457 | + |
| 13458 | + if (idx == p2[1]) |
| 13459 | + { |
| 13460 | + p[-3] = (unsigned char) pop_failure_jump; |
| 13461 | + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); |
| 13462 | + } |
| 13463 | + } |
| 13464 | + else if ((re_opcode_t) p1[3] == charset) |
| 13465 | + { |
| 13466 | + int idx; |
| 13467 | + /* We win if the charset inside the loop |
| 13468 | + has no overlap with the one after the loop. */ |
| 13469 | + for (idx = 0; |
| 13470 | + idx < (int) p2[1] && idx < (int) p1[4]; |
| 13471 | + idx++) |
| 13472 | + if ((p2[2 + idx] & p1[5 + idx]) != 0) |
| 13473 | + break; |
| 13474 | + |
| 13475 | + if (idx == p2[1] || idx == p1[4]) |
| 13476 | + { |
| 13477 | + p[-3] = (unsigned char) pop_failure_jump; |
| 13478 | + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); |
| 13479 | + } |
| 13480 | + } |
| 13481 | + } |
| 13482 | +#endif /* not WCHAR */ |
| 13483 | + } |
| 13484 | + p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ |
| 13485 | + if ((re_opcode_t) p[-1] != pop_failure_jump) |
| 13486 | + { |
| 13487 | + p[-1] = (UCHAR_T) jump; |
| 13488 | + DEBUG_PRINT1 (" Match => jump.\n"); |
| 13489 | + goto unconditional_jump; |
| 13490 | + } |
| 13491 | + /* Note fall through. */ |
| 13492 | + |
| 13493 | + |
| 13494 | + /* The end of a simple repeat has a pop_failure_jump back to |
| 13495 | + its matching on_failure_jump, where the latter will push a |
| 13496 | + failure point. The pop_failure_jump takes off failure |
| 13497 | + points put on by this pop_failure_jump's matching |
| 13498 | + on_failure_jump; we got through the pattern to here from the |
| 13499 | + matching on_failure_jump, so didn't fail. */ |
| 13500 | + case pop_failure_jump: |
| 13501 | + { |
| 13502 | + /* We need to pass separate storage for the lowest and |
| 13503 | + highest registers, even though we don't care about the |
| 13504 | + actual values. Otherwise, we will restore only one |
| 13505 | + register from the stack, since lowest will == highest in |
| 13506 | + `pop_failure_point'. */ |
| 13507 | + active_reg_t dummy_low_reg, dummy_high_reg; |
| 13508 | + UCHAR_T *pdummy __attribute__ ((unused)) = NULL; |
| 13509 | + const CHAR_T *sdummy __attribute__ ((unused)) = NULL; |
| 13510 | + |
| 13511 | + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); |
| 13512 | + POP_FAILURE_POINT (sdummy, pdummy, |
| 13513 | + dummy_low_reg, dummy_high_reg, |
| 13514 | + reg_dummy, reg_dummy, reg_info_dummy); |
| 13515 | + } |
| 13516 | + /* Note fall through. */ |
| 13517 | + |
| 13518 | + unconditional_jump: |
| 13519 | +#ifdef _LIBC |
| 13520 | + DEBUG_PRINT2 ("\n%p: ", p); |
| 13521 | +#else |
| 13522 | + DEBUG_PRINT2 ("\n0x%x: ", p); |
| 13523 | +#endif |
| 13524 | + /* Note fall through. */ |
| 13525 | + |
| 13526 | + /* Unconditionally jump (without popping any failure points). */ |
| 13527 | + case jump: |
| 13528 | + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ |
| 13529 | + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); |
| 13530 | + p += mcnt; /* Do the jump. */ |
| 13531 | +#ifdef _LIBC |
| 13532 | + DEBUG_PRINT2 ("(to %p).\n", p); |
| 13533 | +#else |
| 13534 | + DEBUG_PRINT2 ("(to 0x%x).\n", p); |
| 13535 | +#endif |
| 13536 | + break; |
| 13537 | + |
| 13538 | + |
| 13539 | + /* We need this opcode so we can detect where alternatives end |
| 13540 | + in `group_match_null_string_p' et al. */ |
| 13541 | + case jump_past_alt: |
| 13542 | + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); |
| 13543 | + goto unconditional_jump; |
| 13544 | + |
| 13545 | + |
| 13546 | + /* Normally, the on_failure_jump pushes a failure point, which |
| 13547 | + then gets popped at pop_failure_jump. We will end up at |
| 13548 | + pop_failure_jump, also, and with a pattern of, say, `a+', we |
| 13549 | + are skipping over the on_failure_jump, so we have to push |
| 13550 | + something meaningless for pop_failure_jump to pop. */ |
| 13551 | + case dummy_failure_jump: |
| 13552 | + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); |
| 13553 | + /* It doesn't matter what we push for the string here. What |
| 13554 | + the code at `fail' tests is the value for the pattern. */ |
| 13555 | + PUSH_FAILURE_POINT (NULL, NULL, -2); |
| 13556 | + goto unconditional_jump; |
| 13557 | + |
| 13558 | + |
| 13559 | + /* At the end of an alternative, we need to push a dummy failure |
| 13560 | + point in case we are followed by a `pop_failure_jump', because |
| 13561 | + we don't want the failure point for the alternative to be |
| 13562 | + popped. For example, matching `(a|ab)*' against `aab' |
| 13563 | + requires that we match the `ab' alternative. */ |
| 13564 | + case push_dummy_failure: |
| 13565 | + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); |
| 13566 | + /* See comments just above at `dummy_failure_jump' about the |
| 13567 | + two zeroes. */ |
| 13568 | + PUSH_FAILURE_POINT (NULL, NULL, -2); |
| 13569 | + break; |
| 13570 | + |
| 13571 | + /* Have to succeed matching what follows at least n times. |
| 13572 | + After that, handle like `on_failure_jump'. */ |
| 13573 | + case succeed_n: |
| 13574 | + EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); |
| 13575 | + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); |
| 13576 | + |
| 13577 | + assert (mcnt >= 0); |
| 13578 | + /* Originally, this is how many times we HAVE to succeed. */ |
| 13579 | + if (mcnt > 0) |
| 13580 | + { |
| 13581 | + mcnt--; |
| 13582 | + p += OFFSET_ADDRESS_SIZE; |
| 13583 | + STORE_NUMBER_AND_INCR (p, mcnt); |
| 13584 | +#ifdef _LIBC |
| 13585 | + DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE |
| 13586 | + , mcnt); |
| 13587 | +#else |
| 13588 | + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE |
| 13589 | + , mcnt); |
| 13590 | +#endif |
| 13591 | + } |
| 13592 | + else if (mcnt == 0) |
| 13593 | + { |
| 13594 | +#ifdef _LIBC |
| 13595 | + DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", |
| 13596 | + p + OFFSET_ADDRESS_SIZE); |
| 13597 | +#else |
| 13598 | + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", |
| 13599 | + p + OFFSET_ADDRESS_SIZE); |
| 13600 | +#endif /* _LIBC */ |
| 13601 | + |
| 13602 | +#ifdef WCHAR |
| 13603 | + p[1] = (UCHAR_T) no_op; |
| 13604 | +#else |
| 13605 | + p[2] = (UCHAR_T) no_op; |
| 13606 | + p[3] = (UCHAR_T) no_op; |
| 13607 | +#endif /* WCHAR */ |
| 13608 | + goto on_failure; |
| 13609 | + } |
| 13610 | + break; |
| 13611 | + |
| 13612 | + case jump_n: |
| 13613 | + EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); |
| 13614 | + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); |
| 13615 | + |
| 13616 | + /* Originally, this is how many times we CAN jump. */ |
| 13617 | + if (mcnt) |
| 13618 | + { |
| 13619 | + mcnt--; |
| 13620 | + STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt); |
| 13621 | + |
| 13622 | +#ifdef _LIBC |
| 13623 | + DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE, |
| 13624 | + mcnt); |
| 13625 | +#else |
| 13626 | + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE, |
| 13627 | + mcnt); |
| 13628 | +#endif /* _LIBC */ |
| 13629 | + goto unconditional_jump; |
| 13630 | + } |
| 13631 | + /* If don't have to jump any more, skip over the rest of command. */ |
| 13632 | + else |
| 13633 | + p += 2 * OFFSET_ADDRESS_SIZE; |
| 13634 | + break; |
| 13635 | + |
| 13636 | + case set_number_at: |
| 13637 | + { |
| 13638 | + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); |
| 13639 | + |
| 13640 | + EXTRACT_NUMBER_AND_INCR (mcnt, p); |
| 13641 | + p1 = p + mcnt; |
| 13642 | + EXTRACT_NUMBER_AND_INCR (mcnt, p); |
| 13643 | +#ifdef _LIBC |
| 13644 | + DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); |
| 13645 | +#else |
| 13646 | + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); |
| 13647 | +#endif |
| 13648 | + STORE_NUMBER (p1, mcnt); |
| 13649 | + break; |
| 13650 | + } |
| 13651 | + |
| 13652 | +#if 0 |
| 13653 | + /* The DEC Alpha C compiler 3.x generates incorrect code for the |
| 13654 | + test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of |
| 13655 | + AT_WORD_BOUNDARY, so this code is disabled. Expanding the |
| 13656 | + macro and introducing temporary variables works around the bug. */ |
| 13657 | + |
| 13658 | + case wordbound: |
| 13659 | + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); |
| 13660 | + if (AT_WORD_BOUNDARY (d)) |
| 13661 | + break; |
| 13662 | + goto fail; |
| 13663 | + |
| 13664 | + case notwordbound: |
| 13665 | + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); |
| 13666 | + if (AT_WORD_BOUNDARY (d)) |
| 13667 | + goto fail; |
| 13668 | + break; |
| 13669 | +#else |
| 13670 | + case wordbound: |
| 13671 | + { |
| 13672 | + boolean prevchar, thischar; |
| 13673 | + |
| 13674 | + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); |
| 13675 | + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) |
| 13676 | + break; |
| 13677 | + |
| 13678 | + prevchar = WORDCHAR_P (d - 1); |
| 13679 | + thischar = WORDCHAR_P (d); |
| 13680 | + if (prevchar != thischar) |
| 13681 | + break; |
| 13682 | + goto fail; |
| 13683 | + } |
| 13684 | + |
| 13685 | + case notwordbound: |
| 13686 | + { |
| 13687 | + boolean prevchar, thischar; |
| 13688 | + |
| 13689 | + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); |
| 13690 | + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) |
| 13691 | + goto fail; |
| 13692 | + |
| 13693 | + prevchar = WORDCHAR_P (d - 1); |
| 13694 | + thischar = WORDCHAR_P (d); |
| 13695 | + if (prevchar != thischar) |
| 13696 | + goto fail; |
| 13697 | + break; |
| 13698 | + } |
| 13699 | +#endif |
| 13700 | + |
| 13701 | + case wordbeg: |
| 13702 | + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); |
| 13703 | + if (!AT_STRINGS_END (d) && WORDCHAR_P (d) |
| 13704 | + && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) |
| 13705 | + break; |
| 13706 | + goto fail; |
| 13707 | + |
| 13708 | + case wordend: |
| 13709 | + DEBUG_PRINT1 ("EXECUTING wordend.\n"); |
| 13710 | + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) |
| 13711 | + && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) |
| 13712 | + break; |
| 13713 | + goto fail; |
| 13714 | + |
| 13715 | +#ifdef emacs |
| 13716 | + case before_dot: |
| 13717 | + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); |
| 13718 | + if (PTR_CHAR_POS ((unsigned char *) d) >= point) |
| 13719 | + goto fail; |
| 13720 | + break; |
| 13721 | + |
| 13722 | + case at_dot: |
| 13723 | + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); |
| 13724 | + if (PTR_CHAR_POS ((unsigned char *) d) != point) |
| 13725 | + goto fail; |
| 13726 | + break; |
| 13727 | + |
| 13728 | + case after_dot: |
| 13729 | + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); |
| 13730 | + if (PTR_CHAR_POS ((unsigned char *) d) <= point) |
| 13731 | + goto fail; |
| 13732 | + break; |
| 13733 | + |
| 13734 | + case syntaxspec: |
| 13735 | + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); |
| 13736 | + mcnt = *p++; |
| 13737 | + goto matchsyntax; |
| 13738 | + |
| 13739 | + case wordchar: |
| 13740 | + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); |
| 13741 | + mcnt = (int) Sword; |
| 13742 | + matchsyntax: |
| 13743 | + PREFETCH (); |
| 13744 | + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ |
| 13745 | + d++; |
| 13746 | + if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) |
| 13747 | + goto fail; |
| 13748 | + SET_REGS_MATCHED (); |
| 13749 | + break; |
| 13750 | + |
| 13751 | + case notsyntaxspec: |
| 13752 | + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); |
| 13753 | + mcnt = *p++; |
| 13754 | + goto matchnotsyntax; |
| 13755 | + |
| 13756 | + case notwordchar: |
| 13757 | + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); |
| 13758 | + mcnt = (int) Sword; |
| 13759 | + matchnotsyntax: |
| 13760 | + PREFETCH (); |
| 13761 | + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ |
| 13762 | + d++; |
| 13763 | + if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) |
| 13764 | + goto fail; |
| 13765 | + SET_REGS_MATCHED (); |
| 13766 | + break; |
| 13767 | + |
| 13768 | +#else /* not emacs */ |
| 13769 | + case wordchar: |
| 13770 | + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); |
| 13771 | + PREFETCH (); |
| 13772 | + if (!WORDCHAR_P (d)) |
| 13773 | + goto fail; |
| 13774 | + SET_REGS_MATCHED (); |
| 13775 | + d++; |
| 13776 | + break; |
| 13777 | + |
| 13778 | + case notwordchar: |
| 13779 | + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); |
| 13780 | + PREFETCH (); |
| 13781 | + if (WORDCHAR_P (d)) |
| 13782 | + goto fail; |
| 13783 | + SET_REGS_MATCHED (); |
| 13784 | + d++; |
| 13785 | + break; |
| 13786 | +#endif /* not emacs */ |
| 13787 | + |
| 13788 | + default: |
| 13789 | + abort (); |
| 13790 | + } |
| 13791 | + continue; /* Successfully executed one pattern command; keep going. */ |
| 13792 | + |
| 13793 | + |
| 13794 | + /* We goto here if a matching operation fails. */ |
| 13795 | + fail: |
| 13796 | + if (!FAIL_STACK_EMPTY ()) |
| 13797 | + { /* A restart point is known. Restore to that state. */ |
| 13798 | + DEBUG_PRINT1 ("\nFAIL:\n"); |
| 13799 | + POP_FAILURE_POINT (d, p, |
| 13800 | + lowest_active_reg, highest_active_reg, |
| 13801 | + regstart, regend, reg_info); |
| 13802 | + |
| 13803 | + /* If this failure point is a dummy, try the next one. */ |
| 13804 | + if (!p) |
| 13805 | + goto fail; |
| 13806 | + |
| 13807 | + /* If we failed to the end of the pattern, don't examine *p. */ |
| 13808 | + assert (p <= pend); |
| 13809 | + if (p < pend) |
| 13810 | + { |
| 13811 | + boolean is_a_jump_n = false; |
| 13812 | + |
| 13813 | + /* If failed to a backwards jump that's part of a repetition |
| 13814 | + loop, need to pop this failure point and use the next one. */ |
| 13815 | + switch ((re_opcode_t) *p) |
| 13816 | + { |
| 13817 | + case jump_n: |
| 13818 | + is_a_jump_n = true; |
| 13819 | + case maybe_pop_jump: |
| 13820 | + case pop_failure_jump: |
| 13821 | + case jump: |
| 13822 | + p1 = p + 1; |
| 13823 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 13824 | + p1 += mcnt; |
| 13825 | + |
| 13826 | + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) |
| 13827 | + || (!is_a_jump_n |
| 13828 | + && (re_opcode_t) *p1 == on_failure_jump)) |
| 13829 | + goto fail; |
| 13830 | + break; |
| 13831 | + default: |
| 13832 | + /* do nothing */ ; |
| 13833 | + } |
| 13834 | + } |
| 13835 | + |
| 13836 | + if (d >= string1 && d <= end1) |
| 13837 | + dend = end_match_1; |
| 13838 | + } |
| 13839 | + else |
| 13840 | + break; /* Matching at this starting point really fails. */ |
| 13841 | + } /* for (;;) */ |
| 13842 | + |
| 13843 | + if (best_regs_set) |
| 13844 | + goto restore_best_regs; |
| 13845 | + |
| 13846 | + FREE_VARIABLES (); |
| 13847 | + |
| 13848 | + return -1; /* Failure to match. */ |
| 13849 | +} /* re_match_2 */ |
| 13850 | + |
| 13851 | +/* Subroutine definitions for re_match_2. */ |
| 13852 | + |
| 13853 | + |
| 13854 | +/* We are passed P pointing to a register number after a start_memory. |
| 13855 | + |
| 13856 | + Return true if the pattern up to the corresponding stop_memory can |
| 13857 | + match the empty string, and false otherwise. |
| 13858 | + |
| 13859 | + If we find the matching stop_memory, sets P to point to one past its number. |
| 13860 | + Otherwise, sets P to an undefined byte less than or equal to END. |
| 13861 | + |
| 13862 | + We don't handle duplicates properly (yet). */ |
| 13863 | + |
| 13864 | +static boolean |
| 13865 | +PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, |
| 13866 | + PREFIX(register_info_type) *reg_info) |
| 13867 | +{ |
| 13868 | + int mcnt; |
| 13869 | + /* Point to after the args to the start_memory. */ |
| 13870 | + UCHAR_T *p1 = *p + 2; |
| 13871 | + |
| 13872 | + while (p1 < end) |
| 13873 | + { |
| 13874 | + /* Skip over opcodes that can match nothing, and return true or |
| 13875 | + false, as appropriate, when we get to one that can't, or to the |
| 13876 | + matching stop_memory. */ |
| 13877 | + |
| 13878 | + switch ((re_opcode_t) *p1) |
| 13879 | + { |
| 13880 | + /* Could be either a loop or a series of alternatives. */ |
| 13881 | + case on_failure_jump: |
| 13882 | + p1++; |
| 13883 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 13884 | + |
| 13885 | + /* If the next operation is not a jump backwards in the |
| 13886 | + pattern. */ |
| 13887 | + |
| 13888 | + if (mcnt >= 0) |
| 13889 | + { |
| 13890 | + /* Go through the on_failure_jumps of the alternatives, |
| 13891 | + seeing if any of the alternatives cannot match nothing. |
| 13892 | + The last alternative starts with only a jump, |
| 13893 | + whereas the rest start with on_failure_jump and end |
| 13894 | + with a jump, e.g., here is the pattern for `a|b|c': |
| 13895 | + |
| 13896 | + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 |
| 13897 | + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 |
| 13898 | + /exactn/1/c |
| 13899 | + |
| 13900 | + So, we have to first go through the first (n-1) |
| 13901 | + alternatives and then deal with the last one separately. */ |
| 13902 | + |
| 13903 | + |
| 13904 | + /* Deal with the first (n-1) alternatives, which start |
| 13905 | + with an on_failure_jump (see above) that jumps to right |
| 13906 | + past a jump_past_alt. */ |
| 13907 | + |
| 13908 | + while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] == |
| 13909 | + jump_past_alt) |
| 13910 | + { |
| 13911 | + /* `mcnt' holds how many bytes long the alternative |
| 13912 | + is, including the ending `jump_past_alt' and |
| 13913 | + its number. */ |
| 13914 | + |
| 13915 | + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - |
| 13916 | + (1 + OFFSET_ADDRESS_SIZE), |
| 13917 | + reg_info)) |
| 13918 | + return false; |
| 13919 | + |
| 13920 | + /* Move to right after this alternative, including the |
| 13921 | + jump_past_alt. */ |
| 13922 | + p1 += mcnt; |
| 13923 | + |
| 13924 | + /* Break if it's the beginning of an n-th alternative |
| 13925 | + that doesn't begin with an on_failure_jump. */ |
| 13926 | + if ((re_opcode_t) *p1 != on_failure_jump) |
| 13927 | + break; |
| 13928 | + |
| 13929 | + /* Still have to check that it's not an n-th |
| 13930 | + alternative that starts with an on_failure_jump. */ |
| 13931 | + p1++; |
| 13932 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 13933 | + if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] != |
| 13934 | + jump_past_alt) |
| 13935 | + { |
| 13936 | + /* Get to the beginning of the n-th alternative. */ |
| 13937 | + p1 -= 1 + OFFSET_ADDRESS_SIZE; |
| 13938 | + break; |
| 13939 | + } |
| 13940 | + } |
| 13941 | + |
| 13942 | + /* Deal with the last alternative: go back and get number |
| 13943 | + of the `jump_past_alt' just before it. `mcnt' contains |
| 13944 | + the length of the alternative. */ |
| 13945 | + EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); |
| 13946 | + |
| 13947 | + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) |
| 13948 | + return false; |
| 13949 | + |
| 13950 | + p1 += mcnt; /* Get past the n-th alternative. */ |
| 13951 | + } /* if mcnt > 0 */ |
| 13952 | + break; |
| 13953 | + |
| 13954 | + |
| 13955 | + case stop_memory: |
| 13956 | + assert (p1[1] == **p); |
| 13957 | + *p = p1 + 2; |
| 13958 | + return true; |
| 13959 | + |
| 13960 | + |
| 13961 | + default: |
| 13962 | + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) |
| 13963 | + return false; |
| 13964 | + } |
| 13965 | + } /* while p1 < end */ |
| 13966 | + |
| 13967 | + return false; |
| 13968 | +} /* group_match_null_string_p */ |
| 13969 | + |
| 13970 | + |
| 13971 | +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: |
| 13972 | + It expects P to be the first byte of a single alternative and END one |
| 13973 | + byte past the last. The alternative can contain groups. */ |
| 13974 | + |
| 13975 | +static boolean |
| 13976 | +PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end, |
| 13977 | + PREFIX(register_info_type) *reg_info) |
| 13978 | +{ |
| 13979 | + int mcnt; |
| 13980 | + UCHAR_T *p1 = p; |
| 13981 | + |
| 13982 | + while (p1 < end) |
| 13983 | + { |
| 13984 | + /* Skip over opcodes that can match nothing, and break when we get |
| 13985 | + to one that can't. */ |
| 13986 | + |
| 13987 | + switch ((re_opcode_t) *p1) |
| 13988 | + { |
| 13989 | + /* It's a loop. */ |
| 13990 | + case on_failure_jump: |
| 13991 | + p1++; |
| 13992 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 13993 | + p1 += mcnt; |
| 13994 | + break; |
| 13995 | + |
| 13996 | + default: |
| 13997 | + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) |
| 13998 | + return false; |
| 13999 | + } |
| 14000 | + } /* while p1 < end */ |
| 14001 | + |
| 14002 | + return true; |
| 14003 | +} /* alt_match_null_string_p */ |
| 14004 | + |
| 14005 | + |
| 14006 | +/* Deals with the ops common to group_match_null_string_p and |
| 14007 | + alt_match_null_string_p. |
| 14008 | + |
| 14009 | + Sets P to one after the op and its arguments, if any. */ |
| 14010 | + |
| 14011 | +static boolean |
| 14012 | +PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end, |
| 14013 | + PREFIX(register_info_type) *reg_info) |
| 14014 | +{ |
| 14015 | + int mcnt; |
| 14016 | + boolean ret; |
| 14017 | + int reg_no; |
| 14018 | + UCHAR_T *p1 = *p; |
| 14019 | + |
| 14020 | + switch ((re_opcode_t) *p1++) |
| 14021 | + { |
| 14022 | + case no_op: |
| 14023 | + case begline: |
| 14024 | + case endline: |
| 14025 | + case begbuf: |
| 14026 | + case endbuf: |
| 14027 | + case wordbeg: |
| 14028 | + case wordend: |
| 14029 | + case wordbound: |
| 14030 | + case notwordbound: |
| 14031 | +#ifdef emacs |
| 14032 | + case before_dot: |
| 14033 | + case at_dot: |
| 14034 | + case after_dot: |
| 14035 | +#endif |
| 14036 | + break; |
| 14037 | + |
| 14038 | + case start_memory: |
| 14039 | + reg_no = *p1; |
| 14040 | + assert (reg_no > 0 && reg_no <= MAX_REGNUM); |
| 14041 | + ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); |
| 14042 | + |
| 14043 | + /* Have to set this here in case we're checking a group which |
| 14044 | + contains a group and a back reference to it. */ |
| 14045 | + |
| 14046 | + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) |
| 14047 | + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; |
| 14048 | + |
| 14049 | + if (!ret) |
| 14050 | + return false; |
| 14051 | + break; |
| 14052 | + |
| 14053 | + /* If this is an optimized succeed_n for zero times, make the jump. */ |
| 14054 | + case jump: |
| 14055 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 14056 | + if (mcnt >= 0) |
| 14057 | + p1 += mcnt; |
| 14058 | + else |
| 14059 | + return false; |
| 14060 | + break; |
| 14061 | + |
| 14062 | + case succeed_n: |
| 14063 | + /* Get to the number of times to succeed. */ |
| 14064 | + p1 += OFFSET_ADDRESS_SIZE; |
| 14065 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 14066 | + |
| 14067 | + if (mcnt == 0) |
| 14068 | + { |
| 14069 | + p1 -= 2 * OFFSET_ADDRESS_SIZE; |
| 14070 | + EXTRACT_NUMBER_AND_INCR (mcnt, p1); |
| 14071 | + p1 += mcnt; |
| 14072 | + } |
| 14073 | + else |
| 14074 | + return false; |
| 14075 | + break; |
| 14076 | + |
| 14077 | + case duplicate: |
| 14078 | + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) |
| 14079 | + return false; |
| 14080 | + break; |
| 14081 | + |
| 14082 | + case set_number_at: |
| 14083 | + p1 += 2 * OFFSET_ADDRESS_SIZE; |
| 14084 | + |
| 14085 | + default: |
| 14086 | + /* All other opcodes mean we cannot match the empty string. */ |
| 14087 | + return false; |
| 14088 | + } |
| 14089 | + |
| 14090 | + *p = p1; |
| 14091 | + return true; |
| 14092 | +} /* common_op_match_null_string_p */ |
| 14093 | + |
| 14094 | + |
| 14095 | +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN |
| 14096 | + bytes; nonzero otherwise. */ |
| 14097 | + |
| 14098 | +static int |
| 14099 | +PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, register int len, |
| 14100 | + RE_TRANSLATE_TYPE translate) |
| 14101 | +{ |
| 14102 | + register const UCHAR_T *p1 = (const UCHAR_T *) s1; |
| 14103 | + register const UCHAR_T *p2 = (const UCHAR_T *) s2; |
| 14104 | + while (len) |
| 14105 | + { |
| 14106 | +#ifdef WCHAR |
| 14107 | + if (((*p1<=0xff)?translate[*p1++]:*p1++) |
| 14108 | + != ((*p2<=0xff)?translate[*p2++]:*p2++)) |
| 14109 | + return 1; |
| 14110 | +#else /* BYTE */ |
| 14111 | + if (translate[*p1++] != translate[*p2++]) return 1; |
| 14112 | +#endif /* WCHAR */ |
| 14113 | + len--; |
| 14114 | + } |
| 14115 | + return 0; |
| 14116 | +} |
| 14117 | + |
| 14118 | + |
| 14119 | +#else /* not INSIDE_RECURSION */ |
| 14120 | + |
| 14121 | +/* Entry points for GNU code. */ |
| 14122 | + |
| 14123 | +/* re_compile_pattern is the GNU regular expression compiler: it |
| 14124 | + compiles PATTERN (of length SIZE) and puts the result in BUFP. |
| 14125 | + Returns 0 if the pattern was valid, otherwise an error string. |
| 14126 | + |
| 14127 | + Assumes the `allocated' (and perhaps `buffer') and `translate' fields |
| 14128 | + are set in BUFP on entry. |
| 14129 | + |
| 14130 | + We call regex_compile to do the actual compilation. */ |
| 14131 | + |
| 14132 | +const char * |
| 14133 | +re_compile_pattern (const char *pattern, size_t length, |
| 14134 | + struct re_pattern_buffer *bufp) |
| 14135 | +{ |
| 14136 | + reg_errcode_t ret; |
| 14137 | + |
| 14138 | + /* GNU code is written to assume at least RE_NREGS registers will be set |
| 14139 | + (and at least one extra will be -1). */ |
| 14140 | + bufp->regs_allocated = REGS_UNALLOCATED; |
| 14141 | + |
| 14142 | + /* And GNU code determines whether or not to get register information |
| 14143 | + by passing null for the REGS argument to re_match, etc., not by |
| 14144 | + setting no_sub. */ |
| 14145 | + bufp->no_sub = 0; |
| 14146 | + |
| 14147 | + /* Match anchors at newline. */ |
| 14148 | + bufp->newline_anchor = 1; |
| 14149 | + |
| 14150 | +# ifdef MBS_SUPPORT |
| 14151 | + if (MB_CUR_MAX != 1) |
| 14152 | + ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); |
| 14153 | + else |
| 14154 | +# endif |
| 14155 | + ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); |
| 14156 | + |
| 14157 | + if (!ret) |
| 14158 | + return NULL; |
| 14159 | + return gettext (re_error_msgid[(int) ret]); |
| 14160 | +} |
| 14161 | +#ifdef _LIBC |
| 14162 | +weak_alias (__re_compile_pattern, re_compile_pattern) |
| 14163 | +#endif |
| 14164 | + |
| 14165 | +/* Entry points compatible with 4.2 BSD regex library. We don't define |
| 14166 | + them unless specifically requested. */ |
| 14167 | + |
| 14168 | +#if defined _REGEX_RE_COMP || defined _LIBC |
| 14169 | + |
| 14170 | +/* BSD has one and only one pattern buffer. */ |
| 14171 | +static struct re_pattern_buffer re_comp_buf; |
| 14172 | + |
| 14173 | +char * |
| 14174 | +#ifdef _LIBC |
| 14175 | +/* Make these definitions weak in libc, so POSIX programs can redefine |
| 14176 | + these names if they don't use our functions, and still use |
| 14177 | + regcomp/regexec below without link errors. */ |
| 14178 | +weak_function |
| 14179 | +#endif |
| 14180 | +re_comp (const char *s) |
| 14181 | +{ |
| 14182 | + reg_errcode_t ret; |
| 14183 | + |
| 14184 | + if (!s) |
| 14185 | + { |
| 14186 | + if (!re_comp_buf.buffer) |
| 14187 | + return (char *) gettext ("No previous regular expression"); |
| 14188 | + return 0; |
| 14189 | + } |
| 14190 | + |
| 14191 | + if (!re_comp_buf.buffer) |
| 14192 | + { |
| 14193 | + re_comp_buf.buffer = (unsigned char *) malloc (200); |
| 14194 | + if (re_comp_buf.buffer == NULL) |
| 14195 | + return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); |
| 14196 | + re_comp_buf.allocated = 200; |
| 14197 | + |
| 14198 | + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); |
| 14199 | + if (re_comp_buf.fastmap == NULL) |
| 14200 | + return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); |
| 14201 | + } |
| 14202 | + |
| 14203 | + /* Since `re_exec' always passes NULL for the `regs' argument, we |
| 14204 | + don't need to initialize the pattern buffer fields which affect it. */ |
| 14205 | + |
| 14206 | + /* Match anchors at newlines. */ |
| 14207 | + re_comp_buf.newline_anchor = 1; |
| 14208 | + |
| 14209 | +# ifdef MBS_SUPPORT |
| 14210 | + if (MB_CUR_MAX != 1) |
| 14211 | + ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); |
| 14212 | + else |
| 14213 | +# endif |
| 14214 | + ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); |
| 14215 | + |
| 14216 | + if (!ret) |
| 14217 | + return NULL; |
| 14218 | + |
| 14219 | + /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ |
| 14220 | + return (char *) gettext (re_error_msgid[(int) ret]); |
| 14221 | +} |
| 14222 | + |
| 14223 | + |
| 14224 | +int |
| 14225 | +#ifdef _LIBC |
| 14226 | +weak_function |
| 14227 | +#endif |
| 14228 | +re_exec (const char *s) |
| 14229 | +{ |
| 14230 | + const int len = strlen (s); |
| 14231 | + return |
| 14232 | + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); |
| 14233 | +} |
| 14234 | + |
| 14235 | +#endif /* _REGEX_RE_COMP */ |
| 14236 | + |
| 14237 | +/* POSIX.2 functions. Don't define these for Emacs. */ |
| 14238 | + |
| 14239 | +#ifndef emacs |
| 14240 | + |
| 14241 | +/* regcomp takes a regular expression as a string and compiles it. |
| 14242 | + |
| 14243 | + PREG is a regex_t *. We do not expect any fields to be initialized, |
| 14244 | + since POSIX says we shouldn't. Thus, we set |
| 14245 | + |
| 14246 | + `buffer' to the compiled pattern; |
| 14247 | + `used' to the length of the compiled pattern; |
| 14248 | + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the |
| 14249 | + REG_EXTENDED bit in CFLAGS is set; otherwise, to |
| 14250 | + RE_SYNTAX_POSIX_BASIC; |
| 14251 | + `newline_anchor' to REG_NEWLINE being set in CFLAGS; |
| 14252 | + `fastmap' to an allocated space for the fastmap; |
| 14253 | + `fastmap_accurate' to zero; |
| 14254 | + `re_nsub' to the number of subexpressions in PATTERN. |
| 14255 | + |
| 14256 | + PATTERN is the address of the pattern string. |
| 14257 | + |
| 14258 | + CFLAGS is a series of bits which affect compilation. |
| 14259 | + |
| 14260 | + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we |
| 14261 | + use POSIX basic syntax. |
| 14262 | + |
| 14263 | + If REG_NEWLINE is set, then . and [^...] don't match newline. |
| 14264 | + Also, regexec will try a match beginning after every newline. |
| 14265 | + |
| 14266 | + If REG_ICASE is set, then we considers upper- and lowercase |
| 14267 | + versions of letters to be equivalent when matching. |
| 14268 | + |
| 14269 | + If REG_NOSUB is set, then when PREG is passed to regexec, that |
| 14270 | + routine will report only success or failure, and nothing about the |
| 14271 | + registers. |
| 14272 | + |
| 14273 | + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for |
| 14274 | + the return codes and their meanings.) */ |
| 14275 | + |
| 14276 | +int |
| 14277 | +regcomp (regex_t *preg, const char *pattern, int cflags) |
| 14278 | +{ |
| 14279 | + reg_errcode_t ret; |
| 14280 | + reg_syntax_t syntax |
| 14281 | + = (cflags & REG_EXTENDED) ? |
| 14282 | + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; |
| 14283 | + |
| 14284 | + /* regex_compile will allocate the space for the compiled pattern. */ |
| 14285 | + preg->buffer = 0; |
| 14286 | + preg->allocated = 0; |
| 14287 | + preg->used = 0; |
| 14288 | + |
| 14289 | + /* Try to allocate space for the fastmap. */ |
| 14290 | + preg->fastmap = (char *) malloc (1 << BYTEWIDTH); |
| 14291 | + |
| 14292 | + if (cflags & REG_ICASE) |
| 14293 | + { |
| 14294 | + int i; |
| 14295 | + |
| 14296 | + preg->translate |
| 14297 | + = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE |
| 14298 | + * sizeof (*(RE_TRANSLATE_TYPE)0)); |
| 14299 | + if (preg->translate == NULL) |
| 14300 | + return (int) REG_ESPACE; |
| 14301 | + |
| 14302 | + /* Map uppercase characters to corresponding lowercase ones. */ |
| 14303 | + for (i = 0; i < CHAR_SET_SIZE; i++) |
| 14304 | + preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; |
| 14305 | + } |
| 14306 | + else |
| 14307 | + preg->translate = NULL; |
| 14308 | + |
| 14309 | + /* If REG_NEWLINE is set, newlines are treated differently. */ |
| 14310 | + if (cflags & REG_NEWLINE) |
| 14311 | + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ |
| 14312 | + syntax &= ~RE_DOT_NEWLINE; |
| 14313 | + syntax |= RE_HAT_LISTS_NOT_NEWLINE; |
| 14314 | + /* It also changes the matching behavior. */ |
| 14315 | + preg->newline_anchor = 1; |
| 14316 | + } |
| 14317 | + else |
| 14318 | + preg->newline_anchor = 0; |
| 14319 | + |
| 14320 | + preg->no_sub = !!(cflags & REG_NOSUB); |
| 14321 | + |
| 14322 | + /* POSIX says a null character in the pattern terminates it, so we |
| 14323 | + can use strlen here in compiling the pattern. */ |
| 14324 | +# ifdef MBS_SUPPORT |
| 14325 | + if (MB_CUR_MAX != 1) |
| 14326 | + ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); |
| 14327 | + else |
| 14328 | +# endif |
| 14329 | + ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); |
| 14330 | + |
| 14331 | + /* POSIX doesn't distinguish between an unmatched open-group and an |
| 14332 | + unmatched close-group: both are REG_EPAREN. */ |
| 14333 | + if (ret == REG_ERPAREN) ret = REG_EPAREN; |
| 14334 | + |
| 14335 | + if (ret == REG_NOERROR && preg->fastmap) |
| 14336 | + { |
| 14337 | + /* Compute the fastmap now, since regexec cannot modify the pattern |
| 14338 | + buffer. */ |
| 14339 | + if (re_compile_fastmap (preg) == -2) |
| 14340 | + { |
| 14341 | + /* Some error occurred while computing the fastmap, just forget |
| 14342 | + about it. */ |
| 14343 | + free (preg->fastmap); |
| 14344 | + preg->fastmap = NULL; |
| 14345 | + } |
| 14346 | + } |
| 14347 | + |
| 14348 | + return (int) ret; |
| 14349 | +} |
| 14350 | +#ifdef _LIBC |
| 14351 | +weak_alias (__regcomp, regcomp) |
| 14352 | +#endif |
| 14353 | + |
| 14354 | + |
| 14355 | +/* regexec searches for a given pattern, specified by PREG, in the |
| 14356 | + string STRING. |
| 14357 | + |
| 14358 | + If NMATCH is zero or REG_NOSUB was set in the cflags argument to |
| 14359 | + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at |
| 14360 | + least NMATCH elements, and we set them to the offsets of the |
| 14361 | + corresponding matched substrings. |
| 14362 | + |
| 14363 | + EFLAGS specifies `execution flags' which affect matching: if |
| 14364 | + REG_NOTBOL is set, then ^ does not match at the beginning of the |
| 14365 | + string; if REG_NOTEOL is set, then $ does not match at the end. |
| 14366 | + |
| 14367 | + We return 0 if we find a match and REG_NOMATCH if not. */ |
| 14368 | + |
| 14369 | +int |
| 14370 | +regexec (const regex_t *preg, const char *string, size_t nmatch, |
| 14371 | + regmatch_t pmatch[], int eflags) |
| 14372 | +{ |
| 14373 | + int ret; |
| 14374 | + struct re_registers regs; |
| 14375 | + regex_t private_preg; |
| 14376 | + int len = strlen (string); |
| 14377 | + boolean want_reg_info = !preg->no_sub && nmatch > 0; |
| 14378 | + |
| 14379 | + private_preg = *preg; |
| 14380 | + |
| 14381 | + private_preg.not_bol = !!(eflags & REG_NOTBOL); |
| 14382 | + private_preg.not_eol = !!(eflags & REG_NOTEOL); |
| 14383 | + |
| 14384 | + /* The user has told us exactly how many registers to return |
| 14385 | + information about, via `nmatch'. We have to pass that on to the |
| 14386 | + matching routines. */ |
| 14387 | + private_preg.regs_allocated = REGS_FIXED; |
| 14388 | + |
| 14389 | + if (want_reg_info) |
| 14390 | + { |
| 14391 | + regs.num_regs = nmatch; |
| 14392 | + regs.start = TALLOC (nmatch * 2, regoff_t); |
| 14393 | + if (regs.start == NULL) |
| 14394 | + return (int) REG_NOMATCH; |
| 14395 | + regs.end = regs.start + nmatch; |
| 14396 | + } |
| 14397 | + |
| 14398 | + /* Perform the searching operation. */ |
| 14399 | + ret = re_search (&private_preg, string, len, |
| 14400 | + /* start: */ 0, /* range: */ len, |
| 14401 | + want_reg_info ? ®s : (struct re_registers *) 0); |
| 14402 | + |
| 14403 | + /* Copy the register information to the POSIX structure. */ |
| 14404 | + if (want_reg_info) |
| 14405 | + { |
| 14406 | + if (ret >= 0) |
| 14407 | + { |
| 14408 | + unsigned r; |
| 14409 | + |
| 14410 | + for (r = 0; r < nmatch; r++) |
| 14411 | + { |
| 14412 | + pmatch[r].rm_so = regs.start[r]; |
| 14413 | + pmatch[r].rm_eo = regs.end[r]; |
| 14414 | + } |
| 14415 | + } |
| 14416 | + |
| 14417 | + /* If we needed the temporary register info, free the space now. */ |
| 14418 | + free (regs.start); |
| 14419 | + } |
| 14420 | + |
| 14421 | + /* We want zero return to mean success, unlike `re_search'. */ |
| 14422 | + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; |
| 14423 | +} |
| 14424 | +#ifdef _LIBC |
| 14425 | +/* EGLIBC: This is handled in regexec-compat.c. */ |
| 14426 | +/*weak_alias (__regexec, regexec)*/ |
| 14427 | +#include "regexec-compat.c" |
| 14428 | +#endif |
| 14429 | + |
| 14430 | + |
| 14431 | +/* Returns a message corresponding to an error code, ERRCODE, returned |
| 14432 | + from either regcomp or regexec. We don't use PREG here. */ |
| 14433 | + |
| 14434 | +size_t |
| 14435 | +regerror (int errcode, const regex_t *preg __attribute__ ((unused)), |
| 14436 | + char *errbuf, size_t errbuf_size) |
| 14437 | +{ |
| 14438 | + const char *msg; |
| 14439 | + size_t msg_size; |
| 14440 | + |
| 14441 | + if (errcode < 0 |
| 14442 | + || errcode >= (int) (sizeof (re_error_msgid) |
| 14443 | + / sizeof (re_error_msgid[0]))) |
| 14444 | + /* Only error codes returned by the rest of the code should be passed |
| 14445 | + to this routine. If we are given anything else, or if other regex |
| 14446 | + code generates an invalid error code, then the program has a bug. |
| 14447 | + Dump core so we can fix it. */ |
| 14448 | + abort (); |
| 14449 | + |
| 14450 | + msg = gettext (re_error_msgid[errcode]); |
| 14451 | + |
| 14452 | + msg_size = strlen (msg) + 1; /* Includes the null. */ |
| 14453 | + |
| 14454 | + if (errbuf_size != 0) |
| 14455 | + { |
| 14456 | + if (msg_size > errbuf_size) |
| 14457 | + { |
| 14458 | +#if defined HAVE_MEMPCPY || defined _LIBC |
| 14459 | + *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; |
| 14460 | +#else |
| 14461 | + memcpy (errbuf, msg, errbuf_size - 1); |
| 14462 | + errbuf[errbuf_size - 1] = 0; |
| 14463 | +#endif |
| 14464 | + } |
| 14465 | + else |
| 14466 | + memcpy (errbuf, msg, msg_size); |
| 14467 | + } |
| 14468 | + |
| 14469 | + return msg_size; |
| 14470 | +} |
| 14471 | +#ifdef _LIBC |
| 14472 | +weak_alias (__regerror, regerror) |
| 14473 | +#endif |
| 14474 | + |
| 14475 | + |
| 14476 | +/* Free dynamically allocated space used by PREG. */ |
| 14477 | + |
| 14478 | +void |
| 14479 | +regfree (regex_t *preg) |
| 14480 | +{ |
| 14481 | + if (preg->buffer != NULL) |
| 14482 | + free (preg->buffer); |
| 14483 | + preg->buffer = NULL; |
| 14484 | + |
| 14485 | + preg->allocated = 0; |
| 14486 | + preg->used = 0; |
| 14487 | + |
| 14488 | + if (preg->fastmap != NULL) |
| 14489 | + free (preg->fastmap); |
| 14490 | + preg->fastmap = NULL; |
| 14491 | + preg->fastmap_accurate = 0; |
| 14492 | + |
| 14493 | + if (preg->translate != NULL) |
| 14494 | + free (preg->translate); |
| 14495 | + preg->translate = NULL; |
| 14496 | +} |
| 14497 | +#ifdef _LIBC |
| 14498 | +weak_alias (__regfree, regfree) |
| 14499 | +#endif |
| 14500 | + |
| 14501 | +#endif /* not emacs */ |
| 14502 | + |
| 14503 | +#endif /* not INSIDE_RECURSION */ |
| 14504 | + |
| 14505 | + |
| 14506 | +#undef STORE_NUMBER |
| 14507 | +#undef STORE_NUMBER_AND_INCR |
| 14508 | +#undef EXTRACT_NUMBER |
| 14509 | +#undef EXTRACT_NUMBER_AND_INCR |
| 14510 | + |
| 14511 | +#undef DEBUG_PRINT_COMPILED_PATTERN |
| 14512 | +#undef DEBUG_PRINT_DOUBLE_STRING |
| 14513 | + |
| 14514 | +#undef INIT_FAIL_STACK |
| 14515 | +#undef RESET_FAIL_STACK |
| 14516 | +#undef DOUBLE_FAIL_STACK |
| 14517 | +#undef PUSH_PATTERN_OP |
| 14518 | +#undef PUSH_FAILURE_POINTER |
| 14519 | +#undef PUSH_FAILURE_INT |
| 14520 | +#undef PUSH_FAILURE_ELT |
| 14521 | +#undef POP_FAILURE_POINTER |
| 14522 | +#undef POP_FAILURE_INT |
| 14523 | +#undef POP_FAILURE_ELT |
| 14524 | +#undef DEBUG_PUSH |
| 14525 | +#undef DEBUG_POP |
| 14526 | +#undef PUSH_FAILURE_POINT |
| 14527 | +#undef POP_FAILURE_POINT |
| 14528 | + |
| 14529 | +#undef REG_UNSET_VALUE |
| 14530 | +#undef REG_UNSET |
| 14531 | + |
| 14532 | +#undef PATFETCH |
| 14533 | +#undef PATFETCH_RAW |
| 14534 | +#undef PATUNFETCH |
| 14535 | +#undef TRANSLATE |
| 14536 | + |
| 14537 | +#undef INIT_BUF_SIZE |
| 14538 | +#undef GET_BUFFER_SPACE |
| 14539 | +#undef BUF_PUSH |
| 14540 | +#undef BUF_PUSH_2 |
| 14541 | +#undef BUF_PUSH_3 |
| 14542 | +#undef STORE_JUMP |
| 14543 | +#undef STORE_JUMP2 |
| 14544 | +#undef INSERT_JUMP |
| 14545 | +#undef INSERT_JUMP2 |
| 14546 | +#undef EXTEND_BUFFER |
| 14547 | +#undef GET_UNSIGNED_NUMBER |
| 14548 | +#undef FREE_STACK_RETURN |
| 14549 | + |
| 14550 | +# undef POINTER_TO_OFFSET |
| 14551 | +# undef MATCHING_IN_FRST_STRING |
| 14552 | +# undef PREFETCH |
| 14553 | +# undef AT_STRINGS_BEG |
| 14554 | +# undef AT_STRINGS_END |
| 14555 | +# undef WORDCHAR_P |
| 14556 | +# undef FREE_VAR |
| 14557 | +# undef FREE_VARIABLES |
| 14558 | +# undef NO_HIGHEST_ACTIVE_REG |
| 14559 | +# undef NO_LOWEST_ACTIVE_REG |
| 14560 | + |
| 14561 | +# undef CHAR_T |
| 14562 | +# undef UCHAR_T |
| 14563 | +# undef COMPILED_BUFFER_VAR |
| 14564 | +# undef OFFSET_ADDRESS_SIZE |
| 14565 | +# undef CHAR_CLASS_SIZE |
| 14566 | +# undef PREFIX |
| 14567 | +# undef ARG_PREFIX |
| 14568 | +# undef PUT_CHAR |
| 14569 | +# undef BYTE |
| 14570 | +# undef WCHAR |
| 14571 | + |
| 14572 | +# define DEFINED_ONCE |
| 14573 | diff --git a/pwd/Makefile b/pwd/Makefile |
| 14574 | index 7f6de03..916d546 100644 |
| 14575 | --- a/pwd/Makefile |
| 14576 | +++ b/pwd/Makefile |
| 14577 | @@ -18,6 +18,8 @@ |
| 14578 | # |
| 14579 | # Sub-makefile for pwd portion of the library. |
| 14580 | # |
| 14581 | +include ../option-groups.mak |
| 14582 | + |
| 14583 | subdir := pwd |
| 14584 | |
| 14585 | include ../Makeconfig |
| 14586 | diff --git a/resolv/Makefile b/resolv/Makefile |
| 14587 | index 1dcb75f..2e4b630 100644 |
| 14588 | --- a/resolv/Makefile |
| 14589 | +++ b/resolv/Makefile |
| 14590 | @@ -18,6 +18,8 @@ |
| 14591 | # |
| 14592 | # Sub-makefile for resolv portion of the library. |
| 14593 | # |
| 14594 | +include ../option-groups.mak |
| 14595 | + |
| 14596 | subdir := resolv |
| 14597 | |
| 14598 | include ../Makeconfig |
| 14599 | @@ -27,21 +29,22 @@ headers := resolv.h \ |
| 14600 | arpa/nameser.h arpa/nameser_compat.h \ |
| 14601 | sys/bitypes.h |
| 14602 | |
| 14603 | -routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ |
| 14604 | - res_hconf res_libc res-state |
| 14605 | +routines-$(OPTION_EGLIBC_INET) \ |
| 14606 | + += herror inet_addr inet_ntop inet_pton nsap_addr res_init \ |
| 14607 | + res_hconf res_libc res-state |
| 14608 | |
| 14609 | -tests = tst-aton tst-leaks tst-inet_ntop |
| 14610 | -xtests = tst-leaks2 |
| 14611 | +tests-$(OPTION_EGLIBC_INET) += tst-aton tst-leaks tst-inet_ntop |
| 14612 | +xtests-$(OPTION_EGLIBC_INET) += tst-leaks2 |
| 14613 | |
| 14614 | generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace |
| 14615 | |
| 14616 | -extra-libs := libresolv libnss_dns |
| 14617 | +extra-libs-$(OPTION_EGLIBC_INET) += libresolv libnss_dns |
| 14618 | ifeq ($(have-thread-library),yes) |
| 14619 | -extra-libs += libanl |
| 14620 | -routines += gai_sigqueue |
| 14621 | +extra-libs-$(OPTION_EGLIBC_INET_ANL) += libanl |
| 14622 | +routines-$(OPTION_EGLIBC_INET) += gai_sigqueue |
| 14623 | tests += tst-res_hconf_reorder |
| 14624 | endif |
| 14625 | -extra-libs-others = $(extra-libs) |
| 14626 | +extra-libs-others-y += $(extra-libs-y) |
| 14627 | libresolv-routines := gethnamaddr res_comp res_debug \ |
| 14628 | res_data res_mkquery res_query res_send \ |
| 14629 | inet_net_ntop inet_net_pton inet_neta base64 \ |
| 14630 | @@ -61,7 +64,7 @@ routines += $(libnss_dns-routines) $(libresolv-routines) |
| 14631 | static-only-routines += $(libnss_dns-routines) $(libresolv-routines) |
| 14632 | endif |
| 14633 | |
| 14634 | -ifeq (yesyes,$(build-shared)$(have-thread-library)) |
| 14635 | +ifeq (yesyesy,$(build-shared)$(have-thread-library)$(OPTION_EGLIBC_INET_ANL)) |
| 14636 | tests: $(objpfx)ga_test |
| 14637 | endif |
| 14638 | |
| 14639 | diff --git a/stdio-common/Makefile b/stdio-common/Makefile |
| 14640 | index d0bf0e1..8655801 100644 |
| 14641 | --- a/stdio-common/Makefile |
| 14642 | +++ b/stdio-common/Makefile |
| 14643 | @@ -18,6 +18,8 @@ |
| 14644 | # |
| 14645 | # Specific makefile for stdio-common. |
| 14646 | # |
| 14647 | +include ../option-groups.mak |
| 14648 | + |
| 14649 | subdir := stdio-common |
| 14650 | |
| 14651 | include ../Makeconfig |
| 14652 | @@ -30,7 +32,7 @@ routines := \ |
| 14653 | vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \ |
| 14654 | reg-modifier reg-type \ |
| 14655 | printf_size fprintf printf snprintf sprintf asprintf dprintf \ |
| 14656 | - vfwprintf vfscanf vfwscanf \ |
| 14657 | + vfscanf \ |
| 14658 | fscanf scanf sscanf \ |
| 14659 | perror psignal \ |
| 14660 | tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ |
| 14661 | @@ -41,23 +43,36 @@ routines := \ |
| 14662 | isoc99_vsscanf \ |
| 14663 | psiginfo |
| 14664 | |
| 14665 | -aux := errlist siglist printf-parsemb printf-parsewc fxprintf |
| 14666 | +# Ideally, _itowa and itowa-digits would be in this option group as |
| 14667 | +# well, but it is used unconditionally by printf_fp and printf_fphex, |
| 14668 | +# and it didn't seem straightforward to disentangle it. |
| 14669 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 14670 | + += vfwprintf vfwscanf |
| 14671 | + |
| 14672 | +aux := errlist siglist printf-parsemb fxprintf |
| 14673 | +aux-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += printf-parsewc |
| 14674 | |
| 14675 | tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ |
| 14676 | temptest tst-fileno test-fwrite tst-ungetc tst-ferror \ |
| 14677 | xbug errnobug \ |
| 14678 | bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \ |
| 14679 | - tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \ |
| 14680 | + tfformat tiformat tllformat tstdiomisc tst-printfsz \ |
| 14681 | scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \ |
| 14682 | - scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ |
| 14683 | - tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ |
| 14684 | - tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \ |
| 14685 | + scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf \ |
| 14686 | + tst-fseek tst-fmemopen tst-gets \ |
| 14687 | + tst-sprintf tst-rndseek tst-fdopen tst-fphex \ |
| 14688 | tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ |
| 14689 | - tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \ |
| 14690 | - bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ |
| 14691 | - scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ |
| 14692 | - bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ |
| 14693 | + tst-fwrite bug16 bug17 tst-sprintf2 bug18 \ |
| 14694 | + bug19 tst-popen2 scanf14 scanf15 bug21 bug22 \ |
| 14695 | + scanf16 scanf17 tst-setvbuf1 bug23 bug24 \ |
| 14696 | + bug-vfprintf-nargs tst-sprintf3 \ |
| 14697 | bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 |
| 14698 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 14699 | + += tst-sscanf tst-swprintf test-vfprintf bug14 scanf13 tst-grouping |
| 14700 | +tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ |
| 14701 | + += tst-perror bug19a bug20 tst-long-dbl-fphex tst-fphex-wide |
| 14702 | +tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 14703 | + += bug18a tst-swscanf tst-wc-printf |
| 14704 | |
| 14705 | test-srcs = tst-unbputc tst-printf |
| 14706 | |
| 14707 | diff --git a/stdio-common/_i18n_number.h b/stdio-common/_i18n_number.h |
| 14708 | index 3c73044..ac62b3a 100644 |
| 14709 | --- a/stdio-common/_i18n_number.h |
| 14710 | +++ b/stdio-common/_i18n_number.h |
| 14711 | @@ -19,10 +19,13 @@ |
| 14712 | #include <stdbool.h> |
| 14713 | #include <wchar.h> |
| 14714 | #include <wctype.h> |
| 14715 | +#include <gnu/option-groups.h> |
| 14716 | |
| 14717 | #include "../locale/outdigits.h" |
| 14718 | #include "../locale/outdigitswc.h" |
| 14719 | |
| 14720 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 14721 | + |
| 14722 | static CHAR_T * |
| 14723 | _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) |
| 14724 | { |
| 14725 | @@ -115,3 +118,13 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) |
| 14726 | |
| 14727 | return w; |
| 14728 | } |
| 14729 | + |
| 14730 | +#else |
| 14731 | + |
| 14732 | +static CHAR_T * |
| 14733 | +_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) |
| 14734 | +{ |
| 14735 | + return w; |
| 14736 | +} |
| 14737 | + |
| 14738 | +#endif |
| 14739 | diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c |
| 14740 | index 7b2eb94..8476076 100644 |
| 14741 | --- a/stdio-common/fxprintf.c |
| 14742 | +++ b/stdio-common/fxprintf.c |
| 14743 | @@ -23,6 +23,7 @@ |
| 14744 | #include <wchar.h> |
| 14745 | #include <string.h> |
| 14746 | #include <libioP.h> |
| 14747 | +#include <gnu/option-groups.h> |
| 14748 | |
| 14749 | |
| 14750 | int |
| 14751 | @@ -37,6 +38,7 @@ __fxprintf (FILE *fp, const char *fmt, ...) |
| 14752 | int res; |
| 14753 | if (_IO_fwide (fp, 0) > 0) |
| 14754 | { |
| 14755 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 14756 | size_t len = strlen (fmt) + 1; |
| 14757 | wchar_t wfmt[len]; |
| 14758 | for (size_t i = 0; i < len; ++i) |
| 14759 | @@ -45,6 +47,9 @@ __fxprintf (FILE *fp, const char *fmt, ...) |
| 14760 | wfmt[i] = fmt[i]; |
| 14761 | } |
| 14762 | res = __vfwprintf (fp, wfmt, ap); |
| 14763 | +#else |
| 14764 | + abort(); |
| 14765 | +#endif |
| 14766 | } |
| 14767 | else |
| 14768 | res = _IO_vfprintf (fp, fmt, ap); |
| 14769 | diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c |
| 14770 | index 3023b20..bd0df66 100644 |
| 14771 | --- a/stdio-common/printf_fp.c |
| 14772 | +++ b/stdio-common/printf_fp.c |
| 14773 | @@ -39,6 +39,7 @@ |
| 14774 | #include <unistd.h> |
| 14775 | #include <stdlib.h> |
| 14776 | #include <wchar.h> |
| 14777 | +#include <gnu/option-groups.h> |
| 14778 | #include <stdbool.h> |
| 14779 | #include <rounding-mode.h> |
| 14780 | |
| 14781 | @@ -142,6 +143,10 @@ extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, |
| 14782 | extern unsigned int __guess_grouping (unsigned int intdig_max, |
| 14783 | const char *grouping); |
| 14784 | |
| 14785 | +/* Ideally, when OPTION_EGLIBC_LOCALE_CODE is disabled, this should do |
| 14786 | + all its work in ordinary characters, rather than doing it in wide |
| 14787 | + characters and then converting at the end. But that is a challenge |
| 14788 | + for another day. */ |
| 14789 | |
| 14790 | static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, |
| 14791 | unsigned int intdig_no, const char *grouping, |
| 14792 | @@ -251,7 +256,14 @@ ___printf_fp (FILE *fp, |
| 14793 | mp_limb_t cy; |
| 14794 | |
| 14795 | /* Nonzero if this is output on a wide character stream. */ |
| 14796 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 14797 | int wide = info->wide; |
| 14798 | +#else |
| 14799 | + /* This should never be called on a wide-oriented stream when |
| 14800 | + OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't |
| 14801 | + be trusted to figure that out. */ |
| 14802 | + const int wide = 0; |
| 14803 | +#endif |
| 14804 | |
| 14805 | /* Buffer in which we produce the output. */ |
| 14806 | wchar_t *wbuffer = NULL; |
| 14807 | @@ -261,6 +273,7 @@ ___printf_fp (FILE *fp, |
| 14808 | p.expsign = 0; |
| 14809 | |
| 14810 | /* Figure out the decimal point character. */ |
| 14811 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 14812 | if (info->extra == 0) |
| 14813 | { |
| 14814 | decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); |
| 14815 | @@ -280,7 +293,13 @@ ___printf_fp (FILE *fp, |
| 14816 | /* The decimal point character must not be zero. */ |
| 14817 | assert (*decimal != '\0'); |
| 14818 | assert (decimalwc != L'\0'); |
| 14819 | +#else |
| 14820 | + /* Hard-code values from 'C' locale. */ |
| 14821 | + decimal = "."; |
| 14822 | + decimalwc = L'.'; |
| 14823 | +#endif |
| 14824 | |
| 14825 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 14826 | if (info->group) |
| 14827 | { |
| 14828 | if (info->extra == 0) |
| 14829 | @@ -324,6 +343,9 @@ ___printf_fp (FILE *fp, |
| 14830 | } |
| 14831 | else |
| 14832 | grouping = NULL; |
| 14833 | +#else |
| 14834 | + grouping = NULL; |
| 14835 | +#endif |
| 14836 | |
| 14837 | /* Fetch the argument value. */ |
| 14838 | #ifndef __NO_LONG_DOUBLE_MATH |
| 14839 | diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c |
| 14840 | index 6c3b5e9..f660ce0 100644 |
| 14841 | --- a/stdio-common/printf_fphex.c |
| 14842 | +++ b/stdio-common/printf_fphex.c |
| 14843 | @@ -28,6 +28,7 @@ |
| 14844 | #include <_itoa.h> |
| 14845 | #include <_itowa.h> |
| 14846 | #include <locale/localeinfo.h> |
| 14847 | +#include <gnu/option-groups.h> |
| 14848 | #include <stdbool.h> |
| 14849 | #include <rounding-mode.h> |
| 14850 | |
| 14851 | @@ -139,10 +140,18 @@ __printf_fphex (FILE *fp, |
| 14852 | int done = 0; |
| 14853 | |
| 14854 | /* Nonzero if this is output on a wide character stream. */ |
| 14855 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 14856 | int wide = info->wide; |
| 14857 | +#else |
| 14858 | + /* This should never be called on a wide-oriented stream when |
| 14859 | + OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't |
| 14860 | + be trusted to figure that out. */ |
| 14861 | + const int wide = 0; |
| 14862 | +#endif |
| 14863 | |
| 14864 | |
| 14865 | /* Figure out the decimal point character. */ |
| 14866 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 14867 | if (info->extra == 0) |
| 14868 | { |
| 14869 | decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); |
| 14870 | @@ -156,6 +165,10 @@ __printf_fphex (FILE *fp, |
| 14871 | } |
| 14872 | /* The decimal point character must never be zero. */ |
| 14873 | assert (*decimal != '\0' && decimalwc != L'\0'); |
| 14874 | +#else |
| 14875 | + decimal = "."; |
| 14876 | + decimalwc = L'.'; |
| 14877 | +#endif |
| 14878 | |
| 14879 | |
| 14880 | /* Fetch the argument value. */ |
| 14881 | diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c |
| 14882 | index 7dcd58e..6fb7491 100644 |
| 14883 | --- a/stdio-common/printf_size.c |
| 14884 | +++ b/stdio-common/printf_size.c |
| 14885 | @@ -23,6 +23,7 @@ |
| 14886 | #include <math.h> |
| 14887 | #include <printf.h> |
| 14888 | #include <libioP.h> |
| 14889 | +#include <gnu/option-groups.h> |
| 14890 | |
| 14891 | |
| 14892 | /* This defines make it possible to use the same code for GNU C library and |
| 14893 | @@ -116,7 +117,14 @@ __printf_size (FILE *fp, const struct printf_info *info, |
| 14894 | |
| 14895 | struct printf_info fp_info; |
| 14896 | int done = 0; |
| 14897 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 14898 | int wide = info->wide; |
| 14899 | +#else |
| 14900 | + /* This should never be called on a wide-oriented stream when |
| 14901 | + OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't |
| 14902 | + be trusted to figure that out. */ |
| 14903 | + const int wide = 0; |
| 14904 | +#endif |
| 14905 | int res; |
| 14906 | |
| 14907 | /* Fetch the argument value. */ |
| 14908 | diff --git a/stdio-common/scanf14.c b/stdio-common/scanf14.c |
| 14909 | index cffccb0..6cc260a 100644 |
| 14910 | --- a/stdio-common/scanf14.c |
| 14911 | +++ b/stdio-common/scanf14.c |
| 14912 | @@ -3,6 +3,7 @@ |
| 14913 | #include <string.h> |
| 14914 | #include <wchar.h> |
| 14915 | #include <libc-internal.h> |
| 14916 | +#include <gnu/option-groups.h> |
| 14917 | |
| 14918 | #define FAIL() \ |
| 14919 | do { \ |
| 14920 | @@ -48,6 +49,7 @@ main (void) |
| 14921 | /* See explanation above. */ |
| 14922 | DIAG_PUSH_NEEDS_COMMENT; |
| 14923 | DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat"); |
| 14924 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 14925 | if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2) |
| 14926 | FAIL (); |
| 14927 | else |
| 14928 | @@ -57,6 +59,7 @@ main (void) |
| 14929 | memset (lsp, 'x', sizeof L"3.25"); |
| 14930 | free (lsp); |
| 14931 | } |
| 14932 | +#endif |
| 14933 | if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2) |
| 14934 | FAIL (); |
| 14935 | else |
| 14936 | diff --git a/stdio-common/tst-popen.c b/stdio-common/tst-popen.c |
| 14937 | index 5def27f..7c9b91e 100644 |
| 14938 | --- a/stdio-common/tst-popen.c |
| 14939 | +++ b/stdio-common/tst-popen.c |
| 14940 | @@ -19,6 +19,7 @@ |
| 14941 | #include <stdio.h> |
| 14942 | #include <string.h> |
| 14943 | #include <wchar.h> |
| 14944 | +#include <gnu/option-groups.h> |
| 14945 | |
| 14946 | static int |
| 14947 | do_test (void) |
| 14948 | @@ -34,12 +35,14 @@ do_test (void) |
| 14949 | return 1; |
| 14950 | } |
| 14951 | |
| 14952 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 14953 | /* POSIX says that pipe streams are byte-oriented. */ |
| 14954 | if (fwide (f, 0) >= 0) |
| 14955 | { |
| 14956 | puts ("popen did not return byte-oriented stream"); |
| 14957 | result = 1; |
| 14958 | } |
| 14959 | +#endif |
| 14960 | |
| 14961 | if (getline (&line, &len, f) != 5) |
| 14962 | { |
| 14963 | diff --git a/stdio-common/tst-sprintf.c b/stdio-common/tst-sprintf.c |
| 14964 | index d5284b9..f1e3d21 100644 |
| 14965 | --- a/stdio-common/tst-sprintf.c |
| 14966 | +++ b/stdio-common/tst-sprintf.c |
| 14967 | @@ -3,7 +3,7 @@ |
| 14968 | #include <locale.h> |
| 14969 | #include <string.h> |
| 14970 | #include <libc-internal.h> |
| 14971 | - |
| 14972 | +#include <gnu/option-groups.h> |
| 14973 | |
| 14974 | static int |
| 14975 | do_test (void) |
| 14976 | @@ -11,12 +11,14 @@ do_test (void) |
| 14977 | char buf[100]; |
| 14978 | int result = 0; |
| 14979 | |
| 14980 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 14981 | if (sprintf (buf, "%.0ls", L"foo") != 0 |
| 14982 | || strlen (buf) != 0) |
| 14983 | { |
| 14984 | puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output"); |
| 14985 | result = 1; |
| 14986 | } |
| 14987 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 14988 | |
| 14989 | #define SIZE (1024*70000) |
| 14990 | #define STR(x) #x |
| 14991 | diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c |
| 14992 | index 5548a71..31ed024 100644 |
| 14993 | --- a/stdio-common/tstdiomisc.c |
| 14994 | +++ b/stdio-common/tstdiomisc.c |
| 14995 | @@ -4,6 +4,7 @@ |
| 14996 | #include <string.h> |
| 14997 | #include <wchar.h> |
| 14998 | #include <libc-internal.h> |
| 14999 | +#include <gnu/option-groups.h> |
| 15000 | |
| 15001 | static int |
| 15002 | t1 (void) |
| 15003 | @@ -134,6 +135,7 @@ F (void) |
| 15004 | printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", |
| 15005 | buf); |
| 15006 | |
| 15007 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 15008 | swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", |
| 15009 | qnanval, qnanval, qnanval, qnanval, |
| 15010 | qnanval, qnanval, qnanval, qnanval); |
| 15011 | @@ -171,6 +173,7 @@ F (void) |
| 15012 | result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; |
| 15013 | printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", |
| 15014 | wbuf); |
| 15015 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 15016 | |
| 15017 | lqnanval = NAN; |
| 15018 | |
| 15019 | @@ -215,6 +218,7 @@ F (void) |
| 15020 | printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", |
| 15021 | buf); |
| 15022 | |
| 15023 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 15024 | swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), |
| 15025 | L"%La %LA %Le %LE %Lf %LF %Lg %LG", |
| 15026 | lqnanval, lqnanval, lqnanval, lqnanval, |
| 15027 | @@ -259,6 +263,7 @@ F (void) |
| 15028 | result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; |
| 15029 | printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n", |
| 15030 | wbuf); |
| 15031 | +#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */ |
| 15032 | |
| 15033 | return result; |
| 15034 | } |
| 15035 | diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c |
| 15036 | index 0592e70..f21d973 100644 |
| 15037 | --- a/stdio-common/vfprintf.c |
| 15038 | +++ b/stdio-common/vfprintf.c |
| 15039 | @@ -29,6 +29,7 @@ |
| 15040 | #include <_itoa.h> |
| 15041 | #include <locale/localeinfo.h> |
| 15042 | #include <stdio.h> |
| 15043 | +#include <gnu/option-groups.h> |
| 15044 | |
| 15045 | /* This code is shared between the standard stdio implementation found |
| 15046 | in GNU C library and the libio implementation originally found in |
| 15047 | @@ -140,6 +141,18 @@ typedef wchar_t THOUSANDS_SEP_T; |
| 15048 | # define EOF WEOF |
| 15049 | #endif |
| 15050 | |
| 15051 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 15052 | +# define MULTIBYTE_SUPPORT (1) |
| 15053 | +#else |
| 15054 | +# define MULTIBYTE_SUPPORT (0) |
| 15055 | +#endif |
| 15056 | + |
| 15057 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15058 | +# define LOCALE_SUPPORT (1) |
| 15059 | +#else |
| 15060 | +# define LOCALE_SUPPORT (0) |
| 15061 | +#endif |
| 15062 | + |
| 15063 | #include "_i18n_number.h" |
| 15064 | |
| 15065 | /* Include the shared code for parsing the format string. */ |
| 15066 | @@ -1065,8 +1078,11 @@ static const uint8_t jump_table[] = |
| 15067 | # define process_string_arg(fspec) \ |
| 15068 | LABEL (form_character): \ |
| 15069 | /* Character. */ \ |
| 15070 | - if (is_long) \ |
| 15071 | - goto LABEL (form_wcharacter); \ |
| 15072 | + if (is_long) \ |
| 15073 | + { \ |
| 15074 | + assert (MULTIBYTE_SUPPORT); \ |
| 15075 | + goto LABEL (form_wcharacter); \ |
| 15076 | + } \ |
| 15077 | --width; /* Account for the character itself. */ \ |
| 15078 | if (!left) \ |
| 15079 | PAD (' '); \ |
| 15080 | @@ -1079,6 +1095,7 @@ static const uint8_t jump_table[] = |
| 15081 | break; \ |
| 15082 | \ |
| 15083 | LABEL (form_wcharacter): \ |
| 15084 | + assert (MULTIBYTE_SUPPORT); \ |
| 15085 | { \ |
| 15086 | /* Wide character. */ \ |
| 15087 | char buf[MB_CUR_MAX]; \ |
| 15088 | @@ -1145,6 +1162,7 @@ static const uint8_t jump_table[] = |
| 15089 | } \ |
| 15090 | else \ |
| 15091 | { \ |
| 15092 | + assert (MULTIBYTE_SUPPORT); \ |
| 15093 | const wchar_t *s2 = (const wchar_t *) string; \ |
| 15094 | mbstate_t mbstate; \ |
| 15095 | \ |
| 15096 | @@ -1399,7 +1417,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) |
| 15097 | LABEL (flag_quote): |
| 15098 | group = 1; |
| 15099 | |
| 15100 | - if (grouping == (const char *) -1) |
| 15101 | + if (! LOCALE_SUPPORT) |
| 15102 | + grouping = NULL; |
| 15103 | + else if (grouping == (const char *) -1) |
| 15104 | { |
| 15105 | #ifdef COMPILE_WPRINTF |
| 15106 | thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, |
| 15107 | @@ -1728,8 +1748,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, |
| 15108 | size_t cnt; |
| 15109 | |
| 15110 | CHAR_T *workstart = NULL; |
| 15111 | - |
| 15112 | - if (grouping == (const char *) -1) |
| 15113 | + if (! LOCALE_SUPPORT) |
| 15114 | + grouping = NULL; |
| 15115 | + else if (grouping == (const char *) -1) |
| 15116 | { |
| 15117 | #ifdef COMPILE_WPRINTF |
| 15118 | thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC, |
| 15119 | diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c |
| 15120 | index 0e204e7..66cc0af 100644 |
| 15121 | --- a/stdio-common/vfscanf.c |
| 15122 | +++ b/stdio-common/vfscanf.c |
| 15123 | @@ -29,6 +29,7 @@ |
| 15124 | #include <wctype.h> |
| 15125 | #include <bits/libc-lock.h> |
| 15126 | #include <locale/localeinfo.h> |
| 15127 | +#include <gnu/option-groups.h> |
| 15128 | |
| 15129 | #ifdef __GNUC__ |
| 15130 | # define HAVE_LONGLONG |
| 15131 | @@ -133,6 +134,12 @@ |
| 15132 | # define WINT_T int |
| 15133 | #endif |
| 15134 | |
| 15135 | +#if __OPTION_POSIX_C_LANG_WIDE_CHAR |
| 15136 | +# define MULTIBYTE_SUPPORT (1) |
| 15137 | +#else |
| 15138 | +# define MULTIBYTE_SUPPORT (0) |
| 15139 | +#endif |
| 15140 | + |
| 15141 | #define encode_error() do { \ |
| 15142 | errval = 4; \ |
| 15143 | __set_errno (EILSEQ); \ |
| 15144 | @@ -316,24 +323,35 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15145 | ARGCHECK (s, format); |
| 15146 | |
| 15147 | { |
| 15148 | -#ifndef COMPILE_WSCANF |
| 15149 | +#if __OPTION_EGLIBC_LOCALE_CODE && !defined (COMPILE_WSCANF) |
| 15150 | struct __locale_data *const curnumeric = loc->__locales[LC_NUMERIC]; |
| 15151 | #endif |
| 15152 | |
| 15153 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15154 | /* Figure out the decimal point character. */ |
| 15155 | -#ifdef COMPILE_WSCANF |
| 15156 | +# ifdef COMPILE_WSCANF |
| 15157 | decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); |
| 15158 | -#else |
| 15159 | +# else |
| 15160 | decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string; |
| 15161 | -#endif |
| 15162 | +# endif |
| 15163 | /* Figure out the thousands separator character. */ |
| 15164 | -#ifdef COMPILE_WSCANF |
| 15165 | +# ifdef COMPILE_WSCANF |
| 15166 | thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); |
| 15167 | -#else |
| 15168 | +# else |
| 15169 | thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string; |
| 15170 | if (*thousands == '\0') |
| 15171 | thousands = NULL; |
| 15172 | -#endif |
| 15173 | +# endif |
| 15174 | +#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */ |
| 15175 | + /* Hard-code values from the C locale. */ |
| 15176 | +# ifdef COMPILE_WSCANF |
| 15177 | + decimal = L'.'; |
| 15178 | + thousands = L'\0'; |
| 15179 | +# else |
| 15180 | + decimal = "."; |
| 15181 | + thousands = NULL; |
| 15182 | +# endif |
| 15183 | +#endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 15184 | } |
| 15185 | |
| 15186 | /* Lock the stream. */ |
| 15187 | @@ -385,6 +403,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15188 | #ifndef COMPILE_WSCANF |
| 15189 | if (!isascii ((unsigned char) *f)) |
| 15190 | { |
| 15191 | + assert (MULTIBYTE_SUPPORT); |
| 15192 | + |
| 15193 | /* Non-ASCII, may be a multibyte. */ |
| 15194 | int len = __mbrlen (f, strlen (f), &state); |
| 15195 | if (len > 0) |
| 15196 | @@ -830,6 +850,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15197 | } |
| 15198 | /* FALLTHROUGH */ |
| 15199 | case L_('C'): |
| 15200 | + assert (MULTIBYTE_SUPPORT); |
| 15201 | + |
| 15202 | if (width == -1) |
| 15203 | width = 1; |
| 15204 | |
| 15205 | @@ -1172,6 +1194,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15206 | /* FALLTHROUGH */ |
| 15207 | |
| 15208 | case L_('S'): |
| 15209 | + assert (MULTIBYTE_SUPPORT); |
| 15210 | + |
| 15211 | { |
| 15212 | #ifndef COMPILE_WSCANF |
| 15213 | mbstate_t cstate; |
| 15214 | @@ -1419,10 +1443,17 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15215 | const char *mbdigits[10]; |
| 15216 | const char *mbdigits_extended[10]; |
| 15217 | #endif |
| 15218 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15219 | /* "to_inpunct" is a map from ASCII digits to their |
| 15220 | equivalent in locale. This is defined for locales |
| 15221 | which use an extra digits set. */ |
| 15222 | wctrans_t map = __wctrans ("to_inpunct"); |
| 15223 | +#else |
| 15224 | + /* This will always be the case when |
| 15225 | + OPTION_EGLIBC_LOCALE_CODE is disabled, but the |
| 15226 | + compiler can't figure that out. */ |
| 15227 | + wctrans_t map = NULL; |
| 15228 | +#endif |
| 15229 | int n; |
| 15230 | |
| 15231 | from_level = 0; |
| 15232 | @@ -2088,6 +2119,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15233 | --width; |
| 15234 | } |
| 15235 | |
| 15236 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15237 | wctrans_t map; |
| 15238 | if (__builtin_expect ((flags & I18N) != 0, 0) |
| 15239 | /* Hexadecimal floats make no sense, fixing localized |
| 15240 | @@ -2304,6 +2336,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15241 | ; |
| 15242 | #endif |
| 15243 | } |
| 15244 | +#endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 15245 | |
| 15246 | /* Have we read any character? If we try to read a number |
| 15247 | in hexadecimal notation and we have read only the `0x' |
| 15248 | @@ -2343,7 +2376,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15249 | |
| 15250 | case L_('['): /* Character class. */ |
| 15251 | if (flags & LONG) |
| 15252 | - STRING_ARG (wstr, wchar_t, 100); |
| 15253 | + { |
| 15254 | + assert (MULTIBYTE_SUPPORT); |
| 15255 | + STRING_ARG (wstr, wchar_t, 100); |
| 15256 | + } |
| 15257 | else |
| 15258 | STRING_ARG (str, char, 100); |
| 15259 | |
| 15260 | @@ -2417,6 +2453,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
| 15261 | if (flags & LONG) |
| 15262 | { |
| 15263 | size_t now = read_in; |
| 15264 | + assert (MULTIBYTE_SUPPORT); |
| 15265 | #ifdef COMPILE_WSCANF |
| 15266 | if (__glibc_unlikely (inchar () == WEOF)) |
| 15267 | input_error (); |
| 15268 | diff --git a/stdlib/Makefile b/stdlib/Makefile |
| 15269 | index 402466a..7e7e304 100644 |
| 15270 | --- a/stdlib/Makefile |
| 15271 | +++ b/stdlib/Makefile |
| 15272 | @@ -18,6 +18,8 @@ |
| 15273 | # |
| 15274 | # Makefile for stdlib routines |
| 15275 | # |
| 15276 | +include ../option-groups.mak |
| 15277 | + |
| 15278 | subdir := stdlib |
| 15279 | |
| 15280 | include ../Makeconfig |
| 15281 | @@ -30,7 +32,7 @@ headers := stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h \ |
| 15282 | alloca.h fmtmsg.h \ |
| 15283 | bits/stdlib-bsearch.h |
| 15284 | |
| 15285 | -routines := \ |
| 15286 | +routines-y := \ |
| 15287 | atof atoi atol atoll \ |
| 15288 | abort \ |
| 15289 | bsearch qsort msort \ |
| 15290 | @@ -39,7 +41,6 @@ routines := \ |
| 15291 | quick_exit at_quick_exit cxa_at_quick_exit cxa_thread_atexit_impl \ |
| 15292 | abs labs llabs \ |
| 15293 | div ldiv lldiv \ |
| 15294 | - mblen mbstowcs mbtowc wcstombs wctomb \ |
| 15295 | random random_r rand rand_r \ |
| 15296 | drand48 erand48 lrand48 nrand48 mrand48 jrand48 \ |
| 15297 | srand48 seed48 lcong48 \ |
| 15298 | @@ -52,9 +53,18 @@ routines := \ |
| 15299 | strtof_l strtod_l strtold_l \ |
| 15300 | system canonicalize \ |
| 15301 | a64l l64a \ |
| 15302 | - rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \ |
| 15303 | - strtoimax strtoumax wcstoimax wcstoumax \ |
| 15304 | + getsubopt xpg_basename \ |
| 15305 | + strtoimax strtoumax \ |
| 15306 | getcontext setcontext makecontext swapcontext |
| 15307 | +routines-$(OPTION_EGLIBC_LOCALE_CODE) += \ |
| 15308 | + strfmon strfmon_l |
| 15309 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += \ |
| 15310 | + mblen mbstowcs mbtowc wcstombs wctomb \ |
| 15311 | + wcstoimax wcstoumax |
| 15312 | +ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP)) |
| 15313 | +routines-y += rpmatch |
| 15314 | +endif |
| 15315 | +routines-$(OPTION_EGLIBC_FMTMSG) += fmtmsg |
| 15316 | aux = grouping groupingwc tens_in_limb |
| 15317 | |
| 15318 | # These routines will be omitted from the libc shared object. |
| 15319 | @@ -62,20 +72,24 @@ aux = grouping groupingwc tens_in_limb |
| 15320 | # linked against when the shared library will be used. |
| 15321 | static-only-routines = atexit at_quick_exit |
| 15322 | |
| 15323 | -test-srcs := tst-fmtmsg |
| 15324 | -tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ |
| 15325 | +test-srcs-$(OPTION_EGLIBC_FMTMSG) := tst-fmtmsg |
| 15326 | +tests := tst-strtol tst-strtod testrand testsort testdiv \ |
| 15327 | test-canon test-canon2 tst-strtoll tst-environ \ |
| 15328 | tst-xpg-basename tst-random tst-random2 tst-bsearch \ |
| 15329 | tst-limits tst-rand48 bug-strtod tst-setcontext \ |
| 15330 | - tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \ |
| 15331 | - bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 \ |
| 15332 | - tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5 \ |
| 15333 | + tst-setcontext2 test-a64l tst-qsort tst-system \ |
| 15334 | + bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \ |
| 15335 | + tst-rand48-2 tst-makecontext \ |
| 15336 | tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \ |
| 15337 | tst-makecontext3 bug-getcontext bug-fmtmsg1 \ |
| 15338 | tst-secure-getenv tst-strtod-overflow tst-strtod-round \ |
| 15339 | tst-tininess tst-strtod-underflow tst-tls-atexit \ |
| 15340 | tst-setcontext3 tst-tls-atexit-nodelete |
| 15341 | tests-static := tst-secure-getenv |
| 15342 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 15343 | + += tst-strtod3 tst-strtod4 tst-strtod5 testmb2 |
| 15344 | +tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 15345 | + += testmb |
| 15346 | |
| 15347 | modules-names = tst-tls-atexit-lib |
| 15348 | |
| 15349 | @@ -116,8 +130,10 @@ CFLAGS-tst-makecontext2.c = $(stack-align-test-flags) |
| 15350 | tests-special += $(objpfx)isomac.out |
| 15351 | |
| 15352 | ifeq ($(run-built-tests),yes) |
| 15353 | +ifeq (y,$(OPTION_EGLIBC_FMTMSG)) |
| 15354 | tests-special += $(objpfx)tst-fmtmsg.out |
| 15355 | endif |
| 15356 | +endif |
| 15357 | |
| 15358 | include ../Rules |
| 15359 | |
| 15360 | diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c |
| 15361 | index e13ab1e..63efe41 100644 |
| 15362 | --- a/stdlib/strtod_l.c |
| 15363 | +++ b/stdlib/strtod_l.c |
| 15364 | @@ -17,6 +17,7 @@ |
| 15365 | License along with the GNU C Library; if not, see |
| 15366 | <http://www.gnu.org/licenses/>. */ |
| 15367 | |
| 15368 | +#include <gnu/option-groups.h> |
| 15369 | #include <xlocale.h> |
| 15370 | |
| 15371 | extern double ____strtod_l_internal (const char *, char **, int, __locale_t); |
| 15372 | @@ -548,6 +549,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc) |
| 15373 | /* Used in several places. */ |
| 15374 | int cnt; |
| 15375 | |
| 15376 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15377 | struct __locale_data *current = loc->__locales[LC_NUMERIC]; |
| 15378 | |
| 15379 | if (__glibc_unlikely (group)) |
| 15380 | @@ -586,6 +588,17 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc) |
| 15381 | decimal_len = strlen (decimal); |
| 15382 | assert (decimal_len > 0); |
| 15383 | #endif |
| 15384 | +#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */ |
| 15385 | + /* Hard-code values from the 'C' locale. */ |
| 15386 | + grouping = NULL; |
| 15387 | +#ifdef USE_WIDE_CHAR |
| 15388 | + decimal = L'.'; |
| 15389 | +# define decimal_len 1 |
| 15390 | +#else |
| 15391 | + decimal = "."; |
| 15392 | + decimal_len = 1; |
| 15393 | +#endif |
| 15394 | +#endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 15395 | |
| 15396 | /* Prepare number representation. */ |
| 15397 | exponent = 0; |
| 15398 | diff --git a/stdlib/tst-strtod.c b/stdlib/tst-strtod.c |
| 15399 | index a469208..28fb423 100644 |
| 15400 | --- a/stdlib/tst-strtod.c |
| 15401 | +++ b/stdlib/tst-strtod.c |
| 15402 | @@ -23,6 +23,7 @@ |
| 15403 | #include <errno.h> |
| 15404 | #include <string.h> |
| 15405 | #include <math.h> |
| 15406 | +#include <gnu/option-groups.h> |
| 15407 | |
| 15408 | struct ltest |
| 15409 | { |
| 15410 | @@ -176,7 +177,9 @@ main (int argc, char ** argv) |
| 15411 | |
| 15412 | status |= long_dbl (); |
| 15413 | |
| 15414 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15415 | status |= locale_test (); |
| 15416 | +#endif |
| 15417 | |
| 15418 | return status ? EXIT_FAILURE : EXIT_SUCCESS; |
| 15419 | } |
| 15420 | @@ -219,6 +222,7 @@ long_dbl (void) |
| 15421 | return 0; |
| 15422 | } |
| 15423 | |
| 15424 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15425 | /* Perform a few tests in a locale with thousands separators. */ |
| 15426 | static int |
| 15427 | locale_test (void) |
| 15428 | @@ -276,3 +280,4 @@ locale_test (void) |
| 15429 | |
| 15430 | return result; |
| 15431 | } |
| 15432 | +#endif /* __OPTION_EGLIBC_LOCALE_CODE */ |
| 15433 | diff --git a/streams/Makefile b/streams/Makefile |
| 15434 | index a8a6162..ceb423f 100644 |
| 15435 | --- a/streams/Makefile |
| 15436 | +++ b/streams/Makefile |
| 15437 | @@ -18,11 +18,14 @@ |
| 15438 | # |
| 15439 | # Makefile for streams. |
| 15440 | # |
| 15441 | +include ../option-groups.mak |
| 15442 | + |
| 15443 | subdir := streams |
| 15444 | |
| 15445 | include ../Makeconfig |
| 15446 | |
| 15447 | headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h |
| 15448 | -routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach |
| 15449 | +routines-$(OPTION_EGLIBC_STREAMS) \ |
| 15450 | + += isastream getmsg getpmsg putmsg putpmsg fattach fdetach |
| 15451 | |
| 15452 | include ../Rules |
| 15453 | diff --git a/string/Makefile b/string/Makefile |
| 15454 | index 8424a61..5988834 100644 |
| 15455 | --- a/string/Makefile |
| 15456 | +++ b/string/Makefile |
| 15457 | @@ -18,6 +18,8 @@ |
| 15458 | # |
| 15459 | # Sub-makefile for string portion of library. |
| 15460 | # |
| 15461 | +include ../option-groups.mak |
| 15462 | + |
| 15463 | subdir := string |
| 15464 | |
| 15465 | include ../Makeconfig |
| 15466 | @@ -39,10 +41,12 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ |
| 15467 | $(addprefix argz-,append count create ctsep next \ |
| 15468 | delete extract insert stringify \ |
| 15469 | addsep replace) \ |
| 15470 | - envz basename \ |
| 15471 | + basename \ |
| 15472 | strcoll_l strxfrm_l string-inlines memrchr \ |
| 15473 | xpg-strerror strerror_l |
| 15474 | |
| 15475 | +routines-$(OPTION_EGLIBC_ENVZ) += envz |
| 15476 | + |
| 15477 | strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ |
| 15478 | stpcpy stpncpy strcat strchr strcmp strcpy strcspn \ |
| 15479 | strlen strncmp strncpy strpbrk strrchr strspn memmem \ |
| 15480 | @@ -51,10 +55,12 @@ strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ |
| 15481 | tests := tester inl-tester noinl-tester testcopy test-ffs \ |
| 15482 | tst-strlen stratcliff tst-svc tst-inlcall \ |
| 15483 | bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \ |
| 15484 | - tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ |
| 15485 | + tst-strtok tst-strfry \ |
| 15486 | bug-strtok1 $(addprefix test-,$(strop-tests)) \ |
| 15487 | - bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ |
| 15488 | - tst-strtok_r |
| 15489 | + tst-strxfrm2 tst-endian tst-svc2 tst-strtok_r |
| 15490 | +tests-$(OPTION_EGLIBC_ENVZ) += bug-envz1 |
| 15491 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 15492 | + += tst-strxfrm bug-strcoll1 |
| 15493 | |
| 15494 | xtests = tst-strcoll-overflow |
| 15495 | |
| 15496 | diff --git a/string/strcoll_l.c b/string/strcoll_l.c |
| 15497 | index 8f1225f..b36b18c 100644 |
| 15498 | --- a/string/strcoll_l.c |
| 15499 | +++ b/string/strcoll_l.c |
| 15500 | @@ -24,6 +24,7 @@ |
| 15501 | #include <stdint.h> |
| 15502 | #include <string.h> |
| 15503 | #include <sys/param.h> |
| 15504 | +#include <gnu/option-groups.h> |
| 15505 | |
| 15506 | #ifndef STRING_TYPE |
| 15507 | # define STRING_TYPE char |
| 15508 | @@ -260,7 +261,11 @@ int |
| 15509 | STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) |
| 15510 | { |
| 15511 | struct __locale_data *current = l->__locales[LC_COLLATE]; |
| 15512 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15513 | uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; |
| 15514 | +#else |
| 15515 | + const uint_fast32_t nrules = 0; |
| 15516 | +#endif |
| 15517 | /* We don't assign the following values right away since it might be |
| 15518 | unnecessary in case there are no rules. */ |
| 15519 | const unsigned char *rulesets; |
| 15520 | diff --git a/string/strerror_l.c b/string/strerror_l.c |
| 15521 | index 2ed78b5..6584813 100644 |
| 15522 | --- a/string/strerror_l.c |
| 15523 | +++ b/string/strerror_l.c |
| 15524 | @@ -21,6 +21,7 @@ |
| 15525 | #include <stdlib.h> |
| 15526 | #include <string.h> |
| 15527 | #include <sys/param.h> |
| 15528 | +#include <gnu/option-groups.h> |
| 15529 | |
| 15530 | |
| 15531 | static __thread char *last_value; |
| 15532 | @@ -29,10 +30,14 @@ static __thread char *last_value; |
| 15533 | static const char * |
| 15534 | translate (const char *str, locale_t loc) |
| 15535 | { |
| 15536 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15537 | locale_t oldloc = __uselocale (loc); |
| 15538 | const char *res = _(str); |
| 15539 | __uselocale (oldloc); |
| 15540 | return res; |
| 15541 | +#else |
| 15542 | + return str; |
| 15543 | +#endif |
| 15544 | } |
| 15545 | |
| 15546 | |
| 15547 | diff --git a/string/strxfrm_l.c b/string/strxfrm_l.c |
| 15548 | index 8b61ea2..41fdc22 100644 |
| 15549 | --- a/string/strxfrm_l.c |
| 15550 | +++ b/string/strxfrm_l.c |
| 15551 | @@ -24,6 +24,7 @@ |
| 15552 | #include <stdlib.h> |
| 15553 | #include <string.h> |
| 15554 | #include <sys/param.h> |
| 15555 | +#include <gnu/option-groups.h> |
| 15556 | |
| 15557 | #ifndef STRING_TYPE |
| 15558 | # define STRING_TYPE char |
| 15559 | @@ -669,7 +670,11 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l) |
| 15560 | { |
| 15561 | locale_data_t l_data; |
| 15562 | struct __locale_data *current = l->__locales[LC_COLLATE]; |
| 15563 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15564 | l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; |
| 15565 | +#else |
| 15566 | + l_data.nrules = 0; |
| 15567 | +#endif |
| 15568 | |
| 15569 | /* Handle byte comparison case. */ |
| 15570 | if (l_data.nrules == 0) |
| 15571 | diff --git a/string/test-strcmp.c b/string/test-strcmp.c |
| 15572 | index dc4ba6f..a978656 100644 |
| 15573 | --- a/string/test-strcmp.c |
| 15574 | +++ b/string/test-strcmp.c |
| 15575 | @@ -329,34 +329,6 @@ check (void) |
| 15576 | FOR_EACH_IMPL (impl, 0) |
| 15577 | check_result (impl, s1 + i1, s2 + i2, exp_result); |
| 15578 | } |
| 15579 | - |
| 15580 | - /* Test cases where there are multiple zero bytes after the first. */ |
| 15581 | - |
| 15582 | - for (size_t i = 0; i < 16 + 1; i++) |
| 15583 | - { |
| 15584 | - s1[i] = 0x00; |
| 15585 | - s2[i] = 0x00; |
| 15586 | - } |
| 15587 | - |
| 15588 | - for (size_t i = 0; i < 16; i++) |
| 15589 | - { |
| 15590 | - int exp_result; |
| 15591 | - |
| 15592 | - for (int val = 0x01; val < 0x100; val++) |
| 15593 | - { |
| 15594 | - for (size_t j = 0; j < i; j++) |
| 15595 | - { |
| 15596 | - s1[j] = val; |
| 15597 | - s2[j] = val; |
| 15598 | - } |
| 15599 | - |
| 15600 | - s2[i] = val; |
| 15601 | - |
| 15602 | - exp_result = SIMPLE_STRCMP (s1, s2); |
| 15603 | - FOR_EACH_IMPL (impl, 0) |
| 15604 | - check_result (impl, s1, s2, exp_result); |
| 15605 | - } |
| 15606 | - } |
| 15607 | } |
| 15608 | |
| 15609 | |
| 15610 | diff --git a/string/tst-strxfrm.c b/string/tst-strxfrm.c |
| 15611 | index f48cfc0..c3a51f9 100644 |
| 15612 | --- a/string/tst-strxfrm.c |
| 15613 | +++ b/string/tst-strxfrm.c |
| 15614 | @@ -3,6 +3,7 @@ |
| 15615 | #include <stdio.h> |
| 15616 | #include <stdlib.h> |
| 15617 | #include <string.h> |
| 15618 | +#include <gnu/option-groups.h> |
| 15619 | |
| 15620 | |
| 15621 | char const string[] = ""; |
| 15622 | @@ -64,8 +65,10 @@ do_test (void) |
| 15623 | int result = 0; |
| 15624 | |
| 15625 | result |= test ("C"); |
| 15626 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15627 | result |= test ("en_US.ISO-8859-1"); |
| 15628 | result |= test ("de_DE.UTF-8"); |
| 15629 | +#endif |
| 15630 | |
| 15631 | return result; |
| 15632 | } |
| 15633 | diff --git a/string/tst-strxfrm2.c b/string/tst-strxfrm2.c |
| 15634 | index d5a1115..19c7f30 100644 |
| 15635 | --- a/string/tst-strxfrm2.c |
| 15636 | +++ b/string/tst-strxfrm2.c |
| 15637 | @@ -1,6 +1,7 @@ |
| 15638 | #include <locale.h> |
| 15639 | #include <stdio.h> |
| 15640 | #include <string.h> |
| 15641 | +#include <gnu/option-groups.h> |
| 15642 | |
| 15643 | static int |
| 15644 | do_test (void) |
| 15645 | @@ -38,6 +39,7 @@ do_test (void) |
| 15646 | res = 1; |
| 15647 | } |
| 15648 | |
| 15649 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 15650 | if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) |
| 15651 | { |
| 15652 | puts ("setlocale failed"); |
| 15653 | @@ -75,6 +77,7 @@ do_test (void) |
| 15654 | res = 1; |
| 15655 | } |
| 15656 | } |
| 15657 | +#endif |
| 15658 | |
| 15659 | return res; |
| 15660 | } |
| 15661 | diff --git a/sunrpc/Makefile b/sunrpc/Makefile |
| 15662 | index 60caa0a..5bc70ab 100644 |
| 15663 | --- a/sunrpc/Makefile |
| 15664 | +++ b/sunrpc/Makefile |
| 15665 | @@ -18,6 +18,8 @@ |
| 15666 | # |
| 15667 | # Sub-makefile for sunrpc portion of the library. |
| 15668 | # |
| 15669 | +include ../option-groups.mak |
| 15670 | + |
| 15671 | subdir := sunrpc |
| 15672 | |
| 15673 | include ../Makeconfig |
| 15674 | @@ -55,7 +57,6 @@ headers-in-tirpc = $(addprefix rpc/,auth.h auth_unix.h clnt.h pmap_clnt.h \ |
| 15675 | headers-not-in-tirpc = $(addprefix rpc/,key_prot.h rpc_des.h) \ |
| 15676 | $(rpcsvc:%=rpcsvc/%) rpcsvc/bootparam.h |
| 15677 | headers = rpc/netdb.h |
| 15678 | -install-others = $(inst_sysconfdir)/rpc |
| 15679 | generated += $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \ |
| 15680 | $(rpcsvc:%.x=rpcsvc/%.stmp) rpcgen |
| 15681 | generated-dirs += rpcsvc |
| 15682 | @@ -65,20 +66,28 @@ headers += $(headers-in-tirpc) $(headers-not-in-tirpc) |
| 15683 | endif |
| 15684 | |
| 15685 | ifeq ($(build-shared),yes) |
| 15686 | -need-export-routines := auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ |
| 15687 | +need-export-routines-$(OPTION_EGLIBC_SUNRPC) := \ |
| 15688 | + auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ |
| 15689 | clnt_udp get_myaddr key_call netname pm_getport \ |
| 15690 | - rpc_thread svc svc_tcp svc_udp xcrypt xdr_array xdr \ |
| 15691 | + rpc_thread svc svc_tcp svc_udp xdr_array xdr \ |
| 15692 | xdr_intXX_t xdr_mem xdr_ref xdr_sizeof xdr_stdio \ |
| 15693 | svc_run |
| 15694 | +need-export-routines-y += xcrypt |
| 15695 | +need-export-routines := $(need-export-routines-y) |
| 15696 | |
| 15697 | -routines := auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ |
| 15698 | +routines-$(OPTION_EGLIBC_SUNRPC) := \ |
| 15699 | + auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ |
| 15700 | rpc_dtable getrpcport pmap_clnt pm_getmaps pmap_prot pmap_prot2 \ |
| 15701 | pmap_rmt rpc_prot rpc_common rpc_cmsg svc_auth svc_authux svc_raw \ |
| 15702 | svc_simple xdr_float xdr_rec publickey authdes_prot \ |
| 15703 | - des_crypt des_impl des_soft key_prot openchild rtime svcauth_des \ |
| 15704 | + key_prot openchild rtime svcauth_des \ |
| 15705 | getrpcent getrpcbyname getrpcbynumber \ |
| 15706 | getrpcent_r getrpcbyname_r getrpcbynumber_r \ |
| 15707 | - clnt_unix svc_unix create_xid $(need-export-routines) |
| 15708 | + clnt_unix svc_unix create_xid |
| 15709 | + |
| 15710 | +# xdecrypt is also used by nss/nss_files/files-key.c. |
| 15711 | +routines-y += des_crypt des_impl des_soft $(need-export-routines) |
| 15712 | + |
| 15713 | ifneq ($(link-obsolete-rpc),yes) |
| 15714 | # We only add the RPC for compatibility to libc.so. |
| 15715 | shared-only-routines = $(routines) |
| 15716 | @@ -87,25 +96,28 @@ endif |
| 15717 | |
| 15718 | # We do not build rpcinfo anymore. It is not needed for a bootstrap |
| 15719 | # and not wanted on complete systems. |
| 15720 | -# others := rpcinfo |
| 15721 | -# install-sbin := rpcinfo |
| 15722 | -install-bin := rpcgen |
| 15723 | +# others-$(OPTION_EGLIBC_SUNRPC) += rpcinfo |
| 15724 | +# install-sbin-$(OPTION_EGLIBC_SUNRPC) += rpcinfo |
| 15725 | +install-bin-$(OPTION_EGLIBC_SUNRPC) += rpcgen |
| 15726 | rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ |
| 15727 | rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \ |
| 15728 | rpc_tblout.o rpc_sample.o |
| 15729 | -extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) |
| 15730 | -others += rpcgen |
| 15731 | +extra-objs-$(OPTION_EGLIBC_SUNRPC) = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) |
| 15732 | +others-$(OPTION_EGLIBC_SUNRPC) += rpcgen |
| 15733 | + |
| 15734 | +install-others-$(OPTION_EGLIBC_SUNRPC) += $(inst_sysconfdir)/rpc |
| 15735 | |
| 15736 | -tests = tst-xdrmem tst-xdrmem2 test-rpcent |
| 15737 | -xtests := tst-getmyaddr |
| 15738 | +tests-$(OPTION_EGLIBC_SUNRPC) = tst-xdrmem tst-xdrmem2 test-rpcent |
| 15739 | +xtests-$(OPTION_EGLIBC_SUNRPC) := tst-getmyaddr |
| 15740 | |
| 15741 | ifeq ($(have-thread-library),yes) |
| 15742 | -xtests += thrsvc |
| 15743 | +xtests-$(OPTION_EGLIBC_SUNRPC) += thrsvc |
| 15744 | endif |
| 15745 | |
| 15746 | headers += $(rpcsvc:%.x=rpcsvc/%.h) |
| 15747 | -extra-libs := librpcsvc |
| 15748 | -extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass. |
| 15749 | +extra-libs-$(OPTION_EGLIBC_SUNRPC) += librpcsvc |
| 15750 | +# Make it in `others' pass, not `lib' pass. |
| 15751 | +extra-libs-others-y += $(extra-libs-y) |
| 15752 | librpcsvc-routines = $(rpcsvc:%.x=x%) |
| 15753 | librpcsvc-inhibit-o = .os # Build no shared rpcsvc library. |
| 15754 | omit-deps = $(librpcsvc-routines) |
| 15755 | diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile |
| 15756 | index 17c129b..543791a 100644 |
| 15757 | --- a/sysdeps/arm/Makefile |
| 15758 | +++ b/sysdeps/arm/Makefile |
| 15759 | @@ -37,10 +37,13 @@ ifeq ($(subdir),csu) |
| 15760 | # get offset to rtld_global._dl_hwcap |
| 15761 | gen-as-const-headers += rtld-global-offsets.sym tlsdesc.sym |
| 15762 | aeabi_constants = aeabi_lcsts aeabi_sighandlers aeabi_math |
| 15763 | -aeabi_routines = aeabi_assert aeabi_localeconv aeabi_errno_addr \ |
| 15764 | +aeabi_routines = aeabi_assert aeabi_errno_addr \ |
| 15765 | aeabi_mb_cur_max aeabi_atexit aeabi_memclr aeabi_memcpy \ |
| 15766 | aeabi_memmove aeabi_memset \ |
| 15767 | aeabi_read_tp libc-aeabi_read_tp |
| 15768 | +ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) |
| 15769 | +aeabi_routines += aeabi_localeconv |
| 15770 | +endif |
| 15771 | |
| 15772 | sysdep_routines += $(aeabi_constants) $(aeabi_routines) |
| 15773 | static-only-routines += $(aeabi_constants) aeabi_read_tp |
| 15774 | diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
| 15775 | index 7a0fe8d..a3e2c0a 100644 |
| 15776 | --- a/sysdeps/generic/ldsodefs.h |
| 15777 | +++ b/sysdeps/generic/ldsodefs.h |
| 15778 | @@ -435,6 +435,12 @@ extern struct rtld_global _rtld_global __rtld_global_attribute__; |
| 15779 | # undef __rtld_global_attribute__ |
| 15780 | #endif |
| 15781 | |
| 15782 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 15783 | +# define GLRO_dl_debug_mask GLRO(dl_debug_mask) |
| 15784 | +#else |
| 15785 | +# define GLRO_dl_debug_mask 0 |
| 15786 | +#endif |
| 15787 | + |
| 15788 | #ifndef SHARED |
| 15789 | # define GLRO(name) _##name |
| 15790 | #else |
| 15791 | @@ -447,8 +453,10 @@ struct rtld_global_ro |
| 15792 | { |
| 15793 | #endif |
| 15794 | |
| 15795 | +#if __OPTION_EGLIBC_RTLD_DEBUG |
| 15796 | /* If nonzero the appropriate debug information is printed. */ |
| 15797 | EXTERN int _dl_debug_mask; |
| 15798 | +#endif |
| 15799 | #define DL_DEBUG_LIBS (1 << 0) |
| 15800 | #define DL_DEBUG_IMPCALLS (1 << 1) |
| 15801 | #define DL_DEBUG_BINDINGS (1 << 2) |
| 15802 | diff --git a/sysdeps/gnu/Makefile b/sysdeps/gnu/Makefile |
| 15803 | index ea68037..3175cc3 100644 |
| 15804 | --- a/sysdeps/gnu/Makefile |
| 15805 | +++ b/sysdeps/gnu/Makefile |
| 15806 | @@ -59,7 +59,8 @@ $(foreach o,$(object-suffixes) $(object-suffixes:=.d),\ |
| 15807 | endif |
| 15808 | |
| 15809 | ifeq ($(subdir),login) |
| 15810 | -sysdep_routines += setutxent getutxent endutxent getutxid getutxline \ |
| 15811 | +sysdep_routines-$(OPTION_EGLIBC_UTMPX) \ |
| 15812 | + += setutxent getutxent endutxent getutxid getutxline \ |
| 15813 | pututxline utmpxname updwtmpx getutmpx getutmp |
| 15814 | |
| 15815 | sysdep_headers += utmpx.h bits/utmpx.h |
| 15816 | diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile |
| 15817 | index 222122d..4509357 100644 |
| 15818 | --- a/sysdeps/ieee754/ldbl-opt/Makefile |
| 15819 | +++ b/sysdeps/ieee754/ldbl-opt/Makefile |
| 15820 | @@ -11,19 +11,18 @@ libm-routines += s_nexttowardfd |
| 15821 | routines += math_ldbl_opt nldbl-compat |
| 15822 | |
| 15823 | extra-libs += libnldbl |
| 15824 | -libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \ |
| 15825 | +libnldbl-calls = asprintf dprintf fprintf fscanf iovfscanf \ |
| 15826 | obstack_printf obstack_vprintf printf scanf snprintf \ |
| 15827 | - sprintf sscanf swprintf swscanf vasprintf vdprintf vfprintf \ |
| 15828 | - vfscanf vfwprintf vfwscanf vprintf vscanf vsnprintf \ |
| 15829 | - vsprintf vsscanf vswprintf vswscanf vwprintf vwscanf \ |
| 15830 | - wprintf wscanf printf_fp printf_size \ |
| 15831 | - fprintf_chk fwprintf_chk printf_chk snprintf_chk sprintf_chk \ |
| 15832 | - swprintf_chk vfprintf_chk vfwprintf_chk vprintf_chk \ |
| 15833 | - vsnprintf_chk vsprintf_chk vswprintf_chk vwprintf_chk \ |
| 15834 | - wprintf_chk asprintf_chk vasprintf_chk dprintf_chk \ |
| 15835 | + sprintf sscanf vasprintf vdprintf vfprintf \ |
| 15836 | + vfscanf vprintf vscanf vsnprintf \ |
| 15837 | + vsprintf vsscanf \ |
| 15838 | + printf_fp printf_size \ |
| 15839 | + fprintf_chk printf_chk snprintf_chk sprintf_chk \ |
| 15840 | + vfprintf_chk vprintf_chk \ |
| 15841 | + vsnprintf_chk vsprintf_chk \ |
| 15842 | + asprintf_chk vasprintf_chk dprintf_chk \ |
| 15843 | vdprintf_chk obstack_printf_chk obstack_vprintf_chk \ |
| 15844 | syslog syslog_chk vsyslog vsyslog_chk \ |
| 15845 | - strfmon strfmon_l \ |
| 15846 | strtold strtold_l strtoldint wcstold wcstold_l wcstoldint \ |
| 15847 | qecvt qfcvt qgcvt qecvt_r qfcvt_r \ |
| 15848 | isinf isnan finite signbit scalb log2 lgamma_r ceil \ |
| 15849 | @@ -38,9 +37,15 @@ libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \ |
| 15850 | casinh cexp clog cproj csin csinh csqrt ctan ctanh cpow \ |
| 15851 | cabs carg cimag creal clog10 \ |
| 15852 | isoc99_scanf isoc99_fscanf isoc99_sscanf \ |
| 15853 | - isoc99_vscanf isoc99_vfscanf isoc99_vsscanf \ |
| 15854 | + isoc99_vscanf isoc99_vfscanf isoc99_vsscanf |
| 15855 | +libnldbl-calls-$(OPTION_EGLIBC_LOCALE_CODE) += strfmon strfmon_l |
| 15856 | +libnldbl-calls-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += fwprintf fwscanf \ |
| 15857 | + swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf \ |
| 15858 | + vwprintf vwscanf wprintf wscanf fwprintf_chk swprintf_chk \ |
| 15859 | + vfwprintf_chk vswprintf_chk vwprintf_chk wprintf_chk \ |
| 15860 | isoc99_wscanf isoc99_fwscanf isoc99_swscanf \ |
| 15861 | isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf |
| 15862 | +libnldbl-calls += $(libnldbl-calls-y) |
| 15863 | libnldbl-routines = $(libnldbl-calls:%=nldbl-%) |
| 15864 | libnldbl-inhibit-o = $(object-suffixes) |
| 15865 | libnldbl-static-only-routines = $(libnldbl-routines) |
| 15866 | diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c |
| 15867 | index 0198886..55501cd 100644 |
| 15868 | --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c |
| 15869 | +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c |
| 15870 | @@ -26,6 +26,7 @@ |
| 15871 | #include <locale/localeinfo.h> |
| 15872 | #include <sys/syslog.h> |
| 15873 | #include <bits/libc-lock.h> |
| 15874 | +#include <gnu/option-groups.h> |
| 15875 | |
| 15876 | #include "nldbl-compat.h" |
| 15877 | |
| 15878 | @@ -33,20 +34,14 @@ libc_hidden_proto (__nldbl_vfprintf) |
| 15879 | libc_hidden_proto (__nldbl_vsscanf) |
| 15880 | libc_hidden_proto (__nldbl_vsprintf) |
| 15881 | libc_hidden_proto (__nldbl_vfscanf) |
| 15882 | -libc_hidden_proto (__nldbl_vfwscanf) |
| 15883 | libc_hidden_proto (__nldbl_vdprintf) |
| 15884 | -libc_hidden_proto (__nldbl_vswscanf) |
| 15885 | -libc_hidden_proto (__nldbl_vfwprintf) |
| 15886 | -libc_hidden_proto (__nldbl_vswprintf) |
| 15887 | libc_hidden_proto (__nldbl_vsnprintf) |
| 15888 | libc_hidden_proto (__nldbl_vasprintf) |
| 15889 | libc_hidden_proto (__nldbl_obstack_vprintf) |
| 15890 | -libc_hidden_proto (__nldbl___vfwprintf_chk) |
| 15891 | libc_hidden_proto (__nldbl___vsnprintf_chk) |
| 15892 | libc_hidden_proto (__nldbl___vfprintf_chk) |
| 15893 | libc_hidden_proto (__nldbl___vsyslog_chk) |
| 15894 | libc_hidden_proto (__nldbl___vsprintf_chk) |
| 15895 | -libc_hidden_proto (__nldbl___vswprintf_chk) |
| 15896 | libc_hidden_proto (__nldbl___vasprintf_chk) |
| 15897 | libc_hidden_proto (__nldbl___vdprintf_chk) |
| 15898 | libc_hidden_proto (__nldbl___obstack_vprintf_chk) |
| 15899 | @@ -54,8 +49,17 @@ libc_hidden_proto (__nldbl___vstrfmon) |
| 15900 | libc_hidden_proto (__nldbl___vstrfmon_l) |
| 15901 | libc_hidden_proto (__nldbl___isoc99_vsscanf) |
| 15902 | libc_hidden_proto (__nldbl___isoc99_vfscanf) |
| 15903 | + |
| 15904 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 15905 | +libc_hidden_proto (__nldbl_vfwscanf) |
| 15906 | +libc_hidden_proto (__nldbl_vswscanf) |
| 15907 | +libc_hidden_proto (__nldbl_vfwprintf) |
| 15908 | +libc_hidden_proto (__nldbl_vswprintf) |
| 15909 | +libc_hidden_proto (__nldbl___vfwprintf_chk) |
| 15910 | +libc_hidden_proto (__nldbl___vswprintf_chk) |
| 15911 | libc_hidden_proto (__nldbl___isoc99_vswscanf) |
| 15912 | libc_hidden_proto (__nldbl___isoc99_vfwscanf) |
| 15913 | +#endif |
| 15914 | |
| 15915 | static void |
| 15916 | __nldbl_cleanup (void *arg) |
| 15917 | @@ -117,6 +121,7 @@ __nldbl_fprintf (FILE *stream, const char *fmt, ...) |
| 15918 | } |
| 15919 | weak_alias (__nldbl_fprintf, __nldbl__IO_fprintf) |
| 15920 | |
| 15921 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 15922 | int |
| 15923 | attribute_compat_text_section weak_function |
| 15924 | __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...) |
| 15925 | @@ -130,6 +135,7 @@ __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...) |
| 15926 | |
| 15927 | return done; |
| 15928 | } |
| 15929 | +#endif |
| 15930 | |
| 15931 | int |
| 15932 | attribute_compat_text_section |
| 15933 | @@ -226,6 +232,7 @@ __nldbl_snprintf (char *s, size_t maxlen, const char *fmt, ...) |
| 15934 | return done; |
| 15935 | } |
| 15936 | |
| 15937 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 15938 | int |
| 15939 | attribute_compat_text_section |
| 15940 | __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...) |
| 15941 | @@ -239,6 +246,7 @@ __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...) |
| 15942 | |
| 15943 | return done; |
| 15944 | } |
| 15945 | +#endif |
| 15946 | |
| 15947 | int |
| 15948 | attribute_compat_text_section weak_function |
| 15949 | @@ -264,6 +272,7 @@ __nldbl_vdprintf (int d, const char *fmt, va_list arg) |
| 15950 | } |
| 15951 | libc_hidden_def (__nldbl_vdprintf) |
| 15952 | |
| 15953 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 15954 | int |
| 15955 | attribute_compat_text_section weak_function |
| 15956 | __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap) |
| 15957 | @@ -275,6 +284,7 @@ __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap) |
| 15958 | return res; |
| 15959 | } |
| 15960 | libc_hidden_def (__nldbl_vfwprintf) |
| 15961 | +#endif |
| 15962 | |
| 15963 | int |
| 15964 | attribute_compat_text_section |
| 15965 | @@ -297,6 +307,7 @@ __nldbl_vsnprintf (char *string, size_t maxlen, const char *fmt, |
| 15966 | libc_hidden_def (__nldbl_vsnprintf) |
| 15967 | weak_alias (__nldbl_vsnprintf, __nldbl___vsnprintf) |
| 15968 | |
| 15969 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 15970 | int |
| 15971 | attribute_compat_text_section weak_function |
| 15972 | __nldbl_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *fmt, |
| 15973 | @@ -330,6 +341,7 @@ __nldbl_wprintf (const wchar_t *fmt, ...) |
| 15974 | |
| 15975 | return done; |
| 15976 | } |
| 15977 | +#endif |
| 15978 | |
| 15979 | int |
| 15980 | attribute_compat_text_section |
| 15981 | @@ -419,6 +431,7 @@ __nldbl_scanf (const char *fmt, ...) |
| 15982 | return done; |
| 15983 | } |
| 15984 | |
| 15985 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 15986 | int |
| 15987 | attribute_compat_text_section |
| 15988 | __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) |
| 15989 | @@ -491,6 +504,7 @@ __nldbl_wscanf (const wchar_t *fmt, ...) |
| 15990 | |
| 15991 | return done; |
| 15992 | } |
| 15993 | +#endif |
| 15994 | |
| 15995 | int |
| 15996 | attribute_compat_text_section |
| 15997 | @@ -506,6 +520,7 @@ __nldbl___fprintf_chk (FILE *stream, int flag, const char *fmt, ...) |
| 15998 | return done; |
| 15999 | } |
| 16000 | |
| 16001 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16002 | int |
| 16003 | attribute_compat_text_section |
| 16004 | __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...) |
| 16005 | @@ -519,6 +534,7 @@ __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...) |
| 16006 | |
| 16007 | return done; |
| 16008 | } |
| 16009 | +#endif |
| 16010 | |
| 16011 | int |
| 16012 | attribute_compat_text_section |
| 16013 | @@ -563,6 +579,7 @@ __nldbl___sprintf_chk (char *s, int flag, size_t slen, const char *fmt, ...) |
| 16014 | return done; |
| 16015 | } |
| 16016 | |
| 16017 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16018 | int |
| 16019 | attribute_compat_text_section |
| 16020 | __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen, |
| 16021 | @@ -577,6 +594,7 @@ __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen, |
| 16022 | |
| 16023 | return done; |
| 16024 | } |
| 16025 | +#endif |
| 16026 | |
| 16027 | int |
| 16028 | attribute_compat_text_section |
| 16029 | @@ -590,6 +608,7 @@ __nldbl___vfprintf_chk (FILE *s, int flag, const char *fmt, va_list ap) |
| 16030 | } |
| 16031 | libc_hidden_def (__nldbl___vfprintf_chk) |
| 16032 | |
| 16033 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16034 | int |
| 16035 | attribute_compat_text_section |
| 16036 | __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap) |
| 16037 | @@ -601,6 +620,7 @@ __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap) |
| 16038 | return res; |
| 16039 | } |
| 16040 | libc_hidden_def (__nldbl___vfwprintf_chk) |
| 16041 | +#endif |
| 16042 | |
| 16043 | int |
| 16044 | attribute_compat_text_section |
| 16045 | @@ -635,6 +655,7 @@ __nldbl___vsprintf_chk (char *string, int flag, size_t slen, const char *fmt, |
| 16046 | } |
| 16047 | libc_hidden_def (__nldbl___vsprintf_chk) |
| 16048 | |
| 16049 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16050 | int |
| 16051 | attribute_compat_text_section |
| 16052 | __nldbl___vswprintf_chk (wchar_t *string, size_t maxlen, int flag, size_t slen, |
| 16053 | @@ -668,6 +689,7 @@ __nldbl___wprintf_chk (int flag, const wchar_t *fmt, ...) |
| 16054 | |
| 16055 | return done; |
| 16056 | } |
| 16057 | +#endif |
| 16058 | |
| 16059 | int |
| 16060 | attribute_compat_text_section |
| 16061 | @@ -775,6 +797,7 @@ __nldbl___printf_fp (FILE *fp, const struct printf_info *info, |
| 16062 | return ___printf_fp (fp, &info_no_ldbl, args); |
| 16063 | } |
| 16064 | |
| 16065 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 16066 | ssize_t |
| 16067 | attribute_compat_text_section |
| 16068 | __nldbl_strfmon (char *s, size_t maxsize, const char *format, ...) |
| 16069 | @@ -829,6 +852,7 @@ __nldbl___vstrfmon_l (char *s, size_t maxsize, __locale_t loc, |
| 16070 | return res; |
| 16071 | } |
| 16072 | libc_hidden_def (__nldbl___vstrfmon_l) |
| 16073 | +#endif |
| 16074 | |
| 16075 | void |
| 16076 | attribute_compat_text_section |
| 16077 | @@ -941,6 +965,7 @@ __nldbl___isoc99_scanf (const char *fmt, ...) |
| 16078 | return done; |
| 16079 | } |
| 16080 | |
| 16081 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16082 | int |
| 16083 | attribute_compat_text_section |
| 16084 | __nldbl___isoc99_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) |
| 16085 | @@ -1014,6 +1039,7 @@ __nldbl___isoc99_wscanf (const wchar_t *fmt, ...) |
| 16086 | |
| 16087 | return done; |
| 16088 | } |
| 16089 | +#endif |
| 16090 | |
| 16091 | #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0) |
| 16092 | compat_symbol (libc, __nldbl__IO_printf, _IO_printf, GLIBC_2_0); |
| 16093 | @@ -1057,6 +1083,7 @@ compat_symbol (libc, __nldbl_printf_size, printf_size, GLIBC_2_1); |
| 16094 | compat_symbol (libc, __nldbl___strfmon_l, __strfmon_l, GLIBC_2_1); |
| 16095 | #endif |
| 16096 | #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_2) |
| 16097 | +# if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16098 | compat_symbol (libc, __nldbl_swprintf, swprintf, GLIBC_2_2); |
| 16099 | compat_symbol (libc, __nldbl_vwprintf, vwprintf, GLIBC_2_2); |
| 16100 | compat_symbol (libc, __nldbl_wprintf, wprintf, GLIBC_2_2); |
| 16101 | @@ -1069,6 +1096,7 @@ compat_symbol (libc, __nldbl_vfwscanf, vfwscanf, GLIBC_2_2); |
| 16102 | compat_symbol (libc, __nldbl_vswscanf, vswscanf, GLIBC_2_2); |
| 16103 | compat_symbol (libc, __nldbl_vwscanf, vwscanf, GLIBC_2_2); |
| 16104 | compat_symbol (libc, __nldbl_wscanf, wscanf, GLIBC_2_2); |
| 16105 | +# endif |
| 16106 | #endif |
| 16107 | #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_3) |
| 16108 | compat_symbol (libc, __nldbl_strfmon_l, strfmon_l, GLIBC_2_3); |
| 16109 | diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h |
| 16110 | index 0d2c8af..f4cea50 100644 |
| 16111 | --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h |
| 16112 | +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h |
| 16113 | @@ -30,6 +30,7 @@ |
| 16114 | #include <math.h> |
| 16115 | #include <monetary.h> |
| 16116 | #include <sys/syslog.h> |
| 16117 | +#include <gnu/option-groups.h> |
| 16118 | |
| 16119 | |
| 16120 | /* Declare the __nldbl_NAME function the wrappers call that's in libc.so. */ |
| 16121 | @@ -37,19 +38,15 @@ |
| 16122 | |
| 16123 | NLDBL_DECL (_IO_vfscanf); |
| 16124 | NLDBL_DECL (vfscanf); |
| 16125 | -NLDBL_DECL (vfwscanf); |
| 16126 | NLDBL_DECL (obstack_vprintf); |
| 16127 | NLDBL_DECL (vasprintf); |
| 16128 | NLDBL_DECL (dprintf); |
| 16129 | NLDBL_DECL (vdprintf); |
| 16130 | NLDBL_DECL (fprintf); |
| 16131 | NLDBL_DECL (vfprintf); |
| 16132 | -NLDBL_DECL (vfwprintf); |
| 16133 | NLDBL_DECL (vsnprintf); |
| 16134 | NLDBL_DECL (vsprintf); |
| 16135 | NLDBL_DECL (vsscanf); |
| 16136 | -NLDBL_DECL (vswprintf); |
| 16137 | -NLDBL_DECL (vswscanf); |
| 16138 | NLDBL_DECL (__asprintf); |
| 16139 | NLDBL_DECL (asprintf); |
| 16140 | NLDBL_DECL (__printf_fp); |
| 16141 | @@ -66,12 +63,18 @@ NLDBL_DECL (__isoc99_sscanf); |
| 16142 | NLDBL_DECL (__isoc99_vscanf); |
| 16143 | NLDBL_DECL (__isoc99_vfscanf); |
| 16144 | NLDBL_DECL (__isoc99_vsscanf); |
| 16145 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16146 | +NLDBL_DECL (vfwscanf); |
| 16147 | +NLDBL_DECL (vfwprintf); |
| 16148 | +NLDBL_DECL (vswprintf); |
| 16149 | +NLDBL_DECL (vswscanf); |
| 16150 | NLDBL_DECL (__isoc99_wscanf); |
| 16151 | NLDBL_DECL (__isoc99_fwscanf); |
| 16152 | NLDBL_DECL (__isoc99_swscanf); |
| 16153 | NLDBL_DECL (__isoc99_vwscanf); |
| 16154 | NLDBL_DECL (__isoc99_vfwscanf); |
| 16155 | NLDBL_DECL (__isoc99_vswscanf); |
| 16156 | +#endif |
| 16157 | |
| 16158 | /* This one does not exist in the normal interface, only |
| 16159 | __nldbl___vstrfmon really exists. */ |
| 16160 | @@ -82,22 +85,23 @@ extern ssize_t __nldbl___vstrfmon (char *, size_t, const char *, va_list) |
| 16161 | since we don't compile with _FORTIFY_SOURCE. */ |
| 16162 | extern int __nldbl___vfprintf_chk (FILE *__restrict, int, |
| 16163 | const char *__restrict, _G_va_list); |
| 16164 | -extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, |
| 16165 | - const wchar_t *__restrict, __gnuc_va_list); |
| 16166 | extern int __nldbl___vsprintf_chk (char *__restrict, int, size_t, |
| 16167 | const char *__restrict, _G_va_list) __THROW; |
| 16168 | extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t, |
| 16169 | const char *__restrict, _G_va_list) |
| 16170 | __THROW; |
| 16171 | -extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, |
| 16172 | - const wchar_t *__restrict, __gnuc_va_list) |
| 16173 | - __THROW; |
| 16174 | extern int __nldbl___vasprintf_chk (char **, int, const char *, _G_va_list) |
| 16175 | __THROW; |
| 16176 | extern int __nldbl___vdprintf_chk (int, int, const char *, _G_va_list); |
| 16177 | extern int __nldbl___obstack_vprintf_chk (struct obstack *, int, const char *, |
| 16178 | _G_va_list) __THROW; |
| 16179 | extern void __nldbl___vsyslog_chk (int, int, const char *, va_list); |
| 16180 | - |
| 16181 | +#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO |
| 16182 | +extern int __nldbl___vfwprintf_chk (FILE *__restrict, int, |
| 16183 | + const wchar_t *__restrict, __gnuc_va_list); |
| 16184 | +extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t, |
| 16185 | + const wchar_t *__restrict, __gnuc_va_list) |
| 16186 | + __THROW; |
| 16187 | +#endif |
| 16188 | |
| 16189 | #endif /* __NLDBL_COMPAT_H */ |
| 16190 | diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile |
| 16191 | index e9339a3..782009b 100644 |
| 16192 | --- a/sysdeps/nptl/Makefile |
| 16193 | +++ b/sysdeps/nptl/Makefile |
| 16194 | @@ -18,6 +18,9 @@ |
| 16195 | |
| 16196 | ifeq ($(subdir),nptl) |
| 16197 | libpthread-sysdep_routines += errno-loc |
| 16198 | +ifeq ($(OPTION_EGLIBC_BIG_MACROS),n) |
| 16199 | +sysdep_routines += small-macros-fns |
| 16200 | +endif |
| 16201 | endif |
| 16202 | |
| 16203 | ifeq ($(subdir),rt) |
| 16204 | diff --git a/sysdeps/nptl/bits/libc-lock.h b/sysdeps/nptl/bits/libc-lock.h |
| 16205 | index 5599cf1..b839378 100644 |
| 16206 | --- a/sysdeps/nptl/bits/libc-lock.h |
| 16207 | +++ b/sysdeps/nptl/bits/libc-lock.h |
| 16208 | @@ -24,6 +24,14 @@ |
| 16209 | #include <stddef.h> |
| 16210 | |
| 16211 | |
| 16212 | +#ifdef _LIBC |
| 16213 | +# include <lowlevellock.h> |
| 16214 | +# include <tls.h> |
| 16215 | +# include <pthread-functions.h> |
| 16216 | +# include <errno.h> /* For EBUSY. */ |
| 16217 | +# include <gnu/option-groups.h> /* For __OPTION_EGLIBC_BIG_MACROS. */ |
| 16218 | +#endif |
| 16219 | + |
| 16220 | /* Mutex type. */ |
| 16221 | #if defined _LIBC || defined _IO_MTSAFE_IO |
| 16222 | # if (!IS_IN (libc) && !IS_IN (libpthread)) || !defined _LIBC |
| 16223 | @@ -87,6 +95,15 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; |
| 16224 | |
| 16225 | /* Lock the recursive named lock variable. */ |
| 16226 | #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) |
| 16227 | +# if __OPTION_EGLIBC_BIG_MACROS != 1 |
| 16228 | +/* EGLIBC: Declare wrapper function for a big macro if either |
| 16229 | + !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from |
| 16230 | + small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ |
| 16231 | +extern void __libc_lock_lock_recursive_fn (__libc_lock_recursive_t *); |
| 16232 | +libc_hidden_proto (__libc_lock_lock_recursive_fn); |
| 16233 | +# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ |
| 16234 | +# if __OPTION_EGLIBC_BIG_MACROS |
| 16235 | + |
| 16236 | # define __libc_lock_lock_recursive(NAME) \ |
| 16237 | do { \ |
| 16238 | void *self = THREAD_SELF; \ |
| 16239 | @@ -97,6 +114,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; |
| 16240 | } \ |
| 16241 | ++(NAME).cnt; \ |
| 16242 | } while (0) |
| 16243 | +# else |
| 16244 | +# define __libc_lock_lock_recursive(NAME) \ |
| 16245 | + __libc_lock_lock_recursive_fn (&(NAME)) |
| 16246 | +# endif /* __OPTION_EGLIBC_BIG_MACROS */ |
| 16247 | #else |
| 16248 | # define __libc_lock_lock_recursive(NAME) \ |
| 16249 | __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) |
| 16250 | @@ -104,6 +125,14 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; |
| 16251 | |
| 16252 | /* Try to lock the recursive named lock variable. */ |
| 16253 | #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) |
| 16254 | +# if __OPTION_EGLIBC_BIG_MACROS != 1 |
| 16255 | +/* EGLIBC: Declare wrapper function for a big macro if either |
| 16256 | + !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from |
| 16257 | + small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ |
| 16258 | +extern int __libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *); |
| 16259 | +libc_hidden_proto (__libc_lock_trylock_recursive_fn); |
| 16260 | +# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ |
| 16261 | +# if __OPTION_EGLIBC_BIG_MACROS |
| 16262 | # define __libc_lock_trylock_recursive(NAME) \ |
| 16263 | ({ \ |
| 16264 | int result = 0; \ |
| 16265 | @@ -122,6 +151,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; |
| 16266 | ++(NAME).cnt; \ |
| 16267 | result; \ |
| 16268 | }) |
| 16269 | +# else |
| 16270 | +# define __libc_lock_trylock_recursive(NAME) \ |
| 16271 | + __libc_lock_trylock_recursive_fn (&(NAME)) |
| 16272 | +# endif /* __OPTION_EGLIBC_BIG_MACROS */ |
| 16273 | #else |
| 16274 | # define __libc_lock_trylock_recursive(NAME) \ |
| 16275 | __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) |
| 16276 | @@ -129,6 +162,14 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; |
| 16277 | |
| 16278 | /* Unlock the recursive named lock variable. */ |
| 16279 | #if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread)) |
| 16280 | +# if __OPTION_EGLIBC_BIG_MACROS != 1 |
| 16281 | +/* EGLIBC: Declare wrapper function for a big macro if either |
| 16282 | + !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from |
| 16283 | + small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ |
| 16284 | +extern void __libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *); |
| 16285 | +libc_hidden_proto (__libc_lock_unlock_recursive_fn); |
| 16286 | +# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ |
| 16287 | +# if __OPTION_EGLIBC_BIG_MACROS |
| 16288 | /* We do no error checking here. */ |
| 16289 | # define __libc_lock_unlock_recursive(NAME) \ |
| 16290 | do { \ |
| 16291 | @@ -138,6 +179,10 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; |
| 16292 | lll_unlock ((NAME).lock, LLL_PRIVATE); \ |
| 16293 | } \ |
| 16294 | } while (0) |
| 16295 | +# else |
| 16296 | +# define __libc_lock_unlock_recursive(NAME) \ |
| 16297 | + __libc_lock_unlock_recursive_fn (&(NAME)) |
| 16298 | +# endif /* __OPTION_EGLIBC_BIG_MACROS */ |
| 16299 | #else |
| 16300 | # define __libc_lock_unlock_recursive(NAME) \ |
| 16301 | __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) |
| 16302 | diff --git a/sysdeps/nptl/bits/libc-lockP.h b/sysdeps/nptl/bits/libc-lockP.h |
| 16303 | index f55f621..da98869 100644 |
| 16304 | --- a/sysdeps/nptl/bits/libc-lockP.h |
| 16305 | +++ b/sysdeps/nptl/bits/libc-lockP.h |
| 16306 | @@ -33,6 +33,8 @@ |
| 16307 | #include <lowlevellock.h> |
| 16308 | #include <tls.h> |
| 16309 | #include <pthread-functions.h> |
| 16310 | +#include <errno.h> /* For EBUSY. */ |
| 16311 | +#include <gnu/option-groups.h> /* For __OPTION_EGLIBC_BIG_MACROS. */ |
| 16312 | |
| 16313 | #if IS_IN (libpthread) |
| 16314 | /* This gets us the declarations of the __pthread_* internal names, |
| 16315 | @@ -171,10 +173,22 @@ typedef pthread_key_t __libc_key_t; |
| 16316 | |
| 16317 | /* Lock the named lock variable. */ |
| 16318 | #if IS_IN (libc) || IS_IN (libpthread) |
| 16319 | -# ifndef __libc_lock_lock |
| 16320 | -# define __libc_lock_lock(NAME) \ |
| 16321 | +# if __OPTION_EGLIBC_BIG_MACROS != 1 |
| 16322 | +/* EGLIBC: Declare wrapper function for a big macro if either |
| 16323 | + !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from |
| 16324 | + small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ |
| 16325 | +extern void __libc_lock_lock_fn (__libc_lock_t *); |
| 16326 | +libc_hidden_proto (__libc_lock_lock_fn); |
| 16327 | +# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ |
| 16328 | +# if __OPTION_EGLIBC_BIG_MACROS |
| 16329 | +# ifndef __libc_lock_lock |
| 16330 | +# define __libc_lock_lock(NAME) \ |
| 16331 | ({ lll_lock (NAME, LLL_PRIVATE); 0; }) |
| 16332 | -# endif |
| 16333 | +# endif |
| 16334 | +# else |
| 16335 | +# define __libc_lock_lock(NAME) \ |
| 16336 | + __libc_lock_lock_fn (&(NAME)) |
| 16337 | +# endif /* __OPTION_EGLIBC_BIG_MACROS */ |
| 16338 | #else |
| 16339 | # undef __libc_lock_lock |
| 16340 | # define __libc_lock_lock(NAME) \ |
| 16341 | @@ -187,10 +201,22 @@ typedef pthread_key_t __libc_key_t; |
| 16342 | |
| 16343 | /* Try to lock the named lock variable. */ |
| 16344 | #if IS_IN (libc) || IS_IN (libpthread) |
| 16345 | -# ifndef __libc_lock_trylock |
| 16346 | -# define __libc_lock_trylock(NAME) \ |
| 16347 | +# if __OPTION_EGLIBC_BIG_MACROS != 1 |
| 16348 | +/* EGLIBC: Declare wrapper function for a big macro if either |
| 16349 | + !__OPTION_EGLIBC_BIG_MACROS or we are using a back door from |
| 16350 | + small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ |
| 16351 | +extern int __libc_lock_trylock_fn (__libc_lock_t *); |
| 16352 | +libc_hidden_proto (__libc_lock_trylock_fn); |
| 16353 | +# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ |
| 16354 | +# if __OPTION_EGLIBC_BIG_MACROS |
| 16355 | +# ifndef __libc_lock_trylock |
| 16356 | +# define __libc_lock_trylock(NAME) \ |
| 16357 | lll_trylock (NAME) |
| 16358 | -# endif |
| 16359 | +# endif |
| 16360 | +# else |
| 16361 | +# define __libc_lock_trylock(NAME) \ |
| 16362 | + __libc_lock_trylock_fn (&(NAME)) |
| 16363 | +# endif /* __OPTION_EGLIBC_BIG_MACROS */ |
| 16364 | #else |
| 16365 | # undef __libc_lock_trylock |
| 16366 | # define __libc_lock_trylock(NAME) \ |
| 16367 | @@ -206,8 +232,20 @@ typedef pthread_key_t __libc_key_t; |
| 16368 | |
| 16369 | /* Unlock the named lock variable. */ |
| 16370 | #if IS_IN (libc) || IS_IN (libpthread) |
| 16371 | +# if __OPTION_EGLIBC_BIG_MACROS != 1 |
| 16372 | +/* EGLIBC: Declare wrapper function for a big macro if either |
| 16373 | + !__OPTION_EGLIBC_BIG_MACROS, or we are using a back door from |
| 16374 | + small-macros-fns.c (__OPTION_EGLIBC_BIG_MACROS == 2). */ |
| 16375 | +extern void __libc_lock_unlock_fn (__libc_lock_t *); |
| 16376 | +libc_hidden_proto (__libc_lock_unlock_fn); |
| 16377 | +# endif /* __OPTION_EGLIBC_BIG_MACROS != 1 */ |
| 16378 | +# if __OPTION_EGLIBC_BIG_MACROS |
| 16379 | # define __libc_lock_unlock(NAME) \ |
| 16380 | lll_unlock (NAME, LLL_PRIVATE) |
| 16381 | +# else |
| 16382 | +# define __libc_lock_unlock(NAME) \ |
| 16383 | + __libc_lock_unlock_fn (&(NAME)) |
| 16384 | +# endif /* __OPTION_EGLIBC_BIG_MACROS */ |
| 16385 | #else |
| 16386 | # define __libc_lock_unlock(NAME) \ |
| 16387 | __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) |
| 16388 | diff --git a/sysdeps/nptl/small-macros-fns.c b/sysdeps/nptl/small-macros-fns.c |
| 16389 | new file mode 100644 |
| 16390 | index 0000000..f751053 |
| 16391 | --- /dev/null |
| 16392 | +++ b/sysdeps/nptl/small-macros-fns.c |
| 16393 | @@ -0,0 +1,72 @@ |
| 16394 | +/* EGLIBC: function wrappers for big macros. |
| 16395 | + Copyright (C) 2009 Free Software Foundation, Inc. |
| 16396 | + This file is part of the GNU C Library. |
| 16397 | + |
| 16398 | + The GNU C Library is free software; you can redistribute it and/or |
| 16399 | + modify it under the terms of the GNU Lesser General Public License as |
| 16400 | + published by the Free Software Foundation; either version 2.1 of the |
| 16401 | + License, or (at your option) any later version. |
| 16402 | + |
| 16403 | + The GNU C Library is distributed in the hope that it will be useful, |
| 16404 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16405 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16406 | + Lesser General Public License for more details. |
| 16407 | + |
| 16408 | + You should have received a copy of the GNU Lesser General Public |
| 16409 | + License along with the GNU C Library; see the file COPYING.LIB. If not, |
| 16410 | + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 16411 | + Boston, MA 02111-1307, USA. */ |
| 16412 | + |
| 16413 | +#include <gnu/option-groups.h> |
| 16414 | + |
| 16415 | +/* Handle macros from ./bits/libc-lock.h. */ |
| 16416 | +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) |
| 16417 | + |
| 16418 | +/* Get the macros for function bodies through a back door. */ |
| 16419 | +# undef __OPTION_EGLIBC_BIG_MACROS |
| 16420 | +# define __OPTION_EGLIBC_BIG_MACROS 2 |
| 16421 | +# include <bits/libc-lock.h> |
| 16422 | + |
| 16423 | +void |
| 16424 | +__libc_lock_lock_fn (__libc_lock_t *name) |
| 16425 | +{ |
| 16426 | + __libc_lock_lock (*name); |
| 16427 | +} |
| 16428 | +libc_hidden_def (__libc_lock_lock_fn); |
| 16429 | + |
| 16430 | +void |
| 16431 | +__libc_lock_lock_recursive_fn (__libc_lock_recursive_t *name) |
| 16432 | +{ |
| 16433 | + __libc_lock_lock_recursive (*name); |
| 16434 | +} |
| 16435 | +libc_hidden_def (__libc_lock_lock_recursive_fn); |
| 16436 | + |
| 16437 | +int |
| 16438 | +__libc_lock_trylock_fn (__libc_lock_t *name) |
| 16439 | +{ |
| 16440 | + return __libc_lock_trylock (*name); |
| 16441 | +} |
| 16442 | +libc_hidden_def (__libc_lock_trylock_fn); |
| 16443 | + |
| 16444 | +int |
| 16445 | +__libc_lock_trylock_recursive_fn (__libc_lock_recursive_t *name) |
| 16446 | +{ |
| 16447 | + return __libc_lock_trylock_recursive (*name); |
| 16448 | +} |
| 16449 | +libc_hidden_def (__libc_lock_trylock_recursive_fn); |
| 16450 | + |
| 16451 | +void |
| 16452 | +__libc_lock_unlock_fn (__libc_lock_t *name) |
| 16453 | +{ |
| 16454 | + __libc_lock_unlock (*name); |
| 16455 | +} |
| 16456 | +libc_hidden_def (__libc_lock_unlock_fn); |
| 16457 | + |
| 16458 | +void |
| 16459 | +__libc_lock_unlock_recursive_fn (__libc_lock_recursive_t *name) |
| 16460 | +{ |
| 16461 | + __libc_lock_unlock_recursive (*name); |
| 16462 | +} |
| 16463 | +libc_hidden_def (__libc_lock_unlock_recursive_fn); |
| 16464 | + |
| 16465 | +#endif /*defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)*/ |
| 16466 | diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c |
| 16467 | index 26e4692..d0a26c8 100644 |
| 16468 | --- a/sysdeps/unix/sysv/linux/gethostid.c |
| 16469 | +++ b/sysdeps/unix/sysv/linux/gethostid.c |
| 16470 | @@ -21,6 +21,7 @@ |
| 16471 | #include <unistd.h> |
| 16472 | #include <netdb.h> |
| 16473 | #include <not-cancel.h> |
| 16474 | +#include <gnu/option-groups.h> |
| 16475 | |
| 16476 | #define HOSTIDFILE "/etc/hostid" |
| 16477 | |
| 16478 | @@ -89,6 +90,7 @@ gethostid (void) |
| 16479 | return id; |
| 16480 | } |
| 16481 | |
| 16482 | +#if __OPTION_EGLIBC_INET |
| 16483 | /* Getting from the file was not successful. An intelligent guess for |
| 16484 | a unique number of a host is its IP address. Return this. */ |
| 16485 | if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0') |
| 16486 | @@ -115,5 +117,9 @@ gethostid (void) |
| 16487 | /* For the return value to be not exactly the IP address we do some |
| 16488 | bit fiddling. */ |
| 16489 | return (int32_t) (in.s_addr << 16 | in.s_addr >> 16); |
| 16490 | +#else |
| 16491 | + /* Return an arbitrary value. */ |
| 16492 | + return 0; |
| 16493 | +#endif |
| 16494 | } |
| 16495 | #endif |
| 16496 | diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c |
| 16497 | index 53a8bbb..cb110d4 100644 |
| 16498 | --- a/sysdeps/unix/sysv/linux/libc_fatal.c |
| 16499 | +++ b/sysdeps/unix/sysv/linux/libc_fatal.c |
| 16500 | @@ -23,6 +23,7 @@ |
| 16501 | #include <string.h> |
| 16502 | #include <sys/mman.h> |
| 16503 | #include <sys/uio.h> |
| 16504 | +#include <gnu/option-groups.h> |
| 16505 | |
| 16506 | static bool |
| 16507 | writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total) |
| 16508 | @@ -40,6 +41,7 @@ writev_for_fatal (int fd, const struct iovec *iov, size_t niov, size_t total) |
| 16509 | static void |
| 16510 | backtrace_and_maps (int do_abort, bool written, int fd) |
| 16511 | { |
| 16512 | +#if __OPTION_EGLIBC_BACKTRACE |
| 16513 | if (do_abort > 1 && written) |
| 16514 | { |
| 16515 | void *addrs[64]; |
| 16516 | @@ -62,6 +64,7 @@ backtrace_and_maps (int do_abort, bool written, int fd) |
| 16517 | close_not_cancel_no_status (fd2); |
| 16518 | } |
| 16519 | } |
| 16520 | +#endif /* __OPTION_EGLIBC_BACKTRACE */ |
| 16521 | } |
| 16522 | #define BEFORE_ABORT backtrace_and_maps |
| 16523 | |
| 16524 | diff --git a/time/Makefile b/time/Makefile |
| 16525 | index a411f62..2d022ca 100644 |
| 16526 | --- a/time/Makefile |
| 16527 | +++ b/time/Makefile |
| 16528 | @@ -18,6 +18,8 @@ |
| 16529 | # |
| 16530 | # Makefile for time routines |
| 16531 | # |
| 16532 | +include ../option-groups.mak |
| 16533 | + |
| 16534 | subdir := time |
| 16535 | |
| 16536 | include ../Makeconfig |
| 16537 | @@ -30,15 +32,23 @@ routines := offtime asctime clock ctime ctime_r difftime \ |
| 16538 | tzfile getitimer setitimer \ |
| 16539 | stime dysize timegm ftime \ |
| 16540 | getdate strptime strptime_l \ |
| 16541 | - strftime wcsftime strftime_l wcsftime_l \ |
| 16542 | + strftime strftime_l \ |
| 16543 | timespec_get |
| 16544 | -aux := era alt_digit lc-time-cleanup |
| 16545 | |
| 16546 | -tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ |
| 16547 | - tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ |
| 16548 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 16549 | + := wcsftime wcsftime_l |
| 16550 | +aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup |
| 16551 | + |
| 16552 | +tests := test_time clocktest tst-posixtz \ |
| 16553 | + tst-getdate tst-mktime tst-mktime2 tst-strftime \ |
| 16554 | tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ |
| 16555 | tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime |
| 16556 | |
| 16557 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 16558 | + += tst-strptime tst-ftime_l |
| 16559 | +tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ |
| 16560 | + += tst_wcsftime |
| 16561 | + |
| 16562 | include ../Rules |
| 16563 | |
| 16564 | tz-cflags = -DTZDIR='"$(zonedir)"' \ |
| 16565 | diff --git a/time/strftime_l.c b/time/strftime_l.c |
| 16566 | index b48ef34..bfdd618 100644 |
| 16567 | --- a/time/strftime_l.c |
| 16568 | +++ b/time/strftime_l.c |
| 16569 | @@ -35,6 +35,10 @@ |
| 16570 | # include "../locale/localeinfo.h" |
| 16571 | #endif |
| 16572 | |
| 16573 | +#ifdef _LIBC |
| 16574 | +# include <gnu/option-groups.h> |
| 16575 | +#endif |
| 16576 | + |
| 16577 | #if defined emacs && !defined HAVE_BCOPY |
| 16578 | # define HAVE_MEMCPY 1 |
| 16579 | #endif |
| 16580 | @@ -882,7 +886,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| 16581 | case L_('C'): |
| 16582 | if (modifier == L_('E')) |
| 16583 | { |
| 16584 | -#if HAVE_STRUCT_ERA_ENTRY |
| 16585 | +#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY |
| 16586 | struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); |
| 16587 | if (era) |
| 16588 | { |
| 16589 | @@ -955,7 +959,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| 16590 | |
| 16591 | if (modifier == L_('O') && 0 <= number_value) |
| 16592 | { |
| 16593 | -#ifdef _NL_CURRENT |
| 16594 | +#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT) |
| 16595 | /* Get the locale specific alternate representation of |
| 16596 | the number NUMBER_VALUE. If none exist NULL is returned. */ |
| 16597 | const CHAR_T *cp = nl_get_alt_digit (number_value |
| 16598 | @@ -1260,7 +1264,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| 16599 | case L_('Y'): |
| 16600 | if (modifier == 'E') |
| 16601 | { |
| 16602 | -#if HAVE_STRUCT_ERA_ENTRY |
| 16603 | +#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY |
| 16604 | struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); |
| 16605 | if (era) |
| 16606 | { |
| 16607 | @@ -1285,7 +1289,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| 16608 | case L_('y'): |
| 16609 | if (modifier == L_('E')) |
| 16610 | { |
| 16611 | -#if HAVE_STRUCT_ERA_ENTRY |
| 16612 | +#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY |
| 16613 | struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); |
| 16614 | if (era) |
| 16615 | { |
| 16616 | diff --git a/time/strptime_l.c b/time/strptime_l.c |
| 16617 | index 5640cce..784ccbc 100644 |
| 16618 | --- a/time/strptime_l.c |
| 16619 | +++ b/time/strptime_l.c |
| 16620 | @@ -29,6 +29,7 @@ |
| 16621 | |
| 16622 | #ifdef _LIBC |
| 16623 | # define HAVE_LOCALTIME_R 0 |
| 16624 | +# include <gnu/option-groups.h> |
| 16625 | # include "../locale/localeinfo.h" |
| 16626 | #endif |
| 16627 | |
| 16628 | @@ -84,7 +85,7 @@ localtime_r (t, tp) |
| 16629 | if (val < from || val > to) \ |
| 16630 | return NULL; \ |
| 16631 | } while (0) |
| 16632 | -#ifdef _NL_CURRENT |
| 16633 | +#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT) |
| 16634 | # define get_alt_number(from, to, n) \ |
| 16635 | ({ \ |
| 16636 | __label__ do_normal; \ |
| 16637 | @@ -257,8 +258,10 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16638 | int cnt; |
| 16639 | int cnt_longest; |
| 16640 | size_t val; |
| 16641 | +#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE |
| 16642 | size_t num_eras; |
| 16643 | struct era_entry *era = NULL; |
| 16644 | +#endif |
| 16645 | enum ptime_locale_status { not, loc, raw } decided_longest; |
| 16646 | struct __strptime_state |
| 16647 | { |
| 16648 | @@ -820,6 +823,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16649 | s.want_xday = 1; |
| 16650 | break; |
| 16651 | case 'C': |
| 16652 | +#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE |
| 16653 | if (s.decided != raw) |
| 16654 | { |
| 16655 | if (s.era_cnt >= 0) |
| 16656 | @@ -856,10 +860,12 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16657 | |
| 16658 | s.decided = raw; |
| 16659 | } |
| 16660 | +#endif |
| 16661 | /* The C locale has no era information, so use the |
| 16662 | normal representation. */ |
| 16663 | goto match_century; |
| 16664 | case 'y': |
| 16665 | +#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE |
| 16666 | if (s.decided != raw) |
| 16667 | { |
| 16668 | get_number(0, 9999, 4); |
| 16669 | @@ -918,9 +924,10 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16670 | |
| 16671 | s.decided = raw; |
| 16672 | } |
| 16673 | - |
| 16674 | +#endif |
| 16675 | goto match_year_in_century; |
| 16676 | case 'Y': |
| 16677 | +#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE |
| 16678 | if (s.decided != raw) |
| 16679 | { |
| 16680 | num_eras = _NL_CURRENT_WORD (LC_TIME, |
| 16681 | @@ -948,6 +955,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16682 | |
| 16683 | s.decided = raw; |
| 16684 | } |
| 16685 | +#endif |
| 16686 | get_number (0, 9999, 4); |
| 16687 | tm->tm_year = val - 1900; |
| 16688 | s.want_century = 0; |
| 16689 | @@ -1118,6 +1126,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16690 | tm->tm_year = (s.century - 19) * 100; |
| 16691 | } |
| 16692 | |
| 16693 | +#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE |
| 16694 | if (s.era_cnt != -1) |
| 16695 | { |
| 16696 | era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG); |
| 16697 | @@ -1132,6 +1141,7 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) |
| 16698 | tm->tm_year = era->start_date[0]; |
| 16699 | } |
| 16700 | else |
| 16701 | +#endif |
| 16702 | if (s.want_era) |
| 16703 | { |
| 16704 | /* No era found but we have seen an E modifier. Rectify some |
| 16705 | diff --git a/timezone/Makefile b/timezone/Makefile |
| 16706 | index 886b06e..f922684 100644 |
| 16707 | --- a/timezone/Makefile |
| 16708 | +++ b/timezone/Makefile |
| 16709 | @@ -127,7 +127,7 @@ $(testdata)/XT%: testdata/XT% |
| 16710 | |
| 16711 | $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make |
| 16712 | sed -e 's|/bin/bash|/bin/sh|' \ |
| 16713 | - -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ |
| 16714 | + -e '/TZDIR=/s|\$$(pwd)|$(zonedir)|' \ |
| 16715 | -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \ |
| 16716 | -e '/PKGVERSION=/s|=.*|="$(PKGVERSION)"|' \ |
| 16717 | -e '/REPORT_BUGS_TO=/s|=.*|="$(REPORT_BUGS_TO)"|' \ |
| 16718 | diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile |
| 16719 | index 44a4494..db9fc24 100644 |
| 16720 | --- a/wcsmbs/Makefile |
| 16721 | +++ b/wcsmbs/Makefile |
| 16722 | @@ -18,15 +18,21 @@ |
| 16723 | # |
| 16724 | # Sub-makefile for wcsmbs portion of the library. |
| 16725 | # |
| 16726 | +include ../option-groups.mak |
| 16727 | + |
| 16728 | subdir := wcsmbs |
| 16729 | |
| 16730 | include ../Makeconfig |
| 16731 | |
| 16732 | headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h |
| 16733 | |
| 16734 | -routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ |
| 16735 | +# These functions are used by printf_fp.c, even in the plain case; see |
| 16736 | +# comments there for OPTION_EGLIBC_LOCALE_CODE. |
| 16737 | +routines := wmemcpy wmemset |
| 16738 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 16739 | + := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ |
| 16740 | wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \ |
| 16741 | - wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \ |
| 16742 | + wmemcmp wmemmove wcpcpy wcpncpy wmempcpy \ |
| 16743 | btowc wctob mbsinit \ |
| 16744 | mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \ |
| 16745 | mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \ |
| 16746 | @@ -38,14 +44,21 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ |
| 16747 | wcscoll_l wcsxfrm_l \ |
| 16748 | wcscasecmp wcsncase wcscasecmp_l wcsncase_l \ |
| 16749 | wcsmbsload mbsrtowcs_l \ |
| 16750 | - isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \ |
| 16751 | isoc99_swscanf isoc99_vswscanf \ |
| 16752 | mbrtoc16 c16rtomb |
| 16753 | |
| 16754 | -strop-tests := wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy |
| 16755 | -tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \ |
| 16756 | - tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \ |
| 16757 | - tst-c16c32-1 wcsatcliff $(addprefix test-,$(strop-tests)) |
| 16758 | +routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \ |
| 16759 | + += isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf |
| 16760 | + |
| 16761 | +strop-tests := wcscmp wmemcmp wmemcmp wcslen wcschr wcsrchr wcscpy |
| 16762 | + |
| 16763 | +tests := tst-wchar-h |
| 16764 | +tests-$(OPTION_EGLIBC_LOCALE_CODE) \ |
| 16765 | + += tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb tst-c16c32-1 |
| 16766 | +tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 16767 | + += tst-wcstof wcsmbs-tst1 tst-wcsnlen \ |
| 16768 | + tst-wcpncpy tst-mbsrtowcs \ |
| 16769 | + wcsatcliff $(addprefix test-,$(strop-tests)) |
| 16770 | |
| 16771 | include ../Rules |
| 16772 | |
| 16773 | diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c |
| 16774 | index 6bb49bc..2ab9d07 100644 |
| 16775 | --- a/wcsmbs/wcsmbsload.c |
| 16776 | +++ b/wcsmbs/wcsmbsload.c |
| 16777 | @@ -21,6 +21,7 @@ |
| 16778 | #include <limits.h> |
| 16779 | #include <stdlib.h> |
| 16780 | #include <string.h> |
| 16781 | +#include <gnu/option-groups.h> |
| 16782 | |
| 16783 | #include <locale/localeinfo.h> |
| 16784 | #include <wcsmbsload.h> |
| 16785 | @@ -143,6 +144,7 @@ __wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp) |
| 16786 | }) |
| 16787 | |
| 16788 | |
| 16789 | +#if __OPTION_EGLIBC_LOCALE_CODE |
| 16790 | /* Some of the functions here must not be used while setlocale is called. */ |
| 16791 | __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) |
| 16792 | |
| 16793 | @@ -211,6 +213,17 @@ __wcsmbs_load_conv (struct __locale_data *new_category) |
| 16794 | |
| 16795 | __libc_rwlock_unlock (__libc_setlocale_lock); |
| 16796 | } |
| 16797 | +#else |
| 16798 | +void |
| 16799 | +internal_function |
| 16800 | +__wcsmbs_load_conv (struct __locale_data *new_category) |
| 16801 | +{ |
| 16802 | + /* When OPTION_EGLIBC_LOCALE_CODE is disabled, we should never reach |
| 16803 | + this point: there is no way to change locales, so every locale |
| 16804 | + passed to get_gconv_fcts should be _nl_C_LC_CTYPE. */ |
| 16805 | + abort (); |
| 16806 | +} |
| 16807 | +#endif |
| 16808 | |
| 16809 | |
| 16810 | /* Clone the current conversion function set. */ |
| 16811 | diff --git a/wctype/Makefile b/wctype/Makefile |
| 16812 | index c56f07c..4e8af43 100644 |
| 16813 | --- a/wctype/Makefile |
| 16814 | +++ b/wctype/Makefile |
| 16815 | @@ -18,14 +18,20 @@ |
| 16816 | # |
| 16817 | # Sub-makefile for wctype portion of the library. |
| 16818 | # |
| 16819 | +include ../option-groups.mak |
| 16820 | + |
| 16821 | subdir := wctype |
| 16822 | |
| 16823 | include ../Makeconfig |
| 16824 | |
| 16825 | headers := wctype.h |
| 16826 | -routines := wcfuncs wctype iswctype wctrans towctrans \ |
| 16827 | - wcfuncs_l wctype_l iswctype_l wctrans_l towctrans_l |
| 16828 | - |
| 16829 | -tests := test_wctype test_wcfuncs bug-wctypeh |
| 16830 | +routines := wctrans towctrans towctrans_l |
| 16831 | +routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 16832 | + := wcfuncs wctype iswctype \ |
| 16833 | + wcfuncs_l wctype_l iswctype_l wctrans_l |
| 16834 | + |
| 16835 | +tests := |
| 16836 | +tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \ |
| 16837 | + += test_wctype test_wcfuncs bug-wctypeh |
| 16838 | |
| 16839 | include ../Rules |
| 16840 | -- |
| 16841 | 2.1.4 |
| 16842 | |