]> git.ipfire.org Git - thirdparty/bird.git/blame - filter/decl.m4
Filter: Moved f_inst allocation to separate function
[thirdparty/bird.git] / filter / decl.m4
CommitLineData
4f082dfa
MM
1m4_divert(-1)m4_dnl
2#
3# BIRD -- Construction of per-instruction structures
4#
5# (c) 2018 Maria Matejka <mq@jmq.cz>
6#
7# Can be freely distributed and used under the terms of the GNU GPL.
8#
9#
10# Global Diversions:
11# 4 enum fi_code
b256f241 12# 5 enum fi_code to string
de12cd18
MM
13# 6 dump line item
14# 7 dump line item callers
23e3b1e6 15# 8 linearize
132529ce 16# 9 same (filter comparator)
ea4f55e3 17# 1 union in struct f_inst
236828d0 18# 3 constructors + interpreter
4f082dfa
MM
19#
20# Per-inst Diversions:
ea4f55e3 21# 101 content of per-inst struct
04160812
MM
22# 102 constructor arguments
23# 103 constructor body
de12cd18 24# 104 dump line item content
23e3b1e6 25# 105 linearize body
132529ce 26# 106 comparator body
d1039926
MM
27# 107 struct f_line_item content
28# 108 interpreter body
04160812 29#
64bb1346
MM
30# Final diversions
31# 200+ completed text before it is flushed to output
4f082dfa 32
87bd7cd7
MM
33m4_dnl m4_debugmode(aceflqtx)
34
4f082dfa 35m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */')
ea4f55e3
MM
36m4_define(FID_INST, `FID_ZONE(1, Instruction structure for config)')
37m4_define(FID_LINE, `FID_ZONE(2, Instruction structure for interpreter)')
4f082dfa
MM
38m4_define(FID_NEW, `FID_ZONE(3, Constructor)')
39m4_define(FID_ENUM, `FID_ZONE(4, Code enum)')
b256f241 40m4_define(FID_ENUM_STR, `FID_ZONE(5, Code enum to string)')
de12cd18
MM
41m4_define(FID_DUMP, `FID_ZONE(6, Dump line)')
42m4_define(FID_DUMP_CALLER, `FID_ZONE(7, Dump line caller)')
23e3b1e6 43m4_define(FID_LINEARIZE, `FID_ZONE(8, Linearize)')
132529ce 44m4_define(FID_SAME, `FID_ZONE(9, Comparison)')
4f082dfa
MM
45
46m4_define(FID_STRUCT_IN, `m4_divert(101)')
47m4_define(FID_NEW_ARGS, `m4_divert(102)')
48m4_define(FID_NEW_BODY, `m4_divert(103)')
dd4d4095 49m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
23e3b1e6 50m4_define(FID_LINEARIZE_BODY, `m4_divert(105)m4_define([[FID_LINEARIZE_BODY_EXISTS]])')
132529ce 51m4_define(FID_SAME_BODY, `m4_divert(106)')
ea4f55e3 52m4_define(FID_LINE_IN, `m4_divert(107)')
d1039926 53m4_define(FID_INTERPRET_BODY, `m4_divert(108)')
4f082dfa 54
d1039926 55m4_define(FID_ALL, `FID_INTERPRET_BODY');
64bb1346 56m4_define(FID_HIC, `m4_ifelse(TARGET, [[H]], $1, TARGET, [[I]], $2, TARGET, [[C]], $3)')
87bd7cd7 57
4f082dfa
MM
58m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[
59FID_ENUM
60INST_NAME(),
b256f241
MM
61FID_ENUM_STR
62[INST_NAME()] = "INST_NAME()",
ea4f55e3
MM
63FID_INST
64struct {
4f082dfa 65m4_undivert(101)
ea4f55e3
MM
66} i_[[]]INST_NAME();
67FID_LINE
68struct {
69m4_undivert(107)
70} i_[[]]INST_NAME();
4f082dfa 71FID_NEW
64bb1346 72FID_HIC(
64bb1346 73[[
236828d0
MM
74struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
75[[m4_undivert(102)]]
76);]],
77[[
78 case INST_NAME():
79 #define whati (&(what->i_]]INST_NAME()[[))
80 m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow"); fstk->vcnt -= INST_INVAL(); ]])
81 [[m4_undivert(108)]]
82 #undef whati
83 break;
84]],
85[[
86struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
87[[m4_undivert(102)]]
88)
64bb1346 89 {
4212c0e7 90 struct f_inst *what = fi_new(fi_code);
63f49457 91 #define whati (&(what->i_]]INST_NAME()[[))
64bb1346 92 [[m4_undivert(103)]]
63f49457
MM
93 #undef whati
94 return what;
64bb1346
MM
95 }
96]])
de12cd18
MM
97
98FID_DUMP_CALLER
99case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break;
100
101FID_DUMP
102m4_ifdef([[FID_DUMP_BODY_EXISTS]],
ea4f55e3 103[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item_, const int indent)]],
de12cd18
MM
104[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]])
105m4_undefine([[FID_DUMP_BODY_EXISTS]])
106{
ea4f55e3 107#define item (&(item_->i_]]INST_NAME()[[))
de12cd18 108m4_undivert(104)
ea4f55e3 109#undef item
de12cd18 110}
dd4d4095 111
23e3b1e6 112FID_LINEARIZE
dd4d4095 113case INST_NAME(): {
63f49457 114#define whati (&(what->i_]]INST_NAME()[[))
ea4f55e3 115#define item (&(dest->items[pos].i_]]INST_NAME()[[))
dd4d4095 116 m4_undivert(105)
63f49457 117#undef whati
ea4f55e3 118#undef item
63f49457
MM
119 dest->items[pos].fi_code = what->fi_code;
120 dest->items[pos].lineno = what->lineno;
dd4d4095
MM
121 break;
122}
23e3b1e6 123m4_undefine([[FID_LINEARIZE_BODY_EXISTS]])
dd4d4095 124
132529ce
MM
125FID_SAME
126case INST_NAME():
ea4f55e3
MM
127#define f1 (&(f1_->i_]]INST_NAME()[[))
128#define f2 (&(f2_->i_]]INST_NAME()[[))
132529ce 129m4_undivert(106)
ea4f55e3
MM
130#undef f1
131#undef f2
132529ce
MM
132break;
133
4f082dfa
MM
134]])')
135
d1039926
MM
136m4_define(INST, `m4_dnl
137INST_FLUSH()m4_dnl
138m4_define([[INST_NAME]], [[$1]])m4_dnl
139m4_define([[INST_INVAL]], [[$2]])m4_dnl
140FID_ALL() m4_dnl
141')
4f082dfa 142
dd4d4095
MM
143m4_dnl FID_MEMBER call:
144m4_dnl type
145m4_dnl name in f_inst
146m4_dnl name in f_line_item
132529ce 147m4_dnl comparator for same
dd4d4095
MM
148m4_dnl dump format string
149m4_dnl dump format args
d1039926 150m4_dnl interpreter body
4f082dfa 151m4_define(FID_MEMBER, `m4_dnl
ea4f55e3
MM
152FID_LINE_IN
153$1 $2;
4f082dfa
MM
154FID_STRUCT_IN
155$1 $2;
156FID_NEW_ARGS
157, $1 $2
158FID_NEW_BODY
63f49457 159whati->$2 = $2;
de12cd18 160m4_ifelse($3,,,[[
23e3b1e6 161FID_LINEARIZE_BODY
63f49457 162item->$3 = whati->$2;
dd4d4095
MM
163]])
164m4_ifelse($4,,,[[
132529ce
MM
165FID_SAME_BODY
166if ($4) return 0;
167]])
168m4_ifelse($5,,,[[
de12cd18 169FID_DUMP_BODY
132529ce 170debug("%s$5\n", INDENT, $6);
de12cd18 171]])
d1039926
MM
172m4_ifelse($7,,,[[
173FID_INTERPRET_BODY
174$7
175]])
176FID_ALL')
4f082dfa 177
d1039926 178m4_define(ARG_ANY, `
ea4f55e3 179FID_STRUCT_IN
63f49457 180struct f_inst * f$1;
ea4f55e3 181FID_NEW_ARGS
63f49457 182, struct f_inst * f$1
4f082dfa 183FID_NEW_BODY
63f49457
MM
184whati->f$1 = f$1;
185for (const struct f_inst *child = f$1; child; child = child->next) what->size += child->size;
23e3b1e6 186FID_LINEARIZE_BODY
63f49457 187pos = linearize(dest, whati->f$1, pos);m4_dnl
d1039926
MM
188FID_ALL()')
189
190m4_define(ARG, `ARG_ANY($1)
191FID_INTERPRET_BODY
192if (v$1.type != $2) runtime("Argument $1 of instruction %s must be of type $2, got 0x%02x", f_instruction_name(what->fi_code), v$1.type)m4_dnl
193FID_ALL()')
194
195m4_define(LINEX, `FID_INTERPRET_BODY
196do {
1757a6fc
MM
197 fstk->estk[fstk->ecnt].pos = 0;
198 fstk->estk[fstk->ecnt].line = $1;
199 fstk->estk[fstk->ecnt].ventry = fstk->vcnt;
200 fstk->estk[fstk->ecnt].vbase = fstk->estk[fstk->ecnt-1].vbase;
201 fstk->estk[fstk->ecnt].emask = 0;
202 fstk->ecnt++;
d1039926
MM
203} while (0)m4_dnl
204FID_ALL()')
205
ea4f55e3
MM
206m4_define(LINE, `
207FID_LINE_IN
208const struct f_line * fl$1;
209FID_STRUCT_IN
210const struct f_inst * f$1;
211FID_NEW_ARGS
212, const struct f_inst * f$1
4f082dfa 213FID_NEW_BODY
63f49457 214whati->f$1 = f$1;
de12cd18 215FID_DUMP_BODY
ea4f55e3 216f_dump_line(item->fl$1, indent + 1);
23e3b1e6 217FID_LINEARIZE_BODY
63f49457 218item->fl$1 = f_linearize(whati->f$1);
132529ce 219FID_SAME_BODY
ea4f55e3 220if (!f_same(f1->fl$1, f2->fl$1)) return 0;
d1039926
MM
221FID_INTERPRET_BODY
222do { if (whati->fl$1) {
223 LINEX(whati->fl$1);
224} } while(0)m4_dnl
225FID_ALL()')
226
a84b8b6e 227m4_define(RESULT, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])')
f74d1976
MM
228m4_define(RESULT_VAL, `FID_INTERPRET_BODY()do { res = $1; fstk->vcnt++; } while (0)FID_ALL()')
229m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])')
d1039926 230
132529ce 231m4_define(SYMBOL, `FID_MEMBER(const struct symbol *, sym, sym,
d1039926
MM
232[[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name, const struct symbol *sym = whati->sym)')
233m4_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),)')
234m4_define(FRET, `FID_MEMBER(enum filter_return, fret, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret), enum filter_return fret = whati->fret)')
235m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs), enum ec_subtype ecs = whati->ecs)')
236m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], route table %s, item->rtc->name, struct rtable *table = whati->rtc->table)')
237m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa, sa, f1->sa.sa_code != f2->sa.sa_code,,, struct f_static_attr sa = whati->sa)')
238m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da, da, f1->da.ea_code != f2->da.ea_code,,, struct f_dynamic_attr da = whati->da)')
132529ce 239m4_define(COUNT, `FID_MEMBER(uint, count, count, f1->count != f2->count, number %u, item->count)')
d1039926 240m4_define(TREE, `FID_MEMBER(const struct f_tree *, tree, tree, [[!same_tree(f1->tree, f2->tree)]], tree %p, item->tree, const struct f_tree *tree = whati->tree)')
132529ce 241m4_define(STRING, `FID_MEMBER(const char *, s, s, [[strcmp(f1->s, f2->s)]], string \"%s\", item->s)')
de12cd18
MM
242
243m4_define(FID_WR_PUT_LIST)
64bb1346 244m4_define(FID_WR_PUT_ALSO, `m4_define([[FID_WR_PUT_LIST]],FID_WR_PUT_LIST()[[FID_WR_DPUT(]]FID_WR_DIDX[[)FID_WR_DPUT(]]$1[[)]])m4_define([[FID_WR_DIDX]],m4_eval(FID_WR_DIDX+1))m4_divert(FID_WR_DIDX)')
de12cd18 245
64bb1346
MM
246m4_define(FID_WR_DIRECT, `m4_ifelse(TARGET,[[$1]],[[FID_WR_INIT()]],[[FID_WR_STOP()]])')
247m4_define(FID_WR_INIT, `m4_define([[FID_WR_DIDX]],200)m4_define([[FID_WR_PUT]],[[FID_WR_PUT_ALSO($]][[@)]])m4_divert(200)')
248m4_define(FID_WR_STOP, `m4_define([[FID_WR_PUT]])m4_divert(-1)')
4f082dfa 249
04160812 250m4_changequote([[,]])
64bb1346 251FID_WR_DIRECT(I)
236828d0 252FID_WR_PUT(3)
64bb1346 253FID_WR_DIRECT(C)
87bd7cd7
MM
254#include "nest/bird.h"
255#include "filter/filter.h"
256#include "filter/f-inst.h"
b256f241 257
b256f241
MM
258/* Instruction codes to string */
259static const char * const f_instruction_name_str[] = {
260FID_WR_PUT(5)
261};
262
263const char *
264f_instruction_name(enum f_instruction_code fi)
265{
266 if (fi < (sizeof(f_instruction_name_str) / sizeof(f_instruction_name_str[0])))
267 return f_instruction_name_str[fi];
268 else
269 bug("Got unknown instruction code: %d", fi);
270}
271
4212c0e7
MM
272static inline struct f_inst *
273fi_new(enum f_instruction_code fi_code)
274{
275 struct f_inst *what = cfg_allocz(sizeof(struct f_inst));
276 what->lineno = ifs->lino;
277 what->size = 1;
278 what->fi_code = fi_code;
279 return what;
280}
281
de12cd18
MM
282/* Instruction constructors */
283FID_WR_PUT(3)
284
285/* Line dumpers */
286#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
287static const char f_dump_line_indent_str[] = " ";
de12cd18
MM
288
289FID_WR_PUT(6)
290
ea4f55e3 291void f_dump_line(const struct f_line *dest, uint indent)
de12cd18
MM
292{
293 if (!dest) {
294 debug("%sNo filter line (NULL)\n", INDENT);
295 return;
296 }
297 debug("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len);
298 for (uint i=0; i<dest->len; i++) {
299 const struct f_line_item *item = &dest->items[i];
300 debug("%sInstruction %s at line %u\n", INDENT, f_instruction_name(item->fi_code), item->lineno);
301 switch (item->fi_code) {
302FID_WR_PUT(7)
303 default: bug("Unknown instruction %x in f_dump_line", item->fi_code);
304 }
305 }
306 debug("%sFilter line %p dump done\n", INDENT, dest);
307}
308
23e3b1e6 309/* Linearize */
dd4d4095 310static uint
63f49457 311linearize(struct f_line *dest, const struct f_inst *what, uint pos)
dd4d4095 312{
63f49457
MM
313 for ( ; what; what = what->next) {
314 switch (what->fi_code) {
dd4d4095
MM
315FID_WR_PUT(8)
316 }
317 pos++;
318 }
319 return pos;
320}
321
322struct f_line *
23e3b1e6 323f_linearize_concat(const struct f_inst * const inst[], uint count)
dd4d4095
MM
324{
325 uint len = 0;
326 for (uint i=0; i<count; i++)
327 for (const struct f_inst *what = inst[i]; what; what = what->next)
328 len += what->size;
329
330 struct f_line *out = cfg_allocz(sizeof(struct f_line) + sizeof(struct f_line_item)*len);
331
332 for (uint i=0; i<count; i++)
23e3b1e6 333 out->len = linearize(out, inst[i], out->len);
dd4d4095
MM
334
335#if DEBUGGING
336 f_dump_line(out, 0);
337#endif
338 return out;
339}
340
132529ce
MM
341/* Filter line comparison */
342int
343f_same(const struct f_line *fl1, const struct f_line *fl2)
344{
345 if ((!fl1) && (!fl2))
346 return 1;
347 if ((!fl1) || (!fl2))
348 return 0;
349 if (fl1->len != fl2->len)
350 return 0;
351 for (uint i=0; i<fl1->len; i++) {
ea4f55e3
MM
352#define f1_ (&(fl1->items[i]))
353#define f2_ (&(fl2->items[i]))
354 if (f1_->fi_code != f2_->fi_code)
132529ce 355 return 0;
ea4f55e3 356 if (f1_->flags != f2_->flags)
132529ce
MM
357 return 0;
358
ea4f55e3 359 switch(f1_->fi_code) {
132529ce
MM
360FID_WR_PUT(9)
361 }
362 }
ea4f55e3
MM
363#undef f1_
364#undef f2_
132529ce
MM
365 return 1;
366}
367
368
64bb1346 369FID_WR_DIRECT(H)
de12cd18
MM
370/* Filter instruction codes */
371enum f_instruction_code {
372FID_WR_PUT(4)
ea4f55e3 373} PACKED;
4f082dfa 374
ea4f55e3 375/* Filter instruction structure for config */
4f082dfa 376struct f_inst {
96d757c1 377 struct f_inst *next; /* Next instruction */
4f082dfa
MM
378 enum f_instruction_code fi_code; /* Instruction code */
379 int size; /* How many instructions are underneath */
380 int lineno; /* Line number */
ea4f55e3
MM
381 union {
382 FID_WR_PUT(1)
383 };
384};
385
386/* Filter line item */
387struct f_line_item {
388 enum f_instruction_code fi_code; /* What to do */
389 enum f_instruction_flags flags; /* Flags, instruction-specific */
390 uint lineno; /* Where */
4f082dfa 391 union {
04160812 392 FID_WR_PUT(2)
4f082dfa
MM
393 };
394};
395
396/* Instruction constructors */
04160812 397FID_WR_PUT(3)
de12cd18 398
04160812
MM
399m4_divert(-1)
400m4_changequote(`,')
401
64bb1346
MM
402m4_define(FID_CLEANUP, `m4_ifelse($1,$2,,[[m4_undivert($1)FID_CLEANUP(m4_eval($1+1),$2)]])')
403m4_define(FID_WR_DPUT, `m4_undivert($1)')
404
405m4_m4wrap(`INST_FLUSH()m4_divert(0)FID_WR_PUT_LIST()m4_divert(-1)FID_CLEANUP(1,200)')
4f082dfa
MM
406
407m4_changequote([[,]])