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