OSDN Git Service

pgindent run.
[pg-rex/syncrep.git] / src / backend / regex / regcomp.c
index da4f202..71e69de 100644 (file)
  *             @(#)regcomp.c   8.5 (Berkeley) 3/20/94
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)regcomp.c  8.5 (Berkeley) 3/20/94";
+#include "postgres.h"
 
-#endif                                                 /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
 #include <ctype.h>
 #include <limits.h>
-#include <stdlib.h>
 #include <assert.h>
 
-#include <regex/regex.h>
-#include <regex/utils.h>
-#include <regex/regex2.h>
-#include <regex/cclass.h>
-#include <regex/cname.h>
+#include "regex/regex.h"
+#include "regex/utils.h"
+#include "regex/regex2.h"
+#include "regex/cname.h"
+#include <locale.h>
+
+struct cclass
+{
+       char       *name;
+       char       *chars;
+       char       *multis;
+};
+static struct cclass *cclasses = NULL;
+static struct cclass *cclass_init(void);
 
 /*
  * parse structure, passed up and down to avoid global variables and
@@ -62,8 +64,8 @@ static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94";
  */
 struct parse
 {
-       char       *next;                       /* next character in RE */
-       char       *end;                        /* end of string (-> NUL normally) */
+       pg_wchar   *next;                       /* next character in RE */
+       pg_wchar   *end;                        /* end of string (-> NUL normally) */
        int                     error;                  /* has an error been seen? */
        sop                *strip;                      /* malloced strip */
        sopno           ssize;                  /* malloced strip size (allocated) */
@@ -76,58 +78,54 @@ struct parse
        sopno           pend[NPAREN];   /* -> ) ([0] unused) */
 };
 
-/* ========= begin header generated by ./mkh ========= */
-#ifdef __cplusplus
-extern         "C"
-{
-#endif
-
-/* === regcomp.c === */
-       static void p_ere(struct parse * p, int stop);
-       static void p_ere_exp(struct parse * p);
-       static void p_str(struct parse * p);
-       static void p_bre(struct parse * p, int end1, int end2);
-       static int      p_simp_re(struct parse * p, int starordinary);
-       static int      p_count(struct parse * p);
-       static void p_bracket(struct parse * p);
-       static void p_b_term(struct parse * p, cset * cs);
-       static void p_b_cclass(struct parse * p, cset * cs);
-       static void p_b_eclass(struct parse * p, cset * cs);
-       static char p_b_symbol(struct parse * p);
-       static char p_b_coll_elem(struct parse * p, int endc);
-       static char othercase(int ch);
-       static void bothcases(struct parse * p, int ch);
-       static void ordinary(struct parse * p, int ch);
-       static void nonnewline(struct parse * p);
-       static void repeat(struct parse * p, sopno start, int from, int to);
-       static int      seterr(struct parse * p, int e);
-       static cset *allocset(struct parse * p);
-       static void freeset(struct parse * p, cset * cs);
-       static int      freezeset(struct parse * p, cset * cs);
-       static int      firstch(struct parse * p, cset * cs);
-       static int      nch(struct parse * p, cset * cs);
-       static void mcadd(struct parse * p, cset * cs, char *cp);
-       static void mcinvert(struct parse * p, cset * cs);
-       static void mccase(struct parse * p, cset * cs);
-       static int      isinsets(struct re_guts * g, int c);
-       static int      samesets(struct re_guts * g, int c1, int c2);
-       static void categorize(struct parse * p, struct re_guts * g);
-       static sopno dupl(struct parse * p, sopno start, sopno finish);
-       static void doemit(struct parse * p, sop op, size_t opnd);
-       static void doinsert(struct parse * p, sop op, size_t opnd, sopno pos);
-       static void dofwd(struct parse * p, sopno pos, sop value);
-       static void enlarge(struct parse * p, sopno size);
-       static void stripsnug(struct parse * p, struct re_guts * g);
-       static void findmust(struct parse * p, struct re_guts * g);
-       static sopno pluscount(struct parse * p, struct re_guts * g);
-
-#ifdef __cplusplus
-}
-
-#endif
-/* ========= end header generated by ./mkh ========= */
-
-static char nuls[10];                  /* place to point scanner in event of
+static void p_ere(struct parse * p, int stop);
+static void p_ere_exp(struct parse * p);
+static void p_str(struct parse * p);
+static void p_bre(struct parse * p, int end1, int end2);
+static int     p_simp_re(struct parse * p, int starordinary);
+static int     p_count(struct parse * p);
+static void p_bracket(struct parse * p);
+static void p_b_term(struct parse * p, cset *cs);
+static void p_b_cclass(struct parse * p, cset *cs);
+static void p_b_eclass(struct parse * p, cset *cs);
+static pg_wchar p_b_symbol(struct parse * p);
+static char p_b_coll_elem(struct parse * p, int endc);
+static unsigned char othercase(int ch);
+static void bothcases(struct parse * p, int ch);
+static void ordinary(struct parse * p, int ch);
+static void nonnewline(struct parse * p);
+static void repeat(struct parse * p, sopno start, int from, int to);
+static int     seterr(struct parse * p, int e);
+static cset *allocset(struct parse * p);
+static void freeset(struct parse * p, cset *cs);
+static int     freezeset(struct parse * p, cset *cs);
+static int     firstch(struct parse * p, cset *cs);
+static int     nch(struct parse * p, cset *cs);
+static void mcadd(struct parse * p, cset *cs, char *cp);
+static void mcinvert(struct parse * p, cset *cs);
+static void mccase(struct parse * p, cset *cs);
+static int     isinsets(struct re_guts * g, int c);
+static int     samesets(struct re_guts * g, int c1, int c2);
+static void categorize(struct parse * p, struct re_guts * g);
+static sopno dupl(struct parse * p, sopno start, sopno finish);
+static void doemit(struct parse * p, sop op, size_t opnd);
+static void doinsert(struct parse * p, sop op, size_t opnd, sopno pos);
+static void dofwd(struct parse * p, sopno pos, sop value);
+static void enlarge(struct parse * p, sopno size);
+static void stripsnug(struct parse * p, struct re_guts * g);
+static void findmust(struct parse * p, struct re_guts * g);
+static sopno pluscount(struct parse * p, struct re_guts * g);
+static int     pg_isdigit(int c);
+static int     pg_isalpha(int c);
+static int     pg_isalnum(int c);
+static int     pg_isupper(int c);
+static int     pg_islower(int c);
+static int     pg_iscntrl(int c);
+static int     pg_isgraph(int c);
+static int     pg_isprint(int c);
+static int     pg_ispunct(int c);
+
+static pg_wchar nuls[10];              /* place to point scanner in event of
                                                                 * error */
 
 /*
@@ -168,28 +166,21 @@ static int        never = 0;                      /* for use in asserts; shuts lint up */
 #endif
 
 /*
- - regcomp - interface for parser and compilation
- = extern int regcomp(regex_t *, const char *, int);
- = #define             REG_BASIC               0000
- = #define             REG_EXTENDED    0001
- = #define             REG_ICASE               0002
- = #define             REG_NOSUB               0004
- = #define             REG_NEWLINE             0010
- = #define             REG_NOSPEC              0020
- = #define             REG_PEND                0040
- = #define             REG_DUMP                0200
+ * regcomp - interface for parser and compilation
+ * returns 0 success, otherwise REG_something
  */
