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