blob: 3954916dafb23a1faa84396f8957dc366d85e140 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
2
3/*
4 * Add an elementary chunk of target language text
5 * into appropriate output stream.
6 */
7int
8asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
9 const char *p;
10 int lf_found;
11 va_list ap;
12 out_chunk_t *m;
13 char *buf;
14 int ret;
15
Lev Walkin64399722004-08-11 07:17:22 +000016 switch(arg->target->target) {
17 case OT_IGNORE:
18 return 0;
19 case OT_ASSERT:
20 assert(arg->target->target != OT_ASSERT);
21 return -1;
22 default:
23 break;
24 }
25
Lev Walkinf15320b2004-06-03 03:38:44 +000026 /*
27 * Make sure the output has a single LF and only at the end.
28 */
29 for(lf_found = 0, p = fmt; *p; p++) {
30 if(*p == '\n') {
31 lf_found++;
32 assert(p[1] == '\0');
33 }
34 }
35 assert(lf_found <= 1);
36
37 /*
38 * Print out the indentation.
39 */
40 if(arg->indented == 0) {
41 int i = arg->indent_level;
42 arg->indented = 1;
43 while(i--) {
44 ret = asn1c_compiled_output(arg, "\t");
45 if(ret == -1) return -1;
46 }
47 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +000048 if(lf_found)
49 arg->indented = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000050
51 /*
52 * Estimate necessary size.
53 */
54 buf = "";
55 va_start(ap, fmt);
56 ret = vsnprintf(buf, 0, fmt, ap);
57 va_end(ap);
58 assert(ret >= 0);
59
60 /*
61 * Allocate buffer.
62 */
63 m = calloc(1, sizeof(out_chunk_t));
64 if(m == NULL) return -1;
65 m->len = ret + 1;
66 m->buf = malloc(ret + 1);
67 if(m->buf == NULL) {
68 free(m);
69 return -1;
70 }
71
72 /*
73 * Fill the buffer.
74 */
75 va_start(ap, fmt);
76 ret = vsnprintf(m->buf, m->len, fmt, ap);
77 assert(ret < m->len);
78 m->len = ret;
79 va_end(ap);
80
Lev Walkin3dcaafa2004-08-11 05:21:32 +000081 if(arg->target->target == OT_INCLUDES) {
82 out_chunk_t *v;
83 TQ_FOR(v, &(arg->target->targets[OT_INCLUDES]), next) {
84 if(m->len == v->len
85 && !memcmp(m->buf, v->buf, m->len))
86 break;
87 }
88 if(v) {
89 /* Entry is already present. Skip it. */
90 free(m->buf);
91 free(m);
92 return 0;
93 }
94 }
Lev Walkinf15320b2004-06-03 03:38:44 +000095
Lev Walkin3dcaafa2004-08-11 05:21:32 +000096 TQ_ADD(&(arg->target->targets[arg->target->target]), m, next);
Lev Walkinf15320b2004-06-03 03:38:44 +000097
98 return 0;
99}