// crm114_.c - Controllable Regex Mutilator, version v1.0
// Copyright 2001-2006 William S. Yerazunis, all rights reserved.
//
// This software is licensed to the public under the Free Software
// Foundation's GNU GPL, version 2. You may obtain a copy of the
// GPL by visiting the Free Software Foundations web site at
// www.fsf.org, and a copy is included in this distribution.
//
// Other licenses may be negotiated; contact the
// author for details.
//
// include some standard files
#include "crm114_sysincludes.h"
// include any local crm114 configuration file
#include "crm114_config.h"
// include the crm114 data structures file
#include "crm114_structs.h"
// and include the routine declarations file
#include "crm114.h"
// the command line argc, argv
extern int prog_argc;
extern char **prog_argv;
// the auxilliary input buffer (for WINDOW input)
extern char *newinputbuf;
// the globals used when we need a big buffer - allocated once, used
// wherever needed. These are sized to the same size as the data window.
extern char *inbuf;
extern char *outbuf;
extern char *tempbuf;
// If we got to here, we need to run some user-interfacing
// (i.e. debugging).
//
// possible return values:
// 1: reparse and continue execution
// -1: exit immediately
// 0: continue
long crm_debugger ()
{
long ichar;
static int firsttime = 1;
static FILE *mytty;
if (firsttime)
{
fprintf (stderr, "CRM114 Debugger - type \"h\" for help. ");
fprintf (stderr, "User trace turned on.\n");
user_trace = 1;
firsttime = 0;
if (user_trace)
fprintf (stderr, "Opening the user terminal for debugging I/O\n");
#ifdef POSIX
mytty = fopen ("/dev/tty", "rb");
#endif
#ifdef WIN32
mytty = fopen ("CON", "rb");
#endif
clearerr (mytty);
};
if (csl->mct[csl->cstmt]->stmt_break > 0)
fprintf (stderr, "Breakpoint tripped at statement %ld\n", csl->cstmt);
debug_top:
// let the user know they're in the debugger
//
fprintf (stderr, "\ncrm-dbg> ");
// find out what they want to do
//
ichar = 0;
while (!feof (mytty)
&& ichar < data_window_size - 1
&& (inbuf [ichar-1] != '\n' ) )
{
inbuf[ichar] = fgetc (mytty);
ichar++;
};
inbuf [ichar] = '\000';
if (feof (mytty) )
{
fprintf (stderr, "Quitting\n");
if (engine_exit_base != 0)
{
exit (engine_exit_base + 8);
}
else
exit ( EXIT_SUCCESS );
};
// now a big siwtch statement on the first character of the command
//
switch (inbuf[0])
{
case 'q':
case 'Q':
{
if (user_trace)
fprintf (stderr, "Quitting.\n");
if (engine_exit_base != 0)
{
exit (engine_exit_base + 9);
}
else
exit ( EXIT_SUCCESS );
};
break;
case 'n':
case 'N':
{
debug_countdown = 0;
return (0);
}
break;
case 'c':
case 'C':
{
sscanf (&inbuf[1], "%ld", &debug_countdown);
if (debug_countdown <= 0)
{
debug_countdown = -1;
fprintf (stderr, "continuing execution...\n");
}
else
{
fprintf (stderr, "continuing %ld cycles...\n", debug_countdown);
};
return (0);
};
break;
case 't':
if (user_trace == 0 )
{
user_trace = 1 ;
fprintf (stderr, "User tracing on");
}
else
{
user_trace = 0;
fprintf (stderr, "User tracing off");
};
break;
case 'T':
if (internal_trace == 0 )
{
internal_trace = 1 ;
fprintf (stderr, "Internal tracing on");
}
else
{
internal_trace = 0;
fprintf (stderr, "Internal tracing off");
};
break;
case 'e':
{
fprintf (stderr, "expanding: \n");
memmove (inbuf, &inbuf[1], strlen (inbuf) -1);
crm_nexpandvar (inbuf, strlen(inbuf) -1, data_window_size);
fprintf (stderr, "%s", inbuf);
};
break;
case 'i':
{
fprintf (stderr, "Isolating %s", &inbuf[1]);
fprintf (stderr, "NOT YET IMPLEMENTED! Sorry. \n");
}
break;
case 'v':
{
long i, j;
long stmtnum;
i = sscanf (&inbuf[1], "%ld", &stmtnum);
if (i > 0)
{
fprintf (stderr, "statement %ld: ", stmtnum);
if ( stmtnum < 0 || stmtnum > csl->nstmts)
{
fprintf (stderr, "... does not exist!\n");
}
else
{
for ( j = csl->mct[stmtnum]->start;
j < csl->mct[stmtnum+1]->start;
j++)
{
fprintf (stderr, "%c", csl->filetext[j]);
};
};
}
else
{
fprintf (stderr, "What statement do you want to view?\n");
}
};
break;
case 'j':
{
long nextstmt;
long i;
long vindex;
i = sscanf (&inbuf[1], "%ld", &nextstmt);
if (i == 0)
{
// maybe the user put in a label?
long tstart;
long tlen;
crm_nextword (&inbuf[1], strlen (&inbuf[1]), 0,
&tstart, &tlen);
memmove (inbuf, &inbuf[1+tstart], tlen);
inbuf[tlen] = '\000';
vindex= crm_vht_lookup (vht, inbuf, tlen);
if (vht[vindex] == NULL)
{
fprintf (stderr, "No label '%s' in this program. ", inbuf);
fprintf (stderr, "Staying at line %ld\n", csl->cstmt);
nextstmt = csl->cstmt;
}
else
{
nextstmt = vht[vindex]->linenumber;
};
};
if (nextstmt <= 0)
{
nextstmt = 0;
}
if (nextstmt >= csl->nstmts)
{
nextstmt = csl-> nstmts;
fprintf (stderr, "last statement is %ld, assume you meant that.\n",
csl->nstmts);
};
if (csl->cstmt != nextstmt)
fprintf (stderr, "Next statement is statement %ld\n", nextstmt);
csl->cstmt = nextstmt;
}
return (1);
break;
case 'b':
{ // is there a breakpoint to make?
long breakstmt;
long i;
long vindex;
breakstmt = -1;
i = sscanf (&inbuf[1], "%ld", &breakstmt);
if (i == 0)
{
// maybe the user put in a label?
long tstart;
long tlen;
crm_nextword (&inbuf[1], strlen (&inbuf[1]), 0,
&tstart, &tlen);
memmove (inbuf, &inbuf[1+tstart], tlen);
inbuf[tlen] = '\000';
vindex= crm_vht_lookup (vht, inbuf, tlen);
fprintf (stderr, "vindex = %ld\n", vindex);
if (vht[vindex] == NULL)
{
fprintf (stderr, "No label '%s' in this program. ", inbuf);
fprintf (stderr, "No breakpoint change made. \n");
}
else
{
breakstmt = vht[vindex]->linenumber;
};
};
if (breakstmt <= -1)
{
breakstmt = 0;
}
if (breakstmt >= csl->nstmts)
{
breakstmt = csl-> nstmts;
fprintf (stderr, "last statement is %ld, assume you meant that.\n",
csl->nstmts);
};
csl->mct[breakstmt]->stmt_break = 1 - csl->mct[breakstmt]->stmt_break;
if (csl->mct[breakstmt]->stmt_break == 1)
{
fprintf (stderr, "Setting breakpoint at statement %ld\n",
breakstmt);
}
else
{
fprintf (stderr, "Clearing breakpoint at statement %ld\n",
breakstmt);
};
}
return (1);
break;
case 'a':
{ // do a debugger-level alteration
// maybe the user put in a label?
long vstart, vlen;
long vindex;
long ostart, oend, olen;
crm_nextword (&inbuf[1], strlen (&inbuf[1]), 0,
&vstart, &vlen);
memmove (inbuf, &inbuf[1+vstart], vlen);
inbuf[vlen] = '\000';
vindex= crm_vht_lookup (vht, inbuf, vlen);
if (vht[vindex] == NULL)
{
fprintf (stderr, "No variable '%s' in this program. ", inbuf);
}
// now grab what's left of the input as the value to set
//
ostart = vlen + 1;
while (inbuf[ostart] != '/' && inbuf[ostart] != '\000') ostart++;
ostart++;
oend = ostart + 1;
while (inbuf[oend] != '/' && inbuf[oend] != '\000') oend++;
memmove (outbuf,
&inbuf[ostart],
oend - ostart);
outbuf [oend - ostart] = '\000';
olen = crm_nexpandvar (outbuf, oend - ostart, data_window_size);
crm_destructive_alter_nvariable (inbuf, vlen, outbuf, olen);
};
break;
case 'f':
{
csl->cstmt = csl->mct[csl->cstmt]->fail_index - 1;
fprintf (stderr, "Forward to }, next statement : %ld\n", csl->cstmt);
csl->aliusstk [csl->mct[csl->cstmt]->nest_level] = -1;
};
return (1);
break;
case 'l':
{
csl->cstmt = csl->mct[csl->cstmt]->liaf_index;
fprintf (stderr, "Backward to {, next statement : %ld\n", csl->cstmt);
};
return (1);
break;
case 'h':
{
fprintf (stderr, "a :var: /value/ - alter :var: to /value/ \n");
fprintf (stderr, "b <n> - toggle breakpoint on line <n> \n");
fprintf (stderr, "b <label> - toggle breakpoint on <label> \n");
fprintf (stderr, "c - continue execution till breakpoint or end\n");
fprintf (stderr, "c <n> - execute <number> more statements\n");
fprintf (stderr, "e - expand an expression\n");
fprintf (stderr, "f - fail forward to block-closing '}'\n");
fprintf (stderr, "j <n> - jump to statement <number>\n");
fprintf (stderr, "j <label> - jump to statement <label>\n");
fprintf (stderr, "l - liaf backward to block-opening '{'\n");
fprintf (stderr, "n - execute next statement (same as 'c 1')\n");
fprintf (stderr, "q - quit the program and exit\n");
fprintf (stderr, "t - toggle user-level tracing\n");
fprintf (stderr, "T - toggle system-level tracing\n");
fprintf (stderr, "v <n> - view source code statement <n>\n");
};
break;
default:
{
fprintf (stderr, "Command unrecognized - type \"h\" for help. \n");
};
};
goto debug_top;
}
syntax highlighted by Code2HTML, v. 0.9.1