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