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 of
17 * 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/*
35 * Unknown-error explanation.
36 */
37
38static char unk[] = "*** unknown regex error code 0x%x ***";
39
40/*
41 * Struct to map among codes, code names, and explanations.
42 */
43
44static struct rerr {
45    int code;
46    const char *name;
47    const char *explain;
48} rerrs[] = {
49    /* The actual table is built from regex.h */
50#include "regerrs.h"
51    { -1, "", "oops" },		/* explanation special-cased in code */
52};
53
54/*
55 - regerror - the interface to error numbers
56 */
57/* ARGSUSED */
58size_t				/* Actual space needed (including NUL) */
59regerror(
60    int code,			/* Error code, or REG_ATOI or REG_ITOA */
61    const regex_t *preg,	/* Associated regex_t (unused at present) */
62    char *errbuf,		/* Result buffer (unless errbuf_size==0) */
63    size_t errbuf_size)		/* Available space in errbuf, can be 0 */
64{
65    struct rerr *r;
66    const char *msg;
67    char convbuf[sizeof(unk)+50]; /* 50 = plenty for int */
68    size_t len;
69    int icode;
70
71    switch (code) {
72    case REG_ATOI:		/* Convert name to number */
73	for (r = rerrs; r->code >= 0; r++) {
74	    if (strcmp(r->name, errbuf) == 0) {
75		break;
76	    }
77	}
78	sprintf(convbuf, "%d", r->code); /* -1 for unknown */
79	msg = convbuf;
80	break;
81    case REG_ITOA:		/* Convert number to name */
82	icode = atoi(errbuf);	/* Not our problem if this fails */
83	for (r = rerrs; r->code >= 0; r++) {
84	    if (r->code == icode) {
85		break;
86	    }
87	}
88	if (r->code >= 0) {
89	    msg = r->name;
90	} else {		/* Unknown; tell him the number */
91	    sprintf(convbuf, "REG_%u", (unsigned)icode);
92	    msg = convbuf;
93	}
94	break;
95    default:			/* A real, normal error code */
96	for (r = rerrs; r->code >= 0; r++) {
97	    if (r->code == code) {
98		break;
99	    }
100	}
101	if (r->code >= 0) {
102	    msg = r->explain;
103	} else {		/* Unknown; say so */
104	    sprintf(convbuf, unk, code);
105	    msg = convbuf;
106	}
107	break;
108    }
109
110    len = strlen(msg) + 1;	/* Space needed, including NUL */
111    if (errbuf_size > 0) {
112	if (errbuf_size > len) {
113	    strcpy(errbuf, msg);
114	} else {		/* Truncate to fit */
115	    strncpy(errbuf, msg, errbuf_size-1);
116	    errbuf[errbuf_size-1] = '\0';
117	}
118    }
119
120    return len;
121}
122
123/*
124 * Local Variables:
125 * mode: c
126 * c-basic-offset: 4
127 * fill-column: 78
128 * End:
129 */
130