blob: fb41871153eda3de2de4a79d87901e0e94e23c92 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00002#include "asn1c_out.h"
Lev Walkinf15320b2004-06-03 03:38:44 +00003
4/*
5 * Add an elementary chunk of target language text
6 * into appropriate output stream.
7 */
8int
9asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
Lev Walkin59004fa2004-08-20 13:37:01 +000010 struct compiler_stream_destination_s *dst;
Lev Walkinf15320b2004-06-03 03:38:44 +000011 const char *p;
12 int lf_found;
13 va_list ap;
14 out_chunk_t *m;
15 char *buf;
16 int ret;
17
Lev Walkin64399722004-08-11 07:17:22 +000018 switch(arg->target->target) {
19 case OT_IGNORE:
20 return 0;
21 case OT_ASSERT:
22 assert(arg->target->target != OT_ASSERT);
23 return -1;
24 default:
Lev Walkin59004fa2004-08-20 13:37:01 +000025 dst = &arg->target->destination[arg->target->target];
Lev Walkin64399722004-08-11 07:17:22 +000026 break;
27 }
28
Lev Walkinf15320b2004-06-03 03:38:44 +000029 /*
30 * Make sure the output has a single LF and only at the end.
31 */
32 for(lf_found = 0, p = fmt; *p; p++) {
33 if(*p == '\n') {
34 lf_found++;
35 assert(p[1] == '\0');
36 }
37 }
38 assert(lf_found <= 1);
39
40 /*
41 * Print out the indentation.
42 */
Lev Walkin59004fa2004-08-20 13:37:01 +000043 if(dst->indented == 0) {
44 int i = dst->indent_level;
45 dst->indented = 1;
Lev Walkinf15320b2004-06-03 03:38:44 +000046 while(i--) {
47 ret = asn1c_compiled_output(arg, "\t");
48 if(ret == -1) return -1;
49 }
50 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +000051 if(lf_found)
Lev Walkin59004fa2004-08-20 13:37:01 +000052 dst->indented = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000053
54 /*
55 * Estimate necessary size.
56 */
57 buf = "";
58 va_start(ap, fmt);
59 ret = vsnprintf(buf, 0, fmt, ap);
60 va_end(ap);
61 assert(ret >= 0);
62
63 /*
64 * Allocate buffer.
65 */
66 m = calloc(1, sizeof(out_chunk_t));
67 if(m == NULL) return -1;
68 m->len = ret + 1;
69 m->buf = malloc(ret + 1);
70 if(m->buf == NULL) {
71 free(m);
72 return -1;
73 }
74
75 /*
76 * Fill the buffer.
77 */
78 va_start(ap, fmt);
79 ret = vsnprintf(m->buf, m->len, fmt, ap);
80 assert(ret < m->len);
81 m->len = ret;
82 va_end(ap);
83
Lev Walkin3dcaafa2004-08-11 05:21:32 +000084 if(arg->target->target == OT_INCLUDES) {
85 out_chunk_t *v;
Lev Walkin59004fa2004-08-20 13:37:01 +000086 TQ_FOR(v, &dst->chunks, next) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +000087 if(m->len == v->len
88 && !memcmp(m->buf, v->buf, m->len))
89 break;
90 }
91 if(v) {
92 /* Entry is already present. Skip it. */
93 free(m->buf);
94 free(m);
95 return 0;
96 }
97 }
Lev Walkinf15320b2004-06-03 03:38:44 +000098
Lev Walkin59004fa2004-08-20 13:37:01 +000099 TQ_ADD(&dst->chunks, m, next);
Lev Walkinf15320b2004-06-03 03:38:44 +0000100
101 return 0;
102}