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 */
35 static char unk[] = "*** unknown regex error code 0x%x ***";
36 
37 /* struct to map among codes, code names, and explanations */
38 static 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 */
52 size_t				/* actual space needed (including NUL) */
regerror(errcode,preg,errbuf,errbuf_size)53 regerror(errcode, preg, errbuf, errbuf_size)
54 int errcode;			/* error code, or REG_ATOI or REG_ITOA */
55 CONST regex_t *preg;		/* associated regex_t (unused at present) */
56 char *errbuf;			/* result buffer (unless errbuf_size==0) */
57 size_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 (errcode) {
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 == errcode)
88 				break;
89 		if (r->code >= 0)
90 			msg = r->explain;
91 		else {			/* unknown; say so */
92 			sprintf(convbuf, unk, errcode);
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