]> git.saurik.com Git - wxWidgets.git/blame - src/regex/regc_locale.c
new (for wxBase) or updated and (hopefully() improved Watcom makefiles
[wxWidgets.git] / src / regex / regc_locale.c
CommitLineData
830efc9b
RN
1/*
2 * regc_locale.c --
3 *
4 * This file contains locale-specific regexp routines.
5 * This file is #included by regcomp.c.
6 *
7 * Copyright (c) 1998 by Scriptics Corporation.
8 *
9 * This software is copyrighted by the Regents of the University of
10 * California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
11 * Corporation and other parties. The following terms apply to all files
12 * associated with the software unless explicitly disclaimed in
13 * individual files.
14 *
15 * The authors hereby grant permission to use, copy, modify, distribute,
16 * and license this software and its documentation for any purpose, provided
17 * that existing copyright notices are retained in all copies and that this
18 * notice is included verbatim in any distributions. No written agreement,
19 * license, or royalty fee is required for any of the authorized uses.
20 * Modifications to this software may be copyrighted by their authors
21 * and need not follow the licensing terms described here, provided that
22 * the new terms are clearly indicated on the first page of each file where
23 * they apply.
24 *
25 * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
26 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
27 * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
28 * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
34 * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
35 * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
36 * MODIFICATIONS.
37 *
38 * GOVERNMENT USE: If you are acquiring this software on behalf of the
39 * U.S. government, the Government shall have only "Restricted Rights"
40 * in the software and related documentation as defined in the Federal
41 * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
42 * are acquiring the software on behalf of the Department of Defense, the
43 * software shall be classified as "Commercial Computer Software" and the
44 * Government shall have only "Restricted Rights" as defined in Clause
45 * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
46 * authors grant the U.S. Government and others acting in its behalf
47 * permission to use and distribute the software in accordance with the
48 * terms specified in this license.
49 *
50 * $Header$
51 */
52
53int char_and_wchar_strncmp (const char* cp, const wx_wchar* wp, size_t nNum)
54{
55 while(*cp++ == (const char)*wp++ && --nNum){}
56
57 return nNum;
58}
59
60/* ASCII character-name table */
61
62static struct cname
63{
64 char *name;
65 char code;
66} cnames[] =
67
68{
69 {
70 "NUL", '\0'
71 },
72 {
73 "SOH", '\001'
74 },
75 {
76 "STX", '\002'
77 },
78 {
79 "ETX", '\003'
80 },
81 {
82 "EOT", '\004'
83 },
84 {
85 "ENQ", '\005'
86 },
87 {
88 "ACK", '\006'
89 },
90 {
91 "BEL", '\007'
92 },
93 {
94 "alert", '\007'
95 },
96 {
97 "BS", '\010'
98 },
99 {
100 "backspace", '\b'
101 },
102 {
103 "HT", '\011'
104 },
105 {
106 "tab", '\t'
107 },
108 {
109 "LF", '\012'
110 },
111 {
112 "newline", '\n'
113 },
114 {
115 "VT", '\013'
116 },
117 {
118 "vertical-tab", '\v'
119 },
120 {
121 "FF", '\014'
122 },
123 {
124 "form-feed", '\f'
125 },
126 {
127 "CR", '\015'
128 },
129 {
130 "carriage-return", '\r'
131 },
132 {
133 "SO", '\016'
134 },
135 {
136 "SI", '\017'
137 },
138 {
139 "DLE", '\020'
140 },
141 {
142 "DC1", '\021'
143 },
144 {
145 "DC2", '\022'
146 },
147 {
148 "DC3", '\023'
149 },
150 {
151 "DC4", '\024'
152 },
153 {
154 "NAK", '\025'
155 },
156 {
157 "SYN", '\026'
158 },
159 {
160 "ETB", '\027'
161 },
162 {
163 "CAN", '\030'
164 },
165 {
166 "EM", '\031'
167 },
168 {
169 "SUB", '\032'
170 },
171 {
172 "ESC", '\033'
173 },
174 {
175 "IS4", '\034'
176 },
177 {
178 "FS", '\034'
179 },
180 {
181 "IS3", '\035'
182 },
183 {
184 "GS", '\035'
185 },
186 {
187 "IS2", '\036'
188 },
189 {
190 "RS", '\036'
191 },
192 {
193 "IS1", '\037'
194 },
195 {
196 "US", '\037'
197 },
198 {
199 "space", ' '
200 },
201 {
202 "exclamation-mark", '!'
203 },
204 {
205 "quotation-mark", '"'
206 },
207 {
208 "number-sign", '#'
209 },
210 {
211 "dollar-sign", '$'
212 },
213 {
214 "percent-sign", '%'
215 },
216 {
217 "ampersand", '&'
218 },
219 {
220 "apostrophe", '\''
221 },
222 {
223 "left-parenthesis", '('
224 },
225 {
226 "right-parenthesis", ')'
227 },
228 {
229 "asterisk", '*'
230 },
231 {
232 "plus-sign", '+'
233 },
234 {
235 "comma", ','
236 },
237 {
238 "hyphen", '-'
239 },
240 {
241 "hyphen-minus", '-'
242 },
243 {
244 "period", '.'
245 },
246 {
247 "full-stop", '.'
248 },
249 {
250 "slash", '/'
251 },
252 {
253 "solidus", '/'
254 },
255 {
256 "zero", '0'
257 },
258 {
259 "one", '1'
260 },
261 {
262 "two", '2'
263 },
264 {
265 "three", '3'
266 },
267 {
268 "four", '4'
269 },
270 {
271 "five", '5'
272 },
273 {
274 "six", '6'
275 },
276 {
277 "seven", '7'
278 },
279 {
280 "eight", '8'
281 },
282 {
283 "nine", '9'
284 },
285 {
286 "colon", ':'
287 },
288 {
289 "semicolon", ';'
290 },
291 {
292 "less-than-sign", '<'
293 },
294 {
295 "equals-sign", '='
296 },
297 {
298 "greater-than-sign", '>'
299 },
300 {
301 "question-mark", '?'
302 },
303 {
304 "commercial-at", '@'
305 },
306 {
307 "left-square-bracket", '['
308 },
309 {
310 "backslash", '\\'
311 },
312 {
313 "reverse-solidus", '\\'
314 },
315 {
316 "right-square-bracket", ']'
317 },
318 {
319 "circumflex", '^'
320 },
321 {
322 "circumflex-accent", '^'
323 },
324 {
325 "underscore", '_'
326 },
327 {
328 "low-line", '_'
329 },
330 {
331 "grave-accent", '`'
332 },
333 {
334 "left-brace", '{'
335 },
336 {
337 "left-curly-bracket", '{'
338 },
339 {
340 "vertical-line", '|'
341 },
342 {
343 "right-brace", '}'
344 },
345 {
346 "right-curly-bracket", '}'
347 },
348 {
349 "tilde", '~'
350 },
351 {
352 "DEL", '\177'
353 },
354 {
355 NULL, 0
356 }
357};
358
359/*
360 * some ctype functions with non-ascii-char guard
361 */
362static int
363wx_isdigit(wx_wchar c)
364{
365 return (c >= 0 && c <= UCHAR_MAX && isdigit((unsigned char) c));
366}
367
368static int
369wx_isalpha(wx_wchar c)
370{
371 return (c >= 0 && c <= UCHAR_MAX && isalpha((unsigned char) c));
372}
373
374static int
375wx_isalnum(wx_wchar c)
376{
377 return (c >= 0 && c <= UCHAR_MAX && isalnum((unsigned char) c));
378}
379
380static int
381wx_isupper(wx_wchar c)
382{
383 return (c >= 0 && c <= UCHAR_MAX && isupper((unsigned char) c));
384}
385
386static int
387wx_islower(wx_wchar c)
388{
389 return (c >= 0 && c <= UCHAR_MAX && islower((unsigned char) c));
390}
391
392static int
393wx_isgraph(wx_wchar c)
394{
395 return (c >= 0 && c <= UCHAR_MAX && isgraph((unsigned char) c));
396}
397
398static int
399wx_ispunct(wx_wchar c)
400{
401 return (c >= 0 && c <= UCHAR_MAX && ispunct((unsigned char) c));
402}
403
404static int
405wx_isspace(wx_wchar c)
406{
407 return (c >= 0 && c <= UCHAR_MAX && isspace((unsigned char) c));
408}
409
410static wx_wchar
411wx_toupper(wx_wchar c)
412{
413 if (c >= 0 && c <= UCHAR_MAX)
414 return toupper((unsigned char) c);
415 return c;
416}
417
418static wx_wchar
419wx_tolower(wx_wchar c)
420{
421 if (c >= 0 && c <= UCHAR_MAX)
422 return tolower((unsigned char) c);
423 return c;
424}
425
426
427/*
428 * nmcces - how many distinct MCCEs are there?
429 */
430static int
431nmcces(struct vars * v)
432{
433 /*
434 * No multi-character collating elements defined at the moment.
435 */
436 return 0;
437}
438
439/*
440 * nleaders - how many chrs can be first chrs of MCCEs?
441 */
442static int
443nleaders(struct vars * v)
444{
445 return 0;
446}
447
448/*
449 * allmcces - return a cvec with all the MCCEs of the locale
450 */
451static struct cvec *
452allmcces(struct vars * v, /* context */
453 struct cvec * cv) /* this is supposed to have enough room */
454{
455 return clearcvec(cv);
456}
457
458/*
459 * element - map collating-element name to celt
460 */
461static celt
462element(struct vars * v, /* context */
463 chr *startp, /* points to start of name */
464 chr *endp) /* points just past end of name */
465{
466 struct cname *cn;
467 size_t len;
468
469 /* generic: one-chr names stand for themselves */
470 assert(startp < endp);
471 len = endp - startp;
472 if (len == 1)
473 return *startp;
474
475 NOTE(REG_ULOCALE);
476
477 /* search table */
478 for (cn = cnames; cn->name != NULL; cn++)
479 {
480 if (strlen(cn->name) == len &&
481 char_and_wchar_strncmp(cn->name, startp, len) == 0)
482 {
483 break; /* NOTE BREAK OUT */
484 }
485 }
486 if (cn->name != NULL)
487 return CHR(cn->code);
488
489 /* couldn't find it */
490 ERR(REG_ECOLLATE);
491 return 0;
492}
493
494/*
495 * range - supply cvec for a range, including legality check
496 */
497static struct cvec *
498range(struct vars * v, /* context */
499 celt a, /* range start */
500 celt b, /* range end, might equal a */
501 int cases) /* case-independent? */
502{
503 int nchrs;
504 struct cvec *cv;
505 celt c,
506 lc,
507 uc;
508
509 if (a != b && !before(a, b))
510 {
511 ERR(REG_ERANGE);
512 return NULL;
513 }
514
515 if (!cases)
516 { /* easy version */
517 cv = getcvec(v, 0, 1, 0);
518 NOERRN();
519 addrange(cv, a, b);
520 return cv;
521 }
522
523 /*
524 * When case-independent, it's hard to decide when cvec ranges are
525 * usable, so for now at least, we won't try. We allocate enough
526 * space for two case variants plus a little extra for the two title
527 * case variants.
528 */
529
530 nchrs = (b - a + 1) * 2 + 4;
531
532 cv = getcvec(v, nchrs, 0, 0);
533 NOERRN();
534
535 for (c = a; c <= b; c++)
536 {
537 addchr(cv, c);
538 lc = wx_tolower((chr) c);
539 if (c != lc)
540 addchr(cv, lc);
541 uc = wx_toupper((chr) c);
542 if (c != uc)
543 addchr(cv, uc);
544 }
545
546 return cv;
547}
548
549/*
550 * before - is celt x before celt y, for purposes of range legality?
551 */
552static int /* predicate */
553before(celt x, celt y)
554{
555 /* trivial because no MCCEs */
556 if (x < y)
557 return 1;
558 return 0;
559}
560
561/*
562 * eclass - supply cvec for an equivalence class
563 * Must include case counterparts on request.
564 */
565static struct cvec *
566eclass(struct vars * v, /* context */
567 celt c, /* Collating element representing the
568 * equivalence class. */
569 int cases) /* all cases? */
570{
571 struct cvec *cv;
572
573 /* crude fake equivalence class for testing */
574 if ((v->cflags & REG_FAKE) && c == 'x')
575 {
576 cv = getcvec(v, 4, 0, 0);
577 addchr(cv, (chr) 'x');
578 addchr(cv, (chr) 'y');
579 if (cases)
580 {
581 addchr(cv, (chr) 'X');
582 addchr(cv, (chr) 'Y');
583 }
584 return cv;
585 }
586
587 /* otherwise, none */
588 if (cases)
589 return allcases(v, c);
590 cv = getcvec(v, 1, 0, 0);
591 assert(cv != NULL);
592 addchr(cv, (chr) c);
593 return cv;
594}
595
596/*
597 * cclass - supply cvec for a character class
598 *
599 * Must include case counterparts on request.
600 */
601static struct cvec *
602cclass(struct vars * v, /* context */
603 chr *startp, /* where the name starts */
604 chr *endp, /* just past the end of the name */
605 int cases) /* case-independent? */
606{
607 size_t len;
608 struct cvec *cv = NULL;
609 char **namePtr;
610 int i,
611 index;
612
613 /*
614 * The following arrays define the valid character class names.
615 */
616
617 static char *classNames[] = {
618 "alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph",
619 "lower", "print", "punct", "space", "upper", "xdigit", NULL
620 };
621
622 enum classes
623 {
624 CC_ALNUM, CC_ALPHA, CC_ASCII, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH,
625 CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_XDIGIT
626 };
627
628 /*
629 * Map the name to the corresponding enumerated value.
630 */
631 len = endp - startp;
632 index = -1;
633 for (namePtr = classNames, i = 0; *namePtr != NULL; namePtr++, i++)
634 {
635 if (strlen(*namePtr) == len &&
636 char_and_wchar_strncmp(*namePtr, startp, len) == 0)
637 {
638 index = i;
639 break;
640 }
641 }
642 if (index == -1)
643 {
644 ERR(REG_ECTYPE);
645 return NULL;
646 }
647
648 /*
649 * Remap lower and upper to alpha if the match is case insensitive.
650 */
651
652 if (cases &&
653 ((enum classes) index == CC_LOWER ||
654 (enum classes) index == CC_UPPER))
655 index = (int) CC_ALPHA;
656
657 /*
658 * Now compute the character class contents.
659 *
660 * For the moment, assume that only char codes < 256 can be in these
661 * classes.
662 */
663
664 switch ((enum classes) index)
665 {
666 case CC_PRINT:
667 case CC_ALNUM:
668 cv = getcvec(v, UCHAR_MAX, 1, 0);
669 if (cv)
670 {
671 for (i = 0; i <= UCHAR_MAX; i++)
672 {
673 if (wx_isalpha((chr) i))
674 addchr(cv, (chr) i);
675 }
676 addrange(cv, (chr) '0', (chr) '9');
677 }
678 break;
679 case CC_ALPHA:
680 cv = getcvec(v, UCHAR_MAX, 0, 0);
681 if (cv)
682 {
683 for (i = 0; i <= UCHAR_MAX; i++)
684 {
685 if (wx_isalpha((chr) i))
686 addchr(cv, (chr) i);
687 }
688 }
689 break;
690 case CC_ASCII:
691 cv = getcvec(v, 0, 1, 0);
692 if (cv)
693 addrange(cv, 0, 0x7f);
694 break;
695 case CC_BLANK:
696 cv = getcvec(v, 2, 0, 0);
697 addchr(cv, '\t');
698 addchr(cv, ' ');
699 break;
700 case CC_CNTRL:
701 cv = getcvec(v, 0, 2, 0);
702 addrange(cv, 0x0, 0x1f);
703 addrange(cv, 0x7f, 0x9f);
704 break;
705 case CC_DIGIT:
706 cv = getcvec(v, 0, 1, 0);
707 if (cv)
708 addrange(cv, (chr) '0', (chr) '9');
709 break;
710 case CC_PUNCT:
711 cv = getcvec(v, UCHAR_MAX, 0, 0);
712 if (cv)
713 {
714 for (i = 0; i <= UCHAR_MAX; i++)
715 {
716 if (wx_ispunct((chr) i))
717 addchr(cv, (chr) i);
718 }
719 }
720 break;
721 case CC_XDIGIT:
722 cv = getcvec(v, 0, 3, 0);
723 if (cv)
724 {
725 addrange(cv, '0', '9');
726 addrange(cv, 'a', 'f');
727 addrange(cv, 'A', 'F');
728 }
729 break;
730 case CC_SPACE:
731 cv = getcvec(v, UCHAR_MAX, 0, 0);
732 if (cv)
733 {
734 for (i = 0; i <= UCHAR_MAX; i++)
735 {
736 if (wx_isspace((chr) i))
737 addchr(cv, (chr) i);
738 }
739 }
740 break;
741 case CC_LOWER:
742 cv = getcvec(v, UCHAR_MAX, 0, 0);
743 if (cv)
744 {
745 for (i = 0; i <= UCHAR_MAX; i++)
746 {
747 if (wx_islower((chr) i))
748 addchr(cv, (chr) i);
749 }
750 }
751 break;
752 case CC_UPPER:
753 cv = getcvec(v, UCHAR_MAX, 0, 0);
754 if (cv)
755 {
756 for (i = 0; i <= UCHAR_MAX; i++)
757 {
758 if (wx_isupper((chr) i))
759 addchr(cv, (chr) i);
760 }
761 }
762 break;
763 case CC_GRAPH:
764 cv = getcvec(v, UCHAR_MAX, 0, 0);
765 if (cv)
766 {
767 for (i = 0; i <= UCHAR_MAX; i++)
768 {
769 if (wx_isgraph((chr) i))
770 addchr(cv, (chr) i);
771 }
772 }
773 break;
774 }
775 if (cv == NULL)
776 ERR(REG_ESPACE);
777 return cv;
778}
779
780/*
781 * allcases - supply cvec for all case counterparts of a chr (including itself)
782 *
783 * This is a shortcut, preferably an efficient one, for simple characters;
784 * messy cases are done via range().
785 */
786static struct cvec *
787allcases(struct vars * v, /* context */
788 chr pc) /* character to get case equivs of */
789{
790 struct cvec *cv;
791 chr c = (chr) pc;
792 chr lc,
793 uc;
794
795 lc = wx_tolower((chr) c);
796 uc = wx_toupper((chr) c);
797
798 cv = getcvec(v, 2, 0, 0);
799 addchr(cv, lc);
800 if (lc != uc)
801 addchr(cv, uc);
802 return cv;
803}
804
805/*
806 * cmp - chr-substring compare
807 *
808 * Backrefs need this. It should preferably be efficient.
809 * Note that it does not need to report anything except equal/unequal.
810 * Note also that the length is exact, and the comparison should not
811 * stop at embedded NULs!
812 */
813static int /* 0 for equal, nonzero for unequal */
814cmp(const chr *x, const chr *y, /* strings to compare */
815 size_t len) /* exact length of comparison */
816{
817 return memcmp(VS(x), VS(y), len * sizeof(chr));
818}
819
820/*
821 * casecmp - case-independent chr-substring compare
822 *
823 * REG_ICASE backrefs need this. It should preferably be efficient.
824 * Note that it does not need to report anything except equal/unequal.
825 * Note also that the length is exact, and the comparison should not
826 * stop at embedded NULs!
827 */
828static int /* 0 for equal, nonzero for unequal */
829casecmp(const chr *x, const chr *y, /* strings to compare */
830 size_t len) /* exact length of comparison */
831{
832 for (; len > 0; len--, x++, y++)
833 {
834 if ((*x != *y) && (wx_tolower(*x) != wx_tolower(*y)))
835 return 1;
836 }
837 return 0;
838}