diff options
Diffstat (limited to 'libasn1compiler/asn1c_out.c')
-rw-r--r-- | libasn1compiler/asn1c_out.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libasn1compiler/asn1c_out.c b/libasn1compiler/asn1c_out.c new file mode 100644 index 00000000..a6432418 --- /dev/null +++ b/libasn1compiler/asn1c_out.c @@ -0,0 +1,75 @@ +#include "asn1c_internal.h" + +/* + * Add an elementary chunk of target language text + * into appropriate output stream. + */ +int +asn1c_compiled_output(arg_t *arg, const char *fmt, ...) { + const char *p; + int lf_found; + va_list ap; + out_chunk_t *m; + char *buf; + int ret; + + /* + * 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(arg->indented == 0) { + int i = arg->indent_level; + arg->indented = 1; + while(i--) { + ret = asn1c_compiled_output(arg, "\t"); + if(ret == -1) return -1; + } + } + + /* + * Estimate necessary size. + */ + buf = ""; + va_start(ap, fmt); + ret = vsnprintf(buf, 0, fmt, ap); + va_end(ap); + assert(ret >= 0); + + /* + * Allocate buffer. + */ + m = calloc(1, sizeof(out_chunk_t)); + if(m == NULL) return -1; + m->len = ret + 1; + m->buf = malloc(ret + 1); + if(m->buf == NULL) { + free(m); + return -1; + } + + /* + * Fill the buffer. + */ + va_start(ap, fmt); + ret = vsnprintf(m->buf, m->len, fmt, ap); + assert(ret < m->len); + m->len = ret; + va_end(ap); + + TQ_ADD(&(arg->target->targets[arg->target->target]), m, next); + + if(lf_found) + arg->indented = 0; + + return 0; +} |