#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct js_State js_State;
typedef struct js_Ast js_Ast;
static void jsR_run(js_State *J);
static void js_error(js_State *J);
struct js_State
{
int top;
};
enum js_AstType { AST_LIST, AST_IDENTIFIER };
struct js_Ast
{
enum js_AstType type;
js_Ast *a, *b;
const char *string;
};
static void js_throw(js_State *J)
{
printf("SUCCESS: exit with exception as expected!\n");
}
static void js_pop(js_State *J)
{
// XXX BUG NEEDS THIS LINE
J->top = 0;
// XXX BUG NEEDS THIS LINE
// NOTE is infinite recursion messing things up?
js_error(J);
}
static void js_error(js_State *J) {
// XXX BUG NEEDS THIS LINE
jsR_run(J);
// XXX BUG NEEDS THIS LINE
// NOTE is infinite recursion messing things up?
js_pop(J);
js_throw(J);
}
// XXX MUST NOT BE STATIC
void js_pushstring(js_State *J, const char *v)
{
if (v[0] == 0)
// XXX BUG NEEDS THIS LINE
js_error(J);
}
static void jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
{
// XXX BUG NEEDS THIS LINE
js_pushstring(J, "hello");
js_throw(J);
}
int this_is_a_stupid_global = 0;
static void checkfutureword
(js_State
*J
, js_Ast
*exp)
{
// XXX ADDING THIS LINE HIDES THE BUG
//++this_is_a_stupid_global;
if (!strcmp(exp
->string
, "const")) {
// NOTE cannot inline this call
jsC_error
(J
, exp, "'%s' is a future reserved word", exp
->string
);
}
}
// XXX MUST BE STATIC (if externally visible, no bug)
static void cparams(js_State *J, js_Ast *list)
{
printf("cparams %s\n", list
->a
->string
);
checkfutureword(J, list->a);
}
// XXX MUST BE STATIC (if externally visible, no bug)
static void cfunbody(js_State *J, js_Ast *params, js_Ast *body)
{
cparams(J, params);
// XXX BUG NEEDS THIS LINE
// NOTE is null deref messing things up here?
checkfutureword(J, body->a);
}
static void jsR_run(js_State *J)
{
// XXX BUG NEEDS THIS LINE
cfunbody(J, NULL, NULL);
}
static js_Ast *jsP_newnode(js_State *J, enum js_AstType type, js_Ast *a, js_Ast *b)
{
js_Ast
*node
= malloc(sizeof *node
);
node->type = type;
node->a = a;
node->b = b;
node->string = NULL;
return node;
}
static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s)
{
js_Ast *node = jsP_newnode(J, type, 0, 0);
node->string = s;
return node;
}
int main(int argc, char **argv)
{
js_State J = {};
cparams(&J, jsP_newnode(&J, AST_LIST, jsP_newstrnode(&J, AST_IDENTIFIER, "const"), 0));
puts("FAIL: should NOT get here");
}