debug.c revision 312092
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__ 49static void s_print(struct re_guts *, FILE *); 50static char *regchar(int); 51 52/* 53 * regprint - print a regexp for debugging 54 */ 55void 56regprint(regex_t *r, FILE *d) 57{ 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} 120 121/* 122 * s_print - print the strip for debugging 123 */ 124static void 125s_print(struct re_guts *g, FILE *d) 126{ 127 sop *s; 128 cset *cs; 129 int done = 0; 130 sop opnd; 131 int col = 0; 132 ssize_t last; 133 sopno offset = 2; 134# define GAP() { if (offset % 5 == 0) { \ 135 if (col > 40) { \ 136 fprintf(d, "\n\t"); \ 137 col = 0; \ 138 } else { \ 139 fprintf(d, " "); \ 140 col++; \ 141 } \ 142 } else \ 143 col++; \ 144 offset++; \ 145 } 146 147 if (OP(g->strip[0]) != OEND) 148 fprintf(d, "missing initial OEND!\n"); 149 for (s = &g->strip[1]; !done; s++) { 150 opnd = OPND(*s); 151 switch (OP(*s)) { 152 case OEND: 153 fprintf(d, "\n"); 154 done = 1; 155 break; 156 case OCHAR: 157 if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL) 158 fprintf(d, "\\%c", (char)opnd); 159 else 160 fprintf(d, "%s", regchar((char)opnd)); 161 break; 162 case OBOL: 163 fprintf(d, "^"); 164 break; 165 case OEOL: 166 fprintf(d, "$"); 167 break; 168 case OBOW: 169 fprintf(d, "\\{"); 170 break; 171 case OEOW: 172 fprintf(d, "\\}"); 173 break; 174 case OANY: 175 fprintf(d, "."); 176 break; 177 case OANYOF: 178 fprintf(d, "[(%ld)", (long)opnd); 179 cs = &g->sets[opnd]; 180 last = -1; 181 for (size_t i = 0; i < g->csetsize+1; i++) /* +1 flushes */ 182 if (CHIN(cs, i) && i < g->csetsize) { 183 if (last < 0) { 184 fprintf(d, "%s", regchar(i)); 185 last = i; 186 } 187 } else { 188 if (last >= 0) { 189 if (last != (ssize_t)i - 1) 190 fprintf(d, "-%s", 191 regchar(i - 1)); 192 last = -1; 193 } 194 } 195 fprintf(d, "]"); 196 break; 197 case OBACK_: 198 fprintf(d, "(\\<%ld>", (long)opnd); 199 break; 200 case O_BACK: 201 fprintf(d, "<%ld>\\)", (long)opnd); 202 break; 203 case OPLUS_: 204 fprintf(d, "(+"); 205 if (OP(*(s+opnd)) != O_PLUS) 206 fprintf(d, "<%ld>", (long)opnd); 207 break; 208 case O_PLUS: 209 if (OP(*(s-opnd)) != OPLUS_) 210 fprintf(d, "<%ld>", (long)opnd); 211 fprintf(d, "+)"); 212 break; 213 case OQUEST_: 214 fprintf(d, "(?"); 215 if (OP(*(s+opnd)) != O_QUEST) 216 fprintf(d, "<%ld>", (long)opnd); 217 break; 218 case O_QUEST: 219 if (OP(*(s-opnd)) != OQUEST_) 220 fprintf(d, "<%ld>", (long)opnd); 221 fprintf(d, "?)"); 222 break; 223 case OLPAREN: 224 fprintf(d, "((<%ld>", (long)opnd); 225 break; 226 case ORPAREN: 227 fprintf(d, "<%ld>))", (long)opnd); 228 break; 229 case OCH_: 230 fprintf(d, "<"); 231 if (OP(*(s+opnd)) != OOR2) 232 fprintf(d, "<%ld>", (long)opnd); 233 break; 234 case OOR1: 235 if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_) 236 fprintf(d, "<%ld>", (long)opnd); 237 fprintf(d, "|"); 238 break; 239 case OOR2: 240 fprintf(d, "|"); 241 if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH) 242 fprintf(d, "<%ld>", (long)opnd); 243 break; 244 case O_CH: 245 if (OP(*(s-opnd)) != OOR1) 246 fprintf(d, "<%ld>", (long)opnd); 247 fprintf(d, ">"); 248 break; 249 default: 250 fprintf(d, "!%d(%d)!", OP(*s), opnd); 251 break; 252 } 253 if (!done) 254 GAP(); 255 } 256} 257 258/* 259 * regchar - make a character printable 260 */ 261static char * /* -> representation */ 262regchar(int ch) 263{ 264 static char buf[10]; 265 266 if (isprint(ch) || ch == ' ') 267 sprintf(buf, "%c", ch); 268 else 269 sprintf(buf, "\\%o", ch); 270 return(buf); 271} 272#else 273void 274regprint(regex_t *r, FILE *d) 275{ 276 277} 278#endif 279