NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1compiler / asn1c_out.c
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
9 asn1c_compiled_output(arg_t *arg, const char *source, int lineno, const char *func, const char *fmt,
10                       ...) {
11         struct compiler_stream_destination_s *dst;
12         const char *p;
13         int lf_found;
14         va_list ap;
15         out_chunk_t *m;
16         int ret;
17
18         switch(arg->target->target) {
19         case OT_IGNORE:
20                 return 0;
21         default:
22                 dst = &arg->target->destination[arg->target->target];
23                 break;
24         }
25
26         /*
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(dst->indented == 0) {
41                 int i = dst->indent_level;
42                 if (i < 0) {
43                         /* fatal error */
44                         fprintf(stderr, "target %d : Indent level %d ?!\n", arg->target->target, i);
45                         exit(1);
46                 }
47                 dst->indented = 1;
48                 while(i--) {
49                         ret = asn1c_compiled_output(arg, source, lineno, func, "\t");
50                         if(ret == -1) return -1;
51                 }
52         }
53         if(lf_found)
54                 dst->indented = 0;
55
56     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
62         /*
63          * Allocate buffer.
64          */
65         m = calloc(1, sizeof(out_chunk_t));
66         if(m == NULL) return -1;
67
68         m->len = 16;
69         do {
70                 void *tmp;
71                 m->len <<= 2;
72                 tmp = realloc(m->buf, m->len + debug_reserve_size);
73                 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
85         m->len = ret;
86
87     /* 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
96         if(arg->target->target == OT_INCLUDES
97         || arg->target->target == OT_FWD_DECLS
98         || arg->target->target == OT_POST_INCLUDE) {
99                 out_chunk_t *v;
100                 TQ_FOR(v, &dst->chunks, next) {
101                         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         }
112
113         TQ_ADD(&dst->chunks, m, next);
114
115         return 0;
116 }