blob: b381e213f895c48855e489665b2a28fdd9f38fa6 [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
Lev Walkin840fb8e2017-11-19 23:39:59 -08009asn1c_compiled_output(arg_t *arg, const char *source, int lineno, const char *func, const char *fmt,
10 ...) {
Lev Walkin59004fa2004-08-20 13:37:01 +000011 struct compiler_stream_destination_s *dst;
Lev Walkinf15320b2004-06-03 03:38:44 +000012 const char *p;
13 int lf_found;
14 va_list ap;
15 out_chunk_t *m;
Lev Walkinf15320b2004-06-03 03:38:44 +000016 int ret;
17
Lev Walkin64399722004-08-11 07:17:22 +000018 switch(arg->target->target) {
19 case OT_IGNORE:
20 return 0;
Lev Walkin64399722004-08-11 07:17:22 +000021 default:
Lev Walkin59004fa2004-08-20 13:37:01 +000022 dst = &arg->target->destination[arg->target->target];
Lev Walkin64399722004-08-11 07:17:22 +000023 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 */
Lev Walkin59004fa2004-08-20 13:37:01 +000040 if(dst->indented == 0) {
41 int i = dst->indent_level;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +080042 if (i < 0) {
43 /* fatal error */
44 fprintf(stderr, "target %d : Indent level %d ?!\n", arg->target->target, i);
45 exit(1);
46 }
Lev Walkin59004fa2004-08-20 13:37:01 +000047 dst->indented = 1;
Lev Walkinf15320b2004-06-03 03:38:44 +000048 while(i--) {
Lev Walkin840fb8e2017-11-19 23:39:59 -080049 ret = asn1c_compiled_output(arg, source, lineno, func, "\t");
Lev Walkinf15320b2004-06-03 03:38:44 +000050 if(ret == -1) return -1;
51 }
52 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +000053 if(lf_found)
Lev Walkin59004fa2004-08-20 13:37:01 +000054 dst->indented = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000055
Lev Walkin840fb8e2017-11-19 23:39:59 -080056 size_t debug_reserve_size = 0;
57 if(lf_found && (arg->flags & A1C_DEBUG_OUTPUT_ORIGIN_LINES)) {
58 debug_reserve_size =
59 sizeof("\t// :100000 ()") + strlen(source) + strlen(func);
60 }
61
Lev Walkinf15320b2004-06-03 03:38:44 +000062 /*
Lev Walkinf15320b2004-06-03 03:38:44 +000063 * Allocate buffer.
64 */
65 m = calloc(1, sizeof(out_chunk_t));
66 if(m == NULL) return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000067
Lev Walkina460ba32004-10-20 15:40:04 +000068 m->len = 16;
69 do {
70 void *tmp;
71 m->len <<= 2;
Lev Walkin840fb8e2017-11-19 23:39:59 -080072 tmp = realloc(m->buf, m->len + debug_reserve_size);
Lev Walkina460ba32004-10-20 15:40:04 +000073 if(tmp) {
74 m->buf = (char *)tmp;
75 } else {
76 free(m->buf);
77 free(m);
78 return -1;
79 }
80 va_start(ap, fmt);
81 ret = vsnprintf(m->buf, m->len, fmt, ap);
82 va_end(ap);
83 } while(ret >= (m->len - 1) || ret < 0);
84
Lev Walkinf15320b2004-06-03 03:38:44 +000085 m->len = ret;
Lev Walkinf15320b2004-06-03 03:38:44 +000086
Lev Walkin840fb8e2017-11-19 23:39:59 -080087 /* Print out the origin of the lines */
88 if(lf_found && (arg->flags & A1C_DEBUG_OUTPUT_ORIGIN_LINES)) {
89 assert(m->buf[m->len - 1] == '\n');
90 ret = snprintf(m->buf + m->len - 1, debug_reserve_size,
91 "\t// %s:%03d %s()\n", source, lineno, func);
92 assert(ret > 0 && (size_t)ret < debug_reserve_size);
93 m->len = m->len - 1 + ret;
94 }
95
Lev Walkinc8285712005-03-04 22:18:20 +000096 if(arg->target->target == OT_INCLUDES
97 || arg->target->target == OT_FWD_DECLS
98 || arg->target->target == OT_POST_INCLUDE) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +000099 out_chunk_t *v;
Lev Walkin59004fa2004-08-20 13:37:01 +0000100 TQ_FOR(v, &dst->chunks, next) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000101 if(m->len == v->len
102 && !memcmp(m->buf, v->buf, m->len))
103 break;
104 }
105 if(v) {
106 /* Entry is already present. Skip it. */
107 free(m->buf);
108 free(m);
109 return 0;
110 }
111 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000112
Lev Walkin59004fa2004-08-20 13:37:01 +0000113 TQ_ADD(&dst->chunks, m, next);
Lev Walkinf15320b2004-06-03 03:38:44 +0000114
115 return 0;
116}