~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/regex/regc_locale.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

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