1314818Sngie/* $NetBSD: debug.c,v 1.3 2017/01/14 00:50:56 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 1993 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29314818Sngie#include <sys/types.h> 30272343Sngie#include <ctype.h> 31272343Sngie#include <limits.h> 32272343Sngie#include <regex.h> 33272343Sngie#include <stdio.h> 34272343Sngie#include <stdlib.h> 35272343Sngie#include <string.h> 36273011Sngie#include <wchar.h> 37273011Sngie#include <wctype.h> 38272343Sngie 39272343Sngie/* Don't sort these! */ 40272343Sngie#include "utils.h" 41272343Sngie#include "regex2.h" 42272343Sngie 43272343Sngie#include "test_regex.h" 44272343Sngie 45290869Sngie#ifdef __NetBSD__ 46272343Sngiestatic void s_print(struct re_guts *, FILE *); 47272343Sngiestatic char *regchar(int); 48272343Sngie 49272343Sngie/* 50272343Sngie * regprint - print a regexp for debugging 51272343Sngie */ 52272343Sngievoid 53272343Sngieregprint(regex_t *r, FILE *d) 54272343Sngie{ 55272343Sngie struct re_guts *g = r->re_g; 56272343Sngie int c; 57272343Sngie int last; 58272343Sngie int nincat[NC]; 59272343Sngie 60272343Sngie fprintf(d, "%ld states, %zu categories", (long)g->nstates, 61272343Sngie g->ncategories); 62272343Sngie fprintf(d, ", first %ld last %ld", (long)g->firststate, 63272343Sngie (long)g->laststate); 64272343Sngie if (g->iflags&USEBOL) 65272343Sngie fprintf(d, ", USEBOL"); 66272343Sngie if (g->iflags&USEEOL) 67272343Sngie fprintf(d, ", USEEOL"); 68272343Sngie if (g->iflags&BAD) 69272343Sngie fprintf(d, ", BAD"); 70272343Sngie if (g->nsub > 0) 71272343Sngie fprintf(d, ", nsub=%ld", (long)g->nsub); 72272343Sngie if (g->must != NULL) 73272343Sngie fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen, 74272343Sngie g->must); 75272343Sngie if (g->backrefs) 76272343Sngie fprintf(d, ", backrefs"); 77272343Sngie if (g->nplus > 0) 78272343Sngie fprintf(d, ", nplus %ld", (long)g->nplus); 79272343Sngie fprintf(d, "\n"); 80272343Sngie s_print(g, d); 81272343Sngie for (size_t i = 0; i < g->ncategories; i++) { 82272343Sngie nincat[i] = 0; 83272343Sngie for (c = CHAR_MIN; c <= CHAR_MAX; c++) 84272343Sngie if (g->categories[c] == i) 85272343Sngie nincat[i]++; 86272343Sngie } 87272343Sngie fprintf(d, "cc0#%d", nincat[0]); 88272343Sngie for (size_t i = 1; i < g->ncategories; i++) 89272343Sngie if (nincat[i] == 1) { 90272343Sngie for (c = CHAR_MIN; c <= CHAR_MAX; c++) 91272343Sngie if (g->categories[c] == i) 92272343Sngie break; 93272343Sngie fprintf(d, ", %zu=%s", i, regchar(c)); 94272343Sngie } 95272343Sngie fprintf(d, "\n"); 96272343Sngie for (size_t i = 1; i < g->ncategories; i++) 97272343Sngie if (nincat[i] != 1) { 98272343Sngie fprintf(d, "cc%zu\t", i); 99272343Sngie last = -1; 100272343Sngie for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */ 101272343Sngie if (c <= CHAR_MAX && g->categories[c] == i) { 102272343Sngie if (last < 0) { 103272343Sngie fprintf(d, "%s", regchar(c)); 104272343Sngie last = c; 105272343Sngie } 106272343Sngie } else { 107272343Sngie if (last >= 0) { 108272343Sngie if (last != c-1) 109272343Sngie fprintf(d, "-%s", 110272343Sngie regchar(c-1)); 111272343Sngie last = -1; 112272343Sngie } 113272343Sngie } 114272343Sngie fprintf(d, "\n"); 115272343Sngie } 116272343Sngie} 117272343Sngie 118272343Sngie/* 119272343Sngie * s_print - print the strip for debugging 120272343Sngie */ 121272343Sngiestatic void 122272343Sngies_print(struct re_guts *g, FILE *d) 123272343Sngie{ 124272343Sngie sop *s; 125272343Sngie cset *cs; 126272343Sngie int done = 0; 127272343Sngie sop opnd; 128272343Sngie int col = 0; 129272343Sngie ssize_t last; 130272343Sngie sopno offset = 2; 131272343Sngie# define GAP() { if (offset % 5 == 0) { \ 132272343Sngie if (col > 40) { \ 133272343Sngie fprintf(d, "\n\t"); \ 134272343Sngie col = 0; \ 135272343Sngie } else { \ 136272343Sngie fprintf(d, " "); \ 137272343Sngie col++; \ 138272343Sngie } \ 139272343Sngie } else \ 140272343Sngie col++; \ 141272343Sngie offset++; \ 142272343Sngie } 143272343Sngie 144272343Sngie if (OP(g->strip[0]) != OEND) 145272343Sngie fprintf(d, "missing initial OEND!\n"); 146272343Sngie for (s = &g->strip[1]; !done; s++) { 147272343Sngie opnd = OPND(*s); 148272343Sngie switch (OP(*s)) { 149272343Sngie case OEND: 150272343Sngie fprintf(d, "\n"); 151272343Sngie done = 1; 152272343Sngie break; 153272343Sngie case OCHAR: 154272343Sngie if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL) 155272343Sngie fprintf(d, "\\%c", (char)opnd); 156272343Sngie else 157272343Sngie fprintf(d, "%s", regchar((char)opnd)); 158272343Sngie break; 159272343Sngie case OBOL: 160272343Sngie fprintf(d, "^"); 161272343Sngie break; 162272343Sngie case OEOL: 163272343Sngie fprintf(d, "$"); 164272343Sngie break; 165272343Sngie case OBOW: 166272343Sngie fprintf(d, "\\{"); 167272343Sngie break; 168272343Sngie case OEOW: 169272343Sngie fprintf(d, "\\}"); 170272343Sngie break; 171272343Sngie case OANY: 172272343Sngie fprintf(d, "."); 173272343Sngie break; 174272343Sngie case OANYOF: 175272343Sngie fprintf(d, "[(%ld)", (long)opnd); 176272343Sngie cs = &g->sets[opnd]; 177272343Sngie last = -1; 178272343Sngie for (size_t i = 0; i < g->csetsize+1; i++) /* +1 flushes */ 179272343Sngie if (CHIN(cs, i) && i < g->csetsize) { 180272343Sngie if (last < 0) { 181272343Sngie fprintf(d, "%s", regchar(i)); 182272343Sngie last = i; 183272343Sngie } 184272343Sngie } else { 185272343Sngie if (last >= 0) { 186272343Sngie if (last != (ssize_t)i - 1) 187272343Sngie fprintf(d, "-%s", 188272343Sngie regchar(i - 1)); 189272343Sngie last = -1; 190272343Sngie } 191272343Sngie } 192272343Sngie fprintf(d, "]"); 193272343Sngie break; 194272343Sngie case OBACK_: 195272343Sngie fprintf(d, "(\\<%ld>", (long)opnd); 196272343Sngie break; 197272343Sngie case O_BACK: 198272343Sngie fprintf(d, "<%ld>\\)", (long)opnd); 199272343Sngie break; 200272343Sngie case OPLUS_: 201272343Sngie fprintf(d, "(+"); 202272343Sngie if (OP(*(s+opnd)) != O_PLUS) 203272343Sngie fprintf(d, "<%ld>", (long)opnd); 204272343Sngie break; 205272343Sngie case O_PLUS: 206272343Sngie if (OP(*(s-opnd)) != OPLUS_) 207272343Sngie fprintf(d, "<%ld>", (long)opnd); 208272343Sngie fprintf(d, "+)"); 209272343Sngie break; 210272343Sngie case OQUEST_: 211272343Sngie fprintf(d, "(?"); 212272343Sngie if (OP(*(s+opnd)) != O_QUEST) 213272343Sngie fprintf(d, "<%ld>", (long)opnd); 214272343Sngie break; 215272343Sngie case O_QUEST: 216272343Sngie if (OP(*(s-opnd)) != OQUEST_) 217272343Sngie fprintf(d, "<%ld>", (long)opnd); 218272343Sngie fprintf(d, "?)"); 219272343Sngie break; 220272343Sngie case OLPAREN: 221272343Sngie fprintf(d, "((<%ld>", (long)opnd); 222272343Sngie break; 223272343Sngie case ORPAREN: 224272343Sngie fprintf(d, "<%ld>))", (long)opnd); 225272343Sngie break; 226272343Sngie case OCH_: 227272343Sngie fprintf(d, "<"); 228272343Sngie if (OP(*(s+opnd)) != OOR2) 229272343Sngie fprintf(d, "<%ld>", (long)opnd); 230272343Sngie break; 231272343Sngie case OOR1: 232272343Sngie if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_) 233272343Sngie fprintf(d, "<%ld>", (long)opnd); 234272343Sngie fprintf(d, "|"); 235272343Sngie break; 236272343Sngie case OOR2: 237272343Sngie fprintf(d, "|"); 238272343Sngie if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH) 239272343Sngie fprintf(d, "<%ld>", (long)opnd); 240272343Sngie break; 241272343Sngie case O_CH: 242272343Sngie if (OP(*(s-opnd)) != OOR1) 243272343Sngie fprintf(d, "<%ld>", (long)opnd); 244272343Sngie fprintf(d, ">"); 245272343Sngie break; 246272343Sngie default: 247272343Sngie fprintf(d, "!%d(%d)!", OP(*s), opnd); 248272343Sngie break; 249272343Sngie } 250272343Sngie if (!done) 251272343Sngie GAP(); 252272343Sngie } 253272343Sngie} 254272343Sngie 255272343Sngie/* 256272343Sngie * regchar - make a character printable 257272343Sngie */ 258272343Sngiestatic char * /* -> representation */ 259272343Sngieregchar(int ch) 260272343Sngie{ 261272343Sngie static char buf[10]; 262272343Sngie 263272343Sngie if (isprint(ch) || ch == ' ') 264272343Sngie sprintf(buf, "%c", ch); 265272343Sngie else 266272343Sngie sprintf(buf, "\\%o", ch); 267272343Sngie return(buf); 268272343Sngie} 269290869Sngie#else 270290869Sngievoid 271290869Sngieregprint(regex_t *r, FILE *d) 272290869Sngie{ 273290869Sngie 274290869Sngie} 275290869Sngie#endif 276