Filter: More cleanup -- customized structures also in struct f_line_item
This commit is contained in:
parent
0b39b1cbb7
commit
ea4f55e3dc
8 changed files with 191 additions and 148 deletions
|
@ -572,9 +572,9 @@ decls: /* EMPTY */ { $$ = NULL; }
|
||||||
/* Declarations that have no ';' at the end. Beware; these are reversed. */
|
/* Declarations that have no ';' at the end. Beware; these are reversed. */
|
||||||
declsn: one_decl { $$.inst = $1; $$.count = 1; }
|
declsn: one_decl { $$.inst = $1; $$.count = 1; }
|
||||||
| one_decl ';' declsn {
|
| one_decl ';' declsn {
|
||||||
$$ = $3;
|
$1->next = $3.inst;
|
||||||
$$.count++;
|
$$.count = $3.count + 1;
|
||||||
$$.inst->next = $1;
|
$$.inst = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -861,7 +861,7 @@ function_call:
|
||||||
;
|
;
|
||||||
|
|
||||||
symbol_value:
|
symbol_value:
|
||||||
CF_SYM_CONSTANT { $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->val); }
|
CF_SYM_CONSTANT { $$ = f_new_inst(FI_VARIABLE, $1); }
|
||||||
| CF_SYM_VARIABLE { $$ = f_new_inst(FI_VARIABLE, $1); }
|
| CF_SYM_VARIABLE { $$ = f_new_inst(FI_VARIABLE, $1); }
|
||||||
| CF_SYM_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *$1->attribute); }
|
| CF_SYM_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *$1->attribute); }
|
||||||
;
|
;
|
||||||
|
|
130
filter/decl.m4
130
filter/decl.m4
|
@ -14,12 +14,11 @@ m4_divert(-1)m4_dnl
|
||||||
# 7 dump line item callers
|
# 7 dump line item callers
|
||||||
# 8 postfixify
|
# 8 postfixify
|
||||||
# 9 same (filter comparator)
|
# 9 same (filter comparator)
|
||||||
# 1 struct f_inst_FI_...
|
# 1 union in struct f_inst
|
||||||
# 2 union in struct f_inst
|
|
||||||
# 3 constructors
|
# 3 constructors
|
||||||
#
|
#
|
||||||
# Per-inst Diversions:
|
# Per-inst Diversions:
|
||||||
# 101 content of struct f_inst_FI_...
|
# 101 content of per-inst struct
|
||||||
# 102 constructor arguments
|
# 102 constructor arguments
|
||||||
# 103 constructor body
|
# 103 constructor body
|
||||||
# 104 dump line item content
|
# 104 dump line item content
|
||||||
|
@ -35,8 +34,8 @@ m4_define(FID_END, `m4_divert(-1)')
|
||||||
m4_dnl m4_debugmode(aceflqtx)
|
m4_dnl m4_debugmode(aceflqtx)
|
||||||
|
|
||||||
m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */')
|
m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */')
|
||||||
m4_define(FID_STRUCT, `FID_ZONE(1, Per-instruction structure)')
|
m4_define(FID_INST, `FID_ZONE(1, Instruction structure for config)')
|
||||||
m4_define(FID_UNION, `FID_ZONE(2, Union member)')
|
m4_define(FID_LINE, `FID_ZONE(2, Instruction structure for interpreter)')
|
||||||
m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
|
m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
|
||||||
m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
|
m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
|
||||||
m4_define(FID_ENUM_STR, `FID_ZONE(5, Code enum to string)')
|
m4_define(FID_ENUM_STR, `FID_ZONE(5, Code enum to string)')
|
||||||
|
@ -51,6 +50,7 @@ m4_define(FID_NEW_BODY, `m4_divert(103)')
|
||||||
m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
|
m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
|
||||||
m4_define(FID_POSTFIXIFY_BODY, `m4_divert(105)m4_define([[FID_POSTFIXIFY_BODY_EXISTS]])')
|
m4_define(FID_POSTFIXIFY_BODY, `m4_divert(105)m4_define([[FID_POSTFIXIFY_BODY_EXISTS]])')
|
||||||
m4_define(FID_SAME_BODY, `m4_divert(106)')
|
m4_define(FID_SAME_BODY, `m4_divert(106)')
|
||||||
|
m4_define(FID_LINE_IN, `m4_divert(107)')
|
||||||
|
|
||||||
m4_define(FID_ALL, `m4_ifdef([[FID_CURDIV]], [[m4_divert(FID_CURDIV)m4_undefine([[FID_CURDIV]])]])')
|
m4_define(FID_ALL, `m4_ifdef([[FID_CURDIV]], [[m4_divert(FID_CURDIV)m4_undefine([[FID_CURDIV]])]])')
|
||||||
m4_define(FID_C, `m4_ifelse(TARGET, [[C]], FID_ALL, [[m4_define(FID_CURDIV, m4_divnum)m4_divert(-1)]])')
|
m4_define(FID_C, `m4_ifelse(TARGET, [[C]], FID_ALL, [[m4_define(FID_CURDIV, m4_divnum)m4_divert(-1)]])')
|
||||||
|
@ -62,12 +62,14 @@ FID_ENUM
|
||||||
INST_NAME(),
|
INST_NAME(),
|
||||||
FID_ENUM_STR
|
FID_ENUM_STR
|
||||||
[INST_NAME()] = "INST_NAME()",
|
[INST_NAME()] = "INST_NAME()",
|
||||||
FID_STRUCT
|
FID_INST
|
||||||
struct f_inst_[[]]INST_NAME() {
|
struct {
|
||||||
m4_undivert(101)
|
m4_undivert(101)
|
||||||
};
|
} i_[[]]INST_NAME();
|
||||||
FID_UNION
|
FID_LINE
|
||||||
struct f_inst_[[]]INST_NAME() i_[[]]INST_NAME();
|
struct {
|
||||||
|
m4_undivert(107)
|
||||||
|
} i_[[]]INST_NAME();
|
||||||
FID_NEW
|
FID_NEW
|
||||||
struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
|
struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
|
||||||
m4_undivert(102)
|
m4_undivert(102)
|
||||||
|
@ -80,8 +82,9 @@ FID_C
|
||||||
what_->fi_code = fi_code;
|
what_->fi_code = fi_code;
|
||||||
what_->lineno = ifs->lino;
|
what_->lineno = ifs->lino;
|
||||||
what_->size = 1;
|
what_->size = 1;
|
||||||
struct f_inst_[[]]INST_NAME() *what UNUSED = &(what_->i_[[]]INST_NAME());
|
#define what (&(what_->i_]]INST_NAME()[[))
|
||||||
m4_undivert(103)
|
m4_undivert(103)
|
||||||
|
#undef what
|
||||||
return what_;
|
return what_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,19 +93,23 @@ case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break;
|
||||||
|
|
||||||
FID_DUMP
|
FID_DUMP
|
||||||
m4_ifdef([[FID_DUMP_BODY_EXISTS]],
|
m4_ifdef([[FID_DUMP_BODY_EXISTS]],
|
||||||
[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item, const int indent)]]
|
[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item_, const int indent)]],
|
||||||
,
|
|
||||||
[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]])
|
[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]])
|
||||||
m4_undefine([[FID_DUMP_BODY_EXISTS]])
|
m4_undefine([[FID_DUMP_BODY_EXISTS]])
|
||||||
{
|
{
|
||||||
|
#define item (&(item_->i_]]INST_NAME()[[))
|
||||||
m4_undivert(104)
|
m4_undivert(104)
|
||||||
|
#undef item
|
||||||
}
|
}
|
||||||
FID_ALL
|
FID_ALL
|
||||||
|
|
||||||
FID_POSTFIXIFY
|
FID_POSTFIXIFY
|
||||||
case INST_NAME(): {
|
case INST_NAME(): {
|
||||||
m4_ifdef([[FID_POSTFIXIFY_BODY_EXISTS]], [[const struct f_inst_]]INST_NAME()[[ *what = &(what_->i_]]INST_NAME()[[);]], [[]])
|
#define what (&(what_->i_]]INST_NAME()[[))
|
||||||
|
#define item (&(dest->items[pos].i_]]INST_NAME()[[))
|
||||||
m4_undivert(105)
|
m4_undivert(105)
|
||||||
|
#undef what
|
||||||
|
#undef item
|
||||||
dest->items[pos].fi_code = what_->fi_code;
|
dest->items[pos].fi_code = what_->fi_code;
|
||||||
dest->items[pos].lineno = what_->lineno;
|
dest->items[pos].lineno = what_->lineno;
|
||||||
break;
|
break;
|
||||||
|
@ -111,7 +118,11 @@ m4_undefine([[FID_POSTFIXIFY_BODY_EXISTS]])
|
||||||
|
|
||||||
FID_SAME
|
FID_SAME
|
||||||
case INST_NAME():
|
case INST_NAME():
|
||||||
|
#define f1 (&(f1_->i_]]INST_NAME()[[))
|
||||||
|
#define f2 (&(f2_->i_]]INST_NAME()[[))
|
||||||
m4_undivert(106)
|
m4_undivert(106)
|
||||||
|
#undef f1
|
||||||
|
#undef f2
|
||||||
break;
|
break;
|
||||||
|
|
||||||
FID_END
|
FID_END
|
||||||
|
@ -127,6 +138,8 @@ m4_dnl comparator for same
|
||||||
m4_dnl dump format string
|
m4_dnl dump format string
|
||||||
m4_dnl dump format args
|
m4_dnl dump format args
|
||||||
m4_define(FID_MEMBER, `m4_dnl
|
m4_define(FID_MEMBER, `m4_dnl
|
||||||
|
FID_LINE_IN
|
||||||
|
$1 $2;
|
||||||
FID_STRUCT_IN
|
FID_STRUCT_IN
|
||||||
$1 $2;
|
$1 $2;
|
||||||
FID_NEW_ARGS
|
FID_NEW_ARGS
|
||||||
|
@ -135,7 +148,7 @@ FID_NEW_BODY
|
||||||
what->$2 = $2;
|
what->$2 = $2;
|
||||||
m4_ifelse($3,,,[[
|
m4_ifelse($3,,,[[
|
||||||
FID_POSTFIXIFY_BODY
|
FID_POSTFIXIFY_BODY
|
||||||
dest->items[pos].$3 = what->$2;
|
item->$3 = what->$2;
|
||||||
]])
|
]])
|
||||||
m4_ifelse($4,,,[[
|
m4_ifelse($4,,,[[
|
||||||
FID_SAME_BODY
|
FID_SAME_BODY
|
||||||
|
@ -147,55 +160,37 @@ debug("%s$5\n", INDENT, $6);
|
||||||
]])
|
]])
|
||||||
FID_END')
|
FID_END')
|
||||||
|
|
||||||
m4_define(ARG, `FID_MEMBER(const struct f_inst *, f$1,,,,)
|
m4_define(ARG, `
|
||||||
|
FID_STRUCT_IN
|
||||||
|
const struct f_inst * f$1;
|
||||||
|
FID_NEW_ARGS
|
||||||
|
, const struct f_inst * f$1
|
||||||
FID_NEW_BODY
|
FID_NEW_BODY
|
||||||
|
what->f$1 = f$1;
|
||||||
for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
|
for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
|
||||||
FID_POSTFIXIFY_BODY
|
FID_POSTFIXIFY_BODY
|
||||||
pos = postfixify(dest, what->f$1, pos);
|
pos = postfixify(dest, what->f$1, pos);
|
||||||
FID_END')
|
FID_END')
|
||||||
m4_define(ARG_ANY, `FID_MEMBER(const struct f_inst *, f$1,,,,)
|
m4_define(ARG_ANY, `ARG($@)')
|
||||||
|
m4_define(LINE, `
|
||||||
|
FID_LINE_IN
|
||||||
|
const struct f_line * fl$1;
|
||||||
|
FID_STRUCT_IN
|
||||||
|
const struct f_inst * f$1;
|
||||||
|
FID_NEW_ARGS
|
||||||
|
, const struct f_inst * f$1
|
||||||
FID_NEW_BODY
|
FID_NEW_BODY
|
||||||
for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
|
what->f$1 = f$1;
|
||||||
FID_POSTFIXIFY_BODY
|
|
||||||
pos = postfixify(dest, what->f$1, pos);
|
|
||||||
FID_END')
|
|
||||||
m4_define(LINE, `FID_MEMBER(const struct f_inst *, f$1,,[[!f_same(f1->lines[$2], f2->lines[$2])]],,)
|
|
||||||
FID_DUMP_BODY
|
FID_DUMP_BODY
|
||||||
f_dump_line(item->lines[$2], indent + 1);
|
f_dump_line(item->fl$1, indent + 1);
|
||||||
FID_POSTFIXIFY_BODY
|
FID_POSTFIXIFY_BODY
|
||||||
dest->items[pos].lines[$2] = f_postfixify(what->f$1);
|
item->fl$1 = f_postfixify(what->f$1);
|
||||||
FID_END')
|
|
||||||
m4_define(LINEP, `FID_STRUCT_IN
|
|
||||||
const struct f_line *fl$1;
|
|
||||||
FID_DUMP_BODY
|
|
||||||
f_dump_line(item->lines[$2], indent + 1)
|
|
||||||
FID_POSTFIXIFY_BODY
|
|
||||||
dest->items[pos].lines[$2] = what->fl$1;
|
|
||||||
FID_SAME_BODY
|
FID_SAME_BODY
|
||||||
if (!f_same(f1->lines[$2], f2->lines[$2])) return 0;
|
if (!f_same(f1->fl$1, f2->fl$1)) return 0;
|
||||||
FID_END')
|
FID_END')
|
||||||
m4_define(SYMBOL, `FID_MEMBER(const struct symbol *, sym, sym,
|
m4_define(SYMBOL, `FID_MEMBER(const struct symbol *, sym, sym,
|
||||||
[[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name)')
|
[[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name)')
|
||||||
m4_define(VALI, `FID_MEMBER(struct f_val, vali, val, [[!val_same(&f1->val, &f2->val)]], value %s, val_dump(&item->val))')
|
m4_define(VAL, `FID_MEMBER(struct f_val $1, val, val m4_ifelse($1,,,[0]), [[!val_same(&f1->val, &f2->val)]], value %s, val_dump(&item->val))')
|
||||||
m4_define(VALP, `FID_MEMBER(const struct f_val *, valp,, [[!val_same(&f1->val, &f2->val)]], value %s, val_dump(&item->val))
|
|
||||||
FID_POSTFIXIFY_BODY
|
|
||||||
dest->items[pos].val = *(what->valp);
|
|
||||||
FID_END')
|
|
||||||
m4_define(VAR, `m4_dnl
|
|
||||||
FID_STRUCT_IN
|
|
||||||
const struct f_val *valp;
|
|
||||||
const struct symbol *sym;
|
|
||||||
FID_NEW_ARGS
|
|
||||||
, const struct symbol *sym
|
|
||||||
FID_NEW_BODY
|
|
||||||
what->valp = (what->sym = sym)->val;
|
|
||||||
FID_POSTFIXIFY_BODY
|
|
||||||
dest->items[pos].vp = (dest->items[pos].sym = what->sym)->val;
|
|
||||||
FID_SAME_BODY
|
|
||||||
if (strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)) return 0;
|
|
||||||
FID_DUMP_BODY
|
|
||||||
debug("%svariable %s with value %s\n", INDENT, item->sym->name, val_dump(item->vp));
|
|
||||||
FID_END')
|
|
||||||
m4_define(FRET, `FID_MEMBER(enum filter_return, fret, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret))')
|
m4_define(FRET, `FID_MEMBER(enum filter_return, fret, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret))')
|
||||||
m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs))')
|
m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs))')
|
||||||
m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], route table %s, item->rtc->name)')
|
m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], route table %s, item->rtc->name)')
|
||||||
|
@ -240,11 +235,10 @@ FID_WR_PUT(3)
|
||||||
/* Line dumpers */
|
/* Line dumpers */
|
||||||
#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
|
#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
|
||||||
static const char f_dump_line_indent_str[] = " ";
|
static const char f_dump_line_indent_str[] = " ";
|
||||||
void f_dump_line(const struct f_line *dest, int indent);
|
|
||||||
|
|
||||||
FID_WR_PUT(6)
|
FID_WR_PUT(6)
|
||||||
|
|
||||||
void f_dump_line(const struct f_line *dest, int indent)
|
void f_dump_line(const struct f_line *dest, uint indent)
|
||||||
{
|
{
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
debug("%sNo filter line (NULL)\n", INDENT);
|
debug("%sNo filter line (NULL)\n", INDENT);
|
||||||
|
@ -305,17 +299,19 @@ f_same(const struct f_line *fl1, const struct f_line *fl2)
|
||||||
if (fl1->len != fl2->len)
|
if (fl1->len != fl2->len)
|
||||||
return 0;
|
return 0;
|
||||||
for (uint i=0; i<fl1->len; i++) {
|
for (uint i=0; i<fl1->len; i++) {
|
||||||
#define f1 (&(fl1->items[i]))
|
#define f1_ (&(fl1->items[i]))
|
||||||
#define f2 (&(fl2->items[i]))
|
#define f2_ (&(fl2->items[i]))
|
||||||
if (f1->fi_code != f2->fi_code)
|
if (f1_->fi_code != f2_->fi_code)
|
||||||
return 0;
|
return 0;
|
||||||
if (f1->flags != f2->flags)
|
if (f1_->flags != f2_->flags)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch(f1->fi_code) {
|
switch(f1_->fi_code) {
|
||||||
FID_WR_PUT(9)
|
FID_WR_PUT(9)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#undef f1_
|
||||||
|
#undef f2_
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,16 +320,24 @@ FID_WR_DIRECT(900,H)
|
||||||
/* Filter instruction codes */
|
/* Filter instruction codes */
|
||||||
enum f_instruction_code {
|
enum f_instruction_code {
|
||||||
FID_WR_PUT(4)
|
FID_WR_PUT(4)
|
||||||
};
|
} PACKED;
|
||||||
|
|
||||||
/* Per-instruction structures */
|
|
||||||
FID_WR_PUT(1)
|
|
||||||
|
|
||||||
|
/* Filter instruction structure for config */
|
||||||
struct f_inst {
|
struct f_inst {
|
||||||
const struct f_inst *next; /* Next instruction */
|
const struct f_inst *next; /* Next instruction */
|
||||||
enum f_instruction_code fi_code; /* Instruction code */
|
enum f_instruction_code fi_code; /* Instruction code */
|
||||||
int size; /* How many instructions are underneath */
|
int size; /* How many instructions are underneath */
|
||||||
int lineno; /* Line number */
|
int lineno; /* Line number */
|
||||||
|
union {
|
||||||
|
FID_WR_PUT(1)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Filter line item */
|
||||||
|
struct f_line_item {
|
||||||
|
enum f_instruction_code fi_code; /* What to do */
|
||||||
|
enum f_instruction_flags flags; /* Flags, instruction-specific */
|
||||||
|
uint lineno; /* Where */
|
||||||
union {
|
union {
|
||||||
FID_WR_PUT(2)
|
FID_WR_PUT(2)
|
||||||
};
|
};
|
||||||
|
|
124
filter/f-inst.c
124
filter/f-inst.c
|
@ -119,13 +119,12 @@
|
||||||
what->count = len;
|
what->count = len;
|
||||||
FID_END
|
FID_END
|
||||||
|
|
||||||
if (vstk.cnt < what->count) /* TODO: make this check systematic */
|
if (vstk.cnt < whati->count) /* TODO: make this check systematic */
|
||||||
runtime("Construction of BGP path mask from %u elements must have at least that number of elements", what->count);
|
runtime("Construction of BGP path mask from %u elements must have at least that number of elements", whati->count);
|
||||||
|
|
||||||
struct f_path_mask *pm = lp_alloc(fs->pool, sizeof(struct f_path_mask) + what->count * sizeof(struct f_path_mask_item));
|
struct f_path_mask *pm = lp_alloc(fs->pool, sizeof(struct f_path_mask) + whati->count * sizeof(struct f_path_mask_item));
|
||||||
for (uint i=0; i<what->count; i++) {
|
for (uint i=0; i<whati->count; i++) {
|
||||||
//#define pv vstk.val[vstk.cnt-i-1]
|
#define pv vstk.val[vstk.cnt - whati->count + i]
|
||||||
#define pv vstk.val[vstk.cnt - what->count + i]
|
|
||||||
switch (pv.type) {
|
switch (pv.type) {
|
||||||
case T_PATH_MASK_ITEM:
|
case T_PATH_MASK_ITEM:
|
||||||
pm->item[i] = pv.val.pmi;
|
pm->item[i] = pv.val.pmi;
|
||||||
|
@ -141,8 +140,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vstk.cnt -= what->count;
|
vstk.cnt -= whati->count;
|
||||||
pm->len = what->count;
|
pm->len = whati->count;
|
||||||
|
|
||||||
RESULT(T_PATH_MASK, path_mask, pm);
|
RESULT(T_PATH_MASK, path_mask, pm);
|
||||||
}
|
}
|
||||||
|
@ -246,15 +245,53 @@
|
||||||
|
|
||||||
/* some constants have value in a[1], some in *a[0].p, strange. */
|
/* some constants have value in a[1], some in *a[0].p, strange. */
|
||||||
INST(FI_CONSTANT, 0, 1) { /* integer (or simple type) constant, string, set, or prefix_set */
|
INST(FI_CONSTANT, 0, 1) { /* integer (or simple type) constant, string, set, or prefix_set */
|
||||||
VALI; // res = what->val;
|
FID_LINE_IN
|
||||||
|
struct f_val val;
|
||||||
|
FID_STRUCT_IN
|
||||||
|
struct f_val val;
|
||||||
|
FID_NEW_ARGS
|
||||||
|
, const struct f_val val
|
||||||
|
FID_NEW_BODY
|
||||||
|
what->val = val;
|
||||||
|
FID_POSTFIXIFY_BODY
|
||||||
|
item->val = what->val;
|
||||||
|
FID_SAME_BODY
|
||||||
|
if (!val_same(&(f1->val), &(f2->val))) return 0;
|
||||||
|
FID_DUMP_BODY
|
||||||
|
debug("%svalue %s\n", INDENT, val_dump(&item->val));
|
||||||
|
FID_END
|
||||||
|
|
||||||
|
res = whati->val;
|
||||||
RESULT_OK;
|
RESULT_OK;
|
||||||
}
|
}
|
||||||
INST(FI_VARIABLE, 0, 1) {
|
INST(FI_VARIABLE, 0, 1) {
|
||||||
VAR;
|
FID_STRUCT_IN
|
||||||
RESULT_OK;
|
const struct symbol *sym;
|
||||||
}
|
FID_LINE_IN
|
||||||
INST(FI_CONSTANT_INDIRECT, 0, 1) {
|
const struct symbol *sym;
|
||||||
VALP;
|
const struct f_val *valp;
|
||||||
|
FID_NEW_ARGS
|
||||||
|
, const struct symbol *sym
|
||||||
|
FID_NEW_BODY
|
||||||
|
what->sym = sym;
|
||||||
|
FID_POSTFIXIFY_BODY
|
||||||
|
item->valp = (item->sym = what->sym)->val;
|
||||||
|
FID_SAME_BODY
|
||||||
|
if (strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)) return 0;
|
||||||
|
FID_DUMP_BODY
|
||||||
|
switch (item->sym->class) {
|
||||||
|
case SYM_CONSTANT_RANGE:
|
||||||
|
debug("%sconstant %s with value %s\n", INDENT, item->sym->name, val_dump(item->valp));
|
||||||
|
break;
|
||||||
|
case SYM_VARIABLE_RANGE:
|
||||||
|
debug("%svariable %s with current value %s\n", INDENT, item->sym->name, val_dump(item->valp));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bug("Symbol %s of type %d doesn't reference a value", item->sym->name, item->sym->class);
|
||||||
|
}
|
||||||
|
FID_END
|
||||||
|
|
||||||
|
res = *whati->valp;
|
||||||
RESULT_OK;
|
RESULT_OK;
|
||||||
}
|
}
|
||||||
INST(FI_PRINT, 1, 0) {
|
INST(FI_PRINT, 1, 0) {
|
||||||
|
@ -702,36 +739,48 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_CALL, 0, 1) {
|
INST(FI_CALL, 0, 1) {
|
||||||
/* Do not use the symbol on execution */
|
FID_LINE_IN
|
||||||
if (0) {
|
const struct f_line *args;
|
||||||
UNUSED SYMBOL;
|
const struct f_line *body;
|
||||||
}
|
struct symbol *sym;
|
||||||
|
FID_STRUCT_IN
|
||||||
/* Postfixify extracts the function body from the symbol */
|
struct symbol *sym;
|
||||||
FID_POSTFIXIFY_BODY
|
const struct f_inst *args;
|
||||||
dest->items[pos].lines[0] = what->sym->function;
|
FID_NEW_ARGS
|
||||||
FID_END
|
, struct symbol * sym
|
||||||
|
, const struct f_inst *args
|
||||||
/* First push the body on stack */
|
|
||||||
LINEX(what->lines[0]);
|
|
||||||
curline.emask |= FE_RETURN;
|
|
||||||
|
|
||||||
/* Then push the arguments */
|
|
||||||
LINE(1,1);
|
|
||||||
|
|
||||||
FID_NEW_BODY
|
FID_NEW_BODY
|
||||||
if (sym->class != SYM_FUNCTION)
|
if (sym->class != SYM_FUNCTION)
|
||||||
cf_error("You can't call something which is not a function. Really.");
|
cf_error("You can't call something which is not a function. Really.");
|
||||||
|
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
for (const struct f_inst *inst = f1; inst; inst = inst->next)
|
for (const struct f_inst *inst = args; inst; inst = inst->next)
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count != sym->function->args)
|
if (count != sym->function->args)
|
||||||
cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->function->args, count);
|
cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->function->args, count);
|
||||||
|
|
||||||
|
what->sym = sym;
|
||||||
|
what->args = args;
|
||||||
|
FID_DUMP_BODY
|
||||||
|
debug("%scalling %s with following args\n", INDENT, item->sym->name);
|
||||||
|
f_dump_line(item->args, indent + 1);
|
||||||
|
FID_POSTFIXIFY_BODY
|
||||||
|
item->args = f_postfixify(what->args);
|
||||||
|
item->body = (item->sym = what->sym)->function;
|
||||||
|
FID_SAME_BODY
|
||||||
|
/* To be done better */
|
||||||
|
if (strcmp(f1->sym->name, f2->sym->name)) return 0;
|
||||||
|
if (!f_same(f1->args, f2->args)) return 0;
|
||||||
|
if (!f_same(f1->body, f2->body)) return 0;
|
||||||
FID_END
|
FID_END
|
||||||
|
|
||||||
/* FIXME: Optimization of function comparison. */
|
/* First push the body on stack */
|
||||||
|
LINEX(whati->body);
|
||||||
|
curline.emask |= FE_RETURN;
|
||||||
|
|
||||||
|
/* Then push the arguments */
|
||||||
|
LINEX(whati->args);
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_DROP_RESULT, 1, 0) {
|
INST(FI_DROP_RESULT, 1, 0) {
|
||||||
|
@ -741,18 +790,17 @@
|
||||||
INST(FI_SWITCH, 1, 0) {
|
INST(FI_SWITCH, 1, 0) {
|
||||||
ARG_ANY(1);
|
ARG_ANY(1);
|
||||||
TREE;
|
TREE;
|
||||||
const struct f_tree *t = find_tree(what->tree, &v1);
|
if (!tree) {
|
||||||
if (!t) {
|
|
||||||
v1.type = T_VOID;
|
v1.type = T_VOID;
|
||||||
t = find_tree(what->tree, &v1);
|
tree = find_tree(tree, &v1);
|
||||||
if (!t) {
|
if (!tree) {
|
||||||
debug( "No else statement?\n");
|
debug( "No else statement?\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* It is actually possible to have t->data NULL */
|
/* It is actually possible to have t->data NULL */
|
||||||
|
|
||||||
LINEX(t->data);
|
LINEX(tree->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_IP_MASK, 2, 1) { /* IP.MASK(val) */
|
INST(FI_IP_MASK, 2, 1) { /* IP.MASK(val) */
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
#include "filter/data.h"
|
#include "filter/data.h"
|
||||||
|
|
||||||
|
/* Flags for instructions */
|
||||||
|
enum f_instruction_flags {
|
||||||
|
FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
/* Include generated filter instruction declarations */
|
/* Include generated filter instruction declarations */
|
||||||
#include "filter/inst-gen.h"
|
#include "filter/inst-gen.h"
|
||||||
|
|
||||||
|
@ -25,37 +30,9 @@ const char *f_instruction_name(enum f_instruction_code fi);
|
||||||
|
|
||||||
struct f_inst *f_clear_local_vars(struct f_inst *decls);
|
struct f_inst *f_clear_local_vars(struct f_inst *decls);
|
||||||
|
|
||||||
/* Flags for instructions */
|
|
||||||
enum f_instruction_flags {
|
|
||||||
FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Filter structures for execution */
|
/* Filter structures for execution */
|
||||||
struct f_line;
|
struct f_line;
|
||||||
|
|
||||||
/* The single instruction item */
|
|
||||||
struct f_line_item {
|
|
||||||
enum f_instruction_code fi_code; /* What to do */
|
|
||||||
enum f_instruction_flags flags; /* Flags, instruction-specific */
|
|
||||||
uint lineno; /* Where */
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
const struct f_val *vp;
|
|
||||||
const struct symbol *sym;
|
|
||||||
};
|
|
||||||
struct f_val val;
|
|
||||||
const struct f_line *lines[2];
|
|
||||||
enum filter_return fret;
|
|
||||||
struct f_static_attr sa;
|
|
||||||
struct f_dynamic_attr da;
|
|
||||||
enum ec_subtype ecs;
|
|
||||||
const char *s;
|
|
||||||
const struct f_tree *tree;
|
|
||||||
const struct rtable_config *rtc;
|
|
||||||
uint count;
|
|
||||||
}; /* Additional instruction data */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Line of instructions to be unconditionally executed one after another */
|
/* Line of instructions to be unconditionally executed one after another */
|
||||||
struct f_line {
|
struct f_line {
|
||||||
uint len; /* Line length */
|
uint len; /* Line length */
|
||||||
|
@ -68,6 +45,8 @@ struct f_line *f_postfixify_concat(const struct f_inst * const inst[], uint coun
|
||||||
static inline struct f_line *f_postfixify(const struct f_inst *root)
|
static inline struct f_line *f_postfixify(const struct f_inst *root)
|
||||||
{ return f_postfixify_concat(&root, 1); }
|
{ return f_postfixify_concat(&root, 1); }
|
||||||
|
|
||||||
|
void f_dump_line(const struct f_line *, uint indent);
|
||||||
|
|
||||||
struct filter *f_new_where(const struct f_inst *);
|
struct filter *f_new_where(const struct f_inst *);
|
||||||
static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
|
static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
|
||||||
{ return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
|
{ return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
|
||||||
|
|
|
@ -167,6 +167,11 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
|
||||||
|
|
||||||
#define curline estk.item[estk.cnt-1]
|
#define curline estk.item[estk.cnt-1]
|
||||||
|
|
||||||
|
#if DEBUGGING
|
||||||
|
debug("Interpreting line.");
|
||||||
|
f_dump_line(line, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
while (estk.cnt > 0) {
|
while (estk.cnt > 0) {
|
||||||
while (curline.pos < curline.line->len) {
|
while (curline.pos < curline.line->len) {
|
||||||
const struct f_line_item *what = &(curline.line->items[curline.pos++]);
|
const struct f_line_item *what = &(curline.line->items[curline.pos++]);
|
||||||
|
|
|
@ -74,7 +74,8 @@ bt_assert_filter(int result, const struct f_line_item *assert)
|
||||||
bt_suit_case_result = 0;
|
bt_suit_case_result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_log_suite_case_result(bt_suit_case_result, "Assertion at line %d (%s)", assert->lineno, assert->s);
|
bt_log_suite_case_result(bt_suit_case_result, "Assertion at line %d (%s)",
|
||||||
|
assert->lineno, assert->i_FI_ASSERT.s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -13,8 +13,10 @@ m4_define(DNL, `m4_dnl')
|
||||||
m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
|
m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
|
||||||
m4_divert(1)
|
m4_divert(1)
|
||||||
case INST_NAME():
|
case INST_NAME():
|
||||||
|
#define whati (&(what->i_]]INST_NAME()[[))
|
||||||
m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (vstk.cnt < INST_INVAL()) runtime("Stack underflow"); vstk.cnt -= INST_INVAL(); ]])
|
m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (vstk.cnt < INST_INVAL()) runtime("Stack underflow"); vstk.cnt -= INST_INVAL(); ]])
|
||||||
m4_undivert(2)
|
m4_undivert(2)
|
||||||
|
#undef whati
|
||||||
break;
|
break;
|
||||||
m4_divert(-1)
|
m4_divert(-1)
|
||||||
]])')
|
]])')
|
||||||
|
@ -36,37 +38,35 @@ m4_define(LINEX, `do {
|
||||||
} while (0)')
|
} while (0)')
|
||||||
|
|
||||||
m4_define(LINE, `do {
|
m4_define(LINE, `do {
|
||||||
if (what->lines[$2]) {
|
if (whati->fl$1) {
|
||||||
estk.item[estk.cnt].pos = 0;
|
estk.item[estk.cnt].pos = 0;
|
||||||
estk.item[estk.cnt].line = what->lines[$2];
|
estk.item[estk.cnt].line = whati->fl$1;
|
||||||
estk.item[estk.cnt].ventry = vstk.cnt;
|
estk.item[estk.cnt].ventry = vstk.cnt;
|
||||||
estk.item[estk.cnt].emask = 0;
|
estk.item[estk.cnt].emask = 0;
|
||||||
estk.cnt++;
|
estk.cnt++;
|
||||||
}
|
}
|
||||||
} while (0)')
|
} while (0)')
|
||||||
|
|
||||||
m4_define(LINEP, LINE($1, $2))
|
|
||||||
|
|
||||||
m4_define(ARG_ANY, `')
|
m4_define(ARG_ANY, `')
|
||||||
|
|
||||||
m4_define(SYMBOL, `const struct symbol *sym = what->sym')
|
m4_define(SYMBOL, `const struct symbol *sym = whati->sym')
|
||||||
|
|
||||||
m4_define(VALI, `res = what->val')
|
m4_define(FRET, `enum filter_return fret = whati->fret')
|
||||||
m4_define(VALP, `res = what->val')
|
m4_define(ECS, `enum ec_subtype ecs = whati->ecs')
|
||||||
m4_define(VAR, `res = *what->vp')
|
m4_define(RTC, `struct rtable *table = whati->rtc->table')
|
||||||
m4_define(FRET, `enum filter_return fret = what->fret')
|
m4_define(STATIC_ATTR, `struct f_static_attr sa = whati->sa')
|
||||||
m4_define(ECS, `enum ec_subtype ecs = what->ecs')
|
m4_define(DYNAMIC_ATTR, `struct f_dynamic_attr da = whati->da')
|
||||||
m4_define(RTC, `struct rtable *table = what->rtc->table')
|
m4_define(TREE, `const struct f_tree *tree = whati->tree')
|
||||||
m4_define(STATIC_ATTR, `struct f_static_attr sa = what->sa')
|
|
||||||
m4_define(DYNAMIC_ATTR, `struct f_dynamic_attr da = what->da')
|
|
||||||
m4_define(TREE, `')
|
|
||||||
m4_define(STRING, `')
|
m4_define(STRING, `')
|
||||||
m4_define(COUNT, `')
|
m4_define(COUNT, `')
|
||||||
m4_define(SAME, `')
|
m4_define(SAME, `')
|
||||||
m4_define(FID_STRUCT_IN, `m4_divert(-1)')
|
m4_define(FID_STRUCT_IN, `m4_divert(-1)')
|
||||||
|
m4_define(FID_LINE_IN, `m4_divert(-1)')
|
||||||
m4_define(FID_NEW_ARGS, `m4_divert(-1)')
|
m4_define(FID_NEW_ARGS, `m4_divert(-1)')
|
||||||
m4_define(FID_NEW_BODY, `m4_divert(-1)')
|
m4_define(FID_NEW_BODY, `m4_divert(-1)')
|
||||||
m4_define(FID_POSTFIXIFY_BODY, `m4_divert(-1)')
|
m4_define(FID_POSTFIXIFY_BODY, `m4_divert(-1)')
|
||||||
|
m4_define(FID_SAME_BODY, `m4_divert(-1)')
|
||||||
|
m4_define(FID_DUMP_BODY, `m4_divert(-1)')
|
||||||
m4_define(FID_END, `m4_divert(2)')
|
m4_define(FID_END, `m4_divert(2)')
|
||||||
|
|
||||||
m4_m4wrap(`
|
m4_m4wrap(`
|
||||||
|
|
|
@ -1117,6 +1117,11 @@ int i;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function callmeagain(int a; int b; int c)
|
||||||
|
{
|
||||||
|
return a + b + c;
|
||||||
|
}
|
||||||
|
|
||||||
function fifteen()
|
function fifteen()
|
||||||
{
|
{
|
||||||
return 15;
|
return 15;
|
||||||
|
@ -1133,6 +1138,7 @@ function t_call_function()
|
||||||
bt_assert(callme(3, 2) = 6);
|
bt_assert(callme(3, 2) = 6);
|
||||||
bt_assert(callme(4, 4) = 16);
|
bt_assert(callme(4, 4) = 16);
|
||||||
bt_assert(callme(7, 2) = 14);
|
bt_assert(callme(7, 2) = 14);
|
||||||
|
bt_assert(callmeagain(1, 2, 3) = 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_test_suite(t_call_function, "Testing calling functions");
|
bt_test_suite(t_call_function, "Testing calling functions");
|
||||||
|
|
Loading…
Reference in a new issue