/* dbug.c - debugging routines for rx
*
****************************************************************
* Copyright (C) 1998, 2000 Thomas Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/char/char-name.h"
#include "hackerlab/char/char-class.h"
#include "hackerlab/uni/coding.h"
#include "hackerlab/bitsets/bits.h"
#include "hackerlab/vu/vu.h"
#include "hackerlab/vu/printfmt.h"
#include "hackerlab/rx/dbug.h"
/************************************************************************
*(h0 "Rx Debugging Functions"
* :include ("rx/dbug.h"))
*
*
* The functions in this section are for printing debugging information
* from applications that use Rx.
*/
#ifdef HAVE_POSITIONAL_ARRAY_INITS
#define AT(X) [X] =
#else
#define AT(X)
#endif
#define RX_EXP_NODE_TYPE_NAME(X) #X,
static char *node_type_names[] =
{
RX_EXP_NODE_TYPES(NAME)
};
static void
print_cset_char (int fd, int x)
{
int errn;
if ((x == ']') || (x == '[') || (x == '-') || (x == '^'))
printfmt (&errn, fd, "\\%c", x);
else if (x < 256)
printfmt (&errn, fd, "%s", char_name[x]);
else
printfmt (&errn, fd, "\\u%04x", x);
}
static void
print_cset (int fd, int cset_size, bits cs)
{
int x;
int errn;
if (!cs)
printfmt (&errn, fd, "nil");
else
{
printfmt (&errn, fd, "[");
x = 0;
while (x < cset_size)
{
int y;
x = bits_ffs_range (cs, x, cset_size);
if (x < 0)
break;
y = bits_ffc_range (cs, x, cset_size);
if (y < 0)
y = cset_size + 1;
print_cset_char (fd, x);
if ((y - 1) != x)
{
printfmt (&errn, fd, "-");
print_cset_char (fd, (y - 1));
}
x = y;
}
printfmt (&errn, fd, "]");
}
}
static void
print_string (int fd, enum uni_encoding_scheme encoding, t_uchar * str, size_t str_len, t_uchar bracket)
{
int errn;
if (!str && bracket)
printfmt (&errn, fd, "nil");
else
{
size_t pos;
if (bracket)
printfmt (&errn, fd, "\"");
pos = 0;
while (pos < str_len)
{
t_unicode c;
c = (uni_encoding_iscan_fn (encoding)) (str, &pos, str_len);
if (c < 256)
printfmt (&errn, fd, "%s", char_name[c]);
else
print_cset_char (fd, c);
}
if (bracket)
printfmt (&errn, fd, "\"");
}
}
static void
spaces (int fd, int n)
{
int errn;
while (n--)
printfmt (&errn, fd, " ");
}
/*(c rx_print_rexp)
* void rx_print_rexp (int fd,
* int cset_size,
* int indent,
* struct rx_exp_node * rexp);
*
* Print the expression `rexp' as a list of nodes, using indenting to
* indicate subexpression nesting. See xref:"Regexp Expression
* Trees".
*
* `fd' is the descriptor on which to print the expression.
*
* `cset_size' is the character set size of the expression (usually
* 256).
*
* `indent' is the initial level of indenting for the printed
* expression (usually 0).
*/
void
rx_print_rexp (int fd,
int cset_size,
int indent,
struct rx_exp_node * rexp)
{
int errn;
spaces (fd, indent);
if (!rexp)
printfmt (&errn, fd, "nil\n");
else
{
printfmt (&errn, fd,
"Node %lx type %d (%s), iv=%ld(%c), iv2=%ld, len=%ld obs=%d max_paren=%d, min_paren=%d cs=",
(unsigned long) rexp,
rexp->type,
node_type_names[rexp->type],
rexp->intval,
(( (0 <= rexp->intval)
&& (256 > rexp->intval)
&& char_is_printable (rexp->intval))
? (char)rexp->intval
: ' '),
rexp->intval2,
rexp->len,
rexp->observed,
rexp->max_enclosed_paren,
rexp->min_enclosed_paren);
print_cset (fd, cset_size, rexp->cset);
printfmt (&errn, fd, " s=");
print_string (fd, rexp->encoding, rexp->str, rexp->str_len, 1);
printfmt (&errn, fd, "\n");
if (rexp->left || rexp->right)
{
rx_print_rexp (fd, cset_size, indent + 2, rexp->left);
rx_print_rexp (fd, cset_size, indent + 2, rexp->right);
}
}
}
/*(c rx_unparse_print_rexp)
* void rx_unparse_print_rexp (int fd,
* int cset_size,
* struct rx_exp_node * rexp);
*
* Print the expression `rexp' using regexp syntax.
* See xref:"Regexp Expression Trees".
*/
void
rx_unparse_print_rexp (int fd,
int cset_size,
struct rx_exp_node * rexp)
{
int errn;
if (!rexp)
return;
else
switch (rexp->type)
{
case r_cset:
if (1 != bits_population (rexp->cset))
print_cset (fd, cset_size, rexp->cset);
else
{
int x;
x = bits_ffs (rexp->cset);
print_cset_char (fd, x);
}
break;
case r_string:
print_string (fd, rexp->encoding, rexp->str, rexp->str_len, 0);
break;
case r_parens:
printfmt (&errn, fd, "(");
rx_unparse_print_rexp (fd, cset_size, rexp->left);
printfmt (&errn, fd, ")");
break;
case r_context:
printfmt (&errn, fd, "\\%c", (char)rexp->intval);
break;
case r_cut:
printfmt (&errn, fd, "[[:cut %ld:]]", rexp->intval);
break;
case r_concat:
rx_unparse_print_rexp (fd, cset_size, rexp->left);
rx_unparse_print_rexp (fd, cset_size, rexp->right);
break;
case r_right_concat:
rx_unparse_print_rexp (fd, cset_size, rexp->left);
rx_unparse_print_rexp (fd, cset_size, rexp->right);
break;
case r_alternate:
rx_unparse_print_rexp (fd, cset_size, rexp->left);
printfmt (&errn, fd, "|");
rx_unparse_print_rexp (fd, cset_size, rexp->right);
break;
case r_star:
rx_unparse_print_rexp (fd, cset_size, rexp->left);
printfmt (&errn, fd, "*");
break;
case r_interval:
rx_unparse_print_rexp (fd, cset_size, rexp->left);
printfmt (&errn, fd, "{%ld,%ld}", rexp->intval, rexp->intval2);
break;
}
}
static void
rx_print_nfa_state (int fd, struct rx_nfa * rx, struct rx_nfa_state * state)
{
int errn;
struct rx_nfa_edge * e;
printfmt (&errn, fd,
"state %d, state_label %ld, is_start %d\n",
state->id, state->state_label, state->is_start);
for (e = state->edges; e; e = e->next)
{
printfmt (&errn, fd,
"\tEdge %s to %d ",
(e->type == ne_cset
? "cset"
: (e->type == ne_epsilon
? "epsilon"
: "side effect")),
e->dest->id);
if (e->type == ne_cset)
print_cset (fd, rx->local_cset_size, e->cset);
else
printfmt (&errn, fd, "epsilon");
printfmt (&errn, fd, "\n");
}
}
/*(c rx_print_nfa)
* void rx_print_nfa (int fd, struct rx_nfa * rx);
*
* Print the NFA `rx' as a list of nodes and edges. See
* xref:"Non-deterministic Finite-state Automata".
*
* `fd' is the descriptor on which to print the NFA.
*/
void
rx_print_nfa (int fd, struct rx_nfa * rx)
{
struct rx_nfa_state * state;
for (state = rx->nfa_states; state; state = state->next)
rx_print_nfa_state (fd, rx, state);
}
/*(c rx_print_superstate)
* void rx_print_superstate (int fd, struct rx_superstate * state);
*
* Print the DFA state `state' as a list of the NFA states that it
* contains. See xref:"The Superstate DFA".
*
* `fd' is the descriptor on which to print the NFA.
*/
void
rx_print_superstate (int fd, struct rx_superstate * state)
{
struct rx_superset * set;
int errn;
printfmt (&errn, fd, "superstate: ");
set = state->members;
while (set->car)
{
printfmt (&errn, fd, "%d ", set->car->id);
set = set->cdr;
}
printfmt (&errn, fd, "\n");
}
syntax highlighted by Code2HTML, v. 0.9.1