1/*
2 * regerror - error-code expansion
3 *
4 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
5 *
6 * Development of this software was funded, in part, by Cray Research Inc.,
7 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
8 * Corporation, none of whom are responsible for the results.  The author
9 * thanks all of them.
10 *
11 * Redistribution and use in source and binary forms -- with or without
12 * modification -- are permitted for any purpose, provided that
13 * redistributions in source form retain this entire copyright notice and
14 * indicate the origin and nature of any modifications.
15 *
16 * I'd appreciate being given credit for this package in the documentation
17 * of software which uses it, but that is not a requirement.
18 *
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
22 * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32#include "regguts.h"
33
34/* unknown-error explanation */
35static char unk[] = "*** unknown regex error code 0x%x ***";
36
37/* struct to map among codes, code names, and explanations */
38static struct rerr {
39	int code;
40	char *name;
41	char *explain;
42} rerrs[] = {
43	/* the actual table is built from regex.h */
44#	include "regerrs.h"
45	{ -1,	"",	"oops" },	/* explanation special-cased in code */
46};
47
48/*
49 - regerror - the interface to error numbers
50 */
51/* ARGSUSED */
52size_t				/* actual space needed (including NUL) */
53regerror(code, preg, errbuf, errbuf_size)
54int code;			/* error code, or REG_ATOI or REG_ITOA */
55CONST regex_t *preg;		/* associated regex_t (unused at present) */
56char *errbuf;			/* result buffer (unless errbuf_size==0) */
57size_t errbuf_size;		/* available space in errbuf, can be 0 */
58{
59	struct rerr *r;
60	char *msg;
61	char convbuf[sizeof(unk)+50];	/* 50 = plenty for int */
62	size_t len;
63	int icode;
64
65	switch (code) {
66	case REG_ATOI:		/* convert name to number */
67		for (r = rerrs; r->code >= 0; r++)
68			if (strcmp(r->name, errbuf) == 0)
69				break;
70		sprintf(convbuf, "%d", r->code);	/* -1 for unknown */
71		msg = convbuf;
72		break;
73	case REG_ITOA:		/* convert number to name */
74		icode = atoi(errbuf);	/* not our problem if this fails */
75		for (r = rerrs; r->code >= 0; r++)
76			if (r->code == icode)
77				break;
78		if (r->code >= 0)
79			msg = r->name;
80		else {			/* unknown; tell him the number */
81			sprintf(convbuf, "REG_%u", (unsigned)icode);
82			msg = convbuf;
83		}
84		break;
85	default:		/* a real, normal error code */
86		for (r = rerrs; r->code >= 0; r++)
87			if (r->code == code)
88				break;
89		if (r->code >= 0)
90			msg = r->explain;
91		else {			/* unknown; say so */
92			sprintf(convbuf, unk, code);
93			msg = convbuf;
94		}
95		break;
96	}
97
98	len = strlen(msg) + 1;		/* space needed, including NUL */
99	if (errbuf_size > 0) {
100		if (errbuf_size > len)
101			strcpy(errbuf, msg);
102		else {			/* truncate to fit */
103			strncpy(errbuf, msg, errbuf_size-1);
104			errbuf[errbuf_size-1] = '\0';
105		}
106	}
107
108	return len;
109}
110