-int                                                            /* 0 success, otherwise REG_something */
-pg95_regcomp(preg, pattern, cflags)
-regex_t    *preg;
-const char *pattern;
-int                    cflags;
+int
+pg_regcomp(regex_t *preg, const char *pattern, int cflags)
 {
        struct parse pa;
-       register struct re_guts *g;
-       register struct parse *p = &pa;
-       register int i;
-       register size_t len;
+       struct re_guts *g;
+       struct parse *p = &pa;
+       int                     i;
+       size_t          len;
+       pg_wchar   *wcp;
+
+       if (cclasses == NULL)
+               cclasses = cclass_init();
 
 #ifdef REDEBUG
 #define  GOODFLAGS(f)   (f)
@@ -199,22 +190,30 @@ int                       cflags;
 
        cflags = GOODFLAGS(cflags);
        if ((cflags & REG_EXTENDED) && (cflags & REG_NOSPEC))
-               return (REG_INVARG);
+               return REG_INVARG;
 
        if (cflags & REG_PEND)
        {
-               if (preg->re_endp < pattern)
-                       return (REG_INVARG);
-               len = preg->re_endp - pattern;
+               wcp = preg->patsave;
+               if (preg->re_endp < wcp)
+                       return REG_INVARG;
+               len = preg->re_endp - wcp;
        }
        else
-               len = strlen((char *) pattern);
+       {
+               wcp = (pg_wchar *) malloc((strlen(pattern) + 1) * sizeof(pg_wchar));
+               if (wcp == NULL)
+                       return REG_ESPACE;
+               preg->patsave = wcp;
+               (void) pg_mb2wchar((unsigned char *) pattern, wcp);
+               len = pg_wchar_strlen(wcp);
+       }
 
        /* do the mallocs early so failure handling is easy */
        g = (struct re_guts *) malloc(sizeof(struct re_guts) +
                                                                  (NC - 1) * sizeof(cat_t));
        if (g == NULL)
-               return (REG_ESPACE);
+               return REG_ESPACE;
        p->ssize = len / (size_t) 2 *(size_t) 3 + (size_t) 1;           /* ugh */
 
        p->strip = (sop *) malloc(p->ssize * sizeof(sop));
@@ -222,12 +221,12 @@ int                       cflags;
        if (p->strip == NULL)
        {
                free((char *) g);
-               return (REG_ESPACE);
+               return REG_ESPACE;
        }
 
        /* set things up */
        p->g = g;
-       p->next = (char *) pattern; /* convenience; we do not modify it */
+       p->next = wcp;
        p->end = p->next + len;
        p->error = 0;
        p->ncsalloc = 0;
@@ -281,24 +280,22 @@ int                       cflags;
 
        /* win or lose, we're done */
        if (p->error != 0)                      /* lose */
-               pg95_regfree(preg);
-       return (p->error);
+               pg_regfree(preg);
+       return p->error;
 }
 
 /*
- - p_ere - ERE parser top level, concatenation and alternation
- == static void p_ere(register struct parse *p, int stop);
+ * p_ere - ERE parser top level, concatenation and alternation
  */
 static void
-p_ere(p, stop)
-register struct parse *p;
-int                    stop;                           /* character this ERE should end at */
+p_ere(struct parse * p,
+         int stop)                                     /* character this ERE should end at */
 {
-       register char c;
-       register sopno prevback = 0;
-       register sopno prevfwd = 0;
-       register sopno conc;
-       register int first = 1;         /* is this the first alternative? */
+       char            c;
+       sopno           prevback = 0;
+       sopno           prevfwd = 0;
+       sopno           conc;
+       int                     first = 1;              /* is this the first alternative? */
 
        for (;;)
        {
@@ -335,18 +332,16 @@ int                       stop;                           /* character this ERE should end at */
 }
 
 /*
- - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
- == static void p_ere_exp(register struct parse *p);
+ * p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
  */
 static void
-p_ere_exp(p)
-register struct parse *p;
+p_ere_exp(struct parse * p)
 {
-       register char c;
-       register sopno pos;
-       register int count;
-       register int count2;
-       register sopno subno;
+       pg_wchar        c;
+       sopno           pos;
+       int                     count;
+       int                     count2;
+       sopno           subno;
        int                     wascaret = 0;
 
        assert(MORE());                         /* caller should have ensured this */
@@ -420,7 +415,7 @@ register struct parse *p;
                        break;
                case '{':                               /* okay as ordinary except if digit
                                                                 * follows */
-                       REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT);
+                       REQUIRE(!MORE() || !pg_isdigit(PEEK()), REG_BADRPT);
                        /* FALLTHROUGH */
                default:
                        ordinary(p, c);
@@ -432,7 +427,7 @@ register struct parse *p;
        c = PEEK();
        /* we call { a repetition if followed by a digit */
        if (!(c == '*' || c == '+' || c == '?' ||
-                 (c == '{' && MORE2() && isdigit(PEEK2()))))
+                 (c == '{' && MORE2() && pg_isdigit(PEEK2()))))
                return;                                 /* no repetition, we're done */
        NEXT();
 
