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