]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: More cleanup -- customized structures also in struct f_line_item
authorMaria Matejka <mq@ucw.cz>
Fri, 15 Feb 2019 22:59:44 +0000 (23:59 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 20 Feb 2019 21:30:55 +0000 (22:30 +0100)
filter/config.Y
filter/decl.m4
filter/f-inst.c
filter/f-inst.h
filter/filter.c
filter/filter_test.c
filter/interpret.m4
filter/test.conf

index b3a049585c7fdfdfb08bdd65669b6e1163ad8ee2..495a5e5ba439a6a7a15b80ac4a16116500341320 100644 (file)
@@ -572,9 +572,9 @@ decls: /* EMPTY */ { $$ = NULL; }
 /* Declarations that have no ';' at the end. Beware; these are reversed. */
 declsn: one_decl { $$.inst = $1; $$.count = 1; }
  | one_decl ';' declsn {
-     $$ = $3;
-     $$.count++;
-     $$.inst->next = $1;
+     $1->next = $3.inst;
+     $$.count = $3.count + 1;
+     $$.inst = $1;
    }
  ;
 
@@ -861,7 +861,7 @@ function_call:
  ;
 
 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_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *$1->attribute); }
  ;
index 3043f4fcbdd1689025ff168b336377d4a5e49841..3033438de83a7951b40366684ccf93f22578c5a8 100644 (file)
@@ -14,12 +14,11 @@ m4_divert(-1)m4_dnl
 #      7       dump line item callers
 #      8       postfixify
 #      9       same (filter comparator)
-#      1       struct f_inst_FI_...
-#      2       union in struct f_inst
+#      1       union in struct f_inst
 #      3       constructors
 #
 #      Per-inst Diversions:
-#      101     content of struct f_inst_FI_...
+#      101     content of per-inst struct
 #      102     constructor arguments
 #      103     constructor body
 #      104     dump line item content
@@ -35,8 +34,8 @@ m4_define(FID_END, `m4_divert(-1)')
 m4_dnl m4_debugmode(aceflqtx)
 
 m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */')
-m4_define(FID_STRUCT, `FID_ZONE(1, Per-instruction structure)')
-m4_define(FID_UNION, `FID_ZONE(2, Union member)')
+m4_define(FID_INST, `FID_ZONE(1, Instruction structure for config)')
+m4_define(FID_LINE, `FID_ZONE(2, Instruction structure for interpreter)')
 m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
 m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
 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_POSTFIXIFY_BODY, `m4_divert(105)m4_define([[FID_POSTFIXIFY_BODY_EXISTS]])')
 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_C, `m4_ifelse(TARGET, [[C]], FID_ALL, [[m4_define(FID_CURDIV, m4_divnum)m4_divert(-1)]])')
@@ -62,12 +62,14 @@ FID_ENUM
 INST_NAME(),
 FID_ENUM_STR
 [INST_NAME()] = "INST_NAME()",
-FID_STRUCT
-struct f_inst_[[]]INST_NAME() {
+FID_INST
+struct {
 m4_undivert(101)
-};
-FID_UNION
-struct f_inst_[[]]INST_NAME() i_[[]]INST_NAME();
+} i_[[]]INST_NAME();
+FID_LINE
+struct {
+m4_undivert(107)
+} i_[[]]INST_NAME();
 FID_NEW
 struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
 m4_undivert(102)
@@ -80,8 +82,9 @@ FID_C
   what_->fi_code = fi_code;
   what_->lineno = ifs->lino;
   what_->size = 1;
-  struct f_inst_[[]]INST_NAME() *what UNUSED = &(what_->i_[[]]INST_NAME());
+#define what (&(what_->i_]]INST_NAME()[[))
 m4_undivert(103)
+#undef what
   return what_;
 }
 
@@ -90,19 +93,23 @@ case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break;
 
 FID_DUMP
 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)]])
 m4_undefine([[FID_DUMP_BODY_EXISTS]])
 {
+#define item (&(item_->i_]]INST_NAME()[[))
 m4_undivert(104)
+#undef item
 }
 FID_ALL
 
 FID_POSTFIXIFY
 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)
+#undef what
+#undef item
   dest->items[pos].fi_code = what_->fi_code;
   dest->items[pos].lineno = what_->lineno;
   break;
@@ -111,7 +118,11 @@ m4_undefine([[FID_POSTFIXIFY_BODY_EXISTS]])
 
 FID_SAME
 case INST_NAME():
+#define f1 (&(f1_->i_]]INST_NAME()[[))
+#define f2 (&(f2_->i_]]INST_NAME()[[))
 m4_undivert(106)
+#undef f1
+#undef f2
 break;
 
 FID_END
@@ -127,6 +138,8 @@ m4_dnl comparator for same
 m4_dnl dump format string
 m4_dnl dump format args
 m4_define(FID_MEMBER, `m4_dnl
+FID_LINE_IN
+$1 $2;
 FID_STRUCT_IN
 $1 $2;
 FID_NEW_ARGS
@@ -135,7 +148,7 @@ FID_NEW_BODY
 what->$2 = $2;
 m4_ifelse($3,,,[[
 FID_POSTFIXIFY_BODY
-dest->items[pos].$3 = what->$2;
+item->$3 = what->$2;
 ]])
 m4_ifelse($4,,,[[
 FID_SAME_BODY
@@ -147,55 +160,37 @@ debug("%s$5\n", INDENT, $6);
 ]])
 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
+what->f$1 = f$1;
 for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
 FID_POSTFIXIFY_BODY
 pos = postfixify(dest, what->f$1, pos);
 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
-for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size;
-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])]],,)
+what->f$1 = f$1;
 FID_DUMP_BODY