@@ -463,7 +458,7 @@ register struct parse *p;
                        count = p_count(p);
                        if (EAT(','))
                        {
-                               if (isdigit(PEEK()))
+                               if (pg_isdigit(PEEK()))
                                {
                                        count2 = p_count(p);
                                        REQUIRE(count <= count2, REG_BADBR);
@@ -490,18 +485,16 @@ register struct parse *p;
                return;
        c = PEEK();
        if (!(c == '*' || c == '+' || c == '?' ||
-                 (c == '{' && MORE2() && isdigit(PEEK2()))))
+                 (c == '{' && MORE2() && pg_isdigit(PEEK2()))))
                return;
        SETERROR(REG_BADRPT);
 }
 
 /*
- - p_str - string (no metacharacters) "parser"
- == static void p_str(register struct parse *p);
+ * p_str - string (no metacharacters) "parser"
  */
 static void
-p_str(p)
-register struct parse *p;
+p_str(struct parse * p)
 {
        REQUIRE(MORE(), REG_EMPTY);
        while (MORE())
@@ -509,9 +502,8 @@ register struct parse *p;
 }
 
 /*
- - p_bre - BRE parser top level, anchoring and concatenation
- == static void p_bre(register struct parse *p, register int end1, \
- ==            register int end2);
+ * p_bre - BRE parser top level, anchoring and concatenation
+ *
  * Giving end1 as OUT essentially eliminates the end1/end2 check.
  *
  * This implementation is a bit of a kludge, in that a trailing $ is first
@@ -521,14 +513,13 @@ register struct parse *p;
  * The amount of lookahead needed to avoid this kludge is excessive.
  */
 static void
