ASN.1: Fix handling of CHOICE in ASN.1 compiler
[firefly-linux-kernel-4.4.55.git] / scripts / asn1_compiler.c
index 7750e9c31483b99bdf467db98757ca16e7152847..e87359cd23c0a8b457510ddb90d62f5ba8bb6ef5 100644 (file)
@@ -666,7 +666,7 @@ struct element {
        unsigned        flags;
 #define ELEMENT_IMPLICIT       0x0001
 #define ELEMENT_EXPLICIT       0x0002
-#define ELEMENT_MARKED         0x0004
+#define ELEMENT_TAG_SPECIFIED  0x0004
 #define ELEMENT_RENDERED       0x0008
 #define ELEMENT_SKIPPABLE      0x0010
 #define ELEMENT_CONDITIONAL    0x0020
@@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
 
                element->tag &= ~0x1f;
                element->tag |= strtoul(cursor->value, &p, 10);
+               element->flags |= ELEMENT_TAG_SPECIFIED;
                if (p - cursor->value != cursor->size)
                        abort();
                cursor++;
@@ -1376,7 +1377,7 @@ static void render_out_of_line_list(FILE *out)
  */
 static void render_element(FILE *out, struct element *e, struct element *tag)
 {
-       struct element *ec;
+       struct element *ec, *x;
        const char *cond, *act;
        int entry, skippable = 0, outofline = 0;
 
@@ -1435,15 +1436,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
                break;
        }
 
-       if (e->name)
+       x = tag ?: e;
+       if (x->name)
                render_more(out, "\t\t// %*.*s",
-                           (int)e->name->size, (int)e->name->size,
-                           e->name->value);
+                           (int)x->name->size, (int)x->name->size,
+                           x->name->value);
        render_more(out, "\n");
 
        /* Render the tag */
-       if (!tag)
+       if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED))
                tag = e;
+
        if (tag->class == ASN1_UNIV &&
            tag->tag != 14 &&
            tag->tag != 15 &&
@@ -1539,7 +1542,7 @@ dont_render_tag:
 
        case CHOICE:
                for (ec = e->children; ec; ec = ec->next)
-                       render_element(out, ec, NULL);
+                       render_element(out, ec, ec);
                if (!skippable)
                        render_opcode(out, "ASN1_OP_COND_FAIL,\n");
                if (e->action)