aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1compiler/asn1c_out.c
diff options
context:
space:
mode:
Diffstat (limited to 'libasn1compiler/asn1c_out.c')
-rw-r--r--libasn1compiler/asn1c_out.c75
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;
+}