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