xref: /netbsd-src/tests/lib/libc/regex/debug.c (revision d2bbb37090a3fc9f01819465a647bfe335913c81)
1 /*	$NetBSD: debug.c,v 1.7 2021/02/25 22:37:36 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1993 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <ctype.h>
31 #include <limits.h>
32 #include <regex.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #ifndef __linux__
38 /* Don't sort these! */
39 #include "utils.h"
40 #include "regex2.h"
41 #else
42 #define REGEX_NODEBUG
43 #endif
44 
45 #ifdef REGEX_TRE
46 #define REGEX_NODEBUG
47 #endif
48 
49 #include "test_regex.h"
50 
51 #ifndef REGEX_NODEBUG
52 static void s_print(struct re_guts *, FILE *);
53 static char *regchar(int);
54 #endif
55 
56 /*
57  * regprint - print a regexp for debugging
58  */
59 void
regprint(regex_t * r,FILE * d)60 regprint(regex_t *r, FILE *d)
61 {
62 #ifndef REGEX_NODEBUG
63 	struct re_guts *g = r->re_g;
64 
65 	fprintf(d, ", first %u last %u", g->firststate, g->laststate);
66 	if (g->iflags&USEBOL)
67 		fprintf(d, ", USEBOL");
68 	if (g->iflags&USEEOL)
69 		fprintf(d, ", USEEOL");
70 	if (g->iflags&BAD)
71 		fprintf(d, ", BAD");
72 	if (g->nsub > 0)
73 		fprintf(d, ", nsub=%zu", g->nsub);
74 	if (g->must != NULL)
75 		fprintf(d, ", must(%zu) `%*s'", g->mlen, (int)g->mlen, g->must);
76 	if (g->backrefs)
77 		fprintf(d, ", backrefs");
78 	if (g->nplus > 0)
79 		fprintf(d, ", nplus %u", g->nplus);
80 	fprintf(d, "\n");
81 	s_print(g, d);
82 	fprintf(d, "\n");
83 #endif
84 }
85 
86 #ifndef REGEX_NODEBUG
87 /*
88  * s_print - print the strip for debugging
89  */
90 static void
s_print(struct re_guts * g,FILE * d)91 s_print(struct re_guts *g, FILE *d)
92 {
93 	sop *s;
94 	int done = 0;
95 	sop opnd;
96 	int col = 0;
97 	sopno offset = 2;
98 #	define	GAP()	{	if (offset % 5 == 0) { \
99 					if (col > 40) { \
100 						fprintf(d, "\n\t"); \
101 						col = 0; \
102 					} else { \
103 						fprintf(d, " "); \
104 						col++; \
105 					} \
106 				} else \
107 					col++; \
108 				offset++; \
109 			}
110 
111 	if (OP(g->strip[0]) != OEND)
112 		fprintf(d, "missing initial OEND!\n");
113 	for (s = &g->strip[1]; !done; s++) {
114 		opnd = OPND(*s);
115 		switch (OP(*s)) {
116 		case OEND:
117 			fprintf(d, "\n");
118 			done = 1;
119 			break;
120 		case OCHAR:
121 			if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
122 				fprintf(d, "\\%c", (char)opnd);
123 			else
124 				fprintf(d, "%s", regchar((char)opnd));
125 			break;
126 		case OBOL:
127 			fprintf(d, "^");
128 			break;
129 		case OEOL:
130 			fprintf(d, "$");
131 			break;
132 		case OBOW:
133 			fprintf(d, "\\{");
134 			break;
135 		case OEOW:
136 			fprintf(d, "\\}");
137 			break;
138 		case OANY:
139 			fprintf(d, ".");
140 			break;
141 		case OANYOF:
142 			fprintf(d, "[(%u)", opnd);
143 			fprintf(d, "]");
144 			break;
145 		case OBACK_:
146 			fprintf(d, "(\\<%u>", opnd);
147 			break;
148 		case O_BACK:
149 			fprintf(d, "<%u>\\)", opnd);
150 			break;
151 		case OPLUS_:
152 			fprintf(d, "(+");
153 			if (OP(*(s+opnd)) != O_PLUS)
154 				fprintf(d, "<%u>", opnd);
155 			break;
156 		case O_PLUS:
157 			if (OP(*(s-opnd)) != OPLUS_)
158 				fprintf(d, "<%u>", opnd);
159 			fprintf(d, "+)");
160 			break;
161 		case OQUEST_:
162 			fprintf(d, "(?");
163 			if (OP(*(s+opnd)) != O_QUEST)
164 				fprintf(d, "<%u>", opnd);
165 			break;
166 		case O_QUEST:
167 			if (OP(*(s-opnd)) != OQUEST_)
168 				fprintf(d, "<%u>", opnd);
169 			fprintf(d, "?)");
170 			break;
171 		case OLPAREN:
172 			fprintf(d, "((<%u>", opnd);
173 			break;
174 		case ORPAREN:
175 			fprintf(d, "<%u>))", opnd);
176 			break;
177 		case OCH_:
178 			fprintf(d, "<");
179 			if (OP(*(s+opnd)) != OOR2)
180 				fprintf(d, "<%u>", opnd);
181 			break;
182 		case OOR1:
183 			if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
184 				fprintf(d, "<%u>", opnd);
185 			fprintf(d, "|");
186 			break;
187 		case OOR2:
188 			fprintf(d, "|");
189 			if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
190 				fprintf(d, "<%u>", opnd);
191 			break;
192 		case O_CH:
193 			if (OP(*(s-opnd)) != OOR1)
194 				fprintf(d, "<%u>", opnd);
195 			fprintf(d, ">");
196 			break;
197 		default:
198 			fprintf(d, "!%u(%u)!", OP(*s), opnd);
199 			break;
200 		}
201 		if (!done)
202 			GAP();
203 	}
204 }
205 
206 /*
207  * regchar - make a character printable
208  */
209 static char *			/* -> representation */
regchar(int ch)210 regchar(int ch)
211 {
212 	static char buf[10];
213 
214 	if (isprint(ch) || ch == ' ')
215 		sprintf(buf, "%c", ch);
216 	else
217 		sprintf(buf, "\\%o", ch);
218 	return(buf);
219 }
220 #endif
221