diff options
Diffstat (limited to 'gnu/lib/libregex/test')
29 files changed, 8869 insertions, 0 deletions
diff --git a/gnu/lib/libregex/test/ChangeLog b/gnu/lib/libregex/test/ChangeLog new file mode 100644 index 000000000000..f0265bb26a6a --- /dev/null +++ b/gnu/lib/libregex/test/ChangeLog @@ -0,0 +1,77 @@ +Thu Mar 25 21:23:43 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * debugmalloc.c: #include <string.h>, and remove declaration of + memcpy. + +Sun Dec 13 20:59:32 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * tregress.c (test_regress): Add regression test for matching + "[a-a]" against "a" with the upcase translation map. + + * iregex.c (print_regs): Don't print a newline after the register + contents. + (main): Instead, write out newlines here after printing match and + search results; this way, we get a newline whether or not the + pattern matched. + +Fri Dec 11 03:30:50 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * tregress.c (test_regress): Add new test to catch bug fixed by + change to regex.c today. + + * Makefile.in (dregex.o): Depend on `../regex.[ch]', not `regex.[ch]'. + +Sun Nov 15 07:51:40 1992 Karl Berry (karl@cs.umb.edu) + + * debugmalloc.c (memcpy): Declare; also, include <assert.h>. + + * psx-interf.c (fill_pmatch): Declare offsets as `regoff_t' + instead of `off_t'. + +Thu Nov 12 11:29:58 1992 Karl Berry (karl@cs.umb.edu) + + * iregex.c (main): Remove unused variable `c'; initialize + the char array in C code; only call print_regs if the match and + search succeeded. + (strlen): Declare. + + * tregress.c (test_regress): Bug from enami. + +Tue Nov 10 10:36:53 1992 Karl Berry (karl@cs.umb.edu) + + * tregress.c (test_regress): Remove Emacs 19 diff bug from rms, as + it was never the right thing to test anyway, and the test itself + had bugs in it. + +Mon Nov 9 10:09:40 1992 Karl Berry (karl@cs.umb.edu) + + * tregress.c (test_regress): Bug from meyering. + +Thu Sep 24 10:48:34 1992 Karl Berry (karl@cs.umb.edu) + + * Makefile.in: avoid $< (except in implicit rule). + +Sat Sep 19 15:38:29 1992 Karl Berry (karl@hayley) + + * Makefile.in (TAGS): include regex.c and regex.h. + +Wed Sep 16 09:29:27 1992 Karl Berry (karl@hayley) + + * xmalloc.c (xmalloc): use char *, not void *, as some compilers + bomb out on the latter. + + * Makefile.in (LOADLIBES): use LIBS instead, as that what's + Autoconf wants to define. + + * other.c: remove tests for ^/$ around newlines. + +Tue Sep 15 11:01:15 1992 Karl Berry (karl@hayley) + + * fileregex.c (main): call re_search_2 instead of re_search. + + * Makefile.in (regex.o): make target dregex.o, so VPATH doesn't + find ../regex.o. + +Sun Sep 13 06:50:03 1992 Karl Berry (karl@hayley) + + * Created. diff --git a/gnu/lib/libregex/test/Makefile b/gnu/lib/libregex/test/Makefile new file mode 100644 index 000000000000..5a8656a76e9a --- /dev/null +++ b/gnu/lib/libregex/test/Makefile @@ -0,0 +1,169 @@ +# Generated automatically from Makefile.in by configure. +# Makefile for regex testing. +# +# Copyright (C) 1992 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +CPPFLAGS = +CFLAGS = -g +LDFLAGS = + +srcdir = . +VPATH = .:../. + +CC = gcc +DEFS = -DHAVE_STRING_H=1 +LIBS = $(LOADLIBES) + +ETAGS = etags +SHELL = /bin/sh + +debug = -DDEBUG +ALL_CPPFLAGS = -I. -I$(srcdir) -I../$(srcdir) $(DEFS) $(CPPFLAGS) $(debug) + +.c.o: + $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c $< + + +# Define this as `../regex.o' to get the optimized version. +regex_o = dregex.o +test_h = test.h +test_o = test.o bsd-interf.o other.o tregress.o psx-basic.o psx-extend.o \ + psx-generic.o psx-group.o psx-interf.o psx-interv.o +common_o = printchar.o upcase.o xmalloc.o $(malloc) + +# We have a lot of mallocs we can try when we run afoul of strange bugs. +malloc = +#malloc = # the libc malloc +#malloc = g++malloc.o +#malloc = debugmalloc.o +#malloc = emacsmalloc.o +emacsmallocflags = -Drcheck -Dbotch=abort -DUSG + +# default is to do nothing. +default: + +all: regex syntax + +regex: $(regex_o) $(common_o) $(test_o) main.o + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +# As long as we're doing tests, we enable debugging. +dregex.o: ../regex.c ../regex.h + rm -f $@ + $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c ../$(srcdir)/regex.c + mv regex.o $@ + +# iregex is the interactive regex. +iregex: $(common_o) $(regex_o) iregex.o + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +# fileregex searches for an r.e. in every line of a given file. +fileregex_o = fileregex.o printchar.o $(regex_o) +fileregex: $(fileregex_o) + $(CC) -o $@ $(LDFLAGS) $(fileregex_o) $(LIBS) + +# cppregex is regex with a preprocessed regex.c. Useful when the +# problem is inside some macro. +cppregex: regexcpp.o $(common_o) $(test_o) main.o + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +regexcpp.o: regexcpp.c + +regexcpp.c: regex.c regexcpp.sed + rm -f regexcpp.c + $(CC) -E $(ALL_CPPFLAGS) ../$(srcdir)/regex.c \ + | egrep -v '^#|^ *$$' \ + | sed -f regexcpp.sed \ + > regexcpp.c + chmod a-w regexcpp.c + +# Have to give this malloc special flags. +emacsmalloc.o: emacsmalloc.c + $(CC) -c $(CFLAGS) $(ALL_CPPFLAGS) $(emacsmallocflags) \ + ../$(srcdir)/test/emacsmalloc.c + +syntax: syntax.o + $(CC) $(CFLAGS) -o $@ syntax.o + +syntax.c: syntax.skel bits + sed '/\[\[\[replace.*\]\]\]/r bits' syntax.skel > $@ + +bits: regex.h + sed -n 1,/RE_SYNTAX_EMACS/p ../$(srcdir)/regex.h \ + | grep "#define RE_.*1" \ + | sed 's/^#define \(RE_[A-Z_]*\) .*/ TEST_BIT (\1);/' > $@ + +check: regex + ./regex + +TAGS: regex.c regex.h *.h *.c + $(ETAGS) -t $^ + +depend: + gcc -MM $(ALL_CPPFLAGS) *.c > /tmp/depend +.PHONY: depend + +install: +.PHONY: install + +clean mostlyclean: + rm -f *.o regex cppregex iregex fileregex regexcpp.c syntax + +distclean: clean + rm -f bits syntax.c Makefile + +extraclean: distclean + rm -f *~* *\#* patch* *.orig *.rej *.bak core a.out + +realclean: distclean + rm -f TAGS + +Makefile: Makefile.in ../config.status + (cd ..; sh config.status) + +# Prevent GNU make 3 from overflowing arg limit on system V. +.NOEXPORT: + +# Assumes $(distdir) is the place to put our files. +distfiles = ChangeLog TAGS *.in *.c *.h regexcpp.sed syntax.skel +dist: Makefile TAGS + mkdir $(distdir) + ln $(distfiles) $(distdir) + +# Automatically-generated dependencies below here. +alloca.o : alloca.c +bsd-interf.o : bsd-interf.c +debugmalloc.o : debugmalloc.c +emacsmalloc.o : emacsmalloc.c getpagesize.h +fileregex.o : fileregex.c .././regex.h +g++malloc.o : g++malloc.c //usr/include/stdio.h getpagesize.h +iregex.o : iregex.c .././regex.h +main.o : main.c test.h .././regex.h +malloc-test.o : malloc-test.c +other.o : other.c test.h .././regex.h +printchar.o : printchar.c +psx-basic.o : psx-basic.c test.h .././regex.h +psx-extend.o : psx-extend.c test.h .././regex.h +psx-generic.o : psx-generic.c test.h .././regex.h +psx-group.o : psx-group.c test.h .././regex.h +psx-interf.o : psx-interf.c test.h .././regex.h +psx-interv.o : psx-interv.c test.h .././regex.h +syntax.o : syntax.c .././regex.h +test.o : test.c test.h .././regex.h +tregress.o : tregress.c test.h .././regex.h +upcase.o : upcase.c +xmalloc.o : xmalloc.c diff --git a/gnu/lib/libregex/test/Makefile.in b/gnu/lib/libregex/test/Makefile.in new file mode 100644 index 000000000000..b6a413384f08 --- /dev/null +++ b/gnu/lib/libregex/test/Makefile.in @@ -0,0 +1,168 @@ +# Makefile for regex testing. +# +# Copyright (C) 1992 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +CPPFLAGS = +CFLAGS = -g +LDFLAGS = + +srcdir = @srcdir@ +VPATH = @srcdir@:../@srcdir@ + +CC = @CC@ +DEFS = @DEFS@ +LIBS = @LIBS@ $(LOADLIBES) + +ETAGS = etags +SHELL = /bin/sh + +debug = -DDEBUG +ALL_CPPFLAGS = -I. -I$(srcdir) -I../$(srcdir) $(DEFS) $(CPPFLAGS) $(debug) + +.c.o: + $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c $< + + +# Define this as `../regex.o' to get the optimized version. +regex_o = dregex.o +test_h = test.h +test_o = test.o bsd-interf.o other.o tregress.o psx-basic.o psx-extend.o \ + psx-generic.o psx-group.o psx-interf.o psx-interv.o +common_o = printchar.o upcase.o xmalloc.o $(malloc) + +# We have a lot of mallocs we can try when we run afoul of strange bugs. +malloc = @ALLOCA@ +#malloc = # the libc malloc +#malloc = g++malloc.o +#malloc = debugmalloc.o +#malloc = emacsmalloc.o +emacsmallocflags = -Drcheck -Dbotch=abort -DUSG + +# default is to do nothing. +default: + +all: regex syntax + +regex: $(regex_o) $(common_o) $(test_o) main.o + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +# As long as we're doing tests, we enable debugging. +dregex.o: ../regex.c ../regex.h + rm -f $@ + $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c ../$(srcdir)/regex.c + mv regex.o $@ + +# iregex is the interactive regex. +iregex: $(common_o) $(regex_o) iregex.o + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +# fileregex searches for an r.e. in every line of a given file. +fileregex_o = fileregex.o printchar.o $(regex_o) +fileregex: $(fileregex_o) + $(CC) -o $@ $(LDFLAGS) $(fileregex_o) $(LIBS) + +# cppregex is regex with a preprocessed regex.c. Useful when the +# problem is inside some macro. +cppregex: regexcpp.o $(common_o) $(test_o) main.o + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +regexcpp.o: regexcpp.c + +regexcpp.c: regex.c regexcpp.sed + rm -f regexcpp.c + $(CC) -E $(ALL_CPPFLAGS) ../$(srcdir)/regex.c \ + | egrep -v '^#|^ *$$' \ + | sed -f regexcpp.sed \ + > regexcpp.c + chmod a-w regexcpp.c + +# Have to give this malloc special flags. +emacsmalloc.o: emacsmalloc.c + $(CC) -c $(CFLAGS) $(ALL_CPPFLAGS) $(emacsmallocflags) \ + ../$(srcdir)/test/emacsmalloc.c + +syntax: syntax.o + $(CC) $(CFLAGS) -o $@ syntax.o + +syntax.c: syntax.skel bits + sed '/\[\[\[replace.*\]\]\]/r bits' syntax.skel > $@ + +bits: regex.h + sed -n 1,/RE_SYNTAX_EMACS/p ../$(srcdir)/regex.h \ + | grep "#define RE_.*1" \ + | sed 's/^#define \(RE_[A-Z_]*\) .*/ TEST_BIT (\1);/' > $@ + +check: regex + ./regex + +TAGS: regex.c regex.h *.h *.c + $(ETAGS) -t $^ + +depend: + gcc -MM $(ALL_CPPFLAGS) *.c > /tmp/depend +.PHONY: depend + +install: +.PHONY: install + +clean mostlyclean: + rm -f *.o regex cppregex iregex fileregex regexcpp.c syntax + +distclean: clean + rm -f bits syntax.c Makefile + +extraclean: distclean + rm -f *~* *\#* patch* *.orig *.rej *.bak core a.out + +realclean: distclean + rm -f TAGS + +Makefile: Makefile.in ../config.status + (cd ..; sh config.status) + +# Prevent GNU make 3 from overflowing arg limit on system V. +.NOEXPORT: + +# Assumes $(distdir) is the place to put our files. +distfiles = ChangeLog TAGS *.in *.c *.h regexcpp.sed syntax.skel +dist: Makefile TAGS + mkdir $(distdir) + ln $(distfiles) $(distdir) + +# Automatically-generated dependencies below here. +alloca.o : alloca.c +bsd-interf.o : bsd-interf.c +debugmalloc.o : debugmalloc.c +emacsmalloc.o : emacsmalloc.c getpagesize.h +fileregex.o : fileregex.c .././regex.h +g++malloc.o : g++malloc.c //usr/include/stdio.h getpagesize.h +iregex.o : iregex.c .././regex.h +main.o : main.c test.h .././regex.h +malloc-test.o : malloc-test.c +other.o : other.c test.h .././regex.h +printchar.o : printchar.c +psx-basic.o : psx-basic.c test.h .././regex.h +psx-extend.o : psx-extend.c test.h .././regex.h +psx-generic.o : psx-generic.c test.h .././regex.h +psx-group.o : psx-group.c test.h .././regex.h +psx-interf.o : psx-interf.c test.h .././regex.h +psx-interv.o : psx-interv.c test.h .././regex.h +syntax.o : syntax.c .././regex.h +test.o : test.c test.h .././regex.h +tregress.o : tregress.c test.h .././regex.h +upcase.o : upcase.c +xmalloc.o : xmalloc.c diff --git a/gnu/lib/libregex/test/TAGS b/gnu/lib/libregex/test/TAGS new file mode 100644 index 000000000000..d3aad750dcba --- /dev/null +++ b/gnu/lib/libregex/test/TAGS @@ -0,0 +1,373 @@ + +.././regex.c,4137 +#define AT_STRINGS_BEG(3078,98376 +#define AT_STRINGS_END(3079,98449 +#define AT_WORD_BOUNDARY(3093,99002 +#define BUF_PUSH(887,24995 +#define BUF_PUSH_2(895,25208 +#define BUF_PUSH_3(904,25437 +#define DEBUG_POP(2336,74614 +#define DEBUG_PRINT1(471,14296 +#define DEBUG_PRINT1(785,21263 +#define DEBUG_PRINT2(472,14342 +#define DEBUG_PRINT3(473,14398 +#define DEBUG_PRINT3(787,21316 +#define DEBUG_PRINT4(474,14462 +#define DEBUG_PRINT_COMPILED_PATTERN(475,14534 +#define DEBUG_PRINT_COMPILED_PATTERN(789,21386 +#define DEBUG_PRINT_DOUBLE_STRING(477,14637 +#define DEBUG_PUSH(2338,74684 +#define DEBUG_STATEMENT(470,14267 +#define DOUBLE_FAIL_STACK(2299,73230 +#define EVER_MATCHED_SOMETHING(3028,96680 +#define EXTEND_BUFFER(941,26834 +#define EXTRACT_NUMBER(403,12499 +#define EXTRACT_NUMBER(422,12960 +#define EXTRACT_NUMBER_AND_INCR(430,13181 +#define EXTRACT_NUMBER_AND_INCR(448,13583 +#define FAIL_STACK_EMPTY(2271,72289 +#define FAIL_STACK_FULL(2273,72404 +#define FAIL_STACK_PTR_EMPTY(2272,72344 +#define FAIL_STACK_TOP(2274,72473 +#define FIRST_STRING_P(221,5848 +#define FREE_VAR(3100,99186 +#define FREE_VARIABLES(3101,99240 +#define FREE_VARIABLES(3116,99751 +#define GET_BUFFER_SPACE(882,24802 +#define GET_UNSIGNED_NUMBER(1017,29312 +#define INIT_FAIL_STACK(2279,72612 +#define INSERT_JUMP(923,26079 +#define INSERT_JUMP2(927,26236 +#define ISALNUM(147,3407 +#define ISALPHA(148,3455 +#define ISBLANK(135,3062 +#define ISBLANK(137,3116 +#define ISCNTRL(149,3503 +#define ISDIGIT(146,3359 +#define ISGRAPH(140,3185 +#define ISGRAPH(142,3239 +#define ISLOWER(150,3551 +#define ISPRINT(145,3311 +#define ISPUNCT(151,3599 +#define ISSPACE(152,3647 +#define ISUPPER(153,3695 +#define ISXDIGIT(154,3743 +#define IS_ACTIVE(3026,96578 +#define IS_CHAR_CLASS(1035,29793 +#define MATCHED_SOMETHING(3027,96621 +#define MAX(233,6292 +#define MIN(234,6334 +#define PATFETCH(852,23769 +#define PATFETCH_RAW(860,24020 +#define POINTER_TO_OFFSET(3050,97433 +#define POP_FAILURE_ITEM(2331,74426 +#define POP_FAILURE_POINT(2461,79538 +#define PREFETCH(3064,97916 +#define PUSH_FAILURE_ITEM(2327,74253 +#define PUSH_FAILURE_POINT(2352,75048 +#define PUSH_PATTERN_OP(2317,73841 +#define REGEX_REALLOCATE(185,4875 +#define REGEX_REALLOCATE(210,5495 +#define REGEX_TALLOC(227,6137 +#define REG_MATCH_NULL_STRING_P(3025,96511 +#define REG_UNSET(3055,97649 +#define RETALLOC(226,6058 +#define SET_LIST_BIT(1011,29089 +#define SET_REGS_MATCHED(3034,96936 +#define SIGN_EXTEND_CHAR(166,4109 +#define SIGN_EXTEND_CHAR(169,4217 +#define STORE_JUMP(915,25800 +#define STORE_JUMP2(919,25917 +#define STORE_NUMBER(384,11919 +#define STORE_NUMBER_AND_INCR(394,12242 +#define STREQ(231,6244 +#define SYNTAX(120,2790 +#define TALLOC(225,6003 +#define TRANSLATE(873,24503 +#define WORDCHAR_P(3086,98755 +alt_match_null_string_p 4466,149039 +#define assert(782,21217 +at_begline_loc_p 2131,67979 +at_endline_loc_p 2150,68557 +#define bcmp(54,1656 +bcmp_translate 4591,151831 +#define bcopy(57,1726 +typedef char boolean;236,6377 +#define bzero(60,1793 +common_op_match_null_string_p 4503,149895 +compile_range 2200,69997 +} compile_stack_elt_t;990,28602 +} compile_stack_type;998,28748 +extract_number 411,12714 +extract_number_and_incr 438,13370 +} fail_stack_type;2269,72269 +group_in_compile_stack 2172,69174 +group_match_null_string_p 4357,145267 +init_syntax_once 94,2365 +insert_op1 2091,67107 +insert_op2 2110,67475 +#define isascii(131,3018 +typedef int pattern_offset_t;981,28388 +print_compiled_pattern 726,19792 +print_double_string 753,20605 +print_fastmap 486,14835 +print_partial_compiled_pattern 518,15475 +re_comp 4650,153479 +re_compile_fastmap 2532,82428 +re_compile_pattern 4617,152520 +re_exec 4688,154373 +re_match 3136,100557 +re_match_2 3161,101399 +} re_opcode_t;378,11781 +re_search 2844,90872 +re_search_2 2877,91998 +re_set_registers 2817,90247 +re_set_syntax 808,22087 +regcomp 4736,155972 +regerror 4876,160188 +regex_compile 1062,30922 +regexec 4811,158371 +regfree 4920,161247 +} register_info_type;3023,96488 +typedef unsigned regnum_t;974,28172 +store_op1 2063,66535 +store_op2 2076,66768 +typedef const unsigned 2262,72103 + +.././regex.h,230 +#define _RE_ARGS(394,14981 +#define _RE_ARGS(398,15036 +} reg_errcode_t;270,10874 +typedef unsigned reg_syntax_t;38,1503 +typedef struct re_pattern_buffer regex_t;346,13556 +} regmatch_t;382,14634 +typedef int regoff_t;354,13814 + +getpagesize.h,84 +#define getpagesize(12,137 +#define getpagesize(15,191 +#define getpagesize(20,302 + +test.h,436 +#define BRACES_TO_OPS(107,3169 +#define INVALID_PATTERN(110,3328 +#define MATCH_SELF(114,3429 +#define PARENS_TO_OPS(108,3248 +#define SAFE_STRLEN(14,201 +#define TEST_POSITIONED_MATCH(116,3470 +#define TEST_REGISTERS(104,3011 +#define TEST_REGISTERS_2(97,2703 +#define TEST_SEARCH(127,3875 +#define TEST_SEARCH_2(123,3720 +#define TEST_TRUNCATED_MATCH(120,3608 +typedef enum { false = 0, true = 1 } boolean;16,255 +} test_type;33,572 + +alloca.c,128 +alloca 141,3996 +find_stack_direction 85,2553 +} header;127,3538 +typedef void *pointer;51,1721 +typedef char *pointer;53,1778 + +bsd-interf.c,51 +test_berk_search 8,106 +test_bsd_interface 33,738 + +debugmalloc.c,395 +#define TRACE(8,143 +#define TRACE1(9,197 +#define TRACE2(10,254 +#define TRACE3(11,319 +#define TRACE4(12,392 +#define USER_ALLOC(61,1440 +typedef char *address;15,480 +} *chunk;54,1225 +chunk_delete 115,2778 +chunk_insert 96,2294 +chunk_to_mem 79,1916 +free 261,5604 +free_list_available 175,3947 +malloc 203,4343 +mem_to_chunk 68,1703 +realloc 242,5309 +validate_list 153,3478 +xsbrk 21,545 + +emacsmalloc.c,574 +#define ASSERT(178,5884 +#define ASSERT(181,5985 +#define CHAIN(166,5430 +#define bcmp(73,2821 +#define bcopy(72,2777 +#define bzero(74,2868 +calloc 603,15983 +free 484,13255 +get_lim_data 736,18517 +get_lim_data 752,18767 +get_lim_data 759,18860 +getpool 374,10263 +malloc 413,11133 +malloc_init 218,6863 +malloc_mem_free 707,17940 +malloc_mem_used 688,17683 +malloc_stats 663,17320 +malloc_usable_size 233,7147 +memalign 618,16164 +morecore 244,7380 +realloc 541,14424 +#define start_of_data(110,3486 +#define start_of_data(115,3546 +sys_sbrk 815,20804 +valloc 645,17031 + +fileregex.c,13 +main 11,156 + +g++malloc.c,1543 +#define UPDATE_STATS(33,1090 +#define UPDATE_STATS(35,1131 +static inline int aligned_OK(343,11189 +void* calloc(1039,28692 +void cfree(1048,28894 +static inline void* chunk2mem(619,19336 +#define clear_inuse(592,18767 +static inline void consollink(716,21398 +static void do_free_stats(544,18016 +static void do_malloc_stats(534,17741 +766,22304 +extern 762,22235 + for 1260,34165 +void free(1028,28553 +static inline void frontlink(732,21717 +static unsigned int gcd(557,18251 + if 1212,32427 + if 1216,32582 + if 1220,32737 + if 1224,32880 + if 1229,33094 + if 1233,33251 + if 1238,33463 + if 1242,33609 + if 1247,33739 +#define inuse(590,18680 +static inline unsigned int lcm(580,18540 +void* malloc(939,26370 +static mchunkptr malloc_find_space(858,24561 +void malloc_stats(1201,32256 +unsigned int malloc_usable_size(1054,28936 +static volatile void malloc_user_error(286,9757 +static void malloc_user_error(288,9804 +typedef struct malloc_bin* mbinptr;320,10636 +typedef struct malloc_chunk* mchunkptr;309,10247 +static inline mchunkptr mem2chunk(643,19759 +void* memalign(1118,30363 +#define next_chunk(600,18910 +#define prev_chunk(604,19023 +void* realloc(1071,29263 +static inline unsigned int request2size(335,10993 +mchunkptr sanity_check(628,19486 +#define set_inuse(591,18723 +static inline void set_size(609,19149 +static inline mbinptr size2bin(499,16914 +static inline void split(685,20463 +static 768,22312 +static inline void unlink(671,20263 +void* valloc(1194,32107 +typedef volatile void 760,22184 +764,22271 + +iregex.c,54 +main 20,390 +print_regs 141,2638 +scanstring 87,1839 + +main.c,13 +main 12,242 + +malloc-test.c,112 +#define BITS_BLOCK(12,168 +#define BITS_MASK(13,228 +} bits_list_type;6,56 +init_bits_list 16,311 +main(32,621 + +other.c,18 +test_others 6,96 + +printchar.c,15 +printchar 2,5 + +psx-basic.c,23 +test_posix_basic 7,84 + +psx-extend.c,26 +test_posix_extended 7,88 + +psx-generic.c,26 +test_posix_generic 8,117 + +psx-group.c,20 +test_grouping 7,92 + +psx-interf.c,416 +fill_pmatch 174,4802 +get_error_string 18,260 +init_pattern_buffer 49,1434 +test_compile 67,1925 +test_eflags 245,6876 +test_error_code_allocation 562,16619 +test_error_code_message 524,15247 +test_ignore_case 303,8525 +test_newline 330,9199 +test_nsub 117,3319 +test_pmatch 188,5121 +test_posix_interface 614,18719 +test_posix_match 359,9938 +test_regcomp 138,3725 +test_regerror 592,17621 +test_regexec 394,10783 + +psx-interv.c,21 +test_intervals 6,93 + +test.c,607 +#define SET_FASTMAP(447,13999 +#define bcmp(18,362 +#define bcopy(19,415 +#define bzero(20,473 +compile_and_print_pattern 666,19653 +concat 97,2673 +delimiters_to_ops 571,17477 +general_test 115,2996 +invalid_pattern 542,16821 +#define memcmp(26,611 +#define memcpy(27,660 +print_pattern_info 635,18998 +set_all_registers 58,1390 +test_all_registers 506,15567 +test_case_fold 682,19993 +test_fastmap 460,14363 +test_fastmap_search 474,14668 +test_match 776,22235 +test_match_2 766,22040 +test_match_n_times 715,20798 +test_search_return 408,13011 +valid_nonposix_pattern 646,19239 +valid_pattern 557,17182 + +tregress.c,208 +#define SIMPLE_MATCH(74,1463 +#define SIMPLE_NONMATCH(75,1528 +do_match 78,1599 +itoa 10,199 +simple_compile 44,882 +simple_fail 21,353 +simple_fastmap 55,1115 +simple_search 100,2020 +test_regress 124,2513 + +upcase.c,0 + +xmalloc.c,14 +xmalloc 9,87 diff --git a/gnu/lib/libregex/test/alloca.c b/gnu/lib/libregex/test/alloca.c new file mode 100644 index 000000000000..c1ff22227f8e --- /dev/null +++ b/gnu/lib/libregex/test/alloca.c @@ -0,0 +1,194 @@ +/* + alloca -- (mostly) portable public-domain implementation -- D A Gwyn + + last edit: 86/05/30 rms + include config.h, since on VMS it renames some symbols. + Use xmalloc instead of malloc. + + This implementation of the PWB library alloca() function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + + It should work under any C implementation that uses an + actual procedure stack (as opposed to a linked list of + frames). There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca()-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. +*/ +#ifndef lint +static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */ +#endif + +#ifdef emacs +#include "config.h" +#ifdef static +/* actually, only want this if static is defined as "" + -- this is for usg, in which emacs must undefine static + in order to make unexec workable + */ +#ifndef STACK_DIRECTION +you +lose +-- must know STACK_DIRECTION at compile-time +#endif /* STACK_DIRECTION undefined */ +#endif /* static */ +#endif /* emacs */ + +#ifndef alloca /* If compiling with GCC, this file's not needed. */ + +#ifdef __STDC__ +typedef void *pointer; /* generic pointer type */ +#else +typedef char *pointer; /* generic pointer type */ +#endif + +#define NULL 0 /* null pointer constant */ + +extern void free(); +extern pointer xmalloc(); + +/* + Define STACK_DIRECTION if you know the direction of stack + growth for your system; otherwise it will be automatically + deduced at run-time. + + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown +*/ + +#ifndef STACK_DIRECTION +#define STACK_DIRECTION 0 /* direction unknown */ +#endif + +#if STACK_DIRECTION != 0 + +#define STACK_DIR STACK_DIRECTION /* known at compile-time */ + +#else /* STACK_DIRECTION == 0; need run-time code */ + +static int stack_dir; /* 1 or -1 once known */ +#define STACK_DIR stack_dir + +static void +find_stack_direction (/* void */) +{ + static char *addr = NULL; /* address of first + `dummy', once known */ + auto char dummy; /* to get stack address */ + + if (addr == NULL) + { /* initial entry */ + addr = &dummy; + + find_stack_direction (); /* recurse once */ + } + else /* second entry */ + if (&dummy > addr) + stack_dir = 1; /* stack grew upward */ + else + stack_dir = -1; /* stack grew downward */ +} + +#endif /* STACK_DIRECTION == 0 */ + +/* + An "alloca header" is used to: + (a) chain together all alloca()ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc() + alignment chunk size. The following default should work okay. +*/ + +#ifndef ALIGN_SIZE +#define ALIGN_SIZE sizeof(double) +#endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* to force sizeof(header) */ + struct + { + union hdr *next; /* for chaining headers */ + char *deep; /* for stack depth measure */ + } h; +} header; + +/* + alloca( size ) returns a pointer to at least `size' bytes of + storage which will be automatically reclaimed upon exit from + the procedure that called alloca(). Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. +*/ + +static header *last_alloca_header = NULL; /* -> last alloca header */ + +pointer +alloca (size) /* returns pointer to storage */ + unsigned size; /* # bytes to allocate */ +{ + auto char probe; /* probes stack depth: */ + register char *depth = &probe; + +#if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* unknown growth direction */ + find_stack_direction (); +#endif + + /* Reclaim garbage, defined as all alloca()ed storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* traverses linked list */ + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIR > 0 && hp->h.deep > depth) + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free ((pointer) hp); /* collect garbage */ + + hp = np; /* -> next header */ + } + else + break; /* rest are not deeper */ + + last_alloca_header = hp; /* -> last valid storage */ + } + + if (size == 0) + return NULL; /* no allocation required */ + + /* Allocate combined header + user data storage. */ + + { + register pointer new = xmalloc (sizeof (header) + size); + /* address of header */ + + ((header *)new)->h.next = last_alloca_header; + ((header *)new)->h.deep = depth; + + last_alloca_header = (header *)new; + + /* User storage begins just after header. */ + + return (pointer)((char *)new + sizeof(header)); + } +} + +#endif /* no alloca */ diff --git a/gnu/lib/libregex/test/bsd-interf.c b/gnu/lib/libregex/test/bsd-interf.c new file mode 100644 index 000000000000..56f9e2a2fe68 --- /dev/null +++ b/gnu/lib/libregex/test/bsd-interf.c @@ -0,0 +1,38 @@ +/* bsd-interf.c: test BSD interface. */ + +#ifndef _POSIX_SOURCE /* whole file */ + +#include "test.h" + +void +test_berk_search (pattern, string) + const char *pattern; + char *string; +{ + const char *return_value = re_comp (pattern); + + if (return_value != 0) + { + printf ("This didn't compile: `%s'.\n", pattern); + printf (" The error message was: `%s'.\n", return_value); + } + else + if (test_should_match && re_exec (string) != strlen (string)) + { + printf ("Should have matched but didn't:\n"); + printf (" The pattern was: %s.\n", pattern); + if (string) + printf (" The string was: `%s'.'n", string); + else + printf (" The string was empty.\n"); + } +} + + +void +test_bsd_interface () +{ + test_berk_search ("a", "ab"); +} + +#endif /* _POSIX_SOURCE */ diff --git a/gnu/lib/libregex/test/debugmalloc.c b/gnu/lib/libregex/test/debugmalloc.c new file mode 100644 index 000000000000..5c468e212439 --- /dev/null +++ b/gnu/lib/libregex/test/debugmalloc.c @@ -0,0 +1,273 @@ +/* debugmalloc.c: a malloc for debugging purposes. */ + +#include <stdio.h> +#include <assert.h> +#include <string.h> + +static unsigned trace = 0; +#define TRACE(s) if (trace) fprintf (stderr, "%s", s) +#define TRACE1(s, e1) if (trace) fprintf (stderr, s, e1) +#define TRACE2(s, e1, e2) if (trace) fprintf (stderr, s, e1, e2) +#define TRACE3(s, e1, e2, e3) if (trace) fprintf (stderr, s, e1, e2, e3) +#define TRACE4(s, e1, e2, e3, e4) \ + if (trace) fprintf (stderr, s, e1, e2, e3, e4) + +typedef char *address; + + +/* Wrap our calls to sbrk. */ + +address +xsbrk (incr) + int incr; +{ + extern char *sbrk (); + address ret = sbrk (incr); + + if (ret == (address) -1) + { + perror ("sbrk"); /* Actually, we should return NULL, not quit. */ + abort (); + } + + return ret; +} + + + +typedef struct chunk_struct +{ + /* This is the size (in bytes) that has actually been actually + allocated, not the size that the user requested. */ + unsigned alloc_size; + + /* This is the size the user requested. */ + unsigned user_size; + + /* Points to the next block in one of the lists. */ + struct chunk_struct *next; + + /* Now comes the user's memory. */ + address user_mem; + + /* After the user's memory is a constant. */ +} *chunk; + +#define MALLOC_OVERHEAD 16 + +/* We might play around with the `user_size' field, but the amount of + memory that is actually available in the chunk is always the size + allocated minus the overhead. */ +#define USER_ALLOC(c) ((c)->alloc_size - MALLOC_OVERHEAD) + +/* Given a pointer to a malloc-allocated block, the beginning of the + chunk should always be MALLOC_OVERHEAD - 4 bytes back, since the only + overhead after the user memory is the constant. */ + +chunk +mem_to_chunk (mem) + address mem; +{ + return (chunk) (mem - (MALLOC_OVERHEAD - 4)); +} + + +/* The other direction is even easier, since the user's memory starts at + the `user_mem' member in the chunk. */ + +address +chunk_to_mem (c) + chunk c; +{ + return (address) &(c->user_mem); +} + + + +/* We keep both all the allocated chunks and all the free chunks on + lists. Since we put the next pointers in the chunk structure, we + don't need a separate chunk_list structure. */ +chunk alloc_list = NULL, free_list = NULL; + + +/* We always append the new chunk at the beginning of the list. */ + +void +chunk_insert (chunk_list, new_c) + chunk *chunk_list; + chunk new_c; +{ + chunk c = *chunk_list; /* old beginning of list */ + + TRACE3 (" Inserting 0x%x at the beginning of 0x%x, before 0x%x.\n", + new_c, chunk_list, c); + + *chunk_list = new_c; + new_c->next = c; +} + + +/* Thus, removing an element means we have to search until we find it. + Have to delete before we insert, since insertion changes the next + pointer, which we need to put it on the other list. */ + +void +chunk_delete (chunk_list, dead_c) + chunk *chunk_list; + chunk dead_c; +{ + chunk c = *chunk_list; + chunk prev_c = NULL; + + TRACE2 (" Deleting 0x%x from 0x%x:", dead_c, chunk_list); + + while (c != dead_c && c != NULL) + { + TRACE1 (" 0x%x", c); + prev_c = c; + c = c->next; + } + + if (c == NULL) + { + fprintf (stderr, "Chunk at 0x%x not found on list.\n", dead_c); + abort (); + } + + if (prev_c == NULL) + { + TRACE1 (".\n Setting head to 0x%x.\n", c->next); + *chunk_list = c->next; + } + else + { + TRACE2 (".\n Linking next(0x%x) to 0x%x.\n", prev_c, c->next); + prev_c->next = c->next; + } +} + + +/* See if a list is hunky-dory. */ + +void +validate_list (chunk_list) + chunk *chunk_list; +{ + chunk c; + + TRACE1 (" Validating list at 0x%x:", chunk_list); + + for (c = *chunk_list; c != NULL; c = c->next) + { + assert (c->user_size < c->alloc_size); + assert (memcmp (chunk_to_mem (c) + c->user_size, "Karl", 4)); + TRACE2 (" 0x%x/%d", c, c->user_size); + } + + TRACE (".\n"); +} + + +/* See if we have a free chunk of a given size. We'll take the first + one that is big enough. */ + +chunk +free_list_available (needed) + unsigned needed; +{ + chunk c; + + TRACE1 (" Checking free list for %d bytes:", needed); + + if (free_list == NULL) + { + return NULL; + } + + c = free_list; + + while (c != NULL && USER_ALLOC (c) < needed) + { + TRACE2 (" 0x%x/%d", c, USER_ALLOC (c)); + c = c->next; + } + + TRACE1 ("\n Returning 0x%x.\n", c); + return c; +} + + + + +address +malloc (n) + unsigned n; +{ + address new_mem; + chunk c; + + TRACE1 ("Mallocing %d bytes.\n", n); + + validate_list (&free_list); + validate_list (&alloc_list); + + c = free_list_available (n); + + if (c == NULL) + { /* Nothing suitable on free list. Allocate a new chunk. */ + TRACE (" not on free list.\n"); + c = (chunk) xsbrk (n + MALLOC_OVERHEAD); + c->alloc_size = n + MALLOC_OVERHEAD; + } + else + { /* Found something on free list. Don't split it, just use as is. */ + TRACE (" found on free list.\n"); + chunk_delete (&free_list, c); + } + + /* If we took this from the free list, then the user size might be + different now, and consequently the constant at the end might be in + the wrong place. */ + c->user_size = n; + new_mem = chunk_to_mem (c); + memcpy (new_mem + n, "Karl", 4); + chunk_insert (&alloc_list, c); + + TRACE2 ("Malloc returning 0x%x (chunk 0x%x).\n", new_mem, c); + return new_mem; +} + + +address +realloc (mem, n) + address mem; + unsigned n; +{ + void free (); + chunk c = mem_to_chunk (mem); + address new_mem; + + TRACE3 ("Reallocing %d bytes at 0x%x (chunk 0x%x).\n", n, mem, c); + + new_mem = malloc (n); + memcpy (new_mem, mem, c->user_size); + free (mem); + + return new_mem; +} + + +void +free (mem) + address mem; +{ + chunk c = mem_to_chunk (mem); + + TRACE2 ("Freeing memory at 0x%x (chunk at 0x%x).\n", mem, c); + + validate_list (&free_list); + validate_list (&alloc_list); + + chunk_delete (&alloc_list, c); + chunk_insert (&free_list, c); +} diff --git a/gnu/lib/libregex/test/emacsmalloc.c b/gnu/lib/libregex/test/emacsmalloc.c new file mode 100644 index 000000000000..6eee1fae1acb --- /dev/null +++ b/gnu/lib/libregex/test/emacsmalloc.c @@ -0,0 +1,844 @@ +/* dynamic memory allocation for GNU. + Copyright (C) 1985, 1987 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +In other words, you are welcome to use, share and improve this program. +You are forbidden to forbid anyone else to use, share and improve +what you give them. Help stamp out software-hoarding! */ + + +/* + * @(#)nmalloc.c 1 (Caltech) 2/21/82 + * + * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs + * + * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD. + * + * This is a very fast storage allocator. It allocates blocks of a small + * number of different sizes, and keeps free lists of each size. Blocks + * that don't exactly fit are passed up to the next larger size. In this + * implementation, the available sizes are (2^n)-4 (or -16) bytes long. + * This is designed for use in a program that uses vast quantities of + * memory, but bombs when it runs out. To make it a little better, it + * warns the user when he starts to get near the end. + * + * June 84, ACT: modified rcheck code to check the range given to malloc, + * rather than the range determined by the 2-power used. + * + * Jan 85, RMS: calls malloc_warning to issue warning on nearly full. + * No longer Emacs-specific; can serve as all-purpose malloc for GNU. + * You should call malloc_init to reinitialize after loading dumped Emacs. + * Call malloc_stats to get info on memory stats if MSTATS turned on. + * realloc knows how to return same block given, just changing its size, + * if the power of 2 is correct. + */ + +/* + * nextf[i] is the pointer to the next free block of size 2^(i+3). The + * smallest allocatable block is 8 bytes. The overhead information will + * go in the first int of the block, and the returned pointer will point + * to the second. + * +#ifdef MSTATS + * nmalloc[i] is the difference between the number of mallocs and frees + * for a given block size. +#endif MSTATS + */ + +#ifdef emacs +/* config.h specifies which kind of system this is. */ +#include "config.h" +#include <signal.h> +#else + +/* Determine which kind of system this is. */ +#include <sys/types.h> +#include <signal.h> + +#include <string.h> +#define bcopy(s,d,n) memcpy ((d), (s), (n)) +#define bcmp(s1,s2,n) memcmp ((s1), (s2), (n)) +#define bzero(s,n) memset ((s), 0, (n)) + +#ifndef SIGTSTP +#ifndef VMS +#ifndef USG +#define USG +#endif +#endif /* not VMS */ +#else /* SIGTSTP */ +#ifdef SIGIO +#define BSD4_2 +#endif /* SIGIO */ +#endif /* SIGTSTP */ + +#endif /* not emacs */ + +/* Define getpagesize () if the system does not. */ +#include "getpagesize.h" + +#ifdef BSD +#ifdef BSD4_1 +#include <sys/vlimit.h> /* warn the user when near the end */ +#else /* if 4.2 or newer */ +#include <sys/time.h> +#include <sys/resource.h> +#endif /* if 4.2 or newer */ +#endif + +#ifdef VMS +#include "vlimit.h" +#endif + +extern char *start_of_data (); + +#ifdef BSD +#ifndef DATA_SEG_BITS +#define start_of_data() &etext +#endif +#endif + +#ifndef emacs +#define start_of_data() &etext +#endif + +#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ +#define ISFREE ((char) 0x54) /* magic byte that implies free block */ + /* this is for error checking only */ +#define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by + memalign, with the rest of the word + being the distance to the true + beginning of the block. */ + +extern char etext; + +/* These two are for user programs to look at, when they are interested. */ + +unsigned int malloc_sbrk_used; /* amount of data space used now */ +unsigned int malloc_sbrk_unused; /* amount more we can have */ + +/* start of data space; can be changed by calling init_malloc */ +static char *data_space_start; + +#ifdef MSTATS +static int nmalloc[30]; +static int nmal, nfre; +#endif /* MSTATS */ + +/* If range checking is not turned on, all we have is a flag indicating + whether memory is allocated, an index in nextf[], and a size field; to + realloc() memory we copy either size bytes or 1<<(index+3) bytes depending + on whether the former can hold the exact size (given the value of + 'index'). If range checking is on, we always need to know how much space + is allocated, so the 'size' field is never used. */ + +struct mhead { + char mh_alloc; /* ISALLOC or ISFREE */ + char mh_index; /* index in nextf[] */ +/* Remainder are valid only when block is allocated */ + unsigned short mh_size; /* size, if < 0x10000 */ +#ifdef rcheck + unsigned mh_nbytes; /* number of bytes allocated */ + int mh_magic4; /* should be == MAGIC4 */ +#endif /* rcheck */ +}; + +/* Access free-list pointer of a block. + It is stored at block + 4. + This is not a field in the mhead structure + because we want sizeof (struct mhead) + to describe the overhead for when the block is in use, + and we do not want the free-list pointer to count in that. */ + +#define CHAIN(a) \ + (*(struct mhead **) (sizeof (char *) + (char *) (a))) + +#ifdef rcheck + +/* To implement range checking, we write magic values in at the beginning and + end of each allocated block, and make sure they are undisturbed whenever a + free or a realloc occurs. */ +/* Written in each of the 4 bytes following the block's real space */ +#define MAGIC1 0x55 +/* Written in the 4 bytes before the block's real space */ +#define MAGIC4 0x55555555 +#define ASSERT(p) if (!(p)) botch("p"); else +#define EXTRA 4 /* 4 bytes extra for MAGIC1s */ +#else +#define ASSERT(p) if (!(p)) abort (); else +#define EXTRA 0 +#endif /* rcheck */ + + +/* nextf[i] is free list of blocks of size 2**(i + 3) */ + +static struct mhead *nextf[30]; + +/* busy[i] is nonzero while allocation of block size i is in progress. */ + +static char busy[30]; + +/* Number of bytes of writable memory we can expect to be able to get */ +static unsigned int lim_data; + +/* Level number of warnings already issued. + 0 -- no warnings issued. + 1 -- 75% warning already issued. + 2 -- 85% warning already issued. +*/ +static int warnlevel; + +/* Function to call to issue a warning; + 0 means don't issue them. */ +static void (*warnfunction) (); + +/* nonzero once initial bunch of free blocks made */ +static int gotpool; + +char *_malloc_base; + +static void getpool (); + +/* Cause reinitialization based on job parameters; + also declare where the end of pure storage is. */ +void +malloc_init (start, warnfun) + char *start; + void (*warnfun) (); +{ + if (start) + data_space_start = start; + lim_data = 0; + warnlevel = 0; + warnfunction = warnfun; +} + +/* Return the maximum size to which MEM can be realloc'd + without actually requiring copying. */ + +int +malloc_usable_size (mem) + char *mem; +{ + struct mhead *p + = (struct mhead *) (mem - ((sizeof (struct mhead) + 7) & ~7)); + int blocksize = 8 << p->mh_index; + + return blocksize - sizeof (struct mhead) - EXTRA; +} + +static void +morecore (nu) /* ask system for more memory */ + register int nu; /* size index to get more of */ +{ + char *sbrk (); + register char *cp; + register int nblks; + register unsigned int siz; + int oldmask; + +#ifdef BSD +#ifndef BSD4_1 + int newmask = -1; + /* Blocking these signals interferes with debugging, at least on BSD on + the HP 9000/300. */ +#ifdef SIGTRAP + newmask &= ~(1 << SIGTRAP); +#endif +#ifdef SIGILL + newmask &= ~(1 << SIGILL); +#endif +#ifdef SIGTSTP + newmask &= ~(1 << SIGTSTP); +#endif +#ifdef SIGSTOP + newmask &= ~(1 << SIGSTOP); +#endif + oldmask = sigsetmask (newmask); +#endif +#endif + + if (!data_space_start) + { + data_space_start = start_of_data (); + } + + if (lim_data == 0) + get_lim_data (); + + /* On initial startup, get two blocks of each size up to 1k bytes */ + if (!gotpool) + { getpool (); getpool (); gotpool = 1; } + + /* Find current end of memory and issue warning if getting near max */ + +#ifndef VMS + /* Maximum virtual memory on VMS is difficult to calculate since it + * depends on several dynmacially changing things. Also, alignment + * isn't that important. That is why much of the code here is ifdef'ed + * out for VMS systems. + */ + cp = sbrk (0); + siz = cp - data_space_start; + + if (warnfunction) + switch (warnlevel) + { + case 0: + if (siz > (lim_data / 4) * 3) + { + warnlevel++; + (*warnfunction) ("Warning: past 75% of memory limit"); + } + break; + case 1: + if (siz > (lim_data / 20) * 17) + { + warnlevel++; + (*warnfunction) ("Warning: past 85% of memory limit"); + } + break; + case 2: + if (siz > (lim_data / 20) * 19) + { + warnlevel++; + (*warnfunction) ("Warning: past 95% of memory limit"); + } + break; + } + + if ((int) cp & 0x3ff) /* land on 1K boundaries */ + sbrk (1024 - ((int) cp & 0x3ff)); +#endif /* not VMS */ + + /* Take at least 2k, and figure out how many blocks of the desired size + we're about to get */ + nblks = 1; + if ((siz = nu) < 8) + nblks = 1 << ((siz = 8) - nu); + + if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) + { +#ifdef BSD +#ifndef BSD4_1 + sigsetmask (oldmask); +#endif +#endif + return; /* no more room! */ + } + malloc_sbrk_used = siz; + malloc_sbrk_unused = lim_data - siz; + +#ifndef VMS + if ((int) cp & 7) + { /* shouldn't happen, but just in case */ + cp = (char *) (((int) cp + 8) & ~7); + nblks--; + } +#endif /* not VMS */ + + /* save new header and link the nblks blocks together */ + nextf[nu] = (struct mhead *) cp; + siz = 1 << (nu + 3); + while (1) + { + ((struct mhead *) cp) -> mh_alloc = ISFREE; + ((struct mhead *) cp) -> mh_index = nu; + if (--nblks <= 0) break; + CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); + cp += siz; + } + CHAIN ((struct mhead *) cp) = 0; + +#ifdef BSD +#ifndef BSD4_1 + sigsetmask (oldmask); +#endif +#endif +} + +static void +getpool () +{ + register int nu; + char * sbrk (); + register char *cp = sbrk (0); + + if ((int) cp & 0x3ff) /* land on 1K boundaries */ + sbrk (1024 - ((int) cp & 0x3ff)); + + /* Record address of start of space allocated by malloc. */ + if (_malloc_base == 0) + _malloc_base = cp; + + /* Get 2k of storage */ + + cp = sbrk (04000); + if (cp == (char *) -1) + return; + + /* Divide it into an initial 8-word block + plus one block of size 2**nu for nu = 3 ... 10. */ + + CHAIN (cp) = nextf[0]; + nextf[0] = (struct mhead *) cp; + ((struct mhead *) cp) -> mh_alloc = ISFREE; + ((struct mhead *) cp) -> mh_index = 0; + cp += 8; + + for (nu = 0; nu < 7; nu++) + { + CHAIN (cp) = nextf[nu]; + nextf[nu] = (struct mhead *) cp; + ((struct mhead *) cp) -> mh_alloc = ISFREE; + ((struct mhead *) cp) -> mh_index = nu; + cp += 8 << nu; + } +} + +char * +malloc (n) /* get a block */ + unsigned n; +{ + register struct mhead *p; + register unsigned int nbytes; + register int nunits = 0; + + /* Figure out how many bytes are required, rounding up to the nearest + multiple of 8, then figure out which nestf[] area to use. + Both the beginning of the header and the beginning of the + block should be on an eight byte boundary. */ + nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; + { + register unsigned int shiftr = (nbytes - 1) >> 2; + + while (shiftr >>= 1) + nunits++; + } + + /* In case this is reentrant use of malloc from signal handler, + pick a block size that no other malloc level is currently + trying to allocate. That's the easiest harmless way not to + interfere with the other level of execution. */ + while (busy[nunits]) nunits++; + busy[nunits] = 1; + + /* If there are no blocks of the appropriate size, go get some */ + /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ + if (nextf[nunits] == 0) + morecore (nunits); + + /* Get one block off the list, and set the new list head */ + if ((p = nextf[nunits]) == 0) + { + busy[nunits] = 0; + return 0; + } + nextf[nunits] = CHAIN (p); + busy[nunits] = 0; + + /* Check for free block clobbered */ + /* If not for this check, we would gobble a clobbered free chain ptr */ + /* and bomb out on the NEXT allocate of this size block */ + if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) +#ifdef rcheck + botch ("block on free list clobbered"); +#else /* not rcheck */ + abort (); +#endif /* not rcheck */ + + /* Fill in the info, and if range checking, set up the magic numbers */ + p -> mh_alloc = ISALLOC; +#ifdef rcheck + p -> mh_nbytes = n; + p -> mh_magic4 = MAGIC4; + { + /* Get the location n after the beginning of the user's space. */ + register char *m = (char *) p + ((sizeof *p + 7) & ~7) + n; + + *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; + } +#else /* not rcheck */ + p -> mh_size = n; +#endif /* not rcheck */ +#ifdef MSTATS + nmalloc[nunits]++; + nmal++; +#endif /* MSTATS */ + return (char *) p + ((sizeof *p + 7) & ~7); +} + +free (mem) + char *mem; +{ + register struct mhead *p; + { + register char *ap = mem; + + if (ap == 0) + return; + + p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); + if (p -> mh_alloc == ISMEMALIGN) + { + ap -= p->mh_size; + p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); + } + +#ifndef rcheck + if (p -> mh_alloc != ISALLOC) + abort (); + +#else rcheck + if (p -> mh_alloc != ISALLOC) + { + if (p -> mh_alloc == ISFREE) + botch ("free: Called with already freed block argument\n"); + else + botch ("free: Called with bad argument\n"); + } + + ASSERT (p -> mh_magic4 == MAGIC4); + ap += p -> mh_nbytes; + ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); + ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); +#endif /* rcheck */ + } + { + register int nunits = p -> mh_index; + + ASSERT (nunits <= 29); + p -> mh_alloc = ISFREE; + + /* Protect against signal handlers calling malloc. */ + busy[nunits] = 1; + /* Put this block on the free list. */ + CHAIN (p) = nextf[nunits]; + nextf[nunits] = p; + busy[nunits] = 0; + +#ifdef MSTATS + nmalloc[nunits]--; + nfre++; +#endif /* MSTATS */ + } +} + +char * +realloc (mem, n) + char *mem; + register unsigned n; +{ + register struct mhead *p; + register unsigned int tocopy; + register unsigned int nbytes; + register int nunits; + + if (mem == 0) + return malloc (n); + p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7)); + nunits = p -> mh_index; + ASSERT (p -> mh_alloc == ISALLOC); +#ifdef rcheck + ASSERT (p -> mh_magic4 == MAGIC4); + { + register char *m = mem + (tocopy = p -> mh_nbytes); + ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); + ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); + } +#else /* not rcheck */ + if (p -> mh_index >= 13) + tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7); + else + tocopy = p -> mh_size; +#endif /* not rcheck */ + + /* See if desired size rounds to same power of 2 as actual size. */ + nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; + + /* If ok, use the same block, just marking its size as changed. */ + if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) + { +#ifdef rcheck + register char *m = mem + tocopy; + *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; + p-> mh_nbytes = n; + m = mem + n; + *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; +#else /* not rcheck */ + p -> mh_size = n; +#endif /* not rcheck */ + return mem; + } + + if (n < tocopy) + tocopy = n; + { + register char *new; + + if ((new = malloc (n)) == 0) + return 0; + bcopy (mem, new, tocopy); + free (mem); + return new; + } +} + +/* This is in case something linked with Emacs calls calloc. */ + +char * +calloc (num, size) + unsigned num, size; +{ + register char *mem; + + num *= size; + mem = malloc (num); + if (mem != 0) + bzero (mem, num); + return mem; +} + +#ifndef VMS + +char * +memalign (alignment, size) + unsigned alignment, size; +{ + register char *ptr = malloc (size + alignment); + register char *aligned; + register struct mhead *p; + + if (ptr == 0) + return 0; + /* If entire block has the desired alignment, just accept it. */ + if (((int) ptr & (alignment - 1)) == 0) + return ptr; + /* Otherwise, get address of byte in the block that has that alignment. */ + aligned = (char *) (((int) ptr + alignment - 1) & -alignment); + + /* Store a suitable indication of how to free the block, + so that free can find the true beginning of it. */ + p = (struct mhead *) (aligned - ((7 + sizeof (struct mhead)) & ~7)); + p -> mh_size = aligned - ptr; + p -> mh_alloc = ISMEMALIGN; + return aligned; +} + +#ifndef HPUX +/* This runs into trouble with getpagesize on HPUX. + Patching out seems cleaner than the ugly fix needed. */ +char * +valloc (size) +{ + return memalign (getpagesize (), size); +} +#endif /* not HPUX */ +#endif /* not VMS */ + +#ifdef MSTATS +/* Return statistics describing allocation of blocks of size 2**n. */ + +struct mstats_value + { + int blocksize; + int nfree; + int nused; + }; + +struct mstats_value +malloc_stats (size) + int size; +{ + struct mstats_value v; + register int i; + register struct mhead *p; + + v.nfree = 0; + + if (size < 0 || size >= 30) + { + v.blocksize = 0; + v.nused = 0; + return v; + } + + v.blocksize = 1 << (size + 3); + v.nused = nmalloc[size]; + + for (p = nextf[size]; p; p = CHAIN (p)) + v.nfree++; + + return v; +} +int +malloc_mem_used () +{ + int i; + int size_used; + + size_used = 0; + + for (i = 0; i < 30; i++) + { + int allocation_size = 1 << (i + 3); + struct mhead *p; + + size_used += nmalloc[i] * allocation_size; + } + + return size_used; +} + +int +malloc_mem_free () +{ + int i; + int size_unused; + + size_unused = 0; + + for (i = 0; i < 30; i++) + { + int allocation_size = 1 << (i + 3); + struct mhead *p; + + for (p = nextf[i]; p ; p = CHAIN (p)) + size_unused += allocation_size; + } + + return size_unused; +} +#endif /* MSTATS */ + +/* + * This function returns the total number of bytes that the process + * will be allowed to allocate via the sbrk(2) system call. On + * BSD systems this is the total space allocatable to stack and + * data. On USG systems this is the data space only. + */ + +#ifdef USG + +get_lim_data () +{ + extern long ulimit (); + +#ifdef ULIMIT_BREAK_VALUE + lim_data = ULIMIT_BREAK_VALUE; +#else + lim_data = ulimit (3, 0); +#endif + + lim_data -= (long) data_space_start; +} + +#else /* not USG */ +#if defined (BSD4_1) || defined (VMS) + +get_lim_data () +{ + lim_data = vlimit (LIM_DATA, -1); +} + +#else /* not BSD4_1 and not VMS */ + +get_lim_data () +{ + struct rlimit XXrlimit; + + getrlimit (RLIMIT_DATA, &XXrlimit); +#ifdef RLIM_INFINITY + lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ +#else + lim_data = XXrlimit.rlim_cur; /* soft limit */ +#endif +} + +#endif /* not BSD4_1 and not VMS */ +#endif /* not USG */ + +#ifdef VMS +/* There is a problem when dumping and restoring things on VMS. Calls + * to SBRK don't necessarily result in contiguous allocation. Dumping + * doesn't work when it isn't. Therefore, we make the initial + * allocation contiguous by allocating a big chunk, and do SBRKs from + * there. Once Emacs has dumped there is no reason to continue + * contiguous allocation, malloc doesn't depend on it. + * + * There is a further problem of using brk and sbrk while using VMS C + * run time library routines malloc, calloc, etc. The documentation + * says that this is a no-no, although I'm not sure why this would be + * a problem. In any case, we remove the necessity to call brk and + * sbrk, by calling calloc (to assure zero filled data) rather than + * sbrk. + * + * VMS_ALLOCATION_SIZE is the size of the allocation array. This + * should be larger than the malloc size before dumping. Making this + * too large will result in the startup procedure slowing down since + * it will require more space and time to map it in. + * + * The value for VMS_ALLOCATION_SIZE in the following define was determined + * by running emacs linked (and a large allocation) with the debugger and + * looking to see how much storage was used. The allocation was 201 pages, + * so I rounded it up to a power of two. + */ +#ifndef VMS_ALLOCATION_SIZE +#define VMS_ALLOCATION_SIZE (512*256) +#endif + +/* Use VMS RTL definitions */ +#undef sbrk +#undef brk +#undef malloc +int vms_out_initial = 0; +char vms_initial_buffer[VMS_ALLOCATION_SIZE]; +static char *vms_current_brk = &vms_initial_buffer; +static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1]; + +#include <stdio.h> + +char * +sys_sbrk (incr) + int incr; +{ + char *sbrk(), *temp, *ptr; + + if (vms_out_initial) + { + /* out of initial allocation... */ + if (!(temp = malloc (incr))) + temp = (char *) -1; + } + else + { + /* otherwise, go out of our area */ + ptr = vms_current_brk + incr; /* new current_brk */ + if (ptr <= vms_end_brk) + { + temp = vms_current_brk; + vms_current_brk = ptr; + } + else + { + vms_out_initial = 1; /* mark as out of initial allocation */ + if (!(temp = malloc (incr))) + temp = (char *) -1; + } + } + return temp; +} +#endif /* VMS */ diff --git a/gnu/lib/libregex/test/fileregex.c b/gnu/lib/libregex/test/fileregex.c new file mode 100644 index 000000000000..2c27a0f5ddcd --- /dev/null +++ b/gnu/lib/libregex/test/fileregex.c @@ -0,0 +1,77 @@ +#include <sys/types.h> +#include <stdio.h> +#include "regex.h" + +#define BYTEWIDTH 8 + +/* Sorry, but this is just a test program. */ +#define LINE_MAX 500 + +int +main (argc, argv) + int argc; + char *argv[]; +{ + FILE *f; + char *filename; + char pat[500]; /* Sorry for that maximum size, too. */ + char line[LINE_MAX]; + struct re_pattern_buffer buf; + char fastmap[(1 << BYTEWIDTH)]; + const char *compile_ret; + unsigned lineno = 1; + unsigned nfound = 0; + + /* Actually, it might be useful to allow the data file to be standard + input, and to specify the pattern on the command line. */ + if (argc != 2) + { + fprintf (stderr, "Usage: %s <filename>.\n", argv[0]); + exit (1); + } + + filename = argv[1]; + f = fopen (filename, "r"); + if (f == NULL) + perror (filename); + + buf.allocated = 0; + buf.buffer = NULL; + buf.fastmap = fastmap; + + printf ("Pattern = ", pat); + gets (pat); + + if (feof (stdin)) + { + putchar ('\n'); + exit (0); + } + + compile_ret = re_compile_pattern (pat, strlen (pat), &buf); + if (compile_ret != NULL) + { + fprintf (stderr, "%s: %s\n", pat, compile_ret); + exit (1); + } + + while (fgets (line, LINE_MAX, f) != NULL) + { + size_t len = strlen (line); + struct re_registers regs; + int search_ret + = re_search_2 (&buf, NULL, 0, line, len, 0, len, ®s, len); + + if (search_ret == -2) + { + fprintf (stderr, "%s:%d: re_search failed.\n", filename, lineno); + exit (1); + } + + nfound += search_ret != -1; + lineno++; + } + + printf ("Matches found: %u (out of %u lines).\n", nfound, lineno - 1); + return 0; +} diff --git a/gnu/lib/libregex/test/g++malloc.c b/gnu/lib/libregex/test/g++malloc.c new file mode 100644 index 000000000000..d55ce45643d3 --- /dev/null +++ b/gnu/lib/libregex/test/g++malloc.c @@ -0,0 +1,1288 @@ +#define inline + +/* +Copyright (C) 1989 Free Software Foundation + written by Doug Lea (dl@oswego.edu) + +This file is part of GNU CC. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the GNU CC General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +GNU CC, but only under the conditions described in the +GNU CC General Public License. A copy of this license is +supposed to have been given to you along with GNU CC so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. +*/ + + + +#ifndef NO_LIBGXX_MALLOC /* ignore whole file otherwise */ + +/* compile with -DMALLOC_STATS to collect statistics */ +/* collecting statistics slows down malloc by at least 15% */ + +#ifdef MALLOC_STATS +#define UPDATE_STATS(ARGS) {ARGS;} +#else +#define UPDATE_STATS(ARGS) +#endif + +/* History + + + Tue Jan 16 04:54:27 1990 Doug Lea (dl at g.oswego.edu) + + version 1 released in libg++ + + Sun Jan 21 05:52:47 1990 Doug Lea (dl at g.oswego.edu) + + bins are now own struct for, sanity. + + new victim search strategy: scan up and consolidate. + Both faster and less fragmentation. + + refined when to scan bins for consolidation, via consollink, etc. + + realloc: always try to expand chunk, avoiding some fragmentation. + + changed a few inlines into macros + + hardwired SBRK_UNIT to 4096 for uniformity across systems + + Tue Mar 20 14:18:23 1990 Doug Lea (dl at g.oswego.edu) + + calloc and cfree now correctly parameterized. + + Sun Apr 1 10:00:48 1990 Doug Lea (dl at g.oswego.edu) + + added memalign and valloc. + + Sun Jun 24 05:46:48 1990 Doug Lea (dl at g.oswego.edu) + + #include gepagesize.h only ifndef sun + cache pagesize after first call + + Wed Jul 25 08:35:19 1990 Doug Lea (dl at g.oswego.edu) + + No longer rely on a `designated victim': + + 1. It sometimes caused splits of large chunks + when smaller ones would do, leading to + bad worst-case fragmentation. + + 2. Scanning through the av array fast anyway, + so the overhead isn't worth it. + + To compensate, several other minor changes: + + 1. Unusable chunks are checked for consolidation during + searches inside bins, better distributing chunks + across bins. + + 2. Chunks are returned when found in malloc_find_space, + rather than finishing cleaning everything up, to + avoid wasted iterations due to (1). +*/ + +/* + A version of malloc/free/realloc tuned for C++ applications. + + Here's what you probably want to know first: + + In various tests, this appears to be about as fast as, + and usually substantially less memory-wasteful than BSD/GNUemacs malloc. + + Generally, it is slower (by perhaps 20%) than bsd-style malloc + only when bsd malloc would waste a great deal of space in + fragmented blocks, which this malloc recovers; or when, by + chance or design, nearly all requests are near the bsd malloc + power-of-2 allocation bin boundaries, and as many chunks are + used as are allocated. + + It uses more space than bsd malloc only when, again by chance + or design, only bsdmalloc bin-sized requests are malloced, or when + little dynamic space is malloced, since this malloc may grab larger + chunks from the system at a time than bsd. + + In other words, this malloc seems generally superior to bsd + except perhaps for programs that are specially tuned to + deal with bsdmalloc's characteristics. But even here, the + performance differences are slight. + + + This malloc, like any other, is a compromised design. + + + Chunks of memory are maintained using a `boundary tag' method as + described in e.g., Knuth or Standish. This means that the size of + the chunk is stored both in the front of the chunk and at the end. + This makes consolidating fragmented chunks into bigger chunks very fast. + The size field is also used to hold bits representing whether a + chunk is free or in use. + + Malloced chunks have space overhead of 8 bytes: The preceding + and trailing size fields. When they are freed, the list pointer + fields are also needed. + + Available chunks are kept in doubly linked lists. The lists are + maintained in an array of bins using a power-of-two method, except + that instead of 32 bins (one for each 1 << i), there are 128: each + power of two is split in quarters. The use of very fine bin sizes + closely approximates the use of one bin per actually used size, + without necessitating the overhead of locating such bins. It is + especially desirable in common C++ applications where large numbers + of identically-sized blocks are malloced/freed in some dynamic + manner, and then later are all freed. The finer bin sizes make + finding blocks fast, with little wasted overallocation. The + consolidation methods ensure that once the collection of blocks is + no longer useful, fragments are gathered into bigger chunks awaiting new + roles. + + The bins av[i] serve as heads of the lists. Bins contain a dummy + header for the chunk lists, and a `dirty' field used to indicate + whether the list may need to be scanned for consolidation. + + On allocation, the bin corresponding to the request size is + scanned, and if there is a chunk with size >= requested, it + is split, if too big, and used. Chunks on the list which are + too small are examined for consolidation during this traversal. + + If no chunk exists in the list bigger bins are scanned in search of + a victim. + + If no victim can be found, then smaller bins are examined for + consolidation in order to construct a victim. + + Finally, if consolidation fails to come up with a usable chunk, + more space is obtained from the system. + + After a split, the remainder is placed on + the back of the appropriate bin list. (All freed chunks are placed + on fronts of lists. All remaindered or consolidated chunks are + placed on the rear. Correspondingly, searching within a bin + starts at the front, but finding victims is from the back. All + of this approximates the effect of having 2 kinds of lists per + bin: returned chunks vs unallocated chunks, but without the overhead + of maintaining 2 lists.) + + Deallocation (free) consists only of placing the chunk on + a list. + + Reallocation proceeds in the usual way. If a chunk can be extended, + it is, else a malloc-copy-free sequence is taken. + + memalign requests more than enough space from malloc, finds a + spot within that chunk that meets the alignment request, and + then possibly frees the leading and trailing space. Overreliance + on memalign is a sure way to fragment space. + + + Some other implementation matters: + + 8 byte alignment is currently hardwired into the design. Calling + memalign will return a chunk that is both 8-byte aligned, and + meets the requested alignment. + + The basic overhead of a used chunk is 8 bytes: 4 at the front and + 4 at the end. + + When a chunk is free, 8 additional bytes are needed for free list + pointers. Thus, the minimum allocatable size is 16 bytes. + + The existence of front and back overhead permits some reasonably + effective fence-bashing checks: The front and back fields must + be identical. This is checked only within free() and realloc(). + The checks are fast enough to be made non-optional. + + The overwriting of parts of freed memory with the freelist pointers + can also be very effective (albeit in an annoying way) in helping + users track down dangling pointers. + + User overwriting of freed space will often result in crashes + within malloc or free. + + These routines are also tuned to C++ in that free(0) is a noop and + a failed malloc automatically calls (*new_handler)(). + + malloc(0) returns a pointer to something of the minimum allocatable size. + + Additional memory is gathered from the system (via sbrk) in a + way that allows chunks obtained across different sbrk calls to + be consolidated, but does not require contiguous memory: Thus, + it should be safe to intersperse mallocs with other sbrk calls. + + This malloc is NOT designed to work in multiprocessing applications. + No semaphores or other concurrency control are provided to ensure + that multiple malloc or free calls don't run at the same time, + which could be disasterous. + + VERY heavy use of inlines is made, for clarity. If this malloc + is ported via a compiler without inlining capabilities, all + inlines should be transformed into macros -- making them non-inline + makes malloc at least twice as slow. + + +*/ + + +/* preliminaries */ + +#ifdef __cplusplus +#include <stdio.h> +#else +#include "//usr/include/stdio.h" /* needed for error reporting */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef USG +extern void* memset(void*, int, int); +extern void* memcpy(void*, const void*, int); +/*inline void bzero(void* s, int l) { memset(s, 0, l); }*/ +#else +/*extern void bzero(void*, unsigned int);*/ +#endif + +/*extern void bcopy(void*, void*, unsigned int);*/ + +extern void* sbrk(unsigned int); + +/* Put this in instead of commmented out stuff above. */ +#define bcopy(s,d,n) memcpy((d),(s),(n)) +#define bcmp(s1,s2,n) memcmp((s1),(s2),(n)) +#define bzero(s,n) memset((s),0,(n)) + + +#ifdef __GNUC__ +extern volatile void abort(); +#else +extern void abort(); +#endif + +#ifdef __cplusplus +}; /* end of extern "C" */ +#endif + + +/* A good multiple to call sbrk with */ + +#define SBRK_UNIT 4096 + + + +/* how to die on detected error */ + +#ifdef __GNUC__ +static volatile void malloc_user_error() +#else +static void malloc_user_error() +#endif +{ + fputs("malloc/free/realloc: clobbered space detected\n", stderr); abort(); +} + + + +/* Basic overhead for each malloc'ed chunk */ + + +struct malloc_chunk +{ + unsigned int size; /* Size in bytes, including overhead. */ + /* Or'ed with INUSE if in use. */ + + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; + +}; + +typedef struct malloc_chunk* mchunkptr; + +struct malloc_bin +{ + struct malloc_chunk hd; /* dummy list header */ + unsigned int dirty; /* True if maybe consolidatable */ + /* Wasting a word here makes */ + /* sizeof(bin) a power of 2, */ + /* which makes size2bin() faster */ +}; + +typedef struct malloc_bin* mbinptr; + + +/* sizes, alignments */ + + +#define SIZE_SZ (sizeof(unsigned int)) +#define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ) +#define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1) + +#define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ) /* MUST == 16! */ + + +/* pad request bytes into a usable size */ + +static inline unsigned int request2size(unsigned int request) +{ + return (request == 0) ? MINSIZE : + ((request + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) + & ~(MALLOC_ALIGN_MASK)); +} + + +static inline int aligned_OK(void* m) +{ + return ((unsigned int)(m) & (MALLOC_ALIGN_MASK)) == 0; +} + + +/* size field or'd with INUSE when in use */ +#define INUSE 0x1 + + + +/* the bins, initialized to have null double linked lists */ + +#define MAXBIN 120 /* 1 more than needed for 32 bit addresses */ + +#define FIRSTBIN (&(av[0])) + +static struct malloc_bin av[MAXBIN] = +{ + { { 0, &(av[0].hd), &(av[0].hd) }, 0 }, + { { 0, &(av[1].hd), &(av[1].hd) }, 0 }, + { { 0, &(av[2].hd), &(av[2].hd) }, 0 }, + { { 0, &(av[3].hd), &(av[3].hd) }, 0 }, + { { 0, &(av[4].hd), &(av[4].hd) }, 0 }, + { { 0, &(av[5].hd), &(av[5].hd) }, 0 }, + { { 0, &(av[6].hd), &(av[6].hd) }, 0 }, + { { 0, &(av[7].hd), &(av[7].hd) }, 0 }, + { { 0, &(av[8].hd), &(av[8].hd) }, 0 }, + { { 0, &(av[9].hd), &(av[9].hd) }, 0 }, + + { { 0, &(av[10].hd), &(av[10].hd) }, 0 }, + { { 0, &(av[11].hd), &(av[11].hd) }, 0 }, + { { 0, &(av[12].hd), &(av[12].hd) }, 0 }, + { { 0, &(av[13].hd), &(av[13].hd) }, 0 }, + { { 0, &(av[14].hd), &(av[14].hd) }, 0 }, + { { 0, &(av[15].hd), &(av[15].hd) }, 0 }, + { { 0, &(av[16].hd), &(av[16].hd) }, 0 }, + { { 0, &(av[17].hd), &(av[17].hd) }, 0 }, + { { 0, &(av[18].hd), &(av[18].hd) }, 0 }, + { { 0, &(av[19].hd), &(av[19].hd) }, 0 }, + + { { 0, &(av[20].hd), &(av[20].hd) }, 0 }, + { { 0, &(av[21].hd), &(av[21].hd) }, 0 }, + { { 0, &(av[22].hd), &(av[22].hd) }, 0 }, + { { 0, &(av[23].hd), &(av[23].hd) }, 0 }, + { { 0, &(av[24].hd), &(av[24].hd) }, 0 }, + { { 0, &(av[25].hd), &(av[25].hd) }, 0 }, + { { 0, &(av[26].hd), &(av[26].hd) }, 0 }, + { { 0, &(av[27].hd), &(av[27].hd) }, 0 }, + { { 0, &(av[28].hd), &(av[28].hd) }, 0 }, + { { 0, &(av[29].hd), &(av[29].hd) }, 0 }, + + { { 0, &(av[30].hd), &(av[30].hd) }, 0 }, + { { 0, &(av[31].hd), &(av[31].hd) }, 0 }, + { { 0, &(av[32].hd), &(av[32].hd) }, 0 }, + { { 0, &(av[33].hd), &(av[33].hd) }, 0 }, + { { 0, &(av[34].hd), &(av[34].hd) }, 0 }, + { { 0, &(av[35].hd), &(av[35].hd) }, 0 }, + { { 0, &(av[36].hd), &(av[36].hd) }, 0 }, + { { 0, &(av[37].hd), &(av[37].hd) }, 0 }, + { { 0, &(av[38].hd), &(av[38].hd) }, 0 }, + { { 0, &(av[39].hd), &(av[39].hd) }, 0 }, + + { { 0, &(av[40].hd), &(av[40].hd) }, 0 }, + { { 0, &(av[41].hd), &(av[41].hd) }, 0 }, + { { 0, &(av[42].hd), &(av[42].hd) }, 0 }, + { { 0, &(av[43].hd), &(av[43].hd) }, 0 }, + { { 0, &(av[44].hd), &(av[44].hd) }, 0 }, + { { 0, &(av[45].hd), &(av[45].hd) }, 0 }, + { { 0, &(av[46].hd), &(av[46].hd) }, 0 }, + { { 0, &(av[47].hd), &(av[47].hd) }, 0 }, + { { 0, &(av[48].hd), &(av[48].hd) }, 0 }, + { { 0, &(av[49].hd), &(av[49].hd) }, 0 }, + + { { 0, &(av[50].hd), &(av[50].hd) }, 0 }, + { { 0, &(av[51].hd), &(av[51].hd) }, 0 }, + { { 0, &(av[52].hd), &(av[52].hd) }, 0 }, + { { 0, &(av[53].hd), &(av[53].hd) }, 0 }, + { { 0, &(av[54].hd), &(av[54].hd) }, 0 }, + { { 0, &(av[55].hd), &(av[55].hd) }, 0 }, + { { 0, &(av[56].hd), &(av[56].hd) }, 0 }, + { { 0, &(av[57].hd), &(av[57].hd) }, 0 }, + { { 0, &(av[58].hd), &(av[58].hd) }, 0 }, + { { 0, &(av[59].hd), &(av[59].hd) }, 0 }, + + { { 0, &(av[60].hd), &(av[60].hd) }, 0 }, + { { 0, &(av[61].hd), &(av[61].hd) }, 0 }, + { { 0, &(av[62].hd), &(av[62].hd) }, 0 }, + { { 0, &(av[63].hd), &(av[63].hd) }, 0 }, + { { 0, &(av[64].hd), &(av[64].hd) }, 0 }, + { { 0, &(av[65].hd), &(av[65].hd) }, 0 }, + { { 0, &(av[66].hd), &(av[66].hd) }, 0 }, + { { 0, &(av[67].hd), &(av[67].hd) }, 0 }, + { { 0, &(av[68].hd), &(av[68].hd) }, 0 }, + { { 0, &(av[69].hd), &(av[69].hd) }, 0 }, + + { { 0, &(av[70].hd), &(av[70].hd) }, 0 }, + { { 0, &(av[71].hd), &(av[71].hd) }, 0 }, + { { 0, &(av[72].hd), &(av[72].hd) }, 0 }, + { { 0, &(av[73].hd), &(av[73].hd) }, 0 }, + { { 0, &(av[74].hd), &(av[74].hd) }, 0 }, + { { 0, &(av[75].hd), &(av[75].hd) }, 0 }, + { { 0, &(av[76].hd), &(av[76].hd) }, 0 }, + { { 0, &(av[77].hd), &(av[77].hd) }, 0 }, + { { 0, &(av[78].hd), &(av[78].hd) }, 0 }, + { { 0, &(av[79].hd), &(av[79].hd) }, 0 }, + + { { 0, &(av[80].hd), &(av[80].hd) }, 0 }, + { { 0, &(av[81].hd), &(av[81].hd) }, 0 }, + { { 0, &(av[82].hd), &(av[82].hd) }, 0 }, + { { 0, &(av[83].hd), &(av[83].hd) }, 0 }, + { { 0, &(av[84].hd), &(av[84].hd) }, 0 }, + { { 0, &(av[85].hd), &(av[85].hd) }, 0 }, + { { 0, &(av[86].hd), &(av[86].hd) }, 0 }, + { { 0, &(av[87].hd), &(av[87].hd) }, 0 }, + { { 0, &(av[88].hd), &(av[88].hd) }, 0 }, + { { 0, &(av[89].hd), &(av[89].hd) }, 0 }, + + { { 0, &(av[90].hd), &(av[90].hd) }, 0 }, + { { 0, &(av[91].hd), &(av[91].hd) }, 0 }, + { { 0, &(av[92].hd), &(av[92].hd) }, 0 }, + { { 0, &(av[93].hd), &(av[93].hd) }, 0 }, + { { 0, &(av[94].hd), &(av[94].hd) }, 0 }, + { { 0, &(av[95].hd), &(av[95].hd) }, 0 }, + { { 0, &(av[96].hd), &(av[96].hd) }, 0 }, + { { 0, &(av[97].hd), &(av[97].hd) }, 0 }, + { { 0, &(av[98].hd), &(av[98].hd) }, 0 }, + { { 0, &(av[99].hd), &(av[99].hd) }, 0 }, + + { { 0, &(av[100].hd), &(av[100].hd) }, 0 }, + { { 0, &(av[101].hd), &(av[101].hd) }, 0 }, + { { 0, &(av[102].hd), &(av[102].hd) }, 0 }, + { { 0, &(av[103].hd), &(av[103].hd) }, 0 }, + { { 0, &(av[104].hd), &(av[104].hd) }, 0 }, + { { 0, &(av[105].hd), &(av[105].hd) }, 0 }, + { { 0, &(av[106].hd), &(av[106].hd) }, 0 }, + { { 0, &(av[107].hd), &(av[107].hd) }, 0 }, + { { 0, &(av[108].hd), &(av[108].hd) }, 0 }, + { { 0, &(av[109].hd), &(av[109].hd) }, 0 }, + + { { 0, &(av[110].hd), &(av[110].hd) }, 0 }, + { { 0, &(av[111].hd), &(av[111].hd) }, 0 }, + { { 0, &(av[112].hd), &(av[112].hd) }, 0 }, + { { 0, &(av[113].hd), &(av[113].hd) }, 0 }, + { { 0, &(av[114].hd), &(av[114].hd) }, 0 }, + { { 0, &(av[115].hd), &(av[115].hd) }, 0 }, + { { 0, &(av[116].hd), &(av[116].hd) }, 0 }, + { { 0, &(av[117].hd), &(av[117].hd) }, 0 }, + { { 0, &(av[118].hd), &(av[118].hd) }, 0 }, + { { 0, &(av[119].hd), &(av[119].hd) }, 0 } +}; + +/* + indexing into bins +*/ + +static inline mbinptr size2bin(unsigned int sz) +{ + mbinptr b = av; + while (sz >= (MINSIZE * 2)) { b += 4; sz >>= 1; } /* find power of 2 */ + b += (sz - MINSIZE) >> 2; /* find quadrant */ + return b; +} + + + +/* counts maintained if MALLOC_STATS defined */ + +#ifdef MALLOC_STATS + +static unsigned int sbrked_mem; +static unsigned int requested_mem; +static unsigned int malloced_mem; +static unsigned int freed_mem; +static unsigned int max_used_mem; + +static unsigned int n_sbrks; +static unsigned int n_mallocs; +static unsigned int n_frees; +static unsigned int n_reallocs; +static unsigned int n_reallocs_with_copy; +static unsigned int n_avail; +static unsigned int max_inuse; + +static unsigned int n_malloc_chunks; +static unsigned int n_malloc_bins; + +static unsigned int n_split; +static unsigned int n_consol; + + +static void do_malloc_stats(const mchunkptr p) +{ + ++n_mallocs; + if ((n_mallocs-n_frees) > max_inuse) + max_inuse = n_mallocs - n_frees; + malloced_mem += (p->size & ~(INUSE)); + if (malloced_mem - freed_mem > max_used_mem) + max_used_mem = malloced_mem - freed_mem; +} + +static void do_free_stats(const mchunkptr p) +{ + ++n_frees; + freed_mem += (p->size & ~(INUSE)); +} + +#endif + + + +/* Utilities needed below for memalign */ +/* This is redundant with libg++ support, but not if used stand-alone */ + +static unsigned int gcd(unsigned int a, unsigned int b) +{ + unsigned int tmp; + + if (b > a) + { + tmp = a; a = b; b = tmp; + } + for(;;) + { + if (b == 0) + return a; + else if (b == 1) + return b; + else + { + tmp = b; + b = a % b; + a = tmp; + } + } +} + +static inline unsigned int lcm(unsigned int x, unsigned int y) +{ + return x / gcd(x, y) * y; +} + + + +/* maintaining INUSE via size field */ + + +#define inuse(p) ((p)->size & INUSE) +#define set_inuse(p) ((p)->size |= INUSE) +#define clear_inuse(b) ((p)->size &= ~INUSE) + + +/* operations on malloc_chunk addresses */ + + +/* return ptr to next physical malloc_chunk */ + +#define next_chunk(p) ((mchunkptr)((char*)(p) + (p)->size)) + +/* return ptr to previous physical malloc_chunk */ + +#define prev_chunk(p) ((mchunkptr)((char*)(p)-((((int*)(p))[-1]) & ~(INUSE)))) + +/* place size at front and back of chunk */ + + +static inline void set_size(mchunkptr p, unsigned int sz) +{ + p->size = *((int*)((char*)(p) + sz - SIZE_SZ)) = sz; +} + + + + +/* conversion from malloc headers to user pointers, and back */ + +static inline void* chunk2mem(mchunkptr p) +{ + void *mem; + set_inuse(p); +mem = (void*)((char*)(p) + SIZE_SZ); + return mem; +} + +/* xxxx my own */ +mchunkptr sanity_check(void* mem) +{ + mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ); + + /* a quick sanity check */ + unsigned int sz = p->size & ~(INUSE); + if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ))) + malloc_user_error(); + + return p; +} + + + + +static inline mchunkptr mem2chunk(void* mem) +{ + mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ); + + /* a quick sanity check */ + unsigned int sz = p->size & ~(INUSE); + if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ))) + malloc_user_error(); + + p->size = sz; /* clears INUSE */ + return p; +} + + + +/* maintaining bins & pointers */ + + +/* maximum bin actually used */ + +static mbinptr malloc_maxbin = FIRSTBIN; + + +/* operations on lists inside bins */ + + +/* take a chunk off a list */ + +static inline void unlink(mchunkptr p) +{ + mchunkptr b = p->bk; + mchunkptr f = p->fd; + + f->bk = b; b->fd = f; + + UPDATE_STATS (--n_avail); +} + + + +/* split a chunk and place on the back of a list */ + +static inline void split(mchunkptr p, unsigned int offset) +{ + unsigned int room = p->size - offset; + if (room >= MINSIZE) + { + mbinptr bn = size2bin(room); /* new bin */ + mchunkptr h = &(bn->hd); /* its head */ + mchunkptr b = h->bk; /* old back element */ + mchunkptr t = (mchunkptr)((char*)(p) + offset); /* remaindered chunk */ + + /* set size */ + t->size = *((int*)((char*)(t) + room - SIZE_SZ)) = room; + + /* link up */ + t->bk = b; t->fd = h; h->bk = b->fd = t; + + /* adjust maxbin (h == b means was empty) */ + if (h == b && bn > malloc_maxbin) malloc_maxbin = bn; + + /* adjust size of chunk to be returned */ + p->size = *((int*)((char*)(p) + offset - SIZE_SZ)) = offset; + + UPDATE_STATS ((++n_split, ++n_avail)); + } +} + + + +/* place a consolidated chunk on the back of a list */ +/* like above, except no split */ + +static inline void consollink(mchunkptr p) +{ + mbinptr bn = size2bin(p->size); + mchunkptr h = &(bn->hd); + mchunkptr b = h->bk; + + p->bk = b; p->fd = h; h->bk = b->fd = p; + + if (h == b && bn > malloc_maxbin) malloc_maxbin = bn; + + UPDATE_STATS(++n_avail); +} + + +/* place a freed chunk on the front of a list */ + +static inline void frontlink(mchunkptr p) +{ + mbinptr bn = size2bin(p->size); + mchunkptr h = &(bn->hd); + mchunkptr f = h->fd; + + p->bk = h; p->fd = f; f->bk = h->fd = p; + + if (h == f && bn > malloc_maxbin) malloc_maxbin = bn; + + bn->dirty = 1; + + UPDATE_STATS(++n_avail); +} + + + +/* Dealing with sbrk */ + + +/* To link consecutive sbrk regions when possible */ + +static int* last_sbrk_end; + + +/* who to call when sbrk returns failure */ + +#ifndef NO_NEW_HANDLER +typedef volatile void (*vfp)(); +#ifdef __cplusplus +extern "C" vfp __new_handler; +#else +extern vfp __new_handler; +#endif +#endif + +static mchunkptr malloc_from_sys(unsigned nb) +{ + mchunkptr p; + unsigned int sbrk_size; + int* ip; + + /* Minimally, we need to pad with enough space */ + /* to place dummy size/use fields to ends if needed */ + + sbrk_size = ((nb + SBRK_UNIT - 1 + SIZE_SZ + SIZE_SZ) + / SBRK_UNIT) * SBRK_UNIT; + + ip = (int*)(sbrk(sbrk_size)); + if ((char*)ip == (char*)(-1)) /* sbrk returns -1 on failure */ + { +#ifndef NO_NEW_HANDLER + (*__new_handler) (); +#endif + return 0; + } + + UPDATE_STATS ((++n_sbrks, sbrked_mem += sbrk_size)); + + + if (last_sbrk_end != &ip[-1]) + { + /* It's either first time through or someone else called sbrk. */ + /* Arrange end-markers at front & back */ + + /* Shouldn't be necessary, but better to be safe */ + while (!aligned_OK(ip)) { ++ip; sbrk_size -= SIZE_SZ; } + + + /* Mark the front as in use to prevent merging. */ + /* Note we can get away with only 1 word, not MINSIZE overhead here */ + + *ip++ = SIZE_SZ | INUSE; + + p = (mchunkptr)ip; + set_size(p,sbrk_size - (SIZE_SZ + SIZE_SZ)); + + } + else + { + mchunkptr l; + + /* We can safely make the header start at end of prev sbrked chunk. */ + /* We will still have space left at the end from a previous call */ + /* to place the end marker, below */ + + p = (mchunkptr)(last_sbrk_end); + set_size(p, sbrk_size); + + + /* Even better, maybe we can merge with last fragment: */ + + l = prev_chunk(p); + if (!inuse(l)) + { + unlink(l); + set_size(l, p->size + l->size); + p = l; + } + + } + + /* mark the end of sbrked space as in use to prevent merging */ + + last_sbrk_end = (int*)((char*)p + p->size); + *last_sbrk_end = SIZE_SZ | INUSE; + + UPDATE_STATS((++n_avail, ++n_malloc_chunks)); + + /* make it safe to unlink in malloc */ + UPDATE_STATS(++n_avail); + p->fd = p->bk = p; + + return p; +} + + + +/* Consolidate dirty bins. */ +/* Stop if found a chunk big enough to satisfy current malloc request */ + +/* (It requires much less bookkeeping to consolidate entire bins */ +/* at once than to keep records of which chunks might be */ +/* consolidatable. So long as the lists are short, which we */ +/* try to ensure via small bin ranges, there is little wasted effort.) */ + +static mchunkptr malloc_find_space(unsigned int nb) +{ + mbinptr b; + + /* first, re-adjust max used bin */ + + while (malloc_maxbin >= FIRSTBIN && + malloc_maxbin->hd.bk == &(malloc_maxbin->hd)) + { + malloc_maxbin->dirty = 0; + --malloc_maxbin; + } + + for (b = malloc_maxbin; b >= FIRSTBIN; --b) + { + UPDATE_STATS(++n_malloc_bins); + + if (b->dirty) + { + mchunkptr h = &(b->hd); /* head of list */ + mchunkptr p = h->fd; /* chunk traverser */ + + while (p != h) + { + mchunkptr nextp = p->fd; /* save, in case of relinks */ + int consolidated = 0; /* only unlink/relink if consolidated */ + + mchunkptr t; + + UPDATE_STATS(++n_malloc_chunks); + + while (!inuse(t = prev_chunk(p))) /* consolidate backward */ + { + if (!consolidated) { consolidated = 1; unlink(p); } + if (t == nextp) nextp = t->fd; + unlink(t); + set_size(t, t->size + p->size); + p = t; + UPDATE_STATS (++n_consol); + } + + while (!inuse(t = next_chunk(p))) /* consolidate forward */ + { + if (!consolidated) { consolidated = 1; unlink(p); } + if (t == nextp) nextp = t->fd; + unlink(t); + set_size(p, p->size + t->size); + UPDATE_STATS (++n_consol); + } + + if (consolidated) + { + if (p->size >= nb) + { + /* make it safe to unlink in malloc */ + UPDATE_STATS(++n_avail); + p->fd = p->bk = p; + return p; + } + else + consollink(p); + } + + p = nextp; + + } + + b->dirty = 0; + + } + } + + /* nothing available - sbrk some more */ + + return malloc_from_sys(nb); +} + + + +/* Finally, the user-level functions */ + +void* malloc(unsigned int bytes) +{ + unsigned int nb = request2size(bytes); /* padded request size */ + mbinptr b = size2bin(nb); /* corresponding bin */ + mchunkptr hd = &(b->hd); /* head of its list */ + mchunkptr p = hd->fd; /* chunk traverser */ + + UPDATE_STATS((requested_mem+=bytes, ++n_malloc_bins)); + + /* Try a (near) exact match in own bin */ + /* clean out unusable but consolidatable chunks in bin while traversing */ + + while (p != hd) + { + UPDATE_STATS(++n_malloc_chunks); + if (p->size >= nb) + goto found; + else /* try to consolidate; same code as malloc_find_space */ + { + mchunkptr nextp = p->fd; /* save, in case of relinks */ + int consolidated = 0; /* only unlink/relink if consolidated */ + + mchunkptr t; + + while (!inuse(t = prev_chunk(p))) /* consolidate backward */ + { + if (!consolidated) { consolidated = 1; unlink(p); } + if (t == nextp) nextp = t->fd; + unlink(t); + set_size(t, t->size + p->size); + p = t; + UPDATE_STATS (++n_consol); + } + + while (!inuse(t = next_chunk(p))) /* consolidate forward */ + { + if (!consolidated) { consolidated = 1; unlink(p); } + if (t == nextp) nextp = t->fd; + unlink(t); + set_size(p, p->size + t->size); + UPDATE_STATS (++n_consol); + } + + if (consolidated) + { + if (p->size >= nb) + { + /* make it safe to unlink again below */ + UPDATE_STATS(++n_avail); + p->fd = p->bk = p; + goto found; + } + else + consollink(p); + } + + p = nextp; + + } + } + + b->dirty = 0; /* true if got here */ + + /* Scan bigger bins for a victim */ + + while (++b <= malloc_maxbin) + { + UPDATE_STATS(++n_malloc_bins); + if ((p = b->hd.bk) != &(b->hd)) /* no need to check size */ + goto found; + } + + /* Consolidate or sbrk */ + + p = malloc_find_space(nb); + + if (p == 0) return 0; /* allocation failure */ + + found: /* Use what we found */ + + unlink(p); + split(p, nb); + UPDATE_STATS(do_malloc_stats(p)); + return chunk2mem(p); +} + + + + +void free(void* mem) +{ + if (mem != 0) + { + mchunkptr p = mem2chunk(mem); + UPDATE_STATS(do_free_stats(p)); + frontlink(p); + } +} + + +void* calloc(unsigned int n, unsigned int elem_size) +{ + unsigned int sz = n * elem_size; + void* p = malloc(sz); + bzero(p, sz); + return p; +}; + +/* This is here for compatibility with older systems */ +void cfree(void *mem) +{ + free(mem); +} + + +unsigned int malloc_usable_size(void* mem) +{ + if (mem == 0) + return 0; + else + { + mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ); + unsigned int sz = p->size & ~(INUSE); + if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ))) + return 0; + else + return sz - MALLOC_MIN_OVERHEAD; + } +} + + + +void* realloc(void* mem, unsigned int bytes) +{ + if (mem == 0) + return malloc(bytes); + else + { + unsigned int nb = request2size(bytes); + mchunkptr p = mem2chunk(mem); + unsigned int oldsize = p->size; + int room; + mchunkptr nxt; + + UPDATE_STATS((++n_reallocs, requested_mem += bytes-oldsize)); + + /* try to expand (even if already big enough), to clean up chunk */ + + while (!inuse(nxt = next_chunk(p))) + { + UPDATE_STATS ((malloced_mem += nxt->size, ++n_consol)); + unlink(nxt); + set_size(p, p->size + nxt->size); + } + + room = p->size - nb; + if (room >= 0) + { + split(p, nb); + UPDATE_STATS(malloced_mem -= room); + return chunk2mem(p); + } + else /* do the obvious */ + { + void* newmem; + set_inuse(p); /* don't let malloc consolidate us yet! */ + newmem = malloc(nb); + bcopy(mem, newmem, oldsize - SIZE_SZ); + free(mem); + UPDATE_STATS(++n_reallocs_with_copy); + return newmem; + } + } +} + + + +/* return a pointer to space with at least the alignment requested */ + +void* memalign(unsigned int alignment, unsigned int bytes) +{ + mchunkptr p; + unsigned int nb = request2size(bytes); + + /* find an alignment that both we and the user can live with: */ + /* least common multiple guarantees mutual happiness */ + unsigned int align = lcm(alignment, MALLOC_MIN_OVERHEAD); + unsigned int mask = align - 1; + + /* call malloc with worst case padding to hit alignment; */ + /* we will give back extra */ + + unsigned int req = nb + align + MINSIZE; + void* m = malloc(req); + + if (m == 0) return m; + + p = mem2chunk(m); + + /* keep statistics on track */ + + UPDATE_STATS(--n_mallocs); + UPDATE_STATS(malloced_mem -= p->size); + UPDATE_STATS(requested_mem -= req); + UPDATE_STATS(requested_mem += bytes); + + if (((int)(m) & (mask)) != 0) /* misaligned */ + { + + /* find an aligned spot inside chunk */ + + mchunkptr ap = (mchunkptr)(( ((int)(m) + mask) & -align) - SIZE_SZ); + + unsigned int gap = (unsigned int)(ap) - (unsigned int)(p); + unsigned int room; + + /* we need to give back leading space in a chunk of at least MINSIZE */ + + if (gap < MINSIZE) + { + /* This works since align >= MINSIZE */ + /* and we've malloc'd enough total room */ + + ap = (mchunkptr)( (int)(ap) + align ); + gap += align; + } + + if (gap + nb > p->size) /* can't happen unless chunk sizes corrupted */ + malloc_user_error(); + + room = p->size - gap; + + /* give back leader */ + set_size(p, gap); + consollink(p); + + /* use the rest */ + p = ap; + set_size(p, room); + } + + /* also give back spare room at the end */ + + split(p, nb); + UPDATE_STATS(do_malloc_stats(p)); + return chunk2mem(p); + +} + +#ifndef sun +#include "getpagesize.h" +#endif + +static unsigned int malloc_pagesize = 0; + +void* valloc(unsigned int bytes) +{ + if (malloc_pagesize == 0) malloc_pagesize = getpagesize(); + return memalign (malloc_pagesize, bytes); +} + + +void malloc_stats() +{ +#ifndef MALLOC_STATS +} +#else + int i; + mchunkptr p; + double nm = (double)(n_mallocs + n_reallocs); + + fprintf(stderr, "\nmalloc statistics\n\n"); + + if (n_mallocs != 0) + fprintf(stderr, "requests = %10u total size = %10u\tave = %10u\n", + n_mallocs, requested_mem, requested_mem/n_mallocs); + + if (n_mallocs != 0) + fprintf(stderr, "mallocs = %10u total size = %10u\tave = %10u\n", + n_mallocs, malloced_mem, malloced_mem/n_mallocs); + + if (n_frees != 0) + fprintf(stderr, "frees = %10u total size = %10u\tave = %10u\n", + n_frees, freed_mem, freed_mem/n_frees); + + if (n_mallocs-n_frees != 0) + fprintf(stderr, "in use = %10u total size = %10u\tave = %10u\n", + n_mallocs-n_frees, malloced_mem-freed_mem, + (malloced_mem-freed_mem) / (n_mallocs-n_frees)); + + if (max_inuse != 0) + fprintf(stderr, "max in use= %10u total size = %10u\tave = %10u\n", + max_inuse, max_used_mem, max_used_mem / max_inuse); + + if (n_avail != 0) + fprintf(stderr, "available = %10u total size = %10u\tave = %10u\n", + n_avail, sbrked_mem - (malloced_mem-freed_mem), + (sbrked_mem - (malloced_mem-freed_mem)) / n_avail); + + if (n_sbrks != 0) + fprintf(stderr, "sbrks = %10u total size = %10u\tave = %10u\n\n", + n_sbrks, sbrked_mem, sbrked_mem/ n_sbrks); + + if (n_reallocs != 0) + fprintf(stderr, "reallocs = %10u with copy = %10u\n\n", + n_reallocs, n_reallocs_with_copy); + + + if (nm != 0) + { + fprintf(stderr, "chunks scanned per malloc = %6.3f\n", + n_malloc_chunks / nm); + fprintf(stderr, "bins scanned per malloc = %6.3f\n", + n_malloc_bins / nm); + fprintf(stderr, "splits per malloc = %6.3f\n", + n_split / nm); + fprintf(stderr, "consolidations per malloc = %6.3f\n", + n_consol / nm); + } + + fprintf(stderr, "\nfree chunks:\n"); + for (i = 0; i < MAXBIN; ++i) + { + p = av[i].hd.fd; + if (p != &(av[i].hd)) + { + unsigned int count = 1; + unsigned int sz = p->size; + for (p = p->fd; p != &(av[i].hd); p = p->fd) + { + if (p->size == sz) + ++count; + else + { + fprintf(stderr, "\tsize = %10u count = %5u\n", sz, count); + count = 1; + sz = p->size; + } + } + + fprintf(stderr, "\tsize = %10u count = %5u\n", sz, count); + + } + } +} +#endif /* MALLOC_STATS */ + +#endif /* NO_LIBGXX_MALLOC */ + + diff --git a/gnu/lib/libregex/test/getpagesize.h b/gnu/lib/libregex/test/getpagesize.h new file mode 100644 index 000000000000..32adae61efa2 --- /dev/null +++ b/gnu/lib/libregex/test/getpagesize.h @@ -0,0 +1,25 @@ +#ifdef BSD +#ifndef BSD4_1 +#define HAVE_GETPAGESIZE +#endif +#endif + +#ifndef HAVE_GETPAGESIZE + +#include <sys/param.h> + +#ifdef EXEC_PAGESIZE +#define getpagesize() EXEC_PAGESIZE +#else +#ifdef NBPG +#define getpagesize() NBPG * CLSIZE +#ifndef CLSIZE +#define CLSIZE 1 +#endif /* no CLSIZE */ +#else /* no NBPG */ +#define getpagesize() NBPC +#endif /* no NBPG */ +#endif /* no EXEC_PAGESIZE */ + +#endif /* not HAVE_GETPAGESIZE */ + diff --git a/gnu/lib/libregex/test/iregex.c b/gnu/lib/libregex/test/iregex.c new file mode 100644 index 000000000000..2346d441fcdb --- /dev/null +++ b/gnu/lib/libregex/test/iregex.c @@ -0,0 +1,164 @@ +/* Main program for interactive testing. For maximum output, compile + this and regex.c with -DDEBUG. */ + +#include <stdio.h> +#include <sys/types.h> +#include "regex.h" + +/* Don't bother to guess about <string.h> vs <strings.h>, etc. */ +extern int strlen (); + +#define BYTEWIDTH 8 + +extern void printchar (); +extern char upcase[]; + +static void scanstring (); +static void print_regs (); + +int +main (argc, argv) + int argc; + char **argv; +{ + int i; + struct re_pattern_buffer buf; + char fastmap[(1 << BYTEWIDTH)]; + + /* Allow a command argument to specify the style of syntax. You can + use the `syntax' program to decode integer syntax values. */ + if (argc > 1) + re_set_syntax (atoi (argv[1])); + + buf.allocated = 0; + buf.buffer = NULL; + buf.fastmap = fastmap; + buf.translate = upcase; + + for (;;) + { + char pat[500], str[500]; + struct re_registers regs; + + /* Some C compilers don't like `char pat[500] = ""'. */ + pat[0] = 0; + + printf ("Pattern (%s) = ", pat); + gets (pat); + scanstring (pat); + + if (feof (stdin)) + { + putchar ('\n'); + exit (0); + } + + if (*pat) + { + re_compile_pattern (pat, strlen (pat), &buf); + re_compile_fastmap (&buf); +#ifdef DEBUG + print_compiled_pattern (&buf); +#endif + } + + printf ("String = "); + gets (str); /* Now read the string to match against */ + scanstring (str); + + i = re_match (&buf, str, strlen (str), 0, ®s); + printf ("Match value %d.\t", i); + if (i >= 0) + print_regs (regs); + putchar ('\n'); + + i = re_search (&buf, str, strlen (str), 0, strlen (str), ®s); + printf ("Search value %d.\t", i); + if (i >= 0) + print_regs (regs); + putchar ('\n'); + } + + /* We never get here, but what the heck. */ + return 0; +} + +void +scanstring (s) + char *s; +{ + char *write = s; + + while (*s != '\0') + { + if (*s == '\\') + { + s++; + + switch (*s) + { + case '\0': + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + *write = *s++ - '0'; + + if ('0' <= *s && *s <= '9') + { + *write = (*write << 3) + (*s++ - '0'); + if ('0' <= *s && *s <= '9') + *write = (*write << 3) + (*s++ - '0'); + } + write++; + break; + + case 'n': + *write++ = '\n'; + s++; + break; + + case 't': + *write++ = '\t'; + s++; + break; + + default: + *write++ = *s++; + break; + } + } + else + *write++ = *s++; + } + + *write++ = '\0'; +} + +/* Print REGS in human-readable form. */ + +void +print_regs (regs) + struct re_registers regs; +{ + int i, end; + + printf ("Registers: "); + + if (regs.num_regs == 0 || regs.start[0] == -1) + { + printf ("(none)"); + } + else + { + /* Find the last register pair that matched. */ + for (end = regs.num_regs - 1; end >= 0; end--) + if (regs.start[end] != -1) + break; + + printf ("[%d ", regs.start[0]); + for (i = 1; i <= end; i++) + printf ("(%d %d) ", regs.start[i], regs.end[i]); + printf ("%d]", regs.end[0]); + } +} diff --git a/gnu/lib/libregex/test/main.c b/gnu/lib/libregex/test/main.c new file mode 100644 index 000000000000..28ae31528579 --- /dev/null +++ b/gnu/lib/libregex/test/main.c @@ -0,0 +1,49 @@ +/* Main routine for running various tests. Meant only to be linked with + all the auxiliary test source files, with `test' undefined. */ + +#include "test.h" + +test_type t = all_test; + + +/* Use this to run the tests we've thought of. */ + +int +main () +{ + switch (t) + { + case all_test: + test_regress (); + test_others (); + test_posix_basic (); + test_posix_extended (); + test_posix_interface (); + break; + + case other_test: + test_others (); + break; + + case posix_basic_test: + test_posix_basic (); + break; + + case posix_extended_test: + test_posix_extended (); + break; + + case posix_interface_test: + test_posix_interface (); + break; + + case regress_test: + test_regress (); + break; + + default: + fprintf (stderr, "Unknown test %d.\n", t); + } + + return 0; +} diff --git a/gnu/lib/libregex/test/malloc-test.c b/gnu/lib/libregex/test/malloc-test.c new file mode 100644 index 000000000000..7e27a15a8905 --- /dev/null +++ b/gnu/lib/libregex/test/malloc-test.c @@ -0,0 +1,47 @@ + + +typedef struct { + unsigned *bits; + unsigned size; +} bits_list_type; + +#define BYTEWIDTH 8 +#define NULL 0 + +#define BITS_BLOCK_SIZE (sizeof (unsigned) * BYTEWIDTH) +#define BITS_BLOCK(position) ((position) / BITS_BLOCK_SIZE) +#define BITS_MASK(position) (1 << ((position) % BITS_BLOCK_SIZE)) + +static unsigned +init_bits_list (bits_list_ptr) + bits_list_type *bits_list_ptr; +{ + bits_list_ptr->bits = NULL; + bits_list_ptr->bits = (unsigned *) malloc (sizeof (unsigned)); + + if (bits_list_ptr->bits == NULL) + return 0; + + bits_list_ptr->bits[0] = (unsigned)0; + bits_list_ptr->size = BITS_BLOCK_SIZE; + + return 1; +} + + +main() +{ + bits_list_type dummy; + bits_list_type dummy_1; + bits_list_type dummy_2; + bits_list_type dummy_3; + + init_bits_list (&dummy); +printf("init 1\n"); + init_bits_list (&dummy_1); +printf("init 2\n"); + init_bits_list (&dummy_2); +printf("init 3\n"); + init_bits_list (&dummy_3); +printf("init 4\n"); +} diff --git a/gnu/lib/libregex/test/other.c b/gnu/lib/libregex/test/other.c new file mode 100644 index 000000000000..d2ceb3844883 --- /dev/null +++ b/gnu/lib/libregex/test/other.c @@ -0,0 +1,503 @@ +/* other.c: test (not exhaustively) non-POSIX regular expressions. */ + +#include "test.h" + +void +test_others () +{ + struct re_registers regs; + + printf ("\nStarting non-POSIX tests.\n"); + t = other_test; + + test_should_match = true; + + /* The big question: does the group participate in the match, or match + the empty string? */ + re_set_syntax (RE_NO_BK_PARENS); + test_match ("(a*)*ab", "ab"); + TEST_REGISTERS ("(a*)*ab", "ab", 0, 2, 0, 0, -1, -1); + test_match ("(a*)*", ""); + TEST_REGISTERS ("(a*)*ab", "ab", 0, 0, 0, 0, -1, -1); + + /* This tests finding the highest and lowest active registers. */ + test_match ("(a(b)c(d(e)f)g)h(i(j)k(l(m)n)o)\\1\\2\\3\\4\\5\\6\\7\\8", + "abcdefghijklmnoabcdefgbdefeijklmnojlmnm"); + + /* Test that \< and \> match at the beginning and end of the string. */ + test_match ("\\<abc\\>", "abc"); + + /* May as well test \` and \' while we're at it. */ + test_match ("\\`abc\\'", "abc"); + +#if 0 + /* Test backreferencing and the fastmap -- which doesn't work. */ + test_fastmap ("(a)*\\1", "a", 0, 0); +#endif + + /* But at least we shouldn't search improperly. */ + test_search_return (-1, "(a)\\1", ""); + + re_set_syntax (RE_SYNTAX_EMACS); + + MATCH_SELF("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + MATCH_SELF ("a^"); + MATCH_SELF ("a^b"); + MATCH_SELF ("$a"); + MATCH_SELF ("a$b"); + + re_set_syntax (RE_BACKSLASH_ESCAPE_IN_LISTS); + test_match ("[\\^a]", "a"); + test_match ("[\\^a]", "^"); + + /* These op characters should be ordinary if RE_CONTEXT_INVALID_OPS + isn't set. */ + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_BRACES | RE_INTERVALS + | RE_NO_BK_PARENS); + MATCH_SELF ("*"); + test_match ("a|*", "*"); + test_match ("(*)", "*"); + + MATCH_SELF ("+"); + test_match ("a|+", "+"); + test_match ("(+)", "+"); + + MATCH_SELF ("?"); + test_match ("a|?", "?"); + test_match ("(?)", "?"); + + MATCH_SELF ("{1}"); + test_match ("a|{1}", "a"); + test_match ("a|{1}", "{1}"); + test_match ("({1})", "{1}"); + + test_match ("\\{", "{"); + + + re_set_syntax (RE_LIMITED_OPS); + MATCH_SELF ("|"); + MATCH_SELF ("a|"); + MATCH_SELF ("a|"); + MATCH_SELF ("a||"); + MATCH_SELF ("a||"); + MATCH_SELF ("(|)"); + + re_set_syntax (RE_SYNTAX_EMACS); + TEST_SEARCH ("^a", "b\na", 0, 3); + TEST_SEARCH ("b$", "b\na", 0, 3); + +#if 0 + /* Newline is no longer special for anchors (16 Sep 92). --karl */ + test_match_2 ("a\n^b", "a", "\nb"); + test_match_2 ("a$\nb", "a\n", "b"); +#endif + + /* Test grouping. */ + re_set_syntax (RE_NO_BK_PARENS); + + test_match ("()", ""); + test_fastmap ("()", "", 0, 0); + TEST_REGISTERS ("()", "", 0, 0, 0, 0, -1, -1); + + test_match ("((((((((()))))))))", ""); + test_fastmap ("((((((((()))))))))", "", 0, 0); + test_match ("a()b", "ab"); + TEST_REGISTERS ("a()b", "ab", 0, 2, 1, 1, -1, -1); + + test_match ("(((((((((())))))))))", ""); + test_fastmap ("(((((((((())))))))))", "", 0, 0); + + test_match ("()*", ""); + TEST_REGISTERS ("()*", "", 0, 0, 0, 0, -1, -1); /* empty string */ + test_match ("(())*", ""); + + re_set_syntax (RE_CONTEXT_INDEP_OPS); + test_match ("*", ""); + + re_set_syntax (RE_INTERVALS | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES); + test_match ("{1}", ""); /* Should remain an interval. */ + MATCH_SELF ("{1"); /* Not a valid interval. */ + + re_set_syntax (RE_NEWLINE_ALT); + test_match ("a\nb", "a"); + test_match ("a\nb", "b"); + + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS); + test_match ("^a", "a"); + test_match ("(^a)", "a"); + test_match ("(a|^b)", "b"); + test_match ("a$", "a"); + test_match ("(a$)", "a"); + test_match ("a$|b", "a"); + + /* You should be able to have empty alternatives if RE_NO_EMPTY_ALTS + isn't set. */ + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS); + + test_match ("|", ""); + test_match ("^|a", ""); + test_match ("^|a", "a"); + test_match ("a|", ""); + test_match ("a|", "a"); + test_match ("a|$", ""); + test_match ("a|$", "a"); + test_match ("a||b", "a"); + test_match ("a||b", ""); + test_match ("a||b", "b"); + test_match ("(|a)", ""); + test_match ("(|a)", "a"); + test_match ("(a|)", ""); + test_match ("(a|)", "a"); + + TEST_SEARCH ("a|$", "xa", 0, 2); + TEST_SEARCH ("a|$", "x", 0, 1); + TEST_SEARCH ("$|b", "x", 0, 1); + TEST_SEARCH ("$|b", "xb", 0, 2); + TEST_SEARCH ("c(a|$)", "xca", 0, 3); + TEST_SEARCH ("c(a|$)", "xc", 0, 2); + TEST_SEARCH ("c($|b)", "xcb", 0, 3); + TEST_SEARCH ("c($|b)", "xc", 0, 2); + TEST_SEARCH ("c($|b$)", "xcb", 0, 3); + TEST_SEARCH ("c($|b$)", "xc", 0, 2); + TEST_SEARCH ("c(a$|$)", "xca", 0, 3); + TEST_SEARCH ("c(a$|$)", "xc", 0, 2); + TEST_SEARCH ("(a$|b$)|$", "x", 0, 1); + TEST_SEARCH ("(a$|b$)|$", "xa", 0, 2); + TEST_SEARCH ("(a$|b$)|$", "xb", 0, 2); + TEST_SEARCH ("(a$|$)|c$", "x", 0, 1); + TEST_SEARCH ("(a$|$)|c$", "xa", 0, 2); + TEST_SEARCH ("(a$|$)|c$", "xc", 0, 2); + TEST_SEARCH ("($|b$)|c$", "x", 0, 1); + TEST_SEARCH ("($|b$)|c$", "xb", 0, 2); + TEST_SEARCH ("($|b$)|c$", "xc", 0, 2); + TEST_SEARCH ("c$|(a$|$)", "x", 0, 1); + TEST_SEARCH ("c$|(a$|$)", "xa", 0, 2); + TEST_SEARCH ("c$|(a$|$)", "xc", 0, 2); + TEST_SEARCH ("c$|($|b$)", "x", 0, 1); + TEST_SEARCH ("c$|($|b$)", "xb", 0, 2); + TEST_SEARCH ("c$|($|b$)", "xc", 0, 2); + TEST_SEARCH ("$|(a$|b$)", "x", 0, 1); + TEST_SEARCH ("$|(a$|b$)", "xa", 0, 2); + TEST_SEARCH ("$|(a$|b$)", "xb", 0, 2); + TEST_SEARCH ("c(a$|b$)|$", "x", 0, 1); + TEST_SEARCH ("c(a$|b$)|$", "xca", 0, 3); + TEST_SEARCH ("c(a$|b$)|$", "xcb", 0, 3); + TEST_SEARCH ("c(a$|$)|d$", "xc", 0, 2); + TEST_SEARCH ("c(a$|$)|d$", "xca", 0, 3); + TEST_SEARCH ("c(a$|$)|d$", "xd", 0, 2); + TEST_SEARCH ("c($|b$)|d$", "xc", 0, 2); + TEST_SEARCH ("c($|b$)|d$", "xcb", 0, 3); + TEST_SEARCH ("c($|b$)|d$", "xd", 0, 2); + TEST_SEARCH ("d(c$|e((a$|$)))", "xdc", 0, 3); + TEST_SEARCH ("d(c$|e((a$|$)))", "xde", 0, 3); + TEST_SEARCH ("d(c$|e((a$|$)))", "xdea", 0, 4); + TEST_SEARCH ("d(c$|e(($|b$)))", "xdc", 0, 3); + TEST_SEARCH ("d(c$|e(($|b$)))", "xde", 0, 3); + TEST_SEARCH ("d(c$|e(($|b$)))", "xdeb", 0, 4); + TEST_SEARCH ("d($|e((a$|b$)))", "xd", 0, 2); + TEST_SEARCH ("d($|e((a$|b$)))", "xdea", 0, 4); + TEST_SEARCH ("d($|e((a$|b$)))", "xdeb", 0, 4); + TEST_SEARCH ("a(b$|c$)|$", "x", 0, 1); + TEST_SEARCH ("a(b$|c$)|$", "xab", 0, 3); + TEST_SEARCH ("a(b$|c$)|$", "xac", 0, 3); + TEST_SEARCH ("a(b$|$)|d$", "xa", 0, 2); + TEST_SEARCH ("a(b$|$)|d$", "xab", 0, 3); + TEST_SEARCH ("a(b$|$)|d$", "xd", 0, 2); + TEST_SEARCH ("a($|c$)|d$", "xa", 0, 2); + TEST_SEARCH ("a($|c$)|d$", "xac", 0, 3); + TEST_SEARCH ("a($|c$)|d$", "xd", 0, 2); + TEST_SEARCH ("d$|a(b$|$)", "xd", 0, 2); + TEST_SEARCH ("d$|a(b$|$)", "xa", 0, 2); + TEST_SEARCH ("d$|a(b$|$)", "xab", 0, 3); + TEST_SEARCH ("d$|a($|c$)", "xd", 0, 2); + TEST_SEARCH ("d$|a($|c$)", "xa", 0, 2); + TEST_SEARCH ("d$|a($|c$)", "xac", 0, 3); + TEST_SEARCH ("$|a(b$|c$)", "x", 0, 1); + TEST_SEARCH ("$|a(b$|c$)", "xab", 0, 3); + TEST_SEARCH ("$|a(b$|c$)", "xac", 0, 3); + TEST_SEARCH ("(a)(b$|c$)|d$", "xab", 0, 3); + TEST_SEARCH ("(a)(b$|c$)|d$", "xac", 0, 3); + TEST_SEARCH ("(a)(b$|c$)|d$", "xd", 0, 2); + TEST_SEARCH ("(a)(b$|$)|d$", "xa", 0, 2); + TEST_SEARCH ("(a)(b$|$)|d$", "xab", 0, 3); + TEST_SEARCH ("(a)(b$|$)|d$", "xd", 0, 2); + TEST_SEARCH ("(a)($|c$)|d$", "xa", 0, 2); + TEST_SEARCH ("(a)($|c$)|d$", "xac", 0, 3); + TEST_SEARCH ("(a)($|c$)|d$", "xd", 0, 2); + TEST_SEARCH ("d$|(a)(b$|$)", "xd", 0, 2); + TEST_SEARCH ("d$|(a)(b$|$)", "xa", 0, 2); + TEST_SEARCH ("d$|(a)(b$|$)", "xab", 0, 3); + TEST_SEARCH ("d$|(a)($|c$)", "xd", 0, 2); + TEST_SEARCH ("d$|(a)($|c$)", "xa", 0, 2); + TEST_SEARCH ("d$|(a)($|c$)", "xac", 0, 3); + TEST_SEARCH ("$|(a)(b$|c$)", "x", 0, 1); + TEST_SEARCH ("$|(a)(b$|c$)", "xab", 0, 3); + TEST_SEARCH ("$|(a)(b$|c$)", "xac", 0, 3); + TEST_SEARCH ("d$|(c$|(a$|$))", "x", 0, 1); + TEST_SEARCH ("d$|(c$|(a$|$))", "xd", 0, 2); + TEST_SEARCH ("d$|(c$|(a$|$))", "xc", 0, 2); + TEST_SEARCH ("d$|(c$|(a$|$))", "xa", 0, 2); + TEST_SEARCH ("d$|(c$|($|b$))", "x", 0, 1); + TEST_SEARCH ("d$|(c$|($|b$))", "xd", 0, 2); + TEST_SEARCH ("d$|(c$|($|b$))", "xc", 0, 2); + TEST_SEARCH ("d$|(c$|($|b$))", "xb", 0, 2); + TEST_SEARCH ("d$|($|(a$|b$))", "x", 0, 1); + TEST_SEARCH ("d$|($|(a$|b$))", "xd", 0, 2); + TEST_SEARCH ("d$|($|(a$|b$))", "xa", 0, 2); + TEST_SEARCH ("d$|($|(a$|b$))", "xb", 0, 2); + TEST_SEARCH ("$|(c$|(a$|b$))", "x", 0, 1); + TEST_SEARCH ("$|(c$|(a$|b$))", "xc", 0, 2); + TEST_SEARCH ("$|(c$|(a$|b$))", "xa", 0, 2); + TEST_SEARCH ("$|(c$|(a$|b$))", "xb", 0, 2); + TEST_SEARCH ("d$|c(a$|$)", "xd", 0, 2); + TEST_SEARCH ("d$|c(a$|$)", "xc", 0, 2); + TEST_SEARCH ("d$|c(a$|$)", "xca", 0, 3); + TEST_SEARCH ("d$|c($|b$)", "xd", 0, 2); + TEST_SEARCH ("d$|c($|b$)", "xc", 0, 2); + TEST_SEARCH ("d$|c($|b$)", "xcb", 0, 3); + TEST_SEARCH ("$|c(a$|b$)", "x", 0, 1); + TEST_SEARCH ("$|c(a$|b$)", "xca", 0, 3); + TEST_SEARCH ("$|c(a$|b$)", "xcb", 0, 3); + TEST_SEARCH ("e(d$|c((a$|$)))", "xed", 0, 3); + TEST_SEARCH ("e(d$|c((a$|$)))", "xec", 0, 3); + TEST_SEARCH ("e(d$|c((a$|$)))", "xeca", 0, 3); + TEST_SEARCH ("e(d$|c(($|b$)))", "xed", 0, 3); + TEST_SEARCH ("e(d$|c(($|b$)))", "xec", 0, 3); + TEST_SEARCH ("e(d$|c(($|b$)))", "xecb", 0, 4); + TEST_SEARCH ("e($|c((a$|b$)))", "xe", 0, 2); + TEST_SEARCH ("e($|c((a$|b$)))", "xeca", 0, 4); + TEST_SEARCH ("e($|c((a$|b$)))", "xecb", 0, 4); + TEST_SEARCH ("ed$|(c((a$|$)))", "xed", 0, 3); + TEST_SEARCH ("ed$|(c((a$|$)))", "xc", 0, 2); + TEST_SEARCH ("ed$|(c((a$|$)))", "xca", 0, 3); + TEST_SEARCH ("ed$|(c(($|b$)))", "xed", 0, 3); + TEST_SEARCH ("ed$|(c(($|b$)))", "xc", 0, 2); + TEST_SEARCH ("ed$|(c(($|b$)))", "xcb", 0, 3); + TEST_SEARCH ("$|(c((a$|b$)))", "x", 0, 1); + TEST_SEARCH ("$|(c((a$|b$)))", "xca", 0, 3); + TEST_SEARCH ("$|(c((a$|b$)))", "xcb", 0, 3); + TEST_SEARCH ("d$|($|(a|b)$)", "x", 0, 1); + TEST_SEARCH ("d$|($|(a|b)$)", "xa", 0, 2); + TEST_SEARCH ("d$|($|(a|b)$)", "xb", 0, 2); + TEST_SEARCH ("$|(c$|(a|b)$)", "x", 0, 1); + TEST_SEARCH ("$|(c$|(a|b)$)", "xc", 0, 2); + TEST_SEARCH ("$|(c$|(a|b)$)", "xa", 0, 2); + TEST_SEARCH ("$|(c$|(a|b)$)", "xb", 0, 2); + + re_set_syntax (0); + test_match ("[^\n]", "a"); + test_match ("[^a]", "\n"); + + TEST_SEARCH ("^a", "b\na", 0, 3); + TEST_SEARCH ("b$", "b\na", 0, 3); + + test_case_fold ("[!-`]", "A"); + test_case_fold ("[!-`]", "a"); + + re_set_syntax (RE_CONTEXT_INDEP_OPS | RE_NO_BK_VBAR | RE_NO_BK_PARENS + | RE_NO_BK_BRACES | RE_INTERVALS); + valid_nonposix_pattern ("()^a"); + valid_nonposix_pattern ("()\\1^a"); + + /* Per Cederqvist (cedar@lysator.liu.se) bug. */ + + re_set_syntax (RE_SYNTAX_EMACS); + + /* One `a' before the \n and 638 a's after it. */ + test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "a\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + /* No a's before the \n and 639 a's after it. */ + test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + /* One `a' before the \n and 639 a's after it. */ + test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "a\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + /* No a's before the \n and 640 a's after it. */ + test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS); + TEST_SEARCH ("^(^a)", "ab", 0, 2); + TEST_SEARCH ("(a$)$", "ba", 0, 2); + test_match ("a|$b", "$b"); + + /* Mike's curiosity item. */ + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS); + test_all_registers ("(foo|foobar)(foo|bar)*\\1(foo|bar)*", + "foobarfoobar", "", + 0, 12, 0, 3, 3, 6, 9, 12, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1); + + /* Another one from Mike. */ + test_match ("(foo|foobarfoo)(bar)*", "foobarfoo"); + + /* And another. */ + test_match("(foo|foobar)(bar|barfoo)?\\1", "foobarfoobar"); + + re_set_syntax (RE_NO_BK_PARENS | RE_INTERVALS | RE_NO_BK_VBAR + | RE_NO_BK_BRACES); /* xx get new ones from ext.*/ + test_match ("((a{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)*", "bb"); + test_all_registers ("((a{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)*", "", "bb", + 0, 2, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1); + + test_match ("((a+?*{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)", "b"); + test_all_registers ("((a+?*{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)", "", "b", + 0, 1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1); + + /* Valid anchoring. */ + /* See generic_test.c and extended_test.c for more search + tests. xx Not sure all these tests are represented in the + search tests. */ + + re_set_syntax (RE_NO_BK_PARENS | RE_NO_BK_VBAR); + valid_nonposix_pattern + ("(((((((((((((((((((((((((((((((((^a)))))))))))))))))))))))))))))))))"); + valid_nonposix_pattern + ("(((((((((((((((((((((((((((((((((a$)))))))))))))))))))))))))))))))))"); + valid_nonposix_pattern ("\\b\\B\\<\\>\\`\\'^a"); + valid_nonposix_pattern ("a$\\b\\B\\<\\>\\`\\'"); + valid_nonposix_pattern ("(^a)"); + valid_nonposix_pattern ("(a$)"); + valid_nonposix_pattern ("(^a)b"); + valid_nonposix_pattern ("b(a$)"); + valid_nonposix_pattern ("(^a|^b)c"); + valid_nonposix_pattern ("c(a$|b$)"); + valid_nonposix_pattern ("(^a|^b)|^c"); + valid_nonposix_pattern ("(a$|b$)|c$"); + valid_nonposix_pattern ("^c|(^a|^b)"); + valid_nonposix_pattern ("c$|(a$|b$)"); + valid_nonposix_pattern ("(^a|^b)c|^d"); + valid_nonposix_pattern ("c(a$|b$)|d$"); + valid_nonposix_pattern ("(((^a|^b))c|^d)e"); + valid_nonposix_pattern ("(c((a|b))|d)e$"); + valid_nonposix_pattern ("^d(c|e((a|b)))"); + valid_nonposix_pattern ("d(c$|e((a$|b$)))"); + valid_nonposix_pattern ("(((^a|^b))c)|^de"); + valid_nonposix_pattern ("(((a|b))c$)|de$"); + + valid_nonposix_pattern ("((a$)$)$"); + valid_nonposix_pattern ("^(^(^a))"); + + valid_nonposix_pattern ("^de|^(c((a|b)))"); + valid_nonposix_pattern ("^de|(^c((a|b)))"); + valid_nonposix_pattern ("de$|(c((a|b)$))"); + valid_nonposix_pattern ("de$|(c((a|b))$)"); + valid_nonposix_pattern ("de$|(c((a|b)))$"); + + valid_nonposix_pattern ("^a(b|c)|^d"); + valid_nonposix_pattern ("a(b$|c$)|d$"); + valid_nonposix_pattern ("^d|^a(b|c)"); + valid_nonposix_pattern ("d$|a(b$|c$)"); + valid_nonposix_pattern ("^d|^(b|c)a"); + valid_nonposix_pattern ("d$|(b|c)a$"); + valid_nonposix_pattern ("^(a)(b|c)|^d"); + valid_nonposix_pattern ("(a)(b|c)$|d$"); + valid_nonposix_pattern ("(^a)(b|c)|^d"); + valid_nonposix_pattern ("(a)(b$|c$)|d$"); + valid_nonposix_pattern ("^d|^(b|c)(a)"); + valid_nonposix_pattern ("d$|(b|c)(a)$"); + valid_nonposix_pattern ("^d|(^b|^c)(a)"); + valid_nonposix_pattern ("d$|(b|c)(a$)"); + valid_nonposix_pattern ("^d|^(a)(b|c)"); + valid_nonposix_pattern ("^d|(^a)(b|c)"); + valid_nonposix_pattern ("d$|(a)(b$|c$)"); + valid_nonposix_pattern ("((^a|^b)|^c)|^d"); + valid_nonposix_pattern ("d$|(c$|(a$|b$))"); + + + /* Tests shouldn't match. */ + test_should_match = false; + + /* Test that RE_CONTEXT_INVALID_OPS has precedence over + RE_CONTEXT_INDEP_OPS. */ + + re_set_syntax (RE_CONTEXT_INDEP_OPS | RE_CONTEXT_INVALID_OPS + | RE_NO_BK_VBAR | RE_NO_BK_PARENS + | RE_NO_BK_BRACES | RE_INTERVALS); + INVALID_PATTERN ("*"); + INVALID_PATTERN ("^*"); + INVALID_PATTERN ("a|*"); + INVALID_PATTERN ("(*)"); + + INVALID_PATTERN ("^+"); + INVALID_PATTERN ("+"); + INVALID_PATTERN ("a|+"); + INVALID_PATTERN ("(+)"); + + INVALID_PATTERN ("^?"); + INVALID_PATTERN ("?"); + INVALID_PATTERN ("a|?"); + INVALID_PATTERN ("(?)"); + + INVALID_PATTERN ("^{1}"); + INVALID_PATTERN ("{1}"); + INVALID_PATTERN ("a|{1}"); + INVALID_PATTERN ("({1})"); + +#if 0 + /* No longer have this syntax option -- POSIX says empty alternatives + are undefined as of draft 11.2. */ + + /* You can't have empty alternatives if RE_NO_EMPTY_ALTS is set. */ + + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS | RE_NO_EMPTY_ALTS); + + INVALID_PATTERN ("|"); + INVALID_PATTERN ("^|a"); + INVALID_PATTERN ("a|"); + INVALID_PATTERN ("a||"); + INVALID_PATTERN ("a||b"); + INVALID_PATTERN ("(|a)"); + INVALID_PATTERN ("(a|)"); + INVALID_PATTERN ("(a|)"); + + + /* Test above with `\(' and `\)'. */ + re_set_syntax (RE_NO_BK_VBAR | RE_NO_EMPTY_ALTS); + INVALID_PATTERN ("\\(|a\\)"); + INVALID_PATTERN ("\\(a|\\)"); + + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS | RE_NO_EMPTY_ALTS); + INVALID_PATTERN ("(|)()$|d$"); +#endif + + /* Test grouping. */ + test_match ("()", "a"); + + /* Test backslashed intervals that are CONTEXTly invalid if have + nothing on which to operate. */ + + re_set_syntax (RE_INTERVALS | RE_CONTEXT_INVALID_OPS); + INVALID_PATTERN ("\\{1\\}"); + + re_set_syntax (0); + test_match ("z-a", "a"); + + re_set_syntax (RE_BK_PLUS_QM); + INVALID_PATTERN ("a*\\"); + + re_set_syntax (0); + INVALID_PATTERN ("a*\\"); + + re_set_syntax (RE_BACKSLASH_ESCAPE_IN_LISTS); + INVALID_PATTERN ("[\\"); + +#if 0 + /* Empty groups are always ok now. (13 Sep 92) */ + re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS | RE_NO_EMPTY_GROUPS); + INVALID_PATTERN ("(|)()$|d$"); +#endif + + printf ("\nFinished non-POSIX tests.\n"); +} + + + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/test/printchar.c b/gnu/lib/libregex/test/printchar.c new file mode 100644 index 000000000000..1b756f441be3 --- /dev/null +++ b/gnu/lib/libregex/test/printchar.c @@ -0,0 +1,14 @@ +void +printchar (c) + char c; +{ + if (c < 040 || c >= 0177) + { + putchar ('\\'); + putchar (((c >> 6) & 3) + '0'); + putchar (((c >> 3) & 7) + '0'); + putchar ((c & 7) + '0'); + } + else + putchar (c); +} diff --git a/gnu/lib/libregex/test/psx-basic.c b/gnu/lib/libregex/test/psx-basic.c new file mode 100644 index 000000000000..52535b6b3076 --- /dev/null +++ b/gnu/lib/libregex/test/psx-basic.c @@ -0,0 +1,253 @@ +/* psx-basic.c: Test POSIX basic regular expressions. */ + +#include "test.h" + + +void +test_posix_basic () +{ + /* Intervals can only match up to RE_DUP_MAX occurences of anything. */ + char dup_max_plus_one[6]; + sprintf (dup_max_plus_one, "%d", RE_DUP_MAX + 1); + + printf ("\nStarting POSIX basic tests.\n"); + t = posix_basic_test; + + re_set_syntax (RE_SYNTAX_POSIX_MINIMAL_BASIC); + + test_posix_generic (); + + printf ("\nContinuing POSIX basic tests.\n"); + +/* Grouping tests that are not the same. */ + + test_should_match = false; + invalid_pattern (REG_EPAREN, PARENS_TO_OPS ("a)")); + + test_should_match = true; + /* Special characters. */ + MATCH_SELF ("*"); + test_match ("\\(*\\)", "*"); + test_match ("\\(^*\\)", "*"); + test_match ("**", "***"); + test_match ("***", "****"); + + MATCH_SELF ("{"); /* of extended... */ + MATCH_SELF ("()"); /* also non-Posix. */ + MATCH_SELF ("a+"); + MATCH_SELF ("a?"); + MATCH_SELF ("a|b"); + MATCH_SELF ("a|"); /* No alternations, */ + MATCH_SELF ("|a"); /* so OK if empty. */ + MATCH_SELF ("a||"); + test_match ("\\(|a\\)", "|a"); + test_match ("\\(a|\\)", "a|"); + test_match ("a\\+", "a+"); + test_match ("a\\?", "a?"); + test_match ("a\\|b", "a|b"); + test_match ("^*", "*"); + test_match ("^+", "+"); + test_match ("^?", "?"); + test_match ("^{", "{"); + /* Valid subexpressions + (empty) in basic only. */ + test_match ("\\(\\)", ""); + + test_match ("a\\(\\)", "a"); + test_match ("\\(\\)b", "b"); + test_match ("a\\(\\)b", "ab"); + TEST_REGISTERS ("a\\(\\)b", "ab", 0, 2, 1, 1, -1, -1); + + test_match ("\\(\\)*", ""); + test_match ("\\(\\(\\)\\)*", ""); + /* Valid back references. */ + + /* N.B.: back references to subexpressions that include a * are + undefined in the spec. The tests are in here to see if we handle + the situation consistently, but if it fails any of them, it doesn't + matter. */ + + test_match ("\\(\\)\\1", ""); + TEST_REGISTERS ("\\(\\)\\1", "", 0, 0, 0, 0, -1, -1); + + test_match ("\\(\\(\\)\\)\\(\\)\\2", ""); + + test_match ("\\(a\\)\\1", "aa"); + TEST_REGISTERS ("\\(a\\)\\1", "aa", 0, 2, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a\\)\\1", "xaax", 1, 3, 1, 2, -1, -1); + + test_match ("\\(\\(a\\)\\)\\1", "aa"); + test_match ("\\(a\\)\\(b\\)\\2\\1", "abba"); + + test_match ("\\(a\\)*\\1", "aa"); + TEST_REGISTERS ("\\(a\\)*\\1", "aa", 0, 2, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a\\)*\\1", "xaax", 0, 0, -1, -1, -1, -1); + + test_match ("\\(\\(a\\)\\2b\\)*", "aab"); + TEST_REGISTERS ("\\(\\(a\\)\\2b\\)*", "aab", 0, 3, 0, 3, 0, 1); + TEST_REGISTERS ("\\(\\(a\\)\\2b\\)*", "xaabx", 0, 0, -1, -1, -1, -1); + + test_match ("\\(a*\\)*\\1", ""); + test_match ("\\(a*\\)*\\1", "aa"); + TEST_REGISTERS ("\\(a*\\)*\\1", "aa", 0, 2, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a*\\)*\\1", "xaax", 0, 0, 0, 0, -1, -1); + + test_match ("\\(a*\\)*\\1", ""); + test_match ("\\(a*\\)*\\1", "aa"); + test_match ("\\(\\(a*\\)*\\)*\\1", "aa"); + test_match ("\\(ab*\\)*\\1", "abab"); + TEST_REGISTERS ("\\(ab*\\)*\\1", "abab", 0, 4, 0, 2, -1, -1); + TEST_REGISTERS ("\\(ab*\\)*\\1", "xababx", 0, 0, -1, -1, -1, -1); + + test_match ("\\(a*\\)ab\\1", "aaba"); + TEST_REGISTERS ("\\(a*\\)ab\\1", "aaba", 0, 4, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a*\\)ab\\1", "xaabax", 1, 5, 1, 2, -1, -1); + + test_match ("\\(a*\\)*ab\\1", "aaba"); + TEST_REGISTERS ("\\(a*\\)*ab\\1", "aaba", 0, 4, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a*\\)*ab\\1", "xaabax", 1, 5, 1, 2, -1, -1); + + test_match ("\\(\\(a*\\)b\\)*\\2", "abb"); + TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "abb", 0, 3, 2, 3, 2, 2); + TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "xabbx", 0, 0, -1, -1, -1, -1); + + /* Different from above. */ + test_match ("\\(\\(a*\\)b*\\)*\\2", "aa"); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aa", 0, 2, 0, 1, 0, 1); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaax", 0, 0, 0, 0, 0, 0); + + test_match ("\\(\\(a*\\)b*\\)*\\2", "aba"); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aba", 0, 3, 0, 2, 0, 1); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xabax", 0, 0, 0, 0, 0, 0); + + test_match ("\\(\\(a*\\)b\\)*\\2", "aababa"); + TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "aababa", 0, 6, 3, 5, 3, 4); + TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "xaababax", 0, 0, -1, -1, -1, -1); + + test_match ("\\(\\(a*\\)b*\\)*\\2", "aabaa"); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aabaa", 0, 5, 0, 3, 0, 2); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaabaax", 0, 0, 0, 0, 0, 0); + + test_match ("\\(\\(a*\\)b*\\)*\\2", "aabbaa"); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aabbaa", 0, 6, 0, 4, 0, 2); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaabbaax", 0, 0, 0, 0, 0, 0); + + test_match ("\\(\\(a*\\)b*\\)*\\2", "abaabaa"); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "abaabaa", 0, 7, 2, 5, 2, 4); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaababaax", 0, 0, 0, 0, 0, 0); + + test_match ("\\(\\(a*\\)b*\\)*a\\2", "aabaaa"); + TEST_REGISTERS ("\\(\\(a*\\)b*a\\)*\\2", "aabaaa", 0, 6, 0, 3, 0, 2); + TEST_REGISTERS ("\\(\\(a*\\)b*a\\)*\\2", "xaabaax", 0, 0, -1, -1, -1, -1); + + test_match ("\\(\\(a*\\)b*\\)*\\2a", "aabaaa"); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2a", "aabaaa", 0, 6, 0, 3, 0, 2); + TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2a", "xaabaaax", 1, 7, 1, 4, 1, 3); + + test_match ("\\(\\(a*\\)b\\)*\\2\\1", "abaabaaaab"); + TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2\\1", "abaabaaaab", 0, 10, 2, 5, 2, 4); + /* We are matching the empty string here. */ + TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2\\1", "xabaabaaaabx", 0, 0, -1, -1, -1, -1); + + test_match ("\\(a*b\\)\\1", "abab"); + test_match ("\\(a\\)\\1\\1", "aaa"); + test_match ("\\(a\\(c\\)d\\)\\1\\2", "acdacdc"); + + test_match ("\\(a\\)\\1*", "aaa"); + TEST_REGISTERS ("\\(a\\)\\1*", "aaa", 0, 3, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a\\)\\1*", "xaaax", 1, 4, 1, 2, -1, -1); + + test_match ("\\(a\\)\\{1,3\\}b\\1", "aba"); + TEST_REGISTERS ("\\(a\\)\\{1,3\\}b\\1", "aba", 0, 3, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a\\)\\{1,3\\}b\\1", "xabax", 1, 4, 1, 2, -1, -1); + + test_match ("\\(\\(a\\)\\2\\)*", "aaaa"); /* rms? */ + TEST_REGISTERS ("\\(\\(a*b\\)\\2\\)*", "bbabab", 0, 6, 2, 6, 2, 4); /* rms? */ + + test_match ("\\(\\(a\\)\\1\\)*", "a1a1"); + + test_match ("\\(\\(a\\)\\2\\)\\1", "aaaa"); + + test_match ("\\(\\(a*\\)\\2\\)\\1", "aaaa"); + TEST_REGISTERS ("\\(\\(a*\\)\\2\\)\\1", "aaaa", 0, 4, 0, 2, 0, 1); + TEST_REGISTERS ("\\(\\(a*\\)\\2\\)\\1", "xaaaax", 0, 0, 0, 0, 0, 0); + + test_match ("\\{1\\}", "{1}"); + test_match ("^\\{1\\}", "{1}"); + + test_match ("\\(a\\)\\1\\{1,2\\}", "aaa"); + TEST_REGISTERS ("\\(a\\)\\1\\{1,2\\}", "aaa", 0, 3, 0, 1, -1, -1); + TEST_REGISTERS ("\\(a\\)\\1\\{1,2\\}", "xaaax", 1, 4, 1, 2, -1, -1); + + + /* Per POSIX D11.1 p. 109, leftmost longest match. */ + + test_match (PARENS_TO_OPS ("(.*).*\\1"), "abcabc"); + + + /* Per POSIX D11.1, p. 125, leftmost longest match. */ + + test_match (PARENS_TO_OPS ("(ac*)c*d[ac]*\\1"), "acdacaaa"); + TEST_REGISTERS (PARENS_TO_OPS ("(ac*)c*d[ac]*\\1"), "acdacaaa", + 0, 8, 0, 1, -1, -1); + + /* Anchors become ordinary, sometimes. */ + MATCH_SELF ("a^"); + MATCH_SELF ("$a"); + MATCH_SELF ("$^"); + test_fastmap ("$a^", "$", 0, 0); + test_match ("$^*", "$^^"); + test_match ("\\($^\\)", "$^"); + test_match ("$*", "$$"); + /* xx -- known bug, solution pending test_match ("^^$", "^"); */ + test_match ("$\\{0,\\}", "$$"); + TEST_SEARCH ("^$*", "$$", 0, 2); + TEST_SEARCH ("^$\\{0,\\}", "$$", 0, 2); + MATCH_SELF ("2^10"); + MATCH_SELF ("$HOME"); + MATCH_SELF ("$1.35"); + + + /* Basic regular expressions, continued; these don't match their strings. */ + test_should_match = false; + + invalid_pattern (REG_EESCAPE, "\\(a\\"); + /* Invalid back references. */ + test_match ("\\(a\\)\\1", "ab"); + test_match ("\\(a\\)\\1\\1", "aab"); + test_match ("\\(a\\)\\(b\\)\\2\\1", "abab"); + test_match ("\\(a\\(c\\)d\\)\\1\\2", "acdc"); + test_match ("\\(a*b\\)\\1", "abaab"); + test_match ("\\(a\\)\\1*", "aaaaaaaaaab"); + test_match ("\\(\\(a\\)\\1\\)*", "aaa"); + invalid_pattern (REG_ESUBREG, "\\1"); + invalid_pattern (REG_ESUBREG, "\\(a\\)\\2"); + test_match ("\\(\\(a\\)\\2\\)*", "abaa"); + test_match ("\\(\\(a\\)\\1\\)*", "a"); + test_match ("\\(\\(a\\)\\2\\)\\1", "abaa"); + test_match ("\\(\\(a*\\)\\2\\)\\1", "abaa"); + /* Invalid intervals. */ + invalid_pattern (REG_EBRACE, "a\\{"); + + invalid_pattern (REG_BADBR, "a\\{-1"); + invalid_pattern (REG_BADBR, concat ("a\\{", (char *)dup_max_plus_one)); + invalid_pattern (REG_BADBR, concat (concat ("a\\{", (char *)dup_max_plus_one), ",")); + invalid_pattern (REG_BADBR, "a\\{1,0"); + + invalid_pattern (REG_EBRACE, "a\\{1"); + invalid_pattern (REG_EBRACE, "a\\{0,"); + invalid_pattern (REG_EBRACE, "a\\{0,1"); + invalid_pattern (REG_EBRACE, "a\\{0,1}"); + + printf ("\nFinished POSIX basic tests.\n"); +} + + + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/test/psx-extend.c b/gnu/lib/libregex/test/psx-extend.c new file mode 100644 index 000000000000..6f02d67b8219 --- /dev/null +++ b/gnu/lib/libregex/test/psx-extend.c @@ -0,0 +1,1244 @@ +/* psx-extend.c: Test POSIX extended regular expressions. */ + +#include "test.h" + + +void +test_posix_extended () +{ + /* Intervals can only match up to RE_DUP_MAX occurences of anything. */ + char dup_max_plus_one[6]; + sprintf (dup_max_plus_one, "%d", RE_DUP_MAX + 1); + + + printf ("\nStarting POSIX extended tests.\n"); + t = posix_extended_test; + + re_set_syntax (RE_SYNTAX_POSIX_MINIMAL_EXTENDED); + + test_posix_generic (); + + printf ("\nContinuing POSIX extended tests.\n"); + + /* Grouping tests that differ from basic's. */ + + test_should_match = true; + MATCH_SELF ("a)"); + + /* Valid use of special characters. */ + test_match ("\\(a", "(a"); + test_match ("a\\+", "a+"); + test_match ("a\\?", "a?"); + test_match ("\\{a", "{a"); + test_match ("\\|a", "|a"); + test_match ("a\\|b", "a|b"); + test_match ("a\\|?", "a"); + test_match ("a\\|?", "a|"); + test_match ("a\\|*", "a"); + test_match ("a\\|*", "a||"); + test_match ("\\(*\\)", ")"); + test_match ("\\(*\\)", "(()"); + test_match ("a\\|+", "a|"); + test_match ("a\\|+", "a||"); + test_match ("\\(+\\)", "()"); + test_match ("\\(+\\)", "(()"); + test_match ("a\\||b", "a|"); + test_match ("\\(?\\)", ")"); + test_match ("\\(?\\)", "()"); + + test_match ("a+", "a"); + test_match ("a+", "aa"); + test_match ("a?", ""); + test_match ("a?", "a"); + + /* Bracket expressions. */ + test_match ("[(]", "("); + test_match ("[+]", "+"); + test_match ("[?]", "?"); + test_match ("[{]", "{"); + test_match ("[|]", "|"); + /* Subexpressions. */ + test_match ("(a+)*", ""); + test_match ("(a+)*", "aa"); + test_match ("(a?)*", ""); + test_match ("(a?)*", "aa"); + /* (No) back references. */ + test_match ("(a)\\1", "a1"); + /* Invalid as intervals, + but are valid patterns. */ + MATCH_SELF ("{"); + test_match ("^{", "{"); + test_match ("a|{", "{"); + test_match ("({)", "{"); + MATCH_SELF ("a{"); + MATCH_SELF ("a{}"); + MATCH_SELF ("a{-1"); + MATCH_SELF ("a{-1}"); + MATCH_SELF ("a{0"); + MATCH_SELF ("a{0,"); + MATCH_SELF (concat ("a{", dup_max_plus_one)); + MATCH_SELF (concat (concat ("a{", dup_max_plus_one), ",")); + MATCH_SELF ("a{1,0"); + MATCH_SELF ("a{1,0}"); + MATCH_SELF ("a{0,1"); + test_match ("[a{0,1}]", "}"); + test_match ("a{1,3}{-1}", "aaa{-1}"); + test_match (concat ("a{1,3}{", dup_max_plus_one), + concat ("aaa{", dup_max_plus_one)); + test_match ("a{1,3}{2,1}", "aaa{2,1}"); + test_match ("a{1,3}{1,2", "aaa{1,2"); + /* Valid consecutive repetitions. */ + test_match ("a*+", "a"); + test_match ("a*?", "a"); + test_match ("a++", "a"); + test_match ("a+*", "a"); + test_match ("a+?", "a"); + test_match ("a??", "a"); + test_match ("a?*", "a"); + test_match ("a?+", "a"); + + test_match ("a{2}?", ""); + test_match ("a{2}?", "aa"); + test_match ("a{2}+", "aa"); + test_match ("a{2}{2}", "aaaa"); + + test_match ("a{1}?*", ""); + test_match ("a{1}?*", "aa"); + + test_match ("(a?){0,3}b", "aaab"); + test_fastmap ("(a?){0,3}b", "ab", 0, 0); + test_match ("(a+){0,3}b", "b"); + test_fastmap ("(a+){0,3}b", "ab", 0, 0); + test_match ("(a+){0,3}b", "ab"); + test_fastmap ("(a+){0,3}b", "ab", 0, 0); + test_match ("(a+){1,3}b", "aaab"); + test_match ("(a?){1,3}b", "aaab"); + + test_match ("\\\\{1}", "\\"); /* Extended only. */ + + test_match ("(a?)?", "a"); + test_match ("(a?b)?c", "abc"); + test_match ("(a+)*b", "b"); + /* Alternatives. */ + test_match ("a|b", "a"); + test_match ("a|b", "b"); + test_fastmap ("a|b", "ab", 0, 0); + + TEST_SEARCH ("a|b", "cb", 0, 2); + TEST_SEARCH ("a|b", "cb", 0, 2); + + test_match ("(a|b|c)", "a"); + test_match ("(a|b|c)", "b"); + test_match ("(a|b|c)", "c"); + + test_match ("(a|b|c)*", "abccba"); + + test_match ("(a(b*))|c", "a"); /* xx do registers. */ + test_match ("(a(b*))|c", "ab"); + test_match ("(a(b*))|c", "c"); + + test_fastmap ("(a+?*|b)", "ab", 0, 0); + test_match ("(a+?*|b)", "b"); + TEST_REGISTERS ("(a+?*|b)", "b", 0, 1, 0, 1, -1, -1); + + test_fastmap ("(a+?*|b)*", "ab", 0, 0); + test_match ("(a+?*|b)*", "bb"); + TEST_REGISTERS ("(a+?*|b)*", "bb", 0, 2, 1, 2, -1, -1); + + test_fastmap ("(a*|b)*", "ab", 0, 0); + test_match ("(a*|b)*", "bb"); + TEST_REGISTERS ("(a*|b)*", "bb", 0, 2, 1, 2, -1, -1); + + test_fastmap ("((a*)|b)*", "ab", 0, 0); + test_match ("((a*)|b)*", "bb"); + TEST_REGISTERS ("((a*)|b)*", "bb", 0, 2, 1, 2, 1, 1); + + test_fastmap ("(a{0,}|b)*", "ab", 0, 0); + test_match ("(a{0,}|b)*", "bb"); + TEST_REGISTERS ("(a{0,}|b)*", "bb", 0, 2, 1, 2, -1, -1); + + test_fastmap ("((a{0,})|b)*", "ab", 0, 0); + test_match ("((a{0,})|b)*", "bb"); + TEST_REGISTERS ("((a{0,})|b)*", "bb", 0, 2, 1, 2, 1, 1); + + /* With c's */ + test_fastmap ("(a+?*|b)c", "abc", 0, 0); + test_match ("(a+?*|b)c", "bc"); + TEST_REGISTERS ("(a+?*|b)c", "bc", 0, 2, 0, 1, -1, -1); + + test_fastmap ("(a+?*|b)*c", "abc", 0, 0); + test_match ("(a+?*|b)*c", "bbc"); + TEST_REGISTERS ("(a+?*|b)*c", "bbc", 0, 3, 1, 2, -1, -1); + + test_fastmap ("(a*|b)*c", "abc", 0, 0); + test_match ("(a*|b)*c", "bbc"); + TEST_REGISTERS ("(a*|b)*c", "bbc", 0, 3, 1, 2, -1, -1); + + test_fastmap ("((a*)|b)*c", "abc", 0, 0); + test_match ("((a*)|b)*c", "bbc"); + TEST_REGISTERS ("((a*)|b)*c", "bbc", 0, 3, 1, 2, 1, 1); + + test_fastmap ("(a{0,}|b)*c", "abc", 0, 0); + test_match ("(a{0,}|b)*c", "bbc"); + TEST_REGISTERS ("(a{0,}|b)*c", "bbc", 0, 3, 1, 2, -1, -1); + + test_fastmap ("((a{0,})|b)*c", "abc", 0, 0); + test_match ("((a{0,})|b)*c", "bbc"); + TEST_REGISTERS ("((a{0,})|b)*c", "bbc", 0, 3, 1, 2, 1, 1); + + + test_fastmap ("((a{0,}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a{0,}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a{0,}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a{0,}\\b\\<)|b)*", "ab", 0, 0); + test_match ("((a{0,}\\b\\<)|b)*", "b"); + TEST_REGISTERS ("((a{0,}\\b\\<)|b)*", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,1}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,1}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,1}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,2}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,2}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,2}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + + test_fastmap ("((a+?*{0,4095}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,4095}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,4095}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,5119}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,5119}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,5119}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,6143}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,6143}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,6143}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,8191}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,8191}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,8191}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,16383}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,16383}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,16383}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + + test_fastmap ("((a+?*{0,}\\b\\<)|b)", "ab", 0, 0); + test_match ("((a+?*{0,}\\b\\<)|b)", "b"); + TEST_REGISTERS ("((a+?*{0,}\\b\\<)|b)", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,}\\b\\<)|b)*", "ab", 0, 0); + test_match ("((a+?*{0,}\\b\\<)|b)*", "b"); + TEST_REGISTERS ("((a+?*{0,}\\b\\<)|b)*", "b", + 0, 1, 0, 1, 0, 0); + + test_fastmap ("((a+?*{0,}\\b\\<)|b)*", "ab", 0, 0); + test_match ("((a+?*{0,}\\b\\<)|b)*", "bb"); + TEST_REGISTERS ("((a+?*{0,}\\b\\<)|b)*", "bb", + 0, 2, 1, 2, 0, 0); + + + /* `*' after group. */ + test_match ("(a*|b*)*c", "c"); + TEST_REGISTERS ("(a*|b*)*c", "c", 0, 1, 0, 0, -1, -1); + + test_match ("(a*|b*)*c", "ac"); + TEST_REGISTERS ("(a*|b*)*c", "ac", 0, 2, 0, 1, -1, -1); + + test_match ("(a*|b*)*c", "aac"); + TEST_REGISTERS ("(a*|b*)*c", "aac", 0, 3, 0, 2, -1, -1); + + test_match ("(a*|b*)*c", "bbc"); + TEST_REGISTERS ("(a*|b*)*c", "bbc", 0, 3, 0, 2, -1, -1); + + test_match ("(a*|b*)*c", "abc"); + TEST_REGISTERS ("(a*|b*)*c", "abc", 0, 3, 1, 2, -1, -1); + + /* No `*' after group. */ + test_match ("(a*|b*)c", "c"); + TEST_REGISTERS ("(a*|b*)c", "c", 0, 1, 0, 0, -1, -1); + + test_match ("(a*|b*)c", "ac"); + TEST_REGISTERS ("(a*|b*)c", "ac", 0, 2, 0, 1, -1, -1); + + test_match ("(a*|b*)c", "bc"); + TEST_REGISTERS ("(a*|b*)c", "bc", 0, 2, 0, 1, -1, -1); + + test_match ("(a*|b*)c", "aac"); + TEST_REGISTERS ("(a*|b*)c", "aac", 0, 3, 0, 2, -1, -1); + + /* Same as above, but with no `*'s in alternatives. + + test_match ("(a|b)*c", "c"); /* `*' after group. */ + TEST_REGISTERS ("(a|b)*c", "c", 0, 1, -1, -1, -1, -1); + + test_match ("(a|b)*c", "ac"); + TEST_REGISTERS ("(a|b)*c", "ac", 0, 2, 0, 1, -1, -1); + + test_match ("(a|b)*c", "bc"); + TEST_REGISTERS ("(a|b)*c", "bc", 0, 2, 0, 1, -1, -1); + + test_match ("(a|b)*c", "abc"); + TEST_REGISTERS ("(a|b)*c", "abc", 0, 3, 1, 2, -1, -1); + + + test_match ("(a*|b*)c", "bbc"); + TEST_REGISTERS ("(a*|b*)c", "bbc", 0, 3, 0, 2, -1, -1); + + /* Complicated second alternative. */ + + test_match ("(a*|(b*)*)*c", "bc"); + TEST_REGISTERS ("(a*|(b*)*)*c", "bc", 0, 2, 0, 1, 0, 1); + + test_match ("(a*|(b*|c*)*)*d", "bd"); + TEST_REGISTERS ("(a*|(b*|c*)*)*d", "bd", 0, 2, 0, 1, 0, 1); + + test_match ("(a*|(b*|c*)*)*d", "bbd"); + TEST_REGISTERS ("(a*|(b*|c*)*)*d", "bbd", 0, 3, 0, 2, 0, 2); + + test_match ("(a*|(b*|c*)*)*d", "cd"); + TEST_REGISTERS ("(a*|(b*|c*)*)*d", "cd", 0, 2, 0, 1, 0, 1); + + test_match ("(a*|(b*|c*)*)*d", "ccd"); + TEST_REGISTERS ("(a*|(b*|c*)*)*d", "ccd", 0, 3, 0, 2, 0, 2); + + test_match ("(a*|b*|c*)*d", "aad"); + TEST_REGISTERS ("(a*|b*|c*)*d", "aad", 0, 3, 0, 2, 0, 2); + + test_match ("(a*|b*|c*)*d", "bbd"); + TEST_REGISTERS ("(a*|b*|c*)*d", "bbd", 0, 3, 0, 2, 0, 2); + + test_match ("(a*|b*|c*)*d", "ccd"); + TEST_REGISTERS ("(a*|b*|c*)*d", "ccd", 0, 3, 0, 2, 0, 2); + + /* Valid anchoring. */ + valid_pattern ("a^"); + valid_pattern ("a^b"); + valid_pattern ("$a"); + valid_pattern ("a$b"); + valid_pattern ("foo^bar"); + valid_pattern ("foo$bar"); + valid_pattern ("(^)"); + valid_pattern ("($)"); + valid_pattern ("(^$)"); + + /* These are the same (but valid) as those (invalid) in other_test.c. */ + valid_pattern + ("(((((((((((((((((((((((((((((((((a^)))))))))))))))))))))))))))))))))"); + valid_pattern + ("((((((((((((((((((((((((((((((((($a)))))))))))))))))))))))))))))))))"); + valid_pattern ("\\(^a\\)"); + valid_pattern ("a\\|^b"); + valid_pattern ("\\w^a"); + valid_pattern ("\\W^a"); + valid_pattern ("(a^)"); + valid_pattern ("($a)"); + valid_pattern ("a(^b)"); + valid_pattern ("a$(b)"); + valid_pattern ("(a)^b"); + valid_pattern ("(a)$b"); + valid_pattern ("(a)(^b)"); + valid_pattern ("(a$)(b)"); + valid_pattern ("(a|b)^c"); + valid_pattern ("(a|b)$c"); + valid_pattern ("(a$|b)c"); + valid_pattern ("(a|b$)c"); + valid_pattern ("a(b|^c)"); + valid_pattern ("a(^b|c)"); + valid_pattern ("a$(b|c)"); + valid_pattern ("(a)(^b|c)"); + valid_pattern ("(a)(b|^c)"); + valid_pattern ("(b$|c)(a)"); + valid_pattern ("(b|c$)(a)"); + valid_pattern ("(a(^b|c))"); + valid_pattern ("(a(b|^c))"); + valid_pattern ("((b$|c)a)"); + valid_pattern ("((b|c$)a)"); + valid_pattern ("((^a|^b)^c)"); + valid_pattern ("(c$(a$|b$))"); + valid_pattern ("((^a|^b)^c)"); + valid_pattern ("((a$|b$)c)"); + valid_pattern ("(c$(a$|b$))"); + valid_pattern ("((^a|^b)|^c)^d"); + valid_pattern ("((a$|b$)|c$)d$"); + valid_pattern ("d$(c$|(a$|b$))"); + valid_pattern ("((^a|^b)|^c)(^d)"); + valid_pattern ("((a$|b$)|c$)(d$)"); + valid_pattern ("(d$)((a$|b$)|c$)"); + valid_pattern ("((^a|^b)|^c)((^d))"); + valid_pattern ("((a$|b$)|c$)((d$))"); + valid_pattern ("((d$))((a$|b$)|c$)"); + valid_pattern ("(((^a|^b))c|^d)^e"); + valid_pattern ("(((a$|b$))c|d$)$e$"); + valid_pattern ("e$(d$|c((a$|b$)))"); + valid_pattern ("(^a)((^b))"); + valid_pattern ("(a$)((b$))"); + valid_pattern ("((^a))(^b)"); + valid_pattern ("((a$))(b$)"); + valid_pattern ("((^a))((^b))"); + valid_pattern ("((a$))((b$))"); + valid_pattern ("((^a)^b)"); + valid_pattern ("((a$)b$)"); + valid_pattern ("(b$(a$))"); + valid_pattern ("(((^a)b)^c)"); + valid_pattern ("(((a$)b)c$)"); + valid_pattern ("(c$(b(a$)))"); + valid_pattern ("(((^a)b)c)^d"); + valid_pattern ("(((a$)b)c)d$"); + valid_pattern ("d$(c(b(a$)))"); + valid_pattern (".^a"); + valid_pattern ("a$."); + valid_pattern ("[a]^b"); + valid_pattern ("b$[a]"); + valid_pattern ("\\(a$\\)"); + valid_pattern ("a$\\|b"); + valid_pattern ("(^a|^b)^c"); + valid_pattern ("c$(a$|b$)"); + valid_pattern ("(^a|^b)^|^c"); + valid_pattern ("(a$|b$)$|$c$"); + valid_pattern ("(a$|$b$)$|c$"); + valid_pattern ("($a$|b$)$|c$"); + valid_pattern ("$(a$|b$)$|c$"); + valid_pattern ("^c|d(^a|^b)"); + valid_pattern ("(^a|^b)|d^c"); + valid_pattern ("c$|(a$|b$)d"); + valid_pattern ("c$d|(a$|b$)"); + valid_pattern ("c(^a|^b)|^d"); + valid_pattern ("(a$|b$)c|d$"); + valid_pattern ("c(((^a|^b))|^d)e"); + valid_pattern ("(c((^a|^b))|^d)e"); + valid_pattern ("((c(^a|^b))|^d)e"); + valid_pattern ("(((^a|^b))|c^d)e"); + valid_pattern ("(((^a|^b))|^d)^e"); + valid_pattern ("(c$((a|b))|d)e$"); + valid_pattern ("(c((a$|b$))|d)e$"); + valid_pattern ("(c((a|b)$)|d)e$"); + valid_pattern ("(c((a|b))|d$)e$"); + valid_pattern ("^d(^c|e((a|b)))"); + valid_pattern ("^d(c|^e((a|b)))"); + valid_pattern ("^d(c|e(^(a|b)))"); + valid_pattern ("^d(c|e((^a|b)))"); + valid_pattern ("^d(c|e((a|^b)))"); + valid_pattern ("^d(c|e((a|b^)))"); + valid_pattern ("^d(c|e((a|b)^))"); + valid_pattern ("^d(c|e((a|b))^)"); + valid_pattern ("^d(c|e((a|b)))^"); + valid_pattern ("d$(c$|e((a$|b$)))"); + valid_pattern ("d(c$|e$((a$|b$)))"); + valid_pattern ("(((^a|^b))^c)|^de"); + valid_pattern ("(((^a|^b))c)|^d^e"); + valid_pattern ("(((a$|b))c$)|de$"); + valid_pattern ("(((a|b$))c$)|de$"); + valid_pattern ("(((a|b))c$)|d$e$"); + valid_pattern ("^d^e|^(c((a|b)))"); + valid_pattern ("^de|^(c^((a|b)))"); + valid_pattern ("^de|^(c(^(a|b)))"); + valid_pattern ("^de|^(c((^a|b)))"); + valid_pattern ("^de|^(c((a|^b)))"); + valid_pattern ("^de|(^c(^(a|b)))"); + valid_pattern ("^de|(^c((^a|b)))"); + valid_pattern ("^de|(^c((a|^b)))"); + valid_pattern ("de$|(c($(a|b)$))"); + valid_pattern ("de$|(c$((a|b)$))"); + valid_pattern ("de$|($c((a|b)$))"); + valid_pattern ("de$|$(c((a|b)$))"); + valid_pattern ("de$|(c($(a|b))$)"); + valid_pattern ("de$|(c$((a|b))$)"); + valid_pattern ("de$|$(c((a|b))$)"); + valid_pattern ("de$|(c($(a|b)))$"); + valid_pattern ("de$|(c$((a|b)))$"); + valid_pattern ("de$|($c((a|b)))$"); + valid_pattern ("de$|$(c((a|b)))$"); + valid_pattern ("^a(^b|c)|^d"); + valid_pattern ("^a(b|^c)|^d"); + valid_pattern ("^a(b|c^)|^d"); + valid_pattern ("^a(b|c)^|^d"); + valid_pattern ("a$(b$|c$)|d$"); + valid_pattern ("^d|^a(^b|c)"); + valid_pattern ("^d|^a(b|^c)"); + valid_pattern ("d$|a$(b$|c$)"); + valid_pattern ("^d|^(b|c)^a"); + valid_pattern ("d$|(b|c$)a$"); + valid_pattern ("d$|(b$|c)a$"); + valid_pattern ("^(a)^(b|c)|^d"); + valid_pattern ("^(a)(^b|c)|^d"); + valid_pattern ("^(a)(b|^c)|^d"); + valid_pattern ("(a)$(b|c)$|d$"); + valid_pattern ("(a$)(b|c)$|d$"); + valid_pattern ("(^a)(^b|c)|^d"); + valid_pattern ("(^a)(b|^c)|^d"); + valid_pattern ("(a)$(b$|c$)|d$"); + valid_pattern ("(a$)(b$|c$)|d$"); + valid_pattern ("^d|^(b|c)^(a)"); + valid_pattern ("^d|^(b|c)(^a)"); + valid_pattern ("d$|(b|c$)(a)$"); + valid_pattern ("d$|(b$|c)(a)$"); + valid_pattern ("^d|(^b|^c)^(a)"); + valid_pattern ("^d|(^b|^c)(^a)"); + valid_pattern ("d$|(b|c)$(a$)"); + valid_pattern ("d$|(b|c$)(a$)"); + valid_pattern ("d$|(b$|c)(a$)"); + valid_pattern ("^d|^(a)^(b|c)"); + valid_pattern ("^d|^(a)(^b|c)"); + valid_pattern ("^d|^(a)(b|^c)"); + valid_pattern ("^d|(^a)^(b|c)"); + valid_pattern ("^d|(^a)(^b|c)"); + valid_pattern ("^d|(^a)(b|^c)"); + valid_pattern ("d$|(a)$(b$|c$)"); + valid_pattern ("d$|(a$)(b$|c$)"); + valid_pattern ("((e^a|^b)|^c)|^d"); + valid_pattern ("((^a|e^b)|^c)|^d"); + valid_pattern ("((^a|^b)|e^c)|^d"); + valid_pattern ("((^a|^b)|^c)|e^d"); + valid_pattern ("d$e|(c$|(a$|b$))"); + valid_pattern ("d$|(c$e|(a$|b$))"); + valid_pattern ("d$|(c$|(a$e|b$))"); + valid_pattern ("d$|(c$|(a$|b$e))"); + valid_pattern ("d$|(c$|(a$|b$)e)"); + valid_pattern ("d$|(c$|(a$|b$))e"); + valid_pattern ("(a|b)^|c"); + valid_pattern ("(a|b)|c^"); + valid_pattern ("$(a|b)|c"); + valid_pattern ("(a|b)|$c"); + valid_pattern ("(a^|^b)|^c"); + valid_pattern ("(^a|b^)|^c"); + valid_pattern ("(^a|^b)|c^"); + valid_pattern ("($a|b$)|c$"); + valid_pattern ("(a$|$b)|c$"); + valid_pattern ("(a$|b$)|$c"); + valid_pattern ("c^|(^a|^b)"); + valid_pattern ("^c|(a^|^b)"); + valid_pattern ("^c|(^a|b^)"); + valid_pattern ("$c|(a$|b$)"); + valid_pattern ("c$|($a|b$)"); + valid_pattern ("c$|(a$|$b)"); + valid_pattern ("c^|^(a|b)"); + valid_pattern ("^c|(a|b)^"); + valid_pattern ("$c|(a|b)$"); + valid_pattern ("c$|$(a|b)"); + valid_pattern ("(a^|^b)c|^d"); + valid_pattern ("(^a|b^)c|^d"); + valid_pattern ("(^a|^b)c|d^"); + valid_pattern ("(^a|^b)^c|^d"); + valid_pattern ("(a|b)c$|$d"); + valid_pattern ("(a|b)$c$|d$"); + valid_pattern ("(a|b)$c$|d$"); + valid_pattern ("(a|b$)c$|d$"); + valid_pattern ("(a$|b)c$|d$"); + valid_pattern ("($a|b)c$|d$"); + valid_pattern ("$(a|b)c$|d$"); + valid_pattern ("^d|^c^(a|b)"); + valid_pattern ("^d|^c(^a|b)"); + valid_pattern ("^d|^c(a|^b)"); + valid_pattern ("^d|^c(a|b^)"); + valid_pattern ("^d|^c(a|b)^"); + valid_pattern ("$d|c(a$|b$)"); + valid_pattern ("d$|c($a$|b$)"); + valid_pattern ("d$|c$(a$|b$)"); + valid_pattern ("d$|$c(a$|b$)"); + + valid_pattern ("(((a^|^b))c|^d)e"); + valid_pattern ("(((^a|b^))c|^d)e"); + valid_pattern ("(((^a|^b))^c|^d)e"); + valid_pattern ("((^(a|b))c|d^)e"); + valid_pattern ("(^((a|b))c|^d)^e"); + valid_pattern ("(^((a|b)^)c|^d)e"); + valid_pattern ("(^((a^|b))c|^d)e"); + valid_pattern ("(^((a|b^))c|^d)e"); + valid_pattern ("(^((a|b)^)c|^d)e"); + valid_pattern ("(^((a|b))^c|^d)e"); + valid_pattern ("(^((a|b))c^|^d)e"); + valid_pattern ("(^((a|b))c|^d^)e"); + valid_pattern ("(^((a|b))c|^d)^e"); + valid_pattern ("(((a|b))c|d)$e$"); + valid_pattern ("(((a|b))c|d$)e$"); + valid_pattern ("(((a|b))c|$d)e$"); + valid_pattern ("(((a|b))c$|d)e$"); + valid_pattern ("(((a|b))$c|d)e$"); + valid_pattern ("(((a|b)$)c|d)e$"); + valid_pattern ("(((a|b$))c|d)e$"); + valid_pattern ("(((a$|b))c|d)e$"); + valid_pattern ("((($a|b))c|d)e$"); + valid_pattern ("(($(a|b))c|d)e$"); + valid_pattern ("($((a|b))c|d)e$"); + valid_pattern ("$(((a|b))c|d)e$"); + valid_pattern ("(^((a|b)^)c|^d)e"); + valid_pattern ("(^((a|b))^c|^d)e"); + valid_pattern ("(^((a|b))c|^d^)e"); + valid_pattern ("(^((a|b))c|^d)^e"); + + valid_pattern ("^e(^d|c((a|b)))"); + valid_pattern ("^e(d|^c((a|b)))"); + valid_pattern ("^e(d|c^((a|b)))"); + valid_pattern ("^e(d|c(^(a|b)))"); + valid_pattern ("^e(d|c((^a|b)))"); + valid_pattern ("^e(d|c((a|^b)))"); + valid_pattern ("^e(d|c((a|b^)))"); + valid_pattern ("^e(d|c((a|b)^))"); + valid_pattern ("^e(d|c((a|b))^)"); + valid_pattern ("^e(d|c((a|b)))^"); + valid_pattern ("e$(d$|c((a$|b$)))"); + valid_pattern ("e(d$|c$((a$|b$)))"); + valid_pattern ("e(d$|c($(a$|b$)))"); + valid_pattern ("e(d$|c(($a$|b$)))"); + valid_pattern ("e$(d$|c((a|b)$))"); + valid_pattern ("e($d$|c((a|b)$))"); + valid_pattern ("e(d$|$c((a|b)$))"); + valid_pattern ("e(d$|c$((a|b)$))"); + valid_pattern ("e(d$|c($(a|b)$))"); + valid_pattern ("e(d$|c(($a|b)$))"); + valid_pattern ("e(d$|c((a|$b)$))"); + valid_pattern ("e(d$|c((a$|$b$)))"); + + valid_pattern ("e$(d$|c((a|b))$)"); + valid_pattern ("e($d$|c((a|b))$)"); + valid_pattern ("e(d$|$c((a|b))$)"); + valid_pattern ("e(d$|c$((a|b))$)"); + valid_pattern ("e(d$|c($(a|b))$)"); + valid_pattern ("e(d$|c(($a|b))$)"); + valid_pattern ("e(d$|c((a|$b))$)"); + valid_pattern ("e$(d$|c((a|b)))$"); + valid_pattern ("e($d$|c((a|b)))$"); + valid_pattern ("e(d$|$c((a|b)))$"); + valid_pattern ("e(d$|c$((a|b)))$"); + valid_pattern ("e(d$|c($(a|b)))$"); + valid_pattern ("e(d$|c(($a|b)))$"); + valid_pattern ("e(d$|c((a|$b)))$"); + valid_pattern ("(((^a|^b)^)c)|^de"); + valid_pattern ("(((^a|^b))^c)|^de"); + valid_pattern ("(((^a|^b))c)^|^de"); + valid_pattern ("$(((a|b))c$)|de$"); + valid_pattern ("($((a|b))c$)|de$"); + valid_pattern ("(($(a|b))c$)|de$"); + valid_pattern ("((($a|b))c$)|de$"); + valid_pattern ("(((a|$b))c$)|de$"); + valid_pattern ("(((a|b)$)c$)|de$"); + valid_pattern ("(((a|b))$c$)|de$"); + valid_pattern ("$(((a|b))c)$|de$"); + valid_pattern ("($((a|b))c)$|de$"); + valid_pattern ("(($(a|b))c)$|de$"); + valid_pattern ("((($a|b))c)$|de$"); + valid_pattern ("(((a|$b))c)$|de$"); + valid_pattern ("(((a|b)$)c)$|de$"); + valid_pattern ("(((a|b))$c)$|de$"); + valid_pattern ("^ed|^(c((a|b)))^"); + valid_pattern ("^ed|^(c((a|b))^)"); + valid_pattern ("^ed|^(c((a|b)^))"); + valid_pattern ("^ed|^(c((a|b^)))"); + valid_pattern ("^ed|^(c((a^|b)))"); + valid_pattern ("^ed|^(c((^a|b)))"); + valid_pattern ("^ed|^(c(^(a|b)))"); + valid_pattern ("^ed|^(c^((a|b)))"); + valid_pattern ("^ed|(^c((a|b)))^"); + valid_pattern ("^ed|(^c((a|b))^)"); + valid_pattern ("^ed|(^c((a|b)^))"); + valid_pattern ("^ed|(^c((a|b^)))"); + valid_pattern ("^ed|(^c((a|^b)))"); + valid_pattern ("^ed|(^c((a^|b)))"); + valid_pattern ("^ed|(^c((^a|b)))"); + valid_pattern ("^ed|(^c(^(a|b)))"); + valid_pattern ("^ed|(^c(^(a|b)))"); + valid_pattern ("^ed|(^c^((a|b)))"); + valid_pattern ("ed$|$(c((a|b)))$"); + valid_pattern ("ed$|($c((a|b)))$"); + valid_pattern ("ed$|(c$((a|b)))$"); + valid_pattern ("ed$|(c($(a|b)))$"); + valid_pattern ("ed$|(c(($a|b)))$"); + valid_pattern ("ed$|(c((a|$b)))$"); + valid_pattern ("ed$|$(c((a|b))$)"); + valid_pattern ("ed$|($c((a|b))$)"); + valid_pattern ("ed$|(c$((a|b))$)"); + valid_pattern ("ed$|(c($(a|b))$)"); + valid_pattern ("ed$|(c(($a|b))$)"); + valid_pattern ("ed$|(c((a|$b))$)"); + valid_pattern ("ed$|$(c((a|b)$))"); + valid_pattern ("ed$|($c((a|b)$))"); + valid_pattern ("ed$|(c$((a|b)$))"); + valid_pattern ("ed$|(c($(a|b)$))"); + valid_pattern ("ed$|(c(($a|b)$))"); + valid_pattern ("ed$|(c((a|$b)$))"); + valid_pattern ("ed$|$(c((a|b)$))"); + valid_pattern ("ed$|($c((a|b)$))"); + valid_pattern ("ed$|(c$((a|b)$))"); + valid_pattern ("ed$|(c($(a|b)$))"); + valid_pattern ("ed$|(c(($a|b)$))"); + valid_pattern ("ed$|(c((a|$b)$))"); + valid_pattern ("ed$|$(c((a|b)$))"); + valid_pattern ("ed$|($c((a|b)$))"); + valid_pattern ("ed$|(c$((a|b)$))"); + valid_pattern ("ed$|(c($(a|b)$))"); + valid_pattern ("ed$|(c(($a|b)$))"); + valid_pattern ("ed$|(c((a|$b)$))"); + valid_pattern ("ed$|$(c((a|b)$))"); + valid_pattern ("ed$|($c((a|b)$))"); + valid_pattern ("ed$|(c$((a|b)$))"); + valid_pattern ("ed$|(c($(a|b)$))"); + valid_pattern ("ed$|(c(($a|b)$))"); + valid_pattern ("ed$|(c((a|$b)$))"); + valid_pattern ("ed$|$(c((a|b)$))"); + valid_pattern ("ed$|($c((a|b)$))"); + valid_pattern ("ed$|(c$((a|b)$))"); + valid_pattern ("ed$|(c($(a|b)$))"); + valid_pattern ("ed$|(c(($a|b)$))"); + valid_pattern ("ed$|(c((a|$b)$))"); + valid_pattern ("ed$|$(c((a$|b$)))"); + valid_pattern ("ed$|($c((a$|b$)))"); + valid_pattern ("ed$|(c$((a$|b$)))"); + valid_pattern ("ed$|(c($(a$|b$)))"); + valid_pattern ("ed$|(c(($a$|b$)))"); + valid_pattern ("ed$|(c((a$|$b$)))"); + valid_pattern ("^a(b|c)^|^d"); + valid_pattern ("^a(b|c^)|^d"); + valid_pattern ("^a(b|^c)|^d"); + valid_pattern ("^a(b^|c)|^d"); + valid_pattern ("^a(^b|c)|^d"); + valid_pattern ("^a^(b|c)|^d"); + valid_pattern ("$a(b$|c$)|d$"); + valid_pattern ("a$(b$|c$)|d$"); + valid_pattern ("a($b$|c$)|d$"); + valid_pattern ("a(b$|$c$)|d$"); + valid_pattern ("a(b$|c$)|$d$"); + valid_pattern ("^(a^)(b|c)|^d"); + valid_pattern ("^(a)^(b|c)|^d"); + valid_pattern ("^(a)(^b|c)|^d"); + valid_pattern ("^(a)(b^|c)|^d"); + valid_pattern ("^(a)(b|^c)|^d"); + valid_pattern ("^(a)(b|c^)|^d"); + valid_pattern ("^(a)(b|c)^|^d"); + valid_pattern ("(^a^)(b|c)|^d"); + valid_pattern ("(^a)^(b|c)|^d"); + valid_pattern ("(^a)(^b|c)|^d"); + valid_pattern ("(^a)(b^|c)|^d"); + valid_pattern ("(^a)(b|^c)|^d"); + valid_pattern ("(^a)(b|c^)|^d"); + valid_pattern ("(^a)(b|c)^|^d"); + + valid_pattern ("(a)(b$|c$)d$"); + valid_pattern ("(a)(b|$c)$|d$"); + valid_pattern ("(a)($b|c)$|d$"); + valid_pattern ("(a)$(b|c)$|d$"); + valid_pattern ("(a$)(b|c)$|d$"); + valid_pattern ("($a)(b|c)$|d$"); + valid_pattern ("$(a)(b|c)$|d$"); + valid_pattern ("(b|c)($a)$|d$"); + valid_pattern ("(b|c)$(a)$|d$"); + valid_pattern ("(b|c$)(a)$|d$"); + valid_pattern ("(b|$c)(a)$|d$"); + valid_pattern ("(b$|c)(a)$|d$"); + valid_pattern ("($b|c)(a)$|d$"); + valid_pattern ("$(b|c)(a)$|d$"); + valid_pattern ("(b|c)($a$)|d$"); + valid_pattern ("(b|c)$(a$)|d$"); + valid_pattern ("(b|c$)(a$)|d$"); + valid_pattern ("(b|$c)(a$)|d$"); + valid_pattern ("(b$|c)(a$)|d$"); + valid_pattern ("($b|c)(a$)|d$"); + valid_pattern ("$(b|c)(a$)|d$"); + valid_pattern ("(a)$(b$|c$)|d$"); + valid_pattern ("(a$)(b$|c$)|d$"); + valid_pattern ("($a)(b$|c$)|d$"); + valid_pattern ("$(a)(b$|c$)|d$"); + valid_pattern ("^d|^(b^|c)(a)"); + valid_pattern ("^d|^(b|c^)(a)"); + valid_pattern ("^d|^(b|c)^(a)"); + valid_pattern ("^d|^(b|c)(^a)"); + valid_pattern ("^d|^(b|c)(a^)"); + valid_pattern ("^d|^(b|c)(a)^"); + valid_pattern ("^d|(^b|^c^)(a)"); + valid_pattern ("^d|(^b|^c)^(a)"); + valid_pattern ("^d|(^b|^c)(^a)"); + valid_pattern ("^d|(^b|^c)(a^)"); + valid_pattern ("^d|(^b|^c)(a)^"); + valid_pattern ("d$|(b|c)($a$)"); + valid_pattern ("d$|(b|c)$(a$)"); + valid_pattern ("d$|(b|c$)(a$)"); + valid_pattern ("d$|(b$|c)(a$)"); + valid_pattern ("d$|($b|c)(a$)"); + valid_pattern ("d$|$(b|c)(a$)"); + valid_pattern ("d$|(b|c)($a)$"); + valid_pattern ("d$|(b|c)$(a)$"); + valid_pattern ("d$|(b|c$)(a)$"); + valid_pattern ("d$|(b$|c)(a)$"); + valid_pattern ("d$|($b|c)(a)$"); + valid_pattern ("d$|$(b|c)(a)$"); + valid_pattern ("^d|^(a^)(b|c)"); + valid_pattern ("^d|^(a)^(b|c)"); + valid_pattern ("^d|^(a)(^b|c)"); + valid_pattern ("^d|^(a)(b^|c)"); + valid_pattern ("^d|^(a)(b|^c)"); + valid_pattern ("^d|^(a)(b|c^)"); + valid_pattern ("^d|^(a)(b|c)^"); + valid_pattern ("^d|(^a^)(b|c)"); + valid_pattern ("^d|(^a)^(b|c)"); + valid_pattern ("^d|(^a)(^b|c)"); + valid_pattern ("^d|(^a)(b^|c)"); + valid_pattern ("^d|(^a)(b|^c)"); + valid_pattern ("^d|(^a)(b|c^)"); + valid_pattern ("^d|(^a)(b|c)^"); + valid_pattern ("d$|(a)$(b$|c$)"); + valid_pattern ("d$|(a$)(b$|c$)"); + valid_pattern ("d$|($a)(b$|c$)"); + valid_pattern ("d$|$(a)(b$|c$)"); + valid_pattern ("d$|(a)(b|$c)$"); + valid_pattern ("d$|(a)($b|c)$"); + valid_pattern ("d$|(a)$(b|c)$"); + valid_pattern ("d$|(a$)(b|c)$"); + valid_pattern ("d$|($a)(b|c)$"); + valid_pattern ("d$|$(a)(b|c)$"); + valid_pattern ("((^a|^b)|^c)|^d^"); + valid_pattern ("((^a|^b)|^c)^|^d"); + valid_pattern ("((^a|^b)|^c^)|^d"); + valid_pattern ("((^a|^b)^|^c)|^d"); + valid_pattern ("((^a|^b^)|^c)|^d"); + valid_pattern ("((^a^|^b)|^c)|^d"); + valid_pattern ("((a|b)|c)|$d$"); + valid_pattern ("((a|b)|$c)|d$"); + valid_pattern ("((a|$b)|c)|d$"); + valid_pattern ("(($a|b)|c)|d$"); + valid_pattern ("($(a|b)|c)|d$"); + valid_pattern ("$((a|b)|c)|d$"); + valid_pattern ("^d^|(c|(a|b))"); + valid_pattern ("^d|(c^|(a|b))"); + valid_pattern ("^d|(c|(a^|b))"); + valid_pattern ("^d|(c|(a|b^))"); + valid_pattern ("^d|(c|(a|b)^)"); + valid_pattern ("^d|(c|(a|b))^"); + valid_pattern ("d$|(c$|(a$|$b$))"); + valid_pattern ("d$|(c$|($a$|b$))"); + valid_pattern ("d$|($c$|(a$|b$))"); + valid_pattern ("d$|$(c$|(a$|b$))"); + valid_pattern ("$d$|(c$|(a$|b$))"); + valid_pattern ("d$|(c$|(a|$b)$)"); + valid_pattern ("d$|(c$|($a|b)$)"); + valid_pattern ("d$|($c$|(a|b)$)"); + valid_pattern ("d$|$(c$|(a|b)$)"); + valid_pattern ("$d$|(c$|(a|b)$)"); + valid_pattern ("d$|(c$|(a|$b))$"); + valid_pattern ("d$|(c$|($a|b))$"); + valid_pattern ("d$|($c$|(a|b))$"); + valid_pattern ("d$|$(c$|(a|b))$"); + valid_pattern ("$d$|(c$|(a|b))$"); + valid_pattern ("^c^|(^a|^b)"); + valid_pattern ("^c|(^a^|^b)"); + valid_pattern ("^c|(^a|^b^)"); + valid_pattern ("^c|(^a|^b)^"); + valid_pattern ("c$|(a$|$b$)"); + valid_pattern ("c$|($a$|b$)"); + valid_pattern ("c$|$(a$|b$)"); + valid_pattern ("$c$|(a$|b$)"); + valid_pattern ("^d^(c|e((a|b)))"); + valid_pattern ("^d(^c|e((a|b)))"); + valid_pattern ("^d(c^|e((a|b)))"); + valid_pattern ("^d(c|^e((a|b)))"); + valid_pattern ("^d(c|e^((a|b)))"); + valid_pattern ("^d(c|e(^(a|b)))"); + valid_pattern ("^d(c|e((^a|b)))"); + valid_pattern ("^d(c|e((a|^b)))"); + valid_pattern ("^d(c|e((a|b^)))"); + valid_pattern ("^d(c|e((a|b)^))"); + valid_pattern ("^d(c|e((a|b))^)"); + valid_pattern ("^d(c|e((a|b)))^"); + valid_pattern ("d(c$|e($(a$|b$)))"); + valid_pattern ("d(c$|e$((a$|b$)))"); + valid_pattern ("d(c$|$e((a$|b$)))"); + valid_pattern ("d($c$|e((a$|b$)))"); + valid_pattern ("d$(c$|e((a$|b$)))"); + valid_pattern ("$d(c$|e((a$|b$)))"); + valid_pattern ("^d|^a^(b|c)"); + valid_pattern ("^d|^a(^b|c)"); + valid_pattern ("^d|^a(b^|c)"); + valid_pattern ("^d|^a(b|^c)"); + valid_pattern ("^d|^a(b|c^)"); + valid_pattern ("^d|^a(b|c)^"); + valid_pattern ("d$|a($b$|c$)"); + valid_pattern ("d$|a$(b$|c$)"); + valid_pattern ("d$|$a(b$|c$)"); + valid_pattern ("$d$|a(b$|c$)"); + valid_pattern ("^d|^(b^|c)a"); + valid_pattern ("^d|^(b|c^)a"); + valid_pattern ("^d|^(b|c)^a"); + valid_pattern ("^d|^(b|c)a^"); + valid_pattern ("d$|(b|c)$a$"); + valid_pattern ("d$|(b|c$)a$"); + valid_pattern ("d$|(b|$c)a$"); + valid_pattern ("d$|(b$|c)a$"); + valid_pattern ("d$|($b|c)a$"); + valid_pattern ("d$|$(b|c)a$"); + valid_pattern ("$d$|(b|c)a$"); + + /* xx Do these use all the valid_nonposix_pattern ones in other_test.c? */ + + TEST_SEARCH ("(^a|^b)c", "ac", 0, 2); + TEST_SEARCH ("(^a|^b)c", "bc", 0, 2); + TEST_SEARCH ("c(a$|b$)", "ca", 0, 2); + TEST_SEARCH ("c(a$|b$)", "cb", 0, 2); + TEST_SEARCH ("^(a|b)|^c", "ad", 0, 2); + TEST_SEARCH ("^(a|b)|^c", "bd", 0, 2); + TEST_SEARCH ("(a|b)$|c$", "da", 0, 2); + TEST_SEARCH ("(a|b)$|c$", "db", 0, 2); + TEST_SEARCH ("(a|b)$|c$", "dc", 0, 2); + TEST_SEARCH ("(^a|^b)|^c", "ad", 0, 2); + TEST_SEARCH ("(^a|^b)|^c", "bd", 0, 2); + TEST_SEARCH ("(^a|^b)|^c", "cd", 0, 2); + TEST_SEARCH ("(a$|b$)|c$", "da", 0, 2); + TEST_SEARCH ("(a$|b$)|c$", "db", 0, 2); + TEST_SEARCH ("(a$|b$)|c$", "dc", 0, 2); + TEST_SEARCH ("^c|(^a|^b)", "ad", 0, 2); + TEST_SEARCH ("^c|(^a|^b)", "bd", 0, 2); + TEST_SEARCH ("^c|(^a|^b)", "cd", 0, 2); + TEST_SEARCH ("c$|(a$|b$)", "da", 0, 2); + TEST_SEARCH ("c$|(a$|b$)", "db", 0, 2); + TEST_SEARCH ("c$|(a$|b$)", "dc", 0, 2); + TEST_SEARCH ("^c|^(a|b)", "ad", 0, 2); + TEST_SEARCH ("^c|^(a|b)", "bd", 0, 2); + TEST_SEARCH ("^c|^(a|b)", "cd", 0, 2); + TEST_SEARCH ("c$|(a|b)$", "da", 0, 2); + TEST_SEARCH ("c$|(a|b)$", "db", 0, 2); + TEST_SEARCH ("c$|(a|b)$", "dc", 0, 2); + TEST_SEARCH ("(^a|^b)c|^d", "ace", 0, 3); + TEST_SEARCH ("(^a|^b)c|^d", "bce", 0, 3); + TEST_SEARCH ("(^a|^b)c|^d", "de", 0, 2); + TEST_SEARCH ("(a|b)c$|d$", "eac", 0, 3); + TEST_SEARCH ("(a|b)c$|d$", "ebc", 0, 3); + TEST_SEARCH ("(a|b)c$|d$", "ed", 0, 3); + TEST_SEARCH ("^d|^c(a|b)", "cae", 0, 3); + TEST_SEARCH ("^d|^c(a|b)", "cbe", 0, 3); + TEST_SEARCH ("^d|^c(a|b)", "de", 0, 3); + TEST_SEARCH ("d$|c(a$|b$)", "eca", 0, 3); + TEST_SEARCH ("d$|c(a$|b$)", "ecb", 0, 3); + TEST_SEARCH ("d$|c(a$|b$)", "ed", 0, 3); + + TEST_SEARCH ("(((^a|^b))c|^d)e", "acef", 0, 4); + TEST_SEARCH ("(((^a|^b))c|^d)e", "bcef", 0, 4); + TEST_SEARCH ("(((^a|^b))c|^d)e", "def", 0, 3); + + TEST_SEARCH ("((^(a|b))c|^d)e", "acef", 0, 4); + TEST_SEARCH ("((^(a|b))c|^d)e", "bcef", 0, 4); + TEST_SEARCH ("((^(a|b))c|^d)e", "def", 0, 3); + + TEST_SEARCH ("(^((a|b))c|^d)e", "acef", 0, 4); + TEST_SEARCH ("(^((a|b))c|^d)e", "bcef", 0, 4); + TEST_SEARCH ("(^((a|b))c|^d)e", "def", 0, 3); + + TEST_SEARCH ("(((a|b))c|d)e$", "face", 0, 4); + TEST_SEARCH ("(((a|b))c|d)e$", "fbce", 0, 4); + TEST_SEARCH ("(((a|b))c|d)e$", "fde", 0, 3); + + TEST_SEARCH ("^e(d|c((a|b)))", "edf", 0, 3); + TEST_SEARCH ("^e(d|c((a|b)))", "ecaf", 0, 4); + TEST_SEARCH ("^e(d|c((a|b)))", "ecbf", 0, 4); + + TEST_SEARCH ("e(d$|c((a$|b$)))", "fed", 0, 3); + TEST_SEARCH ("e(d$|c((a$|b$)))", "feca", 0, 4); + TEST_SEARCH ("e(d$|c((a$|b$)))", "fecb", 0, 4); + + TEST_SEARCH ("e(d$|c((a|b)$))", "fed", 0, 3); + TEST_SEARCH ("e(d$|c((a|b)$))", "feca", 0, 4); + TEST_SEARCH ("e(d$|c((a|b)$))", "fecb", 0, 4); + + TEST_SEARCH ("e(d$|c((a|b))$)", "fed", 0, 3); + TEST_SEARCH ("e(d$|c((a|b))$)", "feca", 0, 3); + TEST_SEARCH ("e(d$|c((a|b))$)", "fecb", 0, 3); + + TEST_SEARCH ("e(d$|c((a|b)))$", "fed", 0, 3); + TEST_SEARCH ("e(d$|c((a|b)))$", "feca", 0, 3); + TEST_SEARCH ("e(d$|c((a|b)))$", "fecb", 0, 3); + + TEST_SEARCH ("(((^a|^b))c)|^de", "acf", 0, 3); + TEST_SEARCH ("(((^a|^b))c)|^de", "bcf", 0, 3); + TEST_SEARCH ("(((^a|^b))c)|^de", "def", 0, 3); + + TEST_SEARCH ("(((a|b))c$)|de$", "fac", 0, 3); + TEST_SEARCH ("(((a|b))c$)|de$", "fbc", 0, 3); + TEST_SEARCH ("(((a|b))c$)|de$", "fde", 0, 3); + + TEST_SEARCH ("(((a|b))c)$|de$", "fac", 0, 3); + TEST_SEARCH ("(((a|b))c)$|de$", "fbc", 0, 3); + TEST_SEARCH ("(((a|b))c)$|de$", "fde", 0, 3); + + TEST_SEARCH ("^ed|^(c((a|b)))", "edf", 0, 3); + TEST_SEARCH ("^ed|^(c((a|b)))", "caf", 0, 3); + TEST_SEARCH ("^ed|^(c((a|b)))", "cbf", 0, 3); + + TEST_SEARCH ("^ed|(^c((a|b)))", "edf", 0, 3); + TEST_SEARCH ("^ed|(^c((a|b)))", "caf", 0, 3); + TEST_SEARCH ("^ed|(^c((a|b)))", "cbf", 0, 3); + + TEST_SEARCH ("ed$|(c((a|b)))$", "fed", 0, 3); + TEST_SEARCH ("ed$|(c((a|b)))$", "fca", 0, 3); + TEST_SEARCH ("ed$|(c((a|b)))$", "fcb", 0, 3); + + TEST_SEARCH ("ed$|(c((a|b))$)", "fed", 0, 3); + TEST_SEARCH ("ed$|(c((a|b))$)", "fca", 0, 3); + TEST_SEARCH ("ed$|(c((a|b))$)", "fcb", 0, 3); + + TEST_SEARCH ("ed$|(c((a|b)$))", "fed", 0, 3); + TEST_SEARCH ("ed$|(c((a|b)$))", "fca", 0, 3); + TEST_SEARCH ("ed$|(c((a|b)$))", "fcb", 0, 3); + + TEST_SEARCH ("ed$|(c((a$|b$)))", "fed", 0, 3); + TEST_SEARCH ("ed$|(c((a$|b$)))", "fca", 0, 3); + TEST_SEARCH ("ed$|(c((a$|b$)))", "fcb", 0, 3); + + TEST_SEARCH ("^a(b|c)|^d", "abe", 0, 3); + TEST_SEARCH ("^a(b|c)|^d", "ace", 0, 3); + TEST_SEARCH ("^a(b|c)|^d", "df", 0, 2); + + TEST_SEARCH ("a(b$|c$)|d$", "fab", 0, 3); + TEST_SEARCH ("a(b$|c$)|d$", "fac", 0, 3); + TEST_SEARCH ("a(b$|c$)|d$", "fd", 0, 2); + + TEST_SEARCH ("^(a)(b|c)|^d", "abe", 0, 3); + TEST_SEARCH ("^(a)(b|c)|^d", "ace", 0, 3); + TEST_SEARCH ("^(a)(b|c)|^d", "df", 0, 2); + + TEST_SEARCH ("(^a)(b|c)|^d", "abe", 0, 3); + TEST_SEARCH ("(^a)(b|c)|^d", "ace", 0, 3); + TEST_SEARCH ("(^a)(b|c)|^d", "df", 0, 2); + + TEST_SEARCH ("(a)(b|c)$|d$", "fab", 0, 3); + TEST_SEARCH ("(a)(b|c)$|d$", "fac", 0, 3); + TEST_SEARCH ("(a)(b|c)$|d$", "fd", 0, 2); + + TEST_SEARCH ("(b|c)(a)$|d$", "fba", 0, 3); + TEST_SEARCH ("(b|c)(a)$|d$", "fca", 0, 3); + TEST_SEARCH ("(b|c)(a)$|d$", "fd", 0, 2); + + TEST_SEARCH ("(b|c)(a$)|d$", "fba", 0, 3); + TEST_SEARCH ("(b|c)(a$)|d$", "fca", 0, 3); + TEST_SEARCH ("(b|c)(a$)|d$", "fd", 0, 2); + + TEST_SEARCH ("(a)(b$|c$)|d$", "fab", 0, 3); + TEST_SEARCH ("(a)(b$|c$)|d$", "fac", 0, 3); + TEST_SEARCH ("(a)(b$|c$)|d$", "fd", 0, 2); + + TEST_SEARCH ("^d|^(b|c)(a)", "df", 0, 2); + TEST_SEARCH ("^d|^(b|c)(a)", "baf", 0, 3); + TEST_SEARCH ("^d|^(b|c)(a)", "caf", 0, 3); + + TEST_SEARCH ("^d|(^b|^c)(a)", "df", 0, 2); + TEST_SEARCH ("^d|(^b|^c)(a)", "baf", 0, 3); + TEST_SEARCH ("^d|(^b|^c)(a)", "caf", 0, 3); + + TEST_SEARCH ("d$|(b|c)(a$)", "fd", 0, 2); + TEST_SEARCH ("d$|(b|c)(a$)", "fba", 0, 3); + TEST_SEARCH ("d$|(b|c)(a$)", "fca", 0, 3); + + TEST_SEARCH ("d$|(b|c)(a)$", "fd", 0, 2); + TEST_SEARCH ("d$|(b|c)(a)$", "fba", 0, 3); + TEST_SEARCH ("d$|(b|c)(a)$", "fca", 0, 3); + + TEST_SEARCH ("d$|(b|c)(a$)", "fd", 0, 2); + TEST_SEARCH ("d$|(b|c)(a$)", "fba", 0, 3); + TEST_SEARCH ("d$|(b|c)(a$)", "fca", 0, 3); + + TEST_SEARCH ("^d|^(a)(b|c)", "df", 0, 2); + TEST_SEARCH ("^d|^(a)(b|c)", "abf", 0, 3); + TEST_SEARCH ("^d|^(a)(b|c)", "acf", 0, 3); + + TEST_SEARCH ("^d|(^a)(b|c)", "df", 0, 2); + TEST_SEARCH ("^d|(^a)(b|c)", "abf", 0, 3); + TEST_SEARCH ("^d|(^a)(b|c)", "acf", 0, 3); + + TEST_SEARCH ("d$|(a)(b$|c$)", "fd", 0, 2); + TEST_SEARCH ("d$|(a)(b$|c$)", "fab", 0, 3); + TEST_SEARCH ("d$|(a)(b$|c$)", "fac", 0, 3); + + TEST_SEARCH ("d$|(a)(b|c)$", "fd", 0, 2); + TEST_SEARCH ("d$|(a)(b|c)$", "fab", 0, 3); + TEST_SEARCH ("d$|(a)(b|c)$", "fac", 0, 3); + + TEST_SEARCH ("((^a|^b)|^c)|^d", "ae", 0, 2); + TEST_SEARCH ("((^a|^b)|^c)|^d", "be", 0, 2); + TEST_SEARCH ("((^a|^b)|^c)|^d", "ce", 0, 2); + TEST_SEARCH ("((^a|^b)|^c)|^d", "de", 0, 2); + + TEST_SEARCH ("((a|b)|c)|d$", "ed", 0, 2); + TEST_SEARCH ("((a|b)|c)|d$", "ea", 0, 2); + TEST_SEARCH ("((a|b)|c)|d$", "eb", 0, 2); + TEST_SEARCH ("((a|b)|c)|d$", "ec", 0, 2); + + TEST_SEARCH ("^d|(c|(a|b))", "de", 0, 2); + + TEST_SEARCH ("d$|(c$|(a$|b$))", "ed", 0, 2); + TEST_SEARCH ("d$|(c$|(a$|b$))", "ec", 0, 2); + TEST_SEARCH ("d$|(c$|(a$|b$))", "ea", 0, 2); + TEST_SEARCH ("d$|(c$|(a$|b$))", "eb", 0, 2); + + TEST_SEARCH ("d$|(c$|(a|b)$)", "ed", 0, 2); + TEST_SEARCH ("d$|(c$|(a|b)$)", "ec", 0, 2); + TEST_SEARCH ("d$|(c$|(a|b)$)", "ea", 0, 2); + TEST_SEARCH ("d$|(c$|(a|b)$)", "eb", 0, 2); + + TEST_SEARCH ("d$|(c$|(a|b))$", "ed", 0, 2); + TEST_SEARCH ("d$|(c$|(a|b))$", "ec", 0, 2); + TEST_SEARCH ("d$|(c$|(a|b))$", "ea", 0, 2); + TEST_SEARCH ("d$|(c$|(a|b))$", "eb", 0, 2); + + test_match ("a|^b", "b"); + test_match ("a|b$", "b"); + test_match ("^b|a", "b"); + test_match ("b$|a", "b"); + test_match ("(^a)", "a"); + test_match ("(a$)", "a"); + TEST_SEARCH ("c|^ab", "aba", 0, 3); + TEST_SEARCH ("c|ba$", "aba", 0, 3); + TEST_SEARCH ("^ab|c", "aba", 0, 3); + TEST_SEARCH ("ba$|c", "aba", 0, 3); + TEST_SEARCH ("(^a)", "ab", 0, 2); + TEST_SEARCH ("(a$)", "ba", 0, 2); + + TEST_SEARCH ("(^a$)", "a", 0, 1); + TEST_SEARCH ("(^a)", "ab", 0, 2); + TEST_SEARCH ("(b$)", "ab", 0, 2); + + /* Backtracking. */ + /* Per POSIX D11.1 p. 108, leftmost longest match. */ + test_match ("(wee|week)(knights|night)", "weeknights"); + + test_match ("(fooq|foo)qbar", "fooqbar"); + test_match ("(fooq|foo)(qbarx|bar)", "fooqbarx"); + + /* Take first alternative that does the longest match. */ + test_all_registers ("(fooq|(foo)|(fo))((qbarx)|(oqbarx)|bar)", "fooqbarx", + "", 0, 8, 0, 3, 0, 3, -1, -1, 3, 8, 3, 8, -1, -1, -1, -1, -1, -1, + -1, -1); + + test_match ("(fooq|foo)*qbar", "fooqbar"); + test_match ("(fooq|foo)*(qbar)", "fooqbar"); + test_match ("(fooq|foo)*(qbar)*", "fooqbar"); + + test_match ("(fooq|fo|o)*qbar", "fooqbar"); + test_match ("(fooq|fo|o)*(qbar)", "fooqbar"); + test_match ("(fooq|fo|o)*(qbar)*", "fooqbar"); + + test_match ("(fooq|fo|o)*(qbar|q)*", "fooqbar"); + test_match ("(fooq|foo)*(qbarx|bar)", "fooqbarx"); + test_match ("(fooq|foo)*(qbarx|bar)*", "fooqbarx"); + + test_match ("(fooq|fo|o)+(qbar|q)+", "fooqbar"); + test_match ("(fooq|foo)+(qbarx|bar)", "fooqbarx"); + test_match ("(fooq|foo)+(qbarx|bar)+", "fooqbarx"); + + /* Per Mike Haertel. */ + test_match ("(foo|foobarfoo)(bar)*", "foobarfoo"); + + /* Combination. */ + test_match ("[ab]?c", "ac"); + test_match ("[ab]*c", "ac"); + test_match ("[ab]+c", "ac"); + test_match ("(a|b)?c", "ac"); + test_match ("(a|b)*c", "ac"); + test_match ("(a|b)+c", "ac"); + test_match ("(a*c)?b", "b"); + test_match ("(a*c)+b", "aacb"); + /* Registers. */ + /* Per David A. Willcox. */ + test_match ("a((b)|(c))d", "acd"); + test_all_registers ("a((b)|(c))d", "acd", "", 0, 3, 1, 2, -1, -1, 1, 2, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + + /* Extended regular expressions, continued; these don't match their strings. */ + test_should_match = false; + +#if 0 + /* Invalid use of special characters. */ + /* These are not invalid anymore, since POSIX says the behavior is + undefined, and we prefer context-independent to context-invalid. */ + invalid_pattern (REG_BADRPT, "*"); + invalid_pattern (REG_BADRPT, "a|*"); + invalid_pattern (REG_BADRPT, "(*)"); + invalid_pattern (REG_BADRPT, "^*"); + invalid_pattern (REG_BADRPT, "+"); + invalid_pattern (REG_BADRPT, "a|+"); + invalid_pattern (REG_BADRPT, "(+)"); + invalid_pattern (REG_BADRPT, "^+"); + + invalid_pattern (REG_BADRPT, "?"); + invalid_pattern (REG_BADRPT, "a|?"); + invalid_pattern (REG_BADRPT, "(?)"); + invalid_pattern (REG_BADRPT, "^?"); + + invalid_pattern (REG_BADPAT, "|"); + invalid_pattern (REG_BADPAT, "a|"); + invalid_pattern (REG_BADPAT, "a||"); + invalid_pattern (REG_BADPAT, "(|a)"); + invalid_pattern (REG_BADPAT, "(a|)"); + + invalid_pattern (REG_BADPAT, PARENS_TO_OPS ("(|)")); + + invalid_pattern (REG_BADRPT, "{1}"); + invalid_pattern (REG_BADRPT, "a|{1}"); + invalid_pattern (REG_BADRPT, "^{1}"); + invalid_pattern (REG_BADRPT, "({1})"); + + invalid_pattern (REG_BADPAT, "|b"); + + invalid_pattern (REG_BADRPT, "^{0,}*"); + invalid_pattern (REG_BADRPT, "$*"); + invalid_pattern (REG_BADRPT, "${0,}*"); +#endif /* 0 */ + + invalid_pattern (REG_EESCAPE, "\\"); + + test_match ("a?b", "a"); + + + test_match ("a+", ""); + test_match ("a+b", "a"); + test_match ("a?", "b"); + +#if 0 + /* We make empty groups valid now, since they are undefined in POSIX. + (13 Sep 92) */ + /* Subexpressions. */ + invalid_pattern (REG_BADPAT, "()"); + invalid_pattern (REG_BADPAT, "a()"); + invalid_pattern (REG_BADPAT, "()b"); + invalid_pattern (REG_BADPAT, "a()b"); + invalid_pattern (REG_BADPAT, "()*"); + invalid_pattern (REG_BADPAT, "(()*"); +#endif + /* Invalid intervals. */ + test_match ("a{2}*", "aaa"); + test_match ("a{2}?", "aaa"); + test_match ("a{2}+", "aaa"); + test_match ("a{2}{2}", "aaa"); + test_match ("a{1}{1}{2}", "aaa"); + test_match ("a{1}{1}{2}", "a"); + /* Invalid alternation. */ + test_match ("a|b", "c"); + + TEST_SEARCH ("c|^ba", "aba", 0, 3); + TEST_SEARCH ("c|ab$", "aba", 0, 3); + TEST_SEARCH ("^ba|c", "aba", 0, 3); + TEST_SEARCH ("ab$|c", "aba", 0, 3); + /* Invalid anchoring. */ + TEST_SEARCH ("(^a)", "ba", 0, 2); + TEST_SEARCH ("(b$)", "ba", 0, 2); + + printf ("\nFinished POSIX extended tests.\n"); +} + + + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/test/psx-generic.c b/gnu/lib/libregex/test/psx-generic.c new file mode 100644 index 000000000000..340e93875515 --- /dev/null +++ b/gnu/lib/libregex/test/psx-generic.c @@ -0,0 +1,336 @@ +/* psx-generic.c: test POSIX re's independent of us using basic or + extended syntax. */ + +#include "test.h" + + +void +test_posix_generic () +{ + int omit_generic_tests = 0; /* reset in debugger to skip */ + + if (omit_generic_tests) + return; + /* Tests somewhat in the order of P1003.2. */ + + /* Both posix basic and extended; should match. */ + + printf ("\nStarting generic POSIX tests.\n"); + test_grouping (); + test_intervals (); + + test_should_match = true; + /* Ordinary characters. */ + printf ("\nContinuing generic POSIX tests.\n"); + + MATCH_SELF (""); + test_fastmap ("", "", 0, 0); + test_fastmap_search ("", "", "", 0, 0, 2, 0, 0); + TEST_REGISTERS ("", "", 0, 0, -1, -1, -1, -1); + TEST_SEARCH ("", "", 0, 0); + TEST_SEARCH_2 ("", "", "", 0, 1, 0); + + MATCH_SELF ("abc"); + test_fastmap ("abc", "a", 0, 0); + TEST_REGISTERS ("abc", "abc", 0, 3, -1, -1, -1, -1); + TEST_REGISTERS ("abc", "xabcx", 1, 4, -1, -1, -1, -1); + + test_match ("\\a","a"); + test_match ("\\0", "0"); + + TEST_SEARCH ("a", "ab", 0, 2); + TEST_SEARCH ("b", "ab", 0, 2); + TEST_SEARCH ("a", "ab", 1, -2); + TEST_SEARCH_2 ("a", "a", "b", 0, 2, 2); + TEST_SEARCH_2 ("b", "a", "b", 0, 2, 2); + TEST_SEARCH_2 ("a", "a", "b", 1, -2, 2); + + test_match ("\n", "\n"); + test_match ("a\n", "a\n"); + test_match ("\nb", "\nb"); + test_match ("a\nb", "a\nb"); + + TEST_SEARCH ("b", "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 236, -237); + /* Valid use of special characters. */ + test_match ("a*", "aa"); + test_fastmap ("a*", "a", 0, 0); + TEST_REGISTERS ("a*", "aa", 0, 2, -1, -1, -1, -1); + + test_match ("a*b", "aab"); + test_fastmap ("a*b", "ab", 0, 0); + + test_match ("a*ab", "aab"); + TEST_REGISTERS ("a*a", "aa", 0, 2, -1, -1, -1, -1); + TEST_REGISTERS ("a*a", "xaax", 1, 3, -1, -1, -1, -1); + + test_match ("\\{", "{"); + test_match ("\\^", "^"); + test_match ("\\.", "."); + test_match ("\\*", "*"); + test_match ("\\[", "["); + test_match ("\\$", "$"); + test_match ("\\\\", "\\"); + + test_match ("ab*", "a"); + test_match ("ab*", "abb"); + + /* Valid consecutive repetitions. */ + test_match ("a**", "a"); + /* Valid period. */ + test_match (".", "a"); + TEST_REGISTERS (".", "a", 0, 1, -1, -1, -1, -1); + test_match (".", "\004"); + test_match (".", "\n"); + /* Valid bracket expressions. */ + test_match ("[ab]", "a"); + test_match ("[ab]", "b"); + test_fastmap ("[ab]", "ab", 0, 0); + TEST_REGISTERS ("[ab]", "a", 0, 1, -1, -1, -1, -1); + TEST_REGISTERS ("[ab]", "xax", 1, 2, -1, -1, -1, -1); + + test_fastmap ("[^ab]", "ab", 1, 1); + test_match ("[^ab]", "c"); + test_match ("[^a]", "\n"); + + test_match ("[a]*a", "aa"); + + test_match ("[[]", "["); + test_match ("[]]", "]"); + test_match ("[.]", "."); + test_match ("[*]", "*"); + test_match ("[\\]", "\\"); + test_match ("[\\(]", "("); + test_match ("[\\)]", ")"); + test_match ("[^]]", "a"); + test_match ("[a^]", "^"); + test_match ("[a$]", "$"); + test_match ("[]a]", "]"); + test_match ("[a][]]", "a]"); + test_match ("[\n]", "\n"); + test_match ("[^a]", "\n"); + test_match ("[a-]", "a"); + + TEST_REGISTERS ("\\`[ \t\n]*", " karl (Karl Berry)", 0, 1, -1, -1, -1, -1); + TEST_REGISTERS ("[ \t\n]*\\'", " karl (Karl Berry)", 18, 18, -1, -1, -1, -1); + + /* Collating, noncollating, + equivalence classes aren't + implemented yet. */ + + + /* Character classes. */ + test_match ("[:alpha:]", "p"); + test_match ("[[:alpha:]]", "a"); + test_match ("[[:alpha:]]", "z"); + test_match ("[[:alpha:]]", "A"); + test_match ("[[:alpha:]]", "Z"); + test_match ("[[:upper:]]", "A"); + test_match ("[[:upper:]]", "Z"); + test_match ("[[:lower:]]", "a"); + test_match ("[[:lower:]]", "z"); + + test_match ("[[:digit:]]", "0"); + test_match ("[[:digit:]]", "9"); + test_fastmap ("[[:digit:]]", "0123456789", 0, 0); + + test_match ("[[:alnum:]]", "0"); + test_match ("[[:alnum:]]", "9"); + test_match ("[[:alnum:]]", "a"); + test_match ("[[:alnum:]]", "z"); + test_match ("[[:alnum:]]", "A"); + test_match ("[[:alnum:]]", "Z"); + test_match ("[[:xdigit:]]", "0"); + test_match ("[[:xdigit:]]", "9"); + test_match ("[[:xdigit:]]", "A"); + test_match ("[[:xdigit:]]", "F"); + test_match ("[[:xdigit:]]", "a"); + test_match ("[[:xdigit:]]", "f"); + test_match ("[[:space:]]", " "); + test_match ("[[:print:]]", " "); + test_match ("[[:print:]]", "~"); + test_match ("[[:punct:]]", ","); + test_match ("[[:graph:]]", "!"); + test_match ("[[:graph:]]", "~"); + test_match ("[[:cntrl:]]", "\177"); + test_match ("[[:digit:]a]", "a"); + test_match ("[[:digit:]a]", "2"); + test_match ("[a[:digit:]]", "a"); + test_match ("[a[:digit:]]", "2"); + test_match ("[[:]", "["); + test_match ("[:]", ":"); + test_match ("[[:a]", "["); + test_match ("[[:alpha:a]", "["); + /* Valid ranges. */ + test_match ("[a-a]", "a"); + test_fastmap ("[a-a]", "a", 0, 0); + TEST_REGISTERS ("[a-a]", "xax", 1, 2, -1, -1, -1, -1); + + test_match ("[a-z]", "z"); + test_fastmap ("[a-z]", "abcdefghijklmnopqrstuvwxyz", 0, 0); + test_match ("[-a]", "-"); /* First */ + test_match ("[-a]", "a"); + test_match ("[a-]", "-"); /* Last */ + test_match ("[a-]", "a"); + test_match ("[--@]", "@"); /* First and starting point. */ + + test_match ("[%--a]", "%"); /* Ending point. */ + test_match ("[%--a]", "-"); /* Ditto. */ + + test_match ("[a%--]", "%"); /* Both ending point and last. */ + test_match ("[a%--]", "-"); + test_match ("[%--a]", "a"); /* Ending point only. */ + test_match ("[a-c-f]", "e"); /* Piggyback. */ + + test_match ("[)-+--/]", "*"); + test_match ("[)-+--/]", ","); + test_match ("[)-+--/]", "/"); + test_match ("[[:digit:]-]", "-"); + /* Concatenation ????*/ + test_match ("[ab][cd]", "ac"); + test_fastmap ("[ab][cd]", "ab", 0, 0); + TEST_REGISTERS ("[ab][cd]", "ad", 0, 2, -1, -1, -1, -1); + TEST_REGISTERS ("[ab][cd]", "xadx", 1, 3, -1, -1, -1, -1); + + /* Valid expression anchoring. */ + test_match ("^a", "a"); + test_fastmap ("^a", "a", 0, 0); + TEST_REGISTERS ("^a", "ax", 0, 1, -1, -1, -1, -1); + + test_match ("^", ""); + TEST_REGISTERS ("^", "", 0, 0, -1, -1, -1, -1); + test_match ("$", ""); + TEST_REGISTERS ("$", "", 0, 0, -1, -1, -1, -1); + + test_match ("a$", "a"); + test_fastmap ("a$", "a", 0, 0); + TEST_REGISTERS ("a$", "xa", 1, 2, -1, -1, -1, -1); + + test_match ("^ab$", "ab"); + test_fastmap ("^ab$", "a", 0, 0); + TEST_REGISTERS ("^a$", "a", 0, 1, -1, -1, -1, -1); + + test_fastmap ("^$", "", 0, 0); + test_match ("^$", ""); + TEST_REGISTERS ("^$", "", 0, 0, -1, -1, -1, -1); + + TEST_SEARCH (PARENS_TO_OPS ("(^a)"), "ab", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("(a$)"), "ba", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("^(^a)"), "ab", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("(a$)$"), "ba", 0, 2); + + /* Two strings. */ + test_match_2 ("ab", "a", "b"); + TEST_REGISTERS_2 ("ab", "a", "b", 0, 2, -1, -1, -1, -1); + + test_match_2 ("a", "", "a"); + test_match_2 ("a", "a", ""); + test_match_2 ("ab", "a", "b"); + /* (start)pos. */ + TEST_POSITIONED_MATCH ("b", "ab", 1); + /* mstop. */ + TEST_TRUNCATED_MATCH ("a", "ab", 1); + + + /* Both basic and extended, continued; should not match. */ + + test_should_match = false; + /* Ordinary characters. */ + test_match ("abc", "ab"); + + TEST_SEARCH ("c", "ab", 0, 2); + TEST_SEARCH ("c", "ab", 0, 2); + TEST_SEARCH ("c", "ab", 1, -2); + TEST_SEARCH ("c", "ab", 0, 10); + TEST_SEARCH ("c", "ab", 1, -10); + TEST_SEARCH_2 ("c", "a", "b", 0, 2, 2); + TEST_SEARCH_2 ("c", "a", "b", 0, 2, 2); + TEST_SEARCH_2 ("c", "a", "b", 0, 2, 2); + TEST_SEARCH_2 ("c", "a", "b", 1, -2, 2); + TEST_SEARCH_2 ("c", "a", "b", 1, -2, 2); + + TEST_SEARCH ("c", "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 236, -237); + + /* Invalid use of special characters. */ + invalid_pattern (REG_EESCAPE, "\\"); + invalid_pattern (REG_EESCAPE, "a\\"); + invalid_pattern (REG_EESCAPE, "a*\\"); + /* Invalid period. */ + test_match (".", ""); + /* Invalid bracket expressions. */ + test_match ("[ab]", "c"); + test_match ("[^b]", "b"); + test_match ("[^]]", "]"); + + invalid_pattern (REG_EBRACK, "["); + invalid_pattern (REG_EBRACK, "[^"); + invalid_pattern (REG_EBRACK, "[a"); + invalid_pattern (REG_EBRACK, "[]"); + invalid_pattern (REG_EBRACK, "[]a"); + invalid_pattern (REG_EBRACK, "a[]a"); + + + test_match ("[:alpha:]", "q"); /* Character classes. */ + test_match ("[[:alpha:]]", "2"); + test_match ("[[:upper:]]", "a"); + test_match ("[[:lower:]]", "A"); + test_match ("[[:digit:]]", "a"); + test_match ("[[:alnum:]]", ":"); + test_match ("[[:xdigit:]]", "g"); + test_match ("[[:space:]]", "a"); + test_match ("[[:print:]]", "\177"); + test_match ("[[:punct:]]", "a"); + test_match ("[[:graph:]]", " "); + test_match ("[[:cntrl:]]", "a"); + invalid_pattern (REG_EBRACK, "[[:"); + invalid_pattern (REG_EBRACK, "[[:alpha:"); + invalid_pattern (REG_EBRACK, "[[:alpha:]"); + invalid_pattern (REG_ECTYPE, "[[::]]"); + invalid_pattern (REG_ECTYPE, "[[:a:]]"); + invalid_pattern (REG_ECTYPE, "[[:alpo:]]"); + invalid_pattern (REG_ECTYPE, "[[:a:]"); + + test_match ("[a-z]", "2"); /* Invalid ranges. */ + test_match ("[^-a]", "-"); + test_match ("[^a-]", "-"); + test_match ("[)-+--/]", "."); + invalid_pattern (REG_ERANGE, "[z-a]"); /* Empty */ + invalid_pattern (REG_ERANGE, "[a--]"); /* Empty */ + invalid_pattern (REG_ERANGE, "[[:digit:]-9]"); + invalid_pattern (REG_ERANGE, "[a-[:alpha:]]"); + invalid_pattern (REG_ERANGE, "[a-"); + invalid_pattern (REG_EBRACK, "[a-z"); + + test_match ("[ab][cd]", "ae"); /* Concatenation. */ + test_match ("b*c", "b"); /* Star. */ + + /* Invalid anchoring. */ + test_match ("^", "a"); + test_match ("^a", "ba"); + test_match ("$", "b"); + test_match ("a$", "ab"); + test_match ("^$", "a"); + test_match ("^ab$", "a"); + + TEST_SEARCH ("^a", "b\na", 0, 3); + TEST_SEARCH ("b$", "b\na", 0, 3); + + test_match_2 ("^a", "\n", "a"); + test_match_2 ("a$", "a", "\n"); + + TEST_SEARCH (PARENS_TO_OPS ("(^a)"), "ba", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("(a$)"), "ab", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("^(^a)"), "ba", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("(a$)$"), "ab", 0, 2); + + printf ("\nFinished generic POSIX tests.\n"); +} + + + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/test/psx-group.c b/gnu/lib/libregex/test/psx-group.c new file mode 100644 index 000000000000..08ae8a28d37a --- /dev/null +++ b/gnu/lib/libregex/test/psx-group.c @@ -0,0 +1,440 @@ +/* psx-group.c: test POSIX grouping, both basic and extended. */ + +#include "test.h" + + +void +test_grouping () +{ + printf ("\nStarting POSIX grouping tests.\n"); + + test_should_match = true; + + test_fastmap (PARENS_TO_OPS ("(a)"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a)"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)"), "a", 0, 1, 0, 1, -1, -1); + TEST_REGISTERS (PARENS_TO_OPS ("(a)"), "xax", 1, 2, 1, 2, -1, -1); + + test_match (PARENS_TO_OPS ("((a))"), "a"); + test_fastmap (PARENS_TO_OPS ("((a))"), "a", 0, 0); + TEST_REGISTERS (PARENS_TO_OPS ("((a))"), "a", 0, 1, 0, 1, 0, 1); + TEST_REGISTERS (PARENS_TO_OPS ("((a))"), "xax", 1, 2, 1, 2, 1, 2); + + test_fastmap (PARENS_TO_OPS ("(a)(b)"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a)(b)"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)(b)"), "ab", 0, 2, 0, 1, 1, 2); + + TEST_REGISTERS (PARENS_TO_OPS ("(a)(b)"), "xabx", 1, 3, 1, 2, 2, 3); + + test_all_registers (PARENS_TO_OPS ("((a)(b))"), "ab", "", 0, 2, 0, 2, 0, 1, + 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + + /* Test that we simply ignore groups past the 255th. */ + test_match (PARENS_TO_OPS ("((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((a))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"), "a"); + + + /* Per POSIX D11.1, p. 125. */ + + test_fastmap (PARENS_TO_OPS ("(a)*"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*"), "", 0, 0, -1, -1, -1, -1); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*"), "aa", 0, 2, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a*)"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)"), "", 0, 0, 0, 0, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a*)"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)"), "a", 0, 1, 0, 1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)b"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(a*)b"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)b"), "b", 0, 1, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(a*)b"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)b"), "ab", 0, 2, 0, 1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a*)b)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a*)b)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "", 0, 0, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("((a*)b)*"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "ab", 0, 2, 0, 2, 0, 1); + + test_match (PARENS_TO_OPS ("((a*)b)*"), "abb"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "abb", 0, 3, 2, 3, 2, 2); + + test_match (PARENS_TO_OPS ("((a*)b)*"), "aabab"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "aabab", 0, 5, 3, 5, 3, 4); + + test_match (PARENS_TO_OPS ("((a*)b)*"), "abbab"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "abbab", 0, 5, 3, 5, 3, 4); + + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "xabbabx", 0, 0, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("((a*)b)*"), "abaabaaaab"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "abaabaaab", 0, 9, 5, 9, 5, 8); + + test_fastmap (PARENS_TO_OPS ("(ab)*"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(ab)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(ab)*"), "", 0, 0, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(ab)*"), "abab"); + TEST_REGISTERS (PARENS_TO_OPS ("(ab)*"), "abab", 0, 4, 2, 4, -1, -1); + + /* We match the empty string here. */ + TEST_REGISTERS (PARENS_TO_OPS ("(ab)*"), "xababx", 0, 0, -1, -1, -1, -1); + + /* Per David A. Willcox. */ + TEST_REGISTERS (PARENS_TO_OPS ("a(b*)c"), "ac", 0, 2, 1, 1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a)*b"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(a)*b"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*b"), "b", 0, 1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(a)*b"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*b"), "ab", 0, 2, 0, 1, -1, -1); + + test_match_2 (PARENS_TO_OPS ("(a)*b"), "a", "ab"); + TEST_REGISTERS_2 (PARENS_TO_OPS ("(a)*b"), "a", "ab", 0, 3, 1, 2, -1, -1); + + test_match (PARENS_TO_OPS ("(a)*b"), "aab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*b"), "aab", 0, 3, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a)*a"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a)*a"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*a"), "a", 0, 1, -1, -1, -1, -1); + + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*"), "", 0, 0, 0, 0, 0, 0); + + test_match (PARENS_TO_OPS ("((a*))*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("((a*))*"), "", 0, 0, 0, 0, 0, 0); + test_match (PARENS_TO_OPS ("((a*))*"), "aa"); + + test_fastmap (PARENS_TO_OPS ("(a*)*b"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(a*)*b"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "b", 0, 1, 0, 0, -1, -1); + + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "xbx", 1, 2, 1, 1, -1, -1); + + test_match (PARENS_TO_OPS ("(a*)*b"), "ab"); /* Per rms. */ + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "ab", 0, 2, 0, 1, -1, -1); + + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "xabx", 1, 3, 1, 2, -1, -1); + + /* Test register restores. */ + test_match (PARENS_TO_OPS ("(a*)*b"), "aab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "aab", 0, 3, 0, 2, -1, -1); + + TEST_REGISTERS_2 (PARENS_TO_OPS ("(a*)*b"), "a", "ab", 0, 3, 0, 2, -1, -1); + + /* We are matching the empty string, with backtracking. */ + test_fastmap (PARENS_TO_OPS ("(a*)a"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a*)a"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)a"), "a", 0, 1, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(a*)a"), "aa"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)a"), "aa", 0, 2, 0, 1, -1, -1); + + /* We are matching the empty string, with backtracking. */ +/*fails test_match (PARENS_TO_OPS ("(a*)*a"), "a"); */ + test_match (PARENS_TO_OPS ("(a*)*a"), "aa"); + /* Match the empty string. */ + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "a", 0, 1, 0, 0, -1, -1); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "xax", 1, 2, 1, 1, -1, -1); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "aa", 0, 2, 0, 1, -1, -1); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "xaax", 1, 3, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a)*ab"), "a", 0 , 0); + test_match (PARENS_TO_OPS ("(a)*ab"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*ab"), "ab", 0, 2, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(a)*ab"), "aab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a)*ab"), "aab", 0, 3, 0, 1, -1, -1); + + TEST_REGISTERS (PARENS_TO_OPS("(a)*ab"), "xaabx", 1, 4, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)ab"), "a", 0 , 0); + test_match (PARENS_TO_OPS ("(a*)ab"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)ab"), "ab", 0, 2, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(a*)ab"), "aab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)ab"), "aab", 0, 3, 0, 1, -1, -1); + + TEST_REGISTERS (PARENS_TO_OPS ("(a*)ab"), "xaabx", 1, 4, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)*ab"), "a", 0 , 0); + test_match (PARENS_TO_OPS ("(a*)*ab"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*ab"), "ab", 0, 2, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(a*)*ab"), "aab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*ab"), "aab", 0, 3, 0, 1, -1, -1); + + TEST_REGISTERS (PARENS_TO_OPS("(a*)*ab"), "xaabx", 1, 4, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)*b*c"), "abc", 0, 0); + test_match (PARENS_TO_OPS ("(a*)*b*c"), "c"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b*c"), "c", 0, 1, 0, 0, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a)*(ab)*"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a)*(ab)*"), "ab"); + /* Register 1 doesn't match at all (vs. matching the empty string) + because of backtracking, hence -1's. */ + TEST_REGISTERS (PARENS_TO_OPS ("(a)*(ab)*"), "ab", 0, 2, -1, -1, 0, 2); + + test_match (PARENS_TO_OPS ("(a*)*(ab)*"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*(ab)*"), "ab", 0, 2, 0, 0, 0, 2); + + test_fastmap (PARENS_TO_OPS ("(a*b)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(a*b)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*"), "", 0, 0, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b)*"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*"), "b", 0, 1, 0, 1, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b)*"), "baab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*"), "baab", 0, 4, 1, 4, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*b*)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(a*b*)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "", 0, 0, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)*"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "a", 0, 1, 0, 1, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)*"), "ba"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "ba", 0, 2, 1, 2, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)*"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "ab", 0, 2, 0, 2, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)*"), "aa"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "aa", 0, 2, 0, 2, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)*"), "bb"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "bb", 0, 2, 0, 2, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)*"), "aba"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "aba", 0, 3, 2, 3, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b*)b"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)b"), "b", 0, 1, 0, 0, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a*)*(b*)*)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a*)*(b*)*)*"), ""); + test_all_registers (PARENS_TO_OPS ("((a*)*(b*)*)*"), "", "", 0, 0, 0, 0, + 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("((a*)*(b*)*)*"), "aba"); + /* Perhaps register 3 should be 3/3 here? Not sure if standard + specifies this. xx*/ + test_all_registers (PARENS_TO_OPS ("((a*)*(b*)*)*"), "aba", "", 0, 3, 2, 3, + 2, 3, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a*)(b*))*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a*)(b*))*"), ""); + + test_all_registers (PARENS_TO_OPS ("((a*)(b*))*"), "", "", 0, 0, 0, 0, + 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), ""); + + test_match (PARENS_TO_OPS ("((a*)(b*))*"), "aba"); + test_all_registers (PARENS_TO_OPS ("((a*)(b*))*"), "aba", "", 0, 3, 2, 3, + 2, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a)*(b)*)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a)*(b)*)*"), ""); + test_all_registers (PARENS_TO_OPS ("((a)*(b)*)*"), "", "", 0, 0, 0, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("((a)*(b)*)*"), "aba"); + + test_all_registers (PARENS_TO_OPS ("((a)*(b)*)*"), "aba", "", 0, 3, 2, 3, + 2, 3, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(c(a)*(b)*)*"), "c", 0, 0); + test_match (PARENS_TO_OPS ("(c(a)*(b)*)*"), ""); + test_all_registers (PARENS_TO_OPS ("(c(a)*(b)*)*"), "", "", 0, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(c(a)*(b)*)*"), "c"); + test_all_registers (PARENS_TO_OPS ("(c(a)*(b)*)*"), "c", "", 0, 1, 0, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("c((a)*(b)*)*"), "c", 0, 0); + test_match (PARENS_TO_OPS ("c((a)*(b)*)*"), "c"); + test_all_registers (PARENS_TO_OPS ("c((a)*(b)*)*"), "c", "", 0, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(((a)*(b)*)*)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(((a)*(b)*)*)*"), ""); + test_all_registers (PARENS_TO_OPS ("(((a)*(b)*)*)*"), "", "", 0, 0, 0, 0, + 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), ""); + test_fastmap (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), "c", 0, 0); + + test_all_registers (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), "", "", 0, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a)*b)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a)*b)*"), ""); + + test_match (PARENS_TO_OPS ("((a)*b)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "", 0, 0, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("((a)*b)*"), "abb"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "abb", 0, 3, 2, 3, 0, 1); /*zz*/ + + test_match (PARENS_TO_OPS ("((a)*b)*"), "abbab"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "abbab", 0, 5, 3, 5, 3, 4); + + /* We match the empty string here. */ + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "xabbabx", 0, 0, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*)*"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(a*)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*"), "", 0, 0, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(a*)*"), "aa"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*)*"), "aa", 0, 2, 0, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a*)*)*"), "a", 0, 0); + test_match (PARENS_TO_OPS ("((a*)*)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)*)*"), "", 0, 0, 0, 0, 0, 0); + + test_match (PARENS_TO_OPS ("((a*)*)*"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)*)*"), "a", 0, 1, 0, 1, 0, 1); + + test_fastmap (PARENS_TO_OPS ("(ab*)*"), "a", 0, 0); + test_match (PARENS_TO_OPS ("(ab*)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*"), "", 0, 0, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(ab*)*"), "aa"); + TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*"), "aa", 0, 2, 1, 2, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(ab*)*c"), "ac", 0, 0); + test_match (PARENS_TO_OPS ("(ab*)*c"), "c"); + TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*c"), "c", 0, 1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(ab*)*c"), "abbac"); + TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*c"), "abbac", 0, 5, 3, 4, -1, -1); + + test_match (PARENS_TO_OPS ("(ab*)*c"), "abac"); + TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*c"), "abac", 0, 4, 2, 3, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*b)*c"), "abc", 0, 0); + test_match (PARENS_TO_OPS ("(a*b)*c"), "c"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "c", 0, 1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b)*c"), "bbc"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "bbc", 0, 3, 1, 2, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b)*c"), "aababc"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "aababc", 0, 6, 3, 5, -1, -1); + + test_match (PARENS_TO_OPS ("(a*b)*c"), "aabaabc"); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "aabaabc", 0, 7, 3, 6, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a*)b*)"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a*)b*)"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)"), "", 0, 0, 0, 0, 0, 0); + + test_match (PARENS_TO_OPS ("((a*)b*)"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)"), "a", 0, 1, 0, 1, 0, 1); + + test_match (PARENS_TO_OPS ("((a*)b*)"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)"), "b", 0, 1, 0, 1, 0, 0); + + test_fastmap (PARENS_TO_OPS ("((a)*b*)"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("((a)*b*)"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "", 0, 0, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("((a)*b*)"), "a"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "a", 0, 1, 0, 1, 0, 1); + + test_match (PARENS_TO_OPS ("((a)*b*)"), "b"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "b", 0, 1, 0, 1, -1, -1); + + test_match (PARENS_TO_OPS ("((a)*b*)"), "ab"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "ab", 0, 2, 0, 2, 0, 1); + + test_fastmap (PARENS_TO_OPS ("((a*)b*)c"), "abc", 0, 0); + test_match (PARENS_TO_OPS ("((a*)b*)c"), "c"); + TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)c"), "c", 0, 1, 0, 0, 0, 0); + + test_fastmap (PARENS_TO_OPS ("((a)*b*)c"), "abc", 0, 0); + test_match (PARENS_TO_OPS ("((a)*b*)c"), "c"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)c"), "c", 0, 1, 0, 0, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(a*b*)*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(a*b*)*"), ""); + TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "", 0, 0, 0, 0, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(((a*))((b*)))*"), "ab", 0, 0); + test_match (PARENS_TO_OPS ("(((a*))((b*)))*"), ""); + test_all_registers (PARENS_TO_OPS ("(((a*))((b*)))*"), "", "", 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("(c*((a*))d*((b*))e*)*"), "abcde", 0, 0); + test_match (PARENS_TO_OPS ("(c*((a*))d*((b*))e*)*"), ""); + test_all_registers (PARENS_TO_OPS ("(c*((a*))d*((b*))e*)*"), "", "", 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1); + + test_fastmap (PARENS_TO_OPS ("((a)*b)*c"), "abc", 0, 0); + test_match (PARENS_TO_OPS ("((a)*b)*c"), "c"); + TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*c"), "c", 0, 1, -1, -1, -1, -1); + + test_match (PARENS_TO_OPS ("(ab)*"), ""); + test_match (PARENS_TO_OPS ("((ab)*)"), ""); + test_match (PARENS_TO_OPS ("(((ab)*))"), ""); + test_match (PARENS_TO_OPS ("((((ab)*)))"), ""); + test_match (PARENS_TO_OPS ("(((((ab)*))))"), ""); + test_match (PARENS_TO_OPS ("((((((ab)*)))))"), ""); + test_match (PARENS_TO_OPS ("(((((((ab)*))))))"), ""); + test_match (PARENS_TO_OPS ("((((((((ab)*)))))))"), ""); + test_match (PARENS_TO_OPS ("(((((((((ab)*))))))))"), ""); + + + test_fastmap (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "a", 0, 0); + test_match (PARENS_TO_OPS ("((((((((((ab)*)))))))))"), ""); + test_match (PARENS_TO_OPS ("(((((((((ab)*))))))))"), ""); + test_all_registers (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "", NULL, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1); + + test_match (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "abab"); + test_all_registers (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "abab", NULL, + 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 2, 4); + + + test_should_match = false; + + invalid_pattern (REG_EPAREN, PARENS_TO_OPS ("(a")); + + test_match (PARENS_TO_OPS ("(a)"), ""); + test_match (PARENS_TO_OPS ("((a))"), "b"); + test_match (PARENS_TO_OPS ("(a)(b)"), "ac"); + test_match (PARENS_TO_OPS ("(ab)*"), "acab"); + test_match (PARENS_TO_OPS ("(a*)*b"), "c"); + test_match (PARENS_TO_OPS ("(a*b)*"), "baa"); + test_match (PARENS_TO_OPS ("(a*b)*"), "baabc"); + test_match (PARENS_TO_OPS ("(a*b*)*"), "c"); + test_match (PARENS_TO_OPS ("((a*)*(b*)*)*"), "c"); + test_match (PARENS_TO_OPS ("(a*)*"), "ab"); + test_match (PARENS_TO_OPS ("((a*)*)*"), "ab"); + test_match (PARENS_TO_OPS ("((a*)*)*"), "b"); + test_match (PARENS_TO_OPS ("(ab*)*"), "abc"); + test_match (PARENS_TO_OPS ("(ab*)*c"), "abbad"); + test_match (PARENS_TO_OPS ("(a*c)*b"), "aacaacd"); + test_match (PARENS_TO_OPS ("(a*)"), "b"); + test_match (PARENS_TO_OPS ("((a*)b*)"), "c"); + + /* Expression anchoring. */ + TEST_SEARCH (PARENS_TO_OPS ("(^b)"), "ab", 0, 2); + TEST_SEARCH (PARENS_TO_OPS ("(a$)"), "ab", 0, 2); + + printf ("\nFinished POSIX grouping tests.\n"); +} diff --git a/gnu/lib/libregex/test/psx-interf.c b/gnu/lib/libregex/test/psx-interf.c new file mode 100644 index 000000000000..8312d5e7d74a --- /dev/null +++ b/gnu/lib/libregex/test/psx-interf.c @@ -0,0 +1,624 @@ +/* psx-interf.c: test POSIX interface. */ + +#include <string.h> +#include <assert.h> + +#include "test.h" + +#define ERROR_CODE_LENGTH 20 +#define TEST_ERRBUF_SIZE 15 + + +void test_compile (); + + +/* ANSWER should be at least ERROR_CODE_LENGTH long. */ + +static char * +get_error_string (error_code, answer) + int error_code; + char answer[]; +{ + switch (error_code) + { + case 0: strcpy (answer, "No error"); break; + case REG_NOMATCH: strcpy (answer, "REG_NOMATCH"); break; + case REG_BADPAT: strcpy (answer, "REG_BADPAT"); break; + case REG_EPAREN: strcpy (answer, "REG_EPAREN"); break; + case REG_ESPACE: strcpy (answer, "REG_ESPACE"); break; + case REG_ECOLLATE: strcpy (answer, "REG_ECOLLATE"); break; + case REG_ECTYPE: strcpy (answer, "REG_ECTYPE"); break; + case REG_EESCAPE: strcpy (answer, "REG_EESCAPE"); break; + case REG_ESUBREG: strcpy (answer, "REG_ESUBREG"); break; + case REG_EBRACK: strcpy (answer, "REG_EBRACK"); break; + case REG_EBRACE: strcpy (answer, "REG_EBRACE"); break; + case REG_BADBR: strcpy (answer, "REG_BADBR"); break; + case REG_ERANGE: strcpy (answer, "REG_ERANGE"); break; + case REG_BADRPT: strcpy (answer, "REG_BADRPT"); break; + case REG_EEND: strcpy (answer, "REG_EEND"); break; + default: strcpy (answer, "Bad error code"); + } + return answer; +} + + +/* I don't think we actually need to initialize all these things. + --karl */ + +void +init_pattern_buffer (pattern_buffer_ptr) + regex_t *pattern_buffer_ptr; +{ + pattern_buffer_ptr->buffer = NULL; + pattern_buffer_ptr->allocated = 0; + pattern_buffer_ptr->used = 0; + pattern_buffer_ptr->fastmap = NULL; + pattern_buffer_ptr->fastmap_accurate = 0; + pattern_buffer_ptr->translate = NULL; + pattern_buffer_ptr->can_be_null = 0; + pattern_buffer_ptr->re_nsub = 0; + pattern_buffer_ptr->no_sub = 0; + pattern_buffer_ptr->not_bol = 0; + pattern_buffer_ptr->not_eol = 0; +} + + +void +test_compile (valid_pattern, error_code_expected, pattern, + pattern_buffer_ptr, cflags) + unsigned valid_pattern; + int error_code_expected; + const char *pattern; + regex_t *pattern_buffer_ptr; + int cflags; +{ + int error_code_returned; + boolean error = false; + char errbuf[TEST_ERRBUF_SIZE]; + + init_pattern_buffer (pattern_buffer_ptr); + error_code_returned = regcomp (pattern_buffer_ptr, pattern, cflags); + + if (valid_pattern && error_code_returned) + { + printf ("\nShould have been a valid pattern but wasn't.\n"); + regerror (error_code_returned, pattern_buffer_ptr, errbuf, + TEST_ERRBUF_SIZE); + printf ("%s", errbuf); + error = true; + } + + if (!valid_pattern && !error_code_returned) + { + printf ("\n\nInvalid pattern compiled as valid:\n"); + error = true; + } + + if (error_code_returned != error_code_expected) + { + char expected_error_string[ERROR_CODE_LENGTH]; + char returned_error_string[ERROR_CODE_LENGTH]; + + get_error_string (error_code_expected, expected_error_string), + get_error_string (error_code_returned, returned_error_string); + + printf (" Expected error code %s but got `%s'.\n", + expected_error_string, returned_error_string); + + error = true; + } + + if (error) + print_pattern_info (pattern, pattern_buffer_ptr); +} + + +static void +test_nsub (sub_count, pattern, cflags) + unsigned sub_count; + char *pattern; + int cflags; + +{ + regex_t pattern_buffer; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); + + if (pattern_buffer.re_nsub != sub_count) + { + printf ("\nShould have counted %d subexpressions but counted %d \ +instead.\n", sub_count, pattern_buffer.re_nsub); + } + + regfree (&pattern_buffer); +} + + +static void +test_regcomp () +{ + regex_t pattern_buffer; + int cflags = 0; + + + printf ("\nStarting regcomp tests.\n"); + + cflags = 0; + test_compile (0, REG_ESUBREG, "\\(a\\)\\2", &pattern_buffer, cflags); + test_compile (0, REG_EBRACE, "a\\{", &pattern_buffer, cflags); + test_compile (0, REG_BADBR, "a\\{-1\\}", &pattern_buffer, cflags); + test_compile (0, REG_EBRACE, "a\\{", &pattern_buffer, cflags); + test_compile (0, REG_EBRACE, "a\\{1", &pattern_buffer, cflags); + + cflags = REG_EXTENDED; + test_compile (0, REG_ECTYPE, "[[:alpo:]]", &pattern_buffer, cflags); + test_compile (0, REG_EESCAPE, "\\", &pattern_buffer, cflags); + test_compile (0, REG_EBRACK, "[a", &pattern_buffer, cflags); + test_compile (0, REG_EPAREN, "(", &pattern_buffer, cflags); + test_compile (0, REG_ERANGE, "[z-a]", &pattern_buffer, cflags); + + test_nsub (1, "(a)", cflags); + test_nsub (2, "((a))", cflags); + test_nsub (2, "(a)(b)", cflags); + + cflags = REG_EXTENDED | REG_NOSUB; + test_nsub (1, "(a)", cflags); + + regfree (&pattern_buffer); + + printf ("\nFinished regcomp tests.\n"); +} + + +static void +fill_pmatch (pmatch, start0, end0, start1, end1, start2, end2) + regmatch_t pmatch[]; + regoff_t start0, end0, start1, end1, start2, end2; +{ + pmatch[0].rm_so = start0; + pmatch[0].rm_eo = end0; + pmatch[1].rm_so = start1; + pmatch[1].rm_eo = end1; + pmatch[2].rm_so = start2; + pmatch[2].rm_eo = end2; +} + + +static void +test_pmatch (pattern, string, nmatch, pmatch, correct_pmatch, cflags) + char *pattern; + char *string; + unsigned nmatch; + regmatch_t pmatch[]; + regmatch_t correct_pmatch[]; + int cflags; +{ + regex_t pattern_buffer; + unsigned this_match; + int error_code_returned; + boolean found_nonmatch = false; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); + error_code_returned = regexec (&pattern_buffer, string, nmatch, pmatch, 0); + + if (error_code_returned == REG_NOMATCH) + printf ("Matching failed in test_pmatch.\n"); + else + { + for (this_match = 0; this_match < nmatch; this_match++) + { + if (pmatch[this_match].rm_so != correct_pmatch[this_match].rm_so) + { + if (found_nonmatch == false) + printf ("\n"); + + printf ("Pmatch start %d wrong: was %d when should have \ +been %d.\n", this_match, pmatch[this_match].rm_so, + correct_pmatch[this_match].rm_so); + found_nonmatch = true; + } + if (pmatch[this_match].rm_eo != correct_pmatch[this_match].rm_eo) + { + if (found_nonmatch == false) + printf ("\n"); + + printf ("Pmatch end %d wrong: was %d when should have been \ +%d.\n", this_match, pmatch[this_match].rm_eo, + correct_pmatch[this_match].rm_eo); + found_nonmatch = true; + } + } + + if (found_nonmatch) + { + printf (" The number of pmatches requested was: %d.\n", nmatch); + printf (" The string to match was: `%s'.\n", string); + print_pattern_info (pattern, &pattern_buffer); + } + } /* error_code_returned == REG_NOMATCH */ + + regfree (&pattern_buffer); +} + + +static void +test_eflags (must_match_bol, must_match_eol, pattern, string, cflags, eflags) + boolean must_match_bol; + boolean must_match_eol; + char *pattern; + char *string; + int cflags; + int eflags; +{ + regex_t pattern_buffer; + int error_code_returned; + boolean was_error = false; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); + error_code_returned = regexec (&pattern_buffer, string, 0, 0, eflags); + + if (error_code_returned == REG_NOMATCH) + { + /* If wasn't true that both 1) the anchored part of the pattern + had to match this string and 2) this string was a proper + substring... */ + + if (!( (must_match_bol && (eflags & REG_NOTBOL)) + || (must_match_eol && (eflags & REG_NOTEOL)) )) + { + printf ("\nEflags test failed: didn't match when should have.\n"); + was_error = true; + } + } + else /* We got a match. */ + { + /* If wasn't true that either 1) the anchored part of the pattern + didn't have to match this string or 2) this string wasn't a + proper substring... */ + + if ((must_match_bol == (eflags & REG_NOTBOL)) + || (must_match_eol == (eflags & REG_NOTEOL))) + { + printf ("\nEflags test failed: matched when shouldn't have.\n"); + was_error = true; + } + } + + if (was_error) + { + printf (" The string to match was: `%s'.\n", string); + print_pattern_info (pattern, &pattern_buffer); + + if (eflags & REG_NOTBOL) + printf (" The eflag REG_BOL was set.\n"); + if (eflags & REG_NOTEOL) + printf (" The eflag REG_EOL was set.\n"); + } + + regfree (&pattern_buffer); +} + + +static void +test_ignore_case (should_match, pattern, string, cflags) + boolean should_match; + char *pattern; + char *string; + int cflags; +{ + regex_t pattern_buffer; + int error_code_returned; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); + error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0); + + if (should_match && error_code_returned == REG_NOMATCH) + { + printf ("\nIgnore-case test failed:\n"); + printf (" The string to match was: `%s'.\n", string); + print_pattern_info (pattern, &pattern_buffer); + + if (cflags & REG_ICASE) + printf (" The cflag REG_ICASE was set.\n"); + } + + regfree (&pattern_buffer); +} + + +static void +test_newline (should_match, pattern, string, cflags) + boolean should_match; + char *pattern; + char *string; + int cflags; +{ + regex_t pattern_buffer; + int error_code_returned; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); + error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0); + + if (should_match && error_code_returned == REG_NOMATCH) + { + printf ("\nNewline test failed:\n"); + printf (" The string to match was: `%s'.\n", string); + print_pattern_info (pattern, &pattern_buffer); + + if (cflags & REG_NEWLINE) + printf (" The cflag REG_NEWLINE was set.\n"); + else + printf (" The cflag REG_NEWLINE wasn't set.\n"); + } + + regfree (&pattern_buffer); +} + + +static void +test_posix_match (should_match, pattern, string, cflags) + boolean should_match; + char *pattern; + char *string; + int cflags; +{ + regex_t pattern_buffer; + int error_code_returned; + boolean was_error = false; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); + error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0); + + if (should_match && error_code_returned == REG_NOMATCH) + { + printf ("\nShould have matched but didn't:\n"); + was_error = true; + } + else if (!should_match && error_code_returned != REG_NOMATCH) + { + printf ("\nShould not have matched but did:\n"); + was_error = true; + } + + if (was_error) + { + printf (" The string to match was: `%s'.\n", string); + print_pattern_info (pattern, &pattern_buffer); + } + + regfree (&pattern_buffer); +} + + +static void +test_regexec () +{ + regmatch_t pmatch[3]; + regmatch_t correct_pmatch[3]; + int cflags = 0; + int eflags = 0; + + printf ("\nStarting regexec tests.\n"); + + cflags = REG_NOSUB; /* shouldn't look at any of pmatch. */ + test_pmatch ("a", "a", 0, pmatch, correct_pmatch, cflags); + + /* Ask for less `pmatch'es than there are pattern subexpressions. + (Shouldn't look at pmatch[2]. */ + cflags = REG_EXTENDED; + fill_pmatch (correct_pmatch, 0, 1, 0, 1, 100, 101); + test_pmatch ("((a))", "a", 2, pmatch, correct_pmatch, cflags); + + /* Ask for same number of `pmatch'es as there are pattern subexpressions. */ + cflags = REG_EXTENDED; + fill_pmatch(correct_pmatch, 0, 1, 0, 1, -1, -1); + test_pmatch ("(a)", "a", 2, pmatch, correct_pmatch, cflags); + + /* Ask for more `pmatch'es than there are pattern subexpressions. */ + cflags = REG_EXTENDED; + fill_pmatch (correct_pmatch, 0, 1, -1, -1, -1, -1); + test_pmatch ("a", "a", 2, pmatch, correct_pmatch, cflags); + + eflags = REG_NOTBOL; + test_eflags (true, false, "^a", "a", cflags, eflags); + test_eflags (true, false, "(^a)", "a", cflags, eflags); + test_eflags (true, false, "a|^b", "b", cflags, eflags); + test_eflags (true, false, "^b|a", "b", cflags, eflags); + + eflags = REG_NOTEOL; + test_eflags (false, true, "a$", "a", cflags, eflags); + test_eflags (false, true, "(a$)", "a", cflags, eflags); + test_eflags (false, true, "a|b$", "b", cflags, eflags); + test_eflags (false, true, "b$|a", "b", cflags, eflags); + + eflags = REG_NOTBOL | REG_NOTEOL; + test_eflags (true, true, "^a$", "a", cflags, eflags); + test_eflags (true, true, "(^a$)", "a", cflags, eflags); + test_eflags (true, true, "a|(^b$)", "b", cflags, eflags); + test_eflags (true, true, "(^b$)|a", "b", cflags, eflags); + + cflags = REG_ICASE; + test_ignore_case (true, "a", "a", cflags); + test_ignore_case (true, "A", "A", cflags); + test_ignore_case (true, "A", "a", cflags); + test_ignore_case (true, "a", "A", cflags); + + test_ignore_case (true, "@", "@", cflags); + test_ignore_case (true, "\\[", "[", cflags); + test_ignore_case (true, "`", "`", cflags); + test_ignore_case (true, "{", "{", cflags); + + test_ignore_case (true, "[!-`]", "A", cflags); + test_ignore_case (true, "[!-`]", "a", cflags); + + cflags = 0; + test_ignore_case (false, "a", "a", cflags); + test_ignore_case (false, "A", "A", cflags); + test_ignore_case (false, "A", "a", cflags); + test_ignore_case (false, "a", "A", cflags); + + test_ignore_case (true, "@", "@", cflags); + test_ignore_case (true, "\\[", "[", cflags); + test_ignore_case (true, "`", "`", cflags); + test_ignore_case (true, "{", "{", cflags); + + test_ignore_case (true, "[!-`]", "A", cflags); + test_ignore_case (false, "[!-`]", "a", cflags); + + + /* Test newline stuff. */ + cflags = REG_EXTENDED | REG_NEWLINE; + test_newline (true, "\n", "\n", cflags); + test_newline (true, "a\n", "a\n", cflags); + test_newline (true, "\nb", "\nb", cflags); + test_newline (true, "a\nb", "a\nb", cflags); + + test_newline (false, ".", "\n", cflags); + test_newline (false, "[^a]", "\n", cflags); + + test_newline (true, "\n^a", "\na", cflags); + test_newline (true, "\n(^a|b)", "\na", cflags); + test_newline (true, "a$\n", "a\n", cflags); + test_newline (true, "(a$|b)\n", "a\n", cflags); + test_newline (true, "(a$|b|c)\n", "a\n", cflags); + test_newline (true, "((a$|b|c)$)\n", "a\n", cflags); + test_newline (true, "((a$|b|c)$)\n", "b\n", cflags); + test_newline (true, "(a$|b)\n|a\n", "a\n", cflags); + + test_newline (true, "^a", "\na", cflags); + test_newline (true, "a$", "a\n", cflags); + + /* Now test normal behavior. */ + cflags = REG_EXTENDED; + test_newline (true, "\n", "\n", cflags); + test_newline (true, "a\n", "a\n", cflags); + test_newline (true, "\nb", "\nb", cflags); + test_newline (true, "a\nb", "a\nb", cflags); + + test_newline (true, ".", "\n", cflags); + test_newline (true, "[^a]", "\n", cflags); + + test_newline (false, "\n^a", "\na", cflags); + test_newline (false, "a$\n", "a\n", cflags); + + test_newline (false, "^a", "\na", cflags); + test_newline (false, "a$", "a\n", cflags); + + + /* Test that matches whole string only. */ + cflags = 0; + test_posix_match (true, "a", "a", cflags); + + /* Tests that match substrings. */ + test_posix_match (true, "a", "ab", cflags); + test_posix_match (true, "b", "ab", cflags); + + /* Test that doesn't match. */ + test_posix_match (false, "a", "b", cflags); + + printf ("\nFinished regexec tests.\n"); +} + + +static void +test_error_code_message (error_code, expected_error_message) + int error_code; + char *expected_error_message; +{ + char returned_error_message[TEST_ERRBUF_SIZE]; + char error_code_string[ERROR_CODE_LENGTH]; + size_t expected_error_message_length = strlen (expected_error_message) + 1; + size_t returned_error_message_length = regerror (error_code, 0, + returned_error_message, + TEST_ERRBUF_SIZE); + + if (returned_error_message_length != expected_error_message_length) + { + printf ("\n\n Testing returned error codes, with expected error \ +message `%s':\n", expected_error_message); + + printf ("\n\n and returned error message `%s':\n", + returned_error_message); + printf (" should have returned a length of %d but returned %d.\n", + expected_error_message_length, returned_error_message_length); + } + + if (strncmp (expected_error_message, returned_error_message, + TEST_ERRBUF_SIZE - 1) != 0) + { + + get_error_string (error_code, error_code_string), + printf ("\n\n With error code %s (%d), expected error message:\n", + error_code_string, error_code); + + printf (" `%s'\n", expected_error_message); + printf (" but got:\n"); + printf (" `%s'\n", returned_error_message); + } +} + + +static void +test_error_code_allocation (error_code, expected_error_message) + int error_code; + char *expected_error_message; +{ + char *returned_error_message = NULL; + char error_code_string[ERROR_CODE_LENGTH]; + size_t returned_error_message_length = regerror (error_code, 0, + returned_error_message, + (size_t)0); + + returned_error_message = xmalloc (returned_error_message_length + 1); + + regerror (error_code, 0, returned_error_message, + returned_error_message_length); + + if (strcmp (expected_error_message, returned_error_message) != 0) + { + get_error_string (error_code, error_code_string), + + printf ("\n\n Testing error code allocation,\n"); + printf ("with error code %s (%d), expected error message:\n", + error_code_string, error_code); + printf (" `%s'\n", expected_error_message); + printf (" but got:\n"); + printf (" `%s'\n", returned_error_message); + } +} + + +static void +test_regerror () +{ + test_error_code_message (REG_NOMATCH, "No match"); + test_error_code_message (REG_BADPAT, "Invalid regular expression"); + test_error_code_message (REG_ECOLLATE, "Invalid collation character"); + test_error_code_message (REG_ECTYPE, "Invalid character class name"); + test_error_code_message (REG_EESCAPE, "Trailing backslash"); + test_error_code_message (REG_ESUBREG, "Invalid back reference"); + test_error_code_message (REG_EBRACK, "Unmatched [ or [^"); + test_error_code_message (REG_EPAREN, "Unmatched ( or \\("); + test_error_code_message (REG_EBRACE, "Unmatched \\{"); + test_error_code_message (REG_BADBR, "Invalid content of \\{\\}"); + test_error_code_message (REG_ERANGE, "Invalid range end"); + test_error_code_message (REG_ESPACE, "Memory exhausted"); + test_error_code_message (REG_BADRPT, "Invalid preceding regular expression"); + test_error_code_message (REG_EEND, "Premature end of regular expression"); + test_error_code_message (REG_ESIZE, "Regular expression too big"); + test_error_code_allocation (REG_ERPAREN, "Unmatched ) or \\)"); +} + + +void +test_posix_interface () +{ + printf ("\nStarting POSIX interface tests.\n"); + t = posix_interface_test; + + test_regcomp (); + test_regexec (); + test_regerror (); + + printf ("\nFinished POSIX interface tests.\n"); +} diff --git a/gnu/lib/libregex/test/psx-interv.c b/gnu/lib/libregex/test/psx-interv.c new file mode 100644 index 000000000000..6725c38d00b8 --- /dev/null +++ b/gnu/lib/libregex/test/psx-interv.c @@ -0,0 +1,140 @@ +/* psx-interv.c: test POSIX intervals, both basic and extended. */ + +#include "test.h" + +void +test_intervals () +{ + printf ("\nStarting POSIX interval tests.\n"); + + test_should_match = true; + /* Valid intervals. */ + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,2}b)*")), "abaab"); + test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,2}b)*")), "a", 0, 0); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,2}b)*")), + "abaab", 0, 5, 2, 5, -1, -1); + + test_match (BRACES_TO_OPS ("a{0}"), ""); + test_fastmap (BRACES_TO_OPS ("a{0}"), "", 0, 0); + TEST_REGISTERS (BRACES_TO_OPS ("a{0}"), "", 0, 0, -1, -1, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS ("a{0}"), "x", 0, 0, -1, -1, -1, -1); + + test_match (BRACES_TO_OPS ("a{0,}"), ""); + test_match (BRACES_TO_OPS ("a{0,}"), "a"); + test_fastmap (BRACES_TO_OPS ("a{0,}"), "a", 0, 0); + TEST_REGISTERS (BRACES_TO_OPS ("a{0,}"), "a", 0, 1, -1, -1, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS ("a{0,}"), "xax", 0, 0, -1, -1, -1, -1); + + test_match (BRACES_TO_OPS ("a{1}"), "a"); + test_match (BRACES_TO_OPS ("a{1,}"), "a"); + test_match (BRACES_TO_OPS ("a{1,}"), "aa"); + test_match (BRACES_TO_OPS ("a{0,0}"), ""); + test_match (BRACES_TO_OPS ("a{0,1}"), ""); + test_match (BRACES_TO_OPS ("a{0,1}"), "a"); + test_match (BRACES_TO_OPS ("a{1,3}"), "a"); + test_match (BRACES_TO_OPS ("a{1,3}"), "aa"); + test_match (BRACES_TO_OPS ("a{1,3}"), "aaa"); + TEST_REGISTERS (BRACES_TO_OPS ("a{1,3}"), "aaa", 0, 3, -1, -1, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS ("a{1,3}"), "xaaax", 1, 4, -1, -1, -1, -1); + + test_match (BRACES_TO_OPS ("a{0,3}b"), "b"); + test_match (BRACES_TO_OPS ("a{0,3}b"), "aaab"); + test_fastmap (BRACES_TO_OPS ("a{0,3}b"), "ab", 0, 0); + TEST_REGISTERS (BRACES_TO_OPS ("a{0,3}b"), "b", 0, 1, -1, -1, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS ("a{0,3}b"), "xbx", 1, 2, -1, -1, -1, -1); + + test_match (BRACES_TO_OPS ("a{1,3}b"), "ab"); + test_match (BRACES_TO_OPS ("a{1,3}b"), "aaab"); + test_match (BRACES_TO_OPS ("ab{1,3}c"), "abbbc"); + + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "b"); + test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "ab", 0, 0); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "b", 0, 1, -1, -1, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "ab", 0, 2, 0, 1, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "xabx", 1, 3, 1, 2, -1, -1); + + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "ab"); + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "aaab"); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "aaab", 0, 4, 2, 3, -1, -1); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "xaaabx", 1, 5, 3, 4, -1, -1); + + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){0,3}b")), "aaaab"); + test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){0,3}b")), "ab", 0, 0); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){0,3}b")), "aaaab", 0, 5, 4, 4, -1, -1); + + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "b"); + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "aaab"); + test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "ab", 0, 0); + + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,1}ab")), "aaaab"); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,1}ab")), "aaaab", 0, 5, 0, 3, -1, -1); + + test_match (BRACES_TO_OPS (".{0,3}b"), "b"); + test_match (BRACES_TO_OPS (".{0,3}b"), "ab"); + + test_match (BRACES_TO_OPS ("[a]{0,3}b"), "b"); + test_match (BRACES_TO_OPS ("[a]{0,3}b"), "aaab"); + test_fastmap (BRACES_TO_OPS ("[a]{0,3}b"), "ab", 0, 0); + test_match (BRACES_TO_OPS ("[^a]{0,3}b"), "bcdb"); + test_match (BRACES_TO_OPS ("ab{0,3}c"), "abbbc"); + test_match (BRACES_TO_OPS ("[[:digit:]]{0,3}d"), "123d"); + test_fastmap (BRACES_TO_OPS ("[[:digit:]]{0,3}d"), "0123456789d", 0, 0); + + test_match (BRACES_TO_OPS ("\\*{0,3}a"), "***a"); + test_match (BRACES_TO_OPS (".{0,3}b"), "aaab"); + test_match (BRACES_TO_OPS ("a{0,3}a"), "aaa"); + /* Backtracking. */ + test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,})*a")), "a", 0, 0); + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,})*a")), "a"); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,})*a")), "a", 0, 1, -1, -1, -1, -1); + + test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a{2,})*aa")), "aa", 0, 0); + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a{2,})*aa")), "aa"); + TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a{2,})*aa")), "aa", 0, 2, -1, -1, -1, -1); + + test_match (BRACES_TO_OPS ("a{2}*"), ""); + test_match (BRACES_TO_OPS ("a{2}*"), "aa"); + + test_match (BRACES_TO_OPS ("a{1}*"), ""); + test_match (BRACES_TO_OPS ("a{1}*"), "a"); + test_match (BRACES_TO_OPS ("a{1}*"), "aa"); + + test_match (BRACES_TO_OPS ("a{1}{1}"), "a"); + + test_match (BRACES_TO_OPS ("a{1}{1}{1}"), "a"); + test_match (BRACES_TO_OPS ("a{1}{1}{2}"), "aa"); + + test_match (BRACES_TO_OPS ("a{1}{1}*"), ""); + test_match (BRACES_TO_OPS ("a{1}{1}*"), "a"); + test_match (BRACES_TO_OPS ("a{1}{1}*"), "aa"); + test_match (BRACES_TO_OPS ("a{1}{1}*"), "aaa"); + + test_match (BRACES_TO_OPS ("a{1}{2}"), "aa"); + test_match (BRACES_TO_OPS ("a{2}{1}"), "aa"); + + + test_should_match = false; + + test_match (BRACES_TO_OPS ("a{0}"), "a"); + test_match (BRACES_TO_OPS ("a{0,}"), "b"); + test_match (BRACES_TO_OPS ("a{1}"), ""); + test_match (BRACES_TO_OPS ("a{1}"), "aa"); + test_match (BRACES_TO_OPS ("a{1,}"), ""); + test_match (BRACES_TO_OPS ("a{1,}"), "b"); + test_match (BRACES_TO_OPS ("a{0,0}"), "a"); + test_match (BRACES_TO_OPS ("a{0,1}"), "aa"); + test_match (BRACES_TO_OPS ("a{0,1}"), "b"); + test_match (BRACES_TO_OPS ("a{1,3}"), ""); + test_match (BRACES_TO_OPS ("a{1,3}"), "aaaa"); + test_match (BRACES_TO_OPS ("a{1,3}"), "b"); + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "aaaab"); + test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "bb"); + test_match (BRACES_TO_OPS ("[a]{0,3}"), "aaaa"); + test_match (BRACES_TO_OPS ("[^a]{0,3}b"), "ab"); + test_match (BRACES_TO_OPS ("ab{0,3}c"), "abababc"); + test_match (BRACES_TO_OPS ("[:alpha:]{0,3}d"), "123d"); + test_match (BRACES_TO_OPS ("\\^{1,3}a"), "a"); + test_match (BRACES_TO_OPS (".{0,3}b"), "aaaab"); + + printf ("\nFinished POSIX interval tests.\n"); +} diff --git a/gnu/lib/libregex/test/regexcpp.sed b/gnu/lib/libregex/test/regexcpp.sed new file mode 100644 index 000000000000..082c1360814f --- /dev/null +++ b/gnu/lib/libregex/test/regexcpp.sed @@ -0,0 +1,8 @@ +/;..*$/s/;/;\ +/g +/{ .*$/s/{/{\ +/g +/ \?[^'] /s/?/?\ +/g +/ : /s/:/:\ +/g diff --git a/gnu/lib/libregex/test/syntax.skel b/gnu/lib/libregex/test/syntax.skel new file mode 100644 index 000000000000..a3fbf64c5983 --- /dev/null +++ b/gnu/lib/libregex/test/syntax.skel @@ -0,0 +1,74 @@ +/* Print which syntax bits are set. */ + +#include <sys/types.h> +#include <stdio.h> +#include "regex.h" + +/* It's coincidental that these two are currently the same. */ +#define LONGEST_BIT_NAME "RE_UNMATCHED_RIGHT_PAREN_ORD" +#define LAST_BIT RE_UNMATCHED_RIGHT_PAREN_ORD + +/* Sum of above, when printed. Assigned in main. */ +static unsigned longest; + + +static void +test_bit (syntax, bit, name) + reg_syntax_t syntax; + unsigned bit; + char *name; +{ + char padding[100], test_str[100]; + int padding_count; + + sprintf (test_str, "%s (%d=0x%x)", name, bit, bit); + padding_count = longest - strlen (test_str); + + padding[padding_count] = 0; + while (padding_count--) + { + padding[padding_count] = ' '; + } + + printf ("%s%s (%d=0x%x): %c\n", + name, padding, bit, bit, syntax & bit ? 'y' : 'n'); +} + + +/* Macro to abbreviate the constant arguments. */ +#define TEST_BIT(bit) test_bit (syntax, bit, #bit) + +int +main (argc, argv) + int argc; + char *argv[]; +{ + reg_syntax_t syntax; + char syntax_str[1000], test_str[100]; + + switch (argc) + { + case 1: + printf ("Syntax? "); + scanf ("%s", syntax_str); + break; + + case 2: + strcpy (syntax_str, argv[1]); + break; + + default: + fprintf (stderr, "Usage: syntax [syntax].\n"); + exit (1); + } + + sscanf (syntax_str, "%i", &syntax); + + /* Figure out the longest name, so we can align the output nicely. */ + sprintf (test_str, "%s (%d=0x%x)", LONGEST_BIT_NAME, LAST_BIT, LAST_BIT); + longest = strlen (test_str); + + /* [[[replace with bit tests]]] */ + + return 0; +} diff --git a/gnu/lib/libregex/test/test.c b/gnu/lib/libregex/test/test.c new file mode 100644 index 000000000000..a8de23ef7429 --- /dev/null +++ b/gnu/lib/libregex/test/test.c @@ -0,0 +1,782 @@ +/* test.c: testing routines for regex.c. */ + +#include <assert.h> + +#ifdef STDC_HEADERS +#include <stdlib.h> +#else +char *malloc (); +char *realloc (); +#endif + +/* Just to be complete, we make both the system V/ANSI and the BSD + versions of the string functions available. */ +#if USG || STDC_HEADERS +#include <string.h> +#define index strchr +#define rindex strrchr +#define bcmp(s1, s2, len) memcmp ((s1), (s2), (len)) +#define bcopy(from, to, len) memcpy ((to), (from), (len)) +#define bzero(s, len) memset ((s), 0, (len)) +#else +#include <strings.h> +#define strchr index +#define strrchr rindex +#ifndef NEED_MEMORY_H +#define memcmp(s1, s2, n) bcmp ((s1), (s2), (n)) +#define memcpy(to, from, len) bcopy ((from), (to), (len)) +#endif +extern char *strtok (); +extern char *strstr (); +#endif /* not USG or STDC_HEADERS */ + +/* SunOS 4.1 declares memchr in <memory.h>, not <string.h>. I don't + understand why. */ +#if NEED_MEMORY_H +#include <memory.h> +#endif + +#include "test.h" + +#define BYTEWIDTH 8 + +extern void print_partial_compiled_pattern (); +extern void print_compiled_pattern (); +extern void print_double_string (); + +/* If nonzero, the results of every test are displayed. */ +boolean verbose = false; + +/* If nonzero, don't do register testing. */ +boolean omit_register_tests = true; + +/* Says whether the current test should match or fail to match. */ +boolean test_should_match; + + +static void +set_all_registers (start0, end0, start1, end1, + start2, end2, start3, end3, + start4, end4, start5, end5, + start6, end6, start7, end7, + start8, end8, start9, end9, regs) + + int start0; int end0; int start1; int end1; + int start2; int end2; int start3; int end3; + int start4; int end4; int start5; int end5; + int start6; int end6; int start7; int end7; + int start8; int end8; int start9; int end9; + struct re_registers *regs; + + { + unsigned r; + + regs->start[0] = start0; regs->end[0] = end0; + regs->start[1] = start1; regs->end[1] = end1; + regs->start[2] = start2; regs->end[2] = end2; + regs->start[3] = start3; regs->end[3] = end3; + regs->start[4] = start4; regs->end[4] = end4; + regs->start[5] = start5; regs->end[5] = end5; + regs->start[6] = start6; regs->end[6] = end6; + regs->start[7] = start7; regs->end[7] = end7; + regs->start[8] = start8; regs->end[8] = end8; + regs->start[9] = start9; regs->end[9] = end9; + for (r = 10; r < regs->num_regs; r++) + { + regs->start[r] = -1; + regs->end[r] = -1; + } + } + + + +/* Return the concatenation of S1 and S2. This would be a prime place + to use varargs. */ + +char * +concat (s1, s2) + char *s1; + char *s2; +{ + char *answer = xmalloc (strlen (s1) + strlen (s2) + 1); + + strcpy (answer, s1); + strcat (answer, s2); + + return answer; +} + + +#define OK_TO_SEARCH (nonconst_buf.fastmap_accurate && (str1 || str2)) + +/* We ignore the `can_be_null' argument. Should just be removed. */ + +void +general_test (pattern_should_be_valid, match_whole_string, + pat, str1, str2, start, range, end, correct_fastmap, + correct_regs, can_be_null) + unsigned pattern_should_be_valid; + unsigned match_whole_string; + const char *pat; + char *str1, *str2; + int start, range, end; + char *correct_fastmap; + struct re_registers *correct_regs; + int can_be_null; +{ + struct re_pattern_buffer nonconst_buf; + struct re_pattern_buffer old_buf; + struct re_registers regs; + const char *r; + char fastmap[1 << BYTEWIDTH]; + unsigned *regs_correct = NULL; + unsigned all_regs_correct = 1; + boolean fastmap_internal_error = false; + unsigned match = 0; + unsigned match_1 = 0; + unsigned match_2 = 0; + unsigned invalid_pattern = 0; + boolean internal_error_1 = false; + boolean internal_error_2 = false; + + + nonconst_buf.allocated = 8; + nonconst_buf.buffer = xmalloc (nonconst_buf.allocated); + nonconst_buf.fastmap = fastmap; + nonconst_buf.translate = 0; + + assert (pat != NULL); + r = re_compile_pattern (pat, strlen (pat), &nonconst_buf); + + /* Kludge: if we are doing POSIX testing, we really should have + called regcomp, not re_compile_pattern. As it happens, the only + way in which it matters is that re_compile_pattern sets the + newline/anchor field for matching (part of what happens when + REG_NEWLINE is given to regcomp). We have to undo that for POSIX + matching. */ + if (t == posix_basic_test || t == posix_extended_test) + nonconst_buf.newline_anchor = 0; + + invalid_pattern = r != NULL; + + if (!r) + { + int r; + + if (!pattern_should_be_valid) + printf ("\nShould have been an invalid pattern but wasn't:\n"); + else + { + fastmap_internal_error = (re_compile_fastmap (&nonconst_buf) == -2); + + if (correct_fastmap) + nonconst_buf.fastmap_accurate = + memcmp (nonconst_buf.fastmap, correct_fastmap, 1 << BYTEWIDTH) + == 0; + + if (OK_TO_SEARCH) + { + old_buf = nonconst_buf; + old_buf.buffer = (unsigned char *) xmalloc (nonconst_buf.used); + memcpy (old_buf.buffer, nonconst_buf.buffer, nonconst_buf.used); + + /* If only one string is null, call re_match or re_search, + which is what the user would probably do. */ + if (str1 == NULL && str2 != NULL + || str2 == NULL && str1 != NULL) + { + char *the_str = str1 == NULL ? str2 : str1; + + match_1 + = match_whole_string + ? (r = re_match (&nonconst_buf, the_str, + strlen (the_str), start, ®s)) + == strlen (the_str) + : (r = re_search (&nonconst_buf, + the_str, strlen (the_str), + start, range, ®s)) + >= 0; + + if (r == -2) + internal_error_1 = true; + } + else + match_1 = 1; + + /* Also call with re_match_2 or re_search_2, as they might + do this. (Also can check calling with either string1 + or string2 or both null.) */ + if (match_whole_string) + { + r = re_match_2 (&nonconst_buf, + str1, SAFE_STRLEN (str1), + str2, SAFE_STRLEN (str2), + start, ®s, end); + match_2 = r == SAFE_STRLEN (str1) + SAFE_STRLEN (str2); + } + else + { + r = re_search_2 (&nonconst_buf, + str1, SAFE_STRLEN (str1), + str2, SAFE_STRLEN (str2), + start, range, ®s, end); + match_2 = r >= 0; + } + + if (r == -2) + internal_error_2 = true; + + match = match_1 & match_2; + + if (correct_regs) + { + unsigned reg; + if (regs_correct != NULL) + free (regs_correct); + + regs_correct + = (unsigned *) xmalloc (regs.num_regs * sizeof (unsigned)); + + for (reg = 0; + reg < regs.num_regs && reg < correct_regs->num_regs; + reg++) + { + regs_correct[reg] + = (regs.start[reg] == correct_regs->start[reg] + && regs.end[reg] == correct_regs->end[reg]) +#ifdef EMPTY_REGS_CONFUSED + /* There is confusion in the standard about + the registers in some patterns which can + match either the empty string or not match. + For example, in `((a*))*' against the empty + string, the two registers can either match + the empty string (be 0/0), or not match + (because of the outer *) (be -1/-1). (Or + one can do one and one can do the other.) */ + || (regs.start[reg] == -1 && regs.end[reg] == -1 + && correct_regs->start[reg] + == correct_regs->end[reg]) +#endif + ; + + all_regs_correct &= regs_correct[reg]; + } + } + } /* OK_TO_SEARCH */ + } + } + + if (fastmap_internal_error) + printf ("\n\nInternal error in re_compile_fastmap:"); + + if (internal_error_1) + { + if (!fastmap_internal_error) + printf ("\n"); + + printf ("\nInternal error in re_match or re_search:"); + } + + if (internal_error_2) + { + if (!internal_error_1) + printf ("\n"); + + printf ("\nInternal error in re_match_2 or re_search_2:"); + } + + if ((OK_TO_SEARCH && ((match && !test_should_match) + || (!match && test_should_match)) + || (correct_regs && !all_regs_correct)) + || !nonconst_buf.fastmap_accurate + || invalid_pattern + || !pattern_should_be_valid + || internal_error_1 || internal_error_2 + || verbose) + { + if (OK_TO_SEARCH && match && !test_should_match) + { + printf ("\n\nMatched but shouldn't have:\n"); + if (match_1) + printf ("The single match/search succeeded.\n"); + + if (match_2) + printf ("The double match/search succeeded.\n"); + } + else if (OK_TO_SEARCH && !match && test_should_match) + { + printf ("\n\nDidn't match but should have:\n"); + if (!match_1) + printf ("The single match/search failed.\n"); + + if (!match_2) + printf ("The double match/search failed.\n"); + } + else if (invalid_pattern && pattern_should_be_valid) + printf ("\n\nInvalid pattern (%s):\n", r); + else if (!nonconst_buf.fastmap_accurate && pattern_should_be_valid) + printf ("\n\nIncorrect fastmap:\n"); + else if (OK_TO_SEARCH && correct_regs && !all_regs_correct) + printf ("\n\nNot all registers were correct:\n"); + else if (verbose) + printf ("\n\nTest was OK:\n"); + + + if ((!(invalid_pattern && !pattern_should_be_valid)) || verbose) + printf (" Pattern: `%s'.\n", pat); + + if (pattern_should_be_valid || verbose + || internal_error_1 || internal_error_2) + { + printf(" Strings: "); + printf ("`%s' and ", str1 == NULL ? "NULL" : str1); + printf ("`%s'.\n", str2 == NULL ? "NULL" : str2); + + if ((OK_TO_SEARCH || verbose || internal_error_1 || internal_error_2) + && !invalid_pattern) + { + if (memcmp (old_buf.buffer, nonconst_buf.buffer, + nonconst_buf.used) != 0 + && !invalid_pattern) + { + printf(" (%s)\n", r ? r : "Valid regular expression"); + printf ("\n Compiled pattern before matching: "); + print_compiled_pattern (&old_buf); + printf ("\n Compiled pattern after matching: "); + } + else + printf ("\n Compiled pattern: "); + + print_compiled_pattern (&nonconst_buf); + } + + if (correct_fastmap && (!nonconst_buf.fastmap_accurate || verbose)) + { + printf ("\n The fastmap should have been: "); + print_fastmap (correct_fastmap); + + printf ("\n Fastmap: "); + print_fastmap (fastmap); + + printf ("\n Compiled pattern before matching: "); + print_compiled_pattern (&nonconst_buf); + } + + if ((!all_regs_correct || verbose) && correct_regs) + { + unsigned this_reg; + printf ("\n Incorrect registers:"); + + for (this_reg = 0; this_reg < regs.num_regs; this_reg++) + { + if (!regs_correct[this_reg]) + { + printf ("\n Register %d's start was %2d. ", this_reg, + regs.start[this_reg]); + printf ("\tIt should have been %d.\n", + correct_regs->start[this_reg]); + printf (" Register %d's end was %2d. ", this_reg, + regs.end[this_reg]); + printf ("\tIt should have been %d.\n", + correct_regs->end[this_reg]); + } + } + } + } + } + + if (nonconst_buf.buffer != NULL) + free (nonconst_buf.buffer); + + if (OK_TO_SEARCH) + { + free (old_buf.buffer); + + if (correct_regs) + free (regs_correct); + + } + + nonconst_buf.buffer = old_buf.buffer = NULL; + regs_correct = NULL; + regs.start = regs.end = NULL; + +} /* general_test */ + + +void +test_search_return (match_start_wanted, pattern, string) + int match_start_wanted; + const char *pattern; + char *string; +{ + struct re_pattern_buffer buf; + char fastmap[1 << BYTEWIDTH]; + const char *compile_return; + int match_start; + static num_times_called = 0; + + num_times_called++; + buf.allocated = 1; + buf.buffer = xmalloc (buf.allocated); + + assert (pattern != NULL); + buf.translate = 0; + compile_return = re_compile_pattern (pattern, strlen (pattern), &buf); + + if (compile_return) + { + printf ("\n\nInvalid pattern in test_match_start:\n"); + printf ("%s\n", compile_return); + } + else + { + buf.fastmap = fastmap; + match_start = re_search (&buf, string, strlen (string), + 0, strlen (string), 0); + + if (match_start != match_start_wanted) + printf ("\nWanted search to start at %d but started at %d.\n", + match_start, match_start_wanted); + } + free (buf.buffer); + buf.buffer = NULL; +} + + +#define SET_FASTMAP() \ + { \ + unsigned this_char; \ + \ + memset (correct_fastmap, invert, (1 << BYTEWIDTH)); \ + \ + for (this_char = 0; this_char < strlen (fastmap_string); this_char++)\ + correct_fastmap[fastmap_string[this_char]] = !invert; \ + correct_fastmap['\n'] = match_newline; \ + } + + +void +test_fastmap (pat, fastmap_string, invert, match_newline) + const char *pat; + char *fastmap_string; + unsigned invert; + unsigned match_newline; +{ + char correct_fastmap[(1 << BYTEWIDTH)]; + + SET_FASTMAP (); + general_test (1, 0, pat, NULL, NULL, -1, 0, -1, correct_fastmap, 0, -1); +} + + +void +test_fastmap_search (pat, str, fastmap_string, invert, match_newline, + can_be_null, start0, end0) + const char *pat; + char *str; + char *fastmap_string; + unsigned invert; + unsigned match_newline; + int can_be_null; + int start0; + int end0; +{ + char correct_fastmap[(1 << BYTEWIDTH)]; + struct re_registers correct_regs; + + correct_regs.num_regs = RE_NREGS; + correct_regs.start = (int *) xmalloc (RE_NREGS * sizeof (int)); + correct_regs.end = (int *) xmalloc (RE_NREGS * sizeof (int)); + + set_all_registers (start0, end0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, &correct_regs); + SET_FASTMAP (); + general_test (1, 0, pat, str, NULL, 0, SAFE_STRLEN (str), SAFE_STRLEN (str), + correct_fastmap, &correct_regs, can_be_null); + + free (correct_regs.start); + free (correct_regs.end); +} + + + + +void +test_all_registers (pat, str1, str2, + start0, end0, start1, end1, + start2, end2, start3, end3, + start4, end4, start5, end5, + start6, end6, start7, end7, + start8, end8, start9, end9) + char *pat; char *str1; char *str2; + int start0; int end0; int start1; int end1; + int start2; int end2; int start3; int end3; + int start4; int end4; int start5; int end5; + int start6; int end6; int start7; int end7; + int start8; int end8; int start9; int end9; +{ + struct re_registers correct_regs; + + if (omit_register_tests) return; + + correct_regs.num_regs = RE_NREGS; + correct_regs.start = (int *) xmalloc (RE_NREGS * sizeof (int)); + correct_regs.end = (int *) xmalloc (RE_NREGS * sizeof (int)); + + set_all_registers (start0, end0, start1, end1, start2, end2, start3, end3, + start4, end4, start5, end5, start6, end6, start7, end7, + start8, end8, start9, end9, &correct_regs); + + general_test (1, 0, pat, str1, str2, 0, + SAFE_STRLEN (str1) + SAFE_STRLEN (str2), + SAFE_STRLEN (str1) + SAFE_STRLEN (str2), + NULL, &correct_regs, -1); + + free (correct_regs.start); + free (correct_regs.end); +} + + +void +invalid_pattern (error_code_expected, pattern) + int error_code_expected; + char *pattern; +{ + regex_t pattern_buffer; + int cflags + = re_syntax_options == RE_SYNTAX_POSIX_EXTENDED + || re_syntax_options == RE_SYNTAX_POSIX_MINIMAL_EXTENDED + ? REG_EXTENDED : 0; + + test_compile (0, error_code_expected, pattern, &pattern_buffer, cflags); +} + + +void +valid_pattern (pattern) + char *pattern; +{ + regex_t pattern_buffer; + int cflags + = re_syntax_options == RE_SYNTAX_POSIX_EXTENDED + || re_syntax_options == RE_SYNTAX_POSIX_MINIMAL_EXTENDED + ? REG_EXTENDED : 0; + + test_compile (1, 0, pattern, &pattern_buffer, cflags); +} + + +char * +delimiters_to_ops (source, left_delimiter, right_delimiter) + char *source; + char left_delimiter; + char right_delimiter; +{ + static char *answer = NULL; + char *tmp = NULL; + boolean double_size = false; + unsigned source_char; + unsigned answer_char = 0; + + assert (source != NULL); + + switch (left_delimiter) + { + case '(': if (!(re_syntax_options & RE_NO_BK_PARENS)) + double_size = true; + break; + case '{': if (!(re_syntax_options & RE_NO_BK_BRACES)) + double_size = true; + break; + default: printf ("Found strange delimiter %c in delimiter_to_ops.\n", + left_delimiter); + printf ("The source was `%s'\n", source); + exit (0); + } + + if (answer == source) + { + tmp = (char *) xmalloc (strlen (source) + 1); + strcpy (tmp, source); + source = tmp; + } + + if (answer) + { + free (answer); + answer = NULL; + } + + answer = (char *) xmalloc ((double_size + ? strlen (source) << 1 + : strlen (source)) + + 1); + if (!double_size) + strcpy (answer, source); + else + { + for (source_char = 0; source_char < strlen (source); source_char++) + { + if (source[source_char] == left_delimiter + || source[source_char] == right_delimiter) + answer[answer_char++] = '\\'; + + answer[answer_char++] = source[source_char]; + } + answer[answer_char] = 0; + } + + return answer; +} + + +void +print_pattern_info (pattern, pattern_buffer_ptr) + const char *pattern; + regex_t *pattern_buffer_ptr; +{ + printf (" Pattern: `%s'.\n", pattern); + printf (" Compiled pattern: "); + print_compiled_pattern (pattern_buffer_ptr); +} + + +void +valid_nonposix_pattern (pattern) + char *pattern; +{ + struct re_pattern_buffer nonconst_buf; + + nonconst_buf.allocated = 0; + nonconst_buf.buffer = NULL; + nonconst_buf.translate = NULL; + + assert (pattern != NULL); + + if (re_compile_pattern (pattern, strlen (pattern), &nonconst_buf)) + { + printf ("Couldn't compile the pattern.\n"); + print_pattern_info (pattern, &nonconst_buf); + } +} + + +void +compile_and_print_pattern (pattern) + char *pattern; +{ + struct re_pattern_buffer nonconst_buf; + + nonconst_buf.allocated = 0; + nonconst_buf.buffer = NULL; + + if (re_compile_pattern (pattern, strlen (pattern), &nonconst_buf)) + printf ("Couldn't compile the pattern.\n"); + + print_pattern_info (pattern, &nonconst_buf); +} + + +void +test_case_fold (pattern, string) + const char *pattern; + char* string; +{ + struct re_pattern_buffer nonconst_buf; + const char *ret; + + init_pattern_buffer (&nonconst_buf); + nonconst_buf.translate = upcase; + + assert (pattern != NULL); + ret = re_compile_pattern (pattern, strlen (pattern), &nonconst_buf); + + if (ret) + { + printf ("\nShould have been a valid pattern but wasn't.\n"); + print_pattern_info (pattern, &nonconst_buf); + } + else + { + if (test_should_match + && re_match (&nonconst_buf, string, strlen (string), 0, 0) + != strlen (string)) + { + printf ("Match failed for case fold.\n"); + printf (" Pattern: `%s'.\n", pattern); + printf (" String: `%s'.\n", string == NULL ? "NULL" : string); + } + } +} + + +void +test_match_n_times (n, pattern, string) + unsigned n; + char* pattern; + char* string; +{ + struct re_pattern_buffer buf; + const char *r; + unsigned match = 0; + unsigned this_match; + + buf.allocated = 0; + buf.buffer = NULL; + buf.translate = 0; + + assert (pattern != NULL); + + r = re_compile_pattern (pattern, strlen (pattern), &buf); + if (r) + { + printf ("Didn't compile.\n"); + printf (" Pattern: %s.\n", pattern); + } + else + { + for (this_match = 1; this_match <= n; this_match++) + match = (re_match (&buf, string, strlen (string), + 0, 0) + == strlen (string)); + + if (match && !test_should_match) + printf ("\n\nMatched but shouldn't have:\n"); + else if (!match && test_should_match) + printf ("\n\nDidn't match but should have:\n"); + + if ((match && !test_should_match) || (!match && test_should_match)) + { + printf(" The string to match was: "); + if (string) + printf ("`%s' and ", string); + else + printf ("`'"); + + printf (" Pattern: %s.\n", pattern); + printf (" Compiled pattern: %s.\n", pattern); + print_compiled_pattern (&buf); + } + } +} + + +void +test_match_2 (pat, str1, str2) + const char *pat; + char *str1; + char *str2; +{ + general_test (1, 1, pat, str1, str2, 0, 1, + SAFE_STRLEN (str1) + SAFE_STRLEN (str2), NULL, 0, -1); +} + +void +test_match (pat, str) + const char *pat; + char *str; +{ + test_match_2 (pat, str, NULL); + test_match_2 (pat, NULL, str); +} diff --git a/gnu/lib/libregex/test/test.h b/gnu/lib/libregex/test/test.h new file mode 100644 index 000000000000..fb67126547cc --- /dev/null +++ b/gnu/lib/libregex/test/test.h @@ -0,0 +1,141 @@ +/* test.h: for Regex testing. */ + +#ifndef TEST_H +#define TEST_H + +#include <stdio.h> +#include <assert.h> + +#include <sys/types.h> +#include "regex.h" + + +/* A strlen that works even on a null pointer. */ +#define SAFE_STRLEN(s) (s == NULL ? 0 : strlen (s)) + +typedef enum { false = 0, true = 1 } boolean; + +extern boolean test_should_match; +extern boolean omit_register_tests; +extern void *xmalloc (); + +/* Defined in upcase.c. */ +extern char upcase[]; + +typedef enum +{ + all_test, + other_test, + posix_basic_test, + posix_extended_test, + posix_interface_test, + regress_test +} test_type; + +extern test_type t; + + +#if __STDC__ + +extern char *concat (char *, char *); + +extern void general_test (unsigned pattern_should_be_valid, + unsigned match_whole_string, + const char *pat, char *str1, char *str2, + int start, int range, int end, + char *correct_fastmap, + struct re_registers *correct_regs, int can_be_null); + + +extern void init_pattern_buffer (regex_t *pattern_buffer_ptr); + +extern void test_compile (unsigned valid_pattern, int error_code_expected, + const char *pattern, regex_t *pattern_buffer_ptr, + int cflags); + +extern char *delimiter_to_ops (char *source, char left_delimiter, + char right_delimiter); + + +extern void test_search_return (int, const char *, char *); + +extern void test_berk_search (const char *pattern, char *string); + +extern void test_fastmap (const char *pat, char *fastmap_string, unsigned invert, + unsigned match_newline); + +extern void test_fastmap_search (const char *pat, char *str, char *fastmap_string, + unsigned invert, unsigned match_newline, + int can_be_null, int start0, int end0); + +extern void test_all_registers (char *pat, char *str1, char *str2, + int start0, int end0, int start1, int end1, + int start2, int end2, int start3, int end3, + int start4, int end4, int start5, int end5, + int start6, int end6, int start7, int end7, + int start8, int end8, int start9, int end9); + +extern void print_pattern_info (const char *pattern, regex_t *pattern_buffer_ptr); +extern void compile_and_print_pattern (char *pattern); + +extern void test_case_fold (const char *pattern, char* string); + +extern void test_posix_generic (); + +extern void test_grouping (); + +extern void invalid_pattern (int error_code_expected, char *pattern); +extern void valid_nonposix_pattern (char *pattern); +extern void valid_pattern (char *pattern); + +extern void test_match_2 (const char *pat, char *str1, char *str2); +extern void test_match (const char *pat, char *str); + +#endif /* __STDC__ */ + + +#define TEST_REGISTERS_2(pat, str1, str2, start0, end0, start1, end1, start2, end2)\ + if (!omit_register_tests) \ + test_all_registers (pat, str1, str2, start0, end0, start1, end1, \ + start2, end2, -1, -1, -1, -1, -1, -1, -1, -1,\ + -1, -1, -1, -1, -1, -1) \ + + +#define TEST_REGISTERS(pat, str, start0, end0, start1, end1, start2, end2) \ + TEST_REGISTERS_2 (pat, str, NULL, start0, end0, start1, end1, start2, end2)\ + +#define BRACES_TO_OPS(string) ((char *) delimiters_to_ops (string, '{', '}')) +#define PARENS_TO_OPS(string) ((char *) delimiters_to_ops (string, '(', ')')) + +#define INVALID_PATTERN(pat) \ + general_test (0, 0, pat, NULL, NULL, -1, 0, -1, NULL, 0, -1) + + +#define MATCH_SELF(p) test_match (p, p) + +#define TEST_POSITIONED_MATCH(pat, str, start) \ + general_test (1, 0, pat, str, NULL, start, 1, SAFE_STRLEN (str), \ + NULL, 0, -1) + +#define TEST_TRUNCATED_MATCH(pat, str, end) \ + general_test (1, 0, pat, str, NULL, 0, 1, end, NULL, 0, -1) + +#define TEST_SEARCH_2(pat, str1, str2, start, range, one_past_end) \ + general_test (1, 0, pat, str1, str2, start, range, one_past_end, \ + NULL, 0, -1) + +#define TEST_SEARCH(pat, str, start, range) \ + { \ + TEST_SEARCH_2 (pat, str, NULL, start, range, SAFE_STRLEN (str)); \ + TEST_SEARCH_2 (pat, NULL, str, start, range, SAFE_STRLEN (str)); \ + } + +#endif /* TEST_H */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/test/tregress.c b/gnu/lib/libregex/test/tregress.c new file mode 100644 index 000000000000..7858cac1502b --- /dev/null +++ b/gnu/lib/libregex/test/tregress.c @@ -0,0 +1,464 @@ +/* tregress.c: reported bugs. The `t' just makes the filename not have + a common prefix with `regex.c', so completion works better. */ + +#include "test.h" + + +boolean pause_at_error = true; + +char * +itoa (i) + int i; +{ + char *a = xmalloc (21); /* sign + 19 digits (enough for 64 bits) + null */ + + sprintf (a, "%d", i); + return a; +} + + +static void +simple_fail (routine, pat, buf, str, ret) + const char *routine; + const char *pat; + struct re_pattern_buffer *buf; + const char *str; + char *ret; +{ + fprintf (stderr, "Failed %s (return = %s).\n", routine, ret); + if (str && *str) fprintf (stderr, " String = %s\n", str); + fprintf (stderr, " Pattern = %s\n", pat); + print_compiled_pattern (buf); + + if (pause_at_error) + { + fprintf (stderr, "RET to continue: "); + (void) getchar (); + } +} + + +/* Abbreviate the most common calls. */ + +static void +simple_compile (pat, buf) + const char *pat; + struct re_pattern_buffer *buf; +{ + const char *ret = re_compile_pattern (pat, strlen (pat), buf); + + if (ret != NULL) simple_fail ("compile", pat, buf, NULL, ret); +} + + +static void +simple_fastmap (pat) + const char *pat; +{ + struct re_pattern_buffer buf; + char fastmap[256]; + int ret; + + buf.allocated = 0; + buf.buffer = buf.translate = NULL; + buf.fastmap = fastmap; + + simple_compile (pat, &buf); + + ret = re_compile_fastmap (&buf); + + if (ret != 0) simple_fail ("fastmap compile", pat, &buf, NULL, itoa (ret)); +} + + +#define SIMPLE_MATCH(pat, str) do_match (pat, str, strlen (str)) +#define SIMPLE_NONMATCH(pat, str) do_match (pat, str, -1) + +static void +do_match (pat, str, expected) + const char *pat, *str; + int expected; +{ + int ret; + unsigned len; + struct re_pattern_buffer buf; + + buf.allocated = 0; + buf.buffer = buf.translate = buf.fastmap = NULL; + + simple_compile (pat, &buf); + + len = strlen (str); + + ret = re_match_2 (&buf, NULL, 0, str, len, 0, NULL, len); + + if (ret != expected) simple_fail ("match", pat, &buf, str, itoa (ret)); +} + + +static void +simple_search (pat, str, correct_startpos) + const char *pat, *str; + int correct_startpos; +{ + int ret; + unsigned len; + struct re_pattern_buffer buf; + + buf.allocated = 0; + buf.buffer = buf.translate = buf.fastmap = NULL; + + simple_compile (pat, &buf); + + len = strlen (str); + + ret = re_search_2 (&buf, NULL, 0, str, len, 0, len, NULL, len); + + if (ret != correct_startpos) + simple_fail ("match", pat, &buf, str, itoa (ret)); +} + +/* Past bugs people have reported. */ + +void +test_regress () +{ + extern char upcase[]; + struct re_pattern_buffer buf; + unsigned len; + struct re_registers regs; + int ret; + char *fastmap = xmalloc (256); + + buf.translate = NULL; + buf.fastmap = NULL; + buf.allocated = 0; + buf.buffer = NULL; + + printf ("\nStarting regression tests.\n"); + t = regress_test; + + test_should_match = true; + re_set_syntax (RE_SYNTAX_EMACS); + + /* enami@sys.ptg.sony.co.jp 10 Nov 92 15:19:02 JST */ + buf.translate = upcase; + SIMPLE_MATCH ("[A-[]", "A"); + buf.translate = NULL; + + /* meyering@cs.utexas.edu Nov 6 22:34:41 1992 */ + simple_search ("\\w+", "a", 0); + + /* jimb@occs.cs.oberlin.edu 10 Sep 92 00:42:33 */ + buf.translate = upcase; + SIMPLE_MATCH ("[\001-\377]", "\001"); + SIMPLE_MATCH ("[\001-\377]", "a"); + SIMPLE_MATCH ("[\001-\377]", "\377"); + buf.translate = NULL; + + /* mike@skinner.cs.uoregon.edu 1 Sep 92 01:45:22 */ + SIMPLE_MATCH ("^^$", "^"); + + /* pclink@qld.tne.oz.au Sep 7 22:42:36 1992 */ + re_set_syntax (RE_INTERVALS); + SIMPLE_MATCH ("^a\\{3\\}$", "aaa"); + SIMPLE_NONMATCH ("^a\\{3\\}$", "aa"); + re_set_syntax (RE_SYNTAX_EMACS); + + /* pclink@qld.tne.oz.au, 31 Aug 92. (conjecture) */ + re_set_syntax (RE_INTERVALS); + simple_search ("a\\{1,3\\}b", "aaab", 0); + simple_search ("a\\{1,3\\}b", "aaaab", 1); + re_set_syntax (RE_SYNTAX_EMACS); + + /* trq@dionysos.thphys.ox.ac.uk, 31 Aug 92. (simplified) */ + simple_fastmap ("^.*\n[ ]*"); + + /* wind!greg@plains.NoDak.edu, 25 Aug 92. (simplified) */ + re_set_syntax (RE_INTERVALS); + SIMPLE_MATCH ("[a-zA-Z]*.\\{5\\}", "xN0000"); + SIMPLE_MATCH ("[a-zA-Z]*.\\{5\\}$", "systemxN0000"); + SIMPLE_MATCH ("\\([a-zA-Z]*\\).\\{5\\}$", "systemxN0000"); + re_set_syntax (RE_SYNTAX_EMACS); + + /* jimb, 18 Aug 92. Don't use \000, so `strlen' (in our testing + routines) will work. (This still tickles the bug jimb reported.) */ + SIMPLE_MATCH ("[\001-\377]", "\001"); + SIMPLE_MATCH ("[\001-\377]", "a"); + SIMPLE_MATCH ("[\001-\377]", "\377"); + + /* jimb, 13 Aug 92. */ + SIMPLE_MATCH ("[\001-\177]", "\177"); + + /* Tests based on bwoelfel's below. */ + SIMPLE_MATCH ("\\(a\\|ab\\)*", "aab"); + SIMPLE_MATCH ("\\(a\\|ab\\)+", "aab"); + SIMPLE_MATCH ("\\(a*\\|ab\\)+", "aab"); + SIMPLE_MATCH ("\\(a+\\|ab\\)+", "aab"); + SIMPLE_MATCH ("\\(a?\\|ab\\)+", "aab"); + + /* bwoelfel@widget.seas.upenn.edu, 25 Jul 92. */ + SIMPLE_MATCH ("^\\([ab]+\\|bc\\)+", "abc"); + + /* jla, 3 Jul 92. Core dump in re_search_2. */ + buf.fastmap = fastmap; + buf.translate = upcase; +#define DATEDUMP_PATTERN " *[0-9]*:" + if (re_compile_pattern (DATEDUMP_PATTERN, strlen (DATEDUMP_PATTERN), &buf) + != NULL) + printf ("date dump compile failed.\n"); + regs.num_regs = 0; + regs.start = regs.end = NULL; + if (re_search_2 (&buf, NULL, 0, "Thu Jul 2 18:34:18 1992", + 24, 3, 21, ®s, 24) != 10) + printf ("date dump search failed.\n"); + buf.fastmap = 0; + buf.translate = 0; + + + /* rms, 4 Jul 1992. Pattern is much slower in Emacs 19. Fastmap + should be only a backslash. */ +#define BEGINEND_PATTERN "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)" + test_fastmap (BEGINEND_PATTERN, "\\", false, 0); + + + /* kaoru@is.s.u-tokyo.ac.jp, 27 Jun 1992. Code for [a-z] (in regex.c) + should translate the whole set. */ + buf.translate = upcase; +#define CASE_SET_PATTERN "[ -`]" + if (re_compile_pattern (CASE_SET_PATTERN, strlen (CASE_SET_PATTERN), &buf) + != NULL) + printf ("case set compile failed.\n"); + if (re_match_2 (&buf, "K", 1, "", 0, 0, NULL, 1) != 1) + printf ("case set match failed.\n"); + +#define CASE_SET_PATTERN2 "[`-|]" + if (re_compile_pattern (CASE_SET_PATTERN2, strlen (CASE_SET_PATTERN2), &buf) + != NULL) + printf ("case set2 compile failed.\n"); + if (re_match_2 (&buf, "K", 1, "", 0, 0, NULL, 1) != 1) + printf ("case set2 match failed.\n"); + + buf.translate = NULL; + + + /* jimb, 27 Jun 92. Problems with gaps in the string. */ +#define GAP_PATTERN "x.*y.*z" + if (re_compile_pattern (GAP_PATTERN, strlen (GAP_PATTERN), &buf) != NULL) + printf ("gap didn't compile.\n"); + if (re_match_2 (&buf, "x-", 2, "y-z-", 4, 0, NULL, 6) != 5) + printf ("gap match failed.\n"); + + + /* jimb, 19 Jun 92. Since `beginning of word' matches at the + beginning of the string, then searching ought to find it there. + If `re_compile_fastmap' is not called, then it works ok. */ + buf.fastmap = fastmap; +#define BOW_BEG_PATTERN "\\<" + if (re_compile_pattern (BOW_BEG_PATTERN, strlen (BOW_BEG_PATTERN), &buf) + != NULL) + printf ("begword-begstring didn't compile.\n"); + if (re_search (&buf, "foo", 3, 0, 3, NULL) != 0) + printf ("begword-begstring search failed.\n"); + + /* Same bug report, different null-matching pattern. */ +#define EMPTY_ANCHOR_PATTERN "^$" + if (re_compile_pattern (EMPTY_ANCHOR_PATTERN, strlen (EMPTY_ANCHOR_PATTERN), + &buf) != NULL) + printf ("empty anchor didn't compile.\n"); + if (re_search (&buf, "foo\n\nbar", 8, 0, 8, NULL) != 4) + printf ("empty anchor search failed.\n"); + + /* jimb@occs.cs.oberlin.edu, 21 Apr 92. After we first allocate + registers for a particular re_pattern_buffer, we might have to + reallocate more registers on subsequent calls -- and we should be + reusing the same memory. */ +#define ALLOC_REG_PATTERN "\\(abc\\)" + free (buf.fastmap); + buf.fastmap = 0; + if (re_compile_pattern (ALLOC_REG_PATTERN, strlen (ALLOC_REG_PATTERN), &buf) + != NULL) + printf ("register allocation didn't compile.\n"); + if (re_match (&buf, "abc", 3, 0, ®s) != 3) + printf ("register allocation didn't match.\n"); + if (regs.start[1] != 0 || regs.end[1] != 3) + printf ("register allocation reg #1 wrong.\n"); + + { + int *old_regstart = regs.start; + int *old_regend = regs.end; + + if (re_match (&buf, "abc", 3, 0, ®s) != 3) + printf ("register reallocation didn't match.\n"); + if (regs.start[1] != 0 || regs.end[1] != 3 + || old_regstart[1] != 0 || old_regend[1] != 3 + || regs.start != old_regstart || regs.end != old_regend) + printf ("register reallocation registers wrong.\n"); + } + + /* jskudlarek@std.MENTORG.COM, 21 Apr 92 (string-match). */ +#define JSKUD_PATTERN "[^/]+\\(/[^/.]+\\)?/[0-9]+$" + if (re_compile_pattern (JSKUD_PATTERN, strlen (JSKUD_PATTERN), &buf) != NULL) + printf ("jskud test didn't compile.\n"); + if (re_search (&buf, "a/1", 3, 0, 3, ®s) != 0) + printf ("jskud test didn't match.\n"); + if (regs.start[1] != -1 || regs.end[1] != -1) + printf ("jskud test, reg #1 wrong.\n"); + + /* jla's bug (with string-match), 5 Feb 92. */ + TEST_SEARCH ("\\`[ \t\n]*", "jla@challenger (Joseph Arceneaux)", 0, 100); + + /* jwz@lucid.com, 8 March 1992 (re-search-forward). (His is the + second.) These are not supposed to match. */ +#if 0 + /* This one fails quickly, because we can change the maybe_pop_jump + from the + to a pop_failure_pop, because of the c's. */ + TEST_SEARCH ("^\\(To\\|CC\\):\\([^c]*\\)+co", +"To: hbs%titanic@lucid.com (Harlan Sexton)\n\ +Cc: eb@thalidomide, jlm@thalidomide\n\ +Subject: Re: so is this really as horrible an idea as it seems to me?\n\ +In-Reply-To: Harlan Sexton's message of Sun 8-Mar-92 11:00:06 PST <9203081900.AA24794@titanic.lucid>\n\ +References: <9203080736.AA05869@thalidomide.lucid>\n\ + <9203081900.AA24794@titanic.lucid>", 0, 5000); + + /* This one takes a long, long time to complete, because we have to + keep the failure points around because we might backtrack. */ + TEST_SEARCH ("^\\(To\\|CC\\):\\(.*\n.*\\)+co", + /* "X-Windows: The joke that kills.\n\ +FCC: /u/jwz/VM/inbox\n\ +From: Jamie Zawinski <jwz@lucid.com>\n\ */ +"To: hbs%titanic@lucid.com (Harlan Sexton)\n\ +Cc: eb@thalidomide, jlm@thalidomide\n\ +Subject: Re: so is this really as horrible an idea as it seems to me?\n\ +In-Reply-To: Harlan Sexton's message of Sun 8-Mar-92 11:00:06 PST <9203081900.AA24794@titanic.lucid>\n\ +References: <9203080736.AA05869@thalidomide.lucid>\n\ + <9203081900.AA24794@titanic.lucid>", 0, 5000); +#endif /* 0 [failed searches] */ + + + /* macrakis' bugs. */ + buf.translate = upcase; /* message of 24 Jan 91 */ + if (re_compile_pattern ("[!-`]", 5, &buf) != NULL) + printf ("Range test didn't compile.\n"); + if (re_match (&buf, "A", 1, 0, NULL) != 1) + printf ("Range test #1 didn't match.\n"); + if (re_match (&buf, "a", 1, 0, NULL) != 1) + printf ("Range test #2 didn't match.\n"); + + buf.translate = 0; +#define FAO_PATTERN "\\(f\\(.\\)o\\)+" + if (re_compile_pattern (FAO_PATTERN, strlen (FAO_PATTERN), &buf) != NULL) + printf ("faofdx test didn't compile.\n"); + if (re_search (&buf, "faofdx", 6, 0, 6, ®s) != 0) + printf ("faofdx test didn't match.\n"); + if (regs.start[1] != 0 || regs.end[1] != 3) + printf ("faofdx test, reg #1 wrong.\n"); + if (regs.start[2] != 1 || regs.end[2] != 2) + printf ("faofdx test, reg #2 wrong.\n"); + + TEST_REGISTERS ("\\(a\\)*a", "aaa", 0, 3, 1, 2, -1, -1); + test_fastmap ("^\\([^ \n]+:\n\\)+\\([^ \n]+:\\)", " \n", 1, 0); + + /* 40 lines, 48 a's in each line. */ + test_match ("^\\([^ \n]+:\n\\)+\\([^ \n]+:\\)", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:"); + + /* 640 a's followed by one b, twice. */ + test_match ("\\(.*\\)\\1", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"); + + /* 640 a's followed by two b's, twice. */ + test_match ("\\(.*\\)\\1", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb"); + + + /* Dave G. bug: Reference to a subexpression which didn't match. + Should fail. */ + re_set_syntax (RE_NO_BK_PARENS | RE_NO_BK_VBAR); + test_match ("(ooooooooooone())-annnnnnnnnnnd-(twooooooooooo\\2)", + "ooooooooooone-annnnnnnnnnnd-twooooooooooo"); + test_match ("(o|t)", "o"); + test_match ("(o()|t)", "o"); + test_match ("(o|t)", "o"); + test_match ("(ooooooooooooooo|tttttttttttttttt())", "ooooooooooooooo"); + test_match ("(o|t())", "o"); + test_match ("(o()|t())", "o"); + test_match ("(ooooooooooooooooooooooooone()|twooooooooooooooooooooooooo())", "ooooooooooooooooooooooooone"); + test_match ("(o()|t())-a-(t\\2|f\\3)", "o-a-t"); + test_match ("(o()|t())-a-(t\\2|f\\3)", "t-a-f"); + + test_should_match = 0; + test_match ("(foo(bar)|second)\\2", "second"); + test_match ("(o()|t())-a-(t\\2|f\\3)", "t-a-t"); + test_match ("(o()|t())-a-(t\\2|f\\3)", "o-a-f"); + + re_set_syntax (RE_SYNTAX_EMACS); + test_match ("\\(foo\\(bar\\)\\|second\\)\\2", "secondbar"); + test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)", + "one-and-four"); + test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)", + "two-and-three"); + + test_should_match = 1; + re_set_syntax (RE_SYNTAX_EMACS); + test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)", + "one-and-three"); + test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)", + "two-and-four"); + + TEST_REGISTERS (":\\(.*\\)", ":/", 0, 2, 1, 2, -1, -1); + + /* Bug with `upcase' translation table, from Nico Josuttis + <nico@bredex.de> */ + test_should_match = 1; + test_case_fold ("[a-a]", "a"); + + printf ("\nFinished regression tests.\n"); +} + + + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/test/upcase.c b/gnu/lib/libregex/test/upcase.c new file mode 100644 index 000000000000..5147b812aaae --- /dev/null +++ b/gnu/lib/libregex/test/upcase.c @@ -0,0 +1,39 @@ +/* Indexed by a character, gives the upper case equivalent of the + character. */ + +char upcase[0400] = + { 000, 001, 002, 003, 004, 005, 006, 007, + 010, 011, 012, 013, 014, 015, 016, 017, + 020, 021, 022, 023, 024, 025, 026, 027, + 030, 031, 032, 033, 034, 035, 036, 037, + 040, 041, 042, 043, 044, 045, 046, 047, + 050, 051, 052, 053, 054, 055, 056, 057, + 060, 061, 062, 063, 064, 065, 066, 067, + 070, 071, 072, 073, 074, 075, 076, 077, + 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, + 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, + 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, + 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 + }; + + diff --git a/gnu/lib/libregex/test/xmalloc.c b/gnu/lib/libregex/test/xmalloc.c new file mode 100644 index 000000000000..88be1a668bd3 --- /dev/null +++ b/gnu/lib/libregex/test/xmalloc.c @@ -0,0 +1,21 @@ +#include <stdio.h> +extern char *malloc (); + +#ifndef NULL +#define NULL 0 +#endif + +void * +xmalloc (size) + unsigned size; +{ + char *new_mem = malloc (size); + + if (new_mem == NULL) + { + fprintf (stderr, "xmalloc: request for %u bytes failed.\n", size); + abort (); + } + + return new_mem; +} |
