blob: 8314bb5616823288330bf0c1234137d0c683fe8c [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;
Lev Walkinf15320b2004-06-03 03:38:44 +000015 int ret;
16
Lev Walkin64399722004-08-11 07:17:22 +000017 switch(arg->target->target) {
18 case OT_IGNORE:
19 return 0;
Lev Walkin64399722004-08-11 07:17:22 +000020 default:
Lev Walkin59004fa2004-08-20 13:37:01 +000021 dst = &arg->target->destination[arg->target->target];
Lev Walkin64399722004-08-11 07:17:22 +000022 break;
23 }
24
Lev Walkinf15320b2004-06-03 03:38:44 +000025 /*
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 */
Lev Walkin59004fa2004-08-20 13:37:01 +000039 if(dst->indented == 0) {
40 int i = dst->indent_level;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +080041 if (i < 0) {
42 /* fatal error */
43 fprintf(stderr, "target %d : Indent level %d ?!\n", arg->target->target, i);
44 exit(1);
45 }
Lev Walkin59004fa2004-08-20 13:37:01 +000046 dst->indented = 1;
Lev Walkinf15320b2004-06-03 03:38:44 +000047 while(i--) {
48 ret = asn1c_compiled_output(arg, "\t");
49 if(ret == -1) return -1;
50 }
51 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +000052 if(lf_found)
Lev Walkin59004fa2004-08-20 13:37:01 +000053 dst->indented = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000054
55 /*
Lev Walkinf15320b2004-06-03 03:38:44 +000056 * Allocate buffer.
57 */
58 m = calloc(1, sizeof(out_chunk_t));
59 if(m == NULL) return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000060
Lev Walkina460ba32004-10-20 15:40:04 +000061 m->len = 16;
62 do {
63 void *tmp;
64 m->len <<= 2;
65 tmp = realloc(m->buf, m->len);
66 if(tmp) {
67 m->buf = (char *)tmp;
68 } else {
69 free(m->buf);
70 free(m);
71 return -1;
72 }
73 va_start(ap, fmt);
74 ret = vsnprintf(m->buf, m->len, fmt, ap);
75 va_end(ap);
76 } while(ret >= (m->len - 1) || ret < 0);
77
Lev Walkinf15320b2004-06-03 03:38:44 +000078 m->len = ret;
Lev Walkinf15320b2004-06-03 03:38:44 +000079
Lev Walkinc8285712005-03-04 22:18:20 +000080 if(arg->target->target == OT_INCLUDES
81 || arg->target->target == OT_FWD_DECLS
82 || arg->target->target == OT_POST_INCLUDE) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +000083 out_chunk_t *v;
Lev Walkin59004fa2004-08-20 13:37:01 +000084 TQ_FOR(v, &dst->chunks, next) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +000085 if(m->len == v->len
86 && !memcmp(m->buf, v->buf, m->len))
87 break;
88 }
89 if(v) {
90 /* Entry is already present. Skip it. */
91 free(m->buf);
92 free(m);
93 return 0;
94 }
95 }
Lev Walkinf15320b2004-06-03 03:38:44 +000096
Lev Walkin59004fa2004-08-20 13:37:01 +000097 TQ_ADD(&dst->chunks, m, next);
Lev Walkinf15320b2004-06-03 03:38:44 +000098
99 return 0;
100}