-p_bre(p, end1, end2)
-register struct parse *p;
-register int end1;                             /* first terminating character */
-register int end2;                             /* second terminating character */
+p_bre(struct parse * p,
+         int end1,                                     /* first terminating character */
+         int end2)                                     /* second terminating character */
 {
-       register sopno start = HERE();
-       register int first = 1;         /* first subexpression? */
-       register int wasdollar = 0;
+       sopno           start = HERE();
+       int                     first = 1;              /* first subexpression? */
+       int                     wasdollar = 0;
 
        if (EAT('^'))
        {
@@ -553,22 +544,20 @@ register int end2;                                /* second terminating character */
 }
 
 /*
- - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
- == static int p_simp_re(register struct parse *p, int starordinary);
+ * p_simp_re - parse a simple RE, an atom possibly followed by a repetition
  */
 static int                                             /* was the simple RE an unbackslashed $? */
-p_simp_re(p, starordinary)
-register struct parse *p;
-int                    starordinary;           /* is a leading * an ordinary character? */
+p_simp_re(struct parse * p,
+                 int starordinary)             /* is a leading * an ordinary character? */
 {
-       register int c;
-       register int count;
-       register int count2;
-       register sopno pos;
-       register int i;
-       register sopno subno;
+       int                     c;
+       int                     count;
+       int                     count2;
+       sopno           pos;
+       int                     i;
+       sopno           subno;
 
-#define  BACKSL  (1<<CHAR_BIT)
+#define  BACKSL  (1<<24)
 
        pos = HERE();                           /* repetion op, if any, covers from here */
 
@@ -577,7 +566,7 @@ int                 starordinary;           /* is a leading * an ordinary character? */
        if (c == '\\')
        {
                REQUIRE(MORE(), REG_EESCAPE);
-               c = BACKSL | (unsigned char) GETNEXT();
+               c = BACKSL | (pg_wchar) GETNEXT();
        }
        switch (c)
        {
@@ -660,7 +649,7 @@ int                 starordinary;           /* is a leading * an ordinary character? */
                count = p_count(p);
                if (EAT(','))
                {
-                       if (MORE() && isdigit(PEEK()))
+                       if (MORE() && pg_isdigit(PEEK()))
                        {
                                count2 = p_count(p);
                                REQUIRE(count <= count2, REG_BADBR);
@@ -682,54 +671,53 @@ int                       starordinary;           /* is a leading * an ordinary character? */
                }
        }
        else if (c == (unsigned char) '$')      /* $ (but not \$) ends it */
-               return (1);
+               return 1;
 
-       return (0);
+       return 0;
 }
 
 /*
- - p_count - parse a repetition count
- == static int p_count(register struct parse *p);
+ * p_count - parse a repetition count
  */
 static int                                             /* the value */
-p_count(p)
-register struct parse *p;
+p_count(struct parse * p)
 {
-       register int count = 0;
-       register int ndigits = 0;
+       int                     count = 0;
+       int                     ndigits = 0;
 
-       while (MORE() && isdigit(PEEK()) && count <= DUPMAX)
+       while (MORE() && pg_isdigit(PEEK()) && count <= DUPMAX)
        {
                count = count * 10 + (GETNEXT() - '0');
                ndigits++;
        }
 
        REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
-       return (count);
+       return count;
 }
 
 /*
- - p_bracket - parse a bracketed character list
- == static void p_bracket(register struct parse *p);
+ * p_bracket - parse a bracketed character list
  *
  * Note a significant property of this code:  if the allocset() did SETERROR,
  * no set operations are done.
  */
 static void
-p_bracket(p)
-register struct parse *p;
+p_bracket(struct parse * p)
 {
-       register cset *cs = allocset(p);
-       register int invert = 0;
+       cset       *cs = allocset(p);
+       int                     invert = 0;
+
+       pg_wchar        sp1[] = {'[', ':', '<', ':', ']', ']'};
+       pg_wchar        sp2[] = {'[', ':', '>', ':', ']', ']'};
 
        /* Dept of Truly Sickening Special-Case Kludges */
-       if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0)
+       if (p->next + 5 < p->end && pg_wchar_strncmp(p->next, sp1, 6) == 0)
        {
                EMIT(OBOW, 0);
                NEXTn(6);
                return;
        }
-       if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0)
+       if (p->next + 5 < p->end && pg_wchar_strncmp(p->next, sp2, 6) == 0)
        {
                EMIT(OEOW, 0);
                NEXTn(6);
@@ -753,11 +741,11 @@ register struct parse *p;
 
        if (p->g->cflags & REG_ICASE)
        {
-               register int i;
-               register int ci;
+               int                     i;
+               int                     ci;
 
                for (i = p->g->csetsize - 1; i >= 0; i--)
-                       if (CHIN(cs, i) && isalpha(i))
+                       if (CHIN(cs, i) && pg_isalpha(i))
                        {
                                ci = othercase(i);
                                if (ci != i)
@@ -768,7 +756,7 @@ register struct parse *p;
        }
        if (invert)
        {
-               register int i;
+               int                     i;
 
                for (i = p->g->csetsize - 1; i >= 0; i--)
                        if (CHIN(cs, i))
@@ -793,18 +781,15 @@ register struct parse *p;
 }
 
 /*
- - p_b_term - parse one term of a bracketed character list
- == static void p_b_term(register struct parse *p, register cset *cs);
+ * p_b_term - parse one term of a bracketed character list
  */
 static void
-p_b_term(p, cs)
-register struct parse *p;
-register cset *cs;
+p_b_term(struct parse * p, cset *cs)
 {
-       register char c;
-       register char start,
+       pg_wchar        c;
+       pg_wchar        start,
                                finish;
-       register int i;
+       int                     i;
 
        /* classify what we've got */
        switch ((MORE()) ? PEEK() : '\0')
@@ -857,6 +842,10 @@ register cset *cs;
                                finish = start;
 /* xxx what about signed chars here... */
                        REQUIRE(start <= finish, REG_ERANGE);
+
+                       if (CHlc(start) != CHlc(finish))
+                               SETERROR(REG_ERANGE);
+
                        for (i = start; i <= finish; i++)
                                CHadd(cs, i);
                        break;
@@ -864,26 +853,25 @@ register cset *cs;
 }
 
 /*
- - p_b_cclass - parse a character-class name and deal with it
- == static void p_b_cclass(register struct parse *p, register cset *cs);
+ * p_b_cclass - parse a character-class name and deal with it
  */
 static void
-p_b_cclass(p, cs)
-register struct parse *p;
-register cset *cs;
+p_b_cclass(struct parse * p, cset *cs)
 {
-       register char *sp = p->next;
-       register struct cclass *cp;
-       register size_t len;
-       register char *u;
-       register char c;
+       pg_wchar   *sp = p->next;
+       struct cclass *cp;
+       size_t          len;
+       char       *u;
+       unsigned char c;
 
-       while (MORE() && isalpha(PEEK()))
+       while (MORE() && pg_isalpha(PEEK()))
                NEXT();
        len = p->next - sp;
+
        for (cp = cclasses; cp->name != NULL; cp++)
-               if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+               if (pg_char_and_wchar_strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
                        break;
+
        if (cp->name == NULL)
        {
                /* oops, didn't find it */
@@ -899,106 +887,95 @@ register cset *cs;
 }
 
 /*
- - p_b_eclass - parse an equivalence-class name and deal with it
- == static void p_b_eclass(register struct parse *p, register cset *cs);
+ * p_b_eclass - parse an equivalence-class name and deal with it
  *
  * This implementation is incomplete. xxx
  */
 static void
-p_b_eclass(p, cs)
-register struct parse *p;
-register cset *cs;
+p_b_eclass(struct parse * p, cset *cs)
 {
-       register char c;
+       char            c;
 
        c = p_b_coll_elem(p, '=');
        CHadd(cs, c);
 }
 
 /*
- - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
- == static char p_b_symbol(register struct parse *p);
+ * p_b_symbol - parse a character or [..]ed multicharacter collating symbol
  */
-static char                                            /* value of symbol */
-p_b_symbol(p)
-register struct parse *p;
+static pg_wchar                                        /* value of symbol */
+p_b_symbol(struct parse * p)
 {
-       register char value;
+       pg_wchar        value;
 
        REQUIRE(MORE(), REG_EBRACK);
        if (!EATTWO('[', '.'))
-               return (GETNEXT());
+               return GETNEXT();
 
        /* collating symbol */
        value = p_b_coll_elem(p, '.');
        REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
-       return (value);
+       return value;
 }
 
 /*
- - p_b_coll_elem - parse a collating-element name and look it up
- == static char p_b_coll_elem(register struct parse *p, int endc);
+ * p_b_coll_elem - parse a collating-element name and look it up
  */
 static char                                            /* value of collating element */
-p_b_coll_elem(p, endc)
-register struct parse *p;
-int                    endc;                           /* name ended by endc,']' */
+p_b_coll_elem(struct parse * p, int endc)
 {
-       register char *sp = p->next;
-       register struct cname *cp;
-       register int len;
+       pg_wchar   *sp = p->next;
+       struct cname *cp;
+       int                     len;
 
        while (MORE() && !SEETWO(endc, ']'))
                NEXT();
        if (!MORE())
        {
                SETERROR(REG_EBRACK);
-               return (0);
+               return 0;
        }
        len = p->next - sp;
+
        for (cp = cnames; cp->name != NULL; cp++)
-               if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
-                       return (cp->code);      /* known name */
+               if (pg_char_and_wchar_strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+                       return cp->code;        /* known name */
+
        if (len == 1)
-               return (*sp);                   /* single character */
+               return *sp;                             /* single character */
        SETERROR(REG_ECOLLATE);         /* neither */
-       return (0);
+       return 0;
 }
 
 /*
- - othercase - return the case counterpart of an alphabetic
- == static char othercase(int ch);
+ * othercase - return the case counterpart of an alphabetic
  */
-static char                                            /* if no counterpart, return ch */
-othercase(ch)
-int                    ch;
+static unsigned char                   /* if no counterpart, return ch */
+othercase(int ch)
 {
-       assert(isalpha(ch));
-       if (isupper(ch))
-               return (tolower(ch));
-       else if (islower(ch))
-               return (toupper(ch));
+       assert(pg_isalpha(ch));
+       if (pg_isupper(ch))
+               return (unsigned char) tolower((unsigned char) ch);
+       else if (pg_islower(ch))
+               return (unsigned char) toupper((unsigned char) ch);
        else
 /* peculiar, but could happen */
-               return (ch);
+               return (unsigned char) ch;
 }
 
 /*
- - bothcases - emit a dualcase version of a two-case character
- == static void bothcases(register struct parse *p, int ch);
+ * bothcases - emit a dualcase version of a two-case character
  *
  * Boy, is this implementation ever a kludge...
  */
 static void
-bothcases(p, ch)
-register struct parse *p;
-int                    ch;
+bothcases(struct parse * p, int ch)
 {
-       register char *oldnext = p->next;
-       register char *oldend = p->end;
-       char            bracket[3];
+       pg_wchar   *oldnext = p->next;
+       pg_wchar   *oldend = p->end;
+       pg_wchar        bracket[3];
 
-       assert(othercase(ch) != ch);/* p_bracket() would recurse */
+       assert(othercase(ch) != ch);    /* p_bracket() would recurse */
        p->next = bracket;
        p->end = bracket + 2;
        bracket[0] = ch;
@@ -1011,39 +988,34 @@ int                      ch;
 }
 
 /*
- - ordinary - emit an ordinary character
- == static void ordinary(register struct parse *p, register int ch);
+ * ordinary - emit an ordinary character
  */
 static void
-ordinary(p, ch)
-register struct parse *p;
-register int ch;
+ordinary(struct parse * p, int ch)
 {
-       register cat_t *cap = p->g->categories;
+       cat_t      *cap = p->g->categories;
 
-       if ((p->g->cflags & REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+       if ((p->g->cflags & REG_ICASE) && pg_isalpha(ch) && othercase(ch) != ch)
                bothcases(p, ch);
        else
        {
-               EMIT(OCHAR, (unsigned char) ch);
-               if (cap[ch] == 0)
+               EMIT(OCHAR, (pg_wchar) ch);
+               if (ch >= CHAR_MIN && ch <= CHAR_MAX && cap[ch] == 0)
                        cap[ch] = p->g->ncategories++;
        }
 }
 
 /*
- - nonnewline - emit REG_NEWLINE version of OANY
- == static void nonnewline(register struct parse *p);
+ * nonnewline - emit REG_NEWLINE version of OANY
  *
  * Boy, is this implementation ever a kludge...
  */
 static void
-nonnewline(p)
-register struct parse *p;
+nonnewline(struct parse * p)
 {
-       register char *oldnext = p->next;
-       register char *oldend = p->end;
-       char            bracket[4];
+       pg_wchar   *oldnext = p->next;
+       pg_wchar   *oldend = p->end;
+       pg_wchar        bracket[4];
 
        p->next = bracket;
        p->end = bracket + 3;
@@ -1058,24 +1030,22 @@ register struct parse *p;
 }
 
 /*
- - repeat - generate code for a bounded repetition, recursively if needed
- == static void repeat(register struct parse *p, sopno start, int from, int to);
+ * repeat - generate code for a bounded repetition, recursively if needed
  */
 static void
-repeat(p, start, from, to)
-register struct parse *p;
-sopno          start;                          /* operand from here to end of strip */
-int                    from;                           /* repeated from this number */
-int                    to;                                     /* to this number of times (maybe
+repeat(struct parse * p,
+          sopno start,                         /* operand from here to end of strip */
+          int from,                            /* repeated from this number */
+          int to)                                      /* to this number of times (maybe
                                                                 * INFINITY) */
 {
-       register sopno finish = HERE();
+       sopno           finish = HERE();
 
 #define  N              2
 #define  INF    3
 #define  REP(f, t)              ((f)*8 + (t))
 #define  MAP(n)  (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
-       register sopno copy;
+       sopno           copy;
 
        if (p->error != 0)                      /* head off possible runaway recursion */
                return;
@@ -1091,7 +1061,7 @@ int                       to;                                     /* to this number of times (maybe
                case REP(0, N): /* as x{1,n}? */
                case REP(0, INF):               /* as x{1,}? */
                        /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
-                       INSERT(OCH_, start);/* offset is wrong... */
+                       INSERT(OCH_, start);    /* offset is wrong... */
                        repeat(p, start + 1, 1, to);
                        ASTERN(OOR1, start);
                        AHEAD(start);           /* ... fix it */
@@ -1133,35 +1103,30 @@ int                     to;                                     /* to this number of times (maybe
 }
 
 /*
- - seterr - set an error condition
- == static int seterr(register struct parse *p, int e);
+ * seterr - set an error condition
  */
 static int                                             /* useless but makes type checking happy */
-seterr(p, e)
-register struct parse *p;
-int                    e;
+seterr(struct parse * p, int e)
 {
        if (p->error == 0)                      /* keep earliest error condition */
                p->error = e;
        p->next = nuls;                         /* try to bring things to a halt */
        p->end = nuls;
-       return (0);                                     /* make the return value well-defined */
+       return 0;                                       /* make the return value well-defined */
 }
 
 /*
- - allocset - allocate a set of characters for []
- == static cset *allocset(register struct parse *p);
+ * allocset - allocate a set of characters for []
  */
 static cset *
-allocset(p)
-register struct parse *p;
+allocset(struct parse * p)
 {
-       register int no = p->g->ncsets++;
-       register size_t nc;
-       register size_t nbytes;
-       register cset *cs;
-       register size_t css = (size_t) p->g->csetsize;
-       register int i;
+       int                     no = p->g->ncsets++;
+       size_t          nc;
+       size_t          nbytes;
+       cset       *cs;
+       size_t          css = (size_t) p->g->csetsize;
+       int                     i;
 
        if (no >= p->ncsalloc)
        {                                                       /* need another column of space */
@@ -1203,21 +1168,18 @@ register struct parse *p;
        cs->smultis = 0;
        cs->multis = NULL;
 
-       return (cs);
+       return cs;
 }
 
 /*
- - freeset - free a now-unused set
- == static void freeset(register struct parse *p, register cset *cs);
+ * freeset - free a now-unused set
  */
 static void
-freeset(p, cs)
-register struct parse *p;
-register cset *cs;
+freeset(struct parse * p, cset *cs)
 {
-       register int i;
-       register cset *top = &p->g->sets[p->g->ncsets];
-       register size_t css = (size_t) p->g->csetsize;
+       int                     i;
+       cset       *top = &p->g->sets[p->g->ncsets];
+       size_t          css = (size_t) p->g->csetsize;
 
        for (i = 0; i < css; i++)
                CHsub(cs, i);
@@ -1226,8 +1188,7 @@ register cset *cs;
 }
 
 /*
- - freezeset - final processing on a set of characters
- == static int freezeset(register struct parse *p, register cset *cs);
+ * freezeset - final processing on a set of characters
  *
  * The main task here is merging identical sets.  This is usually a waste
  * of time (although the hash code minimizes the overhead), but can win
@@ -1236,15 +1197,13 @@ register cset *cs;
  * the same value!
  */
 static int                                             /* set number */
-freezeset(p, cs)
-register struct parse *p;
-register cset *cs;
+freezeset(struct parse * p, cset *cs)
 {
-       register uch h = cs->hash;
-       register int i;
-       register cset *top = &p->g->sets[p->g->ncsets];
-       register cset *cs2;
-       register size_t css = (size_t) p->g->csetsize;
+       uch                     h = cs->hash;
+       int                     i;
+       cset       *top = &p->g->sets[p->g->ncsets];
+       cset       *cs2;
+       size_t          css = (size_t) p->g->csetsize;
 
        /* look for an earlier one which is the same */
        for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
@@ -1264,59 +1223,48 @@ register cset *cs;
                cs = cs2;
        }
 
-       return ((int) (cs - p->g->sets));
+       return (int) (cs - p->g->sets);
 }
 
 /*
- - firstch - return first character in a set (which must have at least one)
- == static int firstch(register struct parse *p, register cset *cs);
+ * firstch - return first character in a set (which must have at least one)
  */
 static int                                             /* character; there is no "none" value */
-firstch(p, cs)
-register struct parse *p;
-register cset *cs;
+firstch(struct parse * p, cset *cs)
 {
-       register int i;
-       register size_t css = (size_t) p->g->csetsize;
+       int                     i;
+       size_t          css = (size_t) p->g->csetsize;
 
        for (i = 0; i < css; i++)
                if (CHIN(cs, i))
-                       return ((char) i);
+                       return i;
        assert(never);
-       return (0);                                     /* arbitrary */
+       return 0;                                       /* arbitrary */
 }
 
 /*
- - nch - number of characters in a set
- == static int nch(register struct parse *p, register cset *cs);
+ * nch - number of characters in a set
  */
 static int
-nch(p, cs)
-register struct parse *p;
-register cset *cs;
+nch(struct parse * p, cset *cs)
 {
-       register int i;
-       register size_t css = (size_t) p->g->csetsize;
-       register int n = 0;
+       int                     i;
+       size_t          css = (size_t) p->g->csetsize;
+       int                     n = 0;
 
        for (i = 0; i < css; i++)
                if (CHIN(cs, i))
                        n++;
-       return (n);
+       return n;
 }
 
 /*
- - mcadd - add a collating element to a cset
- == static void mcadd(register struct parse *p, register cset *cs, \
- ==            register char *cp);
+ * mcadd - add a collating element to a cset
  */
 static void
-mcadd(p, cs, cp)
-register struct parse *p;
-register cset *cs;
-register char *cp;
+mcadd(struct parse * p, cset *cs, char *cp)
 {
-       register size_t oldend = cs->smultis;
+       size_t          oldend = cs->smultis;
 
        cs->smultis += strlen(cp) + 1;
        if (cs->multis == NULL)
@@ -1334,153 +1282,74 @@ register char *cp;
 }
 
 /*
- - mcsub - subtract a collating element from a cset
- == static void mcsub(register cset *cs, register char *cp);
- */
-/*
-static void
-mcsub(cs, cp)
-register cset *cs;
-register char *cp;
-{
-               register char *fp = mcfind(cs, cp);
-               register size_t len = strlen(fp);
-
-               assert(fp != NULL);
-               memmove(fp, fp + len + 1,
-                                                               cs->smultis - (fp + len + 1 - cs->multis));
-               cs->smultis -= len;
-
-               if (cs->smultis == 0) {
-                               free(cs->multis);
-                               cs->multis = NULL;
-                               return;
-               }
-
-               cs->multis = realloc(cs->multis, cs->smultis);
-               assert(cs->multis != NULL);
-}
-*/
-
-/*
- - mcin - is a collating element in a cset?
- == static int mcin(register cset *cs, register char *cp);
- */
-/*
-static int
-mcin(cs, cp)
-register cset *cs;
-register char *cp;
-{
-               return(mcfind(cs, cp) != NULL);
-}
-*/
-
-/*
- - mcfind - find a collating element in a cset
- == static char *mcfind(register cset *cs, register char *cp);
- */
-/*
-static char *
-mcfind(cs, cp)
-register cset *cs;
-register char *cp;
-{
-               register char *p;
-
-               if (cs->multis == NULL)
-                               return(NULL);
-               for (p = cs->multis; *p != '\0'; p += strlen(p) + 1)
-                               if (strcmp(cp, p) == 0)
-                                               return(p);
-               return(NULL);
-}
-*/
-/*
- - mcinvert - invert the list of collating elements in a cset
- == static void mcinvert(register struct parse *p, register cset *cs);
+ * mcinvert - invert the list of collating elements in a cset
  *
  * This would have to know the set of possibilities.  Implementation
  * is deferred.
  */
 static void
-mcinvert(p, cs)
-register struct parse *p;
-register cset *cs;
+mcinvert(struct parse * p, cset *cs)
 {
        assert(cs->multis == NULL); /* xxx */
 }
 
 /*
- - mccase - add case counterparts of the list of collating elements in a cset
- == static void mccase(register struct parse *p, register cset *cs);
+ * mccase - add case counterparts of the list of collating elements in a cset
  *
  * This would have to know the set of possibilities.  Implementation
  * is deferred.
  */
 static void
-mccase(p, cs)
-register struct parse *p;
-register cset *cs;
+mccase(struct parse * p, cset *cs)
 {
        assert(cs->multis == NULL); /* xxx */
 }
 
 /*
- - isinsets - is this character in any sets?
- == static int isinsets(register struct re_guts *g, int c);
+ * isinsets - is this character in any sets?
  */
 static int                                             /* predicate */
-isinsets(g, c)
-register struct re_guts *g;
-int                    c;
+isinsets(struct re_guts * g, int c)
 {
-       register uch *col;
-       register int i;
-       register int ncols = (g->ncsets + (CHAR_BIT - 1)) / CHAR_BIT;
-       register unsigned uc = (unsigned char) c;
+       uch                *col;
+       int                     i;
+       int                     ncols = (g->ncsets + (CHAR_BIT - 1)) / CHAR_BIT;
+       unsigned        uc = (unsigned char) c;
 
        for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
                if (col[uc] != 0)
-                       return (1);
-       return (0);
+                       return 1;
+       return 0;
 }
 
 /*
- - samesets - are these two characters in exactly the same sets?
- == static int samesets(register struct re_guts *g, int c1, int c2);
+ * samesets - are these two characters in exactly the same sets?
  */
 static int                                             /* predicate */
-samesets(g, c1, c2)
-register struct re_guts *g;
-int                    c1;
-int                    c2;
+samesets(struct re_guts * g, int c1, int c2)
 {
-       register uch *col;
-       register int i;
-       register int ncols = (g->ncsets + (CHAR_BIT - 1)) / CHAR_BIT;
-       register unsigned uc1 = (unsigned char) c1;
-       register unsigned uc2 = (unsigned char) c2;
+       uch                *col;
+       int                     i;
+       int                     ncols = (g->ncsets + (CHAR_BIT - 1)) / CHAR_BIT;
+       unsigned        uc1 = (unsigned char) c1;
+       unsigned        uc2 = (unsigned char) c2;
 
        for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
                if (col[uc1] != col[uc2])
-                       return (0);
-       return (1);
+                       return 0;
+       return 1;
 }
 
 /*
- - categorize - sort out character categories
- == static void categorize(struct parse *p, register struct re_guts *g);
+ * categorize - sort out character categories
  */
 static void
-categorize(p, g)
-struct parse *p;
-register struct re_guts *g;
+categorize(struct parse * p, struct re_guts * g)
 {
-       register cat_t *cats = g->categories;
-       register int c;
-       register int c2;
-       register cat_t cat;
+       cat_t      *cats = g->categories;
+       int                     c;
+       int                     c2;
+       cat_t           cat;
 
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1498,42 +1367,36 @@ register struct re_guts *g;
 }
 
 /*
- - dupl - emit a duplicate of a bunch of sops
- == static sopno dupl(register struct parse *p, sopno start, sopno finish);
+ * dupl - emit a duplicate of a bunch of sops
  */
-static sopno                   /* start of duplicate */
-dupl(p, start, finish)
-register struct parse *p;
-sopno          start;                          /* from here */
-sopno          finish;                         /* to this less one */
+static sopno                                   /* start of duplicate */
+dupl(struct parse * p,
+        sopno start,                           /* from here */
+        sopno finish)                          /* to this less one */
 {
-       register sopno ret = HERE();
-       register sopno len = finish - start;
+       sopno           ret = HERE();
+       sopno           len = finish - start;
 
        assert(finish >= start);
        if (len == 0)
-               return (ret);
+               return ret;
        enlarge(p, p->ssize + len); /* this many unexpected additions */
        assert(p->ssize >= p->slen + len);
        memcpy((char *) (p->strip + p->slen),
                   (char *) (p->strip + start), (size_t) len * sizeof(sop));
        p->slen += len;
-       return (ret);
+       return ret;
 }
 
 /*
- - doemit - emit a strip operator
- == static void doemit(register struct parse *p, sop op, size_t opnd);
+ * doemit - emit a strip operator
  *
  * It might seem better to implement this as a macro with a function as
  * hard-case backup, but it's just too big and messy unless there are
  * some changes to the data structures.  Maybe later.
  */
 static void
-doemit(p, op, opnd)
-register struct parse *p;
-sop                    op;
-size_t         opnd;
+doemit(struct parse * p, sop op, size_t opnd)
 {
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1552,19 +1415,14 @@ size_t          opnd;
 }
 
 /*
- - doinsert - insert a sop into the strip
- == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+ * doinsert - insert a sop into the strip
  */
 static void
-doinsert(p, op, opnd, pos)
-register struct parse *p;
-sop                    op;
-size_t         opnd;
-sopno          pos;
+doinsert(struct parse * p, sop op, size_t opnd, sopno pos)
 {
-       register sopno sn;
-       register sop s;
-       register int i;
+       sopno           sn;
+       sop                     s;
+       int                     i;
 
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1580,13 +1438,9 @@ sopno            pos;
        for (i = 1; i < NPAREN; i++)
        {
                if (p->pbegin[i] >= pos)
-               {
                        p->pbegin[i]++;
-               }
                if (p->pend[i] >= pos)
-               {
                        p->pend[i]++;
-               }
        }
 
        memmove((char *) &p->strip[pos + 1], (char *) &p->strip[pos],
@@ -1595,14 +1449,10 @@ sopno           pos;
 }
 
 /*
- - dofwd - complete a forward reference
- == static void dofwd(register struct parse *p, sopno pos, sop value);
+ * dofwd - complete a forward reference
  */
 static void
-dofwd(p, pos, value)
-register struct parse *p;
-register sopno pos;
-sop                    value;
+dofwd(struct parse * p, sopno pos, sop value)
 {
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1613,15 +1463,12 @@ sop                     value;
 }
 
 /*
- - enlarge - enlarge the strip
- == static void enlarge(register struct parse *p, sopno size);
+ * enlarge - enlarge the strip
  */
 static void
-enlarge(p, size)
-register struct parse *p;
-register sopno size;
+enlarge(struct parse * p, sopno size)
 {
-       register sop *sp;
+       sop                *sp;
 
        if (p->ssize >= size)
                return;
@@ -1637,13 +1484,10 @@ register sopno size;
 }
 
 /*
- - stripsnug - compact the strip
- == static void stripsnug(register struct parse *p, register struct re_guts *g);
+ * stripsnug - compact the strip
  */
 static void
-stripsnug(p, g)
-register struct parse *p;
-register struct re_guts *g;
+stripsnug(struct parse * p, struct re_guts * g)
 {
        g->nstates = p->slen;
        g->strip = (sop *) realloc((char *) p->strip, p->slen * sizeof(sop));
@@ -1655,8 +1499,7 @@ register struct re_guts *g;
 }
 
 /*
- - findmust - fill in must and mlen with longest mandatory literal string
- == static void findmust(register struct parse *p, register struct re_guts *g);
+ * findmust - fill in must and mlen with longest mandatory literal string
  *
  * This algorithm could do fancy things like analyzing the operands of |
  * for common subsequences.  Someday.  This code is simple and finds most
@@ -1665,17 +1508,15 @@ register struct re_guts *g;
  * Note that must and mlen got initialized during setup.
  */
 static void
-findmust(p, g)
-struct parse *p;
-register struct re_guts *g;
+findmust(struct parse * p, struct re_guts * g)
 {
-       register sop *scan;
+       sop                *scan;
        sop                *start = 0;
-       register sop *newstart = 0;
-       register sopno newlen;
-       register sop s;
-       register char *cp;
-       register sopno i;
+       sop                *newstart = 0;
+       sopno           newlen;
+       sop                     s;
+       pg_wchar   *cp;
+       sopno           i;
 
        /* avoid making error situations worse */
        if (p->error != 0)
@@ -1690,7 +1531,7 @@ register struct re_guts *g;
                switch (OP(s))
                {
                        case OCHAR: /* sequence member */
-                               if (newlen == 0)/* new sequence */
+                               if (newlen == 0)        /* new sequence */
                                        newstart = scan - 1;
                                newlen++;
                                break;
@@ -1729,7 +1570,7 @@ register struct re_guts *g;
                return;
 
        /* turn it into a character string */
-       g->must = malloc((size_t) g->mlen + 1);
+       g->must = (pg_wchar *) malloc((size_t) (g->mlen + 1) * sizeof(pg_wchar));
        if (g->must == NULL)
        {                                                       /* argh; just forget it */
                g->mlen = 0;
@@ -1742,28 +1583,25 @@ register struct re_guts *g;
                while (OP(s = *scan++) != OCHAR)
                        continue;
                assert(cp < g->must + g->mlen);
-               *cp++ = (char) OPND(s);
+               *cp++ = (pg_wchar) OPND(s);
        }
        assert(cp == g->must + g->mlen);
        *cp++ = '\0';                           /* just on general principles */
 }
 
 /*
- - pluscount - count + nesting
- == static sopno pluscount(register struct parse *p, register struct re_guts *g);
+ * pluscount - count + nesting
  */
-static sopno                   /* nesting depth */
-pluscount(p, g)
-struct parse *p;
-register struct re_guts *g;
+static sopno                                   /* nesting depth */
+pluscount(struct parse * p, struct re_guts * g)
 {
-       register sop *scan;
-       register sop s;
-       register sopno plusnest = 0;
-       register sopno maxnest = 0;
+       sop                *scan;
+       sop                     s;
+       sopno           plusnest = 0;
+       sopno           maxnest = 0;
 
        if (p->error != 0)
-               return (0);                             /* there may not be an OEND */
+               return 0;                               /* there may not be an OEND */
 
        scan = g->strip + 1;
        do
@@ -1783,5 +1621,168 @@ register struct re_guts *g;
        } while (OP(s) != OEND);
        if (plusnest != 0)
                g->iflags |= BAD;
-       return (maxnest);
+       return maxnest;
+}
+
+/*
+ * some ctype functions with non-ascii-char guard
+ */
+static int
+pg_isdigit(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && isdigit((unsigned char) c));
+}
+
+static int
+pg_isalpha(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && isalpha((unsigned char) c));
+}
+
+static int
+pg_isalnum(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && isalnum((unsigned char) c));
+}
+
+static int
+pg_isupper(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && isupper((unsigned char) c));
+}
+
+static int
+pg_islower(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && islower((unsigned char) c));
+}
+
+static int
+pg_iscntrl(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && iscntrl((unsigned char) c));
+}
+
+static int
+pg_isgraph(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && isgraph((unsigned char) c));
+}
+
+static int
+pg_isprint(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && isprint((unsigned char) c));
+}
+
+static int
+pg_ispunct(int c)
+{
+       return (c >= 0 && c <= UCHAR_MAX && ispunct((unsigned char) c));
+}
+
+static struct cclass *
+cclass_init(void)
+{
+       static struct cclass cclasses_C[] = {
+               {"alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", ""},
+               {"alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", ""},
+               {"blank", " \t", ""},
+               {"cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177", ""},
+               {"digit", "0123456789", ""},
+               {"graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ""},
+               {"lower", "abcdefghijklmnopqrstuvwxyz", ""},
+               {"print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", ""},
+               {"punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ""},
+               {"space", "\t\n\v\f\r ", ""},
+               {"upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", ""},
+               {"xdigit", "0123456789ABCDEFabcdef", ""},
+               {NULL, NULL, ""}
+       };
+       struct cclass *cp = NULL;
+       struct cclass *classes = NULL;
+       struct cclass_factory
+       {
+               char       *name;
+               int                     (*func) (int);
+               char       *chars;
+       }                       cclass_factories[] =
+       {
+               {
+                       "alnum", pg_isalnum, NULL
+               },
+               {
+                       "alpha", pg_isalpha, NULL
+               },
+               {
+                       "blank", NULL, " \t"
+               },
+               {
+                       "cntrl", pg_iscntrl, NULL
+               },
+               {
+                       "digit", NULL, "0123456789"
+               },
+               {
+                       "graph", pg_isgraph, NULL
+               },
+               {
+                       "lower", pg_islower, NULL
+               },
+               {
+                       "print", pg_isprint, NULL
+               },
+               {
+                       "punct", pg_ispunct, NULL
+               },
+               {
+                       "space", NULL, "\t\n\v\f\r "
+               },
+               {
+                       "upper", pg_isupper, NULL
+               },
+               {
+                       "xdigit", NULL, "0123456789ABCDEFabcdef"
+               },
+               {
+                       NULL, NULL, NULL
+               }
+       };
+       struct cclass_factory *cf = NULL;
+
+       if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
+               return cclasses_C;
+
+       classes = malloc(sizeof(struct cclass) * (sizeof(cclass_factories) / sizeof(struct cclass_factory)));
+       if (classes == NULL)
+               elog(ERROR, "cclass_init: out of memory");
+
+       cp = classes;
+       for (cf = cclass_factories; cf->name != NULL; cf++)
+       {
+               cp->name = strdup(cf->name);
+               if (cf->chars)
+                       cp->chars = strdup(cf->chars);
+               else
+               {
+                       int                     x = 0,
+                                               y = 0;
+
+                       cp->chars = malloc(sizeof(char) * 256);
+                       if (cp->chars == NULL)
+                               elog(ERROR, "cclass_init: out of memory");
+                       for (x = 0; x < 256; x++)
+                       {
+                               if ((cf->func) (x))
+                                       *(cp->chars + y++) = x;
+                       }
+                       *(cp->chars + y) = '\0';
+               }
+               cp->multis = "";
+               cp++;
+       }
+       cp->name = cp->chars = NULL;
+       cp->multis = "";
+
+       return classes;
 }