--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-06-cve-2014-3467.patch Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,11708 @@
+Source:
+Internal
+
+Info:
+https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-3467
+Multiple unspecified vulnerabilities in the DER decoder in GNU Libtasn1 before
+3.6, as used in GnutTLS, allow remote attackers to cause a denial of service
+(out-of-bounds read) via crafted ASN.1 data.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- ORIGINAL/./lib/parser_aux.c 2015-07-14 18:28:22.919544825 -0700
++++ libtasn1-2.8/./lib/parser_aux.c 2015-07-14 18:45:02.691801820 -0700
+@@ -21,6 +21,7 @@
+ */
+
+ #include <int.h>
++/*#include <hash-pjw-bare.h>*/
+ #include "parser_aux.h"
+ #include "gstr.h"
+ #include "structure.h"
+@@ -44,28 +45,28 @@
+ list_type *firstElement = NULL;
+
+ /******************************************************/
+-/* Function : _asn1_add_node */
++/* Function : _asn1_add_static_node */
+ /* Description: creates a new NODE_ASN element and */
+ /* puts it in the list pointed by firstElement. */
+ /* Parameters: */
+-/* type: type of the new element (see TYPE_ */
++/* type: type of the new element (see TYPE_ */
+ /* and CONST_ constants). */
+ /* Return: pointer to the new element. */
+ /******************************************************/
+ ASN1_TYPE
+-_asn1_add_node (unsigned int type)
++_asn1_add_static_node (unsigned int type)
+ {
+ list_type *listElement;
+ ASN1_TYPE punt;
+
+- punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
++ punt = calloc (1, sizeof (struct node_asn_struct));
+ if (punt == NULL)
+ return NULL;
+
+- listElement = (list_type *) _asn1_malloc (sizeof (list_type));
++ listElement = malloc (sizeof (list_type));
+ if (listElement == NULL)
+ {
+- _asn1_free (punt);
++ free (punt);
+ return NULL;
+ }
+
+@@ -78,6 +79,26 @@
+ return punt;
+ }
+
++#define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
++
++/* Return a hash of the N bytes of X using the method described by
++ Bruno Haible in http://www.haible.de/bruno/hashfunc.html.
++ Note that while many hash functions reduce their result via modulo
++ to a 0..table_size-1 range, this function does not do that. */
++
++size_t
++hash_pjw_bare (const void *x, size_t n)
++{
++ const unsigned char *s = x;
++ size_t h = 0;
++ unsigned i;
++
++ for (i = 0; i < n; i++)
++ h = s[i] + ((h << 9) | (h >> (SIZE_BITS - 9)));
++
++ return h;
++}
++
+ /**
+ * asn1_find_node:
+ * @pointer: NODE_ASN element pointer.
+@@ -96,6 +117,8 @@
+ ASN1_TYPE p;
+ char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
+ const char *n_start;
++ unsigned int nsize;
++ unsigned int nhash;
+
+ if (pointer == NULL)
+ return NULL;
+@@ -106,25 +129,30 @@
+ p = pointer;
+ n_start = name;
+
+- if (p->name != NULL)
++ if (p->name[0] != 0)
+ { /* has *pointer got a name ? */
+ n_end = strchr (n_start, '.'); /* search the first dot */
+ if (n_end)
+ {
+- memcpy (n, n_start, n_end - n_start);
+- n[n_end - n_start] = 0;
++ nsize = n_end - n_start;
++ memcpy (n, n_start, nsize);
++ n[nsize] = 0;
+ n_start = n_end;
+ n_start++;
++
++ nhash = hash_pjw_bare (n, nsize);
+ }
+ else
+ {
+- _asn1_str_cpy (n, sizeof (n), n_start);
++ nsize = _asn1_str_cpy (n, sizeof (n), n_start);
++ nhash = hash_pjw_bare (n, nsize);
++
+ n_start = NULL;
+ }
+
+ while (p)
+ {
+- if ((p->name) && (!strcmp (p->name, n)))
++ if (nhash == p->name_hash && (!strcmp (p->name, n)))
+ break;
+ else
+ p = p->right;
+@@ -144,14 +172,18 @@
+ n_end = strchr (n_start, '.'); /* search the next dot */
+ if (n_end)
+ {
+- memcpy (n, n_start, n_end - n_start);
+- n[n_end - n_start] = 0;
++ nsize = n_end - n_start;
++ memcpy (n, n_start, nsize);
++ n[nsize] = 0;
+ n_start = n_end;
+ n_start++;
++
++ nhash = hash_pjw_bare (n, nsize);
+ }
+ else
+ {
+- _asn1_str_cpy (n, sizeof (n), n_start);
++ nsize = _asn1_str_cpy (n, sizeof (n), n_start);
++ nhash = hash_pjw_bare (n, nsize);
+ n_start = NULL;
+ }
+
+@@ -173,7 +205,7 @@
+ { /* no "?LAST" */
+ while (p)
+ {
+- if ((p->name) && (!strcmp (p->name, n)))
++ if (p->name_hash == nhash && !strcmp (p->name, n))
+ break;
+ else
+ p = p->right;
+@@ -205,7 +237,7 @@
+ if (node->value)
+ {
+ if (node->value != node->small_value)
+- _asn1_free (node->value);
++ free (node->value);
+ node->value = NULL;
+ node->value_len = 0;
+ }
+@@ -219,7 +251,7 @@
+ }
+ else
+ {
+- node->value = _asn1_malloc (len);
++ node->value = malloc (len);
+ if (node->value == NULL)
+ return NULL;
+ }
+@@ -230,10 +262,10 @@
+ }
+
+ /******************************************************************/
+-/* Function : _asn1_set_value_octet */
++/* Function : _asn1_set_value_lv */
+ /* Description: sets the field VALUE in a NODE_ASN element. The */
+ /* previous value (if exist) will be lost. The value */
+-/* given is stored as an octet string. */
++/* given is stored as an length-value format (LV */
+ /* Parameters: */
+ /* node: element pointer. */
+ /* value: pointer to the value that you want to set. */
+@@ -241,7 +273,7 @@
+ /* Return: pointer to the NODE_ASN element. */
+ /******************************************************************/
+ ASN1_TYPE
+-_asn1_set_value_octet (ASN1_TYPE node, const void *value, unsigned int len)
++_asn1_set_value_lv (ASN1_TYPE node, const void *value, unsigned int len)
+ {
+ int len2;
+ void *temp;
+@@ -250,7 +282,7 @@
+ return node;
+
+ asn1_length_der (len, NULL, &len2);
+- temp = (unsigned char *) _asn1_malloc (len + len2);
++ temp = malloc (len + len2);
+ if (temp == NULL)
+ return NULL;
+
+@@ -270,7 +302,7 @@
+ if (node->value)
+ {
+ if (node->value != node->small_value)
+- _asn1_free (node->value);
++ free (node->value);
+ node->value = NULL;
+ node->value_len = 0;
+ }
+@@ -304,7 +336,7 @@
+ /* value is allocated */
+ int prev_len = node->value_len;
+ node->value_len += len;
+- node->value = _asn1_realloc (node->value, node->value_len);
++ node->value = realloc (node->value, node->value_len);
+ if (node->value == NULL)
+ {
+ node->value_len = 0;
+@@ -319,7 +351,7 @@
+ /* value is in node */
+ int prev_len = node->value_len;
+ node->value_len += len;
+- node->value = _asn1_malloc (node->value_len);
++ node->value = malloc (node->value_len);
+ if (node->value == NULL)
+ {
+ node->value_len = 0;
+@@ -347,27 +379,49 @@
+ ASN1_TYPE
+ _asn1_set_name (ASN1_TYPE node, const char *name)
+ {
++ unsigned int nsize;
++
+ if (node == NULL)
+ return node;
+
+- if (node->name)
++ if (name == NULL)
+ {
+- _asn1_free (node->name);
+- node->name = NULL;
++ node->name[0] = 0;
++ node->name_hash = hash_pjw_bare (node->name, 0);
++ return node;
+ }
+
+- if (name == NULL)
+- return node;
++ nsize = _asn1_str_cpy (node->name, sizeof (node->name), name);
++ node->name_hash = hash_pjw_bare (node->name, nsize);
++
++ return node;
++}
+
+- if (strlen (name))
++/******************************************************************/
++/* Function : _asn1_cpy_name */
++/* Description: copies the field NAME in a NODE_ASN element. */
++/* Parameters: */
++/* dst: a dest element pointer. */
++/* src: a source element pointer. */
++/* Return: pointer to the NODE_ASN element. */
++/******************************************************************/
++ASN1_TYPE
++_asn1_cpy_name (ASN1_TYPE dst, ASN1_TYPE src)
++{
++ if (dst == NULL)
++ return dst;
++
++ if (src == NULL)
+ {
+- node->name = (char *) _asn1_strdup (name);
+- if (node->name == NULL)
+- return NULL;
++ dst->name[0] = 0;
++ dst->name_hash = hash_pjw_bare (dst->name, 0);
++ return dst;
+ }
+- else
+- node->name = NULL;
+- return node;
++
++ _asn1_str_cpy (dst->name, sizeof (dst->name), src->name);
++ dst->name_hash = src->name_hash;
++
++ return dst;
+ }
+
+ /******************************************************************/
+@@ -390,21 +444,6 @@
+ return node;
+ }
+
+-/******************************************************************/
+-/* Function : _asn1_get_right */
+-/* Description: returns the element pointed by the RIGHT field of */
+-/* a NODE_ASN element. */
+-/* Parameters: */
+-/* node: NODE_ASN element pointer. */
+-/* Return: field RIGHT of NODE. */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_get_right (ASN1_TYPE node)
+-{
+- if (node == NULL)
+- return NULL;
+- return node->right;
+-}
+
+ /******************************************************************/
+ /* Function : _asn1_get_last_right */
+@@ -427,95 +466,30 @@
+ }
+
+ /******************************************************************/
+-/* Function : _asn1_set_down */
+-/* Description: sets the field DOWN in a NODE_ASN element. */
+-/* Parameters: */
+-/* node: element pointer. */
+-/* down: pointer to a NODE_ASN element that you want be pointed */
+-/* by NODE. */
+-/* Return: pointer to *NODE. */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_set_down (ASN1_TYPE node, ASN1_TYPE down)
+-{
+- if (node == NULL)
+- return node;
+- node->down = down;
+- if (down)
+- down->left = node;
+- return node;
+-}
+-
+-/******************************************************************/
+-/* Function : _asn1_get_down */
+-/* Description: returns the element pointed by the DOWN field of */
+-/* a NODE_ASN element. */
+-/* Parameters: */
+-/* node: NODE_ASN element pointer. */
+-/* Return: field DOWN of NODE. */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_get_down (ASN1_TYPE node)
+-{
+- if (node == NULL)
+- return NULL;
+- return node->down;
+-}
+-
+-/******************************************************************/
+-/* Function : _asn1_get_name */
+-/* Description: returns the name of a NODE_ASN element. */
+-/* Parameters: */
+-/* node: NODE_ASN element pointer. */
+-/* Return: a null terminated string. */
+-/******************************************************************/
+-char *
+-_asn1_get_name (ASN1_TYPE node)
+-{
+- if (node == NULL)
+- return NULL;
+- return node->name;
+-}
+-
+-/******************************************************************/
+-/* Function : _asn1_mod_type */
+-/* Description: change the field TYPE of an NODE_ASN element. */
+-/* The new value is the old one | (bitwise or) the */
+-/* paramener VALUE. */
+-/* Parameters: */
+-/* node: NODE_ASN element pointer. */
+-/* value: the integer value that must be or-ed with the current */
+-/* value of field TYPE. */
+-/* Return: NODE pointer. */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_mod_type (ASN1_TYPE node, unsigned int value)
+-{
+- if (node == NULL)
+- return node;
+- node->type |= value;
+- return node;
+-}
+-
+-
+-/******************************************************************/
+ /* Function : _asn1_remove_node */
+ /* Description: gets free the memory allocated for an NODE_ASN */
+ /* element (not the elements pointed by it). */
+ /* Parameters: */
+ /* node: NODE_ASN element pointer. */
++/* flags: ASN1_DELETE_FLAG_* */
+ /******************************************************************/
+ void
+-_asn1_remove_node (ASN1_TYPE node)
++_asn1_remove_node (ASN1_TYPE node, unsigned int flags)
+ {
+ if (node == NULL)
+ return;
+
+- if (node->name != NULL)
+- _asn1_free (node->name);
+- if (node->value != NULL && node->value != node->small_value)
+- _asn1_free (node->value);
+- _asn1_free (node);
++ if (node->value != NULL)
++ {
++ if (flags & ASN1_DELETE_FLAG_ZEROIZE)
++ {
++ safe_memset(node->value, 0, node->value_len);
++ }
++
++ if (node->value != node->small_value)
++ free (node->value);
++ }
++ free (node);
+ }
+
+ /******************************************************************/
+@@ -555,7 +529,7 @@
+ {
+ listElement = firstElement;
+ firstElement = firstElement->next;
+- _asn1_free (listElement);
++ free (listElement);
+ }
+ }
+
+@@ -573,17 +547,17 @@
+ {
+ listElement = firstElement;
+ firstElement = firstElement->next;
+- _asn1_remove_node (listElement->node);
+- _asn1_free (listElement);
++ _asn1_remove_node (listElement->node, 0);
++ free (listElement);
+ }
+ }
+
+
+ char *
+-_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE])
++_asn1_ltostr (long v, char *str)
+ {
+ long d, r;
+- char temp[20];
++ char temp[LTOSTR_MAX_SIZE];
+ int count, k, start;
+
+ if (v < 0)
+@@ -604,7 +578,7 @@
+ count++;
+ v = d;
+ }
+- while (v && ((start+count) < LTOSTR_MAX_SIZE-1));
++ while (v);
+
+ for (k = 0; k < count; k++)
+ str[k + start] = temp[start + count - k - 1];
+@@ -623,7 +597,7 @@
+ /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
+ /* otherwise ASN1_SUCCESS */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_change_integer_value (ASN1_TYPE node)
+ {
+ ASN1_TYPE p;
+@@ -637,7 +611,8 @@
+ p = node;
+ while (p)
+ {
+- if ((type_field (p->type) == TYPE_INTEGER) && (p->type & CONST_ASSIGN))
++ if ((type_field (p->type) == TYPE_INTEGER)
++ && (p->type & CONST_ASSIGN))
+ {
+ if (p->value)
+ {
+@@ -690,7 +665,7 @@
+ /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
+ /* otherwise ASN1_SUCCESS */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_expand_object_id (ASN1_TYPE node)
+ {
+ ASN1_TYPE p, p2, p3, p4, p5;
+@@ -719,22 +694,25 @@
+ {
+ _asn1_str_cpy (name2, sizeof (name2), name_root);
+ _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p2->value);
++ _asn1_str_cat (name2, sizeof (name2),
++ (char *) p2->value);
+ p3 = asn1_find_node (node, name2);
+- if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+- !(p3->type & CONST_ASSIGN))
++ if (!p3
++ || (type_field (p3->type) != TYPE_OBJECT_ID)
++ || !(p3->type & CONST_ASSIGN))
+ return ASN1_ELEMENT_NOT_FOUND;
+ _asn1_set_down (p, p2->right);
+- _asn1_remove_node (p2);
++ _asn1_remove_node (p2, 0);
+ p2 = p;
+ p4 = p3->down;
+ while (p4)
+ {
+ if (type_field (p4->type) == TYPE_CONSTANT)
+ {
+- p5 = _asn1_add_node_only (TYPE_CONSTANT);
++ p5 =
++ _asn1_add_single_node (TYPE_CONSTANT);
+ _asn1_set_name (p5, p4->name);
+- tlen = strlen (p4->value);
++ tlen = _asn1_strlen (p4->value);
+ if (tlen > 0)
+ _asn1_set_value (p5, p4->value, tlen + 1);
+ if (p2 == p)
+@@ -805,10 +783,10 @@
+ {
+ _asn1_str_cpy (name2, sizeof (name2), name_root);
+ _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p2->value);
++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
+ p3 = asn1_find_node (node, name2);
+- if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+- !(p3->type & CONST_ASSIGN))
++ if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID)
++ || !(p3->type & CONST_ASSIGN))
+ return ASN1_ELEMENT_NOT_FOUND;
+ p4 = p3->down;
+ name2[0] = 0;
+@@ -818,7 +796,8 @@
+ {
+ if (name2[0])
+ _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p4->value);
++ _asn1_str_cat (name2, sizeof (name2),
++ (char *) p4->value);
+ }
+ p4 = p4->right;
+ }
+@@ -871,7 +850,7 @@
+ /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
+ /* otherwise ASN1_SUCCESS */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_type_set_config (ASN1_TYPE node)
+ {
+ ASN1_TYPE p, p2;
+@@ -944,7 +923,7 @@
+ /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
+ /* otherwise ASN1_SUCCESS */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_check_identifier (ASN1_TYPE node)
+ {
+ ASN1_TYPE p, p2;
+@@ -956,15 +935,18 @@
+ p = node;
+ while (p)
+ {
+- if (type_field (p->type) == TYPE_IDENTIFIER)
++ if (p->value && type_field (p->type) == TYPE_IDENTIFIER)
+ {
+ _asn1_str_cpy (name2, sizeof (name2), node->name);
+ _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p->value);
++ _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
+ p2 = asn1_find_node (node, name2);
+ if (p2 == NULL)
+ {
+- strcpy (_asn1_identifierMissing, p->value);
++ if (p->value)
++ _asn1_strcpy (_asn1_identifierMissing, p->value);
++ else
++ _asn1_strcpy (_asn1_identifierMissing, "(null)");
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ }
+ }
+@@ -976,8 +958,8 @@
+ {
+ _asn1_str_cpy (name2, sizeof (name2), node->name);
+ _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p2->value);
+- strcpy (_asn1_identifierMissing, p2->value);
++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
++ _asn1_strcpy (_asn1_identifierMissing, p2->value);
+ p2 = asn1_find_node (node, name2);
+ if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
+ !(p2->type & CONST_ASSIGN))
+@@ -996,11 +978,11 @@
+ {
+ _asn1_str_cpy (name2, sizeof (name2), node->name);
+ _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p2->value);
+- strcpy (_asn1_identifierMissing, p2->value);
++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
++ _asn1_strcpy (_asn1_identifierMissing, p2->value);
+ p2 = asn1_find_node (node, name2);
+- if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
+- !(p2->type & CONST_ASSIGN))
++ if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID)
++ || !(p2->type & CONST_ASSIGN))
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ else
+ _asn1_identifierMissing[0] = 0;
+@@ -1048,7 +1030,7 @@
+ /* a DEFINITIONS element, */
+ /* otherwise ASN1_SUCCESS */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_set_default_tag (ASN1_TYPE node)
+ {
+ ASN1_TYPE p;
+--- ORIGINAL/./lib/libtasn1.h 2015-07-14 18:28:22.936872981 -0700
++++ libtasn1-2.8/./lib/libtasn1.h 2015-07-14 18:45:02.744075374 -0700
+@@ -47,6 +47,17 @@
+
+ #define ASN1_VERSION "2.8"
+
++#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
++# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
++# if _ASN1_GCC_VERSION >= 30100
++# define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
++# endif
++#endif
++
++#ifndef _ASN1_GCC_ATTR_DEPRECATED
++#define _ASN1_GCC_ATTR_DEPRECATED
++#endif
++
+ typedef int asn1_retCode; /* type returned by libtasn1 functions */
+
+ /*****************************************/
+@@ -103,53 +114,73 @@
+ #define ASN1_TAG_ENUMERATED 0x0A
+ #define ASN1_TAG_NULL 0x05
+ #define ASN1_TAG_GENERALSTRING 0x1B
++#define ASN1_TAG_NUMERIC_STRING 0x12
++#define ASN1_TAG_IA5_STRING 0x16
++#define ASN1_TAG_TELETEX_STRING 0x14
++#define ASN1_TAG_PRINTABLE_STRING 0x13
++#define ASN1_TAG_UNIVERSAL_STRING 0x1C
++#define ASN1_TAG_BMP_STRING 0x1E
++#define ASN1_TAG_UTF8_STRING 0x0C
++#define ASN1_TAG_VISIBLE_STRING 0x1A
+
+ /******************************************************/
+ /* Structure definition used for the node of the tree */
+ /* that represent an ASN.1 DEFINITION. */
+ /******************************************************/
+
++ /* maximum number of characters of a name */
++ /* inside a file with ASN1 definitons */
++#define ASN1_MAX_NAME_SIZE 64
++
++ typedef struct node_asn_struct node_asn;
++
++ typedef node_asn *ASN1_TYPE;
++
+ #if !defined ASN1_BUILDING
+ /* This structure is also in internal.h, but then contains more
+ fields. You cannot make any modifications to these fields
+ without breaking ABI. */
+ struct node_asn_struct
+ {
+- char *name; /* Node name */
++ char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */
++ unsigned int name_hash;
+ unsigned int type; /* Node type */
+ unsigned char *value; /* Node value */
+ int value_len;
+- struct node_asn_struct *down; /* Pointer to the son node */
+- struct node_asn_struct *right; /* Pointer to the brother node */
+- struct node_asn_struct *left; /* Pointer to the next list element */
++ ASN1_TYPE down; /* Pointer to the son node */
++ ASN1_TYPE right; /* Pointer to the brother node */
++ ASN1_TYPE left; /* Pointer to the next list element */
+ };
+ #endif
+
+- typedef struct node_asn_struct node_asn;
+-
+- typedef node_asn *ASN1_TYPE;
+-
+ #define ASN1_TYPE_EMPTY NULL
+
++#define ASN1_DELETE_FLAG_ZEROIZE 1
++
+ /*****************************************/
+ /* For the on-disk format of ASN.1 trees */
+ /*****************************************/
+ struct static_struct_asn
+ {
+- const char *name; /* Node name */
+- unsigned int type; /* Node type */
+- const void *value; /* Node value */
++ const char *name; /* Node name */
++ unsigned int type; /* Node type */
++ const void *value; /* Node value */
+ };
+ typedef struct static_struct_asn ASN1_ARRAY_TYPE;
+
++ struct asn1_data_node_st
++ {
++ const char *name; /* Node name */
++ const void *value; /* Node value */
++ unsigned int value_len; /* Node value size */
++ unsigned int type; /* Node value type (TYPE_*) */
++ };
++ typedef struct asn1_data_node_st asn1_data_node_st;
++
+ /***********************************/
+ /* Fixed constants */
+ /***********************************/
+
+- /* maximum number of characters of a name */
+- /* inside a file with ASN1 definitons */
+-#define ASN1_MAX_NAME_SIZE 128
+-
+ /* maximum number of characters */
+ /* of a description message */
+ /* (null character included) */
+@@ -182,6 +213,8 @@
+
+ extern ASN1_API asn1_retCode asn1_delete_structure (ASN1_TYPE * structure);
+
++ extern ASN1_API asn1_retCode asn1_delete_structure2 (ASN1_TYPE * structure, unsigned int flags);
++
+ extern ASN1_API asn1_retCode
+ asn1_delete_element (ASN1_TYPE structure, const char *element_name);
+
+@@ -194,6 +227,13 @@
+ void *ivalue, int *len);
+
+ extern ASN1_API asn1_retCode
++ asn1_read_value_type (ASN1_TYPE root, const char *name,
++ void *ivalue, int *len, unsigned int *etype);
++
++ extern ASN1_API asn1_retCode
++ asn1_read_node_value (ASN1_TYPE node, asn1_data_node_st * data);
++
++ extern ASN1_API asn1_retCode
+ asn1_number_of_elements (ASN1_TYPE element, const char *name, int *num);
+
+ extern ASN1_API asn1_retCode
+@@ -208,7 +248,7 @@
+ asn1_der_decoding_element (ASN1_TYPE * structure,
+ const char *elementName,
+ const void *ider, int len,
+- char *errorDescription);
++ char *errorDescription); _ASN1_GCC_ATTR_DEPRECATED;
+
+ extern ASN1_API asn1_retCode
+ asn1_der_decoding_startEnd (ASN1_TYPE element,
+@@ -239,6 +279,10 @@
+
+ extern ASN1_API void asn1_perror (asn1_retCode error);
+
++#define ASN1_MAX_TAG_SIZE 4
++#define ASN1_MAX_LENGTH_SIZE 9
++#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE)
++
+ /* DER utility functions. */
+
+ extern ASN1_API int
+@@ -273,6 +317,17 @@
+
+ /* Other utility functions. */
+
++ extern ASN1_API
++ int asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
++ unsigned int der_len,
++ const unsigned char **str,
++ unsigned int *str_len);
++
++ extern ASN1_API int
++ asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
++ unsigned int str_len, unsigned char *tl,
++ unsigned int *tl_len);
++
+ extern ASN1_API ASN1_TYPE
+ asn1_find_node (ASN1_TYPE pointer, const char *name);
+
+--- ORIGINAL/./lib/gstr.h 2015-07-14 18:28:22.931870138 -0700
++++ libtasn1-2.8/./lib/gstr.h 2015-07-14 18:45:02.736947739 -0700
+@@ -20,8 +20,24 @@
+ * 02110-1301, USA
+ */
+
+-void _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src);
++unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size,
++ const char *src);
+ void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src);
+
+ #define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
+ #define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
++
++inline static
++void safe_memset(void *data, int c, size_t size)
++{
++ volatile unsigned volatile_zero = 0;
++ volatile char *vdata = (volatile char*)data;
++
++ /* This is based on a nice trick for safe memset,
++ * sent by David Jacobson in the openssl-dev mailing list.
++ */
++
++ do {
++ memset(data, c, size);
++ } while(vdata[volatile_zero] != c);
++}
+--- ORIGINAL/./lib/decoding.c 2015-07-14 18:28:22.909220237 -0700
++++ libtasn1-2.8/./lib/decoding.c 2015-07-14 18:45:02.647975796 -0700
+@@ -27,13 +27,113 @@
+ /*****************************************************/
+
+ #include <int.h>
+-#include "parser_aux.h"
++#include <parser_aux.h>
+ #include <gstr.h>
+-#include "structure.h"
+-#include "element.h"
++#include <structure.h>
++#include <element.h>
++#include <limits.h>
++/*#include <intprops.h>*/
++
++#define INT_ADD_OVERFLOW(a, b) \
++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
++#define INT_MULTIPLY_OVERFLOW(a, b) \
++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
++/* Return 1 if the expression A <op> B would overflow,
++ where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
++ assuming MIN and MAX are the minimum and maximum for the result type.
++ Arguments should be free of side effects. */
++#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \
++ op_result_overflow (a, b, \
++ _GL_INT_MINIMUM (0 * (b) + (a)), \
++ _GL_INT_MAXIMUM (0 * (b) + (a)))
++#define _GL_ADD_OVERFLOW(a, b, min, max) \
++ ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \
++ : (a) < 0 ? (b) <= (a) + (b) \
++ : (b) < 0 ? (a) <= (a) + (b) \
++ : (a) + (b) < (b))
++#define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
++ (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \
++ || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
++#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \
++ ((b) < 0 \
++ ? (a) < (min) - (b) \
++ : (max) - (b) < (a))
++
++#define _GL_SIGNED_INT_MAXIMUM(e) \
++ (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1)
++
++#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
++
++/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
++ <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>. */
++#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
++
++#define CHAR_BIT 8 /* max # of bits in a "char" */
++
++/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
++ See above for restrictions. Avoid && and || as they tickle
++ bugs in Sun C 5.11 2010/08/13 and other compilers; see
++ <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */
++#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
++ ((b) < 0 \
++ ? ((a) < 0 \
++ ? (a) < (max) / (b) \
++ : (b) == -1 \
++ ? 0 \
++ : (min) / (b) < (a)) \
++ : (b) == 0 \
++ ? 0 \
++ : ((a) < 0 \
++ ? (a) < (min) / (b) \
++ : (max) / (b) < (a)))
++
++/* The maximum and minimum values for the type of the expression E,
++ after integer promotion. E should not have side effects. */
++#define _GL_INT_MINIMUM(e) \
++ (_GL_INT_SIGNED (e) \
++ ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \
++ : _GL_INT_CONVERT (e, 0))
++#define _GL_INT_MAXIMUM(e) \
++ (_GL_INT_SIGNED (e) \
++ ? _GL_SIGNED_INT_MAXIMUM (e) \
++ : _GL_INT_NEGATE_CONVERT (e, 1))
++
++/* True if the signed integer expression E uses two's complement. */
++#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1)
++
++/* Return 1 if the integer expression E, after integer promotion, has
++ a signed type. */
++#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
++
++#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
++ INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
++ _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
++
++#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \
++ ((a) < 0 \
++ ? (a) < (min) >> (b) \
++ : (max) >> (b) < (a))
++
++
++#ifdef DEBUG
++# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
++#else
++# define warn()
++#endif
++
++#define HAVE_TWO(x) (x>=2?1:0)
++
++#define DECR_LEN(l, s) do { \
++ l -= s; \
++ if (l < 0) { \
++ warn(); \
++ result = ASN1_DER_ERROR; \
++ goto cleanup; \
++ } \
++ } while (0)
+
+-static asn1_retCode
+-_asn1_get_indefinite_length_string (const unsigned char *der, int *len);
++static int
++_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len);
+
+ static void
+ _asn1_error_description_tag_error (ASN1_TYPE node, char *ErrorDescription)
+@@ -56,14 +156,13 @@
+ *
+ * Returns: Return the decoded length value, or -1 on indefinite
+ * length, or -2 when the value was too big to fit in a int, or -4
+- * when the decoed length value plus @len would exceed @der_len.
+-
++ * when the decoded length value plus @len would exceed @der_len.
+ **/
+-signed long
++long
+ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
+ {
+- int ans;
+- int k, punt;
++ unsigned int ans;
++ int k, punt, sum;
+
+ *len = 0;
+ if (der_len <= 0)
+@@ -73,7 +172,7 @@
+ {
+ /* short form */
+ *len = 1;
+- return der[0];
++ ans = der[0];
+ }
+ else
+ {
+@@ -85,25 +184,34 @@
+ ans = 0;
+ while (punt <= k && punt < der_len)
+ {
+- int last = ans;
++ if (INT_MULTIPLY_OVERFLOW (ans, 256))
++ return -2;
++ ans *= 256;
+
+- ans = ans * 256 + der[punt++];
+- if (ans < last)
+- /* we wrapped around, no bignum support... */
++ if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt])))
+ return -2;
++ ans += der[punt];
++ punt++;
+ }
+ }
+ else
+ { /* indefinite length method */
+- *len = punt;
+- return -1;
++ *len = punt;
++ return -1;
+ }
+
+ *len = punt;
+- if (ans + *len < ans || ans + *len > der_len)
+- return -4;
+- return ans;
+ }
++
++ sum = ans;
++ if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len)))
++ return -2;
++ sum += *len;
++
++ if (sum > der_len)
++ return -4;
++
++ return ans;
+ }
+
+ /**
+@@ -122,7 +230,8 @@
+ asn1_get_tag_der (const unsigned char *der, int der_len,
+ unsigned char *cls, int *len, unsigned long *tag)
+ {
+- int punt, ris;
++ unsigned int ris;
++ int punt;
+
+ if (der == NULL || der_len < 2 || len == NULL)
+ return ASN1_DER_ERROR;
+@@ -139,25 +248,34 @@
+ /* Long form */
+ punt = 1;
+ ris = 0;
+- while (punt <= der_len && der[punt] & 128)
++ while (punt < der_len && der[punt] & 128)
+ {
+- int last = ris;
+- ris = ris * 128 + (der[punt++] & 0x7F);
+- if (ris < last)
+- /* wrapper around, and no bignums... */
++
++ if (INT_MULTIPLY_OVERFLOW (ris, 128))
+ return ASN1_DER_ERROR;
++ ris *= 128;
++
++ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
++ return ASN1_DER_ERROR;
++ ris += (der[punt] & 0x7F);
++ punt++;
+ }
++
+ if (punt >= der_len)
+ return ASN1_DER_ERROR;
+- {
+- int last = ris;
+- ris = ris * 128 + (der[punt++] & 0x7F);
+- if (ris < last)
+- /* wrapper around, and no bignums... */
+- return ASN1_DER_ERROR;
+- }
++
++ if (INT_MULTIPLY_OVERFLOW (ris, 128))
++ return ASN1_DER_ERROR;
++ ris *= 128;
++
++ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
++ return ASN1_DER_ERROR;
++ ris += (der[punt] & 0x7F);
++ punt++;
++
+ *len = punt;
+ }
++
+ if (tag)
+ *tag = ris;
+ return ASN1_SUCCESS;
+@@ -178,7 +296,7 @@
+ *
+ * Since: 2.0
+ **/
+-signed long
++long
+ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len)
+ {
+ int ret;
+@@ -187,8 +305,7 @@
+ ret = asn1_get_length_der (ber, ber_len, len);
+ if (ret == -1)
+ { /* indefinite length method */
+- ret = ber_len;
+- err = _asn1_get_indefinite_length_string (ber + 1, &ret);
++ err = _asn1_get_indefinite_length_string (ber + 1, ber_len, &ret);
+ if (err != ASN1_SUCCESS)
+ return -3;
+ }
+@@ -219,7 +336,6 @@
+ if (der_len <= 0)
+ return ASN1_GENERIC_ERROR;
+
+- /* if(str==NULL) return ASN1_SUCCESS; */
+ *str_len = asn1_get_length_der (der, der_len, &len_len);
+
+ if (*str_len < 0)
+@@ -227,7 +343,10 @@
+
+ *ret_len = *str_len + len_len;
+ if (str_size >= *str_len)
+- memcpy (str, der + len_len, *str_len);
++ {
++ if (*str_len > 0 && str != NULL)
++ memcpy (str, der + len_len, *str_len);
++ }
+ else
+ {
+ return ASN1_MEM_ERROR;
+@@ -246,9 +365,11 @@
+
+ if (der_len <= 0 || str == NULL)
+ return ASN1_DER_ERROR;
++
+ str_len = asn1_get_length_der (der, der_len, &len_len);
+- if (str_len < 0 || str_size < str_len)
++ if (str_len <= 0 || str_size < str_len)
+ return ASN1_DER_ERROR;
++
+ memcpy (str, der + len_len, str_len);
+ str[str_len] = 0;
+ *ret_len = str_len + len_len;
+@@ -262,8 +383,8 @@
+ {
+ int len_len, len, k;
+ int leading;
+- char temp[20];
+- unsigned long val, val1, prev_val;
++ char temp[LTOSTR_MAX_SIZE];
++ unsigned long val, val1;
+
+ *ret_len = 0;
+ if (str && str_size > 0)
+@@ -271,9 +392,10 @@
+
+ if (str == NULL || der_len <= 0)
+ return ASN1_GENERIC_ERROR;
++
+ len = asn1_get_length_der (der, der_len, &len_len);
+
+- if (len < 0 || len > der_len || len_len > der_len)
++ if (len <= 0 || len + len_len > der_len)
+ return ASN1_DER_ERROR;
+
+ val1 = der[len_len] / 40;
+@@ -283,7 +405,6 @@
+ _asn1_str_cat (str, str_size, ".");
+ _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+
+- prev_val = 0;
+ val = 0;
+ leading = 1;
+ for (k = 1; k < len; k++)
+@@ -295,23 +416,24 @@
+ leading = 0;
+
+ /* check for wrap around */
+- val = val << 7;
+- val |= der[len_len + k] & 0x7F;
+-
+- if (val < prev_val)
++ if (INT_LEFT_SHIFT_OVERFLOW (val, 7))
+ return ASN1_DER_ERROR;
+
+- prev_val = val;
++ val = val << 7;
++ val |= der[len_len + k] & 0x7F;
+
+ if (!(der[len_len + k] & 0x80))
+ {
+ _asn1_str_cat (str, str_size, ".");
+ _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+ val = 0;
+- prev_val = 0;
+ leading = 1;
+ }
+ }
++
++ if (INT_ADD_OVERFLOW (len, len_len))
++ return ASN1_DER_ERROR;
++
+ *ret_len = len + len_len;
+
+ return ASN1_SUCCESS;
+@@ -339,6 +461,7 @@
+
+ if (der_len <= 0)
+ return ASN1_GENERIC_ERROR;
++
+ len_byte = asn1_get_length_der (der, der_len, &len_len) - 1;
+ if (len_byte < 0)
+ return ASN1_DER_ERROR;
+@@ -346,11 +469,14 @@
+ *ret_len = len_byte + len_len + 1;
+ *bit_len = len_byte * 8 - der[len_len];
+
+- if (*bit_len <= 0)
++ if (*bit_len < 0)
+ return ASN1_DER_ERROR;
+
+ if (str_size >= len_byte)
+- memcpy (str, der + len_len + 1, len_byte);
++ {
++ if (len_byte > 0 && str)
++ memcpy (str, der + len_len + 1, len_byte);
++ }
+ else
+ {
+ return ASN1_MEM_ERROR;
+@@ -359,12 +485,14 @@
+ return ASN1_SUCCESS;
+ }
+
++
+ static int
+ _asn1_extract_tag_der (ASN1_TYPE node, const unsigned char *der, int der_len,
+ int *ret_len)
+ {
+ ASN1_TYPE p;
+ int counter, len2, len3, is_tag_implicit;
++ int result;
+ unsigned long tag, tag_implicit = 0;
+ unsigned char class, class2, class_implicit = 0;
+
+@@ -392,23 +520,21 @@
+ if (p->type & CONST_EXPLICIT)
+ {
+ if (asn1_get_tag_der
+- (der + counter, der_len - counter, &class, &len2,
++ (der + counter, der_len, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+
+- if (counter + len2 > der_len)
+- return ASN1_DER_ERROR;
++ DECR_LEN(der_len, len2);
+ counter += len2;
+
+ len3 =
+- asn1_get_length_ber (der + counter, der_len - counter,
++ asn1_get_length_ber (der + counter, der_len,
+ &len2);
+ if (len3 < 0)
+ return ASN1_DER_ERROR;
+
++ DECR_LEN(der_len, len2);
+ counter += len2;
+- if (counter > der_len)
+- return ASN1_DER_ERROR;
+
+ if (!is_tag_implicit)
+ {
+@@ -428,9 +554,9 @@
+ if (!is_tag_implicit)
+ {
+ if ((type_field (node->type) == TYPE_SEQUENCE) ||
+- (type_field (node->type) == TYPE_SEQUENCE_OF) ||
+- (type_field (node->type) == TYPE_SET) ||
+- (type_field (node->type) == TYPE_SET_OF))
++ (type_field (node->type) == TYPE_SEQUENCE_OF)
++ || (type_field (node->type) == TYPE_SET)
++ || (type_field (node->type) == TYPE_SET_OF))
+ class2 |= ASN1_CLASS_STRUCTURED;
+ class_implicit = class2;
+ tag_implicit = strtoul ((char *) p->value, NULL, 10);
+@@ -445,11 +571,11 @@
+ if (is_tag_implicit)
+ {
+ if (asn1_get_tag_der
+- (der + counter, der_len - counter, &class, &len2,
++ (der + counter, der_len, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+- if (counter + len2 > der_len)
+- return ASN1_DER_ERROR;
++
++ DECR_LEN(der_len, len2);
+
+ if ((class != class_implicit) || (tag != tag_implicit))
+ {
+@@ -465,87 +591,62 @@
+ }
+ else
+ {
+- if (type_field (node->type) == TYPE_TAG)
++ unsigned type = type_field (node->type);
++ if (type == TYPE_TAG)
+ {
+- counter = 0;
+- *ret_len = counter;
++ *ret_len = 0;
+ return ASN1_SUCCESS;
+ }
+
+ if (asn1_get_tag_der
+- (der + counter, der_len - counter, &class, &len2,
++ (der + counter, der_len, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+
+- if (counter + len2 > der_len)
+- return ASN1_DER_ERROR;
++ DECR_LEN(der_len, len2);
+
+- switch (type_field (node->type))
++ switch (type)
+ {
+ case TYPE_NULL:
+- if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_NULL))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_BOOLEAN:
+- if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_BOOLEAN))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_INTEGER:
+- if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_INTEGER))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_ENUMERATED:
+- if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_ENUMERATED))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_OBJECT_ID:
+- if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_OBJECT_ID))
+- return ASN1_DER_ERROR;
+- break;
+- case TYPE_TIME:
+- if (node->type & CONST_UTC)
+- {
+- if ((class != ASN1_CLASS_UNIVERSAL)
+- || (tag != ASN1_TAG_UTCTime))
+- return ASN1_DER_ERROR;
+- }
+- else
+- {
+- if ((class != ASN1_CLASS_UNIVERSAL)
+- || (tag != ASN1_TAG_GENERALIZEDTime))
+- return ASN1_DER_ERROR;
+- }
+- break;
+- case TYPE_OCTET_STRING:
+- if (((class != ASN1_CLASS_UNIVERSAL)
+- && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED)))
+- || (tag != ASN1_TAG_OCTET_STRING))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_GENERALSTRING:
+- if ((class != ASN1_CLASS_UNIVERSAL)
+- || (tag != ASN1_TAG_GENERALSTRING))
+- return ASN1_DER_ERROR;
+- break;
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ case TYPE_BIT_STRING:
+- if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_BIT_STRING))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_SEQUENCE:
+ case TYPE_SEQUENCE_OF:
+- if ((class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))
+- || (tag != ASN1_TAG_SEQUENCE))
+- return ASN1_DER_ERROR;
+- break;
+ case TYPE_SET:
+ case TYPE_SET_OF:
+- if ((class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))
+- || (tag != ASN1_TAG_SET))
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_UTC_TIME:
++ if ((class != _asn1_tags[type].class)
++ || (tag != _asn1_tags[type].tag))
++ return ASN1_DER_ERROR;
++ break;
++
++ case TYPE_OCTET_STRING:
++ /* OCTET STRING is handled differently to allow
++ * BER encodings (structured class). */
++ if (((class != ASN1_CLASS_UNIVERSAL)
++ && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED)))
++ || (tag != ASN1_TAG_OCTET_STRING))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_ANY:
+ counter -= len2;
+ break;
++ case TYPE_CHOICE:
++ counter -= len2;
++ break;
+ default:
+ return ASN1_DER_ERROR;
+ break;
+@@ -555,6 +656,34 @@
+ counter += len2;
+ *ret_len = counter;
+ return ASN1_SUCCESS;
++
++cleanup:
++ return result;
++}
++
++static int
++extract_tag_der_recursive(ASN1_TYPE node, const unsigned char *der, int der_len,
++ int *ret_len)
++{
++ASN1_TYPE p;
++int ris = ASN1_DER_ERROR;
++
++ if (type_field (node->type) == TYPE_CHOICE)
++ {
++ p = node->down;
++ while (p)
++ {
++ ris = _asn1_extract_tag_der (p, der, der_len, ret_len);
++ if (ris == ASN1_SUCCESS)
++ break;
++ p = p->right;
++ }
++
++ *ret_len = 0;
++ return ris;
++ }
++ else
++ return _asn1_extract_tag_der (node, der, der_len, ret_len);
+ }
+
+ static int
+@@ -616,102 +745,116 @@
+ return ASN1_SUCCESS;
+ }
+
+-static asn1_retCode
++static int
+ _asn1_extract_der_octet (ASN1_TYPE node, const unsigned char *der,
+ int der_len)
+ {
+ int len2, len3;
+- int counter2, counter_end;
++ int counter, counter_end;
++ int result;
+
+ len2 = asn1_get_length_der (der, der_len, &len3);
+ if (len2 < -1)
+ return ASN1_DER_ERROR;
+
+- counter2 = len3 + 1;
++ counter = len3 + 1;
+
+ if (len2 == -1)
+ counter_end = der_len - 2;
+ else
+ counter_end = der_len;
+
+- while (counter2 < counter_end)
++ while (counter < counter_end)
+ {
+- len2 = asn1_get_length_der (der + counter2, der_len - counter2, &len3);
++ len2 = asn1_get_length_der (der + counter, der_len, &len3);
+
+ if (len2 < -1)
+ return ASN1_DER_ERROR;
+
+ if (len2 > 0)
+ {
+- _asn1_append_value (node, der + counter2 + len3, len2);
++ DECR_LEN(der_len, len2+len3);
++ _asn1_append_value (node, der + counter + len3, len2);
+ }
+ else
+ { /* indefinite */
+-
+- len2 =
+- _asn1_extract_der_octet (node, der + counter2 + len3,
+- der_len - counter2 - len3);
+- if (len2 < 0)
+- return len2;
++ DECR_LEN(der_len, len3);
++ result =
++ _asn1_extract_der_octet (node, der + counter + len3,
++ der_len);
++ if (result != ASN1_SUCCESS)
++ return result;
++ DECR_LEN(der_len, len2);
+ }
+
+- counter2 += len2 + len3 + 1;
++ DECR_LEN(der_len, 1);
++ counter += len2 + len3 + 1;
+ }
+
+ return ASN1_SUCCESS;
++
++cleanup:
++ return result;
+ }
+
+-static asn1_retCode
+-_asn1_get_octet_string (const unsigned char *der, ASN1_TYPE node, int *len)
++static int
++_asn1_get_octet_string (ASN1_TYPE node, const unsigned char *der, int der_len, int *len)
+ {
+ int len2, len3, counter, tot_len, indefinite;
++ int result;
+
+ counter = 0;
+
+ if (*(der - 1) & ASN1_CLASS_STRUCTURED)
+ {
+ tot_len = 0;
+- indefinite = asn1_get_length_der (der, *len, &len3);
++ indefinite = asn1_get_length_der (der, der_len, &len3);
+ if (indefinite < -1)
+ return ASN1_DER_ERROR;
+
+ counter += len3;
++ DECR_LEN(der_len, len3);
++
+ if (indefinite >= 0)
+ indefinite += len3;
+
+ while (1)
+ {
+- if (counter > (*len))
++ if (counter > der_len)
+ return ASN1_DER_ERROR;
+
+ if (indefinite == -1)
+ {
+- if ((der[counter] == 0) && (der[counter + 1] == 0))
++ if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
+ {
+ counter += 2;
++ DECR_LEN(der_len, 2);
+ break;
+ }
+ }
+ else if (counter >= indefinite)
+ break;
+
++ DECR_LEN(der_len, 1);
+ if (der[counter] != ASN1_TAG_OCTET_STRING)
+ return ASN1_DER_ERROR;
+
+ counter++;
+
+- len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
++ len2 = asn1_get_length_der (der + counter, der_len, &len3);
+ if (len2 <= 0)
+ return ASN1_DER_ERROR;
+
++ DECR_LEN(der_len, len3 + len2);
+ counter += len3 + len2;
++
+ tot_len += len2;
+ }
+
+ /* copy */
+ if (node)
+ {
+- unsigned char temp[DER_LEN];
++ unsigned char temp[ASN1_MAX_LENGTH_SIZE];
+ int ret;
+
+ len2 = sizeof (temp);
+@@ -719,9 +862,7 @@
+ asn1_length_der (tot_len, temp, &len2);
+ _asn1_set_value (node, temp, len2);
+
+- tot_len += len2;
+-
+- ret = _asn1_extract_der_octet (node, der, *len);
++ ret = _asn1_extract_der_octet (node, der, der_len);
+ if (ret != ASN1_SUCCESS)
+ return ret;
+
+@@ -729,25 +870,29 @@
+ }
+ else
+ { /* NOT STRUCTURED */
+- len2 = asn1_get_length_der (der, *len, &len3);
++ len2 = asn1_get_length_der (der, der_len, &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+- if (len3 + len2 > *len)
+- return ASN1_DER_ERROR;
+- if (node)
+- _asn1_set_value (node, der, len3 + len2);
++
++ DECR_LEN(der_len, len3+len2);
+ counter = len3 + len2;
++ if (node)
++ _asn1_set_value (node, der, counter);
+ }
+
+ *len = counter;
+ return ASN1_SUCCESS;
+
++cleanup:
++ return result;
+ }
+
+-static asn1_retCode
+-_asn1_get_indefinite_length_string (const unsigned char *der, int *len)
++static int
++_asn1_get_indefinite_length_string (const unsigned char *der,
++ int der_len, int *len)
+ {
+ int len2, len3, counter, indefinite;
++ int result;
+ unsigned long tag;
+ unsigned char class;
+
+@@ -755,12 +900,11 @@
+
+ while (1)
+ {
+- if ((*len) < counter)
+- return ASN1_DER_ERROR;
+-
+- if ((der[counter] == 0) && (der[counter + 1] == 0))
++ if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
+ {
+ counter += 2;
++ DECR_LEN(der_len, 2);
++
+ indefinite--;
+ if (indefinite <= 0)
+ break;
+@@ -769,36 +913,55 @@
+ }
+
+ if (asn1_get_tag_der
+- (der + counter, *len - counter, &class, &len2,
++ (der + counter, der_len, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+- if (counter + len2 > *len)
+- return ASN1_DER_ERROR;
++
++ DECR_LEN(der_len, len2);
+ counter += len2;
+- len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
++
++ len2 = asn1_get_length_der (der + counter, der_len, &len3);
+ if (len2 < -1)
+ return ASN1_DER_ERROR;
++
+ if (len2 == -1)
+ {
+ indefinite++;
+ counter += 1;
++ DECR_LEN(der_len, 1);
+ }
+ else
+ {
+ counter += len2 + len3;
++ DECR_LEN(der_len, len2+len3);
+ }
+ }
+
+ *len = counter;
+ return ASN1_SUCCESS;
+
++cleanup:
++ return result;
++}
++
++static void delete_unneeded_choice_fields(ASN1_TYPE p)
++{
++ ASN1_TYPE p2;
++
++ while (p->right)
++ {
++ p2 = p->right;
++ asn1_delete_structure (&p2);
++ }
+ }
+
++
++
+ /**
+ * asn1_der_decoding:
+ * @element: pointer to an ASN1 structure.
+ * @ider: vector that contains the DER encoding.
+- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1].
++ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @errorDescription: null-terminated string contains details when an
+ * error occurred.
+ *
+@@ -806,15 +969,15 @@
+ * string. The structure must just be created with function
+ * asn1_create_element(). If an error occurs during the decoding
+ * procedure, the *@ELEMENT is deleted and set equal to
+- * %ASN1_TYPE_EMPTY.
++ * %NULL.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+- * if @ELEMENT is %ASN1_TYPE_EMPTY, and %ASN1_TAG_ERROR or
++ * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
+ * %ASN1_DER_ERROR if the der encoding doesn't match the structure
+ * name (*@ELEMENT deleted).
+ **/
+-asn1_retCode
+-asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len,
++int
++asn1_der_decoding (ASN1_TYPE * element, const void *ider, int ider_len,
+ char *errorDescription)
+ {
+ ASN1_TYPE node, p, p2, p3;
+@@ -827,13 +990,17 @@
+
+ node = *element;
+
+- if (node == ASN1_TYPE_EMPTY)
++ if (errorDescription != NULL)
++ errorDescription[0] = 0;
++
++ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if (node->type & CONST_OPTION)
+ {
+- asn1_delete_structure (element);
+- return ASN1_GENERIC_ERROR;
++ result = ASN1_GENERIC_ERROR;
++ warn();
++ goto cleanup;
+ }
+
+ counter = 0;
+@@ -847,14 +1014,15 @@
+ if (p->type & CONST_SET)
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ len2 = _asn1_strtol (p2->value, NULL, 10);
+ if (len2 == -1)
+ {
+- if (!der[counter] && !der[counter + 1])
++ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
+ {
+ p = p2;
+ move = UP;
+ counter += 2;
++ DECR_LEN(ider_len, 2);
+ continue;
+ }
+ }
+@@ -866,31 +1034,18 @@
+ }
+ else if (counter > len2)
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ p2 = p2->down;
+ while (p2)
+ {
+ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ {
+- if (type_field (p2->type) != TYPE_CHOICE)
+- ris =
+- _asn1_extract_tag_der (p2, der + counter,
+- len - counter, &len2);
+- else
+- {
+- p3 = p2->down;
+- while (p3)
+- {
+- ris =
+- _asn1_extract_tag_der (p3, der + counter,
+- len - counter, &len2);
+- if (ris == ASN1_SUCCESS)
+- break;
+- p3 = p3->right;
+- }
+- }
++ ris =
++ extract_tag_der_recursive (p2, der + counter,
++ ider_len, &len2);
+ if (ris == ASN1_SUCCESS)
+ {
+ p2->type &= ~CONST_NOT_USED;
+@@ -902,15 +1057,16 @@
+ }
+ if (p2 == NULL)
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ }
+
+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ len2 = _asn1_strtol (p2->value, NULL, 10);
+ if (counter == len2)
+ {
+ if (p->right)
+@@ -933,25 +1089,20 @@
+ {
+ while (p->down)
+ {
+- if (counter < len)
+- ris =
+- _asn1_extract_tag_der (p->down, der + counter,
+- len - counter, &len2);
+- else
+- ris = ASN1_DER_ERROR;
++ ris =
++ extract_tag_der_recursive (p->down, der + counter,
++ ider_len, &len2);
++
+ if (ris == ASN1_SUCCESS)
+ {
+- while (p->down->right)
+- {
+- p2 = p->down->right;
+- asn1_delete_structure (&p2);
+- }
++ delete_unneeded_choice_fields(p->down);
+ break;
+ }
+ else if (ris == ASN1_ERROR_TYPE_ANY)
+ {
+- asn1_delete_structure (element);
+- return ASN1_ERROR_TYPE_ANY;
++ result = ASN1_ERROR_TYPE_ANY;
++ warn();
++ goto cleanup;
+ }
+ else
+ {
+@@ -964,25 +1115,28 @@
+ {
+ if (!(p->type & CONST_OPTION))
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ }
+- else
++ else if (type_field (p->type) != TYPE_CHOICE)
+ p = p->down;
+ }
+
+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ len2 = _asn1_strtol (p2->value, NULL, 10);
++
+ if ((len2 != -1) && (counter > len2))
+ ris = ASN1_TAG_ERROR;
+ }
+
+ if (ris == ASN1_SUCCESS)
+ ris =
+- _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
++ extract_tag_der_recursive (p, der + counter, ider_len, &len2);
++
+ if (ris != ASN1_SUCCESS)
+ {
+ if (p->type & CONST_OPTION)
+@@ -1000,12 +1154,16 @@
+ if (errorDescription != NULL)
+ _asn1_error_description_tag_error (p, errorDescription);
+
+- asn1_delete_structure (element);
+- return ASN1_TAG_ERROR;
++ result = ASN1_TAG_ERROR;
++ warn();
++ goto cleanup;
+ }
+ }
+ else
+- counter += len2;
++ {
++ DECR_LEN(ider_len, len2);
++ counter += len2;
++ }
+ }
+
+ if (ris == ASN1_SUCCESS)
+@@ -1013,19 +1171,24 @@
+ switch (type_field (p->type))
+ {
+ case TYPE_NULL:
++ DECR_LEN(ider_len, 1);
+ if (der[counter])
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ counter++;
+ move = RIGHT;
+ break;
+ case TYPE_BOOLEAN:
++ DECR_LEN(ider_len, 2);
++
+ if (der[counter++] != 1)
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ if (der[counter++] == 0)
+ _asn1_set_value (p, "F", 1);
+@@ -1036,72 +1199,92 @@
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
++ asn1_get_length_der (der + counter, ider_len, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
+- if (len2 + len3 > len - counter)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len3+len2);
++
+ _asn1_set_value (p, der + counter, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_OBJECT_ID:
+ result =
+- _asn1_get_objectid_der (der + counter, len - counter, &len2,
++ _asn1_get_objectid_der (der + counter, ider_len, &len2,
+ temp, sizeof (temp));
+ if (result != ASN1_SUCCESS)
+- {
+- asn1_delete_structure (element);
+- return result;
++ {
++ warn();
++ goto cleanup;
+ }
+
++ DECR_LEN(ider_len, len2);
++
+ tlen = strlen (temp);
+ if (tlen > 0)
+ _asn1_set_value (p, temp, tlen + 1);
++
+ counter += len2;
+ move = RIGHT;
+ break;
+- case TYPE_TIME:
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_UTC_TIME:
+ result =
+- _asn1_get_time_der (der + counter, len - counter, &len2, temp,
++ _asn1_get_time_der (der + counter, ider_len, &len2, temp,
+ sizeof (temp) - 1);
+ if (result != ASN1_SUCCESS)
+- {
+- asn1_delete_structure (element);
+- return result;
+- }
++ {
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len2);
++
+ tlen = strlen (temp);
+ if (tlen > 0)
+- _asn1_set_value (p, temp, tlen + 1);
++ _asn1_set_value (p, temp, tlen);
++
+ counter += len2;
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+- len3 = len - counter;
+- ris = _asn1_get_octet_string (der + counter, p, &len3);
+- if (ris != ASN1_SUCCESS)
+- return ris;
++ result = _asn1_get_octet_string (p, der + counter, ider_len, &len3);
++ if (result != ASN1_SUCCESS)
++ {
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len3);
+ counter += len3;
+ move = RIGHT;
+ break;
+ case TYPE_GENERALSTRING:
+- len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
+- if (len2 < 0)
+- return ASN1_DER_ERROR;
+- if (len3 + len2 > len - counter)
+- return ASN1_DER_ERROR;
+- _asn1_set_value (p, der + counter, len3 + len2);
+- counter += len3 + len2;
+- move = RIGHT;
+- break;
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ case TYPE_BIT_STRING:
+ len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
++ asn1_get_length_der (der + counter, ider_len, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
+- if (len3 + len2 > len - counter)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len3+len2);
++
+ _asn1_set_value (p, der + counter, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+@@ -1110,28 +1293,26 @@
+ case TYPE_SET:
+ if (move == UP)
+ {
+- len2 = strtol (p->value, NULL, 10);
++ len2 = _asn1_strtol (p->value, NULL, 10);
+ _asn1_set_value (p, NULL, 0);
+ if (len2 == -1)
+ { /* indefinite length method */
+- if (len - counter + 1 > 0)
+- {
+- if ((der[counter]) || der[counter + 1])
+- {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
+- }
++ DECR_LEN(ider_len, 2);
++ if ((der[counter]) || der[counter + 1])
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+- else
+- return ASN1_DER_ERROR;
+ counter += 2;
+ }
+ else
+ { /* definite length method */
+ if (len2 != counter)
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ }
+ move = RIGHT;
+@@ -1139,10 +1320,17 @@
+ else
+ { /* move==DOWN || move==RIGHT */
+ len3 =
+- asn1_get_length_der (der + counter, len - counter, &len2);
++ asn1_get_length_der (der + counter, ider_len, &len2);
+ if (len3 < -1)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len2);
+ counter += len2;
++
+ if (len3 > 0)
+ {
+ _asn1_ltostr (counter + len3, temp);
+@@ -1178,12 +1366,10 @@
+ case TYPE_SET_OF:
+ if (move == UP)
+ {
+- len2 = strtol (p->value, NULL, 10);
++ len2 = _asn1_strtol (p->value, NULL, 10);
+ if (len2 == -1)
+ { /* indefinite length method */
+- if ((counter + 2) > len)
+- return ASN1_DER_ERROR;
+- if ((der[counter]) || der[counter + 1])
++ if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
+ {
+ _asn1_append_sequence_set (p);
+ p = p->down;
+@@ -1192,7 +1378,9 @@
+ move = RIGHT;
+ continue;
+ }
++
+ _asn1_set_value (p, NULL, 0);
++ DECR_LEN(ider_len, 2);
+ counter += 2;
+ }
+ else
+@@ -1206,20 +1394,28 @@
+ move = RIGHT;
+ continue;
+ }
++
+ _asn1_set_value (p, NULL, 0);
+ if (len2 != counter)
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ }
+ }
+ else
+ { /* move==DOWN || move==RIGHT */
+ len3 =
+- asn1_get_length_der (der + counter, len - counter, &len2);
++ asn1_get_length_der (der + counter, ider_len, &len2);
+ if (len3 < -1)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len2);
+ counter += len2;
+ if (len3)
+ {
+@@ -1248,56 +1444,76 @@
+ break;
+ case TYPE_ANY:
+ if (asn1_get_tag_der
+- (der + counter, len - counter, &class, &len2,
++ (der + counter, ider_len, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+- return ASN1_DER_ERROR;
+- if (counter + len2 > len)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
++ DECR_LEN(ider_len, len2);
++
+ len4 =
+ asn1_get_length_der (der + counter + len2,
+- len - counter - len2, &len3);
++ ider_len, &len3);
+ if (len4 < -1)
+- return ASN1_DER_ERROR;
+- if (len4 > len - counter + len2 + len3)
+- return ASN1_DER_ERROR;
+- if (len4 != -1)
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++ if (len4 != -1) /* definite */
+ {
+ len2 += len4;
+- _asn1_set_value_octet (p, der + counter, len2 + len3);
++
++ DECR_LEN(ider_len, len4+len3);
++ _asn1_set_value_lv (p, der + counter, len2 + len3);
+ counter += len2 + len3;
+ }
+- else
++ else /* == -1 */
+ { /* indefinite length */
++ ider_len += len2; /* undo DECR_LEN */
++
++ if (counter == 0)
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
+ /* Check indefinite lenth method in an EXPLICIT TAG */
+ if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+ indefinite = 1;
+ else
+ indefinite = 0;
+
+- len2 = len - counter;
+- ris =
+- _asn1_get_indefinite_length_string (der + counter, &len2);
+- if (ris != ASN1_SUCCESS)
++ result =
++ _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
++ if (result != ASN1_SUCCESS)
+ {
+- asn1_delete_structure (element);
+- return ris;
+- }
++ warn();
++ goto cleanup;
++ }
+
+- _asn1_set_value_octet (p, der + counter, len2);
++ DECR_LEN(ider_len, len2);
++ _asn1_set_value_lv (p, der + counter, len2);
+ counter += len2;
+
+ /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+ an indefinite length method. */
+ if (indefinite)
+ {
++ DECR_LEN(ider_len, 2);
+ if (!der[counter] && !der[counter + 1])
+ {
+ counter += 2;
+ }
+ else
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
+ }
+ }
+ }
+@@ -1332,13 +1548,18 @@
+
+ _asn1_delete_not_used (*element);
+
+- if (counter != len)
++ if (ider_len != 0)
+ {
+- asn1_delete_structure (element);
+- return ASN1_DER_ERROR;
++ warn();
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+
+ return ASN1_SUCCESS;
++
++cleanup:
++ asn1_delete_structure (element);
++ return result;
+ }
+
+ #define FOUND 1
+@@ -1360,52 +1581,55 @@
+ * asn1_create_element(). The DER vector must contain the encoding
+ * string of the whole @STRUCTURE. If an error occurs during the
+ * decoding procedure, the *@STRUCTURE is deleted and set equal to
+- * %ASN1_TYPE_EMPTY.
++ * %NULL.
++ *
++ * This function is deprecated and may just be an alias to asn1_der_decoding
++ * in future versions. Use asn1_der_decoding() instead.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+- * if ELEMENT is %ASN1_TYPE_EMPTY or @elementName == NULL, and
++ * if ELEMENT is %NULL or @elementName == NULL, and
+ * %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't
+ * match the structure @structure (*ELEMENT deleted).
+ **/
+-asn1_retCode
++int
+ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName,
+ const void *ider, int len, char *errorDescription)
+ {
+- ASN1_TYPE node, p, p2, p3, nodeFound = ASN1_TYPE_EMPTY;
++ ASN1_TYPE node, p, p2, p3, nodeFound = NULL;
+ char temp[128], currentName[ASN1_MAX_NAME_SIZE * 10], *dot_p, *char_p;
+ int nameLen = ASN1_MAX_NAME_SIZE * 10 - 1, state;
+ int counter, len2, len3, len4, move, ris, tlen;
+- unsigned char class, *temp2;
++ unsigned char class;
+ unsigned long tag;
+ int indefinite, result;
+ const unsigned char *der = ider;
+
+ node = *structure;
+
+- if (node == ASN1_TYPE_EMPTY)
++ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if (elementName == NULL)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_ELEMENT_NOT_FOUND;
++ result = ASN1_ELEMENT_NOT_FOUND;
++ goto cleanup;
+ }
+
+ if (node->type & CONST_OPTION)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_GENERIC_ERROR;
++ result = ASN1_GENERIC_ERROR;
++ goto cleanup;
+ }
+
+- if ((*structure)->name)
++ if ((*structure)->name[0] != 0)
+ { /* Has *structure got a name? */
+ nameLen -= strlen ((*structure)->name);
+ if (nameLen > 0)
+ strcpy (currentName, (*structure)->name);
+ else
+ {
+- asn1_delete_structure (structure);
+- return ASN1_MEM_ERROR;
++ result = ASN1_MEM_ERROR;
++ goto cleanup;
+ }
+ if (!(strcmp (currentName, elementName)))
+ {
+@@ -1444,7 +1668,7 @@
+ if (p->type & CONST_SET)
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ len2 = _asn1_strtol (p2->value, NULL, 10);
+ if (counter == len2)
+ {
+ p = p2;
+@@ -1453,31 +1677,17 @@
+ }
+ else if (counter > len2)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+ p2 = p2->down;
+ while (p2)
+ {
+ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ {
+- if (type_field (p2->type) != TYPE_CHOICE)
+- ris =
+- _asn1_extract_tag_der (p2, der + counter,
++ ris =
++ extract_tag_der_recursive (p2, der + counter,
+ len - counter, &len2);
+- else
+- {
+- p3 = p2->down;
+- while (p3)
+- {
+- ris =
+- _asn1_extract_tag_der (p3, der + counter,
+- len - counter, &len2);
+- if (ris == ASN1_SUCCESS)
+- break;
+- p3 = p3->right;
+- }
+- }
+ if (ris == ASN1_SUCCESS)
+ {
+ p2->type &= ~CONST_NOT_USED;
+@@ -1489,15 +1699,15 @@
+ }
+ if (p2 == NULL)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+ }
+
+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ len2 = _asn1_strtol (p2->value, NULL, 10);
+ if (counter == len2)
+ {
+ if (p->right)
+@@ -1528,17 +1738,13 @@
+ ris = ASN1_DER_ERROR;
+ if (ris == ASN1_SUCCESS)
+ {
+- while (p->down->right)
+- {
+- p2 = p->down->right;
+- asn1_delete_structure (&p2);
+- }
++ delete_unneeded_choice_fields(p->down);
+ break;
+ }
+ else if (ris == ASN1_ERROR_TYPE_ANY)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_ERROR_TYPE_ANY;
++ result = ASN1_ERROR_TYPE_ANY;
++ goto cleanup;
+ }
+ else
+ {
+@@ -1551,18 +1757,18 @@
+ {
+ if (!(p->type & CONST_OPTION))
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+ }
+- else
++ else if (type_field (p->type) != TYPE_CHOICE)
+ p = p->down;
+ }
+
+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ len2 = _asn1_strtol (p2->value, NULL, 10);
+ if (counter > len2)
+ ris = ASN1_TAG_ERROR;
+ }
+@@ -1587,8 +1793,8 @@
+ if (errorDescription != NULL)
+ _asn1_error_description_tag_error (p, errorDescription);
+
+- asn1_delete_structure (structure);
+- return ASN1_TAG_ERROR;
++ result = ASN1_TAG_ERROR;
++ goto cleanup;
+ }
+ }
+ else
+@@ -1602,8 +1808,8 @@
+ case TYPE_NULL:
+ if (der[counter])
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+
+ if (p == nodeFound)
+@@ -1615,8 +1821,8 @@
+ case TYPE_BOOLEAN:
+ if (der[counter++] != 1)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+
+ if (state == FOUND)
+@@ -1640,11 +1846,18 @@
+ len2 =
+ asn1_get_length_der (der + counter, len - counter, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
++
+ if (state == FOUND)
+ {
+ if (len3 + len2 > len - counter)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ _asn1_set_value (p, der + counter, len3 + len2);
+
+ if (p == nodeFound)
+@@ -1660,9 +1873,7 @@
+ _asn1_get_objectid_der (der + counter, len - counter,
+ &len2, temp, sizeof (temp));
+ if (result != ASN1_SUCCESS)
+- {
+- return result;
+- }
++ goto cleanup;
+
+ tlen = strlen (temp);
+
+@@ -1677,24 +1888,25 @@
+ len2 =
+ asn1_get_length_der (der + counter, len - counter, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ len2 += len3;
+ }
+
+ counter += len2;
+ move = RIGHT;
+ break;
+- case TYPE_TIME:
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_UTC_TIME:
+ if (state == FOUND)
+ {
+ result =
+ _asn1_get_time_der (der + counter, len - counter, &len2,
+ temp, sizeof (temp) - 1);
+ if (result != ASN1_SUCCESS)
+- {
+- asn1_delete_structure (structure);
+- return result;
+- }
++ goto cleanup;
+
+ tlen = strlen (temp);
+ if (tlen > 0)
+@@ -1708,7 +1920,10 @@
+ len2 =
+ asn1_get_length_der (der + counter, len - counter, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ len2 += len3;
+ }
+
+@@ -1716,47 +1931,46 @@
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+- len3 = len - counter;
+ if (state == FOUND)
+ {
+- ris = _asn1_get_octet_string (der + counter, p, &len3);
++ result = _asn1_get_octet_string (p, der + counter, len-counter, &len3);
+ if (p == nodeFound)
+ state = EXIT;
+ }
+ else
+- ris = _asn1_get_octet_string (der + counter, NULL, &len3);
++ result = _asn1_get_octet_string (NULL, der + counter, len-counter, &len3);
++
++ if (result != ASN1_SUCCESS)
++ goto cleanup;
+
+- if (ris != ASN1_SUCCESS)
+- return ris;
+ counter += len3;
+ move = RIGHT;
+ break;
+ case TYPE_GENERALSTRING:
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
++ case TYPE_BIT_STRING:
+ len2 =
+ asn1_get_length_der (der + counter, len - counter, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
+- if (state == FOUND)
+ {
+- if (len3 + len2 > len - counter)
+- return ASN1_DER_ERROR;
+- _asn1_set_value (p, der + counter, len3 + len2);
+-
+- if (p == nodeFound)
+- state = EXIT;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+- counter += len3 + len2;
+- move = RIGHT;
+- break;
+- case TYPE_BIT_STRING:
+- len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
+- if (len2 < 0)
+- return ASN1_DER_ERROR;
++
+ if (state == FOUND)
+ {
+ if (len3 + len2 > len - counter)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ _asn1_set_value (p, der + counter, len3 + len2);
+
+ if (p == nodeFound)
+@@ -1769,14 +1983,14 @@
+ case TYPE_SET:
+ if (move == UP)
+ {
+- len2 = strtol (p->value, NULL, 10);
++ len2 = _asn1_strtol (p->value, NULL, 10);
+ _asn1_set_value (p, NULL, 0);
+ if (len2 == -1)
+ { /* indefinite length method */
+ if ((der[counter]) || der[counter + 1])
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+ counter += 2;
+ }
+@@ -1784,8 +1998,8 @@
+ { /* definite length method */
+ if (len2 != counter)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+ }
+ if (p == nodeFound)
+@@ -1800,7 +2014,10 @@
+ asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ counter += len2 + len3;
+ move = RIGHT;
+ }
+@@ -1810,7 +2027,10 @@
+ asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ counter += len2;
+ if (len3 > 0)
+ {
+@@ -1849,7 +2069,7 @@
+ case TYPE_SET_OF:
+ if (move == UP)
+ {
+- len2 = strtol (p->value, NULL, 10);
++ len2 = _asn1_strtol (p->value, NULL, 10);
+ if (len2 > counter)
+ {
+ _asn1_append_sequence_set (p);
+@@ -1862,8 +2082,8 @@
+ _asn1_set_value (p, NULL, 0);
+ if (len2 != counter)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+
+ if (p == nodeFound)
+@@ -1877,7 +2097,10 @@
+ asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ counter += len2 + len3;
+ move = RIGHT;
+ }
+@@ -1887,7 +2110,10 @@
+ asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < 0)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+ counter += len2;
+ if (len3)
+ {
+@@ -1898,7 +2124,8 @@
+ _asn1_set_value (p, temp, tlen + 1);
+ p2 = p->down;
+ while ((type_field (p2->type) == TYPE_TAG)
+- || (type_field (p2->type) == TYPE_SIZE))
++ || (type_field (p2->type) ==
++ TYPE_SIZE))
+ p2 = p2->right;
+ if (p2->right == NULL)
+ _asn1_append_sequence_set (p);
+@@ -1913,23 +2140,32 @@
+ if (asn1_get_tag_der
+ (der + counter, len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
++
+ if (counter + len2 > len)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+
+ len4 =
+ asn1_get_length_der (der + counter + len2,
+ len - counter - len2, &len3);
+ if (len4 < -1)
+- return ASN1_DER_ERROR;
++ {
++ result = ASN1_DER_ERROR;
++ goto cleanup;
++ }
+
+ if (len4 != -1)
+ {
+ len2 += len4;
+ if (state == FOUND)
+ {
+- _asn1_set_value_octet (p, der + counter, len2 + len3);
+- temp2 = NULL;
++ _asn1_set_value_lv (p, der + counter, len2 + len3);
+
+ if (p == nodeFound)
+ state = EXIT;
+@@ -1944,18 +2180,14 @@
+ else
+ indefinite = 0;
+
+- len2 = len - counter;
+- ris =
+- _asn1_get_indefinite_length_string (der + counter, &len2);
+- if (ris != ASN1_SUCCESS)
+- {
+- asn1_delete_structure (structure);
+- return ris;
+- }
++ result =
++ _asn1_get_indefinite_length_string (der + counter, len-counter, &len2);
++ if (result != ASN1_SUCCESS)
++ goto cleanup;
+
+ if (state == FOUND)
+ {
+- _asn1_set_value_octet (p, der + counter, len2);
++ _asn1_set_value_lv (p, der + counter, len2);
+
+ if (p == nodeFound)
+ state = EXIT;
+@@ -1973,8 +2205,8 @@
+ }
+ else
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+ }
+ }
+@@ -2007,8 +2239,8 @@
+ }
+ else
+ {
+- asn1_delete_structure (structure);
+- return ASN1_MEM_ERROR;
++ result = ASN1_MEM_ERROR;
++ goto cleanup;
+ }
+ if (!(strcmp (currentName, elementName)))
+ {
+@@ -2050,8 +2282,8 @@
+ strcat (currentName, p->name);
+ else
+ {
+- asn1_delete_structure (structure);
+- return ASN1_MEM_ERROR;
++ result = ASN1_MEM_ERROR;
++ goto cleanup;
+ }
+
+ if (!(strcmp (currentName, elementName)))
+@@ -2105,18 +2337,22 @@
+
+ if (counter > len)
+ {
+- asn1_delete_structure (structure);
+- return ASN1_DER_ERROR;
++ result = ASN1_DER_ERROR;
++ goto cleanup;
+ }
+
+ return ASN1_SUCCESS;
++
++cleanup:
++ asn1_delete_structure (structure);
++ return result;
+ }
+
+ /**
+ * asn1_der_decoding_startEnd:
+ * @element: pointer to an ASN1 element
+ * @ider: vector that contains the DER encoding.
+- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1]
++ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]
+ * @name_element: an element of NAME structure.
+ * @start: the position of the first byte of NAME_ELEMENT decoding
+ * (@ider[*start])
+@@ -2137,20 +2373,20 @@
+ * element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding
+ * doesn't match the structure ELEMENT.
+ **/
+-asn1_retCode
+-asn1_der_decoding_startEnd (ASN1_TYPE element, const void *ider, int len,
++int
++asn1_der_decoding_startEnd (ASN1_TYPE element, const void *ider, int ider_len,
+ const char *name_element, int *start, int *end)
+ {
+- ASN1_TYPE node, node_to_find, p, p2, p3;
++ ASN1_TYPE node, node_to_find, p, p2;
+ int counter, len2, len3, len4, move, ris;
+ unsigned char class;
+ unsigned long tag;
+- int indefinite;
++ int indefinite, result = ASN1_DER_ERROR;
+ const unsigned char *der = ider;
+
+ node = element;
+
+- if (node == ASN1_TYPE_EMPTY)
++ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ node_to_find = asn1_find_node (node, name_element);
+@@ -2161,7 +2397,7 @@
+ if (node_to_find == node)
+ {
+ *start = 0;
+- *end = len - 1;
++ *end = ider_len - 1;
+ return ASN1_SUCCESS;
+ }
+
+@@ -2173,6 +2409,9 @@
+ p = node;
+ while (1)
+ {
++ if (p == NULL)
++ return ASN1_DER_ERROR;
++
+ ris = ASN1_SUCCESS;
+
+ if (move != UP)
+@@ -2180,14 +2419,21 @@
+ if (p->type & CONST_SET)
+ {
+ p2 = _asn1_find_up (p);
+- len2 = strtol (p2->value, NULL, 10);
++ if (p2 == NULL)
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
++ len2 = _asn1_strtol (p2->value, NULL, 10);
+ if (len2 == -1)
+ {
+- if (!der[counter] && !der[counter + 1])
++ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
+ {
+ p = p2;
+ move = UP;
+ counter += 2;
++ DECR_LEN(ider_len, 2);
+ continue;
+ }
+ }
+@@ -2198,23 +2444,20 @@
+ continue;
+ }
+ else if (counter > len2)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
+ p2 = p2->down;
++
+ while (p2)
+ {
+ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ { /* CONTROLLARE */
+- if (type_field (p2->type) != TYPE_CHOICE)
+- ris =
+- _asn1_extract_tag_der (p2, der + counter,
+- len - counter, &len2);
+- else
+- {
+- p3 = p2->down;
+- ris =
+- _asn1_extract_tag_der (p3, der + counter,
+- len - counter, &len2);
+- }
++ ris =
++ extract_tag_der_recursive (p2, der + counter,
++ ider_len, &len2);
+ if (ris == ASN1_SUCCESS)
+ {
+ p2->type &= ~CONST_NOT_USED;
+@@ -2225,7 +2468,10 @@
+ p2 = p2->right;
+ }
+ if (p2 == NULL)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
+ }
+
+ if (p == node_to_find)
+@@ -2234,8 +2480,14 @@
+ if (type_field (p->type) == TYPE_CHOICE)
+ {
+ p = p->down;
++ if (p == NULL)
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
+ ris =
+- _asn1_extract_tag_der (p, der + counter, len - counter,
++ _asn1_extract_tag_der (p, der + counter, ider_len,
+ &len2);
+ if (p == node_to_find)
+ *start = counter;
+@@ -2243,7 +2495,7 @@
+
+ if (ris == ASN1_SUCCESS)
+ ris =
+- _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
++ _asn1_extract_tag_der (p, der + counter, ider_len, &len2);
+ if (ris != ASN1_SUCCESS)
+ {
+ if (p->type & CONST_OPTION)
+@@ -2257,11 +2509,15 @@
+ }
+ else
+ {
++ warn();
+ return ASN1_TAG_ERROR;
+ }
+ }
+ else
+- counter += len2;
++ {
++ DECR_LEN(ider_len, len2);
++ counter += len2;
++ }
+ }
+
+ if (ris == ASN1_SUCCESS)
+@@ -2269,63 +2525,63 @@
+ switch (type_field (p->type))
+ {
+ case TYPE_NULL:
++ DECR_LEN(ider_len, 1);
++
+ if (der[counter])
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
+ counter++;
+ move = RIGHT;
+ break;
+ case TYPE_BOOLEAN:
+- if (der[counter++] != 1)
+- return ASN1_DER_ERROR;
+- counter++;
+- move = RIGHT;
+- break;
+- case TYPE_INTEGER:
+- case TYPE_ENUMERATED:
+- len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
+- if (len2 < 0)
+- return ASN1_DER_ERROR;
+- counter += len3 + len2;
+- move = RIGHT;
+- break;
+- case TYPE_OBJECT_ID:
+- len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
+- if (len2 < 0)
+- return ASN1_DER_ERROR;
+- counter += len2 + len3;
+- move = RIGHT;
+- break;
+- case TYPE_TIME:
+- len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
+- if (len2 < 0)
+- return ASN1_DER_ERROR;
+- counter += len2 + len3;
++ DECR_LEN(ider_len, 2);
++
++ if (der[counter] != 1)
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
++ counter += 2;
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+- len3 = len - counter;
+- ris = _asn1_get_octet_string (der + counter, NULL, &len3);
++ ris = _asn1_get_octet_string (NULL, der + counter, ider_len, &len3);
+ if (ris != ASN1_SUCCESS)
+- return ris;
++ {
++ warn();
++ return ris;
++ }
++ DECR_LEN(ider_len, len3);
+ counter += len3;
+ move = RIGHT;
+ break;
++ case TYPE_UTC_TIME:
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_OBJECT_ID:
++ case TYPE_INTEGER:
++ case TYPE_ENUMERATED:
+ case TYPE_GENERALSTRING:
+- len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
+- if (len2 < 0)
+- return ASN1_DER_ERROR;
+- counter += len3 + len2;
+- move = RIGHT;
+- break;
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ case TYPE_BIT_STRING:
+ len2 =
+- asn1_get_length_der (der + counter, len - counter, &len3);
++ asn1_get_length_der (der + counter, ider_len, &len3);
+ if (len2 < 0)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
++ DECR_LEN(ider_len, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+@@ -2334,10 +2590,16 @@
+ if (move != UP)
+ {
+ len3 =
+- asn1_get_length_der (der + counter, len - counter, &len2);
++ asn1_get_length_der (der + counter, ider_len, &len2);
+ if (len3 < -1)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
++ DECR_LEN(ider_len, len2);
+ counter += len2;
++
+ if (len3 == 0)
+ move = RIGHT;
+ else
+@@ -2345,8 +2607,11 @@
+ }
+ else
+ {
+- if (!der[counter] && !der[counter + 1]) /* indefinite length method */
+- counter += 2;
++ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */
++ {
++ counter += 2;
++ DECR_LEN(ider_len, 2);
++ }
+ move = RIGHT;
+ }
+ break;
+@@ -2355,13 +2620,26 @@
+ if (move != UP)
+ {
+ len3 =
+- asn1_get_length_der (der + counter, len - counter, &len2);
++ asn1_get_length_der (der + counter, ider_len, &len2);
+ if (len3 < -1)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
++ DECR_LEN(ider_len, len2);
+ counter += len2;
+- if ((len3 == -1) && !der[counter] && !der[counter + 1])
+- counter += 2;
+- else if (len3)
++
++ if (len3 == -1)
++ {
++ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
++ {
++ DECR_LEN(ider_len, 2);
++ counter += 2;
++ }
++ }
++
++ if (len3)
+ {
+ p2 = p->down;
+ while ((type_field (p2->type) == TYPE_TAG) ||
+@@ -2372,52 +2650,79 @@
+ }
+ else
+ {
+- if (!der[counter] && !der[counter + 1]) /* indefinite length method */
+- counter += 2;
++ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */
++ {
++ DECR_LEN(ider_len, 2);
++ counter += 2;
++ }
+ }
+ move = RIGHT;
+ break;
+ case TYPE_ANY:
+ if (asn1_get_tag_der
+- (der + counter, len - counter, &class, &len2,
++ (der + counter, ider_len, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+- return ASN1_DER_ERROR;
+- if (counter + len2 > len)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
++
++ DECR_LEN(ider_len, len2);
+
+ len4 =
+ asn1_get_length_der (der + counter + len2,
+- len - counter - len2, &len3);
++ ider_len, &len3);
+ if (len4 < -1)
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
+
+ if (len4 != -1)
+ {
+- counter += len2 + len4 + len3;
++ DECR_LEN(ider_len, len3 + len4);
++ counter += len2 + len3 + len4;
+ }
+ else
+ { /* indefinite length */
+ /* Check indefinite lenth method in an EXPLICIT TAG */
++ ider_len += len2; /* undo DECR_LEN */
++
++ if (counter == 0)
++ {
++ result = ASN1_DER_ERROR;
++ warn();
++ goto cleanup;
++ }
++
+ if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+ indefinite = 1;
+ else
+ indefinite = 0;
+
+- len2 = len - counter;
+ ris =
+- _asn1_get_indefinite_length_string (der + counter, &len2);
++ _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
+ if (ris != ASN1_SUCCESS)
+- return ris;
++ {
++ warn();
++ return ris;
++ }
+ counter += len2;
++ DECR_LEN(ider_len, len2);
+
+ /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+ an indefinite length method. */
+ if (indefinite)
+ {
++ DECR_LEN(ider_len, 2);
++
+ if (!der[counter] && !der[counter + 1])
+ counter += 2;
+ else
+- return ASN1_DER_ERROR;
++ {
++ warn();
++ return ASN1_DER_ERROR;
++ }
+ }
+ }
+ move = RIGHT;
+@@ -2455,7 +2760,11 @@
+ p = _asn1_find_up (p);
+ }
+
++ warn();
+ return ASN1_ELEMENT_NOT_FOUND;
++
++cleanup:
++ return result;
+ }
+
+ /**
+@@ -2474,21 +2783,21 @@
+ * problem in OBJECT_ID -> TYPE association, or other error codes
+ * depending on DER decoding.
+ **/
+-asn1_retCode
++int
+ asn1_expand_any_defined_by (ASN1_TYPE definitions, ASN1_TYPE * element)
+ {
+- char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1],
++ char name[2 * ASN1_MAX_NAME_SIZE + 1],
+ value[ASN1_MAX_NAME_SIZE];
+- asn1_retCode retCode = ASN1_SUCCESS, result;
++ int retCode = ASN1_SUCCESS, result;
+ int len, len2, len3;
+- ASN1_TYPE p, p2, p3, aux = ASN1_TYPE_EMPTY;
++ ASN1_TYPE p, p2, p3, aux = NULL;
+ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
++ const char *definitionsName;
+
+- if ((definitions == ASN1_TYPE_EMPTY) || (*element == ASN1_TYPE_EMPTY))
++ if ((definitions == NULL) || (*element == NULL))
+ return ASN1_ELEMENT_NOT_FOUND;
+
+- strcpy (definitionsName, definitions->name);
+- strcat (definitionsName, ".");
++ definitionsName = definitions->name;
+
+ p = *element;
+ while (p)
+@@ -2521,7 +2830,7 @@
+ p3 = p3->down;
+ while (p3)
+ {
+- if ((p3->name) && !(strcmp (p3->name, p2->name)))
++ if (!(strcmp (p3->name, p2->name)))
+ break;
+ p3 = p3->right;
+ }
+@@ -2543,13 +2852,13 @@
+
+ while (p3)
+ {
+- if ((p3->name) && !(strcmp (p3->name, p2->name)))
++ if (!(strcmp (p3->name, p2->name)))
+ break;
+ p3 = p3->right;
+ }
+
+- if ((!p3) || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+- (p3->value == NULL))
++ if ((!p3) || (type_field (p3->type) != TYPE_OBJECT_ID)
++ || (p3->value == NULL))
+ {
+ retCode = ASN1_ERROR_TYPE_ANY;
+ break;
+@@ -2563,15 +2872,14 @@
+ if ((type_field (p2->type) == TYPE_OBJECT_ID) &&
+ (p2->type & CONST_ASSIGN))
+ {
+- strcpy (name, definitionsName);
+- strcat (name, p2->name);
++ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name);
+
+ len = ASN1_MAX_NAME_SIZE;
+ result =
+ asn1_read_value (definitions, name, value, &len);
+
+ if ((result == ASN1_SUCCESS)
+- && (!strcmp (p3->value, value)))
++ && (!_asn1_strcmp (p3->value, value)))
+ {
+ p2 = p2->right; /* pointer to the structure to
+ use for expansion */
+@@ -2580,14 +2888,13 @@
+
+ if (p2)
+ {
+- strcpy (name, definitionsName);
+- strcat (name, p2->name);
++ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name);
+
+ result =
+ asn1_create_element (definitions, name, &aux);
+ if (result == ASN1_SUCCESS)
+ {
+- _asn1_set_name (aux, p->name);
++ _asn1_cpy_name (aux, p);
+ len2 =
+ asn1_get_length_der (p->value,
+ p->value_len, &len3);
+@@ -2608,7 +2915,7 @@
+ if (result == ASN1_SUCCESS)
+ {
+ p = aux;
+- aux = ASN1_TYPE_EMPTY;
++ aux = NULL;
+ break;
+ }
+ else
+@@ -2704,22 +3011,22 @@
+ * %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to
+ * use for expansion, or other errors depending on DER decoding.
+ **/
+-asn1_retCode
++int
+ asn1_expand_octet_string (ASN1_TYPE definitions, ASN1_TYPE * element,
+ const char *octetName, const char *objectName)
+ {
+ char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE];
+- asn1_retCode retCode = ASN1_SUCCESS, result;
++ int retCode = ASN1_SUCCESS, result;
+ int len, len2, len3;
+- ASN1_TYPE p2, aux = ASN1_TYPE_EMPTY;
+- ASN1_TYPE octetNode = ASN1_TYPE_EMPTY, objectNode = ASN1_TYPE_EMPTY;
++ ASN1_TYPE p2, aux = NULL;
++ ASN1_TYPE octetNode = NULL, objectNode = NULL;
+ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+
+- if ((definitions == ASN1_TYPE_EMPTY) || (*element == ASN1_TYPE_EMPTY))
++ if ((definitions == NULL) || (*element == NULL))
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ octetNode = asn1_find_node (*element, octetName);
+- if (octetNode == ASN1_TYPE_EMPTY)
++ if (octetNode == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+ if (type_field (octetNode->type) != TYPE_OCTET_STRING)
+ return ASN1_ELEMENT_NOT_FOUND;
+@@ -2727,7 +3034,7 @@
+ return ASN1_VALUE_NOT_FOUND;
+
+ objectNode = asn1_find_node (*element, objectName);
+- if (objectNode == ASN1_TYPE_EMPTY)
++ if (objectNode == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if (type_field (objectNode->type) != TYPE_OBJECT_ID)
+@@ -2752,7 +3059,7 @@
+ result = asn1_read_value (definitions, name, value, &len);
+
+ if ((result == ASN1_SUCCESS)
+- && (!strcmp (objectNode->value, value)))
++ && (!_asn1_strcmp (objectNode->value, value)))
+ {
+
+ p2 = p2->right; /* pointer to the structure to
+@@ -2769,7 +3076,7 @@
+ result = asn1_create_element (definitions, name, &aux);
+ if (result == ASN1_SUCCESS)
+ {
+- _asn1_set_name (aux, octetNode->name);
++ _asn1_cpy_name (aux, octetNode);
+ len2 =
+ asn1_get_length_der (octetNode->value,
+ octetNode->value_len, &len3);
+@@ -2788,7 +3095,7 @@
+ result = asn1_delete_structure (&octetNode);
+ if (result == ASN1_SUCCESS)
+ {
+- aux = ASN1_TYPE_EMPTY;
++ aux = NULL;
+ break;
+ }
+ else
+@@ -2827,3 +3134,61 @@
+
+ return retCode;
+ }
++
++/**
++ * asn1_decode_simple_der:
++ * @etype: The type of the string to be encoded (TYPE_)
++ * @der: the encoded string
++ * @der_len: the bytes of the encoded string
++ * @str: a pointer to the data
++ * @str_len: the length of the data
++ *
++ * Decodes a simple DER encoded type (e.g. a string, which is not constructed).
++ * The output is a pointer inside the @der.
++ *
++ * Returns: %ASN1_SUCCESS if successful or an error value.
++ **/
++int
++asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
++ unsigned int der_len, const unsigned char **str,
++ unsigned int *str_len)
++{
++ int tag_len, len_len;
++ const unsigned char *p;
++ unsigned char class;
++ unsigned long tag;
++ long ret;
++
++ if (der == NULL || der_len == 0)
++ return ASN1_VALUE_NOT_VALID;
++
++ if (ETYPE_OK (etype) == 0)
++ return ASN1_VALUE_NOT_VALID;
++
++ /* doesn't handle constructed classes */
++ if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
++ return ASN1_VALUE_NOT_VALID;
++
++ p = der;
++ ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
++ if (ret != ASN1_SUCCESS)
++ return ret;
++
++ if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype))
++ return ASN1_DER_ERROR;
++
++ p += tag_len;
++ der_len -= tag_len;
++
++ ret = asn1_get_length_der (p, der_len, &len_len);
++ if (ret < 0)
++ return ASN1_DER_ERROR;
++
++ p += len_len;
++ der_len -= len_len;
++
++ *str_len = ret;
++ *str = p;
++
++ return ASN1_SUCCESS;
++}
+--- ORIGINAL/./lib/structure.c 2015-07-14 18:28:22.916996471 -0700
++++ libtasn1-2.8/./lib/structure.c 2015-07-14 18:45:02.684513241 -0700
+@@ -38,7 +38,7 @@
+
+
+ /******************************************************/
+-/* Function : _asn1_add_node_only */
++/* Function : _asn1_add_single_node */
+ /* Description: creates a new NODE_ASN element. */
+ /* Parameters: */
+ /* type: type of the new element (see TYPE_ */
+@@ -46,11 +46,11 @@
+ /* Return: pointer to the new element. */
+ /******************************************************/
+ ASN1_TYPE
+-_asn1_add_node_only (unsigned int type)
++_asn1_add_single_node (unsigned int type)
+ {
+ ASN1_TYPE punt;
+
+- punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
++ punt = calloc (1, sizeof (struct node_asn_struct));
+ if (punt == NULL)
+ return NULL;
+
+@@ -78,7 +78,7 @@
+ }
+
+
+-asn1_retCode
++int
+ _asn1_create_static_structure (ASN1_TYPE pointer, char *output_file_name,
+ char *vector_name)
+ {
+@@ -105,7 +105,7 @@
+ {
+ fprintf (file, " { ");
+
+- if (p->name)
++ if (p->name[0] != 0)
+ fprintf (file, "\"%s\", ", p->name);
+ else
+ fprintf (file, "NULL, ");
+@@ -168,28 +168,24 @@
+ * Creates the structures needed to manage the ASN.1 definitions.
+ * @array is a vector created by asn1_parser2array().
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Structure created correctly.
+- *
+- * %ASN1_ELEMENT_NOT_EMPTY: *@definitions not ASN1_TYPE_EMPTY.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined (see @errorDescription for more information).
+- *
+- * %ASN1_ARRAY_ERROR: The array pointed by @array is wrong.
++ * Returns: %ASN1_SUCCESS if structure was created correctly,
++ * %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL,
++ * %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier
++ * that is not defined (see @errorDescription for more information),
++ * %ASN1_ARRAY_ERROR if the array pointed by @array is wrong.
+ **/
+-asn1_retCode
++int
+ asn1_array2tree (const ASN1_ARRAY_TYPE * array, ASN1_TYPE * definitions,
+ char *errorDescription)
+ {
+ ASN1_TYPE p, p_last = NULL;
+ unsigned long k;
+ int move;
+- asn1_retCode result;
++ int result;
++ unsigned int type;
+
+
+- if (*definitions != ASN1_TYPE_EMPTY)
++ if (*definitions != NULL)
+ return ASN1_ELEMENT_NOT_EMPTY;
+
+ move = UP;
+@@ -197,7 +193,9 @@
+ k = 0;
+ while (array[k].value || array[k].type || array[k].name)
+ {
+- p = _asn1_add_node (array[k].type & (~CONST_DOWN));
++ type = convert_old_type (array[k].type);
++
++ p = _asn1_add_static_node (type & (~CONST_DOWN));
+ if (array[k].name)
+ _asn1_set_name (p, array[k].name);
+ if (array[k].value)
+@@ -213,9 +211,9 @@
+
+ p_last = p;
+
+- if (array[k].type & CONST_DOWN)
++ if (type & CONST_DOWN)
+ move = DOWN;
+- else if (array[k].type & CONST_RIGHT)
++ else if (type & CONST_RIGHT)
+ move = RIGHT;
+ else
+ {
+@@ -269,7 +267,7 @@
+ if (result != ASN1_SUCCESS)
+ {
+ _asn1_delete_list_and_nodes ();
+- *definitions = ASN1_TYPE_EMPTY;
++ *definitions = NULL;
+ }
+ else
+ _asn1_delete_list ();
+@@ -282,20 +280,34 @@
+ * @structure: pointer to the structure that you want to delete.
+ *
+ * Deletes the structure *@structure. At the end, *@structure is set
+- * to ASN1_TYPE_EMPTY.
++ * to NULL.
+ *
+- * Returns:
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ * *@structure was NULL.
++ **/
++int
++asn1_delete_structure (ASN1_TYPE * structure)
++{
++ return asn1_delete_structure2(structure, 0);
++}
++
++/**
++ * asn1_delete_structure2:
++ * @structure: pointer to the structure that you want to delete.
++ * @flags: additional flags (see %ASN1_DELETE_FLAG)
+ *
+- * %ASN1_SUCCESS: Everything OK.
++ * Deletes the structure *@structure. At the end, *@structure is set
++ * to NULL.
+ *
+- * %ASN1_ELEMENT_NOT_FOUND: *@structure was ASN1_TYPE_EMPTY.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ * *@structure was NULL.
+ **/
+-asn1_retCode
+-asn1_delete_structure (ASN1_TYPE * structure)
++int
++asn1_delete_structure2 (ASN1_TYPE * structure, unsigned int flags)
+ {
+ ASN1_TYPE p, p2, p3;
+
+- if (*structure == ASN1_TYPE_EMPTY)
++ if (*structure == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = *structure;
+@@ -312,7 +324,7 @@
+ {
+ p3 = _asn1_find_up (p);
+ _asn1_set_down (p3, p2);
+- _asn1_remove_node (p);
++ _asn1_remove_node (p, flags);
+ p = p3;
+ }
+ else
+@@ -331,13 +343,13 @@
+ }
+ else
+ _asn1_set_right (p3, p2);
+- _asn1_remove_node (p);
++ _asn1_remove_node (p, flags);
+ p = NULL;
+ }
+ }
+ }
+
+- *structure = ASN1_TYPE_EMPTY;
++ *structure = NULL;
+ return ASN1_SUCCESS;
+ }
+
+@@ -351,20 +363,17 @@
+ *
+ * Deletes the element named *@element_name inside *@structure.
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Everything OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: The name element was not found.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ * the @element_name was not found.
+ **/
+-asn1_retCode
++int
+ asn1_delete_element (ASN1_TYPE structure, const char *element_name)
+ {
+ ASN1_TYPE p2, p3, source_node;
+
+ source_node = asn1_find_node (structure, element_name);
+
+- if (source_node == ASN1_TYPE_EMPTY)
++ if (source_node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p2 = source_node->right;
+@@ -392,7 +401,7 @@
+ if (source_node == NULL)
+ return NULL;
+
+- dest_node = _asn1_add_node_only (source_node->type);
++ dest_node = _asn1_add_single_node (source_node->type);
+
+ p_s = source_node;
+ p_d = dest_node;
+@@ -403,45 +412,34 @@
+ {
+ if (move != UP)
+ {
+- if (p_s->name)
+- _asn1_set_name (p_d, p_s->name);
++ if (p_s->name[0] != 0)
++ _asn1_cpy_name (p_d, p_s);
+ if (p_s->value)
+ _asn1_set_value (p_d, p_s->value, p_s->value_len);
+- move = DOWN;
+- }
+- else
+- move = RIGHT;
+-
+- if (move == DOWN)
+- {
+ if (p_s->down)
+ {
+ p_s = p_s->down;
+ p_d_prev = p_d;
+- p_d = _asn1_add_node_only (p_s->type);
++ p_d = _asn1_add_single_node (p_s->type);
+ _asn1_set_down (p_d_prev, p_d);
++ continue;
+ }
+- else
+- move = RIGHT;
+ }
+
+ if (p_s == source_node)
+ break;
+
+- if (move == RIGHT)
++ if (p_s->right)
+ {
+- if (p_s->right)
+- {
+- p_s = p_s->right;
+- p_d_prev = p_d;
+- p_d = _asn1_add_node_only (p_s->type);
+- _asn1_set_right (p_d_prev, p_d);
+- }
+- else
+- move = UP;
++ move = RIGHT;
++ p_s = p_s->right;
++ p_d_prev = p_d;
++ p_d = _asn1_add_single_node (p_s->type);
++ _asn1_set_right (p_d_prev, p_d);
+ }
+- if (move == UP)
++ else
+ {
++ move = UP;
+ p_s = _asn1_find_up (p_s);
+ p_d = _asn1_find_up (p_d);
+ }
+@@ -464,7 +462,7 @@
+ }
+
+
+-static asn1_retCode
++static int
+ _asn1_type_choice_config (ASN1_TYPE node)
+ {
+ ASN1_TYPE p, p2, p3, p4;
+@@ -480,7 +478,8 @@
+ {
+ if (move != UP)
+ {
+- if ((type_field (p->type) == TYPE_CHOICE) && (p->type & CONST_TAG))
++ if ((type_field (p->type) == TYPE_CHOICE)
++ && (p->type & CONST_TAG))
+ {
+ p2 = p->down;
+ while (p2)
+@@ -493,8 +492,8 @@
+ {
+ if (type_field (p3->type) == TYPE_TAG)
+ {
+- p4 = _asn1_add_node_only (p3->type);
+- tlen = strlen (p3->value);
++ p4 = _asn1_add_single_node (p3->type);
++ tlen = _asn1_strlen (p3->value);
+ if (tlen > 0)
+ _asn1_set_value (p4, p3->value, tlen + 1);
+ _asn1_set_right (p4, p2->down);
+@@ -549,7 +548,7 @@
+ }
+
+
+-static asn1_retCode
++static int
+ _asn1_expand_identifier (ASN1_TYPE * node, ASN1_TYPE root)
+ {
+ ASN1_TYPE p, p2, p3;
+@@ -568,15 +567,13 @@
+ {
+ if (type_field (p->type) == TYPE_IDENTIFIER)
+ {
+- _asn1_str_cpy (name2, sizeof (name2), root->name);
+- _asn1_str_cat (name2, sizeof (name2), ".");
+- _asn1_str_cat (name2, sizeof (name2), p->value);
++ snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value);
+ p2 = _asn1_copy_structure2 (root, name2);
+ if (p2 == NULL)
+ {
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ }
+- _asn1_set_name (p2, p->name);
++ _asn1_cpy_name (p2, p);
+ p2->right = p->right;
+ p2->left = p->left;
+ if (p->right)
+@@ -619,7 +616,7 @@
+
+ if (p == *node)
+ *node = p2;
+- _asn1_remove_node (p);
++ _asn1_remove_node (p, 0);
+ p = p2;
+ move = DOWN;
+ continue;
+@@ -670,13 +667,10 @@
+ *
+ * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Creation OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
++ * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
++ * @source_name is not known.
+ **/
+-asn1_retCode
++int
+ asn1_create_element (ASN1_TYPE definitions, const char *source_name,
+ ASN1_TYPE * element)
+ {
+@@ -734,7 +728,7 @@
+ for (k = 0; k < indent; k++)
+ fprintf (out, " ");
+ fprintf (out, "name:");
+- if (p->name)
++ if (p->name[0] != 0)
+ fprintf (out, "%s ", p->name);
+ else
+ fprintf (out, "NULL ");
+@@ -751,7 +745,7 @@
+ for (k = 0; k < indent; k++)
+ fprintf (out, " ");
+ fprintf (out, "name:");
+- if (p->name)
++ if (p->name[0] != 0)
+ fprintf (out, "%s ", p->name);
+ else
+ fprintf (out, "NULL ");
+@@ -760,7 +754,8 @@
+
+ if (mode != ASN1_PRINT_NAME)
+ {
+- switch (type_field (p->type))
++ unsigned type = type_field (p->type);
++ switch (type)
+ {
+ case TYPE_CONSTANT:
+ if (mode == ASN1_PRINT_ALL)
+@@ -777,57 +772,21 @@
+ case TYPE_DEFAULT:
+ fprintf (out, "type:DEFAULT");
+ break;
+- case TYPE_NULL:
+- fprintf (out, "type:NULL");
+- break;
+ case TYPE_IDENTIFIER:
+ fprintf (out, "type:IDENTIFIER");
+ break;
+- case TYPE_INTEGER:
+- fprintf (out, "type:INTEGER");
+- break;
+- case TYPE_ENUMERATED:
+- fprintf (out, "type:ENUMERATED");
+- break;
+- case TYPE_TIME:
+- fprintf (out, "type:TIME");
+- break;
+- case TYPE_BOOLEAN:
+- fprintf (out, "type:BOOLEAN");
+- break;
+- case TYPE_SEQUENCE:
+- fprintf (out, "type:SEQUENCE");
+- break;
+- case TYPE_BIT_STRING:
+- fprintf (out, "type:BIT_STR");
+- break;
+- case TYPE_OCTET_STRING:
+- fprintf (out, "type:OCT_STR");
+- break;
+- case TYPE_GENERALSTRING:
+- fprintf (out, "type:GENERALSTRING");
+- break;
+- case TYPE_SEQUENCE_OF:
+- fprintf (out, "type:SEQ_OF");
+- break;
+- case TYPE_OBJECT_ID:
+- fprintf (out, "type:OBJ_ID");
+- break;
+ case TYPE_ANY:
+ fprintf (out, "type:ANY");
+ break;
+- case TYPE_SET:
+- fprintf (out, "type:SET");
+- break;
+- case TYPE_SET_OF:
+- fprintf (out, "type:SET_OF");
+- break;
+ case TYPE_CHOICE:
+ fprintf (out, "type:CHOICE");
+ break;
+ case TYPE_DEFINITIONS:
+ fprintf (out, "type:DEFINITIONS");
+ break;
++ CASE_HANDLED_ETYPES:
++ fprintf (out, "%s", _asn1_tags[type].desc);
++ break;
+ default:
+ break;
+ }
+@@ -886,10 +845,6 @@
+ fprintf (out, "%02x", (p->value)[k + len2]);
+ }
+ break;
+- case TYPE_TIME:
+- if (p->value)
+- fprintf (out, " value:%s", p->value);
+- break;
+ case TYPE_BOOLEAN:
+ if (p->value)
+ {
+@@ -913,7 +868,23 @@
+ }
+ }
+ break;
+- case TYPE_OCTET_STRING:
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_UTC_TIME:
++ if (p->value)
++ {
++ fprintf (out, " value:");
++ for (k = 0; k < p->value_len; k++)
++ fprintf (out, "%c", (p->value)[k]);
++ }
++ break;
++ case TYPE_GENERALSTRING:
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ if (p->value)
+ {
+ len2 = -1;
+@@ -921,10 +892,11 @@
+ fprintf (out, " value:");
+ if (len > 0)
+ for (k = 0; k < len; k++)
+- fprintf (out, "%02x", (p->value)[k + len2]);
++ fprintf (out, "%c", (p->value)[k + len2]);
+ }
+ break;
+- case TYPE_GENERALSTRING:
++ case TYPE_BMP_STRING:
++ case TYPE_OCTET_STRING:
+ if (p->value)
+ {
+ len2 = -1;
+@@ -1072,15 +1044,10 @@
+ * Counts the number of elements of a sub-structure called NAME with
+ * names equal to "?1","?2", ...
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Creation OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: NAME isn't known.
+- *
+- * %ASN1_GENERIC_ERROR: Pointer num equal to NULL.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
+ **/
+-asn1_retCode
++int
+ asn1_number_of_elements (ASN1_TYPE element, const char *name, int *num)
+ {
+ ASN1_TYPE node, p;
+@@ -1098,7 +1065,7 @@
+
+ while (p)
+ {
+- if ((p->name) && (p->name[0] == '?'))
++ if (p->name[0] == '?')
+ (*num)++;
+ p = p->right;
+ }
+@@ -1121,18 +1088,17 @@
+ const char *
+ asn1_find_structure_from_oid (ASN1_TYPE definitions, const char *oidValue)
+ {
+- char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
++ char name[2 * ASN1_MAX_NAME_SIZE + 1];
+ char value[ASN1_MAX_NAME_SIZE];
+ ASN1_TYPE p;
+ int len;
+- asn1_retCode result;
++ int result;
++ const char *definitionsName;
+
+- if ((definitions == ASN1_TYPE_EMPTY) || (oidValue == NULL))
++ if ((definitions == NULL) || (oidValue == NULL))
+ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
+
+-
+- strcpy (definitionsName, definitions->name);
+- strcat (definitionsName, ".");
++ definitionsName = definitions->name;
+
+ /* search the OBJECT_ID into definitions */
+ p = definitions->down;
+@@ -1141,8 +1107,7 @@
+ if ((type_field (p->type) == TYPE_OBJECT_ID) &&
+ (p->type & CONST_ASSIGN))
+ {
+- strcpy (name, definitionsName);
+- strcat (name, p->name);
++ snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name);
+
+ len = ASN1_MAX_NAME_SIZE;
+ result = asn1_read_value (definitions, name, value, &len);
+@@ -1171,9 +1136,9 @@
+ *
+ * Create a deep copy of a ASN1_TYPE variable.
+ *
+- * Return value: Return %ASN1_SUCCESS on success.
++ * Returns: Return %ASN1_SUCCESS on success.
+ **/
+-asn1_retCode
++int
+ asn1_copy_node (ASN1_TYPE dst, const char *dst_name,
+ ASN1_TYPE src, const char *src_name)
+ {
+@@ -1189,27 +1154,27 @@
+ if (result != ASN1_MEM_ERROR)
+ return result;
+
+- data = _asn1_malloc (size);
++ data = malloc (size);
+ if (data == NULL)
+ return ASN1_MEM_ERROR;
+
+ result = asn1_der_coding (src, src_name, data, &size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+- _asn1_free (data);
++ free (data);
+ return result;
+ }
+
+ dst_node = asn1_find_node (dst, dst_name);
+ if (dst_node == NULL)
+ {
+- _asn1_free (data);
++ free (data);
+ return ASN1_ELEMENT_NOT_FOUND;
+ }
+
+ result = asn1_der_decoding (&dst_node, data, size, NULL);
+
+- _asn1_free (data);
++ free (data);
+
+ return result;
+ }
+--- ORIGINAL/./lib/coding.c 2015-07-14 18:28:22.911826177 -0700
++++ libtasn1-2.8/./lib/coding.c 2015-07-14 18:45:02.651262664 -0700
+@@ -31,8 +31,19 @@
+ #include "parser_aux.h"
+ #include <gstr.h>
+ #include "element.h"
++/*#include "minmax.h"*/
+ #include <structure.h>
+
++/* MAX(a,b) returns the maximum of A and B. */
++#ifndef MAX
++# define MAX(a,b) ((a) > (b) ? (a) : (b))
++#endif
++
++/* MIN(a,b) returns the minimum of A and B. */
++#ifndef MIN
++# define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++
+ #define MAX_TAG_LEN 16
+
+ /******************************************************/
+@@ -62,24 +73,30 @@
+ /**
+ * asn1_length_der:
+ * @len: value to convert.
+- * @ans: string returned.
+- * @ans_len: number of meaningful bytes of ANS (ans[0]..ans[ans_len-1]).
++ * @der: buffer to hold the returned encoding (may be %NULL).
++ * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]).
++ *
++ * Creates the DER encoding of the provided length value.
++ * The @der buffer must have enough room for the output. The maximum
++ * length this function will encode is %ASN1_MAX_LENGTH_SIZE.
+ *
+- * Creates the DER coding for the LEN parameter (only the length).
+- * The @ans buffer is pre-allocated and must have room for the output.
++ * To know the size of the DER encoding use a %NULL value for @der.
+ **/
+ void
+-asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len)
++asn1_length_der (unsigned long int len, unsigned char *der, int *der_len)
+ {
+ int k;
+- unsigned char temp[SIZEOF_UNSIGNED_LONG_INT];
++ unsigned char temp[ASN1_MAX_LENGTH_SIZE];
++#if SIZEOF_UNSIGNED_LONG_INT > 8
++ len &= 0xFFFFFFFFFFFFFFFF;
++#endif
+
+ if (len < 128)
+ {
+ /* short form */
+- if (ans != NULL)
+- ans[0] = (unsigned char) len;
+- *ans_len = 1;
++ if (der != NULL)
++ der[0] = (unsigned char) len;
++ *der_len = 1;
+ }
+ else
+ {
+@@ -90,12 +107,12 @@
+ temp[k++] = len & 0xFF;
+ len = len >> 8;
+ }
+- *ans_len = k + 1;
+- if (ans != NULL)
++ *der_len = k + 1;
++ if (der != NULL)
+ {
+- ans[0] = ((unsigned char) k & 0x7F) + 128;
++ der[0] = ((unsigned char) k & 0x7F) + 128;
+ while (k--)
+- ans[*ans_len - 1 - k] = temp[k];
++ der[*der_len - 1 - k] = temp[k];
+ }
+ }
+ }
+@@ -104,6 +121,7 @@
+ /* Function : _asn1_tag_der */
+ /* Description: creates the DER coding for the CLASS */
+ /* and TAG parameters. */
++/* It is limited by the ASN1_MAX_TAG_SIZE variable */
+ /* Parameters: */
+ /* class: value to convert. */
+ /* tag_value: value to convert. */
+@@ -117,7 +135,7 @@
+ unsigned char *ans, int *ans_len)
+ {
+ int k;
+- unsigned char temp[SIZEOF_UNSIGNED_INT];
++ unsigned char temp[ASN1_MAX_TAG_SIZE];
+
+ if (tag_value < 31)
+ {
+@@ -130,10 +148,13 @@
+ /* Long form */
+ ans[0] = (class & 0xE0) + 31;
+ k = 0;
+- while (tag_value)
++ while (tag_value != 0)
+ {
+ temp[k++] = tag_value & 0x7F;
+- tag_value = tag_value >> 7;
++ tag_value >>= 7;
++
++ if (k > ASN1_MAX_TAG_SIZE - 1)
++ break; /* will not encode larger tags */
+ }
+ *ans_len = k + 1;
+ while (k--)
+@@ -144,12 +165,20 @@
+
+ /**
+ * asn1_octet_der:
+- * @str: OCTET string.
+- * @str_len: STR length (str[0]..str[str_len-1]).
+- * @der: string returned.
+- * @der_len: number of meaningful bytes of DER (der[0]..der[ans_len-1]).
++ * @str: the input data.
++ * @str_len: STR length (str[0]..str[*str_len-1]).
++ * @der: encoded string returned.
++ * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]).
++ *
++ * Creates a length-value DER encoding for the input data.
++ * The DER encoding of the input data will be placed in the @der variable.
+ *
+- * Creates the DER coding for an OCTET type (length included).
++ * Note that the OCTET STRING tag is not included in the output.
++ *
++ * This function does not return any value because it is expected
++ * that @der_len will contain enough bytes to store the string
++ * plus the DER encoding. The DER encoding size can be obtained using
++ * asn1_length_der().
+ **/
+ void
+ asn1_octet_der (const unsigned char *str, int str_len,
+@@ -159,11 +188,73 @@
+
+ if (der == NULL || str_len < 0)
+ return;
++
+ asn1_length_der (str_len, der, &len_len);
+ memcpy (der + len_len, str, str_len);
+ *der_len = str_len + len_len;
+ }
+
++
++/**
++ * asn1_encode_simple_der:
++ * @etype: The type of the string to be encoded (TYPE_)
++ * @str: the string data.
++ * @str_len: the string length
++ * @tl: the encoded tag and length
++ * @tl_len: the bytes of the @tl field
++ *
++ * Creates the DER encoding for various simple ASN.1 types like strings etc.
++ * It stores the tag and length in @tl, which should have space for at least
++ * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl.
++ *
++ * The complete DER encoding should consist of the value in @tl appended
++ * with the provided @str.
++ *
++ * Returns: %ASN1_SUCCESS if successful or an error value.
++ **/
++int
++asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
++ unsigned int str_len, unsigned char *tl,
++ unsigned int *tl_len)
++{
++ int tag_len, len_len;
++ unsigned tlen;
++ unsigned char der_tag[ASN1_MAX_TAG_SIZE];
++ unsigned char der_length[ASN1_MAX_LENGTH_SIZE];
++ unsigned char *p;
++
++ if (str == NULL)
++ return ASN1_VALUE_NOT_VALID;
++
++ if (ETYPE_OK (etype) == 0)
++ return ASN1_VALUE_NOT_VALID;
++
++ /* doesn't handle constructed classes */
++ if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
++ return ASN1_VALUE_NOT_VALID;
++
++ _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len);
++
++ asn1_length_der (str_len, der_length, &len_len);
++
++ if (tag_len <= 0 || len_len <= 0)
++ return ASN1_VALUE_NOT_VALID;
++
++ tlen = tag_len + len_len;
++
++ if (*tl_len < tlen)
++ return ASN1_MEM_ERROR;
++
++ p = tl;
++ memcpy (p, der_tag, tag_len);
++ p += tag_len;
++ memcpy (p, der_length, len_len);
++
++ *tl_len = tlen;
++
++ return ASN1_SUCCESS;
++}
++
+ /******************************************************/
+ /* Function : _asn1_time_der */
+ /* Description: creates the DER coding for a TIME */
+@@ -178,19 +269,20 @@
+ /* ASN1_MEM_ERROR when DER isn't big enough */
+ /* ASN1_SUCCESS otherwise */
+ /******************************************************/
+-static asn1_retCode
+-_asn1_time_der (unsigned char *str, unsigned char *der, int *der_len)
++static int
++_asn1_time_der (unsigned char *str, int str_len, unsigned char *der,
++ int *der_len)
+ {
+ int len_len;
+ int max_len;
+
+ max_len = *der_len;
+
+- asn1_length_der (strlen (str), (max_len > 0) ? der : NULL, &len_len);
++ asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len);
+
+- if ((len_len + (int) strlen (str)) <= max_len)
+- memcpy (der + len_len, str, strlen (str));
+- *der_len = len_len + strlen (str);
++ if ((len_len + str_len) <= max_len)
++ memcpy (der + len_len, str, str_len);
++ *der_len = len_len + str_len;
+
+ if ((*der_len) > max_len)
+ return ASN1_MEM_ERROR;
+@@ -247,29 +339,27 @@
+ /* must store the length of DER. */
+ /* Return: */
+ /* ASN1_MEM_ERROR when DER isn't big enough */
+-/* ASN1_SUCCESS otherwise */
++/* ASN1_SUCCESS if succesful */
++/* or an error value. */
+ /******************************************************/
+-static asn1_retCode
++static int
+ _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
+ {
+ int len_len, counter, k, first, max_len;
+- char *temp = NULL, *n_end, *n_start;
++ char *temp, *n_end, *n_start;
+ unsigned char bit7;
+ unsigned long val, val1 = 0;
+- size_t temp_size = str ? strlen (str) : 0;
+-
+- temp_size += 2;
+- if (temp_size < 2)
+- return ASN1_MEM_ALLOC_ERROR;
++ int str_len = _asn1_strlen (str);
+
+ max_len = *der_len;
+
+- temp = (char *) _asn1_malloc (temp_size);
++ temp = malloc (str_len + 2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+- strncpy (temp, str ? (const char *)str : "", temp_size);
+- strncat (temp, ".", 1);
++ memcpy (temp, str, str_len);
++ temp[str_len] = '.';
++ temp[str_len + 1] = 0;
+
+ counter = 0;
+ n_start = temp;
+@@ -316,7 +406,7 @@
+ }
+ *der_len += len_len;
+
+- _asn1_free (temp);
++ free (temp);
+
+ if (max_len < (*der_len))
+ return ASN1_MEM_ERROR;
+@@ -325,7 +415,8 @@
+ }
+
+
+-const char bit_mask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
++static const unsigned char bit_mask[] =
++ { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
+
+ /**
+ * asn1_bit_der:
+@@ -335,8 +426,16 @@
+ * @der_len: number of meaningful bytes of DER
+ * (der[0]..der[ans_len-1]).
+ *
+- * Creates the DER coding for a BIT STRING type (length and pad
+- * included).
++ * Creates a length-value DER encoding for the input data
++ * as it would have been for a BIT STRING.
++ * The DER encoded data will be copied in @der.
++ *
++ * Note that the BIT STRING tag is not included in the output.
++ *
++ * This function does not return any value because it is expected
++ * that @der_len will contain enough bytes to store the string
++ * plus the DER encoding. The DER encoding size can be obtained using
++ * asn1_length_der().
+ **/
+ void
+ asn1_bit_der (const unsigned char *str, int bit_len,
+@@ -346,6 +445,7 @@
+
+ if (der == NULL)
+ return;
++
+ len_byte = bit_len >> 3;
+ len_pad = 8 - (bit_len & 7);
+ if (len_pad == 8)
+@@ -374,7 +474,7 @@
+ /* ASN1_MEM_ERROR if der vector isn't big enough, */
+ /* otherwise ASN1_SUCCESS. */
+ /******************************************************/
+-static asn1_retCode
++static int
+ _asn1_complete_explicit_tag (ASN1_TYPE node, unsigned char *der,
+ int *counter, int *max_len)
+ {
+@@ -387,6 +487,8 @@
+ if (node->type & CONST_TAG)
+ {
+ p = node->down;
++ if (p == NULL)
++ return ASN1_DER_ERROR;
+ /* When there are nested tags we must complete them reverse to
+ the order they were created. This is because completing a tag
+ modifies all data within it, including the incomplete tags
+@@ -431,6 +533,56 @@
+ return ASN1_SUCCESS;
+ }
+
++const tag_and_class_st _asn1_tags[] = {
++ [TYPE_GENERALSTRING] =
++ {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"},
++ [TYPE_NUMERIC_STRING] =
++ {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"},
++ [TYPE_IA5_STRING] =
++ {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"},
++ [TYPE_TELETEX_STRING] =
++ {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"},
++ [TYPE_PRINTABLE_STRING] =
++ {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"},
++ [TYPE_UNIVERSAL_STRING] =
++ {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"},
++ [TYPE_BMP_STRING] =
++ {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"},
++ [TYPE_UTF8_STRING] =
++ {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"},
++ [TYPE_VISIBLE_STRING] =
++ {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"},
++ [TYPE_OCTET_STRING] =
++ {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"},
++ [TYPE_BIT_STRING] =
++ {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"},
++ [TYPE_OBJECT_ID] =
++ {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"},
++ [TYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"},
++ [TYPE_BOOLEAN] =
++ {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"},
++ [TYPE_INTEGER] =
++ {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"},
++ [TYPE_ENUMERATED] =
++ {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"},
++ [TYPE_SEQUENCE] =
++ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
++ "type:SEQUENCE"},
++ [TYPE_SEQUENCE_OF] =
++ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
++ "type:SEQ_OF"},
++ [TYPE_SET] =
++ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"},
++ [TYPE_SET_OF] =
++ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
++ "type:SET_OF"},
++ [TYPE_GENERALIZED_TIME] =
++ {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"},
++ [TYPE_UTC_TIME] =
++ {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"},
++};
++
++unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
+
+ /******************************************************/
+ /* Function : _asn1_insert_tag_der */
+@@ -447,15 +599,15 @@
+ /* ASN1_MEM_ERROR if der vector isn't big enough, */
+ /* otherwise ASN1_SUCCESS. */
+ /******************************************************/
+-static asn1_retCode
++static int
+ _asn1_insert_tag_der (ASN1_TYPE node, unsigned char *der, int *counter,
+ int *max_len)
+ {
+ ASN1_TYPE p;
+ int tag_len, is_tag_implicit;
+- unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1];
++ unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
+ unsigned long tag_implicit = 0;
+- char tag_der[MAX_TAG_LEN];
++ unsigned char tag_der[MAX_TAG_LEN];
+
+ is_tag_implicit = 0;
+
+@@ -482,16 +634,16 @@
+ &tag_len);
+ else
+ _asn1_tag_der (class | ASN1_CLASS_STRUCTURED,
+- strtoul (p->value, NULL, 10), tag_der,
+- &tag_len);
++ _asn1_strtoul (p->value, NULL, 10),
++ tag_der, &tag_len);
+
+ *max_len -= tag_len;
+ if (*max_len >= 0)
+ memcpy (der + *counter, tag_der, tag_len);
+ *counter += tag_len;
+
+- _asn1_ltostr (*counter, temp);
+- _asn1_set_name (p, temp);
++ _asn1_ltostr (*counter, (char *) temp);
++ _asn1_set_name (p, (const char *) temp);
+
+ is_tag_implicit = 0;
+ }
+@@ -500,12 +652,12 @@
+ if (!is_tag_implicit)
+ {
+ if ((type_field (node->type) == TYPE_SEQUENCE) ||
+- (type_field (node->type) == TYPE_SEQUENCE_OF) ||
+- (type_field (node->type) == TYPE_SET) ||
+- (type_field (node->type) == TYPE_SET_OF))
++ (type_field (node->type) == TYPE_SEQUENCE_OF)
++ || (type_field (node->type) == TYPE_SET)
++ || (type_field (node->type) == TYPE_SET_OF))
+ class |= ASN1_CLASS_STRUCTURED;
+ class_implicit = class;
+- tag_implicit = strtoul (p->value, NULL, 10);
++ tag_implicit = _asn1_strtoul (p->value, NULL, 10);
+ is_tag_implicit = 1;
+ }
+ }
+@@ -520,66 +672,15 @@
+ }
+ else
+ {
+- switch (type_field (node->type))
++ unsigned type = type_field (node->type);
++ switch (type)
+ {
+- case TYPE_NULL:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_NULL, tag_der,
+- &tag_len);
+- break;
+- case TYPE_BOOLEAN:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_BOOLEAN, tag_der,
+- &tag_len);
+- break;
+- case TYPE_INTEGER:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_INTEGER, tag_der,
+- &tag_len);
+- break;
+- case TYPE_ENUMERATED:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_ENUMERATED, tag_der,
+- &tag_len);
+- break;
+- case TYPE_OBJECT_ID:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_OBJECT_ID, tag_der,
+- &tag_len);
+- break;
+- case TYPE_TIME:
+- if (node->type & CONST_UTC)
+- {
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_UTCTime, tag_der,
+- &tag_len);
+- }
+- else
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALIZEDTime,
+- tag_der, &tag_len);
+- break;
+- case TYPE_OCTET_STRING:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_OCTET_STRING, tag_der,
+- &tag_len);
+- break;
+- case TYPE_GENERALSTRING:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALSTRING,
++ CASE_HANDLED_ETYPES:
++ _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag,
+ tag_der, &tag_len);
+ break;
+- case TYPE_BIT_STRING:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_BIT_STRING, tag_der,
+- &tag_len);
+- break;
+- case TYPE_SEQUENCE:
+- case TYPE_SEQUENCE_OF:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+- ASN1_TAG_SEQUENCE, tag_der, &tag_len);
+- break;
+- case TYPE_SET:
+- case TYPE_SET_OF:
+- _asn1_tag_der (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+- ASN1_TAG_SET, tag_der, &tag_len);
+- break;
+ case TYPE_TAG:
+- tag_len = 0;
+- break;
+ case TYPE_CHOICE:
+- tag_len = 0;
+- break;
+ case TYPE_ANY:
+ tag_len = 0;
+ break;
+@@ -607,8 +708,10 @@
+ /* der: string with the DER coding. */
+ /* node: pointer to the SET element. */
+ /* Return: */
++/* ASN1_SUCCESS if successful */
++/* or an error value. */
+ /******************************************************/
+-static void
++static int
+ _asn1_ordering_set (unsigned char *der, int der_len, ASN1_TYPE node)
+ {
+ struct vet
+@@ -622,27 +725,31 @@
+ struct vet *first, *last, *p_vet, *p2_vet;
+ ASN1_TYPE p;
+ unsigned char class, *temp;
+- unsigned long tag;
++ unsigned long tag, t;
++ int err;
+
+ counter = 0;
+
+ if (type_field (node->type) != TYPE_SET)
+- return;
++ return ASN1_VALUE_NOT_VALID;
+
+ p = node->down;
+- while ((type_field (p->type) == TYPE_TAG)
+- || (type_field (p->type) == TYPE_SIZE))
++ while (p && ((type_field (p->type) == TYPE_TAG) ||
++ (type_field (p->type) == TYPE_SIZE)))
+ p = p->right;
+
+ if ((p == NULL) || (p->right == NULL))
+- return;
++ return ASN1_SUCCESS;
+
+ first = last = NULL;
+ while (p)
+ {
+- p_vet = (struct vet *) _asn1_malloc (sizeof (struct vet));
++ p_vet = malloc (sizeof (struct vet));
+ if (p_vet == NULL)
+- return;
++ {
++ err = ASN1_MEM_ALLOC_ERROR;
++ goto error;
++ }
+
+ p_vet->next = NULL;
+ p_vet->prev = last;
+@@ -653,17 +760,22 @@
+ last = p_vet;
+
+ /* tag value calculation */
+- if (asn1_get_tag_der
+- (der + counter, der_len - counter, &class, &len2,
+- &tag) != ASN1_SUCCESS)
+- return;
+- p_vet->value = (class << 24) | tag;
++ err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2,
++ &tag);
++ if (err != ASN1_SUCCESS)
++ goto error;
++
++ t = class << 24;
++ p_vet->value = t | tag;
+ counter += len2;
+
+ /* extraction and length */
+ len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
+ if (len2 < 0)
+- return;
++ {
++ err = ASN1_DER_ERROR;
++ goto error;
++ }
+ counter += len + len2;
+
+ p_vet->end = counter;
+@@ -681,16 +793,19 @@
+ if (p_vet->value > p2_vet->value)
+ {
+ /* change position */
+- temp = (unsigned char *) _asn1_malloc (p_vet->end - counter);
++ temp = malloc (p_vet->end - counter);
+ if (temp == NULL)
+- return;
++ {
++ err = ASN1_MEM_ALLOC_ERROR;
++ goto error;
++ }
+
+ memcpy (temp, der + counter, p_vet->end - counter);
+ memcpy (der + counter, der + p_vet->end,
+ p2_vet->end - p_vet->end);
+ memcpy (der + counter + p2_vet->end - p_vet->end, temp,
+ p_vet->end - counter);
+- _asn1_free (temp);
++ free (temp);
+
+ tag = p_vet->value;
+ p_vet->value = p2_vet->value;
+@@ -708,9 +823,19 @@
+ p_vet->prev->next = NULL;
+ else
+ first = NULL;
+- _asn1_free (p_vet);
++ free (p_vet);
++ p_vet = first;
++ }
++ return ASN1_SUCCESS;
++
++error:
++ while (first != NULL)
++ {
+ p_vet = first;
++ first = first->next;
++ free(p_vet);
+ }
++ return err;
+ }
+
+ /******************************************************/
+@@ -721,8 +846,10 @@
+ /* der: string with the DER coding. */
+ /* node: pointer to the SET OF element. */
+ /* Return: */
++/* ASN1_SUCCESS if successful */
++/* or an error value. */
+ /******************************************************/
+-static void
++static int
+ _asn1_ordering_set_of (unsigned char *der, int der_len, ASN1_TYPE node)
+ {
+ struct vet
+@@ -735,28 +862,34 @@
+ struct vet *first, *last, *p_vet, *p2_vet;
+ ASN1_TYPE p;
+ unsigned char *temp, class;
+- unsigned long k, max;
++ unsigned long k, length;
++ int err;
+
+ counter = 0;
+
+ if (type_field (node->type) != TYPE_SET_OF)
+- return;
++ return ASN1_VALUE_NOT_VALID;
+
+ p = node->down;
+- while ((type_field (p->type) == TYPE_TAG)
+- || (type_field (p->type) == TYPE_SIZE))
++ while (p && ((type_field (p->type) == TYPE_TAG) ||
++ (type_field (p->type) == TYPE_SIZE)))
+ p = p->right;
++ if (p == NULL)
++ return ASN1_VALUE_NOT_VALID;
+ p = p->right;
+
+ if ((p == NULL) || (p->right == NULL))
+- return;
++ return ASN1_SUCCESS;
+
+ first = last = NULL;
+ while (p)
+ {
+- p_vet = (struct vet *) _asn1_malloc (sizeof (struct vet));
++ p_vet = malloc (sizeof (struct vet));
+ if (p_vet == NULL)
+- return;
++ {
++ err = ASN1_MEM_ALLOC_ERROR;
++ goto error;
++ }
+
+ p_vet->next = NULL;
+ p_vet->prev = last;
+@@ -770,17 +903,25 @@
+ if (der_len - counter > 0)
+ {
+
+- if (asn1_get_tag_der
+- (der + counter, der_len - counter, &class, &len,
+- NULL) != ASN1_SUCCESS)
+- return;
++ err = asn1_get_tag_der (der + counter, der_len - counter, &class,
++ &len, NULL);
++ if (err != ASN1_SUCCESS)
++ goto error;
+ counter += len;
+
+ len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
+ if (len2 < 0)
+- return;
++ {
++ err = ASN1_DER_ERROR;
++ goto error;
++ }
+ counter += len + len2;
+ }
++ else
++ {
++ err = ASN1_DER_ERROR;
++ goto error;
++ }
+
+ p_vet->end = counter;
+ p = p->right;
+@@ -794,13 +935,9 @@
+ counter = 0;
+ while (p2_vet)
+ {
+- if ((p_vet->end - counter) > (p2_vet->end - p_vet->end))
+- max = p_vet->end - counter;
+- else
+- max = p2_vet->end - p_vet->end;
+-
++ length = MIN(p_vet->end - counter, p2_vet->end - p_vet->end);
+ change = -1;
+- for (k = 0; k < max; k++)
++ for (k = 0; k < length; k++)
+ if (der[counter + k] > der[p_vet->end + k])
+ {
+ change = 1;
+@@ -819,16 +956,19 @@
+ if (change == 1)
+ {
+ /* change position */
+- temp = (unsigned char *) _asn1_malloc (p_vet->end - counter);
++ temp = malloc (p_vet->end - counter);
+ if (temp == NULL)
+- return;
++ {
++ err = ASN1_MEM_ALLOC_ERROR;
++ goto error;
++ }
+
+ memcpy (temp, der + counter, (p_vet->end) - counter);
+ memcpy (der + counter, der + (p_vet->end),
+ (p2_vet->end) - (p_vet->end));
+ memcpy (der + counter + (p2_vet->end) - (p_vet->end), temp,
+ (p_vet->end) - counter);
+- _asn1_free (temp);
++ free (temp);
+
+ p_vet->end = counter + (p2_vet->end - p_vet->end);
+ }
+@@ -842,9 +982,19 @@
+ p_vet->prev->next = NULL;
+ else
+ first = NULL;
+- _asn1_free (p_vet);
++ free (p_vet);
++ p_vet = first;
++ }
++ return ASN1_SUCCESS;
++
++error:
++ while (first != NULL)
++ {
+ p_vet = first;
++ first = first->next;
++ free(p_vet);
+ }
++ return err;
+ }
+
+ /**
+@@ -856,31 +1006,26 @@
+ * pointer to memory cells already allocated.
+ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy
+ * holds the sizeof of der vector.
+- * @errorDescription : return the error description or an empty
++ * @ErrorDescription: return the error description or an empty
+ * string if success.
+ *
+ * Creates the DER encoding for the NAME structure (inside *POINTER
+ * structure).
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: DER encoding OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+- *
+- * %ASN1_VALUE_NOT_FOUND: There is an element without a value.
+- *
+- * %ASN1_MEM_ERROR: @ider vector isn't big enough. Also in this case
+- * LEN will contain the length needed.
++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
++ * if @name is not a valid element, %ASN1_VALUE_NOT_FOUND if there
++ * is an element without a value, %ASN1_MEM_ERROR if the @ider
++ * vector isn't big enough and in this case @len will contain the
++ * length needed.
+ **/
+-asn1_retCode
++int
+ asn1_der_coding (ASN1_TYPE element, const char *name, void *ider, int *len,
+ char *ErrorDescription)
+ {
+ ASN1_TYPE node, p, p2;
+- char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1];
++ unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
+ int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old;
+- asn1_retCode err;
++ int err;
+ unsigned char *der = ider;
+
+ node = asn1_find_node (element, name);
+@@ -1003,7 +1148,8 @@
+ }
+ move = RIGHT;
+ break;
+- case TYPE_TIME:
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_UTC_TIME:
+ if (p->value == NULL)
+ {
+ _asn1_error_description_value_not_found (p, ErrorDescription);
+@@ -1011,7 +1157,7 @@
+ goto error;
+ }
+ len2 = max_len;
+- err = _asn1_time_der (p->value, der + counter, &len2);
++ err = _asn1_time_der (p->value, p->value_len, der + counter, &len2);
+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+ goto error;
+
+@@ -1020,43 +1166,15 @@
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+- if (p->value == NULL)
+- {
+- _asn1_error_description_value_not_found (p, ErrorDescription);
+- err = ASN1_VALUE_NOT_FOUND;
+- goto error;
+- }
+- len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+- if (len2 < 0)
+- {
+- err = ASN1_DER_ERROR;
+- goto error;
+- }
+- max_len -= len2 + len3;
+- if (max_len >= 0)
+- memcpy (der + counter, p->value, len3 + len2);
+- counter += len3 + len2;
+- move = RIGHT;
+- break;
+ case TYPE_GENERALSTRING:
+- if (p->value == NULL)
+- {
+- _asn1_error_description_value_not_found (p, ErrorDescription);
+- err = ASN1_VALUE_NOT_FOUND;
+- goto error;
+- }
+- len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+- if (len2 < 0)
+- {
+- err = ASN1_DER_ERROR;
+- goto error;
+- }
+- max_len -= len2 + len3;
+- if (max_len >= 0)
+- memcpy (der + counter, p->value, len3 + len2);
+- counter += len3 + len2;
+- move = RIGHT;
+- break;
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ case TYPE_BIT_STRING:
+ if (p->value == NULL)
+ {
+@@ -1080,8 +1198,8 @@
+ case TYPE_SET:
+ if (move != UP)
+ {
+- _asn1_ltostr (counter, temp);
+- tlen = strlen (temp);
++ _asn1_ltostr (counter, (char *) temp);
++ tlen = _asn1_strlen (temp);
+ if (tlen > 0)
+ _asn1_set_value (p, temp, tlen + 1);
+ if (p->down == NULL)
+@@ -1106,10 +1224,14 @@
+ }
+ else
+ { /* move==UP */
+- len2 = strtol (p->value, NULL, 10);
++ len2 = _asn1_strtol (p->value, NULL, 10);
+ _asn1_set_value (p, NULL, 0);
+ if ((type_field (p->type) == TYPE_SET) && (max_len >= 0))
+- _asn1_ordering_set (der + len2, max_len - len2, p);
++ {
++ err = _asn1_ordering_set (der + len2, counter - len2, p);
++ if (err != ASN1_SUCCESS)
++ goto error;
++ }
+ asn1_length_der (counter - len2, temp, &len3);
+ max_len -= len3;
+ if (max_len >= 0)
+@@ -1125,8 +1247,8 @@
+ case TYPE_SET_OF:
+ if (move != UP)
+ {
+- _asn1_ltostr (counter, temp);
+- tlen = strlen (temp);
++ _asn1_ltostr (counter, (char *) temp);
++ tlen = _asn1_strlen (temp);
+
+ if (tlen > 0)
+ _asn1_set_value (p, temp, tlen + 1);
+@@ -1146,12 +1268,14 @@
+ }
+ if (move == UP)
+ {
+- len2 = strtol (p->value, NULL, 10);
++ len2 = _asn1_strtol (p->value, NULL, 10);
+ _asn1_set_value (p, NULL, 0);
+ if ((type_field (p->type) == TYPE_SET_OF)
+- && (max_len - len2 > 0))
++ && (counter - len2 > 0) && (max_len >= 0))
+ {
+- _asn1_ordering_set_of (der + len2, max_len - len2, p);
++ err = _asn1_ordering_set_of (der + len2, counter - len2, p);
++ if (err != ASN1_SUCCESS)
++ goto error;
+ }
+ asn1_length_der (counter - len2, temp, &len3);
+ max_len -= len3;
+--- ORIGINAL/./lib/element.h 2015-07-14 18:28:22.926924377 -0700
++++ libtasn1-2.8/./lib/element.h 2015-07-14 18:45:02.724927088 -0700
+@@ -24,11 +24,11 @@
+ #define _ELEMENT_H
+
+
+-asn1_retCode _asn1_append_sequence_set (ASN1_TYPE node);
++int _asn1_append_sequence_set (ASN1_TYPE node);
+
+-asn1_retCode _asn1_convert_integer (const char *value,
+- unsigned char *value_out,
+- int value_out_size, int *len);
++int _asn1_convert_integer (const unsigned char *value,
++ unsigned char *value_out,
++ int value_out_size, int *len);
+
+ void _asn1_hierarchical_name (ASN1_TYPE node, char *name, int name_size);
+
+--- ORIGINAL/./lib/gstr.c 2015-07-14 18:28:22.922080887 -0700
++++ libtasn1-2.8/./lib/gstr.c 2015-07-14 18:45:02.700823028 -0700
+@@ -49,7 +49,8 @@
+ }
+ }
+
+-void
++/* Returns the bytes copied (not including the null terminator) */
++unsigned int
+ _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src)
+ {
+ size_t str_size = strlen (src);
+@@ -57,13 +58,18 @@
+ if (dest_tot_size > str_size)
+ {
+ strcpy (dest, src);
++ return str_size;
+ }
+ else
+ {
+ if (dest_tot_size > 0)
+ {
+- strncpy (dest, src, (dest_tot_size) - 1);
+- dest[dest_tot_size - 1] = 0;
++ str_size = dest_tot_size - 1;
++ memcpy (dest, src, str_size);
++ dest[str_size] = 0;
++ return str_size;
+ }
++ else
++ return 0;
+ }
+ }
+--- ORIGINAL/./lib/int.h 2015-07-14 18:28:22.934362140 -0700
++++ libtasn1-2.8/./lib/int.h 2015-07-14 18:45:02.741226703 -0700
+@@ -47,7 +47,8 @@
+ struct node_asn_struct
+ {
+ /* public fields: */
+- char *name; /* Node name */
++ char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */
++ unsigned int name_hash;
+ unsigned int type; /* Node type */
+ unsigned char *value; /* Node value */
+ int value_len;
+@@ -58,11 +59,53 @@
+ unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */
+ };
+
+-#define _asn1_malloc malloc
+-#define _asn1_free free
+-#define _asn1_calloc calloc
+-#define _asn1_realloc realloc
+-#define _asn1_strdup strdup
++typedef struct tag_and_class_st
++{
++ unsigned tag;
++ unsigned class;
++ const char *desc;
++} tag_and_class_st;
++
++/* the types that are handled in _asn1_tags */
++#define CASE_HANDLED_ETYPES \
++ case TYPE_NULL: \
++ case TYPE_BOOLEAN: \
++ case TYPE_INTEGER: \
++ case TYPE_ENUMERATED: \
++ case TYPE_OBJECT_ID: \
++ case TYPE_OCTET_STRING: \
++ case TYPE_GENERALSTRING: \
++ case TYPE_NUMERIC_STRING: \
++ case TYPE_IA5_STRING: \
++ case TYPE_TELETEX_STRING: \
++ case TYPE_PRINTABLE_STRING: \
++ case TYPE_UNIVERSAL_STRING: \
++ case TYPE_BMP_STRING: \
++ case TYPE_UTF8_STRING: \
++ case TYPE_VISIBLE_STRING: \
++ case TYPE_BIT_STRING: \
++ case TYPE_SEQUENCE: \
++ case TYPE_SEQUENCE_OF: \
++ case TYPE_SET: \
++ case TYPE_UTC_TIME: \
++ case TYPE_GENERALIZED_TIME: \
++ case TYPE_SET_OF
++
++#define ETYPE_TAG(etype) (_asn1_tags[etype].tag)
++#define ETYPE_CLASS(etype) (_asn1_tags[etype].class)
++#define ETYPE_OK(etype) ((etype != TYPE_INVALID && \
++ etype <= _asn1_tags_size && \
++ _asn1_tags[etype].desc != NULL)?1:0)
++
++extern unsigned int _asn1_tags_size;
++extern const tag_and_class_st _asn1_tags[];
++
++#define _asn1_strlen(s) strlen((const char *) s)
++#define _asn1_strtol(n,e,b) strtol((const char *) n, e, b)
++#define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b)
++#define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b)
++#define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b)
++#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b)
+
+ #define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */
+
+@@ -78,6 +121,7 @@
+ #define type_field(x) (x&0xFF)
+
+ /* List of constants for field type of typedef node_asn */
++#define TYPE_INVALID 0
+ #define TYPE_CONSTANT 1
+ #define TYPE_IDENTIFIER 2
+ #define TYPE_INTEGER 3
+@@ -100,6 +144,16 @@
+ #define TYPE_NULL 20
+ #define TYPE_ENUMERATED 21
+ #define TYPE_GENERALSTRING 27
++#define TYPE_NUMERIC_STRING 28
++#define TYPE_IA5_STRING 29
++#define TYPE_TELETEX_STRING 30
++#define TYPE_PRINTABLE_STRING 31
++#define TYPE_UNIVERSAL_STRING 32
++#define TYPE_BMP_STRING 33
++#define TYPE_UTF8_STRING 34
++#define TYPE_VISIBLE_STRING 35
++#define TYPE_UTC_TIME 36
++#define TYPE_GENERALIZED_TIME 37
+
+
+ /***********************************************************************/
+@@ -139,4 +193,28 @@
+ #define CONST_DOWN (1<<29)
+ #define CONST_RIGHT (1<<30)
+
++#define TYPE_TIME 17
++
++/* To convert old types from a static structure */
++inline static unsigned int
++convert_old_type (unsigned int ntype)
++{
++ unsigned int type = ntype & 0xff;
++ if (type == TYPE_TIME)
++ {
++ if (ntype & CONST_UTC)
++ type = TYPE_UTC_TIME;
++ else
++ type = TYPE_GENERALIZED_TIME;
++
++ ntype &= ~(CONST_UTC | CONST_GENERALIZED);
++ ntype &= 0xffffff00;
++ ntype |= type;
++
++ return ntype;
++ }
++ else
++ return ntype;
++}
++
+ #endif /* INT_H */
+--- ORIGINAL/./lib/parser_aux.h 2015-07-14 18:28:22.924499509 -0700
++++ libtasn1-2.8/./lib/parser_aux.h 2015-07-14 18:45:02.703556709 -0700
+@@ -23,12 +23,10 @@
+ #ifndef _PARSER_AUX_H
+ #define _PARSER_AUX_H
+
+-#define DER_LEN 16
+-
+ /***************************************/
+ /* Functions used by ASN.1 parser */
+ /***************************************/
+-ASN1_TYPE _asn1_add_node (unsigned int type);
++ASN1_TYPE _asn1_add_static_node (unsigned int type);
+
+ ASN1_TYPE
+ _asn1_set_value (ASN1_TYPE node, const void *value, unsigned int len);
+@@ -36,47 +34,125 @@
+ ASN1_TYPE _asn1_set_value_m (ASN1_TYPE node, void *value, unsigned int len);
+
+ ASN1_TYPE
+-_asn1_set_value_octet (ASN1_TYPE node, const void *value, unsigned int len);
++_asn1_set_value_lv (ASN1_TYPE node, const void *value, unsigned int len);
+
+ ASN1_TYPE
+ _asn1_append_value (ASN1_TYPE node, const void *value, unsigned int len);
+
+ ASN1_TYPE _asn1_set_name (ASN1_TYPE node, const char *name);
+
+-ASN1_TYPE _asn1_set_right (ASN1_TYPE node, ASN1_TYPE right);
++ASN1_TYPE _asn1_cpy_name (ASN1_TYPE dst, ASN1_TYPE src);
+
+-ASN1_TYPE _asn1_get_right (ASN1_TYPE node);
++ASN1_TYPE _asn1_set_right (ASN1_TYPE node, ASN1_TYPE right);
+
+ ASN1_TYPE _asn1_get_last_right (ASN1_TYPE node);
+
+-ASN1_TYPE _asn1_set_down (ASN1_TYPE node, ASN1_TYPE down);
+-
+-char *_asn1_get_name (ASN1_TYPE node);
+-
+-ASN1_TYPE _asn1_get_down (ASN1_TYPE node);
+-
+-ASN1_TYPE _asn1_mod_type (ASN1_TYPE node, unsigned int value);
+-
+-void _asn1_remove_node (ASN1_TYPE node);
++void _asn1_remove_node (ASN1_TYPE node, unsigned int flags);
+
+ void _asn1_delete_list (void);
+
+ void _asn1_delete_list_and_nodes (void);
+
+-/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */
+-#define LTOSTR_MAX_SIZE 22
+-char *_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE]);
++#define LTOSTR_MAX_SIZE 20
++char *_asn1_ltostr (long v, char *str);
+
+ ASN1_TYPE _asn1_find_up (ASN1_TYPE node);
+
+-asn1_retCode _asn1_change_integer_value (ASN1_TYPE node);
++int _asn1_change_integer_value (ASN1_TYPE node);
+
+-asn1_retCode _asn1_expand_object_id (ASN1_TYPE node);
++int _asn1_expand_object_id (ASN1_TYPE node);
+
+-asn1_retCode _asn1_type_set_config (ASN1_TYPE node);
++int _asn1_type_set_config (ASN1_TYPE node);
+
+-asn1_retCode _asn1_check_identifier (ASN1_TYPE node);
++int _asn1_check_identifier (ASN1_TYPE node);
+
+-asn1_retCode _asn1_set_default_tag (ASN1_TYPE node);
++int _asn1_set_default_tag (ASN1_TYPE node);
++
++/******************************************************************/
++/* Function : _asn1_get_right */
++/* Description: returns the element pointed by the RIGHT field of */
++/* a NODE_ASN element. */
++/* Parameters: */
++/* node: NODE_ASN element pointer. */
++/* Return: field RIGHT of NODE. */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_get_right (ASN1_TYPE node)
++{
++ if (node == NULL)
++ return NULL;
++ return node->right;
++}
++
++/******************************************************************/
++/* Function : _asn1_set_down */
++/* Description: sets the field DOWN in a NODE_ASN element. */
++/* Parameters: */
++/* node: element pointer. */
++/* down: pointer to a NODE_ASN element that you want be pointed */
++/* by NODE. */
++/* Return: pointer to *NODE. */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_set_down (ASN1_TYPE node, ASN1_TYPE down)
++{
++ if (node == NULL)
++ return node;
++ node->down = down;
++ if (down)
++ down->left = node;
++ return node;
++}
++
++/******************************************************************/
++/* Function : _asn1_get_down */
++/* Description: returns the element pointed by the DOWN field of */
++/* a NODE_ASN element. */
++/* Parameters: */
++/* node: NODE_ASN element pointer. */
++/* Return: field DOWN of NODE. */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_get_down (ASN1_TYPE node)
++{
++ if (node == NULL)
++ return NULL;
++ return node->down;
++}
++
++/******************************************************************/
++/* Function : _asn1_get_name */
++/* Description: returns the name of a NODE_ASN element. */
++/* Parameters: */
++/* node: NODE_ASN element pointer. */
++/* Return: a null terminated string. */
++/******************************************************************/
++inline static char *
++_asn1_get_name (ASN1_TYPE node)
++{
++ if (node == NULL)
++ return NULL;
++ return node->name;
++}
++
++/******************************************************************/
++/* Function : _asn1_mod_type */
++/* Description: change the field TYPE of an NODE_ASN element. */
++/* The new value is the old one | (bitwise or) the */
++/* paramener VALUE. */
++/* Parameters: */
++/* node: NODE_ASN element pointer. */
++/* value: the integer value that must be or-ed with the current */
++/* value of field TYPE. */
++/* Return: NODE pointer. */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_mod_type (ASN1_TYPE node, unsigned int value)
++{
++ if (node == NULL)
++ return node;
++ node->type |= value;
++ return node;
++}
+
+ #endif
+--- ORIGINAL/./lib/ASN1.y 2015-07-14 18:28:22.939304180 -0700
++++ libtasn1-2.8/./lib/ASN1.y 2015-07-14 18:45:02.748908645 -0700
+@@ -31,28 +31,33 @@
+ #include <int.h>
+ #include <parser_aux.h>
+ #include <structure.h>
++#include <libtasn1.h>
+
+ static FILE *file_asn1; /* Pointer to file to parse */
+-static asn1_retCode result_parse; /* result of the parser
++static int result_parse = 0; /* result of the parser
+ algorithm */
+ static ASN1_TYPE p_tree; /* pointer to the root of the
+ structure created by the
+ parser*/
+-static unsigned long lineNumber; /* line number describing the
++static unsigned int line_number; /* line number describing the
+ parser position inside the
+ file */
+-static char lastToken[ASN1_MAX_NAME_SIZE+1]; /* last token find in the file
++static char last_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
++static char last_error_token[ASN1_MAX_ERROR_DESCRIPTION_SIZE+1] = ""; /* used when expected errors occur */
++static char last_token[ASN1_MAX_NAME_SIZE+1] = ""; /* last token find in the file
+ to parse before the 'parse
+ error' */
+ extern char _asn1_identifierMissing[];
+-static const char *fileName; /* file to parse */
++static const char *file_name; /* file to parse */
+
+-static int _asn1_yyerror (const char *);
++static void _asn1_yyerror (const char *);
+ static int _asn1_yylex(void);
+
+ %}
+
+ /* Prefix symbols and functions with _asn1_ */
++/* %define parse.lac full */
++%error-verbose
+ %name-prefix="_asn1_yy"
+
+ %union {
+@@ -97,6 +102,15 @@
+ %token UTCTime
+ %token GeneralizedTime
+ %token GeneralString
++%token NumericString
++%token IA5String
++%token TeletexString
++%token PrintableString
++%token UniversalString
++%token BMPString
++%token UTF8String
++%token VisibleString
++
+ %token FROM
+ %token IMPORTS
+ %token ENUMERATED
+@@ -108,9 +122,12 @@
+ %type <node> constant_def type_constant type_constant_list definitions
+ %type <node> definitions_id Time bit_element bit_element_list set_def
+ %type <node> tag_type tag type_assig_right_tag generalstring_def
++%type <node> numericstring_def ia5string_def printablestring_def universalstring_def
++%type <node> bmpstring_def utf8string_def visiblestring_def teletexstring_def
+ %type <node> type_assig_right_tag_default enumerated_def
+ %type <str> pos_num neg_num pos_neg_num pos_neg_identifier pos_neg_list
+ %type <str> num_identifier
++%type <str> int_identifier
+ %type <constant> class explicit_implicit
+
+ %%
+@@ -119,7 +136,7 @@
+ definitions: definitions_id
+ DEFINITIONS explicit_implicit TAGS "::=" BEGIN /* imports_def */
+ type_constant_list END
+- {$$=_asn1_add_node(TYPE_DEFINITIONS|$3);
++ {$$=_asn1_add_static_node(TYPE_DEFINITIONS|$3);
+ _asn1_set_name($$,_asn1_get_name($1));
+ _asn1_set_name($1,"");
+ _asn1_set_right($1,$7);
+@@ -129,29 +146,33 @@
+ }
+ ;
+
+-pos_num : NUM {strcpy($$,$1);}
+- | '+' NUM {strcpy($$,$2);}
++pos_num : NUM {snprintf($$,sizeof($$),"%s",$1);}
++ | '+' NUM {snprintf($$,sizeof($$),"%s",$2);}
++;
++
++neg_num : '-' NUM {snprintf($$,sizeof($$),"-%s",$2);}
+ ;
+
+-neg_num : '-' NUM {strcpy($$,"-");
+- strcat($$,$2);}
++pos_neg_num : pos_num {snprintf($$,sizeof($$),"%s",$1);}
++ | neg_num {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+
+-pos_neg_num : pos_num {strcpy($$,$1);}
+- | neg_num {strcpy($$,$1);}
++num_identifier : NUM {snprintf($$,sizeof($$),"%s",$1);}
++ | IDENTIFIER {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+
+-num_identifier : NUM {strcpy($$,$1);}
+- | IDENTIFIER {strcpy($$,$1);}
++int_identifier : NUM {snprintf($$,sizeof($$),"%s",$1);}
++ | '-' NUM {snprintf($$,sizeof($$),"-%s",$2);}
++ | IDENTIFIER {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+
+-pos_neg_identifier : pos_neg_num {strcpy($$,$1);}
+- | IDENTIFIER {strcpy($$,$1);}
++pos_neg_identifier : pos_neg_num {snprintf($$,sizeof($$),"%s",$1);}
++ | IDENTIFIER {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+
+-constant: '(' pos_neg_num ')' {$$=_asn1_add_node(TYPE_CONSTANT);
++constant: '(' pos_neg_num ')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ _asn1_set_value($$,$2,strlen($2)+1);}
+- | IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_node(TYPE_CONSTANT);
++ | IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ _asn1_set_name($$,$1);
+ _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+@@ -161,9 +182,9 @@
+ _asn1_set_right(_asn1_get_last_right($1),$3);}
+ ;
+
+-obj_constant: num_identifier {$$=_asn1_add_node(TYPE_CONSTANT);
++obj_constant: num_identifier {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ _asn1_set_value($$,$1,strlen($1)+1);}
+- | IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT);
++ | IDENTIFIER'('NUM')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ _asn1_set_name($$,$1);
+ _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+@@ -178,9 +199,9 @@
+ | APPLICATION {$$=CONST_APPLICATION;}
+ ;
+
+-tag_type : '[' NUM ']' {$$=_asn1_add_node(TYPE_TAG);
++tag_type : '[' NUM ']' {$$=_asn1_add_static_node(TYPE_TAG);
+ _asn1_set_value($$,$2,strlen($2)+1);}
+- | '[' class NUM ']' {$$=_asn1_add_node(TYPE_TAG | $2);
++ | '[' class NUM ']' {$$=_asn1_add_static_node(TYPE_TAG | $2);
+ _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+
+@@ -189,10 +210,10 @@
+ | tag_type IMPLICIT {$$=_asn1_mod_type($1,CONST_IMPLICIT);}
+ ;
+
+-default : DEFAULT pos_neg_identifier {$$=_asn1_add_node(TYPE_DEFAULT);
++default : DEFAULT pos_neg_identifier {$$=_asn1_add_static_node(TYPE_DEFAULT);
+ _asn1_set_value($$,$2,strlen($2)+1);}
+- | DEFAULT ASN1_TRUE {$$=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
+- | DEFAULT ASN1_FALSE {$$=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
++ | DEFAULT ASN1_TRUE {$$=_asn1_add_static_node(TYPE_DEFAULT|CONST_TRUE);}
++ | DEFAULT ASN1_FALSE {$$=_asn1_add_static_node(TYPE_DEFAULT|CONST_FALSE);}
+ ;
+
+
+@@ -201,28 +222,28 @@
+ ;
+
+
+-integer_def: INTEGER {$$=_asn1_add_node(TYPE_INTEGER);}
+- | INTEGER'{'constant_list'}' {$$=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
++integer_def: INTEGER {$$=_asn1_add_static_node(TYPE_INTEGER);}
++ | INTEGER'{'constant_list'}' {$$=_asn1_add_static_node(TYPE_INTEGER|CONST_LIST);
+ _asn1_set_down($$,$3);}
+- | integer_def'(' pos_neg_list ')' {$$=_asn1_add_node(TYPE_INTEGER);}
+- | integer_def'('num_identifier'.''.'num_identifier')'
+- {$$=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX);
+- _asn1_set_down($$,_asn1_add_node(TYPE_SIZE));
++ | integer_def'(' pos_neg_list ')' {$$=_asn1_add_static_node(TYPE_INTEGER);}
++ | integer_def'('int_identifier'.''.'int_identifier')'
++ {$$=_asn1_add_static_node(TYPE_INTEGER|CONST_MIN_MAX);
++ _asn1_set_down($$,_asn1_add_static_node(TYPE_SIZE));
+ _asn1_set_value(_asn1_get_down($$),$6,strlen($6)+1);
+ _asn1_set_name(_asn1_get_down($$),$3);}
+ ;
+
+-boolean_def: BOOLEAN {$$=_asn1_add_node(TYPE_BOOLEAN);}
++boolean_def: BOOLEAN {$$=_asn1_add_static_node(TYPE_BOOLEAN);}
+ ;
+
+-Time: UTCTime {$$=_asn1_add_node(TYPE_TIME|CONST_UTC);}
+- | GeneralizedTime {$$=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);}
++Time: UTCTime {$$=_asn1_add_static_node(TYPE_UTC_TIME);}
++ | GeneralizedTime {$$=_asn1_add_static_node(TYPE_GENERALIZED_TIME);}
+ ;
+
+-size_def2: SIZE'('num_identifier')' {$$=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM);
++size_def2: SIZE'('num_identifier')' {$$=_asn1_add_static_node(TYPE_SIZE|CONST_1_PARAM);
+ _asn1_set_value($$,$3,strlen($3)+1);}
+ | SIZE'('num_identifier'.''.'num_identifier')'
+- {$$=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX);
++ {$$=_asn1_add_static_node(TYPE_SIZE|CONST_MIN_MAX);
+ _asn1_set_value($$,$3,strlen($3)+1);
+ _asn1_set_name($$,$6);}
+ ;
+@@ -231,17 +252,57 @@
+ | '(' size_def2 ')' {$$=$2;}
+ ;
+
+-generalstring_def: GeneralString {$$=_asn1_add_node(TYPE_GENERALSTRING);}
+- | GeneralString size_def {$$=_asn1_add_node(TYPE_GENERALSTRING|CONST_SIZE);
++generalstring_def: GeneralString {$$=_asn1_add_static_node(TYPE_GENERALSTRING);}
++ | GeneralString size_def {$$=_asn1_add_static_node(TYPE_GENERALSTRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++numericstring_def: NumericString {$$=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_UNIVERSAL);}
++ | NumericString size_def {$$=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++ia5string_def: IA5String {$$=_asn1_add_static_node(TYPE_IA5_STRING);}
++ | IA5String size_def {$$=_asn1_add_static_node(TYPE_IA5_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++teletexstring_def: TeletexString {$$=_asn1_add_static_node(TYPE_TELETEX_STRING);}
++ | TeletexString size_def {$$=_asn1_add_static_node(TYPE_TELETEX_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++printablestring_def: PrintableString {$$=_asn1_add_static_node(TYPE_PRINTABLE_STRING);}
++ | PrintableString size_def {$$=_asn1_add_static_node(TYPE_PRINTABLE_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++universalstring_def: UniversalString {$$=_asn1_add_static_node(TYPE_UNIVERSAL_STRING);}
++ | UniversalString size_def {$$=_asn1_add_static_node(TYPE_UNIVERSAL_STRING|CONST_SIZE);
+ _asn1_set_down($$,$2);}
+ ;
+
+-octet_string_def : OCTET STRING {$$=_asn1_add_node(TYPE_OCTET_STRING);}
+- | OCTET STRING size_def {$$=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
++bmpstring_def: BMPString {$$=_asn1_add_static_node(TYPE_BMP_STRING);}
++ | BMPString size_def {$$=_asn1_add_static_node(TYPE_BMP_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++utf8string_def: UTF8String {$$=_asn1_add_static_node(TYPE_UTF8_STRING);}
++ | UTF8String size_def {$$=_asn1_add_static_node(TYPE_UTF8_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++visiblestring_def: VisibleString {$$=_asn1_add_static_node(TYPE_VISIBLE_STRING);}
++ | VisibleString size_def {$$=_asn1_add_static_node(TYPE_VISIBLE_STRING|CONST_SIZE);
++ _asn1_set_down($$,$2);}
++;
++
++octet_string_def : OCTET STRING {$$=_asn1_add_static_node(TYPE_OCTET_STRING);}
++ | OCTET STRING size_def {$$=_asn1_add_static_node(TYPE_OCTET_STRING|CONST_SIZE);
+ _asn1_set_down($$,$3);}
+ ;
+
+-bit_element : IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT);
++bit_element : IDENTIFIER'('NUM')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ _asn1_set_name($$,$1);
+ _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+@@ -251,25 +312,25 @@
+ _asn1_set_right(_asn1_get_last_right($1),$3);}
+ ;
+
+-bit_string_def : BIT STRING {$$=_asn1_add_node(TYPE_BIT_STRING);}
+- | BIT STRING size_def {$$=_asn1_add_node(TYPE_BIT_STRING|CONST_SIZE);}
++bit_string_def : BIT STRING {$$=_asn1_add_static_node(TYPE_BIT_STRING);}
++ | BIT STRING size_def {$$=_asn1_add_static_node(TYPE_BIT_STRING|CONST_SIZE);}
+ | BIT STRING'{'bit_element_list'}'
+- {$$=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
++ {$$=_asn1_add_static_node(TYPE_BIT_STRING|CONST_LIST);
+ _asn1_set_down($$,$4);}
+ ;
+
+ enumerated_def : ENUMERATED'{'bit_element_list'}'
+- {$$=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
++ {$$=_asn1_add_static_node(TYPE_ENUMERATED|CONST_LIST);
+ _asn1_set_down($$,$3);}
+ ;
+
+
+-object_def : OBJECT STR_IDENTIFIER {$$=_asn1_add_node(TYPE_OBJECT_ID);}
++object_def : OBJECT STR_IDENTIFIER {$$=_asn1_add_static_node(TYPE_OBJECT_ID);}
+ ;
+
+-type_assig_right: IDENTIFIER {$$=_asn1_add_node(TYPE_IDENTIFIER);
++type_assig_right: IDENTIFIER {$$=_asn1_add_static_node(TYPE_IDENTIFIER);
+ _asn1_set_value($$,$1,strlen($1)+1);}
+- | IDENTIFIER size_def {$$=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE);
++ | IDENTIFIER size_def {$$=_asn1_add_static_node(TYPE_IDENTIFIER|CONST_SIZE);
+ _asn1_set_value($$,$1,strlen($1)+1);
+ _asn1_set_down($$,$2);}
+ | integer_def {$$=$1;}
+@@ -279,12 +340,20 @@
+ | octet_string_def {$$=$1;}
+ | bit_string_def {$$=$1;}
+ | generalstring_def {$$=$1;}
++ | numericstring_def {$$=$1;}
++ | ia5string_def {$$=$1;}
++ | teletexstring_def {$$=$1;}
++ | printablestring_def {$$=$1;}
++ | universalstring_def {$$=$1;}
++ | bmpstring_def {$$=$1;}
++ | utf8string_def {$$=$1;}
++ | visiblestring_def {$$=$1;}
+ | sequence_def {$$=$1;}
+ | object_def {$$=$1;}
+ | choise_def {$$=$1;}
+ | any_def {$$=$1;}
+ | set_def {$$=$1;}
+- | TOKEN_NULL {$$=_asn1_add_node(TYPE_NULL);}
++ | TOKEN_NULL {$$=_asn1_add_static_node(TYPE_NULL);}
+ ;
+
+ type_assig_right_tag : type_assig_right {$$=$1;}
+@@ -308,48 +377,50 @@
+ _asn1_set_right(_asn1_get_last_right($1),$3);}
+ ;
+
+-sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SEQUENCE);
++sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_static_node(TYPE_SEQUENCE);
+ _asn1_set_down($$,$3);}
+- | SEQUENCE OF type_assig_right {$$=_asn1_add_node(TYPE_SEQUENCE_OF);
++ | SEQUENCE OF type_assig_right {$$=_asn1_add_static_node(TYPE_SEQUENCE_OF);
+ _asn1_set_down($$,$3);}
+- | SEQUENCE size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE);
++ | SEQUENCE size_def OF type_assig_right {$$=_asn1_add_static_node(TYPE_SEQUENCE_OF|CONST_SIZE);
+ _asn1_set_right($2,$4);
+ _asn1_set_down($$,$2);}
+ ;
+
+-set_def : SET'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SET);
++set_def : SET'{'type_assig_list'}' {$$=_asn1_add_static_node(TYPE_SET);
+ _asn1_set_down($$,$3);}
+- | SET OF type_assig_right {$$=_asn1_add_node(TYPE_SET_OF);
++ | SET OF type_assig_right {$$=_asn1_add_static_node(TYPE_SET_OF);
+ _asn1_set_down($$,$3);}
+- | SET size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SET_OF|CONST_SIZE);
++ | SET size_def OF type_assig_right {$$=_asn1_add_static_node(TYPE_SET_OF|CONST_SIZE);
+ _asn1_set_right($2,$4);
+ _asn1_set_down($$,$2);}
+ ;
+
+-choise_def : CHOICE'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_CHOICE);
++choise_def : CHOICE'{'type_assig_list'}' {$$=_asn1_add_static_node(TYPE_CHOICE);
+ _asn1_set_down($$,$3);}
+ ;
+
+-any_def : ANY {$$=_asn1_add_node(TYPE_ANY);}
+- | ANY DEFINED BY IDENTIFIER {$$=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY);
+- _asn1_set_down($$,_asn1_add_node(TYPE_CONSTANT));
++any_def : ANY {$$=_asn1_add_static_node(TYPE_ANY);}
++ | ANY DEFINED BY IDENTIFIER {$$=_asn1_add_static_node(TYPE_ANY|CONST_DEFINED_BY);
++ _asn1_set_down($$,_asn1_add_static_node(TYPE_CONSTANT));
+ _asn1_set_name(_asn1_get_down($$),$4);}
+ ;
+
+ type_def : IDENTIFIER "::=" type_assig_right_tag {$$=_asn1_set_name($3,$1);}
++ /* below should match: BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING etc*/
++ | error "::=" type_assig_right_tag {$$=_asn1_set_name($3, last_error_token);}
+ ;
+
+ constant_def : IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}'
+- {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN);
++ {$$=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN);
+ _asn1_set_name($$,$1);
+ _asn1_set_down($$,$6);}
+ | IDENTIFIER IDENTIFIER "::=" '{' obj_constant_list '}'
+- {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
++ {$$=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
+ _asn1_set_name($$,$1);
+ _asn1_set_value($$,$2,strlen($2)+1);
+ _asn1_set_down($$,$5);}
+ | IDENTIFIER INTEGER "::=" pos_neg_num
+- {$$=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN);
++ {$$=_asn1_add_static_node(TYPE_INTEGER|CONST_ASSIGN);
+ _asn1_set_name($$,$1);
+ _asn1_set_value($$,$4,strlen($4)+1);}
+ ;
+@@ -363,27 +434,29 @@
+ _asn1_set_right(_asn1_get_last_right($1),$2);}
+ ;
+
+-definitions_id : IDENTIFIER '{' obj_constant_list '}' {$$=_asn1_add_node(TYPE_OBJECT_ID);
++definitions_id : IDENTIFIER '{' obj_constant_list '}' {$$=_asn1_add_static_node(TYPE_OBJECT_ID);
+ _asn1_set_down($$,$3);
+ _asn1_set_name($$,$1);}
+- | IDENTIFIER '{' '}' {$$=_asn1_add_node(TYPE_OBJECT_ID);
++ | IDENTIFIER '{' '}' {$$=_asn1_add_static_node(TYPE_OBJECT_ID);
++ _asn1_set_name($$,$1);}
++ | IDENTIFIER {$$=_asn1_add_static_node(TYPE_OBJECT_ID);
+ _asn1_set_name($$,$1);}
+ ;
+
+ /*
+-identifier_list : IDENTIFIER {$$=_asn1_add_node(TYPE_IDENTIFIER);
++identifier_list : IDENTIFIER {$$=_asn1_add_static_node(TYPE_IDENTIFIER);
+ _asn1_set_name($$,$1);}
+ | identifier_list IDENTIFIER
+ {$$=$1;
+- _asn1_set_right(_asn1_get_last_right($$),_asn1_add_node(TYPE_IDENTIFIER));
++ _asn1_set_right(_asn1_get_last_right($$),_asn1_add_static_node(TYPE_IDENTIFIER));
+ _asn1_set_name(_asn1_get_last_right($$),$2);}
+ ;
+
+
+ imports_def : empty {$$=NULL;}
+ | IMPORTS identifier_list FROM IDENTIFIER obj_constant_list
+- {$$=_asn1_add_node(TYPE_IMPORTS);
+- _asn1_set_down($$,_asn1_add_node(TYPE_OBJECT_ID));
++ {$$=_asn1_add_static_node(TYPE_IMPORTS);
++ _asn1_set_down($$,_asn1_add_static_node(TYPE_OBJECT_ID));
+ _asn1_set_name(_asn1_get_down($$),$4);
+ _asn1_set_down(_asn1_get_down($$),$5);
+ _asn1_set_right($$,$2);}
+@@ -400,21 +473,25 @@
+
+
+ static const char *key_word[] = {
+- "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING"
+- ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL"
+- ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER"
+- ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED"
+- ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS"
+- ,"BEGIN","END","UTCTime","GeneralizedTime"
+- ,"GeneralString","FROM","IMPORTS","NULL","ENUMERATED"};
++ "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING",
++ "SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL",
++ "DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER",
++ "BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED",
++ "SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS",
++ "BEGIN","END","UTCTime","GeneralizedTime",
++ "GeneralString","FROM","IMPORTS","NULL","ENUMERATED",
++ "NumericString", "IA5String", "TeletexString", "PrintableString",
++ "UniversalString", "BMPString", "UTF8String", "VisibleString"};
++
+ static const int key_word_token[] = {
+- ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING
+- ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL
+- ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER
+- ,BOOLEAN,ASN1_TRUE,ASN1_FALSE,APPLICATION,ANY,DEFINED
+- ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS
+- ,BEGIN,END,UTCTime,GeneralizedTime
+- ,GeneralString,FROM,IMPORTS,TOKEN_NULL,ENUMERATED};
++ ASSIG, OPTIONAL, INTEGER, SIZE, OCTET, STRING, SEQUENCE, BIT, UNIVERSAL,
++ PRIVATE, OPTIONAL, DEFAULT, CHOICE, OF, OBJECT, STR_IDENTIFIER,
++ BOOLEAN, ASN1_TRUE, ASN1_FALSE, APPLICATION, ANY, DEFINED, SET, BY,
++ EXPLICIT, IMPLICIT, DEFINITIONS, TAGS, BEGIN, END, UTCTime,
++ GeneralizedTime, GeneralString, FROM, IMPORTS, TOKEN_NULL,
++ ENUMERATED, NumericString, IA5String, TeletexString, PrintableString,
++ UniversalString, BMPString, UTF8String, VisibleString
++};
+
+ /*************************************************************/
+ /* Function: _asn1_yylex */
+@@ -423,83 +500,98 @@
+ /* Token identifier or ASCII code or 0(zero: End Of File) */
+ /*************************************************************/
+ static int
+-_asn1_yylex()
++_asn1_yylex ()
+ {
+- int c,counter=0,k,lastc;
+- char string[ASN1_MAX_NAME_SIZE+1]; /* will contain the next token */
++ int c, counter = 0, k, lastc;
++ char string[ASN1_MAX_NAME_SIZE + 1]; /* will contain the next token */
+ size_t i;
+
+- while(1)
++ while (1)
+ {
+- while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+- if(c=='\n') lineNumber++;
+-
+- if(c==EOF){
+- strcpy(lastToken,"End Of File");
+- return 0;
+- }
+-
+- if(c=='(' || c==')' || c=='[' || c==']' ||
+- c=='{' || c=='}' || c==',' || c=='.' ||
+- c=='+' || c=='|'){
+- lastToken[0]=c;lastToken[1]=0;
+- return c;
+- }
+- if(c=='-'){ /* Maybe the first '-' of a comment */
+- if((c=fgetc(file_asn1))!='-'){
+- ungetc(c,file_asn1);
+- lastToken[0]='-';lastToken[1]=0;
+- return '-';
+- }
+- else{ /* Comments */
+- lastc=0;
+- counter=0;
+- /* A comment finishes at the next double hypen or the end of line */
+- while((c=fgetc(file_asn1))!=EOF && c!='\n' &&
+- (lastc!='-' || (lastc=='-' && c!='-')))
+- lastc=c;
+- if(c==EOF){
+- strcpy(lastToken,"End Of File");
+- return 0;
+- }
+- else{
+- if(c=='\n') lineNumber++;
+- continue; /* next char, please! (repeat the search) */
+- }
+- }
+- }
+- string[counter++]=c;
+- /* Till the end of the token */
+- while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' ||
+- c=='(' || c==')' || c=='[' || c==']' ||
+- c=='{' || c=='}' || c==',' || c=='.'))
+- {
+- if(counter>=ASN1_MAX_NAME_SIZE){
+- result_parse=ASN1_NAME_TOO_LONG;
+- return 0;
+- }
+- string[counter++]=c;
+- }
+- ungetc(c,file_asn1);
+- string[counter]=0;
+- strcpy(lastToken,string);
+-
+- /* Is STRING a number? */
+- for(k=0;k<counter;k++)
+- if(!isdigit(string[k])) break;
+- if(k>=counter)
+- {
+- strcpy(yylval.str,string);
+- return NUM; /* return the number */
+- }
+-
+- /* Is STRING a keyword? */
+- for(i=0;i<(sizeof(key_word)/sizeof(char*));i++)
+- if(!strcmp(string,key_word[i])) return key_word_token[i];
+-
+- /* STRING is an IDENTIFIER */
+- strcpy(yylval.str,string);
+- return IDENTIFIER;
++ while ((c = fgetc (file_asn1)) == ' ' || c == '\t' || c == '\n')
++ if (c == '\n')
++ line_number++;
++
++ if (c == EOF)
++ {
++ snprintf (last_token, sizeof(last_token), "End Of File");
++ return 0;
++ }
++
++ if (c == '(' || c == ')' || c == '[' || c == ']' ||
++ c == '{' || c == '}' || c == ',' || c == '.' ||
++ c == '+' || c == '|')
++ {
++ last_token[0] = c;
++ last_token[1] = 0;
++ return c;
++ }
++ if (c == '-')
++ { /* Maybe the first '-' of a comment */
++ if ((c = fgetc (file_asn1)) != '-')
++ {
++ ungetc (c, file_asn1);
++ last_token[0] = '-';
++ last_token[1] = 0;
++ return '-';
++ }
++ else
++ { /* Comments */
++ lastc = 0;
++ counter = 0;
++ /* A comment finishes at the next double hypen or the end of line */
++ while ((c = fgetc (file_asn1)) != EOF && c != '\n' &&
++ (lastc != '-' || (lastc == '-' && c != '-')))
++ lastc = c;
++ if (c == EOF)
++ {
++ snprintf (last_token, sizeof(last_token), "End Of File");
++ return 0;
++ }
++ else
++ {
++ if (c == '\n')
++ line_number++;
++ continue; /* next char, please! (repeat the search) */
++ }
++ }
++ }
++ string[counter++] = c;
++ /* Till the end of the token */
++ while (!
++ ((c = fgetc (file_asn1)) == EOF || c == ' ' || c == '\t'
++ || c == '\n' || c == '(' || c == ')' || c == '[' || c == ']'
++ || c == '{' || c == '}' || c == ',' || c == '.'))
++ {
++ if (counter >= ASN1_MAX_NAME_SIZE)
++ {
++ result_parse = ASN1_NAME_TOO_LONG;
++ return 0;
++ }
++ string[counter++] = c;
++ }
++ ungetc (c, file_asn1);
++ string[counter] = 0;
++ snprintf (last_token, sizeof(last_token), "%s", string);
++
++ /* Is STRING a number? */
++ for (k = 0; k < counter; k++)
++ if (!isdigit (string[k]))
++ break;
++ if (k >= counter)
++ {
++ snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++ return NUM; /* return the number */
++ }
++
++ /* Is STRING a keyword? */
++ for (i = 0; i < (sizeof (key_word) / sizeof (char *)); i++)
++ if (!strcmp (string, key_word[i]))
++ return key_word_token[i];
++
++ /* STRING is an IDENTIFIER */
++ snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++ return IDENTIFIER;
+ }
+ }
+
+@@ -509,136 +601,121 @@
+ /* error. */
+ /* Parameters: */
+ /* error : error to describe. */
+-/* errorDescription: string that will contain the */
++/* error_desc: string that will contain the */
+ /* description. */
+ /*************************************************************/
+ static void
+-_asn1_create_errorDescription(int error,char *errorDescription)
++_asn1_create_errorDescription (int error, char *error_desc)
+ {
+- switch(error){
+- case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND:
+- if (errorDescription!=NULL) errorDescription[0]=0;
+- break;
+- case ASN1_SYNTAX_ERROR:
+- if (errorDescription!=NULL) {
+- strcpy(errorDescription,fileName);
+- strcat(errorDescription,":");
+- _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+- strcat(errorDescription,": parse error near '");
+- strcat(errorDescription,lastToken);
+- strcat(errorDescription,"'");
+- }
+- break;
+- case ASN1_NAME_TOO_LONG:
+- if (errorDescription!=NULL) {
+- strcpy(errorDescription,fileName);
+- strcat(errorDescription,":");
+- _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+- strcat(errorDescription,": name too long (more than ");
+- _asn1_ltostr(ASN1_MAX_NAME_SIZE,errorDescription+strlen(errorDescription));
+- strcat(errorDescription," characters)");
+- }
+- break;
+- case ASN1_IDENTIFIER_NOT_FOUND:
+- if (errorDescription!=NULL) {
+- strcpy(errorDescription,fileName);
+- strcat(errorDescription,":");
+- strcat(errorDescription,": identifier '");
+- strcat(errorDescription,_asn1_identifierMissing);
+- strcat(errorDescription,"' not found");
++ if (error_desc == NULL)
++ return;
++
++
++ switch (error)
++ {
++ case ASN1_FILE_NOT_FOUND:
++ snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s file was not found", file_name);
++ break;
++ case ASN1_SYNTAX_ERROR:
++ snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_error);
++ break;
++ case ASN1_NAME_TOO_LONG:
++ snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++ "%s:%u: name too long (more than %u characters)", file_name,
++ line_number, ASN1_MAX_NAME_SIZE);
++ break;
++ case ASN1_IDENTIFIER_NOT_FOUND:
++ snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++ "%s:: identifier '%s' not found", file_name,
++ _asn1_identifierMissing);
++ break;
++ default:
++ error_desc[0] = 0;
++ break;
+ }
+- break;
+- default:
+- if (errorDescription!=NULL) errorDescription[0]=0;
+- break;
+- }
+
+ }
+
+ /**
+ * asn1_parser2tree:
+- * @file_name: specify the path and the name of file that contains
++ * @file: specify the path and the name of file that contains
+ * ASN.1 declarations.
+ * @definitions: return the pointer to the structure created from
+- * "file_name" ASN.1 declarations.
+- * @errorDescription: return the error description or an empty
++ * "file" ASN.1 declarations.
++ * @error_desc: return the error description or an empty
+ * string if success.
+ *
+ * Function used to start the parse algorithm. Creates the structures
+- * needed to manage the definitions included in @file_name file.
+- *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- * is known.
+- *
+- * %ASN1_ELEMENT_NOT_EMPTY: @definitions not %ASN1_TYPE_EMPTY.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @file_name.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
++ * needed to manage the definitions included in @file file.
+ *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- * than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ * identifier is known, %ASN1_ELEMENT_NOT_EMPTY if @definitions not
++ * %NULL, %ASN1_FILE_NOT_FOUND if an error occured while
++ * opening @file, %ASN1_SYNTAX_ERROR if the syntax is not
++ * correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an
++ * identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ * file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ * characters.
+ **/
+-asn1_retCode
+-asn1_parser2tree(const char *file_name, ASN1_TYPE *definitions,
+- char *errorDescription){
++int
++asn1_parser2tree (const char *file, ASN1_TYPE * definitions,
++ char *error_desc)
++{
+
+- p_tree=ASN1_TYPE_EMPTY;
++ p_tree = NULL;
+
+- if(*definitions != ASN1_TYPE_EMPTY)
++ if (*definitions != NULL)
+ return ASN1_ELEMENT_NOT_EMPTY;
+
+- *definitions=ASN1_TYPE_EMPTY;
++ *definitions = NULL;
+
+- fileName = file_name;
++ file_name = file;
+
+ /* open the file to parse */
+- file_asn1=fopen(file_name,"r");
++ file_asn1 = fopen (file, "r");
+
+- if(file_asn1==NULL){
+- result_parse=ASN1_FILE_NOT_FOUND;
+- }
+- else{
+- result_parse=ASN1_SUCCESS;
+-
+- lineNumber=1;
+- yyparse();
+-
+- fclose(file_asn1);
+-
+- if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+- /* set IMPLICIT or EXPLICIT property */
+- _asn1_set_default_tag(p_tree);
+- /* set CONST_SET and CONST_NOT_USED */
+- _asn1_type_set_config(p_tree);
+- /* check the identifier definitions */
+- result_parse=_asn1_check_identifier(p_tree);
+- if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+- /* Delete the list and keep the ASN1 structure */
+- _asn1_delete_list();
+- /* Convert into DER coding the value assign to INTEGER constants */
+- _asn1_change_integer_value(p_tree);
+- /* Expand the IDs of OBJECT IDENTIFIER constants */
+- _asn1_expand_object_id(p_tree);
+-
+- *definitions=p_tree;
+- }
+- else /* some identifiers not defined */
+- /* Delete the list and the ASN1 structure */
+- _asn1_delete_list_and_nodes();
++ if (file_asn1 == NULL)
++ {
++ result_parse = ASN1_FILE_NOT_FOUND;
++ }
++ else
++ {
++ result_parse = ASN1_SUCCESS;
++
++ line_number = 1;
++ yyparse ();
++
++ fclose (file_asn1);
++
++ if (result_parse == ASN1_SUCCESS)
++ { /* syntax OK */
++ /* set IMPLICIT or EXPLICIT property */
++ _asn1_set_default_tag (p_tree);
++ /* set CONST_SET and CONST_NOT_USED */
++ _asn1_type_set_config (p_tree);
++ /* check the identifier definitions */
++ result_parse = _asn1_check_identifier (p_tree);
++ if (result_parse == ASN1_SUCCESS)
++ { /* all identifier defined */
++ /* Delete the list and keep the ASN1 structure */
++ _asn1_delete_list ();
++ /* Convert into DER coding the value assign to INTEGER constants */
++ _asn1_change_integer_value (p_tree);
++ /* Expand the IDs of OBJECT IDENTIFIER constants */
++ _asn1_expand_object_id (p_tree);
++
++ *definitions = p_tree;
++ }
++ else /* some identifiers not defined */
++ /* Delete the list and the ASN1 structure */
++ _asn1_delete_list_and_nodes ();
++ }
++ else /* syntax error */
++ /* Delete the list and the ASN1 structure */
++ _asn1_delete_list_and_nodes ();
+ }
+- else /* syntax error */
+- /* Delete the list and the ASN1 structure */
+- _asn1_delete_list_and_nodes();
+- }
+
+- if (errorDescription!=NULL)
+- _asn1_create_errorDescription(result_parse,errorDescription);
++ _asn1_create_errorDescription (result_parse, error_desc);
+
+ return result_parse;
+ }
+@@ -650,7 +727,7 @@
+ * @outputFileName: specify the path and the name of file that will
+ * contain the C vector definition.
+ * @vectorName: specify the name of the C vector.
+- * @errorDescription : return the error description or an empty
++ * @error_desc: return the error description or an empty
+ * string if success.
+ *
+ * Function that generates a C structure from an ASN1 file. Creates a
+@@ -660,113 +737,118 @@
+ * "/aa/bb/xx_asn1_tab.c". If @vectorName is %NULL the vector name
+ * will be "xx_asn1_tab".
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- * is known.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @inputFileName.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- * than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ * identifier is known, %ASN1_FILE_NOT_FOUND if an error occured
++ * while opening @inputFileName, %ASN1_SYNTAX_ERROR if the syntax is
++ * not correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is
++ * an identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ * file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ * characters.
+ **/
+-int asn1_parser2array(const char *inputFileName,const char *outputFileName,
+- const char *vectorName,char *errorDescription){
+- char *file_out_name=NULL;
+- char *vector_name=NULL;
+- const char *char_p,*slash_p,*dot_p;
++int
++asn1_parser2array (const char *inputFileName, const char *outputFileName,
++ const char *vectorName, char *error_desc)
++{
++ char *file_out_name = NULL;
++ char *vector_name = NULL;
++ const char *char_p, *slash_p, *dot_p;
+
+- p_tree=NULL;
++ p_tree = NULL;
+
+- fileName = inputFileName;
++ file_name = inputFileName;
+
+ /* open the file to parse */
+- file_asn1=fopen(inputFileName,"r");
++ file_asn1 = fopen (inputFileName, "r");
++
++ if (file_asn1 == NULL)
++ result_parse = ASN1_FILE_NOT_FOUND;
++ else
++ {
++ result_parse = ASN1_SUCCESS;
++
++ line_number = 1;
++ yyparse ();
+
+- if(file_asn1==NULL)
+- result_parse=ASN1_FILE_NOT_FOUND;
+- else{
+- result_parse=ASN1_SUCCESS;
+-
+- lineNumber=1;
+- yyparse();
+-
+- fclose(file_asn1);
+-
+- if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+- /* set IMPLICIT or EXPLICIT property */
+- _asn1_set_default_tag(p_tree);
+- /* set CONST_SET and CONST_NOT_USED */
+- _asn1_type_set_config(p_tree);
+- /* check the identifier definitions */
+- result_parse=_asn1_check_identifier(p_tree);
+-
+- if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+-
+- /* searching the last '/' and '.' in inputFileName */
+- char_p=inputFileName;
+- slash_p=inputFileName;
+- while((char_p=strchr(char_p,'/'))){
+- char_p++;
+- slash_p=char_p;
+- }
+-
+- char_p=slash_p;
+- dot_p=inputFileName+strlen(inputFileName);
+-
+- while((char_p=strchr(char_p,'.'))){
+- dot_p=char_p;
+- char_p++;
+- }
+-
+- if(outputFileName == NULL){
+- /* file_out_name = inputFileName + _asn1_tab.c */
+- file_out_name=(char *)malloc(dot_p-inputFileName+1+
+- strlen("_asn1_tab.c"));
+- memcpy(file_out_name,inputFileName,dot_p-inputFileName);
+- file_out_name[dot_p-inputFileName]=0;
+- strcat(file_out_name,"_asn1_tab.c");
+- }
+- else{
+- /* file_out_name = inputFileName */
+- file_out_name=(char *)malloc(strlen(outputFileName)+1);
+- strcpy(file_out_name,outputFileName);
+- }
+-
+- if(vectorName == NULL){
+- /* vector_name = file name + _asn1_tab */
+- vector_name=(char *)malloc(dot_p-slash_p+1+
+- strlen("_asn1_tab"));
+- memcpy(vector_name,slash_p,dot_p-slash_p);
+- vector_name[dot_p-slash_p]=0;
+- strcat(vector_name,"_asn1_tab");
+- }
+- else{
+- /* vector_name = vectorName */
+- vector_name=(char *)malloc(strlen(vectorName)+1);
+- strcpy(vector_name,vectorName);
+- }
+-
+- /* Save structure in a file */
+- _asn1_create_static_structure(p_tree,
+- file_out_name,vector_name);
+-
+- free(file_out_name);
+- free(vector_name);
+- } /* result == OK */
+- } /* result == OK */
+-
+- /* Delete the list and the ASN1 structure */
+- _asn1_delete_list_and_nodes();
+- } /* inputFile exist */
++ fclose (file_asn1);
+
+- if (errorDescription!=NULL)
+- _asn1_create_errorDescription(result_parse,errorDescription);
++ if (result_parse == ASN1_SUCCESS)
++ { /* syntax OK */
++ /* set IMPLICIT or EXPLICIT property */
++ _asn1_set_default_tag (p_tree);
++ /* set CONST_SET and CONST_NOT_USED */
++ _asn1_type_set_config (p_tree);
++ /* check the identifier definitions */
++ result_parse = _asn1_check_identifier (p_tree);
++
++ if (result_parse == ASN1_SUCCESS)
++ { /* all identifier defined */
++
++ /* searching the last '/' and '.' in inputFileName */
++ char_p = inputFileName;
++ slash_p = inputFileName;
++ while ((char_p = strchr (char_p, '/')))
++ {
++ char_p++;
++ slash_p = char_p;
++ }
++
++ char_p = slash_p;
++ dot_p = inputFileName + strlen (inputFileName);
++
++ while ((char_p = strchr (char_p, '.')))
++ {
++ dot_p = char_p;
++ char_p++;
++ }
++
++ if (outputFileName == NULL)
++ {
++ /* file_out_name = inputFileName + _asn1_tab.c */
++ file_out_name = malloc (dot_p - inputFileName + 1 +
++ strlen ("_asn1_tab.c"));
++ memcpy (file_out_name, inputFileName,
++ dot_p - inputFileName);
++ file_out_name[dot_p - inputFileName] = 0;
++ strcat (file_out_name, "_asn1_tab.c");
++ }
++ else
++ {
++ /* file_out_name = inputFileName */
++ file_out_name =
++ (char *) malloc (strlen (outputFileName) + 1);
++ strcpy (file_out_name, outputFileName);
++ }
++
++ if (vectorName == NULL)
++ {
++ /* vector_name = file name + _asn1_tab */
++ vector_name = malloc (dot_p - slash_p + 1 +
++ strlen ("_asn1_tab"));
++ memcpy (vector_name, slash_p, dot_p - slash_p);
++ vector_name[dot_p - slash_p] = 0;
++ strcat (vector_name, "_asn1_tab");
++ }
++ else
++ {
++ /* vector_name = vectorName */
++ vector_name = (char *) malloc (strlen (vectorName) + 1);
++ strcpy (vector_name, vectorName);
++ }
++
++ /* Save structure in a file */
++ _asn1_create_static_structure (p_tree,
++ file_out_name, vector_name);
++
++ free (file_out_name);
++ free (vector_name);
++ } /* result == OK */
++ } /* result == OK */
++
++ /* Delete the list and the ASN1 structure */
++ _asn1_delete_list_and_nodes ();
++ } /* inputFile exist */
++
++ _asn1_create_errorDescription (result_parse, error_desc);
+
+ return result_parse;
+ }
+@@ -779,17 +861,35 @@
+ /* Return: int */
+ /* */
+ /*************************************************************/
+-static int _asn1_yyerror (const char *s)
++static void
++_asn1_yyerror (const char *s)
+ {
+ /* Sends the error description to the std_out */
+
+-#if 0
+- printf("_asn1_yyerror:%s:%ld: %s (Last Token:'%s')\n",fileName,
+- lineNumber,s,lastToken);
+-#endif
++ if (strcmp (last_token, "VisibleString") == 0 ||
++ strcmp (last_token, "PrintableString") == 0 ||
++ strcmp (last_token, "UniversalString") == 0 ||
++ strcmp (last_token, "IA5String") == 0 ||
++ strcmp (last_token, "UTF8String") == 0 ||
++ strcmp (last_token, "NumericString") == 0 ||
++ strcmp (last_token, "TeletexString") == 0 ||
++ strcmp (last_token, "BMPString") == 0)
++ {
++ snprintf (last_error_token, sizeof(last_error_token),
++ "%s", last_token);
++ fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n",
++ file_name, line_number, last_token);
++ return;
++ }
++ last_error_token[0] = 0;
+
+- if(result_parse!=ASN1_NAME_TOO_LONG)
+- result_parse=ASN1_SYNTAX_ERROR;
++ if (result_parse != ASN1_NAME_TOO_LONG)
++ {
++ snprintf (last_error, sizeof(last_error),
++ "%s:%u: Error: %s near '%s'", file_name,
++ line_number, s, last_token);
++ result_parse = ASN1_SYNTAX_ERROR;
++ }
+
+- return 0;
++ return;
+ }
+--- ORIGINAL/./lib/ASN1.c 2015-07-14 18:28:22.941869639 -0700
++++ libtasn1-2.8/./lib/ASN1.c 2015-07-14 18:45:02.758734575 -0700
+@@ -1,21 +1,20 @@
+-
+ /* A Bison parser, made by GNU Bison 2.4.1. */
+
+ /* Skeleton implementation for Bison's Yacc-like parsers in C
+-
++
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+-
++
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+-
++
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+-
++
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+@@ -28,7 +27,7 @@
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+-
++
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+@@ -46,7 +45,7 @@
+ #define YYBISON 1
+
+ /* Bison version. */
+-#define YYBISON_VERSION "2.4.1"
++#define YYBISON_VERSION "3.0.2"
+
+ /* Skeleton name. */
+ #define YYSKELETON_NAME "yacc.c"
+@@ -60,27 +59,22 @@
+ /* Pull parsers. */
+ #define YYPULL 1
+
+-/* Using locations. */
+-#define YYLSP_NEEDED 0
+
+ /* Substitute the variable and function names. */
+ #define yyparse _asn1_yyparse
+ #define yylex _asn1_yylex
+ #define yyerror _asn1_yyerror
+-#define yylval _asn1_yylval
+-#define yychar _asn1_yychar
+ #define yydebug _asn1_yydebug
+ #define yynerrs _asn1_yynerrs
+
++#define yylval _asn1_yylval
++#define yychar _asn1_yychar
+
+ /* Copy the first part of user declarations. */
+-
+-/* Line 189 of yacc.c */
+-#line 1 "ASN1.y"
++#line 1 "ASN1.y" /* yacc.c:339 */
+
+ /*
+- * Copyright (C) 2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 Free
+- * Software Foundation, Inc.
++ * Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+@@ -110,94 +104,108 @@
+ #include <int.h>
+ #include <parser_aux.h>
+ #include <structure.h>
++#include <libtasn1.h>
+
+ static FILE *file_asn1; /* Pointer to file to parse */
+-static asn1_retCode result_parse; /* result of the parser
++static int result_parse = 0; /* result of the parser
+ algorithm */
+ static ASN1_TYPE p_tree; /* pointer to the root of the
+ structure created by the
+ parser*/
+-static unsigned long lineNumber; /* line number describing the
++static unsigned int line_number; /* line number describing the
+ parser position inside the
+ file */
+-static char lastToken[ASN1_MAX_NAME_SIZE+1]; /* last token find in the file
++static char last_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
++static char last_error_token[ASN1_MAX_ERROR_DESCRIPTION_SIZE+1] = ""; /* used when expected errors occur */
++static char last_token[ASN1_MAX_NAME_SIZE+1] = ""; /* last token find in the file
+ to parse before the 'parse
+ error' */
+ extern char _asn1_identifierMissing[];
+-static const char *fileName; /* file to parse */
++static const char *file_name; /* file to parse */
+
+-static int _asn1_yyerror (const char *);
++static void _asn1_yyerror (const char *);
+ static int _asn1_yylex(void);
+
+
++#line 130 "ASN1.c" /* yacc.c:339 */
+
+-/* Line 189 of yacc.c */
+-#line 136 "ASN1.c"
+-
+-/* Enabling traces. */
+-#ifndef YYDEBUG
+-# define YYDEBUG 0
+-#endif
++# ifndef YY_NULLPTR
++# if defined __cplusplus && 201103L <= __cplusplus
++# define YY_NULLPTR nullptr
++# else
++# define YY_NULLPTR 0
++# endif
++# endif
+
+ /* Enabling verbose error messages. */
+ #ifdef YYERROR_VERBOSE
+ # undef YYERROR_VERBOSE
+ # define YYERROR_VERBOSE 1
+ #else
+-# define YYERROR_VERBOSE 0
++# define YYERROR_VERBOSE 1
+ #endif
+
+-/* Enabling the token table. */
+-#ifndef YYTOKEN_TABLE
+-# define YYTOKEN_TABLE 0
+-#endif
+
++/* Debug traces. */
++#ifndef YYDEBUG
++# define YYDEBUG 0
++#endif
++#if YYDEBUG
++extern int _asn1_yydebug;
++#endif
+
+-/* Tokens. */
++/* Token type. */
+ #ifndef YYTOKENTYPE
+ # define YYTOKENTYPE
+- /* Put the tokens into the symbol table, so that GDB and other debuggers
+- know about them. */
+- enum yytokentype {
+- ASSIG = 258,
+- NUM = 259,
+- IDENTIFIER = 260,
+- OPTIONAL = 261,
+- INTEGER = 262,
+- SIZE = 263,
+- OCTET = 264,
+- STRING = 265,
+- SEQUENCE = 266,
+- BIT = 267,
+- UNIVERSAL = 268,
+- PRIVATE = 269,
+- APPLICATION = 270,
+- DEFAULT = 271,
+- CHOICE = 272,
+- OF = 273,
+- OBJECT = 274,
+- STR_IDENTIFIER = 275,
+- BOOLEAN = 276,
+- ASN1_TRUE = 277,
+- ASN1_FALSE = 278,
+- TOKEN_NULL = 279,
+- ANY = 280,
+- DEFINED = 281,
+- BY = 282,
+- SET = 283,
+- EXPLICIT = 284,
+- IMPLICIT = 285,
+- DEFINITIONS = 286,
+- TAGS = 287,
+- BEGIN = 288,
+- END = 289,
+- UTCTime = 290,
+- GeneralizedTime = 291,
+- GeneralString = 292,
+- FROM = 293,
+- IMPORTS = 294,
+- ENUMERATED = 295
+- };
++ enum yytokentype
++ {
++ ASSIG = 258,
++ NUM = 259,
++ IDENTIFIER = 260,
++ OPTIONAL = 261,
++ INTEGER = 262,
++ SIZE = 263,
++ OCTET = 264,
++ STRING = 265,
++ SEQUENCE = 266,
++ BIT = 267,
++ UNIVERSAL = 268,
++ PRIVATE = 269,
++ APPLICATION = 270,
++ DEFAULT = 271,
++ CHOICE = 272,
++ OF = 273,
++ OBJECT = 274,
++ STR_IDENTIFIER = 275,
++ BOOLEAN = 276,
++ ASN1_TRUE = 277,
++ ASN1_FALSE = 278,
++ TOKEN_NULL = 279,
++ ANY = 280,
++ DEFINED = 281,
++ BY = 282,
++ SET = 283,
++ EXPLICIT = 284,
++ IMPLICIT = 285,
++ DEFINITIONS = 286,
++ TAGS = 287,
++ BEGIN = 288,
++ END = 289,
++ UTCTime = 290,
++ GeneralizedTime = 291,
++ GeneralString = 292,
++ NumericString = 293,
++ IA5String = 294,
++ TeletexString = 295,
++ PrintableString = 296,
++ UniversalString = 297,
++ BMPString = 298,
++ UTF8String = 299,
++ VisibleString = 300,
++ FROM = 301,
++ IMPORTS = 302,
++ ENUMERATED = 303
++ };
+ #endif
+ /* Tokens. */
+ #define ASSIG 258
+@@ -235,40 +243,45 @@
+ #define UTCTime 290
+ #define GeneralizedTime 291
+ #define GeneralString 292
+-#define FROM 293
+-#define IMPORTS 294
+-#define ENUMERATED 295
+-
+-
+-
++#define NumericString 293
++#define IA5String 294
++#define TeletexString 295
++#define PrintableString 296
++#define UniversalString 297
++#define BMPString 298
++#define UTF8String 299
++#define VisibleString 300
++#define FROM 301
++#define IMPORTS 302
++#define ENUMERATED 303
+
++/* Value type. */
+ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+-typedef union YYSTYPE
++typedef union YYSTYPE YYSTYPE;
++union YYSTYPE
+ {
+-
+-/* Line 214 of yacc.c */
+-#line 58 "ASN1.y"
++#line 62 "ASN1.y" /* yacc.c:355 */
+
+ unsigned int constant;
+ char str[ASN1_MAX_NAME_SIZE+1];
+ ASN1_TYPE node;
+
+-
+-
+-/* Line 214 of yacc.c */
+-#line 260 "ASN1.c"
+-} YYSTYPE;
++#line 269 "ASN1.c" /* yacc.c:355 */
++};
+ # define YYSTYPE_IS_TRIVIAL 1
+-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+ # define YYSTYPE_IS_DECLARED 1
+ #endif
+
+
+-/* Copy the second part of user declarations. */
++extern YYSTYPE _asn1_yylval;
++
++int _asn1_yyparse (void);
++
+
+
+-/* Line 264 of yacc.c */
+-#line 272 "ASN1.c"
++/* Copy the second part of user declarations. */
++
++#line 284 "ASN1.c" /* yacc.c:358 */
+
+ #ifdef short
+ # undef short
+@@ -282,11 +295,8 @@
+
+ #ifdef YYTYPE_INT8
+ typedef YYTYPE_INT8 yytype_int8;
+-#elif (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+-typedef signed char yytype_int8;
+ #else
+-typedef short int yytype_int8;
++typedef signed char yytype_int8;
+ #endif
+
+ #ifdef YYTYPE_UINT16
+@@ -306,8 +316,7 @@
+ # define YYSIZE_T __SIZE_TYPE__
+ # elif defined size_t
+ # define YYSIZE_T size_t
+-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
++# elif ! defined YYSIZE_T
+ # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+ # define YYSIZE_T size_t
+ # else
+@@ -318,42 +327,71 @@
+ #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+ #ifndef YY_
+-# if YYENABLE_NLS
++# if defined YYENABLE_NLS && YYENABLE_NLS
+ # if ENABLE_NLS
+ # include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+-# define YY_(msgid) dgettext ("bison-runtime", msgid)
++# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+ # endif
+ # endif
+ # ifndef YY_
+-# define YY_(msgid) msgid
++# define YY_(Msgid) Msgid
++# endif
++#endif
++
++#ifndef YY_ATTRIBUTE
++# if (defined __GNUC__ \
++ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
++ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
++# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
++# else
++# define YY_ATTRIBUTE(Spec) /* empty */
++# endif
++#endif
++
++#ifndef YY_ATTRIBUTE_PURE
++# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
++#endif
++
++#ifndef YY_ATTRIBUTE_UNUSED
++# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
++#endif
++
++#if !defined _Noreturn \
++ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
++# if defined _MSC_VER && 1200 <= _MSC_VER
++# define _Noreturn __declspec (noreturn)
++# else
++# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+ # endif
+ #endif
+
+ /* Suppress unused-variable warnings by "using" E. */
+ #if ! defined lint || defined __GNUC__
+-# define YYUSE(e) ((void) (e))
++# define YYUSE(E) ((void) (E))
+ #else
+-# define YYUSE(e) /* empty */
++# define YYUSE(E) /* empty */
+ #endif
+
+-/* Identity function, used to suppress warnings about constant conditions. */
+-#ifndef lint
+-# define YYID(n) (n)
++#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
++/* Suppress an incorrect diagnostic about yylval being uninitialized. */
++# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
++ _Pragma ("GCC diagnostic push") \
++ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
++ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
++# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
++ _Pragma ("GCC diagnostic pop")
+ #else
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+-static int
+-YYID (int yyi)
+-#else
+-static int
+-YYID (yyi)
+- int yyi;
++# define YY_INITIAL_VALUE(Value) Value
+ #endif
+-{
+- return yyi;
+-}
++#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
++# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
++# define YY_IGNORE_MAYBE_UNINITIALIZED_END
++#endif
++#ifndef YY_INITIAL_VALUE
++# define YY_INITIAL_VALUE(Value) /* Nothing. */
+ #endif
+
++
+ #if ! defined yyoverflow || YYERROR_VERBOSE
+
+ /* The parser invokes alloca or malloc; define the necessary symbols. */
+@@ -371,11 +409,11 @@
+ # define alloca _alloca
+ # else
+ # define YYSTACK_ALLOC alloca
+-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
++# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+ # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+-# ifndef _STDLIB_H
+-# define _STDLIB_H 1
++ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
++# ifndef EXIT_SUCCESS
++# define EXIT_SUCCESS 0
+ # endif
+ # endif
+ # endif
+@@ -383,8 +421,8 @@
+ # endif
+
+ # ifdef YYSTACK_ALLOC
+- /* Pacify GCC's `empty if-body' warning. */
+-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
++ /* Pacify GCC's 'empty if-body' warning. */
++# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+ # ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+@@ -398,25 +436,23 @@
+ # ifndef YYSTACK_ALLOC_MAXIMUM
+ # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+ # endif
+-# if (defined __cplusplus && ! defined _STDLIB_H \
++# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+- && (defined YYFREE || defined free)))
++ && (defined YYFREE || defined free)))
+ # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+-# ifndef _STDLIB_H
+-# define _STDLIB_H 1
++# ifndef EXIT_SUCCESS
++# define EXIT_SUCCESS 0
+ # endif
+ # endif
+ # ifndef YYMALLOC
+ # define YYMALLOC malloc
+-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
++# if ! defined malloc && ! defined EXIT_SUCCESS
+ void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+ # endif
+ # endif
+ # ifndef YYFREE
+ # define YYFREE free
+-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
++# if ! defined free && ! defined EXIT_SUCCESS
+ void free (void *); /* INFRINGES ON USER NAME SPACE */
+ # endif
+ # endif
+@@ -426,7 +462,7 @@
+
+ #if (! defined yyoverflow \
+ && (! defined __cplusplus \
+- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
++ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+ /* A type that is properly aligned for any stack member. */
+ union yyalloc
+@@ -444,79 +480,85 @@
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+-/* Copy COUNT objects from FROM to TO. The source and destination do
+- not overlap. */
+-# ifndef YYCOPY
+-# if defined __GNUC__ && 1 < __GNUC__
+-# define YYCOPY(To, From, Count) \
+- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+-# else
+-# define YYCOPY(To, From, Count) \
+- do \
+- { \
+- YYSIZE_T yyi; \
+- for (yyi = 0; yyi < (Count); yyi++) \
+- (To)[yyi] = (From)[yyi]; \
+- } \
+- while (YYID (0))
+-# endif
+-# endif
++# define YYCOPY_NEEDED 1
+
+ /* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+- do \
+- { \
+- YYSIZE_T yynewbytes; \
+- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+- Stack = &yyptr->Stack_alloc; \
+- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+- yyptr += yynewbytes / sizeof (*yyptr); \
+- } \
+- while (YYID (0))
++# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
++ do \
++ { \
++ YYSIZE_T yynewbytes; \
++ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
++ Stack = &yyptr->Stack_alloc; \
++ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
++ yyptr += yynewbytes / sizeof (*yyptr); \
++ } \
++ while (0)
+
+ #endif
+
++#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
++/* Copy COUNT objects from SRC to DST. The source and destination do
++ not overlap. */
++# ifndef YYCOPY
++# if defined __GNUC__ && 1 < __GNUC__
++# define YYCOPY(Dst, Src, Count) \
++ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
++# else
++# define YYCOPY(Dst, Src, Count) \
++ do \
++ { \
++ YYSIZE_T yyi; \
++ for (yyi = 0; yyi < (Count); yyi++) \
++ (Dst)[yyi] = (Src)[yyi]; \
++ } \
++ while (0)
++# endif
++# endif
++#endif /* !YYCOPY_NEEDED */
++
+ /* YYFINAL -- State number of the termination state. */
+ #define YYFINAL 5
+ /* YYLAST -- Last index in YYTABLE. */
+-#define YYLAST 192
++#define YYLAST 223
+
+ /* YYNTOKENS -- Number of terminals. */
+-#define YYNTOKENS 52
++#define YYNTOKENS 60
+ /* YYNNTS -- Number of nonterminals. */
+-#define YYNNTS 43
++#define YYNNTS 52
+ /* YYNRULES -- Number of rules. */
+-#define YYNRULES 99
+-/* YYNRULES -- Number of states. */
+-#define YYNSTATES 190
++#define YYNRULES 128
++/* YYNSTATES -- Number of states. */
++#define YYNSTATES 223
+
+-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
++/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
++ by yylex, with out-of-bounds checking. */
+ #define YYUNDEFTOK 2
+-#define YYMAXUTOK 295
++#define YYMAXUTOK 303
+
+-#define YYTRANSLATE(YYX) \
++#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
++/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
++ as returned by yylex, without out-of-bounds checking. */
+ static const yytype_uint8 yytranslate[] =
+ {
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 43, 44, 2, 41, 45, 42, 51, 2, 2, 2,
++ 51, 52, 2, 49, 53, 50, 59, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 46, 2, 47, 2, 2, 2, 2, 2, 2,
++ 2, 54, 2, 55, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 49, 48, 50, 2, 2, 2, 2,
++ 2, 2, 2, 57, 56, 58, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+@@ -533,81 +575,31 @@
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+- 35, 36, 37, 38, 39, 40
++ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
++ 45, 46, 47, 48
+ };
+
+ #if YYDEBUG
+-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+- YYRHS. */
+-static const yytype_uint16 yyprhs[] =
+-{
+- 0, 0, 3, 12, 14, 17, 20, 22, 24, 26,
+- 28, 30, 32, 36, 41, 43, 47, 49, 54, 56,
+- 59, 61, 63, 65, 69, 74, 76, 79, 82, 85,
+- 88, 91, 93, 97, 99, 104, 109, 117, 119, 121,
+- 123, 128, 136, 138, 142, 144, 147, 150, 154, 159,
+- 161, 165, 168, 172, 178, 183, 186, 188, 191, 193,
+- 195, 197, 199, 201, 203, 205, 207, 209, 211, 213,
+- 215, 217, 219, 222, 224, 227, 230, 233, 235, 239,
+- 244, 248, 253, 258, 262, 267, 272, 274, 279, 283,
+- 291, 298, 303, 305, 307, 309, 312, 317, 321, 323
+-};
+-
+-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+-static const yytype_int8 yyrhs[] =
+-{
+- 53, 0, -1, 93, 31, 94, 32, 3, 33, 92,
+- 34, -1, 4, -1, 41, 4, -1, 42, 4, -1,
+- 54, -1, 55, -1, 4, -1, 5, -1, 56, -1,
+- 5, -1, 43, 56, 44, -1, 5, 43, 56, 44,
+- -1, 59, -1, 60, 45, 59, -1, 57, -1, 5,
+- 43, 4, 44, -1, 61, -1, 62, 61, -1, 13,
+- -1, 14, -1, 15, -1, 46, 4, 47, -1, 46,
+- 63, 4, 47, -1, 64, -1, 64, 29, -1, 64,
+- 30, -1, 16, 58, -1, 16, 22, -1, 16, 23,
+- -1, 56, -1, 67, 48, 56, -1, 7, -1, 7,
+- 49, 60, 50, -1, 68, 43, 67, 44, -1, 68,
+- 43, 57, 51, 51, 57, 44, -1, 21, -1, 35,
+- -1, 36, -1, 8, 43, 57, 44, -1, 8, 43,
+- 57, 51, 51, 57, 44, -1, 71, -1, 43, 71,
+- 44, -1, 37, -1, 37, 72, -1, 9, 10, -1,
+- 9, 10, 72, -1, 5, 43, 4, 44, -1, 75,
+- -1, 76, 45, 75, -1, 12, 10, -1, 12, 10,
+- 72, -1, 12, 10, 49, 76, 50, -1, 40, 49,
+- 76, 50, -1, 19, 20, -1, 5, -1, 5, 72,
+- -1, 68, -1, 78, -1, 69, -1, 70, -1, 74,
+- -1, 77, -1, 73, -1, 85, -1, 79, -1, 87,
+- -1, 88, -1, 86, -1, 24, -1, 80, -1, 65,
+- 80, -1, 81, -1, 81, 66, -1, 81, 6, -1,
+- 5, 82, -1, 83, -1, 84, 45, 83, -1, 11,
+- 49, 84, 50, -1, 11, 18, 80, -1, 11, 72,
+- 18, 80, -1, 28, 49, 84, 50, -1, 28, 18,
+- 80, -1, 28, 72, 18, 80, -1, 17, 49, 84,
+- 50, -1, 25, -1, 25, 26, 27, 5, -1, 5,
+- 3, 81, -1, 5, 19, 20, 3, 49, 62, 50,
+- -1, 5, 5, 3, 49, 62, 50, -1, 5, 7,
+- 3, 56, -1, 89, -1, 90, -1, 91, -1, 92,
+- 91, -1, 5, 49, 62, 50, -1, 5, 49, 50,
+- -1, 29, -1, 30, -1
+-};
+-
+-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
++ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+ static const yytype_uint16 yyrline[] =
+ {
+- 0, 119, 119, 132, 133, 136, 140, 141, 144, 145,
+- 148, 149, 152, 154, 159, 160, 164, 166, 171, 172,
+- 176, 177, 178, 181, 183, 187, 188, 189, 192, 194,
+- 195, 199, 200, 204, 205, 207, 208, 215, 218, 219,
+- 222, 224, 230, 231, 234, 235, 239, 240, 244, 249,
+- 250, 254, 255, 256, 261, 267, 270, 272, 275, 276,
+- 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+- 287, 290, 291, 296, 297, 300, 303, 306, 307, 311,
+- 313, 315, 320, 322, 324, 329, 333, 334, 339, 342,
+- 346, 351, 357, 358, 361, 362, 366, 369, 393, 394
++ 0, 135, 135, 148, 149, 152, 155, 156, 159, 160,
++ 163, 164, 165, 168, 169, 172, 174, 179, 180, 184,
++ 186, 191, 192, 196, 197, 198, 201, 203, 207, 208,
++ 209, 212, 214, 215, 219, 220, 224, 225, 227, 228,
++ 235, 238, 239, 242, 244, 250, 251, 254, 255, 259,
++ 260, 264, 265, 269, 270, 274, 275, 279, 280, 284,
++ 285, 289, 290, 294, 295, 299, 300, 304, 309, 310,
++ 314, 315, 316, 321, 327, 330, 332, 335, 336, 337,
++ 338, 339, 340, 341, 342, 343, 344, 345, 346, 347,
++ 348, 349, 350, 351, 352, 353, 354, 355, 358, 359,
++ 364, 365, 368, 371, 374, 375, 379, 381, 383, 388,
++ 390, 392, 397, 401, 402, 407, 409, 412, 416, 421,
++ 427, 428, 431, 432, 436, 439, 441, 465, 466
+ };
+ #endif
+
+-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
++#if YYDEBUG || YYERROR_VERBOSE || 1
+ /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+ static const char *const yytname[] =
+@@ -618,305 +610,289 @@
+ "OBJECT", "STR_IDENTIFIER", "BOOLEAN", "ASN1_TRUE", "ASN1_FALSE",
+ "TOKEN_NULL", "ANY", "DEFINED", "BY", "SET", "EXPLICIT", "IMPLICIT",
+ "DEFINITIONS", "TAGS", "BEGIN", "END", "UTCTime", "GeneralizedTime",
+- "GeneralString", "FROM", "IMPORTS", "ENUMERATED", "'+'", "'-'", "'('",
++ "GeneralString", "NumericString", "IA5String", "TeletexString",
++ "PrintableString", "UniversalString", "BMPString", "UTF8String",
++ "VisibleString", "FROM", "IMPORTS", "ENUMERATED", "'+'", "'-'", "'('",
+ "')'", "','", "'['", "']'", "'|'", "'{'", "'}'", "'.'", "$accept",
+ "definitions", "pos_num", "neg_num", "pos_neg_num", "num_identifier",
+- "pos_neg_identifier", "constant", "constant_list", "obj_constant",
+- "obj_constant_list", "class", "tag_type", "tag", "default",
+- "pos_neg_list", "integer_def", "boolean_def", "Time", "size_def2",
+- "size_def", "generalstring_def", "octet_string_def", "bit_element",
++ "int_identifier", "pos_neg_identifier", "constant", "constant_list",
++ "obj_constant", "obj_constant_list", "class", "tag_type", "tag",
++ "default", "pos_neg_list", "integer_def", "boolean_def", "Time",
++ "size_def2", "size_def", "generalstring_def", "numericstring_def",
++ "ia5string_def", "teletexstring_def", "printablestring_def",
++ "universalstring_def", "bmpstring_def", "utf8string_def",
++ "visiblestring_def", "octet_string_def", "bit_element",
+ "bit_element_list", "bit_string_def", "enumerated_def", "object_def",
+ "type_assig_right", "type_assig_right_tag",
+ "type_assig_right_tag_default", "type_assig", "type_assig_list",
+ "sequence_def", "set_def", "choise_def", "any_def", "type_def",
+ "constant_def", "type_constant", "type_constant_list", "definitions_id",
+- "explicit_implicit", 0
++ "explicit_implicit", YY_NULLPTR
+ };
+ #endif
+
+ # ifdef YYPRINT
+-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+- token YYLEX-NUM. */
++/* YYTOKNUM[NUM] -- (External) token number corresponding to the
++ (internal) symbol number NUM (which must be that of a token). */
+ static const yytype_uint16 yytoknum[] =
+ {
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+- 295, 43, 45, 40, 41, 44, 91, 93, 124, 123,
+- 125, 46
++ 295, 296, 297, 298, 299, 300, 301, 302, 303, 43,
++ 45, 40, 41, 44, 91, 93, 124, 123, 125, 46
+ };
+ # endif
+
+-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+-static const yytype_uint8 yyr1[] =
++#define YYPACT_NINF -129
++
++#define yypact_value_is_default(Yystate) \
++ (!!((Yystate) == (-129)))
++
++#define YYTABLE_NINF -12
++
++#define yytable_value_is_error(Yytable_value) \
++ 0
++
++ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
++ STATE-NUM. */
++static const yytype_int16 yypact[] =
+ {
+- 0, 52, 53, 54, 54, 55, 56, 56, 57, 57,
+- 58, 58, 59, 59, 60, 60, 61, 61, 62, 62,
+- 63, 63, 63, 64, 64, 65, 65, 65, 66, 66,
+- 66, 67, 67, 68, 68, 68, 68, 69, 70, 70,
+- 71, 71, 72, 72, 73, 73, 74, 74, 75, 76,
+- 76, 77, 77, 77, 78, 79, 80, 80, 80, 80,
+- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+- 80, 81, 81, 82, 82, 82, 83, 84, 84, 85,
+- 85, 85, 86, 86, 86, 87, 88, 88, 89, 90,
+- 90, 90, 91, 91, 92, 92, 93, 93, 94, 94
++ 36, -7, 74, 22, 3, -129, 26, -129, 34, -129,
++ -129, -129, 5, -129, -129, 55, 89, -129, -129, 97,
++ 57, 101, -129, 122, 141, 132, -129, -129, -129, 32,
++ 77, 77, 152, 165, 150, -129, -129, 6, 119, 167,
++ 18, 168, 124, 159, -129, -129, 156, 21, -129, -129,
++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 126,
++ 30, 38, 121, 133, -129, -129, -129, -129, -129, -129,
++ -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
++ -129, -129, -129, -129, -129, -129, 128, 58, 183, 136,
++ 180, -129, -129, 20, 6, 121, 184, 172, -3, 184,
++ -129, 164, 121, 184, 174, -129, -129, -129, -129, -129,
++ -129, -129, -129, -129, 188, 139, -129, -129, -129, 191,
++ -129, -129, -129, 42, 149, -129, 192, 193, -129, -129,
++ -129, 142, 169, 146, 151, 58, -129, 53, -129, -129,
++ 77, -129, 71, 121, 188, -129, 83, 195, -129, 90,
++ 121, 153, -129, 94, -129, 148, 147, -129, 197, -129,
++ 154, 43, 7, -129, -129, 149, -129, -21, -129, 58,
++ 155, 20, -129, 24, -129, 184, -129, -129, 114, -129,
++ -129, -129, -129, 201, 188, -129, -129, 157, 158, -129,
++ 58, -129, 23, -129, 160, 162, -129, -129, -129, 54,
++ -129, -129, -129, 163, -129, 47, -129, -129, 169, -129,
++ -129, -129, -129, -129, -129, -129, -129, 204, 166, 170,
++ -129, -129, -129
+ };
+
+-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+-static const yytype_uint8 yyr2[] =
++ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
++ Performed when YYTABLE does not specify something else to do. Zero
++ means the default is an error. */
++static const yytype_uint8 yydefact[] =
+ {
+- 0, 2, 8, 1, 2, 2, 1, 1, 1, 1,
+- 1, 1, 3, 4, 1, 3, 1, 4, 1, 2,
+- 1, 1, 1, 3, 4, 1, 2, 2, 2, 2,
+- 2, 1, 3, 1, 4, 4, 7, 1, 1, 1,
+- 4, 7, 1, 3, 1, 2, 2, 3, 4, 1,
+- 3, 2, 3, 5, 4, 2, 1, 2, 1, 1,
+- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+- 1, 1, 2, 1, 2, 2, 2, 1, 3, 4,
+- 3, 4, 4, 3, 4, 4, 1, 4, 3, 7,
+- 6, 4, 1, 1, 1, 2, 4, 3, 1, 1
++ 0, 126, 0, 0, 0, 1, 0, 8, 9, 125,
++ 19, 21, 0, 127, 128, 0, 0, 124, 22, 0,
++ 0, 0, 20, 0, 0, 0, 120, 121, 122, 0,
++ 0, 0, 0, 0, 0, 2, 123, 75, 36, 0,
++ 0, 0, 0, 0, 40, 97, 113, 0, 41, 42,
++ 47, 49, 51, 53, 55, 57, 59, 61, 63, 0,
++ 0, 28, 0, 77, 79, 80, 83, 84, 85, 86,
++ 87, 88, 89, 90, 91, 81, 82, 78, 93, 98,
++ 116, 92, 96, 94, 95, 115, 0, 0, 0, 0,
++ 0, 45, 76, 0, 65, 0, 0, 0, 70, 0,
++ 74, 0, 0, 0, 0, 48, 50, 52, 54, 56,
++ 58, 60, 62, 64, 0, 0, 23, 24, 25, 0,
++ 29, 30, 99, 0, 0, 3, 0, 0, 6, 7,
++ 119, 0, 0, 0, 0, 0, 17, 0, 66, 107,
++ 0, 104, 0, 0, 0, 71, 0, 0, 110, 0,
++ 0, 0, 68, 0, 26, 0, 3, 12, 0, 34,
++ 0, 0, 0, 4, 5, 0, 9, 0, 46, 0,
++ 0, 0, 37, 100, 103, 0, 106, 108, 0, 112,
++ 114, 109, 111, 0, 0, 73, 27, 5, 0, 38,
++ 0, 118, 0, 43, 0, 0, 15, 18, 102, 0,
++ 101, 105, 72, 0, 69, 0, 35, 117, 0, 16,
++ 14, 32, 33, 13, 31, 67, 10, 0, 0, 0,
++ 11, 39, 44
+ };
+
+-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+- means the default is an error. */
+-static const yytype_uint8 yydefact[] =
++ /* YYPGOTO[NTERM-NUM]. */
++static const yytype_int16 yypgoto[] =
+ {
+- 0, 0, 0, 0, 0, 1, 0, 8, 9, 97,
+- 16, 18, 0, 98, 99, 0, 0, 96, 19, 0,
+- 0, 0, 17, 0, 0, 92, 93, 94, 0, 0,
+- 0, 0, 0, 2, 95, 56, 33, 0, 0, 0,
+- 0, 0, 37, 70, 86, 0, 38, 39, 44, 0,
+- 0, 25, 0, 58, 60, 61, 64, 62, 63, 59,
+- 66, 71, 88, 65, 69, 67, 68, 0, 0, 0,
+- 0, 0, 42, 57, 0, 46, 0, 0, 0, 51,
+- 0, 55, 0, 0, 0, 0, 45, 0, 0, 20,
+- 21, 22, 0, 26, 27, 72, 0, 0, 3, 0,
+- 0, 6, 7, 91, 0, 0, 0, 0, 0, 14,
+- 0, 47, 80, 0, 77, 0, 0, 0, 52, 0,
+- 0, 83, 0, 0, 0, 49, 0, 23, 0, 3,
+- 9, 31, 0, 0, 0, 4, 5, 0, 0, 43,
+- 0, 0, 0, 34, 73, 76, 0, 79, 81, 0,
+- 85, 87, 82, 84, 0, 0, 54, 24, 0, 35,
+- 0, 90, 0, 40, 0, 0, 12, 15, 75, 0,
+- 74, 78, 53, 0, 50, 0, 32, 89, 0, 13,
+- 11, 29, 30, 10, 28, 48, 0, 0, 36, 41
++ -129, -129, -129, -129, -120, -128, 4, -129, 39, -129,
++ -12, -92, -129, -129, -129, -129, -129, -129, -129, -129,
++ 130, -34, -129, -129, -129, -129, -129, -129, -129, -129,
++ -129, -129, 27, 68, -129, -129, -129, -60, -30, -129,
++ 46, 72, -129, -129, -129, -129, -129, -129, 194, -129,
++ -129, -129
+ };
+
+-/* YYDEFGOTO[NTERM-NUM]. */
++ /* YYDEFGOTO[NTERM-NUM]. */
+ static const yytype_int16 yydefgoto[] =
+ {
+- -1, 2, 101, 102, 103, 10, 184, 109, 110, 11,
+- 12, 92, 51, 52, 170, 133, 53, 54, 55, 72,
+- 73, 56, 57, 125, 126, 58, 59, 60, 61, 62,
+- 145, 114, 115, 63, 64, 65, 66, 25, 26, 27,
+- 28, 3, 15
++ -1, 2, 128, 129, 130, 10, 160, 214, 136, 137,
++ 11, 12, 119, 61, 62, 200, 161, 63, 64, 65,
++ 91, 92, 66, 67, 68, 69, 70, 71, 72, 73,
++ 74, 75, 152, 153, 76, 77, 78, 79, 80, 174,
++ 141, 142, 81, 82, 83, 84, 26, 27, 28, 29,
++ 3, 15
+ };
+
+-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+- STATE-NUM. */
+-#define YYPACT_NINF -96
+-static const yytype_int16 yypact[] =
++ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
++ positive, shift that token. If negative, reduce the rule whose
++ number is the opposite. If YYTABLE_NINF, syntax error. */
++static const yytype_int16 yytable[] =
+ {
+- 24, -14, 48, 56, 0, -96, -10, -96, -2, -96,
+- -96, -96, 2, -96, -96, 71, 111, -96, -96, 117,
+- 83, 96, -96, 127, 42, -96, -96, -96, 10, 77,
+- 130, 131, 115, -96, -96, 8, 90, 132, 13, 135,
+- 92, 126, -96, -96, 122, 15, -96, -96, 8, 100,
+- 93, 49, 119, 94, -96, -96, -96, -96, -96, -96,
+- -96, -96, -96, -96, -96, -96, -96, 102, 28, 149,
+- 110, 150, -96, -96, 17, 8, 119, 152, 142, 22,
+- 152, -96, 134, 119, 152, 144, -96, 158, 118, -96,
+- -96, -96, 160, -96, -96, -96, 35, 88, -96, 162,
+- 163, -96, -96, -96, 120, 114, 124, 128, 28, -96,
+- -8, -96, -96, 77, -96, -7, 119, 158, -96, 18,
+- 165, -96, 50, 119, 129, -96, 54, -96, 133, 123,
+- -96, -96, 125, 37, 4, -96, -96, 88, -27, -96,
+- 28, 137, 17, -96, 20, -96, 152, -96, -96, 66,
+- -96, -96, -96, -96, 169, 158, -96, -96, 136, -96,
+- 28, -96, 7, -96, 138, 139, -96, -96, -96, 68,
+- -96, -96, -96, 140, -96, 114, -96, -96, 114, -96,
+- -96, -96, -96, -96, -96, -96, 141, 146, -96, -96
++ 18, 85, 122, 159, 167, 89, 97, 7, 8, 7,
++ 8, 7, 8, 104, 89, 170, 105, 106, 107, 108,
++ 109, 110, 111, 112, 113, 134, 89, 7, 8, 89,
++ 198, 193, 162, 24, 115, 139, 95, 25, 194, 102,
++ 199, 1, 148, 116, 117, 118, 156, 157, 90, 195,
++ 4, 216, 157, 6, 144, 13, 14, 90, 125, 210,
++ 138, 9, 125, 17, 145, 191, 35, 120, 121, 90,
++ 206, 135, 90, 192, 5, 96, 211, 212, 103, 213,
++ 219, 207, 37, 177, 38, 16, 39, 19, 40, 41,
++ 182, 126, 158, 20, 42, 189, 43, 217, 44, 190,
++ 21, 45, 46, 126, 127, 47, 171, 126, 127, 22,
++ 173, 172, 48, 49, 50, 51, 52, 53, 54, 55,
++ 56, 57, 58, 24, 175, 59, 37, 25, 38, 176,
++ 39, 60, 40, 41, 23, 31, 175, 32, 42, 33,
++ 43, 179, 44, 175, 30, 45, 46, 184, 181, 47,
++ 18, 34, 185, 7, 8, 86, 48, 49, 50, 51,
++ 52, 53, 54, 55, 56, 57, 58, 184, 87, 59,
++ 88, 146, 202, 7, 166, 149, 93, 94, 98, 100,
++ 18, 99, 101, 114, 123, 124, 131, 132, 89, 140,
++ 143, 147, 150, 151, 154, 155, 163, 164, 168, 165,
++ 180, 187, 169, 186, 183, 203, -10, 196, 220, 218,
++ 197, 204, 178, 188, 209, 215, -11, 205, 221, 208,
++ 133, 201, 222, 36
+ };
+
+-/* YYPGOTO[NTERM-NUM]. */
+-static const yytype_int16 yypgoto[] =
++static const yytype_uint8 yycheck[] =
+ {
+- -96, -96, -96, -96, -94, -95, -96, 33, -96, -12,
+- -84, -96, -96, -96, -96, -96, -96, -96, -96, 106,
+- -20, -96, -96, 23, 62, -96, -96, -96, -49, 69,
+- -96, 40, 41, -96, -96, -96, -96, -96, -96, 164,
+- -96, -96, -96
++ 12, 31, 62, 123, 132, 8, 40, 4, 5, 4,
++ 5, 4, 5, 47, 8, 135, 50, 51, 52, 53,
++ 54, 55, 56, 57, 58, 5, 8, 4, 5, 8,
++ 6, 52, 124, 1, 4, 95, 18, 5, 59, 18,
++ 16, 5, 102, 13, 14, 15, 4, 5, 51, 169,
++ 57, 4, 5, 31, 57, 29, 30, 51, 4, 5,
++ 94, 58, 4, 58, 98, 58, 34, 29, 30, 51,
++ 190, 51, 51, 165, 0, 57, 22, 23, 57, 199,
++ 208, 58, 5, 143, 7, 51, 9, 32, 11, 12,
++ 150, 49, 50, 4, 17, 52, 19, 50, 21, 56,
++ 3, 24, 25, 49, 50, 28, 53, 49, 50, 52,
++ 140, 58, 35, 36, 37, 38, 39, 40, 41, 42,
++ 43, 44, 45, 1, 53, 48, 5, 5, 7, 58,
++ 9, 54, 11, 12, 33, 3, 53, 5, 17, 7,
++ 19, 58, 21, 53, 3, 24, 25, 53, 58, 28,
++ 162, 19, 58, 4, 5, 3, 35, 36, 37, 38,
++ 39, 40, 41, 42, 43, 44, 45, 53, 3, 48,
++ 20, 99, 58, 4, 5, 103, 57, 10, 10, 20,
++ 192, 57, 26, 57, 51, 57, 3, 51, 8, 5,
++ 18, 27, 18, 5, 55, 4, 4, 4, 52, 57,
++ 5, 4, 51, 55, 51, 4, 59, 52, 4, 205,
++ 171, 184, 144, 59, 52, 52, 59, 59, 52, 59,
++ 90, 175, 52, 29
+ };
+
+-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+- positive, shift that token. If negative, reduce the rule which
+- number is the opposite. If zero, do what YYDEFACT says.
+- If YYTABLE_NINF, syntax error. */
+-#define YYTABLE_NINF -9
+-static const yytype_int16 yytable[] =
++ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
++ symbol of state STATE-NUM. */
++static const yytype_uint8 yystos[] =
+ {
+- 18, 132, 131, 95, 7, 8, 7, 8, 7, 8,
+- 138, 7, 8, 134, 141, 24, 70, 163, 78, 13,
+- 14, 70, 107, 70, 164, 85, 168, 112, 86, 1,
+- 70, 76, 98, 83, 121, 4, 169, 142, 146, 129,
+- 130, 16, 143, 147, 33, 29, 165, 30, 5, 31,
+- 9, 71, 17, 162, 161, 111, 71, 177, 71, 118,
+- 108, 32, 77, 146, 84, 71, 176, 148, 150, 99,
+- 100, 117, 98, 180, 153, 183, 99, 100, 93, 94,
+- 186, 159, 35, 187, 36, 160, 37, 6, 38, 39,
+- 181, 182, 7, 8, 40, 146, 41, 88, 42, 155,
+- 152, 43, 44, 19, 156, 45, 89, 90, 91, 99,
+- 100, 155, 46, 47, 48, 20, 172, 49, 7, 130,
+- 21, 119, 18, 50, 35, 122, 36, 22, 37, 23,
+- 38, 39, 24, 67, 68, 69, 40, 96, 41, 74,
+- 42, 80, 75, 43, 44, 79, 81, 45, 82, 87,
+- 18, 97, 104, 105, 46, 47, 48, 113, 70, 49,
+- 116, 120, 123, 124, 128, 127, 135, 136, 139, 137,
+- 151, 140, 154, 173, -8, 167, 158, 106, 174, 149,
+- 157, 166, 144, 179, 185, 188, 171, 175, 0, 178,
+- 189, 0, 34
++ 0, 5, 61, 110, 57, 0, 31, 4, 5, 58,
++ 65, 70, 71, 29, 30, 111, 51, 58, 70, 32,
++ 4, 3, 52, 33, 1, 5, 106, 107, 108, 109,
++ 3, 3, 5, 7, 19, 34, 108, 5, 7, 9,
++ 11, 12, 17, 19, 21, 24, 25, 28, 35, 36,
++ 37, 38, 39, 40, 41, 42, 43, 44, 45, 48,
++ 54, 73, 74, 77, 78, 79, 82, 83, 84, 85,
++ 86, 87, 88, 89, 90, 91, 94, 95, 96, 97,
++ 98, 102, 103, 104, 105, 98, 3, 3, 20, 8,
++ 51, 80, 81, 57, 10, 18, 57, 81, 10, 57,
++ 20, 26, 18, 57, 81, 81, 81, 81, 81, 81,
++ 81, 81, 81, 81, 57, 4, 13, 14, 15, 72,
++ 29, 30, 97, 51, 57, 4, 49, 50, 62, 63,
++ 64, 3, 51, 80, 5, 51, 68, 69, 81, 97,
++ 5, 100, 101, 18, 57, 81, 101, 27, 97, 101,
++ 18, 5, 92, 93, 55, 4, 4, 5, 50, 64,
++ 66, 76, 71, 4, 4, 57, 5, 65, 52, 51,
++ 64, 53, 58, 98, 99, 53, 58, 97, 93, 58,
++ 5, 58, 97, 51, 53, 58, 55, 4, 59, 52,
++ 56, 58, 71, 52, 59, 64, 52, 68, 6, 16,
++ 75, 100, 58, 4, 92, 59, 64, 58, 59, 52,
++ 5, 22, 23, 64, 67, 52, 4, 50, 66, 65,
++ 4, 52, 52
+ };
+
+-static const yytype_int16 yycheck[] =
++ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
++static const yytype_uint8 yyr1[] =
+ {
+- 12, 96, 96, 52, 4, 5, 4, 5, 4, 5,
+- 105, 4, 5, 97, 108, 5, 8, 44, 38, 29,
+- 30, 8, 5, 8, 51, 45, 6, 76, 48, 5,
+- 8, 18, 4, 18, 83, 49, 16, 45, 45, 4,
+- 5, 43, 50, 50, 34, 3, 140, 5, 0, 7,
+- 50, 43, 50, 137, 50, 75, 43, 50, 43, 79,
+- 43, 19, 49, 45, 49, 43, 160, 116, 50, 41,
+- 42, 49, 4, 5, 123, 169, 41, 42, 29, 30,
+- 175, 44, 5, 178, 7, 48, 9, 31, 11, 12,
+- 22, 23, 4, 5, 17, 45, 19, 4, 21, 45,
+- 50, 24, 25, 32, 50, 28, 13, 14, 15, 41,
+- 42, 45, 35, 36, 37, 4, 50, 40, 4, 5,
+- 3, 80, 134, 46, 5, 84, 7, 44, 9, 33,
+- 11, 12, 5, 3, 3, 20, 17, 43, 19, 49,
+- 21, 49, 10, 24, 25, 10, 20, 28, 26, 49,
+- 162, 49, 3, 43, 35, 36, 37, 5, 8, 40,
+- 18, 27, 18, 5, 4, 47, 4, 4, 44, 49,
+- 5, 43, 43, 4, 51, 142, 51, 71, 155, 117,
+- 47, 44, 113, 44, 44, 44, 146, 51, -1, 51,
+- 44, -1, 28
++ 0, 60, 61, 62, 62, 63, 64, 64, 65, 65,
++ 66, 66, 66, 67, 67, 68, 68, 69, 69, 70,
++ 70, 71, 71, 72, 72, 72, 73, 73, 74, 74,
++ 74, 75, 75, 75, 76, 76, 77, 77, 77, 77,
++ 78, 79, 79, 80, 80, 81, 81, 82, 82, 83,
++ 83, 84, 84, 85, 85, 86, 86, 87, 87, 88,
++ 88, 89, 89, 90, 90, 91, 91, 92, 93, 93,
++ 94, 94, 94, 95, 96, 97, 97, 97, 97, 97,
++ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
++ 97, 97, 97, 97, 97, 97, 97, 97, 98, 98,
++ 99, 99, 99, 100, 101, 101, 102, 102, 102, 103,
++ 103, 103, 104, 105, 105, 106, 106, 107, 107, 107,
++ 108, 108, 109, 109, 110, 110, 110, 111, 111
+ };
+
+-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+- symbol of state STATE-NUM. */
+-static const yytype_uint8 yystos[] =
++ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
++static const yytype_uint8 yyr2[] =
+ {
+- 0, 5, 53, 93, 49, 0, 31, 4, 5, 50,
+- 57, 61, 62, 29, 30, 94, 43, 50, 61, 32,
+- 4, 3, 44, 33, 5, 89, 90, 91, 92, 3,
+- 5, 7, 19, 34, 91, 5, 7, 9, 11, 12,
+- 17, 19, 21, 24, 25, 28, 35, 36, 37, 40,
+- 46, 64, 65, 68, 69, 70, 73, 74, 77, 78,
+- 79, 80, 81, 85, 86, 87, 88, 3, 3, 20,
+- 8, 43, 71, 72, 49, 10, 18, 49, 72, 10,
+- 49, 20, 26, 18, 49, 72, 72, 49, 4, 13,
+- 14, 15, 63, 29, 30, 80, 43, 49, 4, 41,
+- 42, 54, 55, 56, 3, 43, 71, 5, 43, 59,
+- 60, 72, 80, 5, 83, 84, 18, 49, 72, 84,
+- 27, 80, 84, 18, 5, 75, 76, 47, 4, 4,
+- 5, 56, 57, 67, 62, 4, 4, 49, 57, 44,
+- 43, 56, 45, 50, 81, 82, 45, 50, 80, 76,
+- 50, 5, 50, 80, 43, 45, 50, 47, 51, 44,
+- 48, 50, 62, 44, 51, 56, 44, 59, 6, 16,
+- 66, 83, 50, 4, 75, 51, 56, 50, 51, 44,
+- 5, 22, 23, 56, 58, 44, 57, 57, 44, 44
++ 0, 2, 8, 1, 2, 2, 1, 1, 1, 1,
++ 1, 2, 1, 1, 1, 3, 4, 1, 3, 1,
++ 4, 1, 2, 1, 1, 1, 3, 4, 1, 2,
++ 2, 2, 2, 2, 1, 3, 1, 4, 4, 7,
++ 1, 1, 1, 4, 7, 1, 3, 1, 2, 1,
++ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
++ 2, 1, 2, 1, 2, 2, 3, 4, 1, 3,
++ 2, 3, 5, 4, 2, 1, 2, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
++ 1, 2, 2, 2, 1, 3, 4, 3, 4, 4,
++ 3, 4, 4, 1, 4, 3, 3, 7, 6, 4,
++ 1, 1, 1, 2, 4, 3, 1, 1, 1
+ };
+
+-#define yyerrok (yyerrstatus = 0)
+-#define yyclearin (yychar = YYEMPTY)
+-#define YYEMPTY (-2)
+-#define YYEOF 0
+-
+-#define YYACCEPT goto yyacceptlab
+-#define YYABORT goto yyabortlab
+-#define YYERROR goto yyerrorlab
+
++#define yyerrok (yyerrstatus = 0)
++#define yyclearin (yychar = YYEMPTY)
++#define YYEMPTY (-2)
++#define YYEOF 0
++
++#define YYACCEPT goto yyacceptlab
++#define YYABORT goto yyabortlab
++#define YYERROR goto yyerrorlab
+
+-/* Like YYERROR except do call yyerror. This remains here temporarily
+- to ease the transition to the new meaning of YYERROR, for GCC.
+- Once GCC version 2 has supplanted version 1, this can go. */
+-
+-#define YYFAIL goto yyerrlab
+
+ #define YYRECOVERING() (!!yyerrstatus)
+
+-#define YYBACKUP(Token, Value) \
+-do \
+- if (yychar == YYEMPTY && yylen == 1) \
+- { \
+- yychar = (Token); \
+- yylval = (Value); \
+- yytoken = YYTRANSLATE (yychar); \
+- YYPOPSTACK (1); \
+- goto yybackup; \
+- } \
+- else \
+- { \
++#define YYBACKUP(Token, Value) \
++do \
++ if (yychar == YYEMPTY) \
++ { \
++ yychar = (Token); \
++ yylval = (Value); \
++ YYPOPSTACK (yylen); \
++ yystate = *yyssp; \
++ goto yybackup; \
++ } \
++ else \
++ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+- YYERROR; \
+- } \
+-while (YYID (0))
+-
+-
+-#define YYTERROR 1
+-#define YYERRCODE 256
+-
+-
+-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+- If N is 0, then set CURRENT to the empty location which ends
+- the previous symbol: RHS[0] (always defined). */
+-
+-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+-#ifndef YYLLOC_DEFAULT
+-# define YYLLOC_DEFAULT(Current, Rhs, N) \
+- do \
+- if (YYID (N)) \
+- { \
+- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+- } \
+- else \
+- { \
+- (Current).first_line = (Current).last_line = \
+- YYRHSLOC (Rhs, 0).last_line; \
+- (Current).first_column = (Current).last_column = \
+- YYRHSLOC (Rhs, 0).last_column; \
+- } \
+- while (YYID (0))
+-#endif
++ YYERROR; \
++ } \
++while (0)
++
++/* Error token number */
++#define YYTERROR 1
++#define YYERRCODE 256
+
+
+-/* YY_LOCATION_PRINT -- Print the location on the stream.
+- This macro was not mandated originally: define only if we know
+- we won't break user code: when these are the locations we know. */
+-
+-#ifndef YY_LOCATION_PRINT
+-# if YYLTYPE_IS_TRIVIAL
+-# define YY_LOCATION_PRINT(File, Loc) \
+- fprintf (File, "%d.%d-%d.%d", \
+- (Loc).first_line, (Loc).first_column, \
+- (Loc).last_line, (Loc).last_column)
+-# else
+-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+-# endif
+-#endif
+-
+-
+-/* YYLEX -- calling `yylex' with the right arguments. */
+-
+-#ifdef YYLEX_PARAM
+-# define YYLEX yylex (YYLEX_PARAM)
+-#else
+-# define YYLEX yylex ()
+-#endif
+
+ /* Enable debugging if requested. */
+ #if YYDEBUG
+@@ -926,54 +902,46 @@
+ # define YYFPRINTF fprintf
+ # endif
+
+-# define YYDPRINTF(Args) \
+-do { \
+- if (yydebug) \
+- YYFPRINTF Args; \
+-} while (YYID (0))
+-
+-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+-do { \
+- if (yydebug) \
+- { \
+- YYFPRINTF (stderr, "%s ", Title); \
+- yy_symbol_print (stderr, \
+- Type, Value); \
+- YYFPRINTF (stderr, "\n"); \
+- } \
+-} while (YYID (0))
++# define YYDPRINTF(Args) \
++do { \
++ if (yydebug) \
++ YYFPRINTF Args; \
++} while (0)
+
++/* This macro is provided for backward compatibility. */
++#ifndef YY_LOCATION_PRINT
++# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
++#endif
+
+-/*--------------------------------.
+-| Print this symbol on YYOUTPUT. |
+-`--------------------------------*/
+
+-/*ARGSUSED*/
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
++# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
++do { \
++ if (yydebug) \
++ { \
++ YYFPRINTF (stderr, "%s ", Title); \
++ yy_symbol_print (stderr, \
++ Type, Value); \
++ YYFPRINTF (stderr, "\n"); \
++ } \
++} while (0)
++
++
++/*----------------------------------------.
++| Print this symbol's value on YYOUTPUT. |
++`----------------------------------------*/
++
+ static void
+ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+-#else
+-static void
+-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+- FILE *yyoutput;
+- int yytype;
+- YYSTYPE const * const yyvaluep;
+-#endif
+ {
++ FILE *yyo = yyoutput;
++ YYUSE (yyo);
+ if (!yyvaluep)
+ return;
+ # ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+-# else
+- YYUSE (yyoutput);
+ # endif
+- switch (yytype)
+- {
+- default:
+- break;
+- }
++ YYUSE (yytype);
+ }
+
+
+@@ -981,22 +949,11 @@
+ | Print this symbol on YYOUTPUT. |
+ `--------------------------------*/
+
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+ static void
+ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+-#else
+-static void
+-yy_symbol_print (yyoutput, yytype, yyvaluep)
+- FILE *yyoutput;
+- int yytype;
+- YYSTYPE const * const yyvaluep;
+-#endif
+ {
+- if (yytype < YYNTOKENS)
+- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+- else
+- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
++ YYFPRINTF (yyoutput, "%s %s (",
++ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+@@ -1007,16 +964,8 @@
+ | TOP (included). |
+ `------------------------------------------------------------------*/
+
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+ static void
+ yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+-#else
+-static void
+-yy_stack_print (yybottom, yytop)
+- yytype_int16 *yybottom;
+- yytype_int16 *yytop;
+-#endif
+ {
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+@@ -1027,49 +976,42 @@
+ YYFPRINTF (stderr, "\n");
+ }
+
+-# define YY_STACK_PRINT(Bottom, Top) \
+-do { \
+- if (yydebug) \
+- yy_stack_print ((Bottom), (Top)); \
+-} while (YYID (0))
++# define YY_STACK_PRINT(Bottom, Top) \
++do { \
++ if (yydebug) \
++ yy_stack_print ((Bottom), (Top)); \
++} while (0)
+
+
+ /*------------------------------------------------.
+ | Report that the YYRULE is going to be reduced. |
+ `------------------------------------------------*/
+
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+-static void
+-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+-#else
+ static void
+-yy_reduce_print (yyvsp, yyrule)
+- YYSTYPE *yyvsp;
+- int yyrule;
+-#endif
++yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
+ {
++ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+- unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+- yyrule - 1, yylno);
++ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+- &(yyvsp[(yyi + 1) - (yynrhs)])
+- );
++ yy_symbol_print (stderr,
++ yystos[yyssp[yyi + 1 - yynrhs]],
++ &(yyvsp[(yyi + 1) - (yynrhs)])
++ );
+ YYFPRINTF (stderr, "\n");
+ }
+ }
+
+-# define YY_REDUCE_PRINT(Rule) \
+-do { \
+- if (yydebug) \
+- yy_reduce_print (yyvsp, Rule); \
+-} while (YYID (0))
++# define YY_REDUCE_PRINT(Rule) \
++do { \
++ if (yydebug) \
++ yy_reduce_print (yyssp, yyvsp, Rule); \
++} while (0)
+
+ /* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+@@ -1083,7 +1025,7 @@
+
+
+ /* YYINITDEPTH -- initial size of the parser's stacks. */
+-#ifndef YYINITDEPTH
++#ifndef YYINITDEPTH
+ # define YYINITDEPTH 200
+ #endif
+
+@@ -1098,7 +1040,6 @@
+ # define YYMAXDEPTH 10000
+ #endif
+
+-
+
+ #if YYERROR_VERBOSE
+
+@@ -1107,15 +1048,8 @@
+ # define yystrlen strlen
+ # else
+ /* Return the length of YYSTR. */
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+ static YYSIZE_T
+ yystrlen (const char *yystr)
+-#else
+-static YYSIZE_T
+-yystrlen (yystr)
+- const char *yystr;
+-#endif
+ {
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+@@ -1131,16 +1065,8 @@
+ # else
+ /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+ static char *
+ yystpcpy (char *yydest, const char *yysrc)
+-#else
+-static char *
+-yystpcpy (yydest, yysrc)
+- char *yydest;
+- const char *yysrc;
+-#endif
+ {
+ char *yyd = yydest;
+ const char *yys = yysrc;
+@@ -1170,27 +1096,27 @@
+ char const *yyp = yystr;
+
+ for (;;)
+- switch (*++yyp)
+- {
+- case '\'':
+- case ',':
+- goto do_not_strip_quotes;
+-
+- case '\\':
+- if (*++yyp != '\\')
+- goto do_not_strip_quotes;
+- /* Fall through. */
+- default:
+- if (yyres)
+- yyres[yyn] = *yyp;
+- yyn++;
+- break;
+-
+- case '"':
+- if (yyres)
+- yyres[yyn] = '\0';
+- return yyn;
+- }
++ switch (*++yyp)
++ {
++ case '\'':
++ case ',':
++ goto do_not_strip_quotes;
++
++ case '\\':
++ if (*++yyp != '\\')
++ goto do_not_strip_quotes;
++ /* Fall through. */
++ default:
++ if (yyres)
++ yyres[yyn] = *yyp;
++ yyn++;
++ break;
++
++ case '"':
++ if (yyres)
++ yyres[yyn] = '\0';
++ return yyn;
++ }
+ do_not_strip_quotes: ;
+ }
+
+@@ -1201,161 +1127,160 @@
+ }
+ # endif
+
+-/* Copy into YYRESULT an error message about the unexpected token
+- YYCHAR while in state YYSTATE. Return the number of bytes copied,
+- including the terminating null byte. If YYRESULT is null, do not
+- copy anything; just return the number of bytes that would be
+- copied. As a special case, return 0 if an ordinary "syntax error"
+- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+- size calculation. */
+-static YYSIZE_T
+-yysyntax_error (char *yyresult, int yystate, int yychar)
++/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
++ about the unexpected token YYTOKEN for the state stack whose top is
++ YYSSP.
++
++ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
++ not large enough to hold the message. In that case, also set
++ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
++ required number of bytes is too large to store. */
++static int
++yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
++ yytype_int16 *yyssp, int yytoken)
+ {
+- int yyn = yypact[yystate];
+-
+- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+- return 0;
+- else
++ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
++ YYSIZE_T yysize = yysize0;
++ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
++ /* Internationalized format string. */
++ const char *yyformat = YY_NULLPTR;
++ /* Arguments of yyformat. */
++ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
++ /* Number of reported tokens (one for the "unexpected", one per
++ "expected"). */
++ int yycount = 0;
++
++ /* There are many possibilities here to consider:
++ - If this state is a consistent state with a default action, then
++ the only way this function was invoked is if the default action
++ is an error action. In that case, don't check for expected
++ tokens because there are none.
++ - The only way there can be no lookahead present (in yychar) is if
++ this state is a consistent state with a default action. Thus,
++ detecting the absence of a lookahead is sufficient to determine
++ that there is no unexpected or expected token to report. In that
++ case, just report a simple "syntax error".
++ - Don't assume there isn't a lookahead just because this state is a
++ consistent state with a default action. There might have been a
++ previous inconsistent state, consistent state with a non-default
++ action, or user semantic action that manipulated yychar.
++ - Of course, the expected token list depends on states to have
++ correct lookahead information, and it depends on the parser not
++ to perform extra reductions after fetching a lookahead from the
++ scanner and before detecting a syntax error. Thus, state merging
++ (from LALR or IELR) and default reductions corrupt the expected
++ token list. However, the list is correct for canonical LR with
++ one exception: it will still contain any token that will not be
++ accepted due to an error action in a later state.
++ */
++ if (yytoken != YYEMPTY)
+ {
+- int yytype = YYTRANSLATE (yychar);
+- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+- YYSIZE_T yysize = yysize0;
+- YYSIZE_T yysize1;
+- int yysize_overflow = 0;
+- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+- int yyx;
+-
+-# if 0
+- /* This is so xgettext sees the translatable formats that are
+- constructed on the fly. */
+- YY_("syntax error, unexpected %s");
+- YY_("syntax error, unexpected %s, expecting %s");
+- YY_("syntax error, unexpected %s, expecting %s or %s");
+- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+-# endif
+- char *yyfmt;
+- char const *yyf;
+- static char const yyunexpected[] = "syntax error, unexpected %s";
+- static char const yyexpecting[] = ", expecting %s";
+- static char const yyor[] = " or %s";
+- char yyformat[sizeof yyunexpected
+- + sizeof yyexpecting - 1
+- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+- * (sizeof yyor - 1))];
+- char const *yyprefix = yyexpecting;
+-
+- /* Start YYX at -YYN if negative to avoid negative indexes in
+- YYCHECK. */
+- int yyxbegin = yyn < 0 ? -yyn : 0;
+-
+- /* Stay within bounds of both yycheck and yytname. */
+- int yychecklim = YYLAST - yyn + 1;
+- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+- int yycount = 1;
+-
+- yyarg[0] = yytname[yytype];
+- yyfmt = yystpcpy (yyformat, yyunexpected);
+-
+- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+- {
+- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+- {
+- yycount = 1;
+- yysize = yysize0;
+- yyformat[sizeof yyunexpected - 1] = '\0';
+- break;
+- }
+- yyarg[yycount++] = yytname[yyx];
+- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+- yysize_overflow |= (yysize1 < yysize);
+- yysize = yysize1;
+- yyfmt = yystpcpy (yyfmt, yyprefix);
+- yyprefix = yyor;
+- }
+-
+- yyf = YY_(yyformat);
+- yysize1 = yysize + yystrlen (yyf);
+- yysize_overflow |= (yysize1 < yysize);
+- yysize = yysize1;
+-
+- if (yysize_overflow)
+- return YYSIZE_MAXIMUM;
+-
+- if (yyresult)
+- {
+- /* Avoid sprintf, as that infringes on the user's name space.
+- Don't have undefined behavior even if the translation
+- produced a string with the wrong number of "%s"s. */
+- char *yyp = yyresult;
+- int yyi = 0;
+- while ((*yyp = *yyf) != '\0')
+- {
+- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+- {
+- yyp += yytnamerr (yyp, yyarg[yyi++]);
+- yyf += 2;
+- }
+- else
+- {
+- yyp++;
+- yyf++;
+- }
+- }
+- }
+- return yysize;
++ int yyn = yypact[*yyssp];
++ yyarg[yycount++] = yytname[yytoken];
++ if (!yypact_value_is_default (yyn))
++ {
++ /* Start YYX at -YYN if negative to avoid negative indexes in
++ YYCHECK. In other words, skip the first -YYN actions for
++ this state because they are default actions. */
++ int yyxbegin = yyn < 0 ? -yyn : 0;
++ /* Stay within bounds of both yycheck and yytname. */
++ int yychecklim = YYLAST - yyn + 1;
++ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
++ int yyx;
++
++ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
++ && !yytable_value_is_error (yytable[yyx + yyn]))
++ {
++ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
++ {
++ yycount = 1;
++ yysize = yysize0;
++ break;
++ }
++ yyarg[yycount++] = yytname[yyx];
++ {
++ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
++ if (! (yysize <= yysize1
++ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
++ return 2;
++ yysize = yysize1;
++ }
++ }
++ }
+ }
++
++ switch (yycount)
++ {
++# define YYCASE_(N, S) \
++ case N: \
++ yyformat = S; \
++ break
++ YYCASE_(0, YY_("syntax error"));
++ YYCASE_(1, YY_("syntax error, unexpected %s"));
++ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
++ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
++ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
++ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
++# undef YYCASE_
++ }
++
++ {
++ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
++ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
++ return 2;
++ yysize = yysize1;
++ }
++
++ if (*yymsg_alloc < yysize)
++ {
++ *yymsg_alloc = 2 * yysize;
++ if (! (yysize <= *yymsg_alloc
++ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
++ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
++ return 1;
++ }
++
++ /* Avoid sprintf, as that infringes on the user's name space.
++ Don't have undefined behavior even if the translation
++ produced a string with the wrong number of "%s"s. */
++ {
++ char *yyp = *yymsg;
++ int yyi = 0;
++ while ((*yyp = *yyformat) != '\0')
++ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
++ {
++ yyp += yytnamerr (yyp, yyarg[yyi++]);
++ yyformat += 2;
++ }
++ else
++ {
++ yyp++;
++ yyformat++;
++ }
++ }
++ return 0;
+ }
+ #endif /* YYERROR_VERBOSE */
+-
+
+ /*-----------------------------------------------.
+ | Release the memory associated to this symbol. |
+ `-----------------------------------------------*/
+
+-/*ARGSUSED*/
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+ static void
+ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+-#else
+-static void
+-yydestruct (yymsg, yytype, yyvaluep)
+- const char *yymsg;
+- int yytype;
+- YYSTYPE *yyvaluep;
+-#endif
+ {
+ YYUSE (yyvaluep);
+-
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+- switch (yytype)
+- {
+-
+- default:
+- break;
+- }
++ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
++ YYUSE (yytype);
++ YY_IGNORE_MAYBE_UNINITIALIZED_END
+ }
+
+-/* Prevent warnings from -Wmissing-prototypes. */
+-#ifdef YYPARSE_PARAM
+-#if defined __STDC__ || defined __cplusplus
+-int yyparse (void *YYPARSE_PARAM);
+-#else
+-int yyparse ();
+-#endif
+-#else /* ! YYPARSE_PARAM */
+-#if defined __STDC__ || defined __cplusplus
+-int yyparse (void);
+-#else
+-int yyparse ();
+-#endif
+-#endif /* ! YYPARSE_PARAM */
++
+
+
+ /* The lookahead symbol. */
+@@ -1363,49 +1288,26 @@
+
+ /* The semantic value of the lookahead symbol. */
+ YYSTYPE yylval;
+-
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+
++/*----------.
++| yyparse. |
++`----------*/
+
+-/*-------------------------.
+-| yyparse or yypush_parse. |
+-`-------------------------*/
+-
+-#ifdef YYPARSE_PARAM
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+-int
+-yyparse (void *YYPARSE_PARAM)
+-#else
+-int
+-yyparse (YYPARSE_PARAM)
+- void *YYPARSE_PARAM;
+-#endif
+-#else /* ! YYPARSE_PARAM */
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+- || defined __cplusplus || defined _MSC_VER)
+ int
+ yyparse (void)
+-#else
+-int
+-yyparse ()
+-
+-#endif
+-#endif
+ {
+-
+-
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+- `yyss': related to states.
+- `yyvs': related to semantic values.
++ 'yyss': related to states.
++ 'yyvs': related to semantic values.
+
+- Refer to the stacks thru separate pointers, to allow yyoverflow
++ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+@@ -1423,7 +1325,7 @@
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+- int yytoken;
++ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+@@ -1441,9 +1343,8 @@
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+- yytoken = 0;
+- yyss = yyssa;
+- yyvs = yyvsa;
++ yyssp = yyss = yyssa;
++ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+@@ -1452,14 +1353,6 @@
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+-
+- /* Initialize stack pointers.
+- Waste one element of value and location stack
+- so that they stay on the same level as the state stack.
+- The wasted elements are never initialized. */
+- yyssp = yyss;
+- yyvsp = yyvs;
+-
+ goto yysetstate;
+
+ /*------------------------------------------------------------.
+@@ -1480,23 +1373,23 @@
+
+ #ifdef yyoverflow
+ {
+- /* Give user a chance to reallocate the stack. Use copies of
+- these so that the &'s don't force the real ones into
+- memory. */
+- YYSTYPE *yyvs1 = yyvs;
+- yytype_int16 *yyss1 = yyss;
+-
+- /* Each stack pointer address is followed by the size of the
+- data in use in that stack, in bytes. This used to be a
+- conditional around just the two extra args, but that might
+- be undefined if yyoverflow is a macro. */
+- yyoverflow (YY_("memory exhausted"),
+- &yyss1, yysize * sizeof (*yyssp),
+- &yyvs1, yysize * sizeof (*yyvsp),
+- &yystacksize);
++ /* Give user a chance to reallocate the stack. Use copies of
++ these so that the &'s don't force the real ones into
++ memory. */
++ YYSTYPE *yyvs1 = yyvs;
++ yytype_int16 *yyss1 = yyss;
++
++ /* Each stack pointer address is followed by the size of the
++ data in use in that stack, in bytes. This used to be a
++ conditional around just the two extra args, but that might
++ be undefined if yyoverflow is a macro. */
++ yyoverflow (YY_("memory exhausted"),
++ &yyss1, yysize * sizeof (*yyssp),
++ &yyvs1, yysize * sizeof (*yyvsp),
++ &yystacksize);
+
+- yyss = yyss1;
+- yyvs = yyvs1;
++ yyss = yyss1;
++ yyvs = yyvs1;
+ }
+ #else /* no yyoverflow */
+ # ifndef YYSTACK_RELOCATE
+@@ -1504,22 +1397,22 @@
+ # else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+- goto yyexhaustedlab;
++ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+- yystacksize = YYMAXDEPTH;
++ yystacksize = YYMAXDEPTH;
+
+ {
+- yytype_int16 *yyss1 = yyss;
+- union yyalloc *yyptr =
+- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+- if (! yyptr)
+- goto yyexhaustedlab;
+- YYSTACK_RELOCATE (yyss_alloc, yyss);
+- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
++ yytype_int16 *yyss1 = yyss;
++ union yyalloc *yyptr =
++ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
++ if (! yyptr)
++ goto yyexhaustedlab;
++ YYSTACK_RELOCATE (yyss_alloc, yyss);
++ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ # undef YYSTACK_RELOCATE
+- if (yyss1 != yyssa)
+- YYSTACK_FREE (yyss1);
++ if (yyss1 != yyssa)
++ YYSTACK_FREE (yyss1);
+ }
+ # endif
+ #endif /* no yyoverflow */
+@@ -1528,10 +1421,10 @@
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+- (unsigned long int) yystacksize));
++ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+- YYABORT;
++ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+@@ -1551,7 +1444,7 @@
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+- if (yyn == YYPACT_NINF)
++ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+@@ -1560,7 +1453,7 @@
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+- yychar = YYLEX;
++ yychar = yylex ();
+ }
+
+ if (yychar <= YYEOF)
+@@ -1582,8 +1475,8 @@
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+- if (yyn == 0 || yyn == YYTABLE_NINF)
+- goto yyerrlab;
++ if (yytable_value_is_error (yyn))
++ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+@@ -1600,7 +1493,9 @@
+ yychar = YYEMPTY;
+
+ yystate = yyn;
++ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
++ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+@@ -1623,7 +1518,7 @@
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+- `$$ = $1'.
++ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+@@ -1637,739 +1532,835 @@
+ switch (yyn)
+ {
+ case 2:
+-
+-/* Line 1455 of yacc.c */
+-#line 122 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_DEFINITIONS|(yyvsp[(3) - (8)].constant));
+- _asn1_set_name((yyval.node),_asn1_get_name((yyvsp[(1) - (8)].node)));
+- _asn1_set_name((yyvsp[(1) - (8)].node),"");
+- _asn1_set_right((yyvsp[(1) - (8)].node),(yyvsp[(7) - (8)].node));
+- _asn1_set_down((yyval.node),(yyvsp[(1) - (8)].node));
++#line 138 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_DEFINITIONS|(yyvsp[-5].constant));
++ _asn1_set_name((yyval.node),_asn1_get_name((yyvsp[-7].node)));
++ _asn1_set_name((yyvsp[-7].node),"");
++ _asn1_set_right((yyvsp[-7].node),(yyvsp[-1].node));
++ _asn1_set_down((yyval.node),(yyvsp[-7].node));
+
+ p_tree=(yyval.node);
+ }
++#line 1544 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 3:
+-
+-/* Line 1455 of yacc.c */
+-#line 132 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 148 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1550 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 4:
+-
+-/* Line 1455 of yacc.c */
+-#line 133 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(2) - (2)].str));}
++#line 149 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1556 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 5:
+-
+-/* Line 1455 of yacc.c */
+-#line 136 "ASN1.y"
+- {strcpy((yyval.str),"-");
+- strcat((yyval.str),(yyvsp[(2) - (2)].str));}
++#line 152 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"-%s",(yyvsp[0].str));}
++#line 1562 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 6:
+-
+-/* Line 1455 of yacc.c */
+-#line 140 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 155 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1568 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 7:
+-
+-/* Line 1455 of yacc.c */
+-#line 141 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 156 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1574 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 8:
+-
+-/* Line 1455 of yacc.c */
+-#line 144 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 159 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1580 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 9:
+-
+-/* Line 1455 of yacc.c */
+-#line 145 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 160 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1586 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 10:
+-
+-/* Line 1455 of yacc.c */
+-#line 148 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 163 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1592 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 11:
+-
+-/* Line 1455 of yacc.c */
+-#line 149 "ASN1.y"
+- {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 164 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"-%s",(yyvsp[0].str));}
++#line 1598 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 12:
+-
+-/* Line 1455 of yacc.c */
+-#line 152 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+- _asn1_set_value((yyval.node),(yyvsp[(2) - (3)].str),strlen((yyvsp[(2) - (3)].str))+1);}
++#line 165 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1604 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 13:
+-
+-/* Line 1455 of yacc.c */
+-#line 154 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+- _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 168 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1610 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 14:
+-
+-/* Line 1455 of yacc.c */
+-#line 159 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 169 "ASN1.y" /* yacc.c:1646 */
++ {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1616 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 15:
+-
+-/* Line 1455 of yacc.c */
+-#line 160 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (3)].node);
+- _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (3)].node)),(yyvsp[(3) - (3)].node));}
++#line 172 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1623 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 16:
+-
+-/* Line 1455 of yacc.c */
+-#line 164 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+- _asn1_set_value((yyval.node),(yyvsp[(1) - (1)].str),strlen((yyvsp[(1) - (1)].str))+1);}
++#line 174 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++ _asn1_set_name((yyval.node),(yyvsp[-3].str));
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1631 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 17:
+-
+-/* Line 1455 of yacc.c */
+-#line 166 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+- _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 179 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 1637 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 18:
+-
+-/* Line 1455 of yacc.c */
+-#line 171 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 180 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[-2].node);
++ _asn1_set_right(_asn1_get_last_right((yyvsp[-2].node)),(yyvsp[0].node));}
++#line 1644 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 19:
+-
+-/* Line 1455 of yacc.c */
+-#line 172 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (2)].node);
+- _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (2)].node)),(yyvsp[(2) - (2)].node));}
++#line 184 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++ _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 1651 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 20:
+-
+-/* Line 1455 of yacc.c */
+-#line 176 "ASN1.y"
+- {(yyval.constant)=CONST_UNIVERSAL;}
++#line 186 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++ _asn1_set_name((yyval.node),(yyvsp[-3].str));
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1659 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 21:
+-
+-/* Line 1455 of yacc.c */
+-#line 177 "ASN1.y"
+- {(yyval.constant)=CONST_PRIVATE;}
++#line 191 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 1665 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 22:
+-
+-/* Line 1455 of yacc.c */
+-#line 178 "ASN1.y"
+- {(yyval.constant)=CONST_APPLICATION;}
++#line 192 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[-1].node);
++ _asn1_set_right(_asn1_get_last_right((yyvsp[-1].node)),(yyvsp[0].node));}
++#line 1672 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 23:
+-
+-/* Line 1455 of yacc.c */
+-#line 181 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_TAG);
+- _asn1_set_value((yyval.node),(yyvsp[(2) - (3)].str),strlen((yyvsp[(2) - (3)].str))+1);}
++#line 196 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.constant)=CONST_UNIVERSAL;}
++#line 1678 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 24:
+-
+-/* Line 1455 of yacc.c */
+-#line 183 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_TAG | (yyvsp[(2) - (4)].constant));
+- _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 197 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.constant)=CONST_PRIVATE;}
++#line 1684 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 25:
+-
+-/* Line 1455 of yacc.c */
+-#line 187 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 198 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.constant)=CONST_APPLICATION;}
++#line 1690 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 26:
+-
+-/* Line 1455 of yacc.c */
+-#line 188 "ASN1.y"
+- {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_EXPLICIT);}
++#line 201 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_TAG);
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1697 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 27:
+-
+-/* Line 1455 of yacc.c */
+-#line 189 "ASN1.y"
+- {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_IMPLICIT);}
++#line 203 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_TAG | (yyvsp[-2].constant));
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1704 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 28:
+-
+-/* Line 1455 of yacc.c */
+-#line 192 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_DEFAULT);
+- _asn1_set_value((yyval.node),(yyvsp[(2) - (2)].str),strlen((yyvsp[(2) - (2)].str))+1);}
++#line 207 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 1710 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 29:
+-
+-/* Line 1455 of yacc.c */
+-#line 194 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
++#line 208 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_EXPLICIT);}
++#line 1716 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 30:
+-
+-/* Line 1455 of yacc.c */
+-#line 195 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
++#line 209 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_IMPLICIT);}
++#line 1722 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 31:
++#line 212 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_DEFAULT);
++ _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 1729 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 32:
++#line 214 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_DEFAULT|CONST_TRUE);}
++#line 1735 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 33:
+-
+-/* Line 1455 of yacc.c */
+-#line 204 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_INTEGER);}
+- break;
+-
+- case 34:
+-
+-/* Line 1455 of yacc.c */
+-#line 205 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
+- break;
+-
+- case 35:
+-
+-/* Line 1455 of yacc.c */
+-#line 207 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_INTEGER);}
++#line 215 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_DEFAULT|CONST_FALSE);}
++#line 1741 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 36:
+-
+-/* Line 1455 of yacc.c */
+-#line 209 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX);
+- _asn1_set_down((yyval.node),_asn1_add_node(TYPE_SIZE));
+- _asn1_set_value(_asn1_get_down((yyval.node)),(yyvsp[(6) - (7)].str),strlen((yyvsp[(6) - (7)].str))+1);
+- _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[(3) - (7)].str));}
++#line 224 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER);}
++#line 1747 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 37:
+-
+-/* Line 1455 of yacc.c */
+-#line 215 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_BOOLEAN);}
++#line 225 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER|CONST_LIST);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 1754 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 38:
+-
+-/* Line 1455 of yacc.c */
+-#line 218 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_TIME|CONST_UTC);}
++#line 227 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER);}
++#line 1760 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 39:
+-
+-/* Line 1455 of yacc.c */
+-#line 219 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);}
++#line 229 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER|CONST_MIN_MAX);
++ _asn1_set_down((yyval.node),_asn1_add_static_node(TYPE_SIZE));
++ _asn1_set_value(_asn1_get_down((yyval.node)),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);
++ _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[-4].str));}
++#line 1769 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 40:
+-
+-/* Line 1455 of yacc.c */
+-#line 222 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM);
+- _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 235 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_BOOLEAN);}
++#line 1775 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 41:
+-
+-/* Line 1455 of yacc.c */
+-#line 225 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX);
+- _asn1_set_value((yyval.node),(yyvsp[(3) - (7)].str),strlen((yyvsp[(3) - (7)].str))+1);
+- _asn1_set_name((yyval.node),(yyvsp[(6) - (7)].str));}
++#line 238 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_UTC_TIME);}
++#line 1781 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 42:
+-
+-/* Line 1455 of yacc.c */
+-#line 230 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 239 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_GENERALIZED_TIME);}
++#line 1787 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 43:
+-
+-/* Line 1455 of yacc.c */
+-#line 231 "ASN1.y"
+- {(yyval.node)=(yyvsp[(2) - (3)].node);}
++#line 242 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SIZE|CONST_1_PARAM);
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1794 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 44:
+-
+-/* Line 1455 of yacc.c */
+-#line 234 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_GENERALSTRING);}
++#line 245 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SIZE|CONST_MIN_MAX);
++ _asn1_set_value((yyval.node),(yyvsp[-4].str),strlen((yyvsp[-4].str))+1);
++ _asn1_set_name((yyval.node),(yyvsp[-1].str));}
++#line 1802 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 45:
+-
+-/* Line 1455 of yacc.c */
+-#line 235 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_GENERALSTRING|CONST_SIZE);
+- _asn1_set_down((yyval.node),(yyvsp[(2) - (2)].node));}
++#line 250 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 1808 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 46:
+-
+-/* Line 1455 of yacc.c */
+-#line 239 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OCTET_STRING);}
++#line 251 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[-1].node);}
++#line 1814 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 47:
+-
+-/* Line 1455 of yacc.c */
+-#line 240 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (3)].node));}
++#line 254 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_GENERALSTRING);}
++#line 1820 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 48:
+-
+-/* Line 1455 of yacc.c */
+-#line 244 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+- _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 255 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_GENERALSTRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1827 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 49:
+-
+-/* Line 1455 of yacc.c */
+-#line 249 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 259 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_UNIVERSAL);}
++#line 1833 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 50:
+-
+-/* Line 1455 of yacc.c */
+-#line 250 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (3)].node);
+- _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (3)].node)),(yyvsp[(3) - (3)].node));}
++#line 260 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1840 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 51:
+-
+-/* Line 1455 of yacc.c */
+-#line 254 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_BIT_STRING);}
++#line 264 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_IA5_STRING);}
++#line 1846 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 52:
+-
+-/* Line 1455 of yacc.c */
+-#line 255 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_BIT_STRING|CONST_SIZE);}
++#line 265 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_IA5_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1853 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 53:
+-
+-/* Line 1455 of yacc.c */
+-#line 257 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
+- _asn1_set_down((yyval.node),(yyvsp[(4) - (5)].node));}
++#line 269 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_TELETEX_STRING);}
++#line 1859 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 54:
+-
+-/* Line 1455 of yacc.c */
+-#line 262 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++#line 270 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_TELETEX_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1866 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 55:
+-
+-/* Line 1455 of yacc.c */
+-#line 267 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID);}
++#line 274 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_PRINTABLE_STRING);}
++#line 1872 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 56:
+-
+-/* Line 1455 of yacc.c */
+-#line 270 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_IDENTIFIER);
+- _asn1_set_value((yyval.node),(yyvsp[(1) - (1)].str),strlen((yyvsp[(1) - (1)].str))+1);}
++#line 275 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_PRINTABLE_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1879 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 57:
+-
+-/* Line 1455 of yacc.c */
+-#line 272 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE);
+- _asn1_set_value((yyval.node),(yyvsp[(1) - (2)].str),strlen((yyvsp[(1) - (2)].str))+1);
+- _asn1_set_down((yyval.node),(yyvsp[(2) - (2)].node));}
++#line 279 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_UNIVERSAL_STRING);}
++#line 1885 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 58:
+-
+-/* Line 1455 of yacc.c */
+-#line 275 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 280 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_UNIVERSAL_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1892 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 59:
+-
+-/* Line 1455 of yacc.c */
+-#line 276 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 284 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_BMP_STRING);}
++#line 1898 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 60:
++#line 285 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_BMP_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1905 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 277 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++ case 61:
++#line 289 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_UTF8_STRING);}
++#line 1911 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 62:
+-
+-/* Line 1455 of yacc.c */
+-#line 279 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 290 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_UTF8_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1918 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 63:
+-
+-/* Line 1455 of yacc.c */
+-#line 280 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 294 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_VISIBLE_STRING);}
++#line 1924 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 64:
+-
+-/* Line 1455 of yacc.c */
+-#line 281 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 295 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_VISIBLE_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1931 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 65:
+-
+-/* Line 1455 of yacc.c */
+-#line 282 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 299 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OCTET_STRING);}
++#line 1937 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 66:
+-
+-/* Line 1455 of yacc.c */
+-#line 283 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 300 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OCTET_STRING|CONST_SIZE);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1944 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 67:
+-
+-/* Line 1455 of yacc.c */
+-#line 284 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 304 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++ _asn1_set_name((yyval.node),(yyvsp[-3].str));
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1952 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 68:
+-
+-/* Line 1455 of yacc.c */
+-#line 285 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 309 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 1958 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 69:
+-
+-/* Line 1455 of yacc.c */
+-#line 286 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 310 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[-2].node);
++ _asn1_set_right(_asn1_get_last_right((yyvsp[-2].node)),(yyvsp[0].node));}
++#line 1965 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 70:
+-
+-/* Line 1455 of yacc.c */
+-#line 287 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_NULL);}
++#line 314 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_BIT_STRING);}
++#line 1971 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 71:
+-
+-/* Line 1455 of yacc.c */
+-#line 290 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 315 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_BIT_STRING|CONST_SIZE);}
++#line 1977 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 72:
+-
+-/* Line 1455 of yacc.c */
+-#line 291 "ASN1.y"
+- {(yyval.node)=_asn1_mod_type((yyvsp[(2) - (2)].node),CONST_TAG);
+- _asn1_set_right((yyvsp[(1) - (2)].node),_asn1_get_down((yyval.node)));
+- _asn1_set_down((yyval.node),(yyvsp[(1) - (2)].node));}
++#line 317 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_BIT_STRING|CONST_LIST);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 1984 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 73:
+-
+-/* Line 1455 of yacc.c */
+-#line 296 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 322 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_ENUMERATED|CONST_LIST);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 1991 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 74:
+-
+-/* Line 1455 of yacc.c */
+-#line 297 "ASN1.y"
+- {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_DEFAULT);
+- _asn1_set_right((yyvsp[(2) - (2)].node),_asn1_get_down((yyval.node)));
+- _asn1_set_down((yyval.node),(yyvsp[(2) - (2)].node));}
++#line 327 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);}
++#line 1997 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 75:
+-
+-/* Line 1455 of yacc.c */
+-#line 300 "ASN1.y"
+- {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_OPTION);}
++#line 330 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_IDENTIFIER);
++ _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 2004 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 76:
+-
+-/* Line 1455 of yacc.c */
+-#line 303 "ASN1.y"
+- {(yyval.node)=_asn1_set_name((yyvsp[(2) - (2)].node),(yyvsp[(1) - (2)].str));}
++#line 332 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_IDENTIFIER|CONST_SIZE);
++ _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2012 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 77:
+-
+-/* Line 1455 of yacc.c */
+-#line 306 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 335 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2018 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 78:
+-
+-/* Line 1455 of yacc.c */
+-#line 307 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (3)].node);
+- _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (3)].node)),(yyvsp[(3) - (3)].node));}
++#line 336 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2024 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+ case 79:
++#line 337 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2030 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 311 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SEQUENCE);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++ case 81:
++#line 339 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2036 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 80:
+-
+-/* Line 1455 of yacc.c */
+-#line 313 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SEQUENCE_OF);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (3)].node));}
++ case 82:
++#line 340 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2042 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 81:
++ case 83:
++#line 341 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2048 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 315 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE);
+- _asn1_set_right((yyvsp[(2) - (4)].node),(yyvsp[(4) - (4)].node));
+- _asn1_set_down((yyval.node),(yyvsp[(2) - (4)].node));}
++ case 84:
++#line 342 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2054 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 82:
++ case 85:
++#line 343 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2060 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 320 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SET);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++ case 86:
++#line 344 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2066 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 83:
++ case 87:
++#line 345 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2072 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 322 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SET_OF);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (3)].node));}
++ case 88:
++#line 346 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2078 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 84:
++ case 89:
++#line 347 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2084 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 324 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_SET_OF|CONST_SIZE);
+- _asn1_set_right((yyvsp[(2) - (4)].node),(yyvsp[(4) - (4)].node));
+- _asn1_set_down((yyval.node),(yyvsp[(2) - (4)].node));}
++ case 90:
++#line 348 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2090 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 85:
++ case 91:
++#line 349 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2096 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 329 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_CHOICE);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++ case 92:
++#line 350 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2102 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 86:
++ case 93:
++#line 351 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2108 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 333 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_ANY);}
++ case 94:
++#line 352 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2114 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 87:
++ case 95:
++#line 353 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2120 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 334 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY);
+- _asn1_set_down((yyval.node),_asn1_add_node(TYPE_CONSTANT));
+- _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[(4) - (4)].str));}
++ case 96:
++#line 354 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2126 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 88:
++ case 97:
++#line 355 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_NULL);}
++#line 2132 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 339 "ASN1.y"
+- {(yyval.node)=_asn1_set_name((yyvsp[(3) - (3)].node),(yyvsp[(1) - (3)].str));}
++ case 98:
++#line 358 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2138 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 89:
++ case 99:
++#line 359 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_mod_type((yyvsp[0].node),CONST_TAG);
++ _asn1_set_right((yyvsp[-1].node),_asn1_get_down((yyval.node)));
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2146 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 343 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (7)].str));
+- _asn1_set_down((yyval.node),(yyvsp[(6) - (7)].node));}
++ case 100:
++#line 364 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2152 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 90:
++ case 101:
++#line 365 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_DEFAULT);
++ _asn1_set_right((yyvsp[0].node),_asn1_get_down((yyval.node)));
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2160 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 347 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (6)].str));
+- _asn1_set_value((yyval.node),(yyvsp[(2) - (6)].str),strlen((yyvsp[(2) - (6)].str))+1);
+- _asn1_set_down((yyval.node),(yyvsp[(5) - (6)].node));}
++ case 102:
++#line 368 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_OPTION);}
++#line 2166 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 91:
++ case 103:
++#line 371 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_set_name((yyvsp[0].node),(yyvsp[-1].str));}
++#line 2172 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 352 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+- _asn1_set_value((yyval.node),(yyvsp[(4) - (4)].str),strlen((yyvsp[(4) - (4)].str))+1);}
++ case 104:
++#line 374 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2178 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 92:
++ case 105:
++#line 375 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[-2].node);
++ _asn1_set_right(_asn1_get_last_right((yyvsp[-2].node)),(yyvsp[0].node));}
++#line 2185 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 357 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++ case 106:
++#line 379 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SEQUENCE);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2192 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 93:
++ case 107:
++#line 381 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SEQUENCE_OF);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2199 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 358 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++ case 108:
++#line 383 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SEQUENCE_OF|CONST_SIZE);
++ _asn1_set_right((yyvsp[-2].node),(yyvsp[0].node));
++ _asn1_set_down((yyval.node),(yyvsp[-2].node));}
++#line 2207 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 94:
++ case 109:
++#line 388 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SET);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2214 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 361 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (1)].node);}
++ case 110:
++#line 390 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SET_OF);
++ _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2221 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 95:
++ case 111:
++#line 392 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_SET_OF|CONST_SIZE);
++ _asn1_set_right((yyvsp[-2].node),(yyvsp[0].node));
++ _asn1_set_down((yyval.node),(yyvsp[-2].node));}
++#line 2229 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 362 "ASN1.y"
+- {(yyval.node)=(yyvsp[(1) - (2)].node);
+- _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (2)].node)),(yyvsp[(2) - (2)].node));}
++ case 112:
++#line 397 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_CHOICE);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2236 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 96:
++ case 113:
++#line 401 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_ANY);}
++#line 2242 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 366 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID);
+- _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));}
++ case 114:
++#line 402 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_ANY|CONST_DEFINED_BY);
++ _asn1_set_down((yyval.node),_asn1_add_static_node(TYPE_CONSTANT));
++ _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[0].str));}
++#line 2250 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 97:
++ case 115:
++#line 407 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_set_name((yyvsp[0].node),(yyvsp[-2].str));}
++#line 2256 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 369 "ASN1.y"
+- {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID);
+- _asn1_set_name((yyval.node),(yyvsp[(1) - (3)].str));}
++ case 116:
++#line 409 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_set_name((yyvsp[0].node), last_error_token);}
++#line 2262 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 98:
++ case 117:
++#line 413 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN);
++ _asn1_set_name((yyval.node),(yyvsp[-6].str));
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2270 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 393 "ASN1.y"
+- {(yyval.constant)=CONST_EXPLICIT;}
++ case 118:
++#line 417 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
++ _asn1_set_name((yyval.node),(yyvsp[-5].str));
++ _asn1_set_value((yyval.node),(yyvsp[-4].str),strlen((yyvsp[-4].str))+1);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2279 "ASN1.c" /* yacc.c:1646 */
+ break;
+
+- case 99:
++ case 119:
++#line 422 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER|CONST_ASSIGN);
++ _asn1_set_name((yyval.node),(yyvsp[-3].str));
++ _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 2287 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 394 "ASN1.y"
+- {(yyval.constant)=CONST_IMPLICIT;}
++ case 120:
++#line 427 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2293 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 121:
++#line 428 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2299 "ASN1.c" /* yacc.c:1646 */
+ break;
+
++ case 122:
++#line 431 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[0].node);}
++#line 2305 "ASN1.c" /* yacc.c:1646 */
++ break;
+
++ case 123:
++#line 432 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=(yyvsp[-1].node);
++ _asn1_set_right(_asn1_get_last_right((yyvsp[-1].node)),(yyvsp[0].node));}
++#line 2312 "ASN1.c" /* yacc.c:1646 */
++ break;
+
+-/* Line 1455 of yacc.c */
+-#line 2371 "ASN1.c"
++ case 124:
++#line 436 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);
++ _asn1_set_down((yyval.node),(yyvsp[-1].node));
++ _asn1_set_name((yyval.node),(yyvsp[-3].str));}
++#line 2320 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 125:
++#line 439 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);
++ _asn1_set_name((yyval.node),(yyvsp[-2].str));}
++#line 2327 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 126:
++#line 441 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);
++ _asn1_set_name((yyval.node),(yyvsp[0].str));}
++#line 2334 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 127:
++#line 465 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.constant)=CONST_EXPLICIT;}
++#line 2340 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++ case 128:
++#line 466 "ASN1.y" /* yacc.c:1646 */
++ {(yyval.constant)=CONST_IMPLICIT;}
++#line 2346 "ASN1.c" /* yacc.c:1646 */
++ break;
++
++
++#line 2350 "ASN1.c" /* yacc.c:1646 */
+ default: break;
+ }
++ /* User semantic actions sometimes alter yychar, and that requires
++ that yytoken be updated with the new translation. We take the
++ approach of translating immediately before every use of yytoken.
++ One alternative is translating here after every semantic action,
++ but that translation would be missed if the semantic action invokes
++ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
++ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
++ incorrect destructor might then be invoked immediately. In the
++ case of YYERROR or YYBACKUP, subsequent parser actions might lead
++ to an incorrect destructor call or verbose syntax error message
++ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+@@ -2378,7 +2369,7 @@
+
+ *++yyvsp = yyval;
+
+- /* Now `shift' the result of the reduction. Determine what state
++ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+@@ -2393,10 +2384,14 @@
+ goto yynewstate;
+
+
+-/*------------------------------------.
+-| yyerrlab -- here on detecting error |
+-`------------------------------------*/
++/*--------------------------------------.
++| yyerrlab -- here on detecting error. |
++`--------------------------------------*/
+ yyerrlab:
++ /* Make sure we have latest lookahead translation. See comments at
++ user semantic actions for why this is necessary. */
++ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
++
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+@@ -2404,37 +2399,36 @@
+ #if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+ #else
++# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
++ yyssp, yytoken)
+ {
+- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+- {
+- YYSIZE_T yyalloc = 2 * yysize;
+- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+- yyalloc = YYSTACK_ALLOC_MAXIMUM;
+- if (yymsg != yymsgbuf)
+- YYSTACK_FREE (yymsg);
+- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+- if (yymsg)
+- yymsg_alloc = yyalloc;
+- else
+- {
+- yymsg = yymsgbuf;
+- yymsg_alloc = sizeof yymsgbuf;
+- }
+- }
+-
+- if (0 < yysize && yysize <= yymsg_alloc)
+- {
+- (void) yysyntax_error (yymsg, yystate, yychar);
+- yyerror (yymsg);
+- }
+- else
+- {
+- yyerror (YY_("syntax error"));
+- if (yysize != 0)
+- goto yyexhaustedlab;
+- }
++ char const *yymsgp = YY_("syntax error");
++ int yysyntax_error_status;
++ yysyntax_error_status = YYSYNTAX_ERROR;
++ if (yysyntax_error_status == 0)
++ yymsgp = yymsg;
++ else if (yysyntax_error_status == 1)
++ {
++ if (yymsg != yymsgbuf)
++ YYSTACK_FREE (yymsg);
++ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
++ if (!yymsg)
++ {
++ yymsg = yymsgbuf;
++ yymsg_alloc = sizeof yymsgbuf;
++ yysyntax_error_status = 2;
++ }
++ else
++ {
++ yysyntax_error_status = YYSYNTAX_ERROR;
++ yymsgp = yymsg;
++ }
++ }
++ yyerror (yymsgp);
++ if (yysyntax_error_status == 2)
++ goto yyexhaustedlab;
+ }
++# undef YYSYNTAX_ERROR
+ #endif
+ }
+
+@@ -2443,20 +2437,20 @@
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+- error, discard it. */
++ error, discard it. */
+
+ if (yychar <= YYEOF)
+- {
+- /* Return failure if at end of input. */
+- if (yychar == YYEOF)
+- YYABORT;
+- }
++ {
++ /* Return failure if at end of input. */
++ if (yychar == YYEOF)
++ YYABORT;
++ }
+ else
+- {
+- yydestruct ("Error: discarding",
+- yytoken, &yylval);
+- yychar = YYEMPTY;
+- }
++ {
++ yydestruct ("Error: discarding",
++ yytoken, &yylval);
++ yychar = YYEMPTY;
++ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+@@ -2475,7 +2469,7 @@
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+- /* Do not reclaim the symbols of the rule which action triggered
++ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+@@ -2488,35 +2482,37 @@
+ | yyerrlab1 -- common code for both syntax error and YYERROR. |
+ `-------------------------------------------------------------*/
+ yyerrlab1:
+- yyerrstatus = 3; /* Each real token shifted decrements this. */
++ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+- if (yyn != YYPACT_NINF)
+- {
+- yyn += YYTERROR;
+- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+- {
+- yyn = yytable[yyn];
+- if (0 < yyn)
+- break;
+- }
+- }
++ if (!yypact_value_is_default (yyn))
++ {
++ yyn += YYTERROR;
++ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
++ {
++ yyn = yytable[yyn];
++ if (0 < yyn)
++ break;
++ }
++ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+- YYABORT;
++ YYABORT;
+
+
+ yydestruct ("Error: popping",
+- yystos[yystate], yyvsp);
++ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
++ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
++ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+@@ -2540,7 +2536,7 @@
+ yyresult = 1;
+ goto yyreturn;
+
+-#if !defined(yyoverflow) || YYERROR_VERBOSE
++#if !defined yyoverflow || YYERROR_VERBOSE
+ /*-------------------------------------------------.
+ | yyexhaustedlab -- memory exhaustion comes here. |
+ `-------------------------------------------------*/
+@@ -2552,16 +2548,21 @@
+
+ yyreturn:
+ if (yychar != YYEMPTY)
+- yydestruct ("Cleanup: discarding lookahead",
+- yytoken, &yylval);
+- /* Do not reclaim the symbols of the rule which action triggered
++ {
++ /* Make sure we have latest lookahead translation. See comments at
++ user semantic actions for why this is necessary. */
++ yytoken = YYTRANSLATE (yychar);
++ yydestruct ("Cleanup: discarding lookahead",
++ yytoken, &yylval);
++ }
++ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+- yystos[*yyssp], yyvsp);
++ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+ #ifndef yyoverflow
+@@ -2572,34 +2573,33 @@
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ #endif
+- /* Make sure YYID is used. */
+- return YYID (yyresult);
++ return yyresult;
+ }
+-
+-
+-
+-/* Line 1675 of yacc.c */
+-#line 398 "ASN1.y"
++#line 470 "ASN1.y" /* yacc.c:1906 */
+
+
+
+
+ static const char *key_word[] = {
+- "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING"
+- ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL"
+- ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER"
+- ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED"
+- ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS"
+- ,"BEGIN","END","UTCTime","GeneralizedTime"
+- ,"GeneralString","FROM","IMPORTS","NULL","ENUMERATED"};
++ "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING",
++ "SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL",
++ "DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER",
++ "BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED",
++ "SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS",
++ "BEGIN","END","UTCTime","GeneralizedTime",
++ "GeneralString","FROM","IMPORTS","NULL","ENUMERATED",
++ "NumericString", "IA5String", "TeletexString", "PrintableString",
++ "UniversalString", "BMPString", "UTF8String", "VisibleString"};
++
+ static const int key_word_token[] = {
+- ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING
+- ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL
+- ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER
+- ,BOOLEAN,ASN1_TRUE,ASN1_FALSE,APPLICATION,ANY,DEFINED
+- ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS
+- ,BEGIN,END,UTCTime,GeneralizedTime
+- ,GeneralString,FROM,IMPORTS,TOKEN_NULL,ENUMERATED};
++ ASSIG, OPTIONAL, INTEGER, SIZE, OCTET, STRING, SEQUENCE, BIT, UNIVERSAL,
++ PRIVATE, OPTIONAL, DEFAULT, CHOICE, OF, OBJECT, STR_IDENTIFIER,
++ BOOLEAN, ASN1_TRUE, ASN1_FALSE, APPLICATION, ANY, DEFINED, SET, BY,
++ EXPLICIT, IMPLICIT, DEFINITIONS, TAGS, BEGIN, END, UTCTime,
++ GeneralizedTime, GeneralString, FROM, IMPORTS, TOKEN_NULL,
++ ENUMERATED, NumericString, IA5String, TeletexString, PrintableString,
++ UniversalString, BMPString, UTF8String, VisibleString
++};
+
+ /*************************************************************/
+ /* Function: _asn1_yylex */
+@@ -2608,83 +2608,98 @@
+ /* Token identifier or ASCII code or 0(zero: End Of File) */
+ /*************************************************************/
+ static int
+-_asn1_yylex()
++_asn1_yylex ()
+ {
+- int c,counter=0,k,lastc;
+- char string[ASN1_MAX_NAME_SIZE+1]; /* will contain the next token */
++ int c, counter = 0, k, lastc;
++ char string[ASN1_MAX_NAME_SIZE + 1]; /* will contain the next token */
+ size_t i;
+
+- while(1)
++ while (1)
+ {
+- while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+- if(c=='\n') lineNumber++;
+-
+- if(c==EOF){
+- strcpy(lastToken,"End Of File");
+- return 0;
+- }
+-
+- if(c=='(' || c==')' || c=='[' || c==']' ||
+- c=='{' || c=='}' || c==',' || c=='.' ||
+- c=='+' || c=='|'){
+- lastToken[0]=c;lastToken[1]=0;
+- return c;
+- }
+- if(c=='-'){ /* Maybe the first '-' of a comment */
+- if((c=fgetc(file_asn1))!='-'){
+- ungetc(c,file_asn1);
+- lastToken[0]='-';lastToken[1]=0;
+- return '-';
+- }
+- else{ /* Comments */
+- lastc=0;
+- counter=0;
+- /* A comment finishes at the next double hypen or the end of line */
+- while((c=fgetc(file_asn1))!=EOF && c!='\n' &&
+- (lastc!='-' || (lastc=='-' && c!='-')))
+- lastc=c;
+- if(c==EOF){
+- strcpy(lastToken,"End Of File");
+- return 0;
+- }
+- else{
+- if(c=='\n') lineNumber++;
+- continue; /* next char, please! (repeat the search) */
+- }
+- }
+- }
+- string[counter++]=c;
+- /* Till the end of the token */
+- while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' ||
+- c=='(' || c==')' || c=='[' || c==']' ||
+- c=='{' || c=='}' || c==',' || c=='.'))
+- {
+- if(counter>=ASN1_MAX_NAME_SIZE){
+- result_parse=ASN1_NAME_TOO_LONG;
+- return 0;
+- }
+- string[counter++]=c;
+- }
+- ungetc(c,file_asn1);
+- string[counter]=0;
+- strcpy(lastToken,string);
+-
+- /* Is STRING a number? */
+- for(k=0;k<counter;k++)
+- if(!isdigit(string[k])) break;
+- if(k>=counter)
+- {
+- strcpy(yylval.str,string);
+- return NUM; /* return the number */
+- }
+-
+- /* Is STRING a keyword? */
+- for(i=0;i<(sizeof(key_word)/sizeof(char*));i++)
+- if(!strcmp(string,key_word[i])) return key_word_token[i];
+-
+- /* STRING is an IDENTIFIER */
+- strcpy(yylval.str,string);
+- return IDENTIFIER;
++ while ((c = fgetc (file_asn1)) == ' ' || c == '\t' || c == '\n')
++ if (c == '\n')
++ line_number++;
++
++ if (c == EOF)
++ {
++ snprintf (last_token, sizeof(last_token), "End Of File");
++ return 0;
++ }
++
++ if (c == '(' || c == ')' || c == '[' || c == ']' ||
++ c == '{' || c == '}' || c == ',' || c == '.' ||
++ c == '+' || c == '|')
++ {
++ last_token[0] = c;
++ last_token[1] = 0;
++ return c;
++ }
++ if (c == '-')
++ { /* Maybe the first '-' of a comment */
++ if ((c = fgetc (file_asn1)) != '-')
++ {
++ ungetc (c, file_asn1);
++ last_token[0] = '-';
++ last_token[1] = 0;
++ return '-';
++ }
++ else
++ { /* Comments */
++ lastc = 0;
++ counter = 0;
++ /* A comment finishes at the next double hypen or the end of line */
++ while ((c = fgetc (file_asn1)) != EOF && c != '\n' &&
++ (lastc != '-' || (lastc == '-' && c != '-')))
++ lastc = c;
++ if (c == EOF)
++ {
++ snprintf (last_token, sizeof(last_token), "End Of File");
++ return 0;
++ }
++ else
++ {
++ if (c == '\n')
++ line_number++;
++ continue; /* next char, please! (repeat the search) */
++ }
++ }
++ }
++ string[counter++] = c;
++ /* Till the end of the token */
++ while (!
++ ((c = fgetc (file_asn1)) == EOF || c == ' ' || c == '\t'
++ || c == '\n' || c == '(' || c == ')' || c == '[' || c == ']'
++ || c == '{' || c == '}' || c == ',' || c == '.'))
++ {
++ if (counter >= ASN1_MAX_NAME_SIZE)
++ {
++ result_parse = ASN1_NAME_TOO_LONG;
++ return 0;
++ }
++ string[counter++] = c;
++ }
++ ungetc (c, file_asn1);
++ string[counter] = 0;
++ snprintf (last_token, sizeof(last_token), "%s", string);
++
++ /* Is STRING a number? */
++ for (k = 0; k < counter; k++)
++ if (!isdigit (string[k]))
++ break;
++ if (k >= counter)
++ {
++ snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++ return NUM; /* return the number */
++ }
++
++ /* Is STRING a keyword? */
++ for (i = 0; i < (sizeof (key_word) / sizeof (char *)); i++)
++ if (!strcmp (string, key_word[i]))
++ return key_word_token[i];
++
++ /* STRING is an IDENTIFIER */
++ snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++ return IDENTIFIER;
+ }
+ }
+
+@@ -2694,136 +2709,121 @@
+ /* error. */
+ /* Parameters: */
+ /* error : error to describe. */
+-/* errorDescription: string that will contain the */
++/* error_desc: string that will contain the */
+ /* description. */
+ /*************************************************************/
+ static void
+-_asn1_create_errorDescription(int error,char *errorDescription)
++_asn1_create_errorDescription (int error, char *error_desc)
+ {
+- switch(error){
+- case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND:
+- if (errorDescription!=NULL) errorDescription[0]=0;
+- break;
+- case ASN1_SYNTAX_ERROR:
+- if (errorDescription!=NULL) {
+- strcpy(errorDescription,fileName);
+- strcat(errorDescription,":");
+- _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+- strcat(errorDescription,": parse error near '");
+- strcat(errorDescription,lastToken);
+- strcat(errorDescription,"'");
+- }
+- break;
+- case ASN1_NAME_TOO_LONG:
+- if (errorDescription!=NULL) {
+- strcpy(errorDescription,fileName);
+- strcat(errorDescription,":");
+- _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+- strcat(errorDescription,": name too long (more than ");
+- _asn1_ltostr(ASN1_MAX_NAME_SIZE,errorDescription+strlen(errorDescription));
+- strcat(errorDescription," characters)");
+- }
+- break;
+- case ASN1_IDENTIFIER_NOT_FOUND:
+- if (errorDescription!=NULL) {
+- strcpy(errorDescription,fileName);
+- strcat(errorDescription,":");
+- strcat(errorDescription,": identifier '");
+- strcat(errorDescription,_asn1_identifierMissing);
+- strcat(errorDescription,"' not found");
++ if (error_desc == NULL)
++ return;
++
++
++ switch (error)
++ {
++ case ASN1_FILE_NOT_FOUND:
++ snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s file was not found", file_name);
++ break;
++ case ASN1_SYNTAX_ERROR:
++ snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_error);
++ break;
++ case ASN1_NAME_TOO_LONG:
++ snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++ "%s:%u: name too long (more than %u characters)", file_name,
++ line_number, ASN1_MAX_NAME_SIZE);
++ break;
++ case ASN1_IDENTIFIER_NOT_FOUND:
++ snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++ "%s:: identifier '%s' not found", file_name,
++ _asn1_identifierMissing);
++ break;
++ default:
++ error_desc[0] = 0;
++ break;
+ }
+- break;
+- default:
+- if (errorDescription!=NULL) errorDescription[0]=0;
+- break;
+- }
+
+ }
+
+ /**
+ * asn1_parser2tree:
+- * @file_name: specify the path and the name of file that contains
++ * @file: specify the path and the name of file that contains
+ * ASN.1 declarations.
+ * @definitions: return the pointer to the structure created from
+- * "file_name" ASN.1 declarations.
+- * @errorDescription: return the error description or an empty
++ * "file" ASN.1 declarations.
++ * @error_desc: return the error description or an empty
+ * string if success.
+ *
+ * Function used to start the parse algorithm. Creates the structures
+- * needed to manage the definitions included in @file_name file.
+- *
+- * Returns:
++ * needed to manage the definitions included in @file file.
+ *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- * is known.
+- *
+- * %ASN1_ELEMENT_NOT_EMPTY: @definitions not %ASN1_TYPE_EMPTY.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @file_name.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- * than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ * identifier is known, %ASN1_ELEMENT_NOT_EMPTY if @definitions not
++ * %NULL, %ASN1_FILE_NOT_FOUND if an error occured while
++ * opening @file, %ASN1_SYNTAX_ERROR if the syntax is not
++ * correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an
++ * identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ * file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ * characters.
+ **/
+-asn1_retCode
+-asn1_parser2tree(const char *file_name, ASN1_TYPE *definitions,
+- char *errorDescription){
++int
++asn1_parser2tree (const char *file, ASN1_TYPE * definitions,
++ char *error_desc)
++{
+
+- p_tree=ASN1_TYPE_EMPTY;
++ p_tree = NULL;
+
+- if(*definitions != ASN1_TYPE_EMPTY)
++ if (*definitions != NULL)
+ return ASN1_ELEMENT_NOT_EMPTY;
+
+- *definitions=ASN1_TYPE_EMPTY;
++ *definitions = NULL;
+
+- fileName = file_name;
++ file_name = file;
+
+ /* open the file to parse */
+- file_asn1=fopen(file_name,"r");
++ file_asn1 = fopen (file, "r");
+
+- if(file_asn1==NULL){
+- result_parse=ASN1_FILE_NOT_FOUND;
+- }
+- else{
+- result_parse=ASN1_SUCCESS;
+-
+- lineNumber=1;
+- yyparse();
++ if (file_asn1 == NULL)
++ {
++ result_parse = ASN1_FILE_NOT_FOUND;
++ }
++ else
++ {
++ result_parse = ASN1_SUCCESS;
+
+- fclose(file_asn1);
++ line_number = 1;
++ yyparse ();
+
+- if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+- /* set IMPLICIT or EXPLICIT property */
+- _asn1_set_default_tag(p_tree);
+- /* set CONST_SET and CONST_NOT_USED */
+- _asn1_type_set_config(p_tree);
+- /* check the identifier definitions */
+- result_parse=_asn1_check_identifier(p_tree);
+- if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+- /* Delete the list and keep the ASN1 structure */
+- _asn1_delete_list();
+- /* Convert into DER coding the value assign to INTEGER constants */
+- _asn1_change_integer_value(p_tree);
+- /* Expand the IDs of OBJECT IDENTIFIER constants */
+- _asn1_expand_object_id(p_tree);
++ fclose (file_asn1);
+
+- *definitions=p_tree;
+- }
+- else /* some identifiers not defined */
+- /* Delete the list and the ASN1 structure */
+- _asn1_delete_list_and_nodes();
++ if (result_parse == ASN1_SUCCESS)
++ { /* syntax OK */
++ /* set IMPLICIT or EXPLICIT property */
++ _asn1_set_default_tag (p_tree);
++ /* set CONST_SET and CONST_NOT_USED */
++ _asn1_type_set_config (p_tree);
++ /* check the identifier definitions */
++ result_parse = _asn1_check_identifier (p_tree);
++ if (result_parse == ASN1_SUCCESS)
++ { /* all identifier defined */
++ /* Delete the list and keep the ASN1 structure */
++ _asn1_delete_list ();
++ /* Convert into DER coding the value assign to INTEGER constants */
++ _asn1_change_integer_value (p_tree);
++ /* Expand the IDs of OBJECT IDENTIFIER constants */
++ _asn1_expand_object_id (p_tree);
++
++ *definitions = p_tree;
++ }
++ else /* some identifiers not defined */
++ /* Delete the list and the ASN1 structure */
++ _asn1_delete_list_and_nodes ();
++ }
++ else /* syntax error */
++ /* Delete the list and the ASN1 structure */
++ _asn1_delete_list_and_nodes ();
+ }
+- else /* syntax error */
+- /* Delete the list and the ASN1 structure */
+- _asn1_delete_list_and_nodes();
+- }
+
+- if (errorDescription!=NULL)
+- _asn1_create_errorDescription(result_parse,errorDescription);
++ _asn1_create_errorDescription (result_parse, error_desc);
+
+ return result_parse;
+ }
+@@ -2835,7 +2835,7 @@
+ * @outputFileName: specify the path and the name of file that will
+ * contain the C vector definition.
+ * @vectorName: specify the name of the C vector.
+- * @errorDescription : return the error description or an empty
++ * @error_desc: return the error description or an empty
+ * string if success.
+ *
+ * Function that generates a C structure from an ASN1 file. Creates a
+@@ -2845,113 +2845,118 @@
+ * "/aa/bb/xx_asn1_tab.c". If @vectorName is %NULL the vector name
+ * will be "xx_asn1_tab".
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- * is known.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @inputFileName.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- * than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ * identifier is known, %ASN1_FILE_NOT_FOUND if an error occured
++ * while opening @inputFileName, %ASN1_SYNTAX_ERROR if the syntax is
++ * not correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is
++ * an identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ * file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ * characters.
+ **/
+-int asn1_parser2array(const char *inputFileName,const char *outputFileName,
+- const char *vectorName,char *errorDescription){
+- char *file_out_name=NULL;
+- char *vector_name=NULL;
+- const char *char_p,*slash_p,*dot_p;
++int
++asn1_parser2array (const char *inputFileName, const char *outputFileName,
++ const char *vectorName, char *error_desc)
++{
++ char *file_out_name = NULL;
++ char *vector_name = NULL;
++ const char *char_p, *slash_p, *dot_p;
+
+- p_tree=NULL;
++ p_tree = NULL;
+
+- fileName = inputFileName;
++ file_name = inputFileName;
+
+ /* open the file to parse */
+- file_asn1=fopen(inputFileName,"r");
++ file_asn1 = fopen (inputFileName, "r");
++
++ if (file_asn1 == NULL)
++ result_parse = ASN1_FILE_NOT_FOUND;
++ else
++ {
++ result_parse = ASN1_SUCCESS;
+
+- if(file_asn1==NULL)
+- result_parse=ASN1_FILE_NOT_FOUND;
+- else{
+- result_parse=ASN1_SUCCESS;
+-
+- lineNumber=1;
+- yyparse();
+-
+- fclose(file_asn1);
+-
+- if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+- /* set IMPLICIT or EXPLICIT property */
+- _asn1_set_default_tag(p_tree);
+- /* set CONST_SET and CONST_NOT_USED */
+- _asn1_type_set_config(p_tree);
+- /* check the identifier definitions */
+- result_parse=_asn1_check_identifier(p_tree);
+-
+- if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+-
+- /* searching the last '/' and '.' in inputFileName */
+- char_p=inputFileName;
+- slash_p=inputFileName;
+- while((char_p=strchr(char_p,'/'))){
+- char_p++;
+- slash_p=char_p;
+- }
+-
+- char_p=slash_p;
+- dot_p=inputFileName+strlen(inputFileName);
+-
+- while((char_p=strchr(char_p,'.'))){
+- dot_p=char_p;
+- char_p++;
+- }
+-
+- if(outputFileName == NULL){
+- /* file_out_name = inputFileName + _asn1_tab.c */
+- file_out_name=(char *)malloc(dot_p-inputFileName+1+
+- strlen("_asn1_tab.c"));
+- memcpy(file_out_name,inputFileName,dot_p-inputFileName);
+- file_out_name[dot_p-inputFileName]=0;
+- strcat(file_out_name,"_asn1_tab.c");
+- }
+- else{
+- /* file_out_name = inputFileName */
+- file_out_name=(char *)malloc(strlen(outputFileName)+1);
+- strcpy(file_out_name,outputFileName);
+- }
+-
+- if(vectorName == NULL){
+- /* vector_name = file name + _asn1_tab */
+- vector_name=(char *)malloc(dot_p-slash_p+1+
+- strlen("_asn1_tab"));
+- memcpy(vector_name,slash_p,dot_p-slash_p);
+- vector_name[dot_p-slash_p]=0;
+- strcat(vector_name,"_asn1_tab");
+- }
+- else{
+- /* vector_name = vectorName */
+- vector_name=(char *)malloc(strlen(vectorName)+1);
+- strcpy(vector_name,vectorName);
+- }
+-
+- /* Save structure in a file */
+- _asn1_create_static_structure(p_tree,
+- file_out_name,vector_name);
+-
+- free(file_out_name);
+- free(vector_name);
+- } /* result == OK */
+- } /* result == OK */
+-
+- /* Delete the list and the ASN1 structure */
+- _asn1_delete_list_and_nodes();
+- } /* inputFile exist */
++ line_number = 1;
++ yyparse ();
+
+- if (errorDescription!=NULL)
+- _asn1_create_errorDescription(result_parse,errorDescription);
++ fclose (file_asn1);
++
++ if (result_parse == ASN1_SUCCESS)
++ { /* syntax OK */
++ /* set IMPLICIT or EXPLICIT property */
++ _asn1_set_default_tag (p_tree);
++ /* set CONST_SET and CONST_NOT_USED */
++ _asn1_type_set_config (p_tree);
++ /* check the identifier definitions */
++ result_parse = _asn1_check_identifier (p_tree);
++
++ if (result_parse == ASN1_SUCCESS)
++ { /* all identifier defined */
++
++ /* searching the last '/' and '.' in inputFileName */
++ char_p = inputFileName;
++ slash_p = inputFileName;
++ while ((char_p = strchr (char_p, '/')))
++ {
++ char_p++;
++ slash_p = char_p;
++ }
++
++ char_p = slash_p;
++ dot_p = inputFileName + strlen (inputFileName);
++
++ while ((char_p = strchr (char_p, '.')))
++ {
++ dot_p = char_p;
++ char_p++;
++ }
++
++ if (outputFileName == NULL)
++ {
++ /* file_out_name = inputFileName + _asn1_tab.c */
++ file_out_name = malloc (dot_p - inputFileName + 1 +
++ strlen ("_asn1_tab.c"));
++ memcpy (file_out_name, inputFileName,
++ dot_p - inputFileName);
++ file_out_name[dot_p - inputFileName] = 0;
++ strcat (file_out_name, "_asn1_tab.c");
++ }
++ else
++ {
++ /* file_out_name = inputFileName */
++ file_out_name =
++ (char *) malloc (strlen (outputFileName) + 1);
++ strcpy (file_out_name, outputFileName);
++ }
++
++ if (vectorName == NULL)
++ {
++ /* vector_name = file name + _asn1_tab */
++ vector_name = malloc (dot_p - slash_p + 1 +
++ strlen ("_asn1_tab"));
++ memcpy (vector_name, slash_p, dot_p - slash_p);
++ vector_name[dot_p - slash_p] = 0;
++ strcat (vector_name, "_asn1_tab");
++ }
++ else
++ {
++ /* vector_name = vectorName */
++ vector_name = (char *) malloc (strlen (vectorName) + 1);
++ strcpy (vector_name, vectorName);
++ }
++
++ /* Save structure in a file */
++ _asn1_create_static_structure (p_tree,
++ file_out_name, vector_name);
++
++ free (file_out_name);
++ free (vector_name);
++ } /* result == OK */
++ } /* result == OK */
++
++ /* Delete the list and the ASN1 structure */
++ _asn1_delete_list_and_nodes ();
++ } /* inputFile exist */
++
++ _asn1_create_errorDescription (result_parse, error_desc);
+
+ return result_parse;
+ }
+@@ -2964,18 +2969,35 @@
+ /* Return: int */
+ /* */
+ /*************************************************************/
+-static int _asn1_yyerror (const char *s)
++static void
++_asn1_yyerror (const char *s)
+ {
+ /* Sends the error description to the std_out */
+
+-#if 0
+- printf("_asn1_yyerror:%s:%ld: %s (Last Token:'%s')\n",fileName,
+- lineNumber,s,lastToken);
+-#endif
++ if (strcmp (last_token, "VisibleString") == 0 ||
++ strcmp (last_token, "PrintableString") == 0 ||
++ strcmp (last_token, "UniversalString") == 0 ||
++ strcmp (last_token, "IA5String") == 0 ||
++ strcmp (last_token, "UTF8String") == 0 ||
++ strcmp (last_token, "NumericString") == 0 ||
++ strcmp (last_token, "TeletexString") == 0 ||
++ strcmp (last_token, "BMPString") == 0)
++ {
++ snprintf (last_error_token, sizeof(last_error_token),
++ "%s", last_token);
++ fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n",
++ file_name, line_number, last_token);
++ return;
++ }
++ last_error_token[0] = 0;
+
+- if(result_parse!=ASN1_NAME_TOO_LONG)
+- result_parse=ASN1_SYNTAX_ERROR;
++ if (result_parse != ASN1_NAME_TOO_LONG)
++ {
++ snprintf (last_error, sizeof(last_error),
++ "%s:%u: Error: %s near '%s'", file_name,
++ line_number, s, last_token);
++ result_parse = ASN1_SYNTAX_ERROR;
++ }
+
+- return 0;
++ return;
+ }
+-
+--- ORIGINAL/./lib/element.c 2015-07-14 18:28:22.914356512 -0700
++++ libtasn1-2.8/./lib/element.c 2015-07-14 18:45:02.664963151 -0700
+@@ -46,7 +46,7 @@
+
+ while (p != NULL)
+ {
+- if (p->name != NULL)
++ if (p->name[0] != 0)
+ {
+ _asn1_str_cpy (tmp_name, sizeof (tmp_name), name),
+ _asn1_str_cpy (name, name_size, p->name);
+@@ -75,8 +75,8 @@
+ /* len: number of significant byte of value_out. */
+ /* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */
+ /******************************************************************/
+-asn1_retCode
+-_asn1_convert_integer (const char *value, unsigned char *value_out,
++int
++_asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
+ int value_out_size, int *len)
+ {
+ char negative;
+@@ -84,7 +84,7 @@
+ long valtmp;
+ int k, k2;
+
+- valtmp = strtol (value, NULL, 10);
++ valtmp = _asn1_strtol (value, NULL, 10);
+
+ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
+ {
+@@ -114,10 +114,10 @@
+ return ASN1_MEM_ERROR;
+
+ if (value_out != NULL)
+- {
+- for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+- value_out[k2 - k] = val[k2];
+- }
++ {
++ for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
++ value_out[k2 - k] = val[k2];
++ }
+
+ #if 0
+ printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
+@@ -134,7 +134,7 @@
+ _asn1_append_sequence_set (ASN1_TYPE node)
+ {
+ ASN1_TYPE p, p2;
+- char temp[10];
++ char temp[LTOSTR_MAX_SIZE];
+ long n;
+
+ if (!node || !(node->down))
+@@ -149,7 +149,7 @@
+ p = p->right;
+ _asn1_set_right (p, p2);
+
+- if (p->name == NULL)
++ if (p->name[0] == 0)
+ _asn1_str_cpy (temp, sizeof (temp), "?1");
+ else
+ {
+@@ -267,15 +267,11 @@
+ * result=asn1_write_value(cert,
+ * "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1);
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Set value OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+- *
+- * %ASN1_VALUE_NOT_VALID: VALUE has a wrong format.
++ * Returns: %ASN1_SUCCESS if the value was set,
++ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and
++ * %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format.
+ **/
+-asn1_retCode
++int
+ asn1_write_value (ASN1_TYPE node_root, const char *name,
+ const void *ivalue, int len)
+ {
+@@ -284,6 +280,7 @@
+ int len2, k, k2, negative;
+ size_t i;
+ const unsigned char *value = ivalue;
++ unsigned int type;
+
+ node = asn1_find_node (node_root, name);
+ if (node == NULL)
+@@ -295,8 +292,9 @@
+ return ASN1_SUCCESS;
+ }
+
+- if ((type_field (node->type) == TYPE_SEQUENCE_OF) && (value == NULL)
+- && (len == 0))
++ type = type_field (node->type);
++
++ if ((type == TYPE_SEQUENCE_OF || type == TYPE_SET_OF) && (value == NULL) && (len == 0))
+ {
+ p = node->down;
+ while ((type_field (p->type) == TYPE_TAG)
+@@ -309,10 +307,16 @@
+ return ASN1_SUCCESS;
+ }
+
+- switch (type_field (node->type))
++ /* Don't allow element deletion for other types */
++ if (value == NULL)
++ {
++ return ASN1_VALUE_NOT_VALID;
++ }
++
++ switch (type)
+ {
+ case TYPE_BOOLEAN:
+- if (!strcmp (value, "TRUE"))
++ if (!_asn1_strcmp (value, "TRUE"))
+ {
+ if (node->type & CONST_DEFAULT)
+ {
+@@ -327,7 +331,7 @@
+ else
+ _asn1_set_value (node, "T", 1);
+ }
+- else if (!strcmp (value, "FALSE"))
++ else if (!_asn1_strcmp (value, "FALSE"))
+ {
+ if (node->type & CONST_DEFAULT)
+ {
+@@ -351,8 +355,7 @@
+ {
+ if ((isdigit (value[0])) || (value[0] == '-'))
+ {
+- value_temp =
+- (unsigned char *) _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++ value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ if (value_temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+@@ -368,11 +371,9 @@
+ {
+ if (type_field (p->type) == TYPE_CONSTANT)
+ {
+- if ((p->name) && (!strcmp (p->name, value)))
++ if (!_asn1_strcmp (p->name, value))
+ {
+- value_temp =
+- (unsigned char *)
+- _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++ value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ if (value_temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+@@ -391,13 +392,12 @@
+ }
+ else
+ { /* len != 0 */
+- value_temp = (unsigned char *) _asn1_malloc (len);
++ value_temp = malloc (len);
+ if (value_temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+ memcpy (value_temp, value, len);
+ }
+
+-
+ if (value_temp[0] & 0x80)
+ negative = 1;
+ else
+@@ -405,7 +405,7 @@
+
+ if (negative && (type_field (node->type) == TYPE_ENUMERATED))
+ {
+- _asn1_free (value_temp);
++ free (value_temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+
+@@ -419,7 +419,7 @@
+ (!negative && (value_temp[k] & 0x80)))
+ k--;
+
+- _asn1_set_value_octet (node, value_temp + k, len - k);
++ _asn1_set_value_lv (node, value_temp + k, len - k);
+
+ if (node->type & CONST_DEFAULT)
+ {
+@@ -428,11 +428,10 @@
+ p = p->right;
+ if ((isdigit (p->value[0])) || (p->value[0] == '-'))
+ {
+- default_temp =
+- (unsigned char *) _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++ default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ if (default_temp == NULL)
+ {
+- _asn1_free (value_temp);
++ free (value_temp);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+@@ -443,7 +442,7 @@
+ { /* is an identifier like v1 */
+ if (!(node->type & CONST_LIST))
+ {
+- _asn1_free (value_temp);
++ free (value_temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+ p2 = node->down;
+@@ -451,14 +450,12 @@
+ {
+ if (type_field (p2->type) == TYPE_CONSTANT)
+ {
+- if ((p2->name) && (!strcmp (p2->name, p->value)))
++ if (!_asn1_strcmp (p2->name, p->value))
+ {
+- default_temp =
+- (unsigned char *)
+- _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++ default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ if (default_temp == NULL)
+ {
+- _asn1_free (value_temp);
++ free (value_temp);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+@@ -473,7 +470,7 @@
+ }
+ if (p2 == NULL)
+ {
+- _asn1_free (value_temp);
++ free (value_temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+ }
+@@ -489,12 +486,12 @@
+ if (k2 == len2)
+ _asn1_set_value (node, NULL, 0);
+ }
+- _asn1_free (default_temp);
++ free (default_temp);
+ }
+- _asn1_free (value_temp);
++ free (value_temp);
+ break;
+ case TYPE_OBJECT_ID:
+- for (i = 0; i < strlen (value); i++)
++ for (i = 0; i < _asn1_strlen (value); i++)
+ if ((!isdigit (value[i])) && (value[i] != '.') && (value[i] != '+'))
+ return ASN1_VALUE_NOT_VALID;
+ if (node->type & CONST_DEFAULT)
+@@ -502,75 +499,78 @@
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+- if (!strcmp (value, p->value))
++ if (!_asn1_strcmp (value, p->value))
+ {
+ _asn1_set_value (node, NULL, 0);
+ break;
+ }
+ }
+- _asn1_set_value (node, value, strlen (value) + 1);
++ _asn1_set_value (node, value, _asn1_strlen (value) + 1);
+ break;
+- case TYPE_TIME:
+- if (node->type & CONST_UTC)
+- {
+- if (strlen (value) < 11)
++ case TYPE_UTC_TIME:
++ {
++ len = _asn1_strlen (value);
++ if (len < 11)
++ return ASN1_VALUE_NOT_VALID;
++ for (k = 0; k < 10; k++)
++ if (!isdigit (value[k]))
+ return ASN1_VALUE_NOT_VALID;
+- for (k = 0; k < 10; k++)
+- if (!isdigit (value[k]))
++ switch (len)
++ {
++ case 11:
++ if (value[10] != 'Z')
+ return ASN1_VALUE_NOT_VALID;
+- switch (strlen (value))
+- {
+- case 11:
+- if (value[10] != 'Z')
+- return ASN1_VALUE_NOT_VALID;
+- break;
+- case 13:
+- if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
+- (value[12] != 'Z'))
+- return ASN1_VALUE_NOT_VALID;
+- break;
+- case 15:
+- if ((value[10] != '+') && (value[10] != '-'))
+- return ASN1_VALUE_NOT_VALID;
+- for (k = 11; k < 15; k++)
+- if (!isdigit (value[k]))
+- return ASN1_VALUE_NOT_VALID;
+- break;
+- case 17:
+- if ((!isdigit (value[10])) || (!isdigit (value[11])))
++ break;
++ case 13:
++ if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
++ (value[12] != 'Z'))
++ return ASN1_VALUE_NOT_VALID;
++ break;
++ case 15:
++ if ((value[10] != '+') && (value[10] != '-'))
++ return ASN1_VALUE_NOT_VALID;
++ for (k = 11; k < 15; k++)
++ if (!isdigit (value[k]))
+ return ASN1_VALUE_NOT_VALID;
+- if ((value[12] != '+') && (value[12] != '-'))
++ break;
++ case 17:
++ if ((!isdigit (value[10])) || (!isdigit (value[11])))
++ return ASN1_VALUE_NOT_VALID;
++ if ((value[12] != '+') && (value[12] != '-'))
++ return ASN1_VALUE_NOT_VALID;
++ for (k = 13; k < 17; k++)
++ if (!isdigit (value[k]))
+ return ASN1_VALUE_NOT_VALID;
+- for (k = 13; k < 17; k++)
+- if (!isdigit (value[k]))
+- return ASN1_VALUE_NOT_VALID;
+- break;
+- default:
+- return ASN1_VALUE_NOT_FOUND;
+- }
+- _asn1_set_value (node, value, strlen (value) + 1);
+- }
+- else
+- { /* GENERALIZED TIME */
+- if (value)
+- _asn1_set_value (node, value, strlen (value) + 1);
+- }
++ break;
++ default:
++ return ASN1_VALUE_NOT_FOUND;
++ }
++ _asn1_set_value (node, value, len);
++ }
++ break;
++ case TYPE_GENERALIZED_TIME:
++ len = _asn1_strlen (value);
++ _asn1_set_value (node, value, len);
+ break;
+ case TYPE_OCTET_STRING:
+- if (len == 0)
+- len = strlen (value);
+- _asn1_set_value_octet (node, value, len);
+- break;
+ case TYPE_GENERALSTRING:
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ if (len == 0)
+- len = strlen (value);
+- _asn1_set_value_octet (node, value, len);
++ len = _asn1_strlen (value);
++ _asn1_set_value_lv (node, value, len);
+ break;
+ case TYPE_BIT_STRING:
+ if (len == 0)
+- len = strlen (value);
++ len = _asn1_strlen (value);
+ asn1_length_der ((len >> 3) + 2, NULL, &len2);
+- temp = (unsigned char *) _asn1_malloc ((len >> 3) + 2 + len2);
++ temp = malloc ((len >> 3) + 2 + len2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+@@ -582,7 +582,7 @@
+ p = node->down;
+ while (p)
+ {
+- if (!strcmp (p->name, value))
++ if (!_asn1_strcmp (p->name, value))
+ {
+ p2 = node->down;
+ while (p2)
+@@ -603,11 +603,11 @@
+ return ASN1_ELEMENT_NOT_FOUND;
+ break;
+ case TYPE_ANY:
+- _asn1_set_value_octet (node, value, len);
++ _asn1_set_value_lv (node, value, len);
+ break;
+ case TYPE_SEQUENCE_OF:
+ case TYPE_SET_OF:
+- if (strcmp (value, "NEW"))
++ if (_asn1_strcmp (value, "NEW"))
+ return ASN1_VALUE_NOT_VALID;
+ _asn1_append_sequence_set (node);
+ break;
+@@ -626,29 +626,43 @@
+ return ASN1_MEM_ERROR; \
+ } else { \
+ if (ptr && data_size > 0) \
+- memcpy( ptr, data, data_size); \
++ memcpy (ptr, data, data_size); \
+ }
+
+ #define PUT_STR_VALUE( ptr, ptr_size, data) \
+- *len = strlen(data) + 1; \
++ *len = _asn1_strlen (data) + 1; \
+ if (ptr_size < *len) { \
+ return ASN1_MEM_ERROR; \
+ } else { \
+ /* this strcpy is checked */ \
+ if (ptr) { \
+- strcpy(ptr, data); \
++ _asn1_strcpy (ptr, data); \
+ } \
+ }
+
+-#define ADD_STR_VALUE( ptr, ptr_size, data) \
+- *len += strlen(data); \
+- if (ptr_size < (int) *len) { \
+- (*len)++; \
++#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
++ *len = data_size + 1; \
++ if (ptr_size < *len) { \
+ return ASN1_MEM_ERROR; \
+ } else { \
+- /* this strcat is checked */ \
+- if (ptr) strcat (ptr, data); \
++ /* this strcpy is checked */ \
++ if (ptr) { \
++ if (data_size > 0) \
++ memcpy (ptr, data, data_size); \
++ ptr[data_size] = 0; \
++ } \
+ }
++
++#define ADD_STR_VALUE( ptr, ptr_size, data) \
++ *len += _asn1_strlen(data); \
++ if (ptr_size < (int) *len) { \
++ (*len)++; \
++ return ASN1_MEM_ERROR; \
++ } else { \
++ /* this strcat is checked */ \
++ if (ptr) _asn1_strcat (ptr, data); \
++ }
++
+ /**
+ * asn1_read_value:
+ * @root: pointer to a structure.
+@@ -658,7 +672,7 @@
+ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
+ * holds the sizeof value.
+ *
+- * Returns the value of one element inside a structure.
++ * Returns the value of one element inside a structure.
+ * If an element is OPTIONAL and this returns
+ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
+ * in the der encoding that created the structure. The first element
+@@ -668,6 +682,7 @@
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
++ * INTEGER: VALUE will contain a two's complement form integer.
+ *
+ * integer=-1 -> value[0]=0xFF , len=1.
+ * integer=1 -> value[0]=0x01 , len=1.
+@@ -704,36 +719,109 @@
+ * ANY: If NAME indicates an any type, VALUE will indicate the DER
+ * encoding of the structure actually used.
+ *
+- * Returns:
++ * Returns: %ASN1_SUCCESS if value is returned,
++ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
++ * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
++ * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
++ * to store the result, and in this case @len will contain the number of
++ * bytes needed.
++ **/
++int
++asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
++{
++ return asn1_read_value_type (root, name, ivalue, len, NULL);
++}
++
++/**
++ * asn1_read_value_type:
++ * @root: pointer to a structure.
++ * @name: the name of the element inside a structure that you want to read.
++ * @ivalue: vector that will contain the element's content, must be a
++ * pointer to memory cells already allocated (may be %NULL).
++ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
++ * holds the sizeof value.
++ * @etype: The type of the value read (TYPE)
++ *
++ * Returns the value of one element inside a structure.
++ * If an element is OPTIONAL and this returns
++ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
++ * in the der encoding that created the structure. The first element
++ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
++ * so on.
++ *
++ * Note that there can be valid values with length zero. In these case
++ * this function will succeed and @len will be zero.
++ *
+ *
+- * %ASN1_SUCCESS: Set value OK.
++ * INTEGER: VALUE will contain a two's complement form integer.
+ *
+- * %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
++ * integer=-1 -> value[0]=0xFF , len=1.
++ * integer=1 -> value[0]=0x01 , len=1.
+ *
+- * %ASN1_VALUE_NOT_FOUND: There isn't any value for the element selected.
++ * ENUMERATED: As INTEGER (but only with not negative numbers).
++ *
++ * BOOLEAN: VALUE will be the null terminated string "TRUE" or
++ * "FALSE" and LEN=5 or LEN=6.
++ *
++ * OBJECT IDENTIFIER: VALUE will be a null terminated string with
++ * each number separated by a dot (i.e. "1.2.3.543.1").
++ *
++ * LEN = strlen(VALUE)+1
++ *
++ * UTCTime: VALUE will be a null terminated string in one of these
++ * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
++ * LEN=strlen(VALUE)+1.
++ *
++ * GeneralizedTime: VALUE will be a null terminated string in the
++ * same format used to set the value.
++ *
++ * OCTET STRING: VALUE will contain the octet string and LEN will be
++ * the number of octets.
++ *
++ * GeneralString: VALUE will contain the generalstring and LEN will
++ * be the number of octets.
++ *
++ * BIT STRING: VALUE will contain the bit string organized by bytes
++ * and LEN will be the number of bits.
++ *
++ * CHOICE: If NAME indicates a choice type, VALUE will specify the
++ * alternative selected.
++ *
++ * ANY: If NAME indicates an any type, VALUE will indicate the DER
++ * encoding of the structure actually used.
+ *
+- * %ASN1_MEM_ERROR: The value vector isn't big enough to store the result.
+- * In this case LEN will contain the number of bytes needed.
++ * Returns: %ASN1_SUCCESS if value is returned,
++ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
++ * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
++ * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
++ * to store the result, and in this case @len will contain the number of
++ * bytes needed.
+ **/
+-asn1_retCode
+-asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
++int
++asn1_read_value_type (ASN1_TYPE root, const char *name, void *ivalue,
++ int *len, unsigned int *etype)
+ {
+ ASN1_TYPE node, p, p2;
+- int len2, len3;
++ int len2, len3, result;
+ int value_size = *len;
+ unsigned char *value = ivalue;
++ unsigned type;
+
+ node = asn1_find_node (root, name);
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+- if ((type_field (node->type) != TYPE_NULL) &&
+- (type_field (node->type) != TYPE_CHOICE) &&
++ type = type_field (node->type);
++
++ if ((type != TYPE_NULL) &&
++ (type != TYPE_CHOICE) &&
+ !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) &&
+ (node->value == NULL))
+ return ASN1_VALUE_NOT_FOUND;
+
+- switch (type_field (node->type))
++ if (etype)
++ *etype = type;
++ switch (type)
+ {
+ case TYPE_NULL:
+ PUT_STR_VALUE (value, value_size, "NULL");
+@@ -772,9 +860,10 @@
+ if ((isdigit (p->value[0])) || (p->value[0] == '-')
+ || (p->value[0] == '+'))
+ {
+- if (_asn1_convert_integer
+- (p->value, value, value_size, len) != ASN1_SUCCESS)
+- return ASN1_MEM_ERROR;
++ result = _asn1_convert_integer
++ (p->value, value, value_size, len);
++ if (result != ASN1_SUCCESS)
++ return result;
+ }
+ else
+ { /* is an identifier like v1 */
+@@ -783,12 +872,13 @@
+ {
+ if (type_field (p2->type) == TYPE_CONSTANT)
+ {
+- if ((p2->name) && (!strcmp (p2->name, p->value)))
++ if (!_asn1_strcmp (p2->name, p->value))
+ {
+- if (_asn1_convert_integer
++ result = _asn1_convert_integer
+ (p2->value, value, value_size,
+- len) != ASN1_SUCCESS)
+- return ASN1_MEM_ERROR;
++ len);
++ if (result != ASN1_SUCCESS)
++ return result;
+ break;
+ }
+ }
+@@ -799,16 +889,19 @@
+ else
+ {
+ len2 = -1;
+- if (asn1_get_octet_der
++ result = asn1_get_octet_der
+ (node->value, node->value_len, &len2, value, value_size,
+- len) != ASN1_SUCCESS)
+- return ASN1_MEM_ERROR;
++ len);
++ if (result != ASN1_SUCCESS)
++ return result;
+ }
+ break;
+ case TYPE_OBJECT_ID:
+ if (node->type & CONST_ASSIGN)
+ {
+- value[0] = 0;
++ *len = 0;
++ if (value)
++ value[0] = 0;
+ p = node->down;
+ while (p)
+ {
+@@ -822,7 +915,7 @@
+ }
+ p = p->right;
+ }
+- *len = strlen (value) + 1;
++ (*len)++;
+ }
+ else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+ {
+@@ -836,29 +929,34 @@
+ PUT_STR_VALUE (value, value_size, node->value);
+ }
+ break;
+- case TYPE_TIME:
+- PUT_STR_VALUE (value, value_size, node->value);
++ case TYPE_GENERALIZED_TIME:
++ case TYPE_UTC_TIME:
++ PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len);
+ break;
+ case TYPE_OCTET_STRING:
+- len2 = -1;
+- if (asn1_get_octet_der
+- (node->value, node->value_len, &len2, value, value_size,
+- len) != ASN1_SUCCESS)
+- return ASN1_MEM_ERROR;
+- break;
+ case TYPE_GENERALSTRING:
++ case TYPE_NUMERIC_STRING:
++ case TYPE_IA5_STRING:
++ case TYPE_TELETEX_STRING:
++ case TYPE_PRINTABLE_STRING:
++ case TYPE_UNIVERSAL_STRING:
++ case TYPE_BMP_STRING:
++ case TYPE_UTF8_STRING:
++ case TYPE_VISIBLE_STRING:
+ len2 = -1;
+- if (asn1_get_octet_der
++ result = asn1_get_octet_der
+ (node->value, node->value_len, &len2, value, value_size,
+- len) != ASN1_SUCCESS)
+- return ASN1_MEM_ERROR;
++ len);
++ if (result != ASN1_SUCCESS)
++ return result;
+ break;
+ case TYPE_BIT_STRING:
+ len2 = -1;
+- if (asn1_get_bit_der
++ result = asn1_get_bit_der
+ (node->value, node->value_len, &len2, value, value_size,
+- len) != ASN1_SUCCESS)
+- return ASN1_MEM_ERROR;
++ len);
++ if (result != ASN1_SUCCESS)
++ return result;
+ break;
+ case TYPE_CHOICE:
+ PUT_STR_VALUE (value, value_size, node->down->name);
+@@ -890,13 +988,10 @@
+ * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or
+ * %ASN1_CLASS_CONTEXT_SPECIFIC.
+ *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Set value OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ * @name is not a valid element.
+ **/
+-asn1_retCode
++int
+ asn1_read_tag (ASN1_TYPE root, const char *name, int *tagValue,
+ int *classValue)
+ {
+@@ -927,7 +1022,7 @@
+
+ if (pTag)
+ {
+- *tagValue = strtoul (pTag->value, NULL, 10);
++ *tagValue = _asn1_strtoul (pTag->value, NULL, 10);
+
+ if (pTag->type & CONST_APPLICATION)
+ *classValue = ASN1_CLASS_APPLICATION;
+@@ -940,60 +1035,44 @@
+ }
+ else
+ {
++ unsigned type = type_field (node->type);
+ *classValue = ASN1_CLASS_UNIVERSAL;
+
+- switch (type_field (node->type))
++ switch (type)
+ {
+- case TYPE_NULL:
+- *tagValue = ASN1_TAG_NULL;
+- break;
+- case TYPE_BOOLEAN:
+- *tagValue = ASN1_TAG_BOOLEAN;
+- break;
+- case TYPE_INTEGER:
+- *tagValue = ASN1_TAG_INTEGER;
+- break;
+- case TYPE_ENUMERATED:
+- *tagValue = ASN1_TAG_ENUMERATED;
+- break;
+- case TYPE_OBJECT_ID:
+- *tagValue = ASN1_TAG_OBJECT_ID;
+- break;
+- case TYPE_TIME:
+- if (node->type & CONST_UTC)
+- {
+- *tagValue = ASN1_TAG_UTCTime;
+- }
+- else
+- *tagValue = ASN1_TAG_GENERALIZEDTime;
+- break;
+- case TYPE_OCTET_STRING:
+- *tagValue = ASN1_TAG_OCTET_STRING;
+- break;
+- case TYPE_GENERALSTRING:
+- *tagValue = ASN1_TAG_GENERALSTRING;
+- break;
+- case TYPE_BIT_STRING:
+- *tagValue = ASN1_TAG_BIT_STRING;
+- break;
+- case TYPE_SEQUENCE:
+- case TYPE_SEQUENCE_OF:
+- *tagValue = ASN1_TAG_SEQUENCE;
+- break;
+- case TYPE_SET:
+- case TYPE_SET_OF:
+- *tagValue = ASN1_TAG_SET;
++ CASE_HANDLED_ETYPES:
++ *tagValue = _asn1_tags[type].tag;
+ break;
+ case TYPE_TAG:
+ case TYPE_CHOICE:
+ case TYPE_ANY:
++ *tagValue = -1;
+ break;
+ default:
+ break;
+ }
+ }
+
+-
+ return ASN1_SUCCESS;
++}
+
++/**
++ * asn1_read_node_value:
++ * @node: pointer to a node.
++ * @data: a point to a asn1_data_node_st
++ *
++ * Returns the value a data node inside a ASN1_TYPE structure.
++ * The data returned should be handled as constant values.
++ *
++ * Returns: %ASN1_SUCCESS if the node exists.
++ **/
++int
++asn1_read_node_value (ASN1_TYPE node, asn1_data_node_st * data)
++{
++ data->name = node->name;
++ data->value = node->value;
++ data->value_len = node->value_len;
++ data->type = type_field (node->type);
++
++ return ASN1_SUCCESS;
+ }
+--- ORIGINAL/./lib/structure.h 2015-07-14 18:28:22.929332224 -0700
++++ libtasn1-2.8/./lib/structure.h 2015-07-14 18:45:02.727873654 -0700
+@@ -29,13 +29,12 @@
+ #ifndef _STRUCTURE_H
+ #define _STRUCTURE_H
+
+-asn1_retCode _asn1_create_static_structure (ASN1_TYPE pointer,
+- char *output_file_name,
+- char *vector_name);
++int _asn1_create_static_structure (ASN1_TYPE pointer,
++ char *output_file_name, char *vector_name);
+
+ ASN1_TYPE _asn1_copy_structure3 (ASN1_TYPE source_node);
+
+-ASN1_TYPE _asn1_add_node_only (unsigned int type);
++ASN1_TYPE _asn1_add_single_node (unsigned int type);
+
+ ASN1_TYPE _asn1_find_left (ASN1_TYPE node);
+