xref: /illumos-gate/usr/src/lib/libc/port/regex/regerror.c (revision 4c28a617e3922d92a58e813a5b955eb526b9c386)
1 /*
2  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
3  * Copyright (c) 1992, 1993, 1994 Henry Spencer.
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 
35 #include "lint.h"
36 #include "file64.h"
37 #include <sys/types.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <limits.h>
41 #include <stdlib.h>
42 #include <regex.h>
43 
44 #include "utils.h"
45 #include "../gen/_libc_gettext.h"
46 
47 static const char *regatoi(const regex_t *preg, char *localbuf);
48 
49 #define	RERR(x, msg)	{ x, #x, msg }
50 
51 static struct rerr {
52 	int code;
53 	const char *name;
54 	const char *explain;
55 } rerrs[] = {
56 	RERR(REG_NOMATCH,	"regexec() failed to match"),
57 	RERR(REG_BADPAT,	"invalid regular expression"),
58 	RERR(REG_ECOLLATE,	"invalid collating element"),
59 	RERR(REG_ECTYPE,	"invalid character class"),
60 	RERR(REG_EESCAPE,	"trailing backslash (\\)"),
61 	RERR(REG_ESUBREG,	"invalid backreference number"),
62 	RERR(REG_EBRACK,	"brackets ([ ]) not balanced"),
63 	RERR(REG_EPAREN,	"parentheses not balanced"),
64 	RERR(REG_EBRACE,	"braces not balanced"),
65 	RERR(REG_BADBR,		"invalid repetition count(s)"),
66 	RERR(REG_ERANGE,	"invalid character range"),
67 	RERR(REG_ESPACE,	"out of memory"),
68 	RERR(REG_BADRPT,	"repetition-operator operand invalid"),
69 #ifdef	REG_EMPTY
70 	RERR(REG_EMPTY,		"empty (sub)expression"),
71 #endif
72 	RERR(REG_EFATAL,	"fatal internal error"),
73 #ifdef	REG_INVARG
74 	RERR(REG_INVARG,	"invalid argument to regex routine"),
75 #endif
76 	RERR(REG_ECHAR,		"illegal byte sequence"),
77 	RERR(REG_ENOSYS,	"function not supported"),
78 	RERR(REG_STACK,		"backtrack stack overflow"),
79 	RERR(REG_ENSUB,		"more than 9 \\( \\) pairs"),
80 	RERR(REG_ENEWLINE,	"\n found before end of pattern"),
81 	{0,	"",		"*** unknown regexp error code ***"}
82 };
83 
84 
85 /*
86  * regerror - the interface to error numbers
87  */
88 /* ARGSUSED */
89 size_t
90 regerror(int errcode, const regex_t *_RESTRICT_KYWD preg,
91     char *_RESTRICT_KYWD errbuf, size_t errbuf_size)
92 {
93 	struct rerr *r;
94 	size_t len;
95 	int target = errcode &~ REG_ITOA;
96 	const char *s;
97 	char convbuf[50];
98 
99 	if (errcode == REG_ATOI) {
100 		s = regatoi(preg, convbuf);
101 	} else {
102 		for (r = rerrs; r->code != 0; r++) {
103 			if (r->code == target)
104 				break;
105 		}
106 
107 		if (errcode&REG_ITOA) {
108 			if (r->code != 0)
109 				(void) strcpy(convbuf, r->name);
110 			else
111 				(void) sprintf(convbuf, "REG_0x%x", target);
112 			assert(strlen(convbuf) < sizeof (convbuf));
113 			s = convbuf;
114 		} else {
115 			s = _libc_gettext(r->explain);
116 		}
117 	}
118 
119 	len = strlen(s) + 1;
120 	if (errbuf_size > 0) {
121 		if (errbuf_size > len) {
122 			(void) strcpy(errbuf, s);
123 		} else {
124 			(void) strncpy(errbuf, s, errbuf_size-1);
125 			errbuf[errbuf_size-1] = '\0';
126 		}
127 	}
128 
129 	return (len);
130 }
131 
132 /*
133  * regatoi - internal routine to implement REG_ATOI
134  */
135 static const char *
136 regatoi(const regex_t *preg, char *localbuf)
137 {
138 	struct rerr *r;
139 
140 	for (r = rerrs; r->code != 0; r++) {
141 		if (strcmp(r->name, preg->re_endp) == 0)
142 			break;
143 	}
144 	if (r->code == 0)
145 		return ("0");
146 
147 	(void) sprintf(localbuf, "%d", r->code);
148 	return (localbuf);
149 }
150