-f_dump_line(item->lines[$2], indent + 1);
+f_dump_line(item->fl$1, indent + 1);
 FID_POSTFIXIFY_BODY
-dest->items[pos].lines[$2] = 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;
+item->fl$1 = f_postfixify(what->f$1);
 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')
 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)')
-m4_define(VALI, `FID_MEMBER(struct f_val, vali, val, [[!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(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(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(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 */
 #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[] = "                                ";
-void f_dump_line(const struct f_line *dest, int indent);
 
 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) {
     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)
     return 0;
   for (uint i=0; i<fl1->len; i++) {
-#define f1 (&(fl1->items[i]))
-#define f2 (&(fl2->items[i]))
-    if (f1->fi_code != f2->fi_code)
+#define f1_ (&(fl1->items[i]))
+#define f2_ (&(fl2->items[i]))
+    if (f1_->fi_code != f2_->fi_code)
       return 0;
-    if (f1->flags != f2->flags)
+    if (f1_->flags != f2_->flags)
       return 0;
 
-    switch(f1->fi_code) {
+    switch(f1_->fi_code) {
 FID_WR_PUT(9)
     }
   }
+#undef f1_
+#undef f2_
   return 1;
 }
 
@@ -324,16 +320,24 @@ FID_WR_DIRECT(900,H)
 /* Filter instruction codes */
 enum f_instruction_code {
 FID_WR_PUT(4)
-};
-
-/* Per-instruction structures */
-FID_WR_PUT(1)
+} PACKED;
 
+/* Filter instruction structure for config */
 struct f_inst {
   const struct f_inst *next;           /* Next instruction */
   enum f_instruction_code fi_code;     /* Instruction code */
   int size;                            /* How many instructions are underneath */
   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 {
     FID_WR_PUT(2)
   };
index 6f563873e77594b5d0bdfdce676e87bdc20a788a..128b9e54eb7588471255336444308379aa66b11e 100644 (file)
       what->count = len;
     FID_END
 
-    if (vstk.cnt < what->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);
+    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", whati->count);
 
-    struct f_path_mask *pm = lp_alloc(fs->pool, sizeof(struct f_path_mask) + what->count * sizeof(struct f_path_mask_item));
-    for (uint i=0; i<what->count; i++) {
-//#define pv vstk.val[vstk.cnt-i-1]
-#define pv vstk.val[vstk.cnt - what->count + i]
+    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<whati->count; i++) {
+#define pv vstk.val[vstk.cnt - whati->count + i]
       switch (pv.type) {
        case T_PATH_MASK_ITEM:
          pm->item[i] = pv.val.pmi;
       }
     }
 
-    vstk.cnt -= what->count;
-    pm->len = what->count;
+    vstk.cnt -= whati->count;
+    pm->len = whati->count;
 
     RESULT(T_PATH_MASK, path_mask, pm);
   }
 
     /* 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 */
-    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;
   }
   INST(FI_VARIABLE, 0, 1) {
-    VAR;
-    RESULT_OK;
-  }
-  INST(FI_CONSTANT_INDIRECT, 0, 1) {
-    VALP;
+    FID_STRUCT_IN
+      const struct symbol *sym;
+    FID_LINE_IN
+      const struct symbol *sym;
+      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;
   }
   INST(FI_PRINT, 1, 0) {
   }
 
   INST(FI_CALL, 0, 1) {
-    /* Do not use the symbol on execution */
-    if (0) {
-      UNUSED SYMBOL;
-    }
-
-    /* Postfixify extracts the function body from the symbol */
-    FID_POSTFIXIFY_BODY
-    dest->items[pos].lines[0] = what->sym->function;
-    FID_END
-
-    /* First push the body on stack */
-    LINEX(what->lines[0]);
-    curline.emask |= FE_RETURN;
-
-    /* Then push the arguments */
-    LINE(1,1);
-
+    FID_LINE_IN
+      const struct f_line *args;
+      const struct f_line *body;
+      struct symbol *sym;
+    FID_STRUCT_IN
+      struct symbol *sym;
+      const struct f_inst *args;
+    FID_NEW_ARGS
+      , struct symbol * sym
+      , const struct f_inst *args
     FID_NEW_BODY
       if (sym->class != SYM_FUNCTION)
        cf_error("You can't call something which is not a function. Really.");
 
       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++;
 
       if (count != sym->function->args)
        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
 
-    /* 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_SWITCH, 1, 0) {
     ARG_ANY(1);
     TREE;
-    const struct f_tree *t = find_tree(what->tree, &v1);
-    if (!t) {
+    if (!tree) {
       v1.type = T_VOID;
-      t = find_tree(what->tree, &v1);
-      if (!t) {
+      tree = find_tree(tree, &v1);
+      if (!tree) {
        debug( "No else statement?\n");
        break;
       }
     }
     /* It is actually possible to have t->data NULL */
 
-    LINEX(t->data);
+    LINEX(tree->data);
   }
 
   INST(FI_IP_MASK, 2, 1) { /* IP.MASK(val) */
index 201be5f8c724d02367ea15bb5a56b284f6b7bdb1..5b397a5dc21baea3cccfe1284de1630ab9fe333e 100644 (file)
 #include "filter/filter.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 "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);
 
-/* Flags for instructions */
-enum f_instruction_flags {
-  FIF_PRINTED = 1,             /* FI_PRINT_AND_DIE: message put in buffer */
-};
-
 /* Filter structures for execution */
 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 */
 struct f_line {
   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)
 { 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 *);
 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 */
index 4249d4ee82f12fea1eb4d387991a9507fe9d74e1..8db5119bf584e905f604381af0943c299b85fd57 100644 (file)
@@ -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]
 
+#if DEBUGGING
+  debug("Interpreting line.");
+  f_dump_line(line, 1);
+#endif
+
   while (estk.cnt > 0) {
     while (curline.pos < curline.line->len) {
       const struct f_line_item *what = &(curline.line->items[curline.pos++]);
index d83e8a8b9ab4637c96e505f8f9d01c66091af553..d0dd281a8819c68f0aaf034e61aab533126abb76 100644 (file)
@@ -74,7 +74,8 @@ bt_assert_filter(int result, const struct f_line_item *assert)
     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
index eb368b41e753727fabf3606741898ef0d7cd1eba..ea91e74e715e1ac35038e514993772ac82de239d 100644 (file)
@@ -13,8 +13,10 @@ m4_define(DNL, `m4_dnl')
 m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
 m4_divert(1)
 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_undivert(2)
+#undef whati
 break;
 m4_divert(-1)
 ]])')
@@ -36,37 +38,35 @@ m4_define(LINEX, `do {
 } while (0)')
 
 m4_define(LINE, `do {
-  if (what->lines[$2]) {
+  if (whati->fl$1) {
     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].emask = 0;
     estk.cnt++;
   }
 } while (0)')
 
-m4_define(LINEP, LINE($1, $2))
-
 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(VALP, `res = what->val')
-m4_define(VAR, `res = *what->vp')
-m4_define(FRET, `enum filter_return fret = what->fret')
-m4_define(ECS, `enum ec_subtype ecs = what->ecs')
-m4_define(RTC, `struct rtable *table = what->rtc->table')
-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(FRET, `enum filter_return fret = whati->fret')
+m4_define(ECS, `enum ec_subtype ecs = whati->ecs')
+m4_define(RTC, `struct rtable *table = whati->rtc->table')
+m4_define(STATIC_ATTR, `struct f_static_attr sa = whati->sa')
+m4_define(DYNAMIC_ATTR, `struct f_dynamic_attr da = whati->da')
+m4_define(TREE, `const struct f_tree *tree = whati->tree')
 m4_define(STRING, `')
 m4_define(COUNT, `')
 m4_define(SAME, `')
 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_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_m4wrap(`
index 89215d1ce00370f7dd0f36303b184d91ef968fc9..dc47eb7d3695f76e0cf18b598b03773a89f53d86 100644 (file)
@@ -1117,6 +1117,11 @@ int i;
        return 0;
 }
 
+function callmeagain(int a; int b; int c)
+{
+       return a + b + c;
+}
+
 function fifteen()
 {
        return 15;
@@ -1133,6 +1138,7 @@ function t_call_function()
        bt_assert(callme(3, 2) = 6);
        bt_assert(callme(4, 4) = 16);
        bt_assert(callme(7, 2) = 14);
+       bt_assert(callmeagain(1, 2, 3) = 6);
 }
 
 bt_test_suite(t_call_function, "Testing calling functions");