1 /*	$NetBSD: regerror.c,v 1.23 2007/02/09 23:44:18 junyoung Exp $	*/
2 
3 /*-
4  * Copyright (c) 1992, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Henry Spencer.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)regerror.c	8.4 (Berkeley) 3/20/94
35  */
36 
37 /*-
38  * Copyright (c) 1992, 1993, 1994 Henry Spencer.
39  *
40  * This code is derived from software contributed to Berkeley by
41  * Henry Spencer.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. All advertising materials mentioning features or use of this software
52  *    must display the following acknowledgement:
53  *	This product includes software developed by the University of
54  *	California, Berkeley and its contributors.
55  * 4. Neither the name of the University nor the names of its contributors
56  *    may be used to endorse or promote products derived from this software
57  *    without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69  * SUCH DAMAGE.
70  *
71  *	@(#)regerror.c	8.4 (Berkeley) 3/20/94
72  */
73 
74 #include <sys/cdefs.h>
75 #if defined(LIBC_SCCS) && !defined(lint)
76 #if 0
77 static char sccsid[] = "@(#)regerror.c	8.4 (Berkeley) 3/20/94";
78 #else
79 __RCSID("$NetBSD: regerror.c,v 1.23 2007/02/09 23:44:18 junyoung Exp $");
80 #endif
81 #endif /* LIBC_SCCS and not lint */
82 
83 #include "namespace.h"
84 #include <sys/types.h>
85 
86 #include <assert.h>
87 #include <ctype.h>
88 #include <limits.h>
89 #include <stdio.h>
90 #include <stdlib.h>
91 #include <string.h>
92 #include <regex.h>
93 
94 #ifdef __weak_alias
__weak_alias(regerror,_regerror)95 __weak_alias(regerror,_regerror)
96 #endif
97 
98 #include "utils.h"
99 
100 /* ========= begin header generated by ./mkh ========= */
101 #ifdef __cplusplus
102 extern "C" {
103 #endif
104 
105 /* === regerror.c === */
106 static const char *regatoi(const regex_t *preg, char *localbuf, size_t buflen);
107 
108 #ifdef __cplusplus
109 }
110 #endif
111 /* ========= end header generated by ./mkh ========= */
112 /*
113  = #define	REG_NOMATCH	 1
114  = #define	REG_BADPAT	 2
115  = #define	REG_ECOLLATE	 3
116  = #define	REG_ECTYPE	 4
117  = #define	REG_EESCAPE	 5
118  = #define	REG_ESUBREG	 6
119  = #define	REG_EBRACK	 7
120  = #define	REG_EPAREN	 8
121  = #define	REG_EBRACE	 9
122  = #define	REG_BADBR	10
123  = #define	REG_ERANGE	11
124  = #define	REG_ESPACE	12
125  = #define	REG_BADRPT	13
126  = #define	REG_EMPTY	14
127  = #define	REG_ASSERT	15
128  = #define	REG_INVARG	16
129  = #define	REG_ATOI	255	// convert name to number (!)
130  = #define	REG_ITOA	0400	// convert number to name (!)
131  */
132 static const struct rerr {
133 	int code;
134 	const char *name;
135 	const char *explain;
136 } rerrs[] = {
137 	{ REG_NOMATCH,	"REG_NOMATCH",	"regexec() failed to match" },
138 	{ REG_BADPAT,	"REG_BADPAT",	"invalid regular expression" },
139 	{ REG_ECOLLATE,	"REG_ECOLLATE",	"invalid collating element" },
140 	{ REG_ECTYPE,	"REG_ECTYPE",	"invalid character class" },
141 	{ REG_EESCAPE,	"REG_EESCAPE",	"trailing backslash (\\)" },
142 	{ REG_ESUBREG,	"REG_ESUBREG",	"invalid backreference number" },
143 	{ REG_EBRACK,	"REG_EBRACK",	"brackets ([ ]) not balanced" },
144 	{ REG_EPAREN,	"REG_EPAREN",	"parentheses not balanced" },
145 	{ REG_EBRACE,	"REG_EBRACE",	"braces not balanced" },
146 	{ REG_BADBR,	"REG_BADBR",	"invalid repetition count(s)" },
147 	{ REG_ERANGE,	"REG_ERANGE",	"invalid character range" },
148 	{ REG_ESPACE,	"REG_ESPACE",	"out of memory" },
149 	{ REG_BADRPT,	"REG_BADRPT",	"repetition-operator operand invalid" },
150 	{ REG_EMPTY,	"REG_EMPTY",	"empty (sub)expression" },
151 	{ REG_ASSERT,	"REG_ASSERT",	"\"can't happen\" -- you found a bug" },
152 	{ REG_INVARG,	"REG_INVARG",	"invalid argument to regex routine" },
153 	{ 0,		"",		"*** unknown regexp error code ***" }
154 };
155 
156 /*
157  * regerror - the interface to error numbers
158  * extern size_t regerror(int, const regex_t *, char *, size_t);
159  */
160 /* ARGSUSED */
161 size_t
regerror(int errcode,const regex_t * preg,char * errbuf,size_t errbuf_size)162 regerror(
163     int errcode,
164     const regex_t *preg,
165     char *errbuf,
166     size_t errbuf_size)
167 {
168 	const struct rerr *r;
169 	size_t len;
170 	int target = errcode &~ REG_ITOA;
171 	const char *s;
172 	char convbuf[50];
173 
174 	_DIAGASSERT(errcode != REG_ATOI || preg != NULL);
175 	_DIAGASSERT(errbuf != NULL);
176 
177 	if (errcode == REG_ATOI)
178 		s = regatoi(preg, convbuf, sizeof convbuf);
179 	else {
180 		for (r = rerrs; r->code != 0; r++)
181 			if (r->code == target)
182 				break;
183 
184 		if (errcode & REG_ITOA) {
185 			if (r->code != 0) {
186 				(void)strlcpy(convbuf, r->name, sizeof convbuf);
187 			} else
188 				(void)snprintf(convbuf, sizeof convbuf,
189 				    "REG_0x%x", target);
190 			s = convbuf;
191 		} else
192 			s = r->explain;
193 	}
194 
195 	len = strlen(s) + 1;
196 	if (errbuf_size > 0)
197 		(void)strlcpy(errbuf, s, errbuf_size);
198 
199 	return(len);
200 }
201 
202 /*
203  * regatoi - internal routine to implement REG_ATOI
204  * static const char *regatoi(const regex_t *preg, char *localbuf,
205  * size_t buflen);
206  */
207 static const char *
regatoi(const regex_t * preg,char * localbuf,size_t buflen)208 regatoi(
209     const regex_t *preg,
210     char *localbuf,
211     size_t buflen)
212 {
213 	const struct rerr *r;
214 
215 	for (r = rerrs; r->code != 0; r++)
216 		if (strcmp(r->name, preg->re_endp) == 0)
217 			break;
218 	if (r->code == 0)
219 		return "0";
220 
221 	(void)snprintf(localbuf, buflen, "%d", r->code);
222 	return localbuf;
223 }
224