regerror.c revision 302408
1178481Sjb/*-
2178481Sjb * Copyright (c) 1992, 1993, 1994 Henry Spencer.
3178481Sjb * Copyright (c) 1992, 1993, 1994
4178481Sjb *	The Regents of the University of California.  All rights reserved.
5178481Sjb *
6178481Sjb * This code is derived from software contributed to Berkeley by
7178481Sjb * Henry Spencer.
8178481Sjb *
9178481Sjb * Redistribution and use in source and binary forms, with or without
10178481Sjb * modification, are permitted provided that the following conditions
11178481Sjb * are met:
12178481Sjb * 1. Redistributions of source code must retain the above copyright
13178481Sjb *    notice, this list of conditions and the following disclaimer.
14178481Sjb * 2. Redistributions in binary form must reproduce the above copyright
15178481Sjb *    notice, this list of conditions and the following disclaimer in the
16178481Sjb *    documentation and/or other materials provided with the distribution.
17178481Sjb * 4. Neither the name of the University nor the names of its contributors
18178481Sjb *    may be used to endorse or promote products derived from this software
19178481Sjb *    without specific prior written permission.
20178481Sjb *
21178481Sjb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22178481Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23178481Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24178481Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25178481Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26178481Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27178481Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28178481Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29178481Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30178481Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31178481Sjb * SUCH DAMAGE.
32178481Sjb *
33178481Sjb *	@(#)regerror.c	8.4 (Berkeley) 3/20/94
34178481Sjb */
35178481Sjb
36178481Sjb#if defined(LIBC_SCCS) && !defined(lint)
37178481Sjbstatic char sccsid[] = "@(#)regerror.c	8.4 (Berkeley) 3/20/94";
38178481Sjb#endif /* LIBC_SCCS and not lint */
39178481Sjb#include <sys/cdefs.h>
40277551Sdelphij__FBSDID("$FreeBSD: stable/11/lib/libc/regex/regerror.c 170528 2007-06-11 03:05:54Z delphij $");
41277551Sdelphij
42178481Sjb#include <sys/types.h>
43178481Sjb#include <stdio.h>
44178481Sjb#include <string.h>
45178481Sjb#include <limits.h>
46178481Sjb#include <stdlib.h>
47178481Sjb#include <regex.h>
48178481Sjb
49178481Sjb#include "utils.h"
50178481Sjb
51178481Sjb/* ========= begin header generated by ./mkh ========= */
52178481Sjb#ifdef __cplusplus
53178481Sjbextern "C" {
54178481Sjb#endif
55178481Sjb
56178481Sjb/* === regerror.c === */
57178481Sjbstatic char *regatoi(const regex_t *preg, char *localbuf);
58178481Sjb
59178481Sjb#ifdef __cplusplus
60178481Sjb}
61178481Sjb#endif
62178481Sjb/* ========= end header generated by ./mkh ========= */
63178481Sjb/*
64178481Sjb = #define	REG_NOMATCH	 1
65178481Sjb = #define	REG_BADPAT	 2
66178481Sjb = #define	REG_ECOLLATE	 3
67178481Sjb = #define	REG_ECTYPE	 4
68178481Sjb = #define	REG_EESCAPE	 5
69178481Sjb = #define	REG_ESUBREG	 6
70178481Sjb = #define	REG_EBRACK	 7
71178481Sjb = #define	REG_EPAREN	 8
72178481Sjb = #define	REG_EBRACE	 9
73178481Sjb = #define	REG_BADBR	10
74178481Sjb = #define	REG_ERANGE	11
75178481Sjb = #define	REG_ESPACE	12
76178481Sjb = #define	REG_BADRPT	13
77178481Sjb = #define	REG_EMPTY	14
78178481Sjb = #define	REG_ASSERT	15
79178481Sjb = #define	REG_INVARG	16
80178481Sjb = #define	REG_ILLSEQ	17
81178481Sjb = #define	REG_ATOI	255	// convert name to number (!)
82178481Sjb = #define	REG_ITOA	0400	// convert number to name (!)
83178481Sjb */
84178481Sjbstatic struct rerr {
85178481Sjb	int code;
86178481Sjb	char *name;
87178481Sjb	char *explain;
88178481Sjb} rerrs[] = {
89178481Sjb	{REG_NOMATCH,	"REG_NOMATCH",	"regexec() failed to match"},
90178481Sjb	{REG_BADPAT,	"REG_BADPAT",	"invalid regular expression"},
91178481Sjb	{REG_ECOLLATE,	"REG_ECOLLATE",	"invalid collating element"},
92178481Sjb	{REG_ECTYPE,	"REG_ECTYPE",	"invalid character class"},
93178481Sjb	{REG_EESCAPE,	"REG_EESCAPE",	"trailing backslash (\\)"},
94178546Sjb	{REG_ESUBREG,	"REG_ESUBREG",	"invalid backreference number"},
95178481Sjb	{REG_EBRACK,	"REG_EBRACK",	"brackets ([ ]) not balanced"},
96178481Sjb	{REG_EPAREN,	"REG_EPAREN",	"parentheses not balanced"},
97178481Sjb	{REG_EBRACE,	"REG_EBRACE",	"braces not balanced"},
98178481Sjb	{REG_BADBR,	"REG_BADBR",	"invalid repetition count(s)"},
99178481Sjb	{REG_ERANGE,	"REG_ERANGE",	"invalid character range"},
100178481Sjb	{REG_ESPACE,	"REG_ESPACE",	"out of memory"},
101178481Sjb	{REG_BADRPT,	"REG_BADRPT",	"repetition-operator operand invalid"},
102178481Sjb	{REG_EMPTY,	"REG_EMPTY",	"empty (sub)expression"},
103178481Sjb	{REG_ASSERT,	"REG_ASSERT",	"\"can't happen\" -- you found a bug"},
104178481Sjb	{REG_INVARG,	"REG_INVARG",	"invalid argument to regex routine"},
105178481Sjb	{REG_ILLSEQ,	"REG_ILLSEQ",	"illegal byte sequence"},
106178481Sjb	{0,		"",		"*** unknown regexp error code ***"}
107178481Sjb};
108178481Sjb
109178481Sjb/*
110178481Sjb - regerror - the interface to error numbers
111178481Sjb = extern size_t regerror(int, const regex_t *, char *, size_t);
112178481Sjb */
113178481Sjb/* ARGSUSED */
114178481Sjbsize_t
115178481Sjbregerror(int errcode,
116178481Sjb	 const regex_t * __restrict preg,
117178481Sjb	 char * __restrict errbuf,
118178481Sjb	 size_t errbuf_size)
119178481Sjb{
120178481Sjb	struct rerr *r;
121178481Sjb	size_t len;
122178481Sjb	int target = errcode &~ REG_ITOA;
123178481Sjb	char *s;
124178481Sjb	char convbuf[50];
125178481Sjb
126178481Sjb	if (errcode == REG_ATOI)
127178481Sjb		s = regatoi(preg, convbuf);
128178481Sjb	else {
129178481Sjb		for (r = rerrs; r->code != 0; r++)
130178481Sjb			if (r->code == target)
131178481Sjb				break;
132178481Sjb
133178481Sjb		if (errcode&REG_ITOA) {
134178481Sjb			if (r->code != 0)
135178481Sjb				(void) strcpy(convbuf, r->name);
136178481Sjb			else
137178481Sjb				sprintf(convbuf, "REG_0x%x", target);
138178481Sjb			assert(strlen(convbuf) < sizeof(convbuf));
139178481Sjb			s = convbuf;
140178481Sjb		} else
141178481Sjb			s = r->explain;
142178481Sjb	}
143178481Sjb
144178481Sjb	len = strlen(s) + 1;
145178481Sjb	if (errbuf_size > 0) {
146178481Sjb		if (errbuf_size > len)
147178481Sjb			(void) strcpy(errbuf, s);
148178481Sjb		else {
149178481Sjb			(void) strncpy(errbuf, s, errbuf_size-1);
150178481Sjb			errbuf[errbuf_size-1] = '\0';
151178481Sjb		}
152178481Sjb	}
153178481Sjb
154178481Sjb	return(len);
155178481Sjb}
156178481Sjb
157178481Sjb/*
158178481Sjb - regatoi - internal routine to implement REG_ATOI
159178481Sjb == static char *regatoi(const regex_t *preg, char *localbuf);
160178481Sjb */
161178481Sjbstatic char *
162253661Spfgregatoi(const regex_t *preg, char *localbuf)
163178481Sjb{
164178481Sjb	struct rerr *r;
165178481Sjb
166178481Sjb	for (r = rerrs; r->code != 0; r++)
167178481Sjb		if (strcmp(r->name, preg->re_endp) == 0)
168178481Sjb			break;
169178481Sjb	if (r->code == 0)
170178481Sjb		return("0");
171178481Sjb
172178481Sjb	sprintf(localbuf, "%d", r->code);
173178481Sjb	return(localbuf);
174178481Sjb}
175178481Sjb