aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2017-08-22 01:44:56 -0700
committerLev Walkin <vlm@lionet.info>2017-08-22 01:44:56 -0700
commitd9221847e58b8facd6f97be5a2128dbbd5f7ed25 (patch)
tree42de5523393df1cf1a95ac4a32a9148c2d01efda
parentdb33c8dbde9edd786ba9dd088ee4b0bf983440b6 (diff)
add common lib
-rw-r--r--Makefile.am11
-rw-r--r--asn1c/Makefile.am26
-rw-r--r--configure.ac1
-rw-r--r--libasn1common/Makefile.am8
-rw-r--r--libasn1common/asn1_buffer.c104
-rw-r--r--libasn1common/asn1_buffer.h32
-rw-r--r--libasn1common/asn1_namespace.c148
-rw-r--r--libasn1common/asn1_namespace.h80
-rw-r--r--libasn1common/asn1_ref.c194
-rw-r--r--libasn1common/asn1_ref.h80
-rw-r--r--libasn1compiler/Makefile.am7
-rw-r--r--libasn1fix/Makefile.am63
-rw-r--r--libasn1parser/Makefile.am32
-rw-r--r--libasn1print/Makefile.am11
14 files changed, 726 insertions, 71 deletions
diff --git a/Makefile.am b/Makefile.am
index 24a132fc..33f30ac5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,11 +4,12 @@ ACLOCAL_AMFLAGS = -I m4
@CODE_COVERAGE_RULES@
CODE_COVERAGE_IGNORE_PATTERN="tests/*" "lex.yy.c" "y.tab.c" "asn1p_l.l" "asn1p_y.y"
-SUBDIRS = \
- libasn1parser libasn1fix \
- libasn1print libasn1compiler \
- skeletons examples \
- doc asn1c tests
+SUBDIRS = \
+ libasn1common libasn1parser \
+ libasn1fix libasn1print \
+ libasn1compiler \
+ skeletons examples doc \
+ asn1c tests
docsdir = $(datadir)/doc/asn1c
diff --git a/asn1c/Makefile.am b/asn1c/Makefile.am
index 4a9a9142..b3a10093 100644
--- a/asn1c/Makefile.am
+++ b/asn1c/Makefile.am
@@ -1,19 +1,21 @@
@CODE_COVERAGE_RULES@
AM_CFLAGS = @ADD_CFLAGS@
-AM_CPPFLAGS = \
- -I${top_srcdir}/libasn1compiler \
- -I${top_srcdir}/libasn1parser \
- -I${top_srcdir}/libasn1print \
- -I${top_srcdir}/libasn1fix \
- -I${top_srcdir}/skeletons \
- -DDATADIR=\"$(pkgdatadir)\"
+AM_CPPFLAGS = \
+ -I${top_srcdir}/libasn1compiler \
+ -I${top_srcdir}/libasn1common \
+ -I${top_srcdir}/libasn1parser \
+ -I${top_srcdir}/libasn1print \
+ -I${top_srcdir}/libasn1fix \
+ -I${top_srcdir}/skeletons \
+ -DDATADIR=\"$(pkgdatadir)\"
-asn1c_LDADD = \
- $(top_builddir)/libasn1parser/libasn1parser.la \
- $(top_builddir)/libasn1print/libasn1print.la \
- $(top_builddir)/libasn1fix/libasn1fix.la \
- $(top_builddir)/libasn1compiler/libasn1compiler.la
+asn1c_LDADD = \
+ $(top_builddir)/libasn1common/libasn1common.la \
+ $(top_builddir)/libasn1parser/libasn1parser.la \
+ $(top_builddir)/libasn1print/libasn1print.la \
+ $(top_builddir)/libasn1fix/libasn1fix.la \
+ $(top_builddir)/libasn1compiler/libasn1compiler.la
bin_PROGRAMS = asn1c unber enber
diff --git a/configure.ac b/configure.ac
index ce2d8902..aa7b9b97 100644
--- a/configure.ac
+++ b/configure.ac
@@ -150,6 +150,7 @@ tests/tests-asn1c-compiler/Makefile \
tests/tests-c-compiler/Makefile \
skeletons/tests/Makefile \
libasn1compiler/Makefile \
+libasn1common/Makefile \
libasn1parser/Makefile \
libasn1print/Makefile \
libasn1fix/Makefile \
diff --git a/libasn1common/Makefile.am b/libasn1common/Makefile.am
new file mode 100644
index 00000000..309ad792
--- /dev/null
+++ b/libasn1common/Makefile.am
@@ -0,0 +1,8 @@
+
+noinst_LTLIBRARIES = libasn1common.la
+
+libasn1common_la_SOURCES = \
+ asn1_ref.c asn1_ref.h \
+ asn1_buffer.c asn1_buffer.h \
+ asn1_namespace.c asn1_namespace.h
+
diff --git a/libasn1common/asn1_buffer.c b/libasn1common/asn1_buffer.c
new file mode 100644
index 00000000..ace3dbb4
--- /dev/null
+++ b/libasn1common/asn1_buffer.c
@@ -0,0 +1,104 @@
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "asn1_buffer.h"
+
+/*
+ * Create and destroy the buffer.
+ */
+abuf *
+abuf_new() {
+ abuf *ab = calloc(1, sizeof(abuf));
+ assert(ab);
+ ab->length = 0;
+ ab->size = 32;
+ ab->buffer = calloc(1, ab->size);
+ assert(ab->buffer);
+ return ab;
+}
+
+void abuf_free(abuf *ab) {
+ if(ab) {
+ union {
+ const char *c_buf;
+ char *nc_buf;
+ } const_cast;
+ const_cast.c_buf = ab->buffer;
+ free(const_cast.nc_buf);
+ free(ab);
+ }
+}
+
+/*
+ * Erase contents of the buffer (without destroying it).
+ */
+void
+abuf_clear(abuf *ab) {
+ union {
+ const char *c_buf;
+ char *nc_buf;
+ } const_cast;
+ if(!ab->buffer) {
+ ab->size = 32;
+ ab->buffer = calloc(1, ab->size);
+ assert(ab->buffer);
+ }
+ const_cast.c_buf = ab->buffer;
+ ab->length = 0;
+ const_cast.nc_buf[0] = '\0';
+}
+
+static void
+abuf_resize_by(abuf *ab, size_t add_bytes) {
+ union {
+ const char *c_buf;
+ char *nc_buf;
+ } const_cast;
+ const_cast.c_buf = ab->buffer;
+
+ assert(ab->buffer[ab->length] == '\0');
+
+ size_t new_size = ab->length + add_bytes;
+ char *p = realloc(const_cast.nc_buf, new_size);
+ assert(p);
+ ab->buffer = p;
+ assert(ab->buffer[ab->length] == '\0');
+ ab->size = new_size;
+}
+
+void abuf_str(abuf *ab, const char *str) {
+ abuf_printf(ab, "%s", str);
+}
+
+void abuf_buf(abuf *ab, const abuf *buf) {
+ abuf_printf(ab, "%s", buf->buffer);
+}
+
+void abuf_printf(abuf *ab, const char *fmt, ...) {
+ va_list ap;
+
+ for(;;) {
+ union {
+ const char *c_buf;
+ char *nc_buf;
+ } const_cast;
+ const_cast.c_buf = ab->buffer;
+ va_start(ap, fmt);
+ int ret = vsnprintf(&const_cast.nc_buf[ab->length],
+ ab->size - ab->length, fmt, ap);
+ va_end(ap);
+ assert(ret >= 0);
+ if((size_t)ret < ab->size - ab->length) {
+ ab->length += ret;
+ assert(ab->buffer[ab->length] == '\0');
+ break;
+ }
+ const_cast.nc_buf[ab->length] = '\0'; /* Restore order */
+ abuf_resize_by(ab, ret + 1);
+ }
+}
+
diff --git a/libasn1common/asn1_buffer.h b/libasn1common/asn1_buffer.h
new file mode 100644
index 00000000..464fc74a
--- /dev/null
+++ b/libasn1common/asn1_buffer.h
@@ -0,0 +1,32 @@
+#ifndef ASN1_BUFFER_H
+#define ASN1_BUFFER_H
+
+/*
+ * Your typical dynamic character string buffer.
+ */
+typedef struct {
+ const char *buffer;
+ size_t length;
+ size_t size;
+} abuf;
+
+/*
+ * Create and destroy the buffer.
+ */
+abuf *abuf_new(void);
+void abuf_free(abuf *);
+
+/*
+ * Erase contents of the buffer (without destroying it).
+ */
+void abuf_clear(abuf *);
+
+/*
+ * Add characters to the buffer.
+ */
+void abuf_str(abuf *, const char *str);
+void abuf_buf(abuf *, const abuf *);
+void abuf_printf(abuf *, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#endif /* ASN1_BUFFER_H */
diff --git a/libasn1common/asn1_namespace.c b/libasn1common/asn1_namespace.c
new file mode 100644
index 00000000..db010729
--- /dev/null
+++ b/libasn1common/asn1_namespace.c
@@ -0,0 +1,148 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "asn1_ref.h"
+#include "asn1_buffer.h"
+#include "asn1_namespace.h"
+
+static void (*_add_standard_namespaces_cb)(asn1_namespace_t *);
+
+void
+asn1_namespace_add_standard_namespaces_callback(
+ void (*cb)(asn1_namespace_t *)) {
+ _add_standard_namespaces_cb = cb;
+}
+
+asn1_namespace_t *
+asn1_namespace_new() {
+ asn1_namespace_t *ns = calloc(1, sizeof(*ns));
+
+ if(_add_standard_namespaces_cb) {
+ _add_standard_namespaces_cb(ns);
+ }
+
+ return ns;
+}
+
+void
+asn1_namespace_free(asn1_namespace_t *ns) {
+ if(ns) {
+ for(size_t i = 0; i < ns->elements_count; i++) {
+ switch(ns->elements[i].selector) {
+ case NAM_SPACE:
+ break;
+ case NAM_SYMBOL:
+ free(ns->elements[i].u.symbol.identifier);
+ break;
+ }
+ }
+ free(ns->elements);
+ free(ns);
+ }
+}
+
+asn1_namespace_t *
+asn1_namespace_clone(const asn1_namespace_t *old_ns) {
+ asn1_namespace_t *new_ns = calloc(1, sizeof(*new_ns));
+
+ for(size_t i = 0; i < old_ns->elements_count; i++) {
+ switch(old_ns->elements[i].selector) {
+ case NAM_SPACE:
+ asn1_namespace_add_module(new_ns,
+ old_ns->elements[i].u.space.module,
+ old_ns->elements[i].u.space.stop_search);
+ break;
+ case NAM_SYMBOL:
+ asn1_namespace_add_symbol(
+ new_ns, old_ns->elements[i].u.symbol.opt_governor,
+ old_ns->elements[i].u.symbol.identifier,
+ old_ns->elements[i].u.symbol.resolution);
+ break;
+ }
+ }
+
+ return new_ns;
+}
+
+static size_t
+_add_element(asn1_namespace_t *ns) {
+ size_t idx = ns->elements_count;
+
+ if(ns->elements_count >= ns->elements_size) {
+ size_t elc = ns->elements_size ? ns->elements_size * 2 : 4;
+ ns->elements = realloc(ns->elements, sizeof(ns->elements[0]) * elc);
+ ns->elements_size = elc;
+ }
+
+ ns->elements_count++;
+ return idx;
+}
+
+void
+asn1_namespace_add_symbol(asn1_namespace_t *ns,
+ struct asn1p_ref_s *opt_governor,
+ const char *identifier,
+ struct asn1p_expr_s *resolved_argument) {
+ size_t idx = _add_element(ns);
+
+ ns->elements[idx].selector = NAM_SYMBOL;
+ ns->elements[idx].u.symbol.opt_governor = opt_governor;
+ ns->elements[idx].u.symbol.identifier = strdup(identifier);
+ ns->elements[idx].u.symbol.resolution = resolved_argument;
+}
+
+asn1_namespace_t *
+asn1_namespace_new_from_module(struct asn1p_module_s *module, int stop_search) {
+ asn1_namespace_t *ns = asn1_namespace_new();
+ asn1_namespace_add_module(ns, module, stop_search);
+ return ns;
+}
+
+void
+asn1_namespace_add_module(asn1_namespace_t *ns, struct asn1p_module_s *module,
+ int stop_search) {
+ size_t idx = _add_element(ns);
+
+ ns->elements[idx].selector = NAM_SPACE,
+ ns->elements[idx].u.space.module = module;
+ ns->elements[idx].u.space.stop_search = stop_search;
+}
+
+const char *
+asn1_namespace_string(const asn1_namespace_t *ns) {
+ static abuf ab;
+
+ abuf_clear(&ab);
+
+ if(ns) {
+ abuf_str(&ab, "{");
+ for(size_t i = 0; i < ns->elements_count; i++) {
+ if(i) abuf_str(&ab, ",");
+ switch(ns->elements[i].selector) {
+ case NAM_SPACE:
+ abuf_printf(
+ &ab, "M:\"%s\"%s",
+ *(const char *const *)ns->elements[i].u.space.module,
+ ns->elements[i].u.space.stop_search ? "!" : "");
+ break;
+ case NAM_SYMBOL:
+ abuf_printf(&ab, "S:\"%s%s%s\"",
+ ns->elements[i].u.symbol.opt_governor
+ ? asn1p_ref_string(
+ ns->elements[i].u.symbol.opt_governor)
+ : "",
+ ns->elements[i].u.symbol.opt_governor ? ":" : "",
+ ns->elements[i].u.symbol.identifier);
+ break;
+ }
+ }
+ abuf_str(&ab, "}");
+ return ab.buffer;
+ } else {
+ return "<no namespace>";
+ }
+}
+
diff --git a/libasn1common/asn1_namespace.h b/libasn1common/asn1_namespace.h
new file mode 100644
index 00000000..1ae3d7b9
--- /dev/null
+++ b/libasn1common/asn1_namespace.h
@@ -0,0 +1,80 @@
+/*
+ * Structures and prototypes related to parameterization
+ */
+#ifndef ASN1_NAMESPACE_H
+#define ASN1_NAMESPACE_H
+
+struct asn1p_ref_s; /* Forward declaration */
+struct asn1p_expr_s; /* Forward declaration */
+struct asn1p_module_s; /* Forward declaration */
+
+typedef struct asn1_namespace_s {
+ struct asn1_namespace_element_s {
+ enum {
+ NAM_SPACE, /* The whole search space (e.g. Module) */
+ NAM_SYMBOL, /* A particular symbol */
+ } selector;
+ union {
+ struct {
+ struct asn1p_module_s *module;
+ int stop_search; /* This module MUST contain the symbol */
+ } space;
+ struct {
+ struct asn1p_ref_s *opt_governor; /* optional */
+ char *identifier;
+ struct asn1p_expr_s *resolution;
+ } symbol;
+ } u;
+ } *elements;
+ size_t elements_count;
+ size_t elements_size;
+} asn1_namespace_t;
+
+/*
+ * Set callback used to initialize standard namespaces.
+ */
+void asn1_namespace_add_standard_namespaces_callback(
+ void (*)(asn1_namespace_t *));
+
+asn1_namespace_t *asn1_namespace_new(void);
+void asn1_namespace_free(asn1_namespace_t *);
+
+asn1_namespace_t *asn1_namespace_clone(const asn1_namespace_t *);
+
+asn1_namespace_t *asn1_namespace_new_from_module(struct asn1p_module_s *mod, int stop_search);
+
+void asn1_namespace_add_module(asn1_namespace_t *,
+ struct asn1p_module_s *module, int stop_search);
+
+void asn1_namespace_add_symbol(asn1_namespace_t *,
+ struct asn1p_ref_s *opt_governor,
+ const char *identifier,
+ struct asn1p_expr_s *resolved_argument);
+
+/*
+ * Human-readable namespace layout.
+ * Returns a reference to a statically allocated string.
+ */
+const char *asn1_namespace_string(const asn1_namespace_t *);
+
+/*
+ * Create a new namespace by cloning (ns1) and adding (ns2) on top.
+ * Destroys (ns2).
+ */
+asn1_namespace_t *asn1_namespace_new_ND(const asn1_namespace_t *ns1,
+ asn1_namespace_t *ns2);
+
+/*
+ * Introduce and destroy namespace around the given code.
+ * This aids memory management around dynamic namespaces.
+ */
+#define WITH_MODULE_NAMESPACE(mod, ns_var, code) \
+ ({ \
+ struct asn1_namespace_s *ns_var = \
+ asn1_namespace_new_from_module(mod, 1); \
+ typeof(code) ret = code; \
+ asn1_namespace_free(ns_var); \
+ ret; \
+ })
+
+#endif /* ASN1_NAMESPACE_H */
diff --git a/libasn1common/asn1_ref.c b/libasn1common/asn1_ref.c
new file mode 100644
index 00000000..a5ee9981
--- /dev/null
+++ b/libasn1common/asn1_ref.c
@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "asn1_ref.h"
+
+/*
+ * Construct a new empty reference.
+ */
+asn1p_ref_t *
+asn1p_ref_new(int _lineno, struct asn1p_module_s *mod) {
+ asn1p_ref_t *ref;
+
+ ref = calloc(1, sizeof *ref);
+ assert(ref);
+ asn1p_ref_set_source(ref, mod, _lineno);
+
+ return ref;
+}
+
+void
+asn1p_ref_free(asn1p_ref_t *ref) {
+ if(ref) {
+ if(ref->components) {
+ size_t i = ref->comp_count;
+ while(i--) {
+ free(ref->components[i].name);
+ ref->components[i].name = 0;
+ }
+ free(ref->components);
+ ref->components = 0;
+ }
+
+ free(ref);
+ }
+}
+
+void
+asn1p_ref_set_source(asn1p_ref_t *ref, struct asn1p_module_s *module,
+ int lineno) {
+ if(ref) {
+ ref->module = module;
+ ref->_lineno = lineno;
+ }
+}
+
+static enum asn1p_ref_lex_type_e
+asn1p_ref_name2lextype(const char *name) {
+ enum asn1p_ref_lex_type_e lex_type;
+ int has_lowercase = 0;
+
+ if(*name == '&') {
+ if(name[1] >= 'A' && name[1] <= 'Z') {
+ lex_type = RLT_AmpUppercase;
+ } else {
+ lex_type = RLT_Amplowercase;
+ }
+ } else if(*name >= 'A' && *name <= 'Z') {
+ const char *p;
+
+ for(p = name; *p; p++) {
+ if(*p >= 'a' && *p <= 'z') {
+ has_lowercase = 1;
+ break;
+ }
+ }
+
+ if(has_lowercase) {
+ lex_type = RLT_Uppercase;
+ } else {
+ lex_type = RLT_CAPITALS;
+ }
+ } else if(*name == '@') {
+ if(name[1] == '.')
+ lex_type = RLT_AtDotlowercase;
+ else
+ lex_type = RLT_Atlowercase;
+ } else {
+ lex_type = RLT_lowercase;
+ }
+
+ return lex_type;
+}
+
+int
+asn1p_ref_add_component(asn1p_ref_t *ref, const char *name, enum asn1p_ref_lex_type_e lex_type) {
+
+ if(!ref || !name
+ || (int)lex_type < RLT_UNKNOWN || lex_type >= RLT_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(ref->comp_count == ref->comp_size) {
+ int newsize = ref->comp_size?(ref->comp_size<<2):4;
+ void *p = realloc(ref->components,
+ newsize * sizeof(ref->components[0]));
+ if(p) {
+ ref->components = p;
+ ref->comp_size = newsize;
+ } else {
+ return -1;
+ }
+
+ }
+
+ if(lex_type == RLT_UNKNOWN) {
+ lex_type = asn1p_ref_name2lextype(name);
+ } else {
+ assert(lex_type == asn1p_ref_name2lextype(name));
+ }
+
+ ref->components[ref->comp_count].name = strdup(name);
+ ref->components[ref->comp_count].lex_type = lex_type;
+ if(ref->components[ref->comp_count].name) {
+ ref->comp_count++;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+asn1p_ref_t *
+asn1p_ref_clone(asn1p_ref_t *ref) {
+ asn1p_ref_t *newref;
+
+ newref = asn1p_ref_new(ref->_lineno, ref->module);
+ if(newref) {
+ for(size_t i = 0; i < ref->comp_count; i++) {
+ if(asn1p_ref_add_component(newref,
+ ref->components[i].name,
+ ref->components[i].lex_type
+ )) {
+ asn1p_ref_free(newref);
+ newref = NULL;
+ break;
+ }
+ }
+ }
+
+ return newref;
+}
+
+int
+asn1p_ref_compare(const asn1p_ref_t *a, const asn1p_ref_t *b) {
+ if(a->comp_count != b->comp_count)
+ return -1;
+ if(a->module != b->module)
+ return -1;
+
+ for(size_t i = 0; i < a->comp_count; i++) {
+ if(a->components[i].lex_type != b->components[i].lex_type
+ || strcmp(a->components[i].name, b->components[i].name) != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+const char *
+asn1p_ref_string(const asn1p_ref_t *ref) {
+ static char static_buf[32];
+ static char *buf = static_buf;
+ static size_t buf_size = sizeof(static_buf);
+ char *p = buf;
+
+ if(!ref) return "<no-ref>";
+
+ for(size_t i = 0; i < ref->comp_count; i++) {
+ size_t space = buf_size - (p - buf);
+ int ret =
+ snprintf(p, space, "%s%s", i ? "." : "", ref->components[i].name);
+ if(ret < 0 || (size_t)ret >= space) {
+ i--;
+ char *tmp = malloc(buf_size * 2 + 1);
+ assert(tmp);
+ size_t p_offset = p - buf;
+ memcpy(tmp, buf, (p - buf));
+ if(buf != static_buf) free(buf);
+ buf_size *= 2;
+ buf = tmp;
+ p = tmp + p_offset;
+ } else {
+ p += ret;
+ }
+ }
+
+ *p = '\0';
+ return buf;
+}
+
diff --git a/libasn1common/asn1_ref.h b/libasn1common/asn1_ref.h
new file mode 100644
index 00000000..dbc8f878
--- /dev/null
+++ b/libasn1common/asn1_ref.h
@@ -0,0 +1,80 @@
+/*
+ * Generic reference to the yet unknown type defined elsewhere.
+ */
+#ifndef ASN1_REFERENCE_H
+#define ASN1_REFERENCE_H
+
+struct asn1p_module_s;
+
+typedef struct asn1p_ref_s {
+
+ /*
+ * A set of reference name components.
+ * A reference name consists of several components separated by dots:
+ * "OBJECT-CLASS.&Algorithm.&id"
+ */
+ struct asn1p_ref_component_s {
+ enum asn1p_ref_lex_type_e {
+ RLT_UNKNOWN, /* Invalid? */
+ /*
+ * Object class reference "OCLASS1",
+ * type reference "Type1",
+ * value reference "id",
+ * type field reference "&Type1",
+ * value field reference "&id",
+ * "OBJECT-CLASS"
+ */
+ RLT_CAPITALS,
+ RLT_Uppercase,
+ RLT_lowercase,
+ RLT_AmpUppercase,
+ RLT_Amplowercase,
+ RLT_Atlowercase,
+ RLT_AtDotlowercase,
+ RLT_MAX
+ } lex_type; /* Inferred lexical type of the identifier */
+ char *name; /* An identifier */
+ } *components;
+
+ size_t comp_count; /* Number of the components in the reference name. */
+ size_t comp_size; /* Number of allocated structures */
+
+ struct asn1p_module_s *module; /* Defined in module */
+ int _lineno; /* Number of line in the file */
+} asn1p_ref_t;
+
+/*
+ * Constructor and destructor.
+ */
+asn1p_ref_t *asn1p_ref_new(int _lineno, struct asn1p_module_s *mod);
+void asn1p_ref_free(asn1p_ref_t *);
+
+asn1p_ref_t *asn1p_ref_clone(asn1p_ref_t *ref);
+
+void asn1p_ref_set_source(asn1p_ref_t *, struct asn1p_module_s *module,
+ int lineno);
+
+
+/*
+ * Lexicographically compare references.
+ */
+int asn1p_ref_compare(const asn1p_ref_t *, const asn1p_ref_t *);
+
+/*
+ * Return a pointer to a statically allocated buffer representing the
+ * complete reference.
+ */
+const char *asn1p_ref_string(const asn1p_ref_t *);
+
+/*
+ * Add a new reference component to the existing reference structure.
+ *
+ * RETURN VALUES:
+ * 0: All clear.
+ * -1/EINVAL: Invalid arguments
+ * -1/ENOMEM: Memory allocation failed
+ */
+int asn1p_ref_add_component(asn1p_ref_t *,
+ const char *name, enum asn1p_ref_lex_type_e);
+
+#endif /* ASN1_REFERENCE_H */
diff --git a/libasn1compiler/Makefile.am b/libasn1compiler/Makefile.am
index 096fc2b2..d13a8c02 100644
--- a/libasn1compiler/Makefile.am
+++ b/libasn1compiler/Makefile.am
@@ -1,9 +1,10 @@
AM_CFLAGS = @ADD_CFLAGS@
-AM_CPPFLAGS = \
- -I$(top_srcdir)/libasn1parser \
- -I$(top_srcdir)/libasn1fix
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/libasn1common \
+ -I$(top_srcdir)/libasn1parser \
+ -I$(top_srcdir)/libasn1fix
noinst_LTLIBRARIES = libasn1compiler.la
diff --git a/libasn1fix/Makefile.am b/libasn1fix/Makefile.am
index cd859eba..51c4a7d4 100644
--- a/libasn1fix/Makefile.am
+++ b/libasn1fix/Makefile.am
@@ -1,45 +1,48 @@
@CODE_COVERAGE_RULES@
AM_CFLAGS = @ADD_CFLAGS@
-AM_CPPFLAGS = \
- -I$(top_srcdir)/libasn1parser
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/libasn1common \
+ -I$(top_srcdir)/libasn1parser
noinst_LTLIBRARIES = libasn1fix.la
-libasn1fix_la_SOURCES = \
- asn1fix.c asn1fix.h \
- asn1fix_internal.h \
- asn1fix_misc.c asn1fix_misc.h \
- asn1fix_value.c asn1fix_value.h \
- asn1fix_compat.c asn1fix_compat.h \
- asn1fix_constr.c asn1fix_constr.h \
- asn1fix_cstring.c asn1fix_cstring.h \
- asn1fix_retrieve.c asn1fix_retrieve.h \
- asn1fix_bitstring.c asn1fix_bitstring.h \
- asn1fix_constraint.c asn1fix_constraint.h \
- asn1fix_integer.c asn1fix_integer.h \
- asn1fix_crange.c asn1fix_crange.h \
- asn1fix_dereft.c asn1fix_dereft.h \
- asn1fix_derefv.c asn1fix_derefv.h \
- asn1fix_export.c asn1fix_export.h \
- asn1fix_param.c asn1fix_param.h \
- asn1fix_class.c asn1fix_class.h \
- asn1fix_tags.c asn1fix_tags.h \
- asn1fix_enum.c asn1fix_enum.h \
- asn1fix_cws.c asn1fix_cws.h \
- asn1fix_constraint_compat.c
-
-check_fixer_LDADD = $(noinst_LTLIBRARIES) \
- $(top_builddir)/libasn1parser/libasn1parser.la
+libasn1fix_la_SOURCES = \
+ asn1fix.c asn1fix.h \
+ asn1fix_internal.h \
+ asn1fix_misc.c asn1fix_misc.h \
+ asn1fix_value.c asn1fix_value.h \
+ asn1fix_compat.c asn1fix_compat.h \
+ asn1fix_constr.c asn1fix_constr.h \
+ asn1fix_cstring.c asn1fix_cstring.h \
+ asn1fix_retrieve.c asn1fix_retrieve.h \
+ asn1fix_bitstring.c asn1fix_bitstring.h \
+ asn1fix_constraint.c asn1fix_constraint.h \
+ asn1fix_integer.c asn1fix_integer.h \
+ asn1fix_crange.c asn1fix_crange.h \
+ asn1fix_dereft.c asn1fix_dereft.h \
+ asn1fix_derefv.c asn1fix_derefv.h \
+ asn1fix_export.c asn1fix_export.h \
+ asn1fix_param.c asn1fix_param.h \
+ asn1fix_class.c asn1fix_class.h \
+ asn1fix_tags.c asn1fix_tags.h \
+ asn1fix_enum.c asn1fix_enum.h \
+ asn1fix_cws.c asn1fix_cws.h \
+ asn1fix_constraint_compat.c
+
check_fixer_CPPFLAGS = -DTOP_SRCDIR=${top_srcdir} $(AM_CPPFLAGS)
+check_fixer_LDADD = $(noinst_LTLIBRARIES) \
+ $(top_builddir)/libasn1common/libasn1common.la \
+ $(top_builddir)/libasn1parser/libasn1parser.la
check_crange_SOURCES = asn1fix_crange.c asn1fix_constraint_compat.c
check_crange_CPPFLAGS = -DUNIT_TEST $(AM_CPPFLAGS)
-check_crange_LDADD = $(noinst_LTLIBRARIES) \
- $(top_builddir)/libasn1parser/libasn1parser.la
+check_crange_LDADD = $(noinst_LTLIBRARIES) \
+ $(top_builddir)/libasn1common/libasn1common.la \
+ $(top_builddir)/libasn1parser/libasn1parser.la
check_PROGRAMS = check_crange check_fixer
-TESTS_ENVIRONMENT = ASN1_TESTS_DIR=${top_srcdir}/tests/tests-asn1c-compiler
+TESTS_ENVIRONMENT = top_srcdir=${top_srcdir}
TESTS = ${check_PROGRAMS}
diff --git a/libasn1parser/Makefile.am b/libasn1parser/Makefile.am
index bf9127df..1f7b6e11 100644
--- a/libasn1parser/Makefile.am
+++ b/libasn1parser/Makefile.am
@@ -1,26 +1,26 @@
AM_CFLAGS = @ADD_CFLAGS@
+AM_CPPFLAGS = -I$(top_srcdir)/libasn1common
AM_YFLAGS = -p asn1p_ -d
AM_LFLAGS = -s -p -Cem -Pasn1p_ -olex.yy.c
noinst_LTLIBRARIES = libasn1parser.la
-libasn1parser_la_SOURCES = \
- asn1parser.c asn1parser.h \
- asn1p_y.c asn1p_y.h asn1p_l.c \
- asn1p_module.c asn1p_module.h \
- asn1p_oid.c asn1p_oid.h \
- asn1p_value.c asn1p_value.h \
- asn1p_expr.c asn1p_expr.h \
- asn1p_expr_str.h \
- asn1p_expr2uclass.h \
- asn1p_xports.c asn1p_xports.h \
- asn1p_constr.c asn1p_constr.h \
- asn1p_param.c asn1p_param.h \
- asn1p_class.c asn1p_class.h \
- asn1p_ref.c asn1p_ref.h \
- asn1p_integer.c asn1p_integer.h \
- asn1p_list.h
+libasn1parser_la_SOURCES = \
+ asn1parser.c asn1parser.h \
+ asn1p_y.c asn1p_y.h asn1p_l.c \
+ asn1p_module.c asn1p_module.h \
+ asn1p_oid.c asn1p_oid.h \
+ asn1p_value.c asn1p_value.h \
+ asn1p_expr.c asn1p_expr.h \
+ asn1p_expr_str.h \
+ asn1p_expr2uclass.h \
+ asn1p_xports.c asn1p_xports.h \
+ asn1p_constr.c asn1p_constr.h \
+ asn1p_param.c asn1p_param.h \
+ asn1p_class.c asn1p_class.h \
+ asn1p_integer.c asn1p_integer.h \
+ asn1p_list.h
asn1parser.h: asn1p_expr_str.h
diff --git a/libasn1print/Makefile.am b/libasn1print/Makefile.am
index 3fb11555..853645f8 100644
--- a/libasn1print/Makefile.am
+++ b/libasn1print/Makefile.am
@@ -1,11 +1,12 @@
AM_CFLAGS = @ADD_CFLAGS@
-AM_CPPFLAGS = \
- -I$(top_srcdir)/libasn1parser \
- -I$(top_srcdir)/libasn1fix
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/libasn1common \
+ -I$(top_srcdir)/libasn1parser \
+ -I$(top_srcdir)/libasn1fix
noinst_LTLIBRARIES = libasn1print.la
-libasn1print_la_SOURCES = \
- asn1print.c asn1print.h
+libasn1print_la_SOURCES = \
+ asn1print.c asn1print.h