1 #include <sys/types.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <limits.h>
6 #include <stdlib.h>
7
8 #include "regex.h"
9 #include "utils.h"
10 #include "regerror.ih"
11 #include "php.h"
12
13 /*
14 = #define REG_OKAY 0
15 = #define REG_NOMATCH 1
16 = #define REG_BADPAT 2
17 = #define REG_ECOLLATE 3
18 = #define REG_ECTYPE 4
19 = #define REG_EESCAPE 5
20 = #define REG_ESUBREG 6
21 = #define REG_EBRACK 7
22 = #define REG_EPAREN 8
23 = #define REG_EBRACE 9
24 = #define REG_BADBR 10
25 = #define REG_ERANGE 11
26 = #define REG_ESPACE 12
27 = #define REG_BADRPT 13
28 = #define REG_EMPTY 14
29 = #define REG_ASSERT 15
30 = #define REG_INVARG 16
31 = #define REG_ATOI 255 // convert name to number (!)
32 = #define REG_ITOA 0400 // convert number to name (!)
33 */
34 static const struct rerr {
35 int code;
36 const char *name;
37 const char *explain;
38 } rerrs[] = {
39 {REG_OKAY, "REG_OKAY", "no errors detected"},
40 {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
41 {REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
42 {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
43 {REG_ECTYPE, "REG_ECTYPE", "invalid character class"},
44 {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"},
45 {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"},
46 {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"},
47 {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"},
48 {REG_EBRACE, "REG_EBRACE", "braces not balanced"},
49 {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"},
50 {REG_ERANGE, "REG_ERANGE", "invalid character range"},
51 {REG_ESPACE, "REG_ESPACE", "out of memory"},
52 {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"},
53 {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"},
54 {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"},
55 {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"},
56 {-1, "", "*** unknown regexp error code ***"},
57 };
58
59 /*
60 - regerror - the interface to error numbers
61 = API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t);
62 */
63 /* ARGSUSED */
64 API_EXPORT(size_t)
regerror(int errcode,const regex_t * preg,char * errbuf,size_t errbuf_size)65 regerror(
66 int errcode,
67 const regex_t *preg,
68 char *errbuf,
69 size_t errbuf_size)
70 {
71 register const struct rerr *r;
72 register size_t len;
73 register int target = errcode &~ REG_ITOA;
74 register const char *s;
75 char convbuf[50];
76
77 if (errcode == REG_ATOI)
78 s = regatoi(preg, convbuf, sizeof(convbuf));
79 else {
80 for (r = rerrs; r->code >= 0; r++)
81 if (r->code == target)
82 break;
83
84 if (errcode®_ITOA) {
85 if (r->code >= 0) {
86 (void) strncpy(convbuf, r->name, sizeof(convbuf) - 1);
87 convbuf[sizeof(convbuf) - 1] = '\0';
88 } else {
89 snprintf(convbuf, sizeof(convbuf), "REG_0x%x", target);
90 }
91 assert(strlen(convbuf) < sizeof(convbuf));
92 s = convbuf;
93 } else
94 s = r->explain;
95 }
96
97 len = strlen(s) + 1;
98 if (errbuf_size > 0) {
99 if (errbuf_size > len)
100 (void) strcpy(errbuf, s);
101 else {
102 (void) strncpy(errbuf, s, errbuf_size-1);
103 errbuf[errbuf_size-1] = '\0';
104 }
105 }
106
107 return(len);
108 }
109
110 /*
111 - regatoi - internal routine to implement REG_ATOI
112 == static char *regatoi(const regex_t *preg, char *localbuf, int bufsize);
113 */
114 static char *
regatoi(preg,localbuf,bufsize)115 regatoi(preg, localbuf, bufsize)
116 const regex_t *preg;
117 char *localbuf;
118 int bufsize;
119 {
120 register const struct rerr *r;
121
122 for (r = rerrs; r->code >= 0; r++)
123 if (strcmp(r->name, preg->re_endp) == 0)
124 break;
125 if (r->code < 0)
126 return("0");
127
128 snprintf(localbuf, bufsize, "%d", r->code);
129 return(localbuf);
130 }
131