1 /* $NetBSD: debug.c,v 1.2 2011/10/10 04:32:41 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1993 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <ctype.h> 30 #include <limits.h> 31 #include <regex.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 #include <sys/types.h> 37 #ifdef __FreeBSD__ 38 #include <wchar.h> 39 #include <wctype.h> 40 #endif 41 42 /* Don't sort these! */ 43 #include "utils.h" 44 #include "regex2.h" 45 46 #include "test_regex.h" 47 48 #ifdef __NetBSD__ 49 static void s_print(struct re_guts *, FILE *); 50 static char *regchar(int); 51 #endif 52 53 #ifdef __NetBSD__ 54 /* 55 * regprint - print a regexp for debugging 56 */ 57 void 58 regprint(regex_t *r, FILE *d) 59 { 60 struct re_guts *g = r->re_g; 61 int c; 62 int last; 63 int nincat[NC]; 64 65 fprintf(d, "%ld states, %zu categories", (long)g->nstates, 66 g->ncategories); 67 fprintf(d, ", first %ld last %ld", (long)g->firststate, 68 (long)g->laststate); 69 if (g->iflags&USEBOL) 70 fprintf(d, ", USEBOL"); 71 if (g->iflags&USEEOL) 72 fprintf(d, ", USEEOL"); 73 if (g->iflags&BAD) 74 fprintf(d, ", BAD"); 75 if (g->nsub > 0) 76 fprintf(d, ", nsub=%ld", (long)g->nsub); 77 if (g->must != NULL) 78 fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen, 79 g->must); 80 if (g->backrefs) 81 fprintf(d, ", backrefs"); 82 if (g->nplus > 0) 83 fprintf(d, ", nplus %ld", (long)g->nplus); 84 fprintf(d, "\n"); 85 s_print(g, d); 86 for (size_t i = 0; i < g->ncategories; i++) { 87 nincat[i] = 0; 88 for (c = CHAR_MIN; c <= CHAR_MAX; c++) 89 if (g->categories[c] == i) 90 nincat[i]++; 91 } 92 fprintf(d, "cc0#%d", nincat[0]); 93 for (size_t i = 1; i < g->ncategories; i++) 94 if (nincat[i] == 1) { 95 for (c = CHAR_MIN; c <= CHAR_MAX; c++) 96 if (g->categories[c] == i) 97 break; 98 fprintf(d, ", %zu=%s", i, regchar(c)); 99 } 100 fprintf(d, "\n"); 101 for (size_t i = 1; i < g->ncategories; i++) 102 if (nincat[i] != 1) { 103 fprintf(d, "cc%zu\t", i); 104 last = -1; 105 for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */ 106 if (c <= CHAR_MAX && g->categories[c] == i) { 107 if (last < 0) { 108 fprintf(d, "%s", regchar(c)); 109 last = c; 110 } 111 } else { 112 if (last >= 0) { 113 if (last != c-1) 114 fprintf(d, "-%s", 115 regchar(c-1)); 116 last = -1; 117 } 118 } 119 fprintf(d, "\n"); 120 } 121 } 122 123 /* 124 * s_print - print the strip for debugging 125 */ 126 static void 127 s_print(struct re_guts *g, FILE *d) 128 { 129 sop *s; 130 cset *cs; 131 int done = 0; 132 sop opnd; 133 int col = 0; 134 ssize_t last; 135 sopno offset = 2; 136 # define GAP() { if (offset % 5 == 0) { \ 137 if (col > 40) { \ 138 fprintf(d, "\n\t"); \ 139 col = 0; \ 140 } else { \ 141 fprintf(d, " "); \ 142 col++; \ 143 } \ 144 } else \ 145 col++; \ 146 offset++; \ 147 } 148 149 if (OP(g->strip[0]) != OEND) 150 fprintf(d, "missing initial OEND!\n"); 151 for (s = &g->strip[1]; !done; s++) { 152 opnd = OPND(*s); 153 switch (OP(*s)) { 154 case OEND: 155 fprintf(d, "\n"); 156 done = 1; 157 break; 158 case OCHAR: 159 if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL) 160 fprintf(d, "\\%c", (char)opnd); 161 else 162 fprintf(d, "%s", regchar((char)opnd)); 163 break; 164 case OBOL: 165 fprintf(d, "^"); 166 break; 167 case OEOL: 168 fprintf(d, "$"); 169 break; 170 case OBOW: 171 fprintf(d, "\\{"); 172 break; 173 case OEOW: 174 fprintf(d, "\\}"); 175 break; 176 case OANY: 177 fprintf(d, "."); 178 break; 179 case OANYOF: 180 fprintf(d, "[(%ld)", (long)opnd); 181 cs = &g->sets[opnd]; 182 last = -1; 183 for (size_t i = 0; i < g->csetsize+1; i++) /* +1 flushes */ 184 if (CHIN(cs, i) && i < g->csetsize) { 185 if (last < 0) { 186 fprintf(d, "%s", regchar(i)); 187 last = i; 188 } 189 } else { 190 if (last >= 0) { 191 if (last != (ssize_t)i - 1) 192 fprintf(d, "-%s", 193 regchar(i - 1)); 194 last = -1; 195 } 196 } 197 fprintf(d, "]"); 198 break; 199 case OBACK_: 200 fprintf(d, "(\\<%ld>", (long)opnd); 201 break; 202 case O_BACK: 203 fprintf(d, "<%ld>\\)", (long)opnd); 204 break; 205 case OPLUS_: 206 fprintf(d, "(+"); 207 if (OP(*(s+opnd)) != O_PLUS) 208 fprintf(d, "<%ld>", (long)opnd); 209 break; 210 case O_PLUS: 211 if (OP(*(s-opnd)) != OPLUS_) 212 fprintf(d, "<%ld>", (long)opnd); 213 fprintf(d, "+)"); 214 break; 215 case OQUEST_: 216 fprintf(d, "(?"); 217 if (OP(*(s+opnd)) != O_QUEST) 218 fprintf(d, "<%ld>", (long)opnd); 219 break; 220 case O_QUEST: 221 if (OP(*(s-opnd)) != OQUEST_) 222 fprintf(d, "<%ld>", (long)opnd); 223 fprintf(d, "?)"); 224 break; 225 case OLPAREN: 226 fprintf(d, "((<%ld>", (long)opnd); 227 break; 228 case ORPAREN: 229 fprintf(d, "<%ld>))", (long)opnd); 230 break; 231 case OCH_: 232 fprintf(d, "<"); 233 if (OP(*(s+opnd)) != OOR2) 234 fprintf(d, "<%ld>", (long)opnd); 235 break; 236 case OOR1: 237 if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_) 238 fprintf(d, "<%ld>", (long)opnd); 239 fprintf(d, "|"); 240 break; 241 case OOR2: 242 fprintf(d, "|"); 243 if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH) 244 fprintf(d, "<%ld>", (long)opnd); 245 break; 246 case O_CH: 247 if (OP(*(s-opnd)) != OOR1) 248 fprintf(d, "<%ld>", (long)opnd); 249 fprintf(d, ">"); 250 break; 251 default: 252 fprintf(d, "!%d(%d)!", OP(*s), opnd); 253 break; 254 } 255 if (!done) 256 GAP(); 257 } 258 } 259 260 /* 261 * regchar - make a character printable 262 */ 263 static char * /* -> representation */ 264 regchar(int ch) 265 { 266 static char buf[10]; 267 268 if (isprint(ch) || ch == ' ') 269 sprintf(buf, "%c", ch); 270 else 271 sprintf(buf, "\\%o", ch); 272 return(buf); 273 } 274 #else 275 void 276 regprint(regex_t *r, FILE *d) 277 { 278 279 } 280 #endif 281