[NPL] Misc fixes

svn path=/trunk/; revision=48216
This commit is contained in:
Jakub Zawadzki 2013-03-09 15:53:30 +00:00
parent 91cec2a12e
commit 7b9a23a53a
4 changed files with 395 additions and 104 deletions

View File

@ -53,6 +53,7 @@ typedef enum {
EXPRESSION_STR,
EXPRESSION_INDEX,
EXPRESSION_MULTI_INDEX,
EXPRESSION_FIELD,
EXPRESSION_CALL,
@ -62,6 +63,12 @@ typedef enum {
} npl_expression_type_t;
typedef struct _npl_expression_list {
struct _npl_expression_list *next;
struct _npl_expression *expr;
} npl_expression_list_t;
typedef struct _npl_expression {
union {
struct {
@ -90,6 +97,13 @@ union {
struct _npl_expression *index;
} arr;
struct {
npl_expression_type_t type; /* EXPRESSION_MULTI_INDEX */
struct _npl_expression *base;
npl_expression_list_t *indexes;
} aarr;
struct {
npl_expression_type_t type; /* EXPRESSION_FIELD */
@ -118,13 +132,7 @@ union {
npl_expression_type_t type; /* EXPRESSION_CALL */
struct _npl_expression *fn;
struct _npl_expression_list {
struct _npl_expression_list *next;
struct _npl_expression *expr;
} *args;
npl_expression_list_t *args;
} call;
@ -222,7 +230,7 @@ typedef struct _npl_statement {
} w;
struct {
npl_statement_type_t type; /* STATEMTN_TABLE */
npl_statement_type_t type; /* STATEMENT_TABLE */
npl_table_t data;
} t;
@ -251,7 +259,8 @@ typedef struct _npl_statement {
npl_expression_t *format;
struct _npl_statements *sts;
struct hfinfo *hfi; /* set by code gen */
/* after 1st pass of code generator */
struct hfinfo *hfi;
} f;
};
@ -292,12 +301,16 @@ typedef struct {
npl_expression_t *display_format;
npl_expression_t *size;
/* after 1st pass of code generator */
const char *hf_type;
} npl_type_t;
typedef enum {
DECL_INVALID = 0,
DECL_ATTR,
DECL_INCLUDE,
DECL_STRUCT,
DECL_TABLE,
DECL_CONST,
@ -306,8 +319,8 @@ typedef enum {
} npl_decl_type_t;
typedef struct _npl_attr {
npl_expression_t expr;
typedef struct {
npl_expression_list_t *expr_list;
} npl_attr_t;
typedef struct {
@ -322,6 +335,12 @@ typedef struct {
npl_attr_t data;
} a;
struct {
npl_decl_type_t type; /* DECL_INCLUDE */
char *file;
} i;
struct {
npl_decl_type_t type; /* DECL_STRUCT */
@ -362,6 +381,4 @@ typedef struct {
} *decls;
int parse_ok;
} npl_code_t;

View File

@ -25,7 +25,7 @@
#include "ast.h"
#include "xmem.h"
void npl_parse_file(npl_code_t *code, FILE *f, const char *filename); /* parser.l */
int npl_parse_file(npl_code_t *code, FILE *f, const char *filename); /* parser.l */
static void gen_expr(FILE *f, npl_expression_t *e);
static void gen_statements(FILE *f, struct _npl_statements *sts);
@ -39,6 +39,16 @@ struct hfinfo {
struct hfinfo *hfs;
static void _fail(const char *file, int line, const char *msg) {
fprintf(stderr, "!!! %s:%d fail(%s)\n", file, line, msg);
abort();
}
#define fail(msg) _fail(__FILE__, __LINE__, msg)
#define xassert(expr) \
do { if (!(expr)) fail("Assertion failed: " #expr); } while(0);
static struct hfinfo *
add_hfi(npl_statement_t *st)
@ -57,8 +67,9 @@ add_hfi(npl_statement_t *st)
}
static const char *
hfi_name(const struct hfinfo *hfi)
hfi_var(const struct hfinfo *hfi)
{
/* XXX nicer name */
static char hf_name[64];
snprintf(hf_name, sizeof(hf_name), "hf_field_%u", hfi->id);
@ -66,6 +77,127 @@ hfi_name(const struct hfinfo *hfi)
return hf_name;
}
static const char *
hfi_name(const struct hfinfo *hfi)
{
return hfi->st->f.id;
}
static const char *
hfi_filter(const struct hfinfo *hfi)
{
/* TODO stub */
return "";
}
static const char *
hfi_type(const struct hfinfo *hfi)
{
/* TODO stub */
return "FT_BYTES";
}
static const char *
hfi_display(const struct hfinfo *hfi)
{
/* TODO stub */
return "BASE_NONE";
}
static unsigned int
hfi_mask(const struct hfinfo *hfi)
{
/* TODO stub */
return 0;
}
static int
expr_to_int(const npl_expression_t *npl, int *val)
{
if (npl->type == EXPRESSION_INT) {
*val = npl->num.digit;
return 1;
}
if (npl->type == EXPRESSION_UNARY) {
if (!expr_to_int(npl->u.operand, val))
return 0;
switch (npl->u.operator) {
case OP1_MINUS:
*val = -(*val);
return 1;
case OP1_NEG:
*val = ~(*val);
return 1;
case OP1_NOT:
*val = !(*val);
return 1;
}
}
return 0;
}
static int
expr_to_str(const npl_expression_t *npl, const char **val)
{
if (npl->type == EXPRESSION_STR) {
*val = npl->str.str;
return 1;
}
return 0;
}
static const char *
type_to_ft(const npl_type_t *t, int size)
{
switch (t->type) {
case FIELD_DECIMAL:
if (size == 4)
return "FT_FLOAT";
if (size == 8)
return "FT_DOUBLE";
fprintf(stderr, "!!! decimal, size: %d\n", size);
return NULL;
case FIELD_NUMBER:
if (size == 1)
return "FT_INT8";
if (size == 2)
return "FT_INT16";
if (size == 3)
return "FT_INT24";
if (size == 4)
return "FT_INT32";
if (size <= 8)
return "FT_INT64";
fprintf(stderr, "!!! number, size: %d\n", size);
return NULL;
case FIELD_UNSIGNED_NUMBER:
if (size == 1)
return "FT_UINT8";
if (size == 2)
return "FT_UINT16";
if (size == 3)
return "FT_UINT24";
if (size == 4)
return "FT_UINT32";
if (size <= 8)
return "FT_UINT64";
fprintf(stderr, "!!! number, size: %d\n", size);
return NULL;
case FIELD_TIME:
/* XXX, FT_ABSOLUTE_TIME or FT_RELATIVE_TIME? */
fprintf(stderr, "!!! time, size: %d\n", size);
return "FT_ABSOLUTE_TIME";
}
fprintf(stderr, "!!! not handled, type: %d, size: %d\n", t->type, size);
return NULL;
}
#define gen_fprintf(f, args...) \
do { \
@ -160,7 +292,7 @@ gen_expr(FILE *f, npl_expression_t *e)
case EXPRESSION_CALL:
{
struct _npl_expression_list *arg;
npl_expression_list_t *arg;
char *ind = "";
gen_expr(f, e->call.fn);
@ -173,12 +305,101 @@ gen_expr(FILE *f, npl_expression_t *e)
gen_fprintf(f, ")");
return;
}
case EXPRESSION_FIELD:
gen_expr(f, e->fld.base);
gen_fprintf(f, ".%s ", e->fld.field);
return;
}
fprintf(stderr, "XXXX expr->type: %d\n", e->type);
}
static int
gen_table_struct(FILE *f, npl_table_t *t)
{
enum { CANT, VALUE_STRING, STRING_STRING } type;
struct npl_table_case *c;
int all_int = 1;
int all_str = 1;
if (t->params.count || !t->switch_expr || t->default_expr)
return 0;
for (c = t->cases; c; c = c->next) {
const char *str;
int val;
if (!c->return_expr || !expr_to_str(c->return_expr, &str))
return 0;
if (all_int && !expr_to_int(&c->e, &val))
all_int = 0;
if (all_str && !expr_to_str(&c->e, &str))
all_str = 0;
if (!all_int && !all_str)
return 0;
}
if (all_int)
type = VALUE_STRING;
else if (all_str)
type = STRING_STRING;
else
type = CANT;
/* table can be converted to value_string, generate one */
if (f && type == VALUE_STRING) {
gen_fprintf(f,
"static const value_string %s[] = {\n",
t->id);
for (c = t->cases; c; c = c->next) {
const char *str;
int val;
/* checked above, should not fail now */
if (!expr_to_str(c->return_expr, &str))
fail("expr_to_str(str)");
if (!expr_to_int(&c->e, &val))
fail("expr_to_int(val)");
gen_fprintf(f, "\t{ %x, \"%s\" },\n", val, str);
}
gen_fprintf(f, "\t{ 0, NULL }\n");
gen_fprintf(f, "};\n");
return 1;
}
/* table can be converted to string_string, generate one */
if (f && type == STRING_STRING) {
gen_fprintf(f,
"static const string_string %s[] = {\n",
t->id);
for (c = t->cases; c; c = c->next) {
const char *str;
const char *val;
/* checked above, should not fail now */
if (!expr_to_str(c->return_expr, &str))
fail("expr_to_str(str)");
if (!expr_to_str(&c->e, &val))
fail("expr_to_str(val)");
gen_fprintf(f, "\t{ \"%s\", \"%s\" },\n", val, str);
}
gen_fprintf(f, "\t{ NULL, NULL }\n");
gen_fprintf(f, "};\n");
return 1;
}
return 0;
}
static void
gen_table(FILE *f, npl_table_t *t)
gen_table_func(FILE *f, npl_table_t *t)
{
struct npl_table_case *c;
@ -215,8 +436,7 @@ again1:
if (!c->return_expr) {
c = c->next;
if (!c)
abort();
xassert(c != NULL);
gen_fprintf(f, "\n");
goto again1;
} else {
@ -244,8 +464,7 @@ again2:
if (!c->return_expr) {
gen_fprintf(f, " || ");
c = c->next;
if (!c)
abort();
xassert(c != NULL);
goto again2;
} else {
gen_fprintf(f, ")\n");
@ -265,6 +484,14 @@ again2:
gen_fprintf(f, "\treturn \"\";\n");
gen_fprintf(f, "}\n");
}
static void
gen_table(FILE *f, npl_table_t *t)
{
if (!gen_table_struct(f, t))
gen_table_func(f, t);
gen_fprintf(f, "\n");
}
@ -297,7 +524,7 @@ gen_statement(FILE *f, npl_statement_t *st)
if (f) {
// XXX, search for st->f.t_id in table.
gen_fprintf(f, "\toffset = dissect_%s(tvb, tree, %s, offset);\n", st->f.t_id, hfi_name(st->f.hfi));
gen_fprintf(f, "\toffset = dissect_%s(tvb, tree, %s, offset);\n", st->f.t_id, hfi_var(st->f.hfi));
}
// XXX st->f.bits, st->f.arr, st->f.format, st->f.sts
return;
@ -336,7 +563,6 @@ gen_statement(FILE *f, npl_statement_t *st)
return;
}
if (c) {
npl_statement_t *default_st = st->sw.data.default_st;
@ -413,6 +639,8 @@ gen_protocol(FILE *f, npl_protocol_t *p)
gen_fprintf(f, "{\n");
gen_fprintf(f,
"\tint offset = 0;\n"
"\tproto_tree *tree = NULL;\n"
"\tproto_item *ti = NULL;\n"
"\n"
);
@ -439,8 +667,7 @@ gen_struct(FILE *f, npl_struct_t *s)
snprintf(id, sizeof(id), "_noname%u", ++_id);
s->id = xstrdup(id);
if (f != NULL)
abort();
xassert(f == NULL);
}
if (s->count_expr) {
@ -498,25 +725,40 @@ gen_struct(FILE *f, npl_struct_t *s)
static void
gen_const(FILE *f, npl_const_t *c)
{
// TODO
fprintf(stderr, "gen_const() TODO\n");
// TODO, later don't do #define, only add to id table with given value.
gen_fprintf(f, "#define %s", c->id);
gen_expr(f, &c->expr);
gen_fprintf(f, "\n");
}
static void
gen_type(FILE *f, npl_type_t *t)
{
int size = -1;
int byte_order = -1;
const char *hf_type = NULL;
gen_fprintf(f,
"static int\n"
"dissect_type_%s(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)\n"
"dissect_type_%s(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int hf, int offset)\n"
"{\n", t->name);
#if 0
npl_params_t params;
if (t->params.count) {
/* XXX */
fprintf(stderr, "XXX, t->params.count\n");
}
npl_expression_t *byte_order;
npl_expression_t *display_format;
npl_expression_t *size;
#endif
if (t->size && !expr_to_int(t->size, &size))
fprintf(stderr, "!!! expr_to_int(size) failed for type: %s\n", t->name);
if (t->byte_order && !expr_to_int(t->byte_order, &byte_order))
fprintf(stderr, "!!! expr_to_int(byte_order) failed for type: %s\n", t->name);
hf_type = type_to_ft(t, size);
/* npl_expression_t *display_format; */
t->hf_type = hf_type ? hf_type : "FT_BYTES";
gen_fprintf(f, "\treturn offset;\n");
gen_fprintf(f, "}\n");
@ -526,8 +768,7 @@ gen_type(FILE *f, npl_type_t *t)
static void
gen_attr(FILE *f, npl_attr_t *a)
{
// TODO
fprintf(stderr, "gen_attr() TODO");
fprintf(stderr, "gen_attr() TODO\n");
}
static void
@ -571,13 +812,11 @@ gen_hf(FILE *f)
struct hfinfo *hfi;
for (hfi = hfs; hfi; hfi = hfi->next)
gen_fprintf(f, "static int %s = -1;\n", hfi_name(hfi));
gen_fprintf(f, "static int %s = -1;\n", hfi_var(hfi));
}
static const char proto_name[] = "foo"; /* TODO, hardcoded */
static void
gen_proto_register(FILE *f)
gen_proto_register(FILE *f, const char *proto_name)
{
struct hfinfo *hfi;
@ -589,15 +828,14 @@ gen_proto_register(FILE *f)
/* hf array */
gen_fprintf(f, "\tstatic hf_register_info hf[] = {\n");
for (hfi = hfs; hfi; hfi = hfi->next) {
npl_statement_t *st = hfi->st;
gen_fprintf(f,
gen_fprintf(f,
"\t\t{ &%s,\n"
"\t\t\t{ \"%s\", \"%s\", %s, %s, NULL, 0x%.2x, NULL, HFILL }\n"
"\t\t},\n", hfi_name(hfi), st->f.id, "filtr", "typ", "dec", 0x00 );
"\t\t},\n", hfi_var(hfi), hfi_name(hfi), hfi_filter(hfi), hfi_type(hfi), hfi_display(hfi), hfi_mask(hfi) );
}
gen_fprintf(f, "\t}\n\n");
/* ett array */
gen_fprintf(f, "\tstatic gint *ett[] = {\n");
#if 0
&ett_foo,
@ -615,14 +853,14 @@ gen_proto_register(FILE *f)
}
static void
gen_proto_handoff(FILE *f)
gen_proto_handoff(FILE *f, const char *proto_name)
{
gen_fprintf(f,
"void\n"
"proto_reg_handoff_%s(void)\n"
"{", proto_name);
"{\n", proto_name);
gen_fprintf(f, "dissector_handle_t %s_handle = new_create_dissector_handle(dissect_%s, proto_%s);\n", proto_name, proto_name, proto_name);
gen_fprintf(f, "\tdissector_handle_t %s_handle = new_create_dissector_handle(dissect_%s, proto_%s);\n", proto_name, proto_name, proto_name);
#if 0
dissector_add_uint("REG", XXX, %s_handle);
@ -632,10 +870,24 @@ gen_proto_handoff(FILE *f)
gen_fprintf(f, "}\n");
}
static const npl_protocol_t *
get_protocol(npl_code_t *code)
{
struct _npl_decl_list *decl;
for (decl = code->decls; decl; decl = decl->next) {
/* XXX, for now return first */
if (decl->d.type == DECL_PROTOCOL)
return &decl->d.p.data;
}
return NULL;
}
int main(int argc, char **argv) {
FILE *f;
npl_code_t code;
int parse_ok;
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
@ -647,25 +899,36 @@ int main(int argc, char **argv) {
}
memset(&code, 0, sizeof(code));
printf("%s:\n", argv[1]);
npl_parse_file(&code, f, argv[1]);
if (code.parse_ok) {
parse_ok = npl_parse_file(&code, f, argv[1]);
// parse_ok = 0;
if (parse_ok) {
const npl_protocol_t *proto = get_protocol(&code);
const char *proto_name = (proto) ? proto->id : "noname";
FILE *out;
gen_code(NULL, &code);
out = fopen("/tmp/npl.c", "w");
/* TODO declare ett_ */
gen_hf(out);
/* includes */
gen_fprintf(out, "#include \"config.h\"\n");
gen_fprintf(out, "#include <glib.h>\n");
gen_fprintf(out, "#include <epan/packet.h>\n");
gen_fprintf(out, "\n");
gen_fprintf(out, "\n\n");
/* TODO declare forward */
gen_fprintf(out, "static int proto_%s = -1;\n", proto_name);
gen_hf(out);
gen_fprintf(out, "\n");
/* TODO declare ett_ */
gen_fprintf(out, "\n");
gen_code(out, &code);
gen_proto_register(out);
gen_proto_handoff(out);
gen_proto_register(out, proto_name);
gen_proto_handoff(out, proto_name);
fclose(out);
}

View File

@ -485,7 +485,6 @@ parse_params(npl_params_t *p)
static void parse_expression(npl_expression_t *expr);
static npl_expression_t *xparse_expression(void);
static npl_expression_t g_e;
static void
parse_primary(npl_expression_t *expr)
@ -531,6 +530,22 @@ parse_primary(npl_expression_t *expr)
nomatch();
}
/* ExpressionList = Expression, { ",", Expression } ; */
static void
parse_expression_list(npl_expression_list_t **ptr)
{
do {
npl_expression_list_t *cur = xnew(npl_expression_list_t);
*ptr = cur;
ptr = &(cur->next);
cur->expr = xparse_expression();
} while (is_token_accept(TOKEN_COMMA));
*ptr = NULL;
}
static void
parse_expression1(npl_expression_t *expr)
{
@ -539,44 +554,33 @@ parse_expression1(npl_expression_t *expr)
do {
if (is_token_accept(TOKEN_LPAREN)) { /* foo() */
npl_expression_t *fun = xdup(npl_expression_t, expr);
struct _npl_expression_list **ptr = &(expr->call.args);
if (!is_token(TOKEN_RPAREN)) {
do {
struct _npl_expression_list *cur = xnew(struct _npl_expression_list);
*ptr = cur;
ptr = &(cur->next);
cur->expr = xparse_expression();
} while (is_token_accept(TOKEN_COMMA));
}
*ptr = NULL;
npl_expression_list_t *args = NULL;
if (!is_token(TOKEN_RPAREN))
parse_expression_list(&args);
accept(TOKEN_RPAREN);
expr->call.fn = fun;
expr->type = EXPRESSION_CALL;
} else if (is_token(TOKEN_DOLLAR) || is_token(TOKEN_LBRACKET)) { /* arr$[field1, field2, ...], arr[10] */
expr->type = EXPRESSION_CALL;
expr->call.fn = fun;
expr->call.args = args;
} else if (is_token_accept(TOKEN_DOLLAR)) { /* arr$[field1, field2, ...] */
npl_expression_t *base = xdup(npl_expression_t, expr);
npl_expression_list_t *indexes;
accept(TOKEN_LBRACKET);
parse_expression_list(&indexes);
accept(TOKEN_RBRACKET);
expr->type = EXPRESSION_MULTI_INDEX;
expr->aarr.base = base;
expr->aarr.indexes = indexes;
} else if (is_token_accept(TOKEN_LBRACKET)) { /* arr[10] */
npl_expression_t *base = xdup(npl_expression_t, expr);
npl_expression_t *idx;
int aa;
aa = is_token_accept(TOKEN_DOLLAR);
accept(TOKEN_LBRACKET);
idx = xparse_expression();
if (aa) {
while (is_token_accept(TOKEN_COMMA)) {
// XXX ast
npl_expression_t *idx2;
idx2 = xparse_expression();
}
}
accept(TOKEN_RBRACKET);
expr->type = EXPRESSION_INDEX;
@ -921,21 +925,27 @@ static int is_attribute(void) { return is_token(TOKEN_LBRACKET); }
static void
parse_attributes(npl_attr_t *attr)
{
npl_expression_list_t **ptr = &attr->expr_list;
accept(TOKEN_LBRACKET);
do {
parse_expression(&attr->expr);
npl_expression_list_t *cur = xnew(npl_expression_list_t);
*ptr = cur;
ptr = &(cur->next);
cur->expr = xparse_expression();
if (is_token_accept(TOKEN_SEMICOLON))
{ }
else if (is_token_accept(TOKEN_COMMA))
{ }
}
while (!is_token(TOKEN_RBRACKET));
// while (is_token_accept(TOKEN_COMMA));
accept(TOKEN_RBRACKET);
*ptr = NULL;
}
static void parse_statement(npl_statement_t *st);
@ -1007,8 +1017,6 @@ parse_dynamic_switch(npl_switch_t *sw)
is_token_accept(TOKEN_SEMICOLON);
}
static void parse_table(npl_table_t *);
static int is_statement(void) {
return
is_token(TOKEN_WHILE) ||
@ -1076,6 +1084,7 @@ xparse_formatting(void)
return format;
}
static void parse_table(npl_table_t *);
static void parse_struct(npl_struct_t *s, int statement);
static void
@ -1128,12 +1137,12 @@ parse_statement(npl_statement_t *st)
if (is_token_accept(TOKEN_LPAREN)) {
/* XXX, WTF: StringTerm(Property.XMLEncoding, "<", true, false, false) Reason; */
npl_expression_list_t *type_params;
do {
/* XXX, ast */
parse_expression(&g_e);
} while (is_token_accept(TOKEN_COMMA));
parse_expression_list(&type_params);
accept(TOKEN_RPAREN);
/* XXX, store type_params in ast */
}
st->f.id = accept_id();
@ -1375,13 +1384,12 @@ parse_decl(npl_decl_t *d)
parse_protocol(&d->p.data);
} else if (is_type()) {
parse_type(&d->ty.data);
d->type = DECL_TYPE;
parse_type(&d->ty.data);
} else if (is_token_accept(TOKEN_INCLUDE)) {
/* XXX, ast */
char *file = accept_str();
free(file);
d->type = DECL_INCLUDE;
d->i.file = accept_str(); /* XXX, it's C-escaped */ /* XXX, unix / vs dos \\ */
} else
nomatch();
@ -1404,16 +1412,19 @@ parse_npl(npl_code_t *code)
*ptr = NULL;
}
void
int
npl_parse_file(npl_code_t *code, FILE *f, const char *filename)
{
int parse_ok = 0;
yyfilename = filename;
yyin = f;
next_token();
parse_npl(code);
code->parse_ok = 1;
parse_ok = 1;
yylex_destroy();
return parse_ok;
}

View File

@ -12,7 +12,7 @@ static inline void *xmalloc(size_t s) { void *ptr = malloc(s); if (!ptr) oom_kil
static inline void *xrealloc(void *p, size_t s) { void *ptr = realloc(p, s); if (!ptr) oom_killer(); return ptr; }
static inline void *xmemdup(void *p, size_t s) { void *ptr = malloc(s); if (!ptr) oom_killer(); return memcpy(ptr, p, s); }
static inline void *xstrdup(const char *s) { void *ptr = strdup(s); if (!ptr) oom_killer(); return ptr; }
static inline char *xstrdup(const char *s) { void *ptr = strdup(s); if (!ptr) oom_killer(); return ptr; }
#define xnew(x) (x *) xmalloc(sizeof(x))
#define xdup(x, y) (x *) xmemdup(y, sizeof(x))