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