debug.c revision 92889
1251839Sbapt/* $FreeBSD: head/lib/libc/regex/grot/debug.c 92889 2002-03-21 18:49:23Z obrien $
2251839Sbapt */
3251839Sbapt#include <stdio.h>
4251839Sbapt#include <string.h>
5251839Sbapt#include <ctype.h>
6251839Sbapt#include <limits.h>
7251839Sbapt#include <stdlib.h>
8251839Sbapt#include <sys/types.h>
9251839Sbapt#include <regex.h>
10251839Sbapt
11251839Sbapt#include "utils.h"
12251839Sbapt#include "regex2.h"
13251839Sbapt#include "debug.ih"
14251839Sbapt
15251839Sbapt/*
16251839Sbapt - regprint - print a regexp for debugging
17251839Sbapt == void regprint(regex_t *r, FILE *d);
18251839Sbapt */
19251839Sbaptvoid
20251839Sbaptregprint(r, d)
21251839Sbaptregex_t *r;
22251839SbaptFILE *d;
23251839Sbapt{
24251839Sbapt	struct re_guts *g = r->re_g;
25251839Sbapt	int i;
26251839Sbapt	int c;
27251839Sbapt	int last;
28251839Sbapt	int nincat[NC];
29251839Sbapt
30251839Sbapt	fprintf(d, "%ld states, %d categories", (long)g->nstates,
31251839Sbapt							g->ncategories);
32251839Sbapt	fprintf(d, ", first %ld last %ld", (long)g->firststate,
33251839Sbapt						(long)g->laststate);
34251839Sbapt	if (g->iflags&USEBOL)
35251839Sbapt		fprintf(d, ", USEBOL");
36251839Sbapt	if (g->iflags&USEEOL)
37251839Sbapt		fprintf(d, ", USEEOL");
38251839Sbapt	if (g->iflags&BAD)
39251839Sbapt		fprintf(d, ", BAD");
40251839Sbapt	if (g->nsub > 0)
41251839Sbapt		fprintf(d, ", nsub=%ld", (long)g->nsub);
42251839Sbapt	if (g->must != NULL)
43251839Sbapt		fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
44								g->must);
45	if (g->backrefs)
46		fprintf(d, ", backrefs");
47	if (g->nplus > 0)
48		fprintf(d, ", nplus %ld", (long)g->nplus);
49	fprintf(d, "\n");
50	s_print(g, d);
51	for (i = 0; i < g->ncategories; i++) {
52		nincat[i] = 0;
53		for (c = CHAR_MIN; c <= CHAR_MAX; c++)
54			if (g->categories[c] == i)
55				nincat[i]++;
56	}
57	fprintf(d, "cc0#%d", nincat[0]);
58	for (i = 1; i < g->ncategories; i++)
59		if (nincat[i] == 1) {
60			for (c = CHAR_MIN; c <= CHAR_MAX; c++)
61				if (g->categories[c] == i)
62					break;
63			fprintf(d, ", %d=%s", i, regchar(c));
64		}
65	fprintf(d, "\n");
66	for (i = 1; i < g->ncategories; i++)
67		if (nincat[i] != 1) {
68			fprintf(d, "cc%d\t", i);
69			last = -1;
70			for (c = CHAR_MIN; c <= CHAR_MAX+1; c++)	/* +1 does flush */
71				if (c <= CHAR_MAX && g->categories[c] == i) {
72					if (last < 0) {
73						fprintf(d, "%s", regchar(c));
74						last = c;
75					}
76				} else {
77					if (last >= 0) {
78						if (last != c-1)
79							fprintf(d, "-%s",
80								regchar(c-1));
81						last = -1;
82					}
83				}
84			fprintf(d, "\n");
85		}
86}
87
88/*
89 - s_print - print the strip for debugging
90 == static void s_print(struct re_guts *g, FILE *d);
91 */
92static void
93s_print(g, d)
94struct re_guts *g;
95FILE *d;
96{
97	sop *s;
98	cset *cs;
99	int i;
100	int done = 0;
101	sop opnd;
102	int col = 0;
103	int last;
104	sopno offset = 2;
105#	define	GAP()	{	if (offset % 5 == 0) { \
106					if (col > 40) { \
107						fprintf(d, "\n\t"); \
108						col = 0; \
109					} else { \
110						fprintf(d, " "); \
111						col++; \
112					} \
113				} else \
114					col++; \
115				offset++; \
116			}
117
118	if (OP(g->strip[0]) != OEND)
119		fprintf(d, "missing initial OEND!\n");
120	for (s = &g->strip[1]; !done; s++) {
121		opnd = OPND(*s);
122		switch (OP(*s)) {
123		case OEND:
124			fprintf(d, "\n");
125			done = 1;
126			break;
127		case OCHAR:
128			if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
129				fprintf(d, "\\%c", (char)opnd);
130			else
131				fprintf(d, "%s", regchar((char)opnd));
132			break;
133		case OBOL:
134			fprintf(d, "^");
135			break;
136		case OEOL:
137			fprintf(d, "$");
138			break;
139		case OBOW:
140			fprintf(d, "\\{");
141			break;
142		case OEOW:
143			fprintf(d, "\\}");
144			break;
145		case OANY:
146			fprintf(d, ".");
147			break;
148		case OANYOF:
149			fprintf(d, "[(%ld)", (long)opnd);
150			cs = &g->sets[opnd];
151			last = -1;
152			for (i = 0; i < g->csetsize+1; i++)	/* +1 flushes */
153				if (CHIN(cs, i) && i < g->csetsize) {
154					if (last < 0) {
155						fprintf(d, "%s", regchar(i));
156						last = i;
157					}
158				} else {
159					if (last >= 0) {
160						if (last != i-1)
161							fprintf(d, "-%s",
162								regchar(i-1));
163						last = -1;
164					}
165				}
166			fprintf(d, "]");
167			break;
168		case OBACK_:
169			fprintf(d, "(\\<%ld>", (long)opnd);
170			break;
171		case O_BACK:
172			fprintf(d, "<%ld>\\)", (long)opnd);
173			break;
174		case OPLUS_:
175			fprintf(d, "(+");
176			if (OP(*(s+opnd)) != O_PLUS)
177				fprintf(d, "<%ld>", (long)opnd);
178			break;
179		case O_PLUS:
180			if (OP(*(s-opnd)) != OPLUS_)
181				fprintf(d, "<%ld>", (long)opnd);
182			fprintf(d, "+)");
183			break;
184		case OQUEST_:
185			fprintf(d, "(?");
186			if (OP(*(s+opnd)) != O_QUEST)
187				fprintf(d, "<%ld>", (long)opnd);
188			break;
189		case O_QUEST:
190			if (OP(*(s-opnd)) != OQUEST_)
191				fprintf(d, "<%ld>", (long)opnd);
192			fprintf(d, "?)");
193			break;
194		case OLPAREN:
195			fprintf(d, "((<%ld>", (long)opnd);
196			break;
197		case ORPAREN:
198			fprintf(d, "<%ld>))", (long)opnd);
199			break;
200		case OCH_:
201			fprintf(d, "<");
202			if (OP(*(s+opnd)) != OOR2)
203				fprintf(d, "<%ld>", (long)opnd);
204			break;
205		case OOR1:
206			if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
207				fprintf(d, "<%ld>", (long)opnd);
208			fprintf(d, "|");
209			break;
210		case OOR2:
211			fprintf(d, "|");
212			if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
213				fprintf(d, "<%ld>", (long)opnd);
214			break;
215		case O_CH:
216			if (OP(*(s-opnd)) != OOR1)
217				fprintf(d, "<%ld>", (long)opnd);
218			fprintf(d, ">");
219			break;
220		default:
221			fprintf(d, "!%d(%d)!", OP(*s), opnd);
222			break;
223		}
224		if (!done)
225			GAP();
226	}
227}
228
229/*
230 - regchar - make a character printable
231 == static char *regchar(int ch);
232 */
233static char *			/* -> representation */
234regchar(ch)
235int ch;
236{
237	static char buf[10];
238
239	if (isprint(ch) || ch == ' ')
240		sprintf(buf, "%c", ch);
241	else
242		sprintf(buf, "\\%o", ch);
243	return(buf);
244}
245