From ace8a9cb6ae4b869b3de77b95032afb024338424 Mon Sep 17 00:00:00 2001 From: Jakub Zawadzki Date: Sun, 24 Mar 2013 16:38:57 +0000 Subject: [NPL] another weekend work. svn path=/trunk/; revision=48527 --- tools/npl/ast.h | 1 + tools/npl/npl.c | 446 +++++++++++++++++++++++++++++++++++++++++------------ tools/npl/parser.l | 18 ++- 3 files changed, 359 insertions(+), 106 deletions(-) (limited to 'tools/npl') diff --git a/tools/npl/ast.h b/tools/npl/ast.h index 75c1355049..476a3ee79d 100644 --- a/tools/npl/ast.h +++ b/tools/npl/ast.h @@ -9,6 +9,7 @@ typedef enum { OP2_INVALID = 0, OP2_ASSIGN, + OP2_ASSIGN_PLUS, OP2_PLUS, OP2_MINUS, diff --git a/tools/npl/npl.c b/tools/npl/npl.c index 5ade4f04ac..06515bf460 100644 --- a/tools/npl/npl.c +++ b/tools/npl/npl.c @@ -27,7 +27,7 @@ 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 struct symbol *gen_expr(FILE *f, npl_expression_t *e); static void gen_statements(FILE *f, struct _npl_statements *sts); static void gen_struct(FILE *f, npl_struct_t *s); @@ -50,7 +50,9 @@ enum symbol_type { SYMBOL_STRUCT = (1 << 1), SYMBOL_TABLE = (1 << 2), SYMBOL_TYPE = (1 << 3), - SYMBOL_FIELD = (1 << 4) + SYMBOL_FIELD = (1 << 4), + + SYMBOL_SIMPLE = (1 << 5) }; struct symbol { @@ -66,6 +68,8 @@ struct symbol *symbols; struct hfinfo *hfs; struct ettinfo *etts; +static npl_expression_t property_e; + static void _fail(const char *file, int line, const char *msg) { fprintf(stderr, "!!! %s:%d fail(%s)\n", file, line, msg); abort(); @@ -238,36 +242,43 @@ count_expression_list(const npl_expression_list_t *exprs) } return c; } -static const npl_expression_t * -id_to_expr(const char *id) + +static struct symbol * +expr_to_symbol(const npl_expression_t *e) { - struct symbol *sym = symbol_find(id, SYMBOL_EXPR | SYMBOL_FIELD); + struct symbol *sym = NULL; - if (!sym) { - fprintf(stderr, "can't find id: %s\n", id); - abort(); - } + if (e->type == EXPRESSION_ID) { + const char *id = e->id.id; - if (sym->type == SYMBOL_EXPR) - return sym->data; - else if (sym->type == SYMBOL_FIELD) { - fprintf(stderr, "XXX ID %s SYMBOL_FIELD\n", sym->id); - return NULL; - } else { - fprintf(stderr, "ID %s invalid type [%d]\n", sym->id, sym->type); - abort(); + sym = symbol_find(id, SYMBOL_ANY); + + if (!sym) { + fprintf(stderr, "can't find id: %s\n", id); + abort(); + } + + if (sym->type == SYMBOL_EXPR) { + struct symbol *new_sym = expr_to_symbol(sym->data); + + if (new_sym) + sym = new_sym; + } } + return sym; } static int -expr_to_int(const npl_expression_t *e, int *val) +expr_to_const_int(const npl_expression_t *e, int *val) { + struct symbol *sym; + if (e->type == EXPRESSION_INT) { *val = e->num.digit; return 1; } if (e->type == EXPRESSION_UNARY) { - if (!expr_to_int(e->u.operand, val)) + if (!expr_to_const_int(e->u.operand, val)) return 0; switch (e->u.operator) { @@ -282,29 +293,122 @@ expr_to_int(const npl_expression_t *e, int *val) return 1; } } - if (e->type == EXPRESSION_ID) { - e = id_to_expr(e->id.id); - if (e) - return expr_to_int(e, val); - } + + sym = expr_to_symbol(e); + if (sym && sym->type == SYMBOL_EXPR) + return expr_to_const_int(sym->data, val); + return 0; } static int -expr_to_str(const npl_expression_t *e, const char **val) +expr_to_const_str(const npl_expression_t *e, const char **val) { + struct symbol *sym; + if (e->type == EXPRESSION_STR) { *val = e->str.str; return 1; } - if (e->type == EXPRESSION_ID) { - e = id_to_expr(e->id.id); - if (e) - return expr_to_str(e, val); - } + + sym = expr_to_symbol(e); + if (sym && sym->type == SYMBOL_EXPR) + return expr_to_const_str(sym->data, val); + return 0; } +static const char * +type_to_ctype(const npl_type_t *t, int size) +{ + switch (t->type) { + case FIELD_DECIMAL: + if (size == 4) + return "float"; + if (size == 8) + return "double"; + + fprintf(stderr, "!!! decimal, size: %d\n", size); + return NULL; + + case FIELD_NUMBER: + if (size == 1) + return "gint8"; + if (size == 2) + return "gint16"; + if (size == 3 || size == 4) + return "gint32"; + if (size > 4 && size <= 8) + return "gint64"; + + fprintf(stderr, "!!! number, size: %d\n", size); + return NULL; + + case FIELD_UNSIGNED_NUMBER: + if (size == 1) + return "guint8"; + if (size == 2) + return "guint16"; + if (size == 3 || size == 4) + return "guint32"; + if (size > 4 && size <= 8) + return "guint64"; + + fprintf(stderr, "!!! number, size: %d\n", size); + return NULL; + + case FIELD_TIME: + return "nstime_t"; + } + fprintf(stderr, "!!! not handled, type: %d, size: %d\n", t->type, size); + return NULL; +} + +static const char * +type_to_tvb(const npl_type_t *t, int size, int endian) +{ + switch (t->type) { + case FIELD_DECIMAL: + if (size == 4 && endian == 0) + return "tvb_get_letohieee_float"; + if (size == 4 && endian == 1) + return "tvb_get_ntohieee_float"; + + if (size == 8 && endian == 0) + return "tvb_get_letohieee_double"; + if (size == 8 && endian == 1) + return "tvb_get_ntohieee_double"; + + fprintf(stderr, "!!! decimal, size: %d, endian: %d\n", size, endian); + return NULL; + + case FIELD_UNSIGNED_NUMBER: + case FIELD_NUMBER: + if (size == 1) + return "tvb_get_guint8"; + + if (size == 2 && endian == 0) + return "tvb_get_letohs"; + if (size == 2 && endian == 1) + return "tvb_get_ntohs"; + + if (t->type == FIELD_UNSIGNED_NUMBER && size == 3 && endian == 0) + return "tvb_get_letoh24"; + if (t->type == FIELD_UNSIGNED_NUMBER && size == 3 && endian == 1) + return "tvb_get_ntoh24"; + + if (size == 4 && endian == 0) + return "tvb_get_letohl"; + if (size == 4 && endian == 1) + return "tvb_get_ntohl"; + + fprintf(stderr, "!!! number, size: %d, endian: %d\n", size, endian); + return NULL; + } + fprintf(stderr, "!!! not handled, type: %d, size: %d, endian: %d\n", t->type, size, endian); + return NULL; +} + static const char * type_to_ft(const npl_type_t *t, int size) { @@ -417,64 +521,81 @@ op2_to_str(npl_op2_t op) } static void -gen_expr_type(FILE *f, npl_type_t *t) +gen_expr_field(FILE *f, struct _npl_statement_field *field) { - fprintf(stderr, "XXX gen expr type: %s\n", t->id); + xassert(field->generate_var || f == NULL); - gen_fprintf(f, "<>", t->id); + field->generate_var = 1; + gen_fprintf(f, "_field_%s", field->id); } static void +gen_expr_type(FILE *f, npl_type_t *t) +{ + int size = -1; + int byte_order = -1; + const char *fetch_func; + + if (t->size && !expr_to_const_int(t->size, &size)) + fprintf(stderr, "!!! expr_to_const_int(size) failed for type: %s\n", t->id); + + if (t->byte_order && !expr_to_const_int(t->byte_order, &byte_order)) + fprintf(stderr, "!!! expr_to_const_int(byte_order) failed for type: %s\n", t->id); + + fetch_func = type_to_tvb(t, size, byte_order); + if (fetch_func) + gen_fprintf(f, "%s", fetch_func); + else + gen_fprintf(f, "<>", 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); - - if (!sym) { - fprintf(stderr, "can't find id: %s\n", e->id.id); - gen_fprintf(f, " <> ", e->id.id); - return; - abort(); - } + { + struct symbol *sym = symbol_find(e->id.id, SYMBOL_EXPR | SYMBOL_FIELD | SYMBOL_TYPE | SYMBOL_SIMPLE); - if (sym->type == SYMBOL_EXPR) { - gen_expr(f, sym->data); - } else if (sym->type == SYMBOL_FIELD) { - struct _npl_statement_field *field = sym->data; + if (!sym) { + fprintf(stderr, "can't find id: %s\n", e->id.id); + abort(); + } - xassert(field->generate_var || f == NULL); + if (sym->type == SYMBOL_EXPR) + gen_expr(f, sym->data); - field->generate_var = 1; - gen_fprintf(f, "_field_%s", sym->id); + else if (sym->type == SYMBOL_FIELD) + gen_expr_field(f, sym->data); - } else if (sym->type == SYMBOL_TYPE) { - npl_type_t *t = sym->data; + else if (sym->type == SYMBOL_TYPE) + gen_expr_type(f, sym->data); - gen_expr_type(f, t); - } else { - fprintf(stderr, "ID %s wrong type [%d]\n", sym->id, sym->type); - abort(); - } + else if (sym->type == SYMBOL_SIMPLE) + gen_fprintf(f, "%s", (const char *) sym->data); + + else { + fprintf(stderr, "ID %s wrong type [%d]\n", sym->id, sym->type); + abort(); } - return; + return sym; + } case EXPRESSION_INT: gen_fprintf(f, " %d ", e->num.digit); - return; + return NULL; case EXPRESSION_STR: // XXX e->str.str is escaped, almost like C-string so just print it. gen_fprintf(f, " \"%s\" ", e->str.str); - return; + return NULL; case EXPRESSION_UNARY: gen_fprintf(f, "("); gen_fprintf(f, "%s", op1_to_str(e->u.operator)); gen_expr(f, e->u.operand); gen_fprintf(f, ")"); - return; + return NULL; case EXPRESSION_BINARY: gen_fprintf(f, "("); @@ -482,14 +603,18 @@ gen_expr(FILE *f, npl_expression_t *e) gen_fprintf(f, " %s ", op2_to_str(e->b.operator)); gen_expr(f, e->b.operand2); gen_fprintf(f, ")"); - return; + return NULL; case EXPRESSION_CALL: { npl_expression_list_t *arg; - char *ind = ""; + struct symbol *sym; + const char *ind = ""; + + sym = gen_expr(f, e->call.fn); + if (!sym) + abort(); - gen_expr(f, e->call.fn); gen_fprintf(f, "("); for (arg = e->call.args; arg; arg = arg->next) { gen_fprintf(f, "%s", ind); @@ -497,15 +622,40 @@ gen_expr(FILE *f, npl_expression_t *e) ind = ", "; } gen_fprintf(f, ")"); - return; + return NULL; } + case EXPRESSION_COND: + gen_fprintf(f, "(("); + gen_expr(f, e->c.test_expr); + gen_fprintf(f, ") ? "); + gen_expr(f, e->c.true_expr); + gen_fprintf(f, " : "); + gen_expr(f, e->c.false_expr); + gen_fprintf(f, ")"); + return NULL; + case EXPRESSION_FIELD: - gen_expr(f, e->fld.base); - gen_fprintf(f, ".%s ", e->fld.field); - return; + { + struct symbol *sym; + + sym = gen_expr(NULL, e->fld.base); + if (!sym) + abort(); + + if (sym->data == &property_e) { + gen_fprintf(f, "<< PROPERTY %s>>", e->fld.field); + } else { + gen_expr(f, e->fld.base); + gen_fprintf(f, ".%s ", e->fld.field); + } + return NULL; + } } + fprintf(stderr, "XXX expr->type: %d\n", e->type); + + return NULL; } static int @@ -524,12 +674,12 @@ gen_table_struct(FILE *f, npl_table_t *t) const char *str; int val; - if (!c->return_expr || !expr_to_str(c->return_expr, &str)) + if (!c->return_expr || !expr_to_const_str(c->return_expr, &str)) return 0; - if (all_int && !expr_to_int(&c->e, &val)) + if (all_int && !expr_to_const_int(&c->e, &val)) all_int = 0; - if (all_str && !expr_to_str(&c->e, &str)) + if (all_str && !expr_to_const_str(&c->e, &str)) all_str = 0; if (!all_int && !all_str) @@ -554,10 +704,10 @@ gen_table_struct(FILE *f, npl_table_t *t) 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)"); + if (!expr_to_const_str(c->return_expr, &str)) + fail("expr_to_const_str(str)"); + if (!expr_to_const_int(&c->e, &val)) + fail("expr_to_const_int(val)"); gen_fprintf(f, "\t{ 0x%x, \"%s\" },\n", val, str); } @@ -577,10 +727,10 @@ gen_table_struct(FILE *f, npl_table_t *t) 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)"); + if (!expr_to_const_str(c->return_expr, &str)) + fail("expr_to_const_str(str)"); + if (!expr_to_const_str(&c->e, &val)) + fail("expr_to_const_str(val)"); gen_fprintf(f, "\t{ \"%s\", \"%s\" },\n", val, str); } @@ -595,12 +745,15 @@ gen_table_struct(FILE *f, npl_table_t *t) static void gen_table_func(FILE *f, npl_table_t *t) { + struct symbol *symroot; struct npl_table_case *c; gen_fprintf(f, "static const char *\n" "format_table_%s", t->id); + symroot = symbols_push(); + gen_fprintf(f, "("); if (t->params.count) { int i; @@ -609,11 +762,13 @@ gen_table_func(FILE *f, npl_table_t *t) if (i) gen_fprintf(f, ", "); gen_fprintf(f, "TYPE %s", t->params.args[i]); + symbol_add(t->params.args[i], SYMBOL_SIMPLE, t->params.args[i]); } } else { /* default */ gen_fprintf(f, "TYPE value"); + symbol_add("value", SYMBOL_SIMPLE, "value"); } gen_fprintf(f, ")\n{\n"); @@ -678,6 +833,8 @@ again2: gen_fprintf(f, "\treturn \"\";\n"); gen_fprintf(f, "}\n"); + + symbols_pop(symroot); } static void @@ -700,6 +857,7 @@ static void gen_field_struct(FILE *f, npl_statement_t *st, npl_struct_t *s) { // XXX st->f.bits, st->f.arr, st->f.format, st->f.sts + // XXX, st->f.generate_var gen_fprintf(f, "\toffset = dissect_struct_%s(tvb, pinfo, tree, %s, offset);\n", s->tmpid, hfi_var(st->f.hfi)); @@ -715,6 +873,8 @@ gen_field_type(FILE *f, npl_statement_t *st, npl_type_t *t) // XXX st->f.bits, st->f.arr, st->f.sts int size = -1; + struct symbol *sym_size = NULL; + int byte_order = -1; npl_expression_t *display_format = t->display_format; const char *hf_type; @@ -734,19 +894,57 @@ gen_field_type(FILE *f, npl_statement_t *st, npl_type_t *t) argv = argv->next; } - if (t->size && !expr_to_int(t->size, &size)) - fprintf(stderr, "!!! expr_to_int(size) failed for type: %s\n", t->id); + xassert(t->size != NULL); + if (!expr_to_const_int(t->size, &size)) { + sym_size = expr_to_symbol(t->size); - 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->id); + if (!sym_size) { + fprintf(stderr, "!!! expr_to_const_int, _symbol(size) failed for type: %s\n", t->id); + abort(); + } + } + + if (t->byte_order && !expr_to_const_int(t->byte_order, &byte_order)) + fprintf(stderr, "!!! expr_to_const_int(byte_order) failed for type: %s\n", t->id); + + if (st->f.generate_var) { + /* XXX, sym_size */ + + const char *ctype = type_to_ctype(t, size); + const char *fetch_func = type_to_tvb(t, size, byte_order); + +/* + if (!ctype || !fetch_func) + abort(); +*/ + + /* XXX, we should declare variable on begin of block (< C99) */ + gen_fprintf(f, "\t%s _field_%s = %s(tvb, offset);\n", ctype, st->f.id, fetch_func); + } + + if (sym_size) { + if (sym_size->type == SYMBOL_FIELD) { + struct _npl_statement_field *field = sym_size->data; - hf_type = type_to_ft(t, size); + xassert(field->generate_var || f == NULL); + + field->generate_var = 1; + } else + fprintf(stderr, "::: %s (%d)\n", sym_size->id, sym_size->type); + + hf_type = NULL; + + } else + hf_type = type_to_ft(t, size); st->f.hfi->hf_type = hf_type; /* prefer statement format over type one (?) */ if (st->f.format) display_format = st->f.format; + + /* XXX, when generate_var we can use fetched value, not proto_tree_add_item() */ + #if 0 if (display_format) fprintf(stderr, "XXX, format\n"); @@ -758,7 +956,30 @@ gen_field_type(FILE *f, npl_statement_t *st, npl_type_t *t) (byte_order == 0) ? "ENC_LITTLE_ENDIAN" : (byte_order == 1) ? "ENC_BIG_ENDIAN" : "ENC_NA"); - gen_fprintf(f, "offset += %d;\n", size); + + if (sym_size) { + /* runtime */ + if (sym_size->type == SYMBOL_FIELD) { + gen_fprintf(f, "offset += _field_%s;\n", sym_size->id); + + } else if (sym_size->type == SYMBOL_EXPR) { + gen_fprintf(f, "\n\t"); + gen_fprintf(f, "offset += ("); + gen_expr(f, sym_size->data); + gen_fprintf(f, ");\n"); + + } else if (sym_size->type == SYMBOL_SIMPLE) { + gen_fprintf(f, "offset += %s;\n", (const char *) sym_size->data); + + } else { + fprintf(stderr, "::: %s (%d)\n", sym_size->id, sym_size->type); + gen_fprintf(f, "offset += XXX;\n"); + } + + } else { + /* const */ + gen_fprintf(f, "offset += %d;\n", size); + } symbols_pop(symroot); } @@ -800,11 +1021,6 @@ gen_statement(FILE *f, npl_statement_t *st) abort(); } - if (st->f.generate_var) { - // XXX - gen_fprintf(f, "\t_field_%s = tvb_...\n", st->f.id); - } - symbol_add(st->f.id, SYMBOL_FIELD, &st->f); if (sym->type == SYMBOL_STRUCT) @@ -1012,7 +1228,7 @@ gen_struct(FILE *f, npl_struct_t *s) gen_fprintf(f, "\tif (parent_tree) {\n" - "\t\tti = proto_tree_add_bytes_format(tree, hf_index, tvb, offset, 0, NULL, \"%s\");\n" + "\t\tti = proto_tree_add_bytes_format(parent_tree, hf_index, tvb, offset, 0, NULL, \"%s\");\n" "\t\ttree = proto_item_add_subtree(ti, %s);\n" "\t}\n", "description", ett_var(s->ett)); @@ -1233,26 +1449,57 @@ get_protocol(npl_code_t *code) return NULL; } +static void +merge_code(npl_code_t *code, npl_code_t *subcode) +{ + struct _npl_decl_list **p = &code->decls; + + while (*p) + p = &(*p)->next; + + *p = subcode->decls; +} + int main(int argc, char **argv) { FILE *f; npl_code_t code; - int parse_ok; - if (argc != 2) { + int i; + + if (argc < 2) { fprintf(stderr, "usage: %s filename\n", argv[0]); return 1; } - if (!(f = fopen(argv[1], "rb"))) { - fprintf(stderr, "can't open: %s\n", argv[1]); - return 1; - } + /* build-in symbols */ + symbol_add("FrameOffset", SYMBOL_SIMPLE, "offset"); + symbol_add("FrameData", SYMBOL_SIMPLE, "tvb"); + symbol_add("Property", SYMBOL_EXPR, &property_e); /* XXX, SYMBOL_STRUCT */ memset(&code, 0, sizeof(code)); - parse_ok = npl_parse_file(&code, f, argv[1]); -// parse_ok = 0; - if (parse_ok) { + for (i = 1; i < argc; i++) { + npl_code_t mcode; + int parse_ok; + + if (!(f = fopen(argv[i], "rb"))) { + fprintf(stderr, "can't open: %s\n", argv[i]); + return 1; + } + + memset(&mcode, 0, sizeof(mcode)); + parse_ok = npl_parse_file(&mcode, f, argv[i]); + fclose(f); + + if (!parse_ok) { + fprintf(stderr, "can't parse: %s\n", argv[i]); + return 1; + } + + merge_code(&code, &mcode); + } + + { const npl_protocol_t *proto = get_protocol(&code); const char *proto_name = (proto) ? proto->id : "noname"; FILE *out; @@ -1280,7 +1527,6 @@ int main(int argc, char **argv) { fclose(out); } - fclose(f); return 0; } diff --git a/tools/npl/parser.l b/tools/npl/parser.l index e97bce5188..57e0d5763d 100644 --- a/tools/npl/parser.l +++ b/tools/npl/parser.l @@ -79,6 +79,7 @@ typedef enum { TOKEN_GEQUAL, TOKEN_ASSIGN, + TOKEN_ASSIGN_PLUS, TOKEN_PLUS, TOKEN_MINUS, TOKEN_MULTIPLY, @@ -170,6 +171,7 @@ or return TOKEN_OROR; ">=" return TOKEN_GEQUAL; "<=" return TOKEN_LEQUAL; +"+=" return TOKEN_ASSIGN_PLUS; "=" return TOKEN_ASSIGN; "+" return TOKEN_PLUS; "-" return TOKEN_MINUS; @@ -881,14 +883,12 @@ parse_expression13(npl_expression_t *expr) expr->c.test_expr = operand; e = xnew(npl_expression_t); -// parse_expression13(e); parse_expression(e); expr->c.true_expr = e; accept(TOKEN_COLON); e = xnew(npl_expression_t); -// parse_expression13(e); - parse_expression(e); + parse_expression13(e); expr->c.false_expr = e; expr->type = EXPRESSION_COND; @@ -907,14 +907,21 @@ xparse_expression(void) static void parse_expression(npl_expression_t *expr) { + npl_op2_t op; + parse_expression13(expr); - if (is_token_accept(TOKEN_ASSIGN)) { + op = + (is_token_accept(TOKEN_ASSIGN)) ? OP2_ASSIGN : + (is_token_accept(TOKEN_ASSIGN_PLUS)) ? OP2_ASSIGN_PLUS : + OP2_INVALID; + + if (op != OP2_INVALID) { npl_expression_t *operand = xdup(npl_expression_t, expr); expr->b.operand2 = xparse_expression(); - expr->b.operator = OP2_ASSIGN; + expr->b.operator = op; expr->b.operand1 = operand; expr->type = EXPRESSION_BINARY; } @@ -1136,7 +1143,6 @@ parse_statement(npl_statement_t *st) st->f.t_id = accept_id(); if (is_token_accept(TOKEN_LPAREN)) { - /* XXX, WTF: StringTerm(Property.XMLEncoding, "<", true, false, false) Reason; */ parse_expression_list(&st->f.params); accept(TOKEN_RPAREN); -- cgit v1.2.3