/************************************************************ * This file is needed if the DEBUGGING macro is defined. * It supplies convenience functions for debugging the program * or examining its workings. ************************************************************/ #include #include #include "re.h" #ifdef DEBUG static char *types[] = {" OR", "AND", "~OR"}; // print out a node in a standard format void dbNode(struct node *node, VD_INT4 recurse) { char range[100]; char quote; char *not = NULL; VD_INT4 which; if (node) { if ((node->min != 1) || (node->max != 1)) { sprintf(range, "[%d - %u] ", node->min, node->max); } else { range[0] = 0; } which= 0; quote = (node->type & N_QUOTE) ? '"' : ' '; switch (node->type & TYPEMASK) { case N_NOTOR: which++; case N_AND: which++; case N_OR: printf("%*s%c%s%d%s\n", recurse, "", quote, types[which], node->id, range); if (recurse) { dbNode(node->d.logic.root, recurse + 2); } break; case N_RANGE: printf("%*s%cRANGE%d%s from %c to %c\n", recurse, "", quote, node->id, range, node->d.range.low, node->d.range.high); break; case N_STRING: printf("%*s%cSTRING%d%s %.*s\n", recurse, "", quote, node->id, range, node->d.string.len, node->d.string.start); break; case N_MEMBER: printf("%*s%cMEMBER%d %s %.*s\n", recurse, "", quote, node->id, range, node->d.string.len, node->d.string.start); break; case N_SUCCESS: printf("%*s SUCCESS\n", recurse, ""); break; case N_STATIC: break; default: printf("%*sUNKNOWN TYPE %d\n", recurse, node->type); } if (recurse) { dbNode(node->link, recurse); } } } // print out the entire parse tree void dbTree(struct node *root) { dbNode(root, 2); } // print out a state in standard format void state(struct state *state) { char *action; if (state->nextAction & A_CHAIN) action = "CHAIN "; else if (state->nextAction & A_REPEAT) action = "REPEAT"; else action = "FAIL "; printf("%3d%4d %s %10.10s: ", state->count, state->parent, action, state->ptr); dbNode(state->node, 0); } // print out a state frame in a standard format void dbState(struct stateStack *stack, VD_INT4 depth) { if (depth < 0) { depth = VDI_topFrame(stack); } printf("%3d:", depth); state(VDI_getState(stack, depth)); } // print out the entire execution stack void dbStack(struct stateStack *stack) { VD_INT4 i; printf("Stack depth = %d, allocated = %d\n", stack->ptr, stack->allocated); for (i = 0; i < stack->ptr; i++) { dbState(stack, i); } printf("\n"); } // print out the results structure void dbResults(struct VD_RE_Result *result, VD_INT4 depth) { printf("%*s'%.*s'\n", depth, "", result->len, result->start); if (result->contains) { dbResults(result->contains, depth + 2); } if (result->chain) { dbResults(result->chain, depth); } } void dbSummary(struct stateStack *stack) { printf("Final stack size %d, maximum stack size %d, allocated stack %d\n", stack->ptr, stack->maxSize, stack->allocated); printf("Iterations: %d; Total frames pushed: %d; total times backtracked: %d\n", stack->iterations, stack->pushed, stack->failed); } static VD_INT4 counters[] = {0, 0, 0, 0, 0, 0}; // give a unique ID number for each node of a given type void nextID(VD_INT4 *p, VD_INT4 type) { switch(type & TYPEMASK) { case N_AND: *p = counters[0]++; break; case N_OR: *p = counters[1]++; break; case N_STRING: *p = counters[2]++; break; case N_MEMBER: *p = counters[3]++; break; case N_RANGE: *p = counters[4]++; break; case N_NOTOR: *p = counters[5]++; break; case N_SUCCESS: break; default: printf("unexpected type value of 0X%x in NEXTID\n", type); } } #endif