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