union_type.c 6.11 KB
Newer Older
Cedric Roux's avatar
 
Cedric Roux committed
1
2
3
4
5
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

6
7
#define G_LOG_DOMAIN ("PARSER")

Cedric Roux's avatar
 
Cedric Roux committed
8
9
#include "rc.h"

10
#include "enum_value_type.h"
Cedric Roux's avatar
 
Cedric Roux committed
11
12
13
14
15
#include "union_type.h"
#include "../libresolver/locate_root.h"
#include "ui_interface.h"

/* There is only one special case of union which is associated to an index: the message id */
Cedric Roux's avatar
Cedric Roux committed
16
int union_msg_dissect_from_buffer(
winckel's avatar
winckel committed
17
18
    types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data,
    buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line)
Cedric Roux's avatar
Cedric Roux committed
19
{
Cedric Roux's avatar
 
Cedric Roux committed
20
    uint32_t message_id;
winckel's avatar
winckel committed
21
22
    int length = 0;
    char cbuf[200];
Cedric Roux's avatar
 
Cedric Roux committed
23
24
25
26
27

    DISPLAY_PARSE_INFO("union_msg", type->name, offset, parent_offset);

    CHECK_FCT(get_message_id(type->head, buffer, &message_id));

winckel's avatar
winckel committed
28
29
30
31
32
33
34
35
36
    if (type->name) {
        DISPLAY_TYPE("Uni");

        length = sprintf(cbuf, "%s |", type->name);
        DISPLAY_BRACE(length += sprintf(&cbuf[length], " {"););
        length += sprintf(&cbuf[length], "\n");
        ui_set_signal_text_cb(user_data, cbuf, length);
    }

Cedric Roux's avatar
 
Cedric Roux committed
37
    if (type->members_child[message_id] != NULL)
Cedric Roux's avatar
Cedric Roux committed
38
39
        type->members_child[message_id]->type_dissect_from_buffer(
            type->members_child[message_id], ui_set_signal_text_cb, user_data,
winckel's avatar
winckel committed
40
41
42
43
44
45
46
47
48
            buffer, offset, parent_offset, type->name == NULL ? indent : indent + DISPLAY_TAB_SIZE, TRUE);

    DISPLAY_BRACE(
            if (type->name) {
                DISPLAY_TYPE("Uni");

                INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "};\n"));
                ui_set_signal_text_cb(user_data, cbuf, length);
            });
Cedric Roux's avatar
 
Cedric Roux committed
49
50
51
52

    return RC_OK;
}

Cedric Roux's avatar
Cedric Roux committed
53
int union_dissect_from_buffer(
winckel's avatar
winckel committed
54
55
    types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data,
    buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line)
Cedric Roux's avatar
Cedric Roux committed
56
{
Cedric Roux's avatar
 
Cedric Roux committed
57
    int length = 0;
58
    char cbuf[50 + (type->name ? strlen (type->name) : 0)];
winckel's avatar
winckel committed
59
    char *name;
60
    int union_child = 0;
Cedric Roux's avatar
 
Cedric Roux committed
61
62
63

    DISPLAY_PARSE_INFO("union", type->name, offset, parent_offset);

64
    memset (cbuf, 0, sizeof(cbuf));
Cedric Roux's avatar
 
Cedric Roux committed
65
66
67
68

//    CHECK_FCT(buffer_has_enouch_data(buffer, offset + parent_offset, type->size / 8));

    if (type->name) {
winckel's avatar
winckel committed
69
70
71
72
73
74
        name = type->name;
    }
    else {
        name = "_anonymous_";
    }
    if (new_line) {
Cedric Roux's avatar
 
Cedric Roux committed
75
        DISPLAY_TYPE("Uni");
winckel's avatar
winckel committed
76
77
78
79
80
    }
    INDENTED_STRING(cbuf, new_line ? indent : 0, length = sprintf(cbuf, "%s |", name));
    DISPLAY_BRACE(length += sprintf(&cbuf[length], " {"););
    length += sprintf(&cbuf[length], "\n");
    ui_set_signal_text_cb(user_data, cbuf, length);
81

winckel's avatar
winckel committed
82
    if (type->name) {
83
84
85
86
87
88
89
90
91
92
93
94
95
96
        if (type->parent != NULL)
        {
            if ((type->parent->name != NULL) && (strcmp(type->parent->name, "choice") == 0))
            {
                /* ASN1 union */

                if ((last_enum_value > 0) && (last_enum_value <= type->nb_members))
                {
                    union_child = last_enum_value - 1;

                    g_debug("ASN1 union \"%s\' detected, use member %d", type->name, union_child);
                }
            }
        }
Cedric Roux's avatar
 
Cedric Roux committed
97
98
99
100
    }


    /* Only dissect the first field present in unions */
101
102
103
    if (type->members_child[union_child] != NULL)
        type->members_child[union_child]->type_dissect_from_buffer(
            type->members_child[union_child], ui_set_signal_text_cb, user_data, buffer,
winckel's avatar
winckel committed
104
            offset, parent_offset, indent + DISPLAY_TAB_SIZE, TRUE);
Cedric Roux's avatar
 
Cedric Roux committed
105

winckel's avatar
winckel committed
106
107
108
    DISPLAY_BRACE(
            DISPLAY_TYPE("Uni");
            INDENTED_STRING(cbuf, indent, sprintf(cbuf, "};\n"));
Cedric Roux's avatar
 
Cedric Roux committed
109

winckel's avatar
winckel committed
110
            length = strlen (cbuf);
Cedric Roux's avatar
 
Cedric Roux committed
111

winckel's avatar
winckel committed
112
            ui_set_signal_text_cb(user_data, cbuf, length););
Cedric Roux's avatar
 
Cedric Roux committed
113
114
115
116

    return 0;
}

winckel's avatar
winckel committed
117
int union_type_file_print(types_t *type, int indent, FILE *file) {
Cedric Roux's avatar
 
Cedric Roux committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    int i;
    if (type == NULL)
        return -1;
    INDENTED(file, indent, fprintf(file, "<Union>\n"));
    INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name));
    INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id));
    INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size));
    INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align));
    INDENTED(file, indent+4, fprintf(file, "Artificial .: %d\n", type->artificial));
    INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file));
    INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line));
    INDENTED(file, indent+4, fprintf(file, "Members ....: %s\n", type->members));
    INDENTED(file, indent+4, fprintf(file, "Mangled ....: %s\n", type->mangled));
    INDENTED(file, indent+4, fprintf(file, "Demangled ..: %s\n", type->demangled));
    if (type->file_ref != NULL)
        type->file_ref->type_file_print (type->file_ref, indent + 4, file);
    for (i = 0; i < type->nb_members; i++) {
        if (type->members_child[i] != NULL)
            type->members_child[i]->type_file_print (type->members_child[i], indent + 4, file);
    }
    INDENTED(file, indent, fprintf(file, "</Union>\n"));

    return 0;
}

winckel's avatar
winckel committed
143
int union_type_hr_display(types_t *type, int indent) {
Cedric Roux's avatar
 
Cedric Roux committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    int i;
    if (type == NULL)
        return -1;
    INDENTED(stdout, indent, printf("<Union>\n"));
    INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name));
    INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id));
    INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size));
    INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align));
    INDENTED(stdout, indent+4, printf("Artificial .: %d\n", type->artificial));
    INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file));
    INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line));
    INDENTED(stdout, indent+4, printf("Members ....: %s\n", type->members));
    INDENTED(stdout, indent+4, printf("Mangled ....: %s\n", type->mangled));
    INDENTED(stdout, indent+4, printf("Demangled ..: %s\n", type->demangled));
    if (type->file_ref != NULL)
        type->file_ref->type_hr_display (type->file_ref, indent + 4);
    for (i = 0; i < type->nb_members; i++) {
        if (type->members_child[i] != NULL)
            type->members_child[i]->type_hr_display (type->members_child[i], indent + 4);
    }
    INDENTED(stdout, indent, printf("</Union>\n"));

    return 0;
}