4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
33 * regcmp() WORKS **ONLY** WITH THE ASCII AND THE Solaris EUC CHARACTER SETS.
34 * IT IS **NOT** CHARACTER SET INDEPENDENT.
38 #pragma weak _regcmp = regcmp
52 /* CONSTANTS SHARED WITH regex() */
56 /* PRIVATE CONSTANTS */
58 #define BACKSLASH '\\'
59 #define CIRCUMFLEX '^'
62 #define DOLLAR_SIGN '$'
64 #define LEFT_CURLY_BRACE '{'
65 #define LEFT_PAREN '('
66 #define LEFT_SQUARE_BRACKET '['
68 #define RIGHT_CURLY_BRACE '}'
69 #define RIGHT_PAREN ')'
70 #define RIGHT_SQUARE_BRACKET ']'
71 #define SINGLE_BYTE_MASK 0xff
72 #define STRINGP_STACK_SIZE 50
75 /* PRIVATE GLOBAL VARIABLES */
77 static char *compilep_stack
[STRINGP_STACK_SIZE
];
78 static char **compilep_stackp
;
79 static mutex_t regcmp_lock
= DEFAULTMUTEX
;
81 /* DECLARATIONS OF PRIVATE FUNCTIONS */
83 static int add_char(char *compilep
, wchar_t wchar
);
84 static int add_single_char_expr(char *compilep
, wchar_t wchar
);
86 #define ERROR_EXIT(mutex_lockp, arg_listp, compile_startp) \
89 lmutex_unlock(mutex_lockp); \
90 if ((compile_startp) != (char *)0) \
91 free((void *)compile_startp); \
94 static int get_count(int *countp
, const char *regexp
);
95 static int get_digit(const char *regexp
);
96 static int get_wchar(wchar_t *wchar
, const char *regexp
);
97 static char *pop_compilep(void);
98 static char *push_compilep(char *compilep
);
99 static boolean_t
valid_range(wchar_t lower_char
, wchar_t upper_char
);
102 /* DEFINITIONS OF PUBLIC VARIABLES */
107 * define thread-specific storage for __i_size
115 return ((int *)tsdalloc(_T_REGCMP_ISIZE
, sizeof (int), NULL
));
118 #define __i_size (*(___i_size()))
120 /* DEFINITION OF regcmp() */
123 regcmp(const char *regexp
, ...)
127 boolean_t can_repeat
;
129 unsigned int class_length
;
131 char *compile_startp
= (char *)0;
133 wchar_t current_char
;
136 unsigned int group_length
;
137 unsigned int high_bits
;
138 boolean_t dash_indicates_range
;
139 unsigned int low_bits
;
142 const char *next_argp
;
143 wchar_t first_char_in_range
;
145 int return_arg_number
;
148 if (___i_size() == (int *)0)
152 * When compiling a regular expression, regcmp() generates at most
153 * two extra single-byte characters for each character in the
154 * expression, so allocating three times the number of bytes in all
155 * the strings that comprise the regular expression will ensure that
156 * regcmp() won't overwrite the end of the allocated block when
157 * compiling the expression.
160 va_start(arg_listp
, regexp
);
163 while (next_argp
!= (char *)0) {
164 arg_strlen
+= strlen(next_argp
);
165 next_argp
= va_arg(arg_listp
, /* const */ char *);
171 compile_startp
= (char *)malloc(3 * arg_strlen
+ 1);
172 if (compile_startp
== (char *)0)
175 lmutex_lock(®cmp_lock
);
177 compilep
= compile_startp
;
178 compilep_stackp
= &compilep_stack
[STRINGP_STACK_SIZE
];
180 /* GET THE FIRST CHARACTER IN THE REGULAR EXPRESSION */
181 va_start(arg_listp
, regexp
);
182 next_argp
= va_arg(arg_listp
, /* const */ char *);
183 char_size
= get_wchar(¤t_char
, regexp
);
185 ERROR_EXIT(®cmp_lock
, arg_listp
, compile_startp
);
186 } else if (char_size
> 0) {
188 } else /* (char_size == 0 ) */ {
190 next_argp
= va_arg(arg_listp
, /* const */ char *);
191 char_size
= get_wchar(¤t_char
, regexp
);
192 if (char_size
<= 0) {
193 ERROR_EXIT(®cmp_lock
, arg_listp
, compile_startp
);
199 /* FIND OUT IF THE EXPRESSION MUST START AT THE START OF A STRING */
201 if (current_char
== CIRCUMFLEX
) {
202 char_size
= get_wchar(¤t_char
, regexp
);
204 ERROR_EXIT(®cmp_lock
, arg_listp
, compile_startp
);
205 } else if (char_size
> 0) {
207 *compilep
= (unsigned char)START_OF_STRING_MARK
;
209 } else if /* (char_size == 0) && */ (next_argp
!= (char *)0) {
211 next_argp
= va_arg(arg_listp
, /* const */ char *);
212 char_size
= get_wchar(¤t_char
, regexp
);
213 if (char_size
<= 0) {
214 ERROR_EXIT(®cmp_lock
, arg_listp
,
219 *compilep
= (unsigned char)START_OF_STRING_MARK
;
222 /* ((char_size==0) && (next_argp==(char *)0)) */
224 * the regular expression is "^"
226 *compilep
= (unsigned char)START_OF_STRING_MARK
;
228 *compilep
= (unsigned char)END_REGEX
;
232 __i_size
= (int)(compilep
- compile_startp
);
234 lmutex_unlock(®cmp_lock
);
235 return (compile_startp
);
239 /* COMPILE THE REGULAR EXPRESSION */
243 can_repeat
= B_FALSE
;
247 * At the end of each iteration get the next character
248 * from the regular expression and increment regexp to
249 * point to the following character. Exit when all
250 * the characters in all the strings in the argument
251 * list have been read.
254 switch (current_char
) {
257 * No fall-through. Each case ends with either
258 * a break or an error exit. Each case starts
259 * with compilep addressing the next location to
260 * be written in the compiled regular expression,
261 * and with regexp addressing the next character
262 * to be read from the regular expression being
263 * compiled. Each case that doesn't return
264 * increments regexp to address the next character
265 * to be read from the regular expression and
266 * increments compilep to address the next
267 * location to be written in the compiled
268 * regular expression.
270 * NOTE: The comments for each case give the meaning
271 * of the regular expression compiled by the case
272 * and the character string written to the compiled
273 * regular expression by the case. Each single
275 * written to the compiled regular expression is
276 * shown enclosed in angle brackets (<>). Each
277 * compiled regular expression begins with a marker
278 * character which is shown as a named constant
279 * (e.g. <ASCII_CHAR>). Character constants are
280 * shown enclosed in single quotes (e.g. <'$'>).
281 * All other single characters written to the
282 * compiled regular expression are shown as lower
283 * case variable names (e.g. <ascii_char> or
284 * <multibyte_char>). Multicharacter
285 * strings written to the compiled regular expression
286 * are shown as variable names followed by elipses
291 /* end of string marker or simple dollar sign */
292 /* compiles to <END_OF_STRING_MARK> or */
293 /* <ASCII_CHAR><'$'> */
295 char_size
= get_wchar(¤t_char
, regexp
);
296 if ((char_size
== 0) && (next_argp
== (char *)0)) {
297 can_repeat
= B_FALSE
;
298 *compilep
= (unsigned char)END_OF_STRING_MARK
;
302 *compilep
= (unsigned char)ASCII_CHAR
;
303 regex_typep
= compilep
;
305 *compilep
= DOLLAR_SIGN
;
308 break; /* end case DOLLAR_SIGN */
310 case DOT
: /* any character */
312 /* compiles to <ANY_CHAR> */
315 *compilep
= (unsigned char)ANY_CHAR
;
316 regex_typep
= compilep
;
319 break; /* end case DOT */
321 case BACKSLASH
: /* escaped character */
324 * compiles to <ASCII_CHAR><ascii_char> or
325 * <MULTIBYTE_CHAR><multibyte_char>
328 char_size
= get_wchar(¤t_char
, regexp
);
329 if (char_size
<= 0) {
330 ERROR_EXIT(®cmp_lock
, arg_listp
,
335 expr_length
= add_single_char_expr(
336 compilep
, current_char
);
337 regex_typep
= compilep
;
338 compilep
+= expr_length
;
340 break; /* end case '\\' */
342 case LEFT_SQUARE_BRACKET
:
343 /* start of a character class expression */
346 * [^...c...] compiles to
347 * <NOT_IN_CLASS><class_length><...c...>
348 * [^...a-z...] compiles to
349 * <NOT_IN_CLASS><class_length><...a<THRU>z...>
350 * [...c...] compiles to
351 * <IN_CLASS><class_length><...c...>
352 * [...a-z...] compiles to
353 * <IN_CLASS><class_length><...a<THRU>z...>
355 * NOTE: <class_length> includes the
356 * <class_length> byte
360 regex_typep
= compilep
;
362 /* DETERMINE THE CLASS TYPE */
365 * NOTE: This algorithm checks the value of the
367 * macro in <euc.h> (included in <widec.h> )
368 * to find out if regcmp()
369 * is compiling the regular expression in a
372 char_size
= get_wchar(¤t_char
, regexp
);
373 if (char_size
<= 0) {
374 ERROR_EXIT(®cmp_lock
, arg_listp
,
376 } else if (current_char
== CIRCUMFLEX
) {
378 char_size
= get_wchar(¤t_char
, regexp
);
379 if (char_size
<= 0) {
380 ERROR_EXIT(®cmp_lock
,
381 arg_listp
, compile_startp
);
385 *compilep
= (unsigned char)
386 NOT_IN_ASCII_CHAR_CLASS
;
388 *compilep
= (unsigned char)
389 NOT_IN_MULTIBYTE_CHAR_CLASS
;
391 /* leave space for <class_length> */
397 *compilep
= (unsigned char)
400 *compilep
= (unsigned char)
401 IN_MULTIBYTE_CHAR_CLASS
;
403 /* leave space for <class_length> */
407 /* COMPILE THE CLASS */
409 * check for a leading right square bracket,
413 if (current_char
== RIGHT_SQUARE_BRACKET
) {
415 * the leading RIGHT_SQUARE_BRACKET may
416 * be part of a character range
417 * expression like "[]-\]"
419 dash_indicates_range
= B_TRUE
;
420 first_char_in_range
= current_char
;
421 char_size
= get_wchar(¤t_char
, regexp
);
422 if (char_size
<= 0) {
423 ERROR_EXIT(®cmp_lock
,
424 arg_listp
, compile_startp
);
427 *compilep
= RIGHT_SQUARE_BRACKET
;
432 * decode the character in the following
433 * while loop and decide then if it can
434 * be the first character
435 * in a character range expression
437 dash_indicates_range
= B_FALSE
;
440 while (current_char
!= RIGHT_SQUARE_BRACKET
) {
441 if (current_char
!= DASH
) {
443 * if a DASH follows current_char,
444 * current_char, the DASH and the
445 * character that follows the DASH
446 * may form a character range
449 dash_indicates_range
= B_TRUE
;
450 first_char_in_range
= current_char
;
451 expr_length
= add_char(
452 compilep
, current_char
);
453 compilep
+= expr_length
;
455 } else if /* (current_char == DASH) && */
456 (dash_indicates_range
== B_FALSE
) {
458 * current_char is a DASH, but
459 * either begins the entire
460 * character class or follows a
461 * character that's already
462 * part of a character range
463 * expression, so it simply
464 * represents the DASH character
470 * if another DASH follows this
471 * one, this DASH is part
472 * of a character range expression
475 dash_indicates_range
= B_TRUE
;
476 first_char_in_range
= current_char
;
480 * ((current_char == DASH &&/
481 * (dash_indicates_range == B_TRUE))
485 * the DASH appears after a single
486 * character that isn't
487 * already part of a character
488 * range expression, so it
489 * and the characters preceding
490 * and following it can form a
491 * character range expression
494 char_size
= get_wchar(
495 ¤t_char
, regexp
);
496 if (char_size
<= 0) {
497 ERROR_EXIT(®cmp_lock
,
498 arg_listp
, compile_startp
);
500 } else if (current_char
==
501 RIGHT_SQUARE_BRACKET
) {
503 * the preceding DASH is
504 * the last character in the
505 * class and represents the
506 * DASH character itself
511 } else if (valid_range(
513 current_char
) == B_FALSE
) {
514 ERROR_EXIT(®cmp_lock
,
515 arg_listp
, compile_startp
);
518 * the DASH is part of a
520 * expression; encode the
521 * rest of the expression
524 *compilep
= (unsigned char)
527 expr_length
= add_char(
528 compilep
, current_char
);
529 compilep
+= expr_length
;
531 * if a DASH follows this
534 * it represents the DASH
537 dash_indicates_range
=
542 /* GET THE NEXT CHARACTER */
544 char_size
= get_wchar(¤t_char
, regexp
);
545 if (char_size
<= 0) {
546 ERROR_EXIT(®cmp_lock
,
547 arg_listp
, compile_startp
);
553 /* end while (current_char != RIGHT_SQUARE_BRACKET) */
555 /* INSERT THE LENGTH OF THE CLASS INTO THE */
556 /* COMPILED EXPRESSION */
558 class_length
= (unsigned int)
559 (compilep
- regex_typep
- 1);
560 if ((class_length
< 2) ||
561 (class_length
> MAX_SINGLE_BYTE_INT
)) {
562 ERROR_EXIT(®cmp_lock
, arg_listp
,
565 *(regex_typep
+ 1) = (unsigned char)
568 break; /* end case LEFT_SQUARE_BRACKET */
573 * start of a parenthesized group of regular
574 * expressions compiles to <'\0'><'\0'>, leaving
575 * space in the compiled regular expression for
576 * <group_type|ADDED_LENGTH_BITS><group_length>
579 if (push_compilep(compilep
) == (char *)0) {
581 * groups can contain groups, so group
583 * must be saved and restored in sequence
585 ERROR_EXIT(®cmp_lock
, arg_listp
,
588 can_repeat
= B_FALSE
;
589 *compilep
= '\0'; /* for debugging */
591 *compilep
= '\0'; /* for debugging */
594 break; /* end case LEFT_PAREN */
597 /* end of a marked group of regular expressions */
600 * (<regex>)$0-9 compiles to
601 * <SAVED_GROUP><substringn><compiled_regex...>\
602 * <END_SAVED_GROUP><substringn><return_arg_number>
603 * (<regex>)* compiles to
604 * <ZERO_OR_MORE_GROUP|ADDED_LENGTH_BITS>
605 * <group_length> <compiled_regex...>
606 * <END_GROUP|ZERO_OR_MORE><groupn>
607 * (<regex>)+ compiles to
608 * <ONE_OR_MORE_GROUP|ADDED_LENGTH_BITS>
610 * <compiled_regex...><END_GROUP|ONE_OR_MORE>
612 * (<regex>){...} compiles to
613 * <COUNTED_GROUP|ADDED_LENGTH_BITS><group_length>\
614 * <compiled_regex...><END_GROUP|COUNT><groupn>\
615 * <minimum_repeat_count><maximum_repeat_count>
616 * otherwise (<regex>) compiles to
617 * <SIMPLE_GROUP><blank><compiled_regex...>
618 * <END_GROUP><groupn>
622 * group_length + (256 * ADDED_LENGTH_BITS) ==
623 * length_of(<compiled_regex...><END_GROUP|...>
626 * length_of(<group_type|ADDED_LENGTH_BITS>
627 * <group_length>\ <compiled_regex...>)
628 * groupn no longer seems to be used, but the code
629 * still computes it to preserve backward
631 * with earlier versions of regex().
634 /* RETRIEVE THE ADDRESS OF THE START OF THE GROUP */
636 regex_typep
= pop_compilep();
637 if (regex_typep
== (char *)0) {
638 ERROR_EXIT(®cmp_lock
, arg_listp
,
641 char_size
= get_wchar(¤t_char
, regexp
);
643 ERROR_EXIT(®cmp_lock
, arg_listp
,
645 } else if (char_size
== 0) {
646 *regex_typep
= SIMPLE_GROUP
;
648 *compilep
= (unsigned char)END_GROUP
;
649 regex_typep
= compilep
;
651 *compilep
= (unsigned char)groupn
;
654 } else if (current_char
== DOLLAR_SIGN
) {
655 *regex_typep
= SAVED_GROUP
;
657 *regex_typep
= (char)substringn
;
658 can_repeat
= B_FALSE
;
660 return_arg_number
= get_digit(regexp
);
661 if ((return_arg_number
< 0) ||
662 (substringn
>= NSUBSTRINGS
)) {
663 ERROR_EXIT(®cmp_lock
, arg_listp
,
667 *compilep
= (unsigned char)END_SAVED_GROUP
;
669 *compilep
= (unsigned char)substringn
;
672 *compilep
= (unsigned char)return_arg_number
;
675 switch (current_char
) {
677 *regex_typep
= ZERO_OR_MORE_GROUP
;
680 *regex_typep
= ONE_OR_MORE_GROUP
;
682 case LEFT_CURLY_BRACE
:
683 *regex_typep
= COUNTED_GROUP
;
686 *regex_typep
= SIMPLE_GROUP
;
688 if (*regex_typep
!= SIMPLE_GROUP
) {
689 group_length
= (unsigned int)
690 (compilep
- regex_typep
);
691 if (group_length
>= 1024) {
692 ERROR_EXIT(®cmp_lock
,
693 arg_listp
, compile_startp
);
695 high_bits
= group_length
>>
697 low_bits
= group_length
&
702 *regex_typep
| high_bits
);
705 (unsigned char)low_bits
;
708 *compilep
= (unsigned char)END_GROUP
;
709 regex_typep
= compilep
;
711 *compilep
= (unsigned char)groupn
;
716 break; /* end case RIGHT_PAREN */
718 case STAR
: /* zero or more repetitions of the */
719 /* preceding expression */
722 * <regex...>* compiles to <regex_type|ZERO_OR_MORE>\
723 * <compiled_regex...>
724 * (<regex...>)* compiles to
725 * <ZERO_OR_MORE_GROUP|ADDED_LENGTH_BITS>\
726 * <group_length><compiled_regex...>\
727 * <END_GROUP|ZERO_OR_MORE><groupn>
730 if (can_repeat
== B_FALSE
) {
731 ERROR_EXIT(®cmp_lock
, arg_listp
,
734 can_repeat
= B_FALSE
;
735 *regex_typep
= (unsigned char)
736 ((unsigned int)*regex_typep
| ZERO_OR_MORE
);
738 break; /* end case '*' */
741 /* one or more repetitions of the preceding */
745 * <regex...>+ compiles to <regex_type|ONE_OR_MORE>\
746 * <compiled_regex...> (<regex...>)+ compiles to
747 * <ONE_OR_MORE_GROUP|ADDED_LENGTH_BITS>\
748 * <group_length><compiled_regex...>\
749 * <END_GROUP|ONE_OR_MORE><groupn>
752 if (can_repeat
== B_FALSE
) {
753 ERROR_EXIT(®cmp_lock
, arg_listp
,
756 can_repeat
= B_FALSE
;
758 (unsigned char)((unsigned int)*
759 regex_typep
| ONE_OR_MORE
);
761 break; /* end case '+' */
763 case LEFT_CURLY_BRACE
:
766 * repeat the preceding regular expression
767 * at least min_count times
768 * and at most max_count times
770 * <regex...>{min_count} compiles to
771 * <regex type|COUNT><compiled_regex...>
772 * <min_count><min_count>
774 * <regex...>{min_count,} compiles to
775 * <regex type|COUNT><compiled_regex...>
776 * <min_count><UNLIMITED>
778 * <regex...>{min_count,max_count} compiles to
779 * <regex type>|COUNT><compiled_regex...>
780 * <min_count><max_count>
782 * (<regex...>){min_count,max_count} compiles to
783 * <COUNTED_GROUP|ADDED_LENGTH_BITS><group_length>\
784 * <compiled_regex...><END_GROUP|COUNT><groupn>\
785 * <minimum_match_count><maximum_match_count>
788 if (can_repeat
== B_FALSE
) {
789 ERROR_EXIT(®cmp_lock
, arg_listp
,
792 can_repeat
= B_FALSE
;
793 *regex_typep
= (unsigned char)((unsigned int)*
794 regex_typep
| COUNT
);
795 count_length
= get_count(&min_count
, regexp
);
796 if (count_length
<= 0) {
797 ERROR_EXIT(®cmp_lock
, arg_listp
,
800 regexp
+= count_length
;
802 if (*regexp
== RIGHT_CURLY_BRACE
) { /* {min_count} */
804 max_count
= min_count
;
805 } else if (*regexp
== COMMA
) { /* {min_count,..} */
808 if (*regexp
== RIGHT_CURLY_BRACE
) {
810 max_count
= UNLIMITED
;
811 } else { /* {min_count,max_count} */
812 count_length
= get_count(
814 if (count_length
<= 0) {
815 ERROR_EXIT(®cmp_lock
,
816 arg_listp
, compile_startp
);
818 regexp
+= count_length
;
819 if (*regexp
!= RIGHT_CURLY_BRACE
) {
820 ERROR_EXIT(®cmp_lock
,
821 arg_listp
, compile_startp
);
825 } else { /* invalid expression */
826 ERROR_EXIT(®cmp_lock
, arg_listp
,
830 if ((min_count
> MAX_SINGLE_BYTE_INT
) ||
831 ((max_count
!= UNLIMITED
) &&
832 (min_count
> max_count
))) {
833 ERROR_EXIT(®cmp_lock
, arg_listp
,
836 *compilep
= (unsigned char)min_count
;
838 *compilep
= (unsigned char)max_count
;
841 break; /* end case LEFT_CURLY_BRACE */
843 default: /* a single non-special character */
846 * compiles to <ASCII_CHAR><ascii_char> or
847 * <MULTIBYTE_CHAR><multibyte_char>
851 regex_typep
= compilep
;
852 expr_length
= add_single_char_expr(compilep
,
854 compilep
+= expr_length
;
856 } /* end switch (current_char) */
858 /* GET THE NEXT CHARACTER FOR THE WHILE LOOP */
860 char_size
= get_wchar(¤t_char
, regexp
);
862 ERROR_EXIT(®cmp_lock
, arg_listp
, compile_startp
);
863 } else if (char_size
> 0) {
865 } else if /* (char_size == 0) && */ (next_argp
!= (char *)0) {
867 next_argp
= va_arg(arg_listp
, /* const */ char *);
868 char_size
= get_wchar(¤t_char
, regexp
);
869 if (char_size
<= 0) {
870 ERROR_EXIT(®cmp_lock
, arg_listp
,
875 } else /* ((char_size == 0) && (next_argp == (char *)0)) */ {
876 if (pop_compilep() != (char *)0) {
877 /* unmatched parentheses */
878 ERROR_EXIT(®cmp_lock
, arg_listp
,
881 *compilep
= (unsigned char)END_REGEX
;
885 __i_size
= (int)(compilep
- compile_startp
);
887 lmutex_unlock(®cmp_lock
);
888 return (compile_startp
);
895 /* DEFINITIONS OF PRIVATE FUNCTIONS */
898 add_char(char *compilep
, wchar_t wchar
)
902 if ((unsigned int)wchar
<= (unsigned int)0x7f) {
903 *compilep
= (unsigned char)wchar
;
906 expr_length
= wctomb(compilep
, wchar
);
908 return (expr_length
);
912 add_single_char_expr(char *compilep
, wchar_t wchar
)
916 if ((unsigned int)wchar
<= (unsigned int)0x7f) {
917 *compilep
= (unsigned char)ASCII_CHAR
;
919 *compilep
= (unsigned char)wchar
;
922 *compilep
= (unsigned char)MULTIBYTE_CHAR
;
925 expr_length
+= wctomb(compilep
, wchar
);
927 return (expr_length
);
931 get_count(int *countp
, const char *regexp
)
933 char count_char
= '0';
935 int count_length
= 0;
937 if (regexp
== (char *)0) {
940 count_char
= *regexp
;
941 while (('0' <= count_char
) && (count_char
<= '9')) {
942 count
= (10 * count
) + (int)(count_char
- '0');
945 count_char
= *regexp
;
949 return (count_length
);
953 get_digit(const char *regexp
)
957 if (regexp
== (char *)0) {
961 if (('0' <= digit
) && (digit
<= '9')) {
962 return ((int)(digit
- '0'));
970 get_wchar(wchar_t *wcharp
, const char *regexp
)
974 if (regexp
== (char *)0) {
976 *wcharp
= (wchar_t)((unsigned int)'\0');
977 } else if (*regexp
== '\0') {
979 *wcharp
= (wchar_t)((unsigned int)*regexp
);
980 } else if ((unsigned char)*regexp
<= (unsigned char)0x7f) {
982 *wcharp
= (wchar_t)((unsigned int)*regexp
);
984 char_size
= mbtowc(wcharp
, regexp
, MB_LEN_MAX
);
994 if (compilep_stackp
>= &compilep_stack
[STRINGP_STACK_SIZE
]) {
997 compilep
= *compilep_stackp
;
1004 push_compilep(char *compilep
)
1006 if (compilep_stackp
<= &compilep_stack
[0]) {
1010 *compilep_stackp
= compilep
;
1016 valid_range(wchar_t lower_char
, wchar_t upper_char
)
1018 return (((lower_char
<= 0x7f) && (upper_char
<= 0x7f) &&
1019 !iswcntrl(lower_char
) && !iswcntrl(upper_char
) &&
1020 (lower_char
< upper_char
)) ||
1021 (((lower_char
& WCHAR_CSMASK
) ==
1022 (upper_char
& WCHAR_CSMASK
)) &&
1023 (lower_char
< upper_char
)));