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