1*d2bbb370Schristos /* $NetBSD: debug.c,v 1.7 2021/02/25 22:37:36 christos Exp $ */
217f9a364Spgoyette
317f9a364Spgoyette /*-
417f9a364Spgoyette * Copyright (c) 1993 The NetBSD Foundation, Inc.
517f9a364Spgoyette * All rights reserved.
617f9a364Spgoyette *
717f9a364Spgoyette * Redistribution and use in source and binary forms, with or without
817f9a364Spgoyette * modification, are permitted provided that the following conditions
917f9a364Spgoyette * are met:
1017f9a364Spgoyette * 1. Redistributions of source code must retain the above copyright
1117f9a364Spgoyette * notice, this list of conditions and the following disclaimer.
1217f9a364Spgoyette * 2. Redistributions in binary form must reproduce the above copyright
1317f9a364Spgoyette * notice, this list of conditions and the following disclaimer in the
1417f9a364Spgoyette * documentation and/or other materials provided with the distribution.
1517f9a364Spgoyette *
1617f9a364Spgoyette * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1717f9a364Spgoyette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1817f9a364Spgoyette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1917f9a364Spgoyette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2017f9a364Spgoyette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2117f9a364Spgoyette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2217f9a364Spgoyette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2317f9a364Spgoyette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2417f9a364Spgoyette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2517f9a364Spgoyette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2617f9a364Spgoyette * POSSIBILITY OF SUCH DAMAGE.
2717f9a364Spgoyette */
2817f9a364Spgoyette
296a94a076Schristos #include <sys/types.h>
3017f9a364Spgoyette #include <ctype.h>
3117f9a364Spgoyette #include <limits.h>
3217f9a364Spgoyette #include <regex.h>
3317f9a364Spgoyette #include <stdio.h>
3417f9a364Spgoyette #include <stdlib.h>
3517f9a364Spgoyette #include <string.h>
3617f9a364Spgoyette
37df5681bdSchristos #ifndef __linux__
3817f9a364Spgoyette /* Don't sort these! */
3917f9a364Spgoyette #include "utils.h"
4017f9a364Spgoyette #include "regex2.h"
41df5681bdSchristos #else
42df5681bdSchristos #define REGEX_NODEBUG
43df5681bdSchristos #endif
44df5681bdSchristos
45df5681bdSchristos #ifdef REGEX_TRE
46df5681bdSchristos #define REGEX_NODEBUG
47df5681bdSchristos #endif
4817f9a364Spgoyette
4917f9a364Spgoyette #include "test_regex.h"
5017f9a364Spgoyette
51df5681bdSchristos #ifndef REGEX_NODEBUG
5217f9a364Spgoyette static void s_print(struct re_guts *, FILE *);
5317f9a364Spgoyette static char *regchar(int);
54df5681bdSchristos #endif
5517f9a364Spgoyette
5617f9a364Spgoyette /*
5717f9a364Spgoyette * regprint - print a regexp for debugging
5817f9a364Spgoyette */
5917f9a364Spgoyette void
regprint(regex_t * r,FILE * d)6017f9a364Spgoyette regprint(regex_t *r, FILE *d)
6117f9a364Spgoyette {
62df5681bdSchristos #ifndef REGEX_NODEBUG
6317f9a364Spgoyette struct re_guts *g = r->re_g;
6417f9a364Spgoyette
650cd1e619Schristos fprintf(d, ", first %u last %u", g->firststate, g->laststate);
6617f9a364Spgoyette if (g->iflags&USEBOL)
6717f9a364Spgoyette fprintf(d, ", USEBOL");
6817f9a364Spgoyette if (g->iflags&USEEOL)
6917f9a364Spgoyette fprintf(d, ", USEEOL");
7017f9a364Spgoyette if (g->iflags&BAD)
7117f9a364Spgoyette fprintf(d, ", BAD");
7217f9a364Spgoyette if (g->nsub > 0)
730cd1e619Schristos fprintf(d, ", nsub=%zu", g->nsub);
7417f9a364Spgoyette if (g->must != NULL)
750cd1e619Schristos fprintf(d, ", must(%zu) `%*s'", g->mlen, (int)g->mlen, g->must);
7617f9a364Spgoyette if (g->backrefs)
7717f9a364Spgoyette fprintf(d, ", backrefs");
7817f9a364Spgoyette if (g->nplus > 0)
790cd1e619Schristos fprintf(d, ", nplus %u", g->nplus);
8017f9a364Spgoyette fprintf(d, "\n");
8117f9a364Spgoyette s_print(g, d);
8217f9a364Spgoyette fprintf(d, "\n");
83df5681bdSchristos #endif
8417f9a364Spgoyette }
8517f9a364Spgoyette
86df5681bdSchristos #ifndef REGEX_NODEBUG
8717f9a364Spgoyette /*
8817f9a364Spgoyette * s_print - print the strip for debugging
8917f9a364Spgoyette */
9017f9a364Spgoyette static void
s_print(struct re_guts * g,FILE * d)9117f9a364Spgoyette s_print(struct re_guts *g, FILE *d)
9217f9a364Spgoyette {
9317f9a364Spgoyette sop *s;
9417f9a364Spgoyette int done = 0;
9517f9a364Spgoyette sop opnd;
9617f9a364Spgoyette int col = 0;
9717f9a364Spgoyette sopno offset = 2;
9817f9a364Spgoyette # define GAP() { if (offset % 5 == 0) { \
9917f9a364Spgoyette if (col > 40) { \
10017f9a364Spgoyette fprintf(d, "\n\t"); \
10117f9a364Spgoyette col = 0; \
10217f9a364Spgoyette } else { \
10317f9a364Spgoyette fprintf(d, " "); \
10417f9a364Spgoyette col++; \
10517f9a364Spgoyette } \
10617f9a364Spgoyette } else \
10717f9a364Spgoyette col++; \
10817f9a364Spgoyette offset++; \
10917f9a364Spgoyette }
11017f9a364Spgoyette
11117f9a364Spgoyette if (OP(g->strip[0]) != OEND)
11217f9a364Spgoyette fprintf(d, "missing initial OEND!\n");
11317f9a364Spgoyette for (s = &g->strip[1]; !done; s++) {
11417f9a364Spgoyette opnd = OPND(*s);
11517f9a364Spgoyette switch (OP(*s)) {
11617f9a364Spgoyette case OEND:
11717f9a364Spgoyette fprintf(d, "\n");
11817f9a364Spgoyette done = 1;
11917f9a364Spgoyette break;
12017f9a364Spgoyette case OCHAR:
12117f9a364Spgoyette if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
12217f9a364Spgoyette fprintf(d, "\\%c", (char)opnd);
12317f9a364Spgoyette else
12417f9a364Spgoyette fprintf(d, "%s", regchar((char)opnd));
12517f9a364Spgoyette break;
12617f9a364Spgoyette case OBOL:
12717f9a364Spgoyette fprintf(d, "^");
12817f9a364Spgoyette break;
12917f9a364Spgoyette case OEOL:
13017f9a364Spgoyette fprintf(d, "$");
13117f9a364Spgoyette break;
13217f9a364Spgoyette case OBOW:
13317f9a364Spgoyette fprintf(d, "\\{");
13417f9a364Spgoyette break;
13517f9a364Spgoyette case OEOW:
13617f9a364Spgoyette fprintf(d, "\\}");
13717f9a364Spgoyette break;
13817f9a364Spgoyette case OANY:
13917f9a364Spgoyette fprintf(d, ".");
14017f9a364Spgoyette break;
14117f9a364Spgoyette case OANYOF:
1420cd1e619Schristos fprintf(d, "[(%u)", opnd);
14317f9a364Spgoyette fprintf(d, "]");
14417f9a364Spgoyette break;
14517f9a364Spgoyette case OBACK_:
1460cd1e619Schristos fprintf(d, "(\\<%u>", opnd);
14717f9a364Spgoyette break;
14817f9a364Spgoyette case O_BACK:
1490cd1e619Schristos fprintf(d, "<%u>\\)", opnd);
15017f9a364Spgoyette break;
15117f9a364Spgoyette case OPLUS_:
15217f9a364Spgoyette fprintf(d, "(+");
15317f9a364Spgoyette if (OP(*(s+opnd)) != O_PLUS)
1540cd1e619Schristos fprintf(d, "<%u>", opnd);
15517f9a364Spgoyette break;
15617f9a364Spgoyette case O_PLUS:
15717f9a364Spgoyette if (OP(*(s-opnd)) != OPLUS_)
1580cd1e619Schristos fprintf(d, "<%u>", opnd);
15917f9a364Spgoyette fprintf(d, "+)");
16017f9a364Spgoyette break;
16117f9a364Spgoyette case OQUEST_:
16217f9a364Spgoyette fprintf(d, "(?");
16317f9a364Spgoyette if (OP(*(s+opnd)) != O_QUEST)
1640cd1e619Schristos fprintf(d, "<%u>", opnd);
16517f9a364Spgoyette break;
16617f9a364Spgoyette case O_QUEST:
16717f9a364Spgoyette if (OP(*(s-opnd)) != OQUEST_)
1680cd1e619Schristos fprintf(d, "<%u>", opnd);
16917f9a364Spgoyette fprintf(d, "?)");
17017f9a364Spgoyette break;
17117f9a364Spgoyette case OLPAREN:
1720cd1e619Schristos fprintf(d, "((<%u>", opnd);
17317f9a364Spgoyette break;
17417f9a364Spgoyette case ORPAREN:
1750cd1e619Schristos fprintf(d, "<%u>))", opnd);
17617f9a364Spgoyette break;
17717f9a364Spgoyette case OCH_:
17817f9a364Spgoyette fprintf(d, "<");
1790cd1e619Schristos if (OP(*(s+opnd)) != OOR2)
1800cd1e619Schristos fprintf(d, "<%u>", opnd);
18117f9a364Spgoyette break;
18217f9a364Spgoyette case OOR1:
1830cd1e619Schristos if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
1840cd1e619Schristos fprintf(d, "<%u>", opnd);
18517f9a364Spgoyette fprintf(d, "|");
18617f9a364Spgoyette break;
18717f9a364Spgoyette case OOR2:
18817f9a364Spgoyette fprintf(d, "|");
1890cd1e619Schristos if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
1900cd1e619Schristos fprintf(d, "<%u>", opnd);
19117f9a364Spgoyette break;
19217f9a364Spgoyette case O_CH:
1930cd1e619Schristos if (OP(*(s-opnd)) != OOR1)
1940cd1e619Schristos fprintf(d, "<%u>", opnd);
19517f9a364Spgoyette fprintf(d, ">");
19617f9a364Spgoyette break;
19717f9a364Spgoyette default:
1980cd1e619Schristos fprintf(d, "!%u(%u)!", OP(*s), opnd);
19917f9a364Spgoyette break;
20017f9a364Spgoyette }
20117f9a364Spgoyette if (!done)
20217f9a364Spgoyette GAP();
20317f9a364Spgoyette }
20417f9a364Spgoyette }
20517f9a364Spgoyette
20617f9a364Spgoyette /*
20717f9a364Spgoyette * regchar - make a character printable
20817f9a364Spgoyette */
20917f9a364Spgoyette static char * /* -> representation */
regchar(int ch)21017f9a364Spgoyette regchar(int ch)
21117f9a364Spgoyette {
21217f9a364Spgoyette static char buf[10];
21317f9a364Spgoyette
21417f9a364Spgoyette if (isprint(ch) || ch == ' ')
21517f9a364Spgoyette sprintf(buf, "%c", ch);
21617f9a364Spgoyette else
21717f9a364Spgoyette sprintf(buf, "\\%o", ch);
21817f9a364Spgoyette return(buf);
21917f9a364Spgoyette }
220df5681bdSchristos #endif
221