1 /*- $MirOS: src/lib/libc/regex/test/debug.c,v 1.3 2007/02/12 05:37:51 tg Exp $
2 * Part of Henry Spencer's regular expression library
3 */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <ctype.h>
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <regex.h>
12
13 #include "utils.h"
14 #include "regex2.h"
15
16 /* ========= begin header generated by ./mkh ========= */
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21 /* === debug.c === */
22 void regprint(regex_t *r, FILE *d);
23 static void s_print(register struct re_guts *g, FILE *d);
24 static char *regchar(int ch);
25
26 #ifdef __cplusplus
27 }
28 #endif
29 /* ========= end header generated by ./mkh ========= */
30
31 /*
32 - regprint - print a regexp for debugging
33 == void regprint(regex_t *r, FILE *d);
34 */
35 void
regprint(regex_t * r,FILE * d)36 regprint(regex_t *r, FILE *d)
37 {
38 register struct re_guts *g = r->re_g;
39 register int i;
40 register int c;
41 register int last;
42 int nincat[NC];
43
44 fprintf(d, "%ld states, %d categories", (long)g->nstates,
45 g->ncategories);
46 fprintf(d, ", first %ld last %ld", (long)g->firststate,
47 (long)g->laststate);
48 if (g->iflags&USEBOL)
49 fprintf(d, ", USEBOL");
50 if (g->iflags&USEEOL)
51 fprintf(d, ", USEEOL");
52 if (g->iflags&BAD)
53 fprintf(d, ", BAD");
54 if (g->nsub > 0)
55 fprintf(d, ", nsub=%ld", (long)g->nsub);
56 if (g->must != NULL)
57 fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
58 g->must);
59 if (g->backrefs)
60 fprintf(d, ", backrefs");
61 if (g->nplus > 0)
62 fprintf(d, ", nplus %ld", (long)g->nplus);
63 fprintf(d, "\n");
64 s_print(g, d);
65 for (i = 0; i < g->ncategories; i++) {
66 nincat[i] = 0;
67 for (c = CHAR_MIN; c <= CHAR_MAX; c++)
68 if (g->categories[c] == i)
69 nincat[i]++;
70 }
71 fprintf(d, "cc0#%d", nincat[0]);
72 for (i = 1; i < g->ncategories; i++)
73 if (nincat[i] == 1) {
74 for (c = CHAR_MIN; c <= CHAR_MAX; c++)
75 if (g->categories[c] == i)
76 break;
77 fprintf(d, ", %d=%s", i, regchar(c));
78 }
79 fprintf(d, "\n");
80 for (i = 1; i < g->ncategories; i++)
81 if (nincat[i] != 1) {
82 fprintf(d, "cc%d\t", i);
83 last = -1;
84 for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */
85 if (c <= CHAR_MAX && g->categories[c] == i) {
86 if (last < 0) {
87 fprintf(d, "%s", regchar(c));
88 last = c;
89 }
90 } else {
91 if (last >= 0) {
92 if (last != c-1)
93 fprintf(d, "-%s",
94 regchar(c-1));
95 last = -1;
96 }
97 }
98 fprintf(d, "\n");
99 }
100 }
101
102 /*
103 - s_print - print the strip for debugging
104 == static void s_print(register struct re_guts *g, FILE *d);
105 */
106 static void
s_print(register struct re_guts * g,FILE * d)107 s_print(register struct re_guts *g, FILE *d)
108 {
109 register sop *s;
110 register cset *cs;
111 register int i;
112 register int done = 0;
113 register sop opnd;
114 register int col = 0;
115 register int last;
116 register sopno offset = 2;
117 # define GAP() { if (offset % 5 == 0) { \
118 if (col > 40) { \
119 fprintf(d, "\n\t"); \
120 col = 0; \
121 } else { \
122 fprintf(d, " "); \
123 col++; \
124 } \
125 } else \
126 col++; \
127 offset++; \
128 }
129
130 if (OP(g->strip[0]) != OEND)
131 fprintf(d, "missing initial OEND!\n");
132 for (s = &g->strip[1]; !done; s++) {
133 opnd = OPND(*s);
134 switch (OP(*s)) {
135 case OEND:
136 fprintf(d, "\n");
137 done = 1;
138 break;
139 case OCHAR:
140 if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
141 fprintf(d, "\\%c", (char)opnd);
142 else
143 fprintf(d, "%s", regchar((char)opnd));
144 break;
145 case OBOL:
146 fprintf(d, "^");
147 break;
148 case OEOL:
149 fprintf(d, "$");
150 break;
151 case OBOW:
152 fprintf(d, "\\{");
153 break;
154 case OEOW:
155 fprintf(d, "\\}");
156 break;
157 case OANY:
158 fprintf(d, ".");
159 break;
160 case OANYOF:
161 fprintf(d, "[(%ld)", (long)opnd);
162 cs = &g->sets[opnd];
163 last = -1;
164 for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */
165 if (CHIN(cs, i) && i < g->csetsize) {
166 if (last < 0) {
167 fprintf(d, "%s", regchar(i));
168 last = i;
169 }
170 } else {
171 if (last >= 0) {
172 if (last != i-1)
173 fprintf(d, "-%s",
174 regchar(i-1));
175 last = -1;
176 }
177 }
178 fprintf(d, "]");
179 break;
180 case OBACK_:
181 fprintf(d, "(\\<%ld>", (long)opnd);
182 break;
183 case O_BACK:
184 fprintf(d, "<%ld>\\)", (long)opnd);
185 break;
186 case OPLUS_:
187 fprintf(d, "(+");
188 if (OP(*(s+opnd)) != O_PLUS)
189 fprintf(d, "<%ld>", (long)opnd);
190 break;
191 case O_PLUS:
192 if (OP(*(s-opnd)) != OPLUS_)
193 fprintf(d, "<%ld>", (long)opnd);
194 fprintf(d, "+)");
195 break;
196 case OQUEST_:
197 fprintf(d, "(?");
198 if (OP(*(s+opnd)) != O_QUEST)
199 fprintf(d, "<%ld>", (long)opnd);
200 break;
201 case O_QUEST:
202 if (OP(*(s-opnd)) != OQUEST_)
203 fprintf(d, "<%ld>", (long)opnd);
204 fprintf(d, "?)");
205 break;
206 case OLPAREN:
207 fprintf(d, "((<%ld>", (long)opnd);
208 break;
209 case ORPAREN:
210 fprintf(d, "<%ld>))", (long)opnd);
211 break;
212 case OCH_:
213 fprintf(d, "<");
214 if (OP(*(s+opnd)) != OOR2)
215 fprintf(d, "<%ld>", (long)opnd);
216 break;
217 case OOR1:
218 if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
219 fprintf(d, "<%ld>", (long)opnd);
220 fprintf(d, "|");
221 break;
222 case OOR2:
223 fprintf(d, "|");
224 if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
225 fprintf(d, "<%ld>", (long)opnd);
226 break;
227 case O_CH:
228 if (OP(*(s-opnd)) != OOR1)
229 fprintf(d, "<%ld>", (long)opnd);
230 fprintf(d, ">");
231 break;
232 default:
233 fprintf(d, "!%d(%d)!", (int)(OP(*s)), (int)opnd);
234 break;
235 }
236 if (!done)
237 GAP();
238 }
239 }
240
241 /*
242 - regchar - make a character printable
243 == static char *regchar(int ch);
244 */
245 static char * /* -> representation */
regchar(int ch)246 regchar(int ch)
247 {
248 static char buf[10];
249
250 if (isprint(ch) || ch == ' ')
251 snprintf(buf, sizeof (buf), "%c", ch);
252 else
253 snprintf(buf, sizeof (buf), "\\%o", ch);
254 return(buf);
255 }
256