xref: /netbsd/tests/lib/libc/regex/debug.c (revision d6f74f4b)
1*d6f74f4bSchristos /*	$NetBSD: debug.c,v 1.7 2021/02/25 22:37:36 christos Exp $	*/
2065b69f2Spgoyette 
3065b69f2Spgoyette /*-
4065b69f2Spgoyette  * Copyright (c) 1993 The NetBSD Foundation, Inc.
5065b69f2Spgoyette  * All rights reserved.
6065b69f2Spgoyette  *
7065b69f2Spgoyette  * Redistribution and use in source and binary forms, with or without
8065b69f2Spgoyette  * modification, are permitted provided that the following conditions
9065b69f2Spgoyette  * are met:
10065b69f2Spgoyette  * 1. Redistributions of source code must retain the above copyright
11065b69f2Spgoyette  *    notice, this list of conditions and the following disclaimer.
12065b69f2Spgoyette  * 2. Redistributions in binary form must reproduce the above copyright
13065b69f2Spgoyette  *    notice, this list of conditions and the following disclaimer in the
14065b69f2Spgoyette  *    documentation and/or other materials provided with the distribution.
15065b69f2Spgoyette  *
16065b69f2Spgoyette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17065b69f2Spgoyette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18065b69f2Spgoyette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19065b69f2Spgoyette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20065b69f2Spgoyette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21065b69f2Spgoyette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22065b69f2Spgoyette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23065b69f2Spgoyette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24065b69f2Spgoyette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25065b69f2Spgoyette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26065b69f2Spgoyette  * POSSIBILITY OF SUCH DAMAGE.
27065b69f2Spgoyette  */
28065b69f2Spgoyette 
2944c11d31Schristos #include <sys/types.h>
30065b69f2Spgoyette #include <ctype.h>
31065b69f2Spgoyette #include <limits.h>
32065b69f2Spgoyette #include <regex.h>
33065b69f2Spgoyette #include <stdio.h>
34065b69f2Spgoyette #include <stdlib.h>
35065b69f2Spgoyette #include <string.h>
36065b69f2Spgoyette 
3735d9891aSchristos #ifndef __linux__
38065b69f2Spgoyette /* Don't sort these! */
39065b69f2Spgoyette #include "utils.h"
40065b69f2Spgoyette #include "regex2.h"
4135d9891aSchristos #else
4235d9891aSchristos #define REGEX_NODEBUG
4335d9891aSchristos #endif
4435d9891aSchristos 
4535d9891aSchristos #ifdef REGEX_TRE
4635d9891aSchristos #define REGEX_NODEBUG
4735d9891aSchristos #endif
48065b69f2Spgoyette 
49065b69f2Spgoyette #include "test_regex.h"
50065b69f2Spgoyette 
5135d9891aSchristos #ifndef REGEX_NODEBUG
52065b69f2Spgoyette static void s_print(struct re_guts *, FILE *);
53065b69f2Spgoyette static char *regchar(int);
5435d9891aSchristos #endif
55065b69f2Spgoyette 
56065b69f2Spgoyette /*
57065b69f2Spgoyette  * regprint - print a regexp for debugging
58065b69f2Spgoyette  */
59065b69f2Spgoyette void
regprint(regex_t * r,FILE * d)60065b69f2Spgoyette regprint(regex_t *r, FILE *d)
61065b69f2Spgoyette {
6235d9891aSchristos #ifndef REGEX_NODEBUG
63065b69f2Spgoyette 	struct re_guts *g = r->re_g;
64065b69f2Spgoyette 
652392a6a5Schristos 	fprintf(d, ", first %u last %u", g->firststate, g->laststate);
66065b69f2Spgoyette 	if (g->iflags&USEBOL)
67065b69f2Spgoyette 		fprintf(d, ", USEBOL");
68065b69f2Spgoyette 	if (g->iflags&USEEOL)
69065b69f2Spgoyette 		fprintf(d, ", USEEOL");
70065b69f2Spgoyette 	if (g->iflags&BAD)
71065b69f2Spgoyette 		fprintf(d, ", BAD");
72065b69f2Spgoyette 	if (g->nsub > 0)
732392a6a5Schristos 		fprintf(d, ", nsub=%zu", g->nsub);
74065b69f2Spgoyette 	if (g->must != NULL)
752392a6a5Schristos 		fprintf(d, ", must(%zu) `%*s'", g->mlen, (int)g->mlen, g->must);
76065b69f2Spgoyette 	if (g->backrefs)
77065b69f2Spgoyette 		fprintf(d, ", backrefs");
78065b69f2Spgoyette 	if (g->nplus > 0)
792392a6a5Schristos 		fprintf(d, ", nplus %u", g->nplus);
80065b69f2Spgoyette 	fprintf(d, "\n");
81065b69f2Spgoyette 	s_print(g, d);
82065b69f2Spgoyette 	fprintf(d, "\n");
8335d9891aSchristos #endif
84065b69f2Spgoyette }
85065b69f2Spgoyette 
8635d9891aSchristos #ifndef REGEX_NODEBUG
87065b69f2Spgoyette /*
88065b69f2Spgoyette  * s_print - print the strip for debugging
89065b69f2Spgoyette  */
90065b69f2Spgoyette static void
s_print(struct re_guts * g,FILE * d)91065b69f2Spgoyette s_print(struct re_guts *g, FILE *d)
92065b69f2Spgoyette {
93065b69f2Spgoyette 	sop *s;
94065b69f2Spgoyette 	int done = 0;
95065b69f2Spgoyette 	sop opnd;
96065b69f2Spgoyette 	int col = 0;
97065b69f2Spgoyette 	sopno offset = 2;
98065b69f2Spgoyette #	define	GAP()	{	if (offset % 5 == 0) { \
99065b69f2Spgoyette 					if (col > 40) { \
100065b69f2Spgoyette 						fprintf(d, "\n\t"); \
101065b69f2Spgoyette 						col = 0; \
102065b69f2Spgoyette 					} else { \
103065b69f2Spgoyette 						fprintf(d, " "); \
104065b69f2Spgoyette 						col++; \
105065b69f2Spgoyette 					} \
106065b69f2Spgoyette 				} else \
107065b69f2Spgoyette 					col++; \
108065b69f2Spgoyette 				offset++; \
109065b69f2Spgoyette 			}
110065b69f2Spgoyette 
111065b69f2Spgoyette 	if (OP(g->strip[0]) != OEND)
112065b69f2Spgoyette 		fprintf(d, "missing initial OEND!\n");
113065b69f2Spgoyette 	for (s = &g->strip[1]; !done; s++) {
114065b69f2Spgoyette 		opnd = OPND(*s);
115065b69f2Spgoyette 		switch (OP(*s)) {
116065b69f2Spgoyette 		case OEND:
117065b69f2Spgoyette 			fprintf(d, "\n");
118065b69f2Spgoyette 			done = 1;
119065b69f2Spgoyette 			break;
120065b69f2Spgoyette 		case OCHAR:
121065b69f2Spgoyette 			if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
122065b69f2Spgoyette 				fprintf(d, "\\%c", (char)opnd);
123065b69f2Spgoyette 			else
124065b69f2Spgoyette 				fprintf(d, "%s", regchar((char)opnd));
125065b69f2Spgoyette 			break;
126065b69f2Spgoyette 		case OBOL:
127065b69f2Spgoyette 			fprintf(d, "^");
128065b69f2Spgoyette 			break;
129065b69f2Spgoyette 		case OEOL:
130065b69f2Spgoyette 			fprintf(d, "$");
131065b69f2Spgoyette 			break;
132065b69f2Spgoyette 		case OBOW:
133065b69f2Spgoyette 			fprintf(d, "\\{");
134065b69f2Spgoyette 			break;
135065b69f2Spgoyette 		case OEOW:
136065b69f2Spgoyette 			fprintf(d, "\\}");
137065b69f2Spgoyette 			break;
138065b69f2Spgoyette 		case OANY:
139065b69f2Spgoyette 			fprintf(d, ".");
140065b69f2Spgoyette 			break;
141065b69f2Spgoyette 		case OANYOF:
1422392a6a5Schristos 			fprintf(d, "[(%u)", opnd);
143065b69f2Spgoyette 			fprintf(d, "]");
144065b69f2Spgoyette 			break;
145065b69f2Spgoyette 		case OBACK_:
1462392a6a5Schristos 			fprintf(d, "(\\<%u>", opnd);
147065b69f2Spgoyette 			break;
148065b69f2Spgoyette 		case O_BACK:
1492392a6a5Schristos 			fprintf(d, "<%u>\\)", opnd);
150065b69f2Spgoyette 			break;
151065b69f2Spgoyette 		case OPLUS_:
152065b69f2Spgoyette 			fprintf(d, "(+");
153065b69f2Spgoyette 			if (OP(*(s+opnd)) != O_PLUS)
1542392a6a5Schristos 				fprintf(d, "<%u>", opnd);
155065b69f2Spgoyette 			break;
156065b69f2Spgoyette 		case O_PLUS:
157065b69f2Spgoyette 			if (OP(*(s-opnd)) != OPLUS_)
1582392a6a5Schristos 				fprintf(d, "<%u>", opnd);
159065b69f2Spgoyette 			fprintf(d, "+)");
160065b69f2Spgoyette 			break;
161065b69f2Spgoyette 		case OQUEST_:
162065b69f2Spgoyette 			fprintf(d, "(?");
163065b69f2Spgoyette 			if (OP(*(s+opnd)) != O_QUEST)
1642392a6a5Schristos 				fprintf(d, "<%u>", opnd);
165065b69f2Spgoyette 			break;
166065b69f2Spgoyette 		case O_QUEST:
167065b69f2Spgoyette 			if (OP(*(s-opnd)) != OQUEST_)
1682392a6a5Schristos 				fprintf(d, "<%u>", opnd);
169065b69f2Spgoyette 			fprintf(d, "?)");
170065b69f2Spgoyette 			break;
171065b69f2Spgoyette 		case OLPAREN:
1722392a6a5Schristos 			fprintf(d, "((<%u>", opnd);
173065b69f2Spgoyette 			break;
174065b69f2Spgoyette 		case ORPAREN:
1752392a6a5Schristos 			fprintf(d, "<%u>))", opnd);
176065b69f2Spgoyette 			break;
177065b69f2Spgoyette 		case OCH_:
178065b69f2Spgoyette 			fprintf(d, "<");
1792392a6a5Schristos 			if (OP(*(s+opnd)) != OOR2)
1802392a6a5Schristos 				fprintf(d, "<%u>", opnd);
181065b69f2Spgoyette 			break;
182065b69f2Spgoyette 		case OOR1:
1832392a6a5Schristos 			if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
1842392a6a5Schristos 				fprintf(d, "<%u>", opnd);
185065b69f2Spgoyette 			fprintf(d, "|");
186065b69f2Spgoyette 			break;
187065b69f2Spgoyette 		case OOR2:
188065b69f2Spgoyette 			fprintf(d, "|");
1892392a6a5Schristos 			if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
1902392a6a5Schristos 				fprintf(d, "<%u>", opnd);
191065b69f2Spgoyette 			break;
192065b69f2Spgoyette 		case O_CH:
1932392a6a5Schristos 			if (OP(*(s-opnd)) != OOR1)
1942392a6a5Schristos 				fprintf(d, "<%u>", opnd);
195065b69f2Spgoyette 			fprintf(d, ">");
196065b69f2Spgoyette 			break;
197065b69f2Spgoyette 		default:
1982392a6a5Schristos 			fprintf(d, "!%u(%u)!", OP(*s), opnd);
199065b69f2Spgoyette 			break;
200065b69f2Spgoyette 		}
201065b69f2Spgoyette 		if (!done)
202065b69f2Spgoyette 			GAP();
203065b69f2Spgoyette 	}
204065b69f2Spgoyette }
205065b69f2Spgoyette 
206065b69f2Spgoyette /*
207065b69f2Spgoyette  * regchar - make a character printable
208065b69f2Spgoyette  */
209065b69f2Spgoyette static char *			/* -> representation */
regchar(int ch)210065b69f2Spgoyette regchar(int ch)
211065b69f2Spgoyette {
212065b69f2Spgoyette 	static char buf[10];
213065b69f2Spgoyette 
214065b69f2Spgoyette 	if (isprint(ch) || ch == ' ')
215065b69f2Spgoyette 		sprintf(buf, "%c", ch);
216065b69f2Spgoyette 	else
217065b69f2Spgoyette 		sprintf(buf, "\\%o", ch);
218065b69f2Spgoyette 	return(buf);
219065b69f2Spgoyette }
22035d9891aSchristos #endif
221