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 {
16 		OT_IGNORE,	/* Ignore this output */
17 		OT_INCLUDES,	/* #include files */
18 		OT_DEPS,	/* Dependencies (other than #includes) */
19 		OT_FWD_DECLS,	/* Forward declarations */
20 		OT_TYPE_DECLS,	/* Type declarations */
21 		OT_FUNC_DECLS,	/* Function declarations */
22 		OT_POST_INCLUDE,/* #include after type definition */
23 		OT_CTABLES,	/* Constraint tables */
24 		OT_CODE,	/* Some code */
25 		OT_CTDEFS,	/* Constraint definitions */
26 		OT_STAT_DEFS,	/* Static definitions */
27 		OT_MAX
28 	} target;
29 
30 	struct compiler_stream_destination_s {
31 		TQ_HEAD(out_chunk_t) chunks;
32 		int indent_level;
33 		int indented;
34 	} destination[OT_MAX];
35 } compiler_streams_t;
36 
37 static char *_compiler_stream2str[] __attribute__ ((unused))
38     = { "IGNORE", "INCLUDES", "DEPS", "FWD-DECLS", "TYPE-DECLS", "FUNC-DECLS", "POST-INCLUDE", "CTABLES", "CODE", "CTDEFS", "STAT-DEFS" };
39 
40 int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
41 
42 
43 /*****************************************************************
44  * Useful macros for invoking asn1c_compiled_output() and friends.
45  */
46 
47 /* Redirect output to a different stream. */
48 #define	REDIR(foo)	do { arg->target->target = foo; } while(0)
49 #define INDENT_LEVEL	\
50 		arg->target->destination[arg->target->target].indent_level
51 #define	INDENT(val)	INDENT_LEVEL += (val)
52 #define	INDENTED(code)	do {					\
53 		INDENT(+1);					\
54 		do { code; } while(0);				\
55 		INDENT(-1);					\
56 	} while(0)
57 
58 #define	EMBED(ev)	do {					\
59 		int saved_target = arg->target->target;		\
60 		REDIR(OT_TYPE_DECLS);				\
61 		arg->embed++;					\
62 		INDENTED(arg_t _tmp = *arg;			\
63 			_tmp.expr = ev;				\
64 			_tmp.default_cb(&_tmp);			\
65 		);						\
66 		arg->embed--;					\
67 		if(ev->expr_type != A1TC_EXTENSIBLE)		\
68 			OUT(";\n");				\
69 		assert(arg->target->target == OT_TYPE_DECLS);	\
70 		REDIR(saved_target);				\
71 	} while(0)
72 
73 /* Output a piece of text into a default stream */
74 #define	OUT(fmt, args...)	asn1c_compiled_output(arg, fmt, ##args)
75 #define	OUT_NOINDENT(fmt, args...)	do {			\
76 	int _saved_indent = INDENT_LEVEL;			\
77 	INDENT_LEVEL = 0;					\
78 	OUT(fmt, ##args);					\
79 	INDENT_LEVEL = _saved_indent;				\
80 } while(0)
81 #define	OUT_DEBUG(fmt, args...) do {				\
82 		if(arg->flags & A1C_DEBUG) OUT(fmt, ##args);	\
83 	} while(0)
84 
85 /* Generate #include line */
86 #define	GEN_INCLUDE_STD(typename)	do {			\
87 	if((arg->flags & A1C_INCLUDES_QUOTED)) {			\
88 		GEN_INCLUDE("\"" typename ".h\"");		\
89 	} else {						\
90 		GEN_INCLUDE("<" typename ".h>");		\
91 	} } while(0)
92 #define	GEN_INCLUDE(filename)	do {				\
93 	int saved_target = arg->target->target;			\
94 	if(!filename) break;					\
95 	REDIR(OT_INCLUDES);					\
96 	OUT_NOINDENT("#include %s\n", filename);		\
97 	REDIR(saved_target);					\
98 } while(0)
99 #define	GEN_POSTINCLUDE(filename)	do {			\
100 	int saved_target = arg->target->target;			\
101 	if(!filename) break;					\
102 	REDIR(OT_POST_INCLUDE);					\
103 	OUT_NOINDENT("#include %s\n", filename);		\
104 	REDIR(saved_target);					\
105 } while(0)
106 
107 /* Generate ASN.1 type declaration */
108 #define	GEN_DECLARE(expr)	do {				\
109 	int saved_target = arg->target->target;			\
110 	REDIR(OT_FUNC_DECLS);					\
111 	OUT_NOINDENT("extern asn_TYPE_descriptor_t "		\
112 			"asn_DEF_%s;\n", MKID(expr));		\
113 	REDIR(saved_target);					\
114 } while(0)
115 
116 /*
117  * Format LONG_MIN according to C90 rules.
118  */
119 #define OINT(iv)	do {					\
120 	if(iv == (-2147483647L - 1))				\
121 		OUT("(-2147483647L - 1)");			\
122 	else							\
123 		OUT("%" PRIdASN, iv);				\
124 } while(0)
125 
126 #define OINTS(iv)	do {					\
127 	if(iv == (-2147483647L - 1))				\
128 		OUT("(-2147483647L - 1)");			\
129 	else							\
130 		OUT("% " PRIdASN, iv);				\
131 } while(0)
132 
133 #endif	/* _ASN1_COMPILED_OUTPUT_H_ */
134