xref: /original-bsd/lib/libc/regex/regerror.c (revision 1d5f76bd)
1 /*-
2  * Copyright (c) 1992 Henry Spencer.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Henry Spencer of the University of Toronto.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)regerror.c	5.4 (Berkeley) 05/21/93
12  */
13 
14 #if defined(LIBC_SCCS) && !defined(lint)
15 static char sccsid[] = "@(#)regerror.c	5.4 (Berkeley) 05/21/93";
16 #endif /* LIBC_SCCS and not lint */
17 
18 #include <sys/types.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <limits.h>
23 #include <stdlib.h>
24 #include <regex.h>
25 
26 #include "utils.h"
27 
28 static char *regatoi __P((const regex_t *, char *));
29 
30 /*
31  = #define	REG_NOMATCH	 1
32  = #define	REG_BADPAT	 2
33  = #define	REG_ECOLLATE	 3
34  = #define	REG_ECTYPE	 4
35  = #define	REG_EESCAPE	 5
36  = #define	REG_ESUBREG	 6
37  = #define	REG_EBRACK	 7
38  = #define	REG_EPAREN	 8
39  = #define	REG_EBRACE	 9
40  = #define	REG_BADBR	10
41  = #define	REG_ERANGE	11
42  = #define	REG_ESPACE	12
43  = #define	REG_BADRPT	13
44  = #define	REG_EMPTY	14
45  = #define	REG_ASSERT	15
46  = #define	REG_INVARG	16
47  = #define	REG_ATOI	255	// convert name to number (!)
48  = #define	REG_ITOA	0400	// convert number to name (!)
49  */
50 static struct rerr {
51 	int code;
52 	char *name;
53 	char *explain;
54 } rerrs[] = {
55 	REG_NOMATCH,	"REG_NOMATCH",	"regexec() failed to match",
56 	REG_BADPAT,	"REG_BADPAT",	"invalid regular expression",
57 	REG_ECOLLATE,	"REG_ECOLLATE",	"invalid collating element",
58 	REG_ECTYPE,	"REG_ECTYPE",	"invalid character class",
59 	REG_EESCAPE,	"REG_EESCAPE",	"trailing backslash (\\)",
60 	REG_ESUBREG,	"REG_ESUBREG",	"invalid backreference number",
61 	REG_EBRACK,	"REG_EBRACK",	"brackets ([ ]) not balanced",
62 	REG_EPAREN,	"REG_EPAREN",	"parentheses not balanced",
63 	REG_EBRACE,	"REG_EBRACE",	"braces not balanced",
64 	REG_BADBR,	"REG_BADBR",	"invalid repetition count(s)",
65 	REG_ERANGE,	"REG_ERANGE",	"invalid character range",
66 	REG_ESPACE,	"REG_ESPACE",	"out of memory",
67 	REG_BADRPT,	"REG_BADRPT",	"repetition-operator operand invalid",
68 	REG_EMPTY,	"REG_EMPTY",	"empty (sub)expression",
69 	REG_ASSERT,	"REG_ASSERT",	"\"can't happen\" -- you found a bug",
70 	REG_INVARG,	"REG_INVARG",	"invalid argument to regex routine",
71 	0,		"",		"*** unknown regexp error code ***",
72 };
73 
74 /*
75  - regerror - the interface to error numbers
76  = extern size_t regerror(int errcode, const regex_t *preg, char *errbuf, \
77  =							size_t errbuf_size);
78  */
79 /* ARGSUSED */
80 size_t
81 regerror(errcode, preg, errbuf, errbuf_size)
82 int errcode;
83 const regex_t *preg;
84 char *errbuf;
85 size_t errbuf_size;
86 {
87 	register struct rerr *r;
88 	register size_t len;
89 	register int target = errcode &~ REG_ITOA;
90 	register char *s;
91 	char convbuf[50];
92 
93 	if (errcode == REG_ATOI)
94 		s = regatoi(preg, convbuf);
95 	else {
96 		for (r = rerrs; r->code != 0; r++)
97 			if (r->code == target)
98 				break;
99 
100 		if (errcode&REG_ITOA) {
101 			if (r->code != 0)
102 				(void) strcpy(convbuf, r->name);
103 			else
104 				sprintf(convbuf, "REG_0x%x", target);
105 			assert(strlen(convbuf) < sizeof(convbuf));
106 			s = convbuf;
107 		} else
108 			s = r->explain;
109 	}
110 
111 	len = strlen(s) + 1;
112 	if (errbuf_size > 0) {
113 		if (errbuf_size > len)
114 			(void) strcpy(errbuf, s);
115 		else {
116 			(void) strncpy(errbuf, s, errbuf_size-1);
117 			errbuf[errbuf_size-1] = '\0';
118 		}
119 	}
120 
121 	return(len);
122 }
123 
124 /*
125  - regatoi - internal routine to implement REG_ATOI
126  = static char *regatoi(const regex_t *preg, char *localbuf);
127  */
128 static char *
129 regatoi(preg, localbuf)
130 const regex_t *preg;
131 char *localbuf;
132 {
133 	register struct rerr *r;
134 	register size_t siz;
135 	register char *p;
136 
137 	for (r = rerrs; r->code != 0; r++)
138 		if (strcmp(r->name, preg->re_endp) == 0)
139 			break;
140 	if (r->code == 0)
141 		return("0");
142 
143 	sprintf(localbuf, "%d", r->code);
144 	return(localbuf);
145 }
146