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