1 #include "asn1c_internal.h"
2 #include "asn1c_out.h"
3
4 /*
5 * Add an elementary chunk of target language text
6 * into appropriate output stream.
7 */
8 int
asn1c_compiled_output(arg_t * arg,const char * fmt,...)9 asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
10 struct compiler_stream_destination_s *dst;
11 const char *p;
12 int lf_found;
13 va_list ap;
14 out_chunk_t *m;
15 int ret;
16
17 switch(arg->target->target) {
18 case OT_IGNORE:
19 return 0;
20 default:
21 dst = &arg->target->destination[arg->target->target];
22 break;
23 }
24
25 /*
26 * Make sure the output has a single LF and only at the end.
27 */
28 for(lf_found = 0, p = fmt; *p; p++) {
29 if(*p == '\n') {
30 lf_found++;
31 assert(p[1] == '\0');
32 }
33 }
34 assert(lf_found <= 1);
35
36 /*
37 * Print out the indentation.
38 */
39 if(dst->indented == 0) {
40 int i = dst->indent_level;
41 dst->indented = 1;
42 while(i--) {
43 ret = asn1c_compiled_output(arg, "\t");
44 if(ret == -1) return -1;
45 }
46 }
47 if(lf_found)
48 dst->indented = 0;
49
50 /*
51 * Allocate buffer.
52 */
53 m = calloc(1, sizeof(out_chunk_t));
54 if(m == NULL) return -1;
55
56 m->len = 16;
57 do {
58 void *tmp;
59 m->len <<= 2;
60 tmp = realloc(m->buf, m->len);
61 if(tmp) {
62 m->buf = (char *)tmp;
63 } else {
64 free(m->buf);
65 free(m);
66 return -1;
67 }
68 va_start(ap, fmt);
69 ret = vsnprintf(m->buf, m->len, fmt, ap);
70 va_end(ap);
71 } while(ret >= (m->len - 1) || ret < 0);
72
73 m->len = ret;
74
75 if(arg->target->target == OT_INCLUDES
76 || arg->target->target == OT_FWD_DECLS
77 || arg->target->target == OT_POST_INCLUDE) {
78 out_chunk_t *v;
79 TQ_FOR(v, &dst->chunks, next) {
80 if(m->len == v->len
81 && !memcmp(m->buf, v->buf, m->len))
82 break;
83 }
84 if(v) {
85 /* Entry is already present. Skip it. */
86 free(m->buf);
87 free(m);
88 return 0;
89 }
90 }
91
92 TQ_ADD(&dst->chunks, m, next);
93
94 return 0;
95 }
96