#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 *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; dst->indented = 1; while(i--) { ret = asn1c_compiled_output(arg, "\t"); if(ret == -1) return -1; } } if(lf_found) dst->indented = 0; /* * 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); 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; 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; }