1 #include <my_global.h>
2 #include <m_string.h>
3 #include <m_ctype.h>
4 
5 #include "my_regex.h"
6 #include "utils.h"
7 #include "regerror.ih"
8 
9 /*
10  = #define	MY_REG_NOMATCH	 1
11  = #define	MY_REG_BADPAT	 2
12  = #define	MY_REG_ECOLLATE	 3
13  = #define	MY_REG_ECTYPE	 4
14  = #define	MY_REG_EESCAPE	 5
15  = #define	MY_REG_ESUBREG	 6
16  = #define	MY_REG_EBRACK	 7
17  = #define	MY_REG_EPAREN	 8
18  = #define	MY_REG_EBRACE	 9
19  = #define	MY_REG_BADBR	10
20  = #define	MY_REG_ERANGE	11
21  = #define	MY_REG_ESPACE	12
22  = #define	MY_REG_BADRPT	13
23  = #define	MY_REG_EMPTY	14
24  = #define	MY_REG_ASSERT	15
25  = #define	MY_REG_INVARG	16
26  = #define	MY_REG_ATOI	255	// convert name to number (!)
27  = #define	MY_REG_ITOA	0400	// convert number to name (!)
28  */
29 static struct rerr {
30 	int code;
31 	const char *name;
32         const char *explain;
33 } rerrs[] = {
34 	{MY_REG_NOMATCH,	"MY_REG_NOMATCH",	"regexec() failed to match"},
35 	{MY_REG_BADPAT,	"MY_REG_BADPAT",	"invalid regular expression"},
36 	{MY_REG_ECOLLATE,	"MY_REG_ECOLLATE",	"invalid collating element"},
37 	{MY_REG_ECTYPE,	"MY_REG_ECTYPE",	"invalid character class"},
38 	{MY_REG_EESCAPE,	"MY_REG_EESCAPE",	"trailing backslash (\\)"},
39 	{MY_REG_ESUBREG,	"MY_REG_ESUBREG",	"invalid backreference number"},
40 	{MY_REG_EBRACK,	"MY_REG_EBRACK",	"brackets ([ ]) not balanced"},
41 	{MY_REG_EPAREN,	"MY_REG_EPAREN",	"parentheses not balanced"},
42 	{MY_REG_EBRACE,	"MY_REG_EBRACE",	"braces not balanced"},
43 	{MY_REG_BADBR,	"MY_REG_BADBR",	"invalid repetition count(s)"},
44 	{MY_REG_ERANGE,	"MY_REG_ERANGE",	"invalid character range"},
45 	{MY_REG_ESPACE,	"MY_REG_ESPACE",	"out of memory"},
46 	{MY_REG_BADRPT,	"MY_REG_BADRPT",	"repetition-operator operand invalid"},
47 	{MY_REG_EMPTY,	"MY_REG_EMPTY",	"empty (sub)expression"},
48 	{MY_REG_ASSERT,	"MY_REG_ASSERT",	"\"can't happen\" -- you found a bug"},
49 	{MY_REG_INVARG,	"MY_REG_INVARG",	"invalid argument to regex routine"},
50 	{0,		"",		"*** unknown regexp error code ***"},
51 };
52 
53 /*
54  - regerror - the interface to error numbers
55  = extern size_t regerror(int, const regex_t *, char *, size_t);
56  */
57 /* ARGSUSED */
58 size_t
my_regerror(int errcode,const my_regex_t * preg,char * errbuf,size_t errbuf_size)59 my_regerror(int errcode, const my_regex_t *preg, char *errbuf, size_t errbuf_size)
60 {
61 	struct rerr *r;
62 	size_t len;
63 	int target = errcode &~ MY_REG_ITOA;
64 	char *s;
65 	char convbuf[50];
66 
67 	if (errcode == MY_REG_ATOI)
68 		s = regatoi(preg, convbuf);
69 	else {
70 		for (r = rerrs; r->code != 0; r++)
71 			if (r->code == target)
72 				break;
73 
74 		if (errcode&MY_REG_ITOA) {
75 			if (r->code != 0)
76 				(void) strcpy(convbuf, r->name);
77 			else
78 				sprintf(convbuf, "MY_REG_0x%x", target);
79 			assert(strlen(convbuf) < sizeof(convbuf));
80 			s = convbuf;
81 		} else
82 			s = (char*) r->explain;
83 	}
84 
85 	len = strlen(s) + 1;
86 	if (errbuf_size > 0) {
87 		if (errbuf_size > len)
88 			(void) strcpy(errbuf, s);
89 		else {
90 			(void) strncpy(errbuf, s, errbuf_size-1);
91 			errbuf[errbuf_size-1] = '\0';
92 		}
93 	}
94 
95 	return(len);
96 }
97 
98 /*
99  - regatoi - internal routine to implement MY_REG_ATOI
100  == static char *regatoi(const regex_t *preg, char *localbuf);
101  */
102 static char *
regatoi(preg,localbuf)103 regatoi(preg, localbuf)
104 const my_regex_t *preg;
105 char *localbuf;
106 {
107 	struct rerr *r;
108 	for (r = rerrs; r->code != 0; r++)
109 		if (strcmp(r->name, preg->re_endp) == 0)
110 			break;
111 	if (r->code == 0)
112 		return((char*) "0");
113 
114 	sprintf(localbuf, "%d", r->code);
115 	return(localbuf);
116 }
117