Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 1 | #ifndef _ASN1_COMPILED_OUTPUT_H_ |
| 2 | #define _ASN1_COMPILED_OUTPUT_H_ |
| 3 | |
| 4 | /* |
| 5 | * An elementary chunk of target language text. |
| 6 | */ |
| 7 | typedef struct out_chunk { |
| 8 | char *buf; |
| 9 | int len; |
| 10 | |
| 11 | TQ_ENTRY(struct out_chunk) next; |
| 12 | } out_chunk_t; |
| 13 | |
| 14 | typedef struct compiler_streams { |
| 15 | enum { |
Lev Walkin | 6439972 | 2004-08-11 07:17:22 +0000 | [diff] [blame] | 16 | OT_IGNORE = -1, |
| 17 | OT_ASSERT = 0, |
Lev Walkin | 3dcaafa | 2004-08-11 05:21:32 +0000 | [diff] [blame] | 18 | OT_INCLUDES, /* #include files */ |
| 19 | OT_DEPS, /* Dependencies (other than #includes) */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 20 | OT_TYPE_DECLS, /* Type declarations */ |
| 21 | OT_FUNC_DECLS, /* Function declarations */ |
| 22 | OT_STAT_DEFS, /* Static definitions */ |
| 23 | OT_CODE, /* Some code */ |
| 24 | OT_MAX |
| 25 | } target; |
| 26 | TQ_HEAD(out_chunk_t) targets[OT_MAX]; |
| 27 | } compiler_streams_t; |
| 28 | |
| 29 | static char *_compiler_stream2str[] __attribute__ ((unused)) |
Lev Walkin | 6439972 | 2004-08-11 07:17:22 +0000 | [diff] [blame] | 30 | = { "ASSERT", "INCLUDES", "DEPS", "TYPE-DECLS", "FUNC-DECLS", "STAT-DEFS", "CODE" }; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 31 | |
| 32 | int asn1c_compiled_output(arg_t *arg, const char *fmt, ...); |
| 33 | |
Lev Walkin | 3dcaafa | 2004-08-11 05:21:32 +0000 | [diff] [blame] | 34 | |
| 35 | /***************************************************************** |
| 36 | * Useful macros for invoking asn1c_compiled_output() and friends. |
| 37 | */ |
| 38 | |
| 39 | /* Redirect output to a different stream. */ |
| 40 | #define REDIR(foo) do { arg->target->target = foo; } while(0) |
| 41 | |
| 42 | #define INDENT(val) arg->indent_level += (val) |
| 43 | #define INDENTED(code) do { \ |
| 44 | INDENT(+1); \ |
| 45 | do { code; } while(0); \ |
| 46 | INDENT(-1); \ |
| 47 | } while(0) |
| 48 | |
| 49 | #define FLAT(code) do { \ |
| 50 | int _il = arg->indent_level; \ |
| 51 | arg->indent_level = 0; \ |
| 52 | do { code; } while(0); \ |
| 53 | arg->indent_level = _il; \ |
| 54 | } while(0) |
| 55 | |
| 56 | #define EMBED(ev) do { \ |
| 57 | int saved_target = arg->target->target; \ |
| 58 | REDIR(OT_TYPE_DECLS); \ |
| 59 | arg->embed++; \ |
| 60 | INDENTED(arg_t _tmp = *arg; \ |
| 61 | _tmp.expr = ev; \ |
| 62 | _tmp.default_cb(&_tmp); \ |
| 63 | ); \ |
| 64 | arg->embed--; \ |
| 65 | assert(arg->target->target == OT_TYPE_DECLS); \ |
| 66 | REDIR(saved_target); \ |
| 67 | } while(0) |
| 68 | |
| 69 | /* Output a piece of text into a default stream */ |
| 70 | #define OUT(fmt, args...) asn1c_compiled_output(arg, fmt, ##args) |
| 71 | #define OUT_NOINDENT(fmt, args...) do { \ |
| 72 | int _saved_indent = arg->indent_level; \ |
| 73 | arg->indent_level = 0; \ |
| 74 | OUT(fmt, ##args); \ |
| 75 | arg->indent_level = _saved_indent; \ |
| 76 | } while(0) |
| 77 | |
| 78 | /* Generate #include line */ |
| 79 | #define GEN_INCLUDE(filename) do { \ |
| 80 | int saved_target = arg->target->target; \ |
| 81 | REDIR(OT_INCLUDES); \ |
| 82 | OUT_NOINDENT("#include <%s.h>\n", filename); \ |
| 83 | REDIR(saved_target); \ |
| 84 | } while(0) |
| 85 | |
| 86 | /* Generate ASN.1 type declaration */ |
| 87 | #define GEN_DECLARE(expr) do { \ |
| 88 | int saved_target = arg->target->target; \ |
| 89 | REDIR(OT_DEPS); \ |
| 90 | OUT_NOINDENT("extern asn1_TYPE_descriptor_t " \ |
| 91 | "asn1_DEF_%s;\n", \ |
| 92 | MKID(expr->Identifier)); \ |
| 93 | REDIR(saved_target); \ |
| 94 | } while(0) |
| 95 | |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 96 | #endif /* _ASN1_COMPILED_OUTPUT_H_ */ |