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