X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=libasn1compiler%2Fasn1c_out.c;fp=libasn1compiler%2Fasn1c_out.c;h=b381e213f895c48855e489665b2a28fdd9f38fa6;hb=70ee6fc793ec8e828067a3569849b6c216054497;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=com%2Fasn1c.git diff --git a/libasn1compiler/asn1c_out.c b/libasn1compiler/asn1c_out.c new file mode 100644 index 0000000..b381e21 --- /dev/null +++ b/libasn1compiler/asn1c_out.c @@ -0,0 +1,116 @@ +#include "asn1c_internal.h" +#include "asn1c_out.h" + +/* + * Add an elementary chunk of target language text + * into appropriate output stream. + */ +int +asn1c_compiled_output(arg_t *arg, const char *source, int lineno, const char *func, const char *fmt, + ...) { + struct compiler_stream_destination_s *dst; + const char *p; + int lf_found; + va_list ap; + out_chunk_t *m; + int ret; + + switch(arg->target->target) { + case OT_IGNORE: + return 0; + default: + dst = &arg->target->destination[arg->target->target]; + break; + } + + /* + * Make sure the output has a single LF and only at the end. + */ + for(lf_found = 0, p = fmt; *p; p++) { + if(*p == '\n') { + lf_found++; + assert(p[1] == '\0'); + } + } + assert(lf_found <= 1); + + /* + * Print out the indentation. + */ + if(dst->indented == 0) { + int i = dst->indent_level; + if (i < 0) { + /* fatal error */ + fprintf(stderr, "target %d : Indent level %d ?!\n", arg->target->target, i); + exit(1); + } + dst->indented = 1; + while(i--) { + ret = asn1c_compiled_output(arg, source, lineno, func, "\t"); + if(ret == -1) return -1; + } + } + if(lf_found) + dst->indented = 0; + + size_t debug_reserve_size = 0; + if(lf_found && (arg->flags & A1C_DEBUG_OUTPUT_ORIGIN_LINES)) { + debug_reserve_size = + sizeof("\t// :100000 ()") + strlen(source) + strlen(func); + } + + /* + * Allocate buffer. + */ + m = calloc(1, sizeof(out_chunk_t)); + if(m == NULL) return -1; + + m->len = 16; + do { + void *tmp; + m->len <<= 2; + tmp = realloc(m->buf, m->len + debug_reserve_size); + if(tmp) { + m->buf = (char *)tmp; + } else { + free(m->buf); + free(m); + return -1; + } + va_start(ap, fmt); + ret = vsnprintf(m->buf, m->len, fmt, ap); + va_end(ap); + } while(ret >= (m->len - 1) || ret < 0); + + m->len = ret; + + /* Print out the origin of the lines */ + if(lf_found && (arg->flags & A1C_DEBUG_OUTPUT_ORIGIN_LINES)) { + assert(m->buf[m->len - 1] == '\n'); + ret = snprintf(m->buf + m->len - 1, debug_reserve_size, + "\t// %s:%03d %s()\n", source, lineno, func); + assert(ret > 0 && (size_t)ret < debug_reserve_size); + m->len = m->len - 1 + ret; + } + + if(arg->target->target == OT_INCLUDES + || arg->target->target == OT_FWD_DECLS + || arg->target->target == OT_POST_INCLUDE) { + out_chunk_t *v; + TQ_FOR(v, &dst->chunks, next) { + if(m->len == v->len + && !memcmp(m->buf, v->buf, m->len)) + break; + } + if(v) { + /* Entry is already present. Skip it. */ + free(m->buf); + free(m); + return 0; + } + } + + TQ_ADD(&dst->chunks, m, next); + + return 0; +}