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