NPL stuff:

- stubs for more NPL built-ins
 - try to guess struct size
 - some work on property attribute.

svn path=/trunk/; revision=48774
This commit is contained in:
Jakub Zawadzki 2013-04-07 17:24:16 +00:00
parent a0f8e6fd1c
commit 1c249ca95c
2 changed files with 254 additions and 104 deletions

View File

@ -164,6 +164,7 @@ typedef struct {
char *tmpid;
struct ettinfo *ett;
struct symbol *sym;
int struct_size;
} npl_struct_t;
typedef struct {
@ -289,6 +290,7 @@ typedef struct _npl_statement {
struct hfinfo *hfi;
npl_expression_t *byte_order_attr;
int generate_var;
int field_size;
} f;
};
@ -309,7 +311,6 @@ typedef struct {
/* code generator */
struct symbol *sym;
npl_expression_t *byte_order_attr;
} npl_protocol_t;
typedef enum {

View File

@ -71,6 +71,7 @@ struct parent_info {
const char *id;
npl_expression_t *byte_order;
int cur_offset;
/* size, offset, bitoffset, ... ? */
};
@ -78,11 +79,17 @@ static struct symbol *gen_expr(FILE *f, npl_expression_t *e);
static void gen_statements(FILE *f, struct parent_info *parent, struct _npl_statements *sts);
static void gen_struct(FILE *f, npl_struct_t *s, npl_attribute_list_t *attr_list);
struct symbol *symbols;
struct hfinfo *hfs;
struct ettinfo *etts;
static struct symbol *symbols;
static struct hfinfo *hfs;
static struct ettinfo *etts;
static npl_expression_t format_string_e;
static npl_expression_t is_value_none_e;
static npl_expression_t this_e;
static npl_expression_t property_e;
static npl_expression_t global_e;
static npl_expression_t local_e;
static void _fail(const char *file, int line, const char *msg) {
fprintf(stderr, "!!! %s:%d fail(%s)\n", file, line, msg);
@ -612,44 +619,58 @@ op2_to_str(npl_op2_t op)
return "";
}
enum attr_flag {
ATTR_PROPERTY = 0,
static int
ATTR_GLOBAL = 1 << 0,
ATTR_LOCAL = 1 << 1,
ATTR_CONV = 1 << 5,
ATTR_POST = 1 << 10
};
static enum attr_flag
resolve_attr_id(const char *id)
{
if (!strcasecmp(id, "property"))
return 0;
return ATTR_PROPERTY;
if (!strcasecmp(id, "Global"))
return 1;
return ATTR_GLOBAL;
if (!strcasecmp(id, "local"))
return 2;
return ATTR_LOCAL;
if (!strcasecmp(id, "conversation"))
return 3;
return ATTR_CONV;
if (!strcasecmp(id, "post"))
return 4;
return ATTR_POST;
fprintf(stderr, ":: attr-id: %s\n", id);
abort();
return -1;
}
static int
resolve_attr_expr(npl_attribute_list_t *attr, const struct _npl_expression *expr)
resolve_attr_expr(const struct _npl_expression *expr)
{
int flags = 0;
switch (expr->type) {
case EXPRESSION_ID:
resolve_attr_id(expr->id.id);
flags |= (int) resolve_attr_id(expr->id.id);
break;
case EXPRESSION_FIELD:
flags |= resolve_attr_expr(attr, expr->fld.base);
resolve_attr_id(expr->fld.field);
flags |= resolve_attr_expr(expr->fld.base);
flags |= (int) resolve_attr_id(expr->fld.field);
break;
default:
fprintf(stderr, "resolve_attr_expr() %d\n", expr->type);
break;
}
xassert(!((flags & ATTR_GLOBAL) && (flags & ATTR_LOCAL)));
return flags;
}
@ -657,7 +678,7 @@ static void
resolve_attr_list(npl_attribute_list_t *attr)
{
while (attr) {
struct _npl_expression *expr = NULL;
struct _npl_expression *expr;
const char *id = NULL;
int flags = 0;
@ -674,7 +695,7 @@ resolve_attr_list(npl_attribute_list_t *attr)
break;
case EXPRESSION_FIELD:
flags = resolve_attr_expr(attr, expr->fld.base);
flags = resolve_attr_expr(expr->fld.base);
id = expr->fld.field;
break;
@ -719,13 +740,19 @@ gen_expr_type(FILE *f, npl_type_t *t)
gen_fprintf(f, "<<TYPE %s>>", t->id);
}
static void
gen_expr_table(FILE *f, npl_table_t *t)
{
gen_fprintf(f, " format_table_%s ", t->id);
}
static struct symbol *
gen_expr(FILE *f, npl_expression_t *e)
{
switch (e->type) {
case EXPRESSION_ID:
{
struct symbol *sym = symbol_find(e->id.id, SYMBOL_EXPR | SYMBOL_FIELD | SYMBOL_TYPE | SYMBOL_SIMPLE);
struct symbol *sym = symbol_find(e->id.id, SYMBOL_EXPR | SYMBOL_FIELD | SYMBOL_TYPE | SYMBOL_SIMPLE | SYMBOL_TABLE);
if (!sym) {
fprintf(stderr, "can't find id: %s\n", e->id.id);
@ -742,6 +769,9 @@ gen_expr(FILE *f, npl_expression_t *e)
else if (sym->type == SYMBOL_TYPE)
gen_expr_type(f, sym->data);
else if (sym->type == SYMBOL_TABLE)
gen_expr_table(f, sym->data);
else if (sym->type == SYMBOL_SIMPLE)
gen_fprintf(f, "%s", (const char *) sym->data);
@ -782,10 +812,15 @@ gen_expr(FILE *f, npl_expression_t *e)
struct symbol *sym;
const char *ind = "";
sym = gen_expr(f, e->call.fn);
if (!sym)
sym = gen_expr(NULL, e->call.fn);
if (!sym) {
fprintf(stderr, "can't call no-symbol\n");
abort();
}
/* XXX check if sym->type can be called (function) */
gen_expr(f, e->call.fn);
gen_fprintf(f, "(");
for (arg = e->call.args; arg; arg = arg->next) {
gen_fprintf(f, "%s", ind);
@ -811,11 +846,18 @@ gen_expr(FILE *f, npl_expression_t *e)
struct symbol *sym;
sym = gen_expr(NULL, e->fld.base);
if (!sym)
if (!sym) {
fprintf(stderr, "can't field no-symbol (accessing %s)\n", e->fld.field);
abort();
}
/* XXX check if sym->type can be dereferenced (struct) */
if (sym->data == &property_e) {
gen_fprintf(f, "<< PROPERTY %s>>", e->fld.field);
} else if (sym->data == &local_e) {
gen_fprintf(f, "_local_property_%s", e->fld.field);
} else if (sym->data == &global_e) {
gen_fprintf(f, "<< GLOBAL PROPERTY %s>>", e->fld.field);
} else {
gen_expr(f, e->fld.base);
gen_fprintf(f, ".%s ", e->fld.field);
@ -824,7 +866,17 @@ gen_expr(FILE *f, npl_expression_t *e)
}
}
fprintf(stderr, "XXX expr->type: %d\n", e->type);
if (e == &this_e)
gen_fprintf(f, "<< this >>");
else if (e == &format_string_e)
gen_fprintf(f, "<< FORMAT STRING >>");
else if (e == &is_value_none_e)
gen_fprintf(f, "<< IS VALUE NONE >>");
else if (e == &property_e || e == &global_e || e == &local_e)
{ /* silent expr->type: 0 warnings */ }
else
fprintf(stderr, "XXX expr->type: %d\n", e->type);
return NULL;
}
@ -1040,6 +1092,15 @@ gen_table(FILE *f, npl_table_t *t)
symbols_pop(symroot);
}
static void
gen_field_proto(FILE *f, struct _npl_statement_field *field, npl_protocol_t *p)
{
/* XXX */
gen_fprintf(f, "\t << CALL PROTOCOL %s >>\n", p->id);
/* XXX, do we care? (only when not @ tail?) */
field->field_size = -1;
}
static void
gen_field_struct(FILE *f, struct _npl_statement_field *field, npl_struct_t *s)
{
@ -1049,6 +1110,7 @@ gen_field_struct(FILE *f, struct _npl_statement_field *field, npl_struct_t *s)
gen_fprintf(f, "\toffset = dissect_struct_%s(tvb, pinfo, tree, %s, offset);\n", s->tmpid, hfi_var(field->hfi));
field->hfi->hf_type = "FT_BYTES";
field->field_size = -1;
}
static void
@ -1084,7 +1146,7 @@ gen_field_type(FILE *f, struct _npl_statement_field *field, npl_type_t *t)
struct symbol *symroot;
int i;
// XXX field.bits, field..arr, field..sts
// XXX field.bits, field.arr, field.sts
int size = -1;
struct symbol *size_sym = NULL;
@ -1129,6 +1191,11 @@ gen_field_type(FILE *f, struct _npl_statement_field *field, npl_type_t *t)
else
byte_order_expr = NULL;
if (field->format)
display_format = field->format;
else
display_format = t->display_format;
if (byte_order_expr) {
if (!expr_to_const_int(byte_order_expr, &byte_order)) {
byte_order_sym = expr_to_symbol(byte_order_expr);
@ -1170,12 +1237,7 @@ gen_field_type(FILE *f, struct _npl_statement_field *field, npl_type_t *t)
hf_type = type_to_ft(t, size);
field->hfi->hf_type = hf_type;
/* prefer statement format over type one (?) */
if (field->format)
display_format = field->format;
else
display_format = t->display_format;
field->field_size = size;
/* XXX, when generate_var we can use fetched value, not proto_tree_add_item() */
@ -1203,19 +1265,21 @@ static void
gen_statement_field(FILE *f, struct parent_info *parent, struct _npl_statement_field *field, npl_attribute_list_t *attr_list)
{
struct symbol *sym;
const char *property_name = NULL;
int property_flags = 0;
if (!field->hfi) {
field->hfi = hfi_add(field, parent);
xassert(f == NULL);
}
sym = symbol_find(field->t_id, SYMBOL_STRUCT | SYMBOL_TYPE);
sym = symbol_find(field->t_id, SYMBOL_STRUCT | SYMBOL_PROTO | SYMBOL_TYPE);
if (!sym) {
fprintf(stderr, "can't find: %s\n", field->t_id);
abort();
}
sym->is_used = 1;
if (!field->hfi && sym->type != SYMBOL_PROTO) {
field->hfi = hfi_add(field, parent);
xassert(f == NULL);
}
symbol_add(field->id, SYMBOL_FIELD, field);
field->byte_order_attr = parent->byte_order;
@ -1224,16 +1288,35 @@ gen_statement_field(FILE *f, struct parent_info *parent, struct _npl_statement_f
while (attr_list) {
const char *attr_name = attr_list->resolved;
npl_expression_t *attr_expr = attr_list->assign_expr;
int flags = attr_list->flags;
int attr_flags = attr_list->flags;
if (attr_name) {
if (!strcasecmp(attr_name, "DataFieldByteOrder")) {
xassert(flags == 0);
xassert(attr_flags == 0);
xassert(attr_expr != NULL);
field->byte_order_attr = attr_expr;
} else
fprintf(stderr, "!!! generating field attr: %s not handled!\n", attr_name);
} else if (attr_expr) {
if (attr_flags & ATTR_LOCAL) {
/* XXX, declare only when first use. support < C99 */
gen_fprintf(f, "\tTYPE _local_property_%s = ", attr_name);
gen_expr(f, attr_expr);
gen_fprintf(f, ";\n");
} else {
gen_fprintf(f, "<<PROPERTY(%d) %s = ", attr_flags, attr_name);
gen_expr(f, attr_expr);
gen_fprintf(f, ">>\n");
}
} else {
/* only one for now */
xassert(property_name == NULL);
property_name = attr_name;
property_flags = attr_flags;
field->generate_var = 1;
}
} else
fprintf(stderr, "!!! generating field attr: not resolved!\n");
@ -1244,11 +1327,18 @@ gen_statement_field(FILE *f, struct parent_info *parent, struct _npl_statement_f
gen_field_struct(f, field, sym->data);
else if (sym->type == SYMBOL_TYPE)
gen_field_type(f, field, sym->data);
else if (sym->type == SYMBOL_PROTO)
gen_field_proto(f, field, sym->data);
else {
/* XXX, SYMBOL_TABLE? */
fprintf(stderr, "%s: wrong type [%d]\n", sym->id, sym->type);
abort();
}
if (property_name) {
/* XXX */
gen_fprintf(f, "<<PROPERTY(%d) %s = FIELD %s>>\n", property_flags, property_name, field->id);
}
}
static void
@ -1263,12 +1353,19 @@ gen_statement(FILE *f, struct parent_info *parent, npl_statement_t *st)
gen_expr(f, &st->w.expr);
gen_fprintf(f, ") {\n");
/* gen_fprintf(f, "\tconst int __while%d_offset = %d;\n", _while_id, offset); */
parent->cur_offset = -1;
gen_statements(f, parent, st->w.sts);
/* gen_fprintf(f, "\tassert(__while%d_offset > offset);\n", _while_id, offset); */
gen_fprintf(f, "\t}\n");
return;
case STATEMENT_STRUCT:
/* XXX, fix if we know size of structure */
parent->cur_offset = -1;
gen_struct(NULL, &st->s.data, NULL);
// XXX put st->s.data somewhere to create this proc.
gen_fprintf(f, "\toffset = dissect_struct_%s(tvb, pinfo, tree, hf_costam, offset);\n", st->s.data.tmpid);
@ -1276,6 +1373,12 @@ gen_statement(FILE *f, struct parent_info *parent, npl_statement_t *st)
case STATEMENT_FIELD:
gen_statement_field(f, parent, &st->f, st->attr_list);
if (parent->cur_offset != -1) {
if (st->f.field_size != -1)
parent->cur_offset += st->f.field_size;
else
parent->cur_offset = -1;
}
return;
/* case STATEMENT_DYNAMIC_SWITCH: */
@ -1283,6 +1386,7 @@ gen_statement(FILE *f, struct parent_info *parent, npl_statement_t *st)
{
struct npl_switch_case *c = st->sw.data.cases;
parent->cur_offset = -1;
if (st->sw.data.switch_expr) {
gen_fprintf(f, "\tswitch (");
gen_expr(f, st->sw.data.switch_expr);
@ -1394,12 +1498,16 @@ static void
gen_protocol(FILE *f, npl_protocol_t *p, npl_attribute_list_t *attr_list)
{
struct parent_info this;
npl_expression_t *byte_order_attr = NULL;
p->sym->is_static = 1;
gen_fprintf(f,
"static int\n"
"dissect_%s(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)\n", p->id);
/* XXX, use data */
xassert(p->params.count == 0);
gen_fprintf(f, "{\n");
gen_fprintf(f,
"\tint offset = 0;\n"
@ -1419,8 +1527,7 @@ gen_protocol(FILE *f, npl_protocol_t *p, npl_attribute_list_t *attr_list)
xassert(flags == 0);
xassert(attr_expr != NULL);
p->byte_order_attr = attr_expr;
byte_order_attr = attr_expr;
} else
fprintf(stderr, "!!! generating protocol attr: %s not handled!\n", attr_name);
} else
@ -1429,20 +1536,24 @@ gen_protocol(FILE *f, npl_protocol_t *p, npl_attribute_list_t *attr_list)
attr_list = attr_list->next;
}
gen_fprintf(f,
"\tif (parent_tree) {\n"
"\t\tti = proto_tree_add_item(parent_tree, proto_%s, tvb, offset, -1, ENC_NA);\n"
"\t\ttree = proto_item_add_subtree(ti, ett_%s);\n"
"\t}\n", p->id, p->id);
gen_fprintf(f, "\tif (parent_tree) {\n");
if (p->format) {
/* TODO */
gen_fprintf(f, "\t\tti = proto_tree_add_protocol_format(parent_tree, proto_%s, tvb, offset, -1, ", p->id);
gen_fprintf(f, "\"TODO\"");
gen_expr(stderr, p->format);
gen_fprintf(f, ");\n");
} else
gen_fprintf(f, "\t\tti = proto_tree_add_item(parent_tree, proto_%s, tvb, offset, -1, ENC_NA);\n", p->id);
}
gen_fprintf(f, "\t\ttree = proto_item_add_subtree(ti, ett_%s);\n", p->id);
gen_fprintf(f, "\t}\n");
memset(&this, 0, sizeof(this));
this.id = p->id;
this.byte_order = p->byte_order_attr;
this.id = NULL;
this.byte_order = byte_order_attr;
gen_statements(f, &this, p->sts);
@ -1504,7 +1615,17 @@ gen_struct(FILE *f, npl_struct_t *s, npl_attribute_list_t *attr_list)
resolve_attr_list(attr_list);
while (attr_list) {
/* XXX, attr */
const char *attr_name = attr_list->resolved;
/*
npl_expression_t *attr_expr = attr_list->assign_expr;
int attr_flags = attr_list->flags;
*/
if (attr_name) {
fprintf(stderr, "!!! generating struct attr: %s!\n", attr_name);
} else
fprintf(stderr, "!!! generating struct attr: not resolved!\n");
attr_list = attr_list->next;
}
@ -1521,9 +1642,9 @@ gen_struct(FILE *f, npl_struct_t *s, npl_attribute_list_t *attr_list)
gen_fprintf(f,
"\tif (parent_tree) {\n"
"\t\tti = proto_tree_add_bytes_format_value(parent_tree, hf_index, tvb, offset, 0, NULL, \"%s\");\n"
"\t\tti = proto_tree_add_bytes_format_value(parent_tree, hf_index, tvb, offset, %d, NULL, \"%s\");\n"
"\t\ttree = proto_item_add_subtree(ti, %s);\n"
"\t}\n", "", ett_var(s->ett));
"\t}\n", s->struct_size, "", ett_var(s->ett));
} else {
if (s->format)
@ -1534,9 +1655,18 @@ gen_struct(FILE *f, npl_struct_t *s, npl_attribute_list_t *attr_list)
this.id = s->id;
gen_statements(f, &this, s->sts);
s->struct_size = this.cur_offset;
if (!s->private)
if (s->struct_size != -1) {
/* XXX, assert runtime s->struct_size == offset - org_offset (?) */
}
if (!s->private && s->struct_size == -1)
gen_fprintf(f, "\tproto_item_set_len(ti, offset - org_offset);\n");
if (s->struct_size == -1)
s->struct_size = 0;
gen_fprintf(f, "\treturn offset;\n");
gen_fprintf(f, "}\n");
gen_fprintf(f, "\n");
@ -1749,6 +1879,65 @@ merge_code(npl_code_t *code, npl_code_t *subcode)
*p = subcode->decls;
}
/* XXX, move to checker.c */
static void
check_code(npl_code_t *code)
{
parse_includes(code);
walk_code(NULL, code, 1);
}
/* XXX, move to generator-c.c */
static void
generate_code(npl_code_t *code)
{
const npl_protocol_t *proto = get_protocol(code);
const char *proto_name = (proto) ? proto->id : "noname";
FILE *out;
struct symbol *sym;
out = fopen("/tmp/npl.c", "w");
/* 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");
/* declare forward (or extern) */
/* XXX, not enough to generate from table (like private structs) */
for (sym = symbols; sym; sym = sym->next) {
const char *sstatic = (sym->is_static) ? "static " : "";
if (!sym->is_used)
continue;
switch (sym->type) {
case SYMBOL_TABLE:
gen_fprintf(out, "%sconst char *format_table_%s(...);\n", sstatic, sym->id);
break;
case SYMBOL_STRUCT:
gen_fprintf(out, "%sint dissect_struct_%s(tvbuff_t *, packet_info *, proto_tree *, int, int);\n", sstatic, sym->id);
break;
case SYMBOL_PROTO:
gen_fprintf(out, "%sint dissect_%s(tvbuff_t *, packet_info *, proto_tree *, void *);\n", sstatic, sym->id);
break;
}
}
gen_fprintf(out, "\n");
gen_fprintf(out, "static int proto_%s = -1;\n", proto_name);
gen_fprintf(out, "static int ett_%s = -1;\n", proto_name);
gen_vars(out);
walk_code(out, code, 1);
gen_proto_register(out, proto_name);
gen_proto_handoff(out, proto_name);
fclose(out);
}
int main(int argc, char **argv) {
FILE *f;
npl_code_t code;
@ -1760,10 +1949,19 @@ int main(int argc, char **argv) {
return 1;
}
/* build-in symbols */
/* build-in expressions */
symbol_add("FrameOffset", SYMBOL_SIMPLE, "offset");
symbol_add("FrameData", SYMBOL_SIMPLE, "tvb");
symbol_add("this", SYMBOL_EXPR, &this_e);
/* built-in functions */
symbol_add("FormatString", SYMBOL_EXPR, &format_string_e);
symbol_add("IsValueNone", SYMBOL_EXPR, &is_value_none_e);
/* built-in structs (?) */
symbol_add("Property", SYMBOL_EXPR, &property_e); /* XXX, SYMBOL_STRUCT */
symbol_add("Global", SYMBOL_EXPR, &global_e); /* XXX, SYMBOL_STRUCT */
symbol_add("Local", SYMBOL_EXPR, &local_e); /* XXX, SYMBOL_STRUCT */
memset(&code, 0, sizeof(code));
@ -1789,58 +1987,9 @@ int main(int argc, char **argv) {
merge_code(&code, &mcode);
}
#if 1
{
const npl_protocol_t *proto = get_protocol(&code);
const char *proto_name = (proto) ? proto->id : "noname";
FILE *out;
struct symbol *sym;
check_code(&code);
generate_code(&code);
parse_includes(&code);
walk_code(NULL, &code, 1);
out = fopen("/tmp/npl.c", "w");
/* 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");
/* declare forward (or extern) */
/* XXX, not enough to generate from table (like private structs) */
for (sym = symbols; sym; sym = sym->next) {
const char *sstatic = (sym->is_static) ? "static " : "";
if (!sym->is_used)
continue;
switch (sym->type) {
case SYMBOL_TABLE:
gen_fprintf(out, "%sconst char *format_table_%s(...)\n", sstatic, sym->id);
break;
case SYMBOL_STRUCT:
gen_fprintf(out, "%sint dissect_struct_%s(tvbuff_t *, packet_info *, proto_tree *, int, int);\n", sstatic, sym->id);
break;
case SYMBOL_PROTO:
gen_fprintf(out, "%sint dissect_%s(tvbuff_t *, packet_info *, proto_tree *, void *);\n", sstatic, sym->id);
break;
}
}
gen_fprintf(out, "\n");
gen_fprintf(out, "static int proto_%s = -1;\n", proto_name);
gen_fprintf(out, "static int ett_%s = -1;\n", proto_name);
gen_vars(out);
walk_code(out, &code, 1);
gen_proto_register(out, proto_name);
gen_proto_handoff(out, proto_name);
fclose(out);
}
#endif
return 0;
}