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