Branch data Line data Source code
1 : : #ifndef CATALOG_H
2 : : #define CATALOG_H
3 : :
4 : : #include <stdlib.h>
5 : : #include "symbols.h"
6 : :
7 : : /* Helper to build more intuitive schema data with fully qualified names. */
8 : :
9 : :
10 : : typedef struct entry entry_t;
11 : : typedef entry_t object_entry_t;
12 : : typedef entry_t enum_entry_t;
13 : : typedef struct scope_entry scope_entry_t;
14 : :
15 : : struct entry {
16 : : fb_compound_type_t *ct;
17 : : char *name;
18 : : };
19 : :
20 : : struct scope_entry {
21 : : fb_scope_t *scope;
22 : : char *name;
23 : : };
24 : :
25 : : typedef struct catalog catalog_t;
26 : :
27 : : struct catalog {
28 : : int qualify_names;
29 : : int nobjects;
30 : : int nenums;
31 : : size_t name_table_size;
32 : : object_entry_t *objects;
33 : : enum_entry_t *enums;
34 : : char *name_table;
35 : : object_entry_t *next_object;
36 : : enum_entry_t *next_enum;
37 : : char *next_name;
38 : : fb_schema_t *schema;
39 : : };
40 : :
41 : 69 : static void count_symbol(void *context, fb_symbol_t *sym)
42 : : {
43 : : catalog_t *catalog = context;
44 : : fb_ref_t *scope_name;
45 : : size_t n = 0;
46 : : fb_compound_type_t *ct;
47 : :
48 [ + + ]: 69 : if (!(ct = get_compound_if_visible(catalog->schema, sym))) {
49 : : return;
50 : : }
51 : :
52 : : /*
53 : : * Find out how much space the name requires. We must store each
54 : : * name in full for sorting because comparing a variable number of
55 : : * parent scope names is otherwise tricky.
56 : : */
57 [ + - ]: 41 : if (catalog->qualify_names) {
58 : 41 : scope_name = ct->scope->name;
59 [ + + ]: 119 : while (scope_name) {
60 : : /* + 1 for '.'. */
61 : 78 : n += (size_t)scope_name->ident->len + 1;
62 : 78 : scope_name = scope_name->link;
63 : : }
64 : : }
65 : : /* + 1 for '\0'. */
66 : 41 : n += (size_t)sym->ident->len + 1;
67 : 41 : catalog->name_table_size += n;
68 : :
69 [ + + - ]: 41 : switch (sym->kind) {
70 : : case fb_is_struct:
71 : : case fb_is_table:
72 : 29 : ++catalog->nobjects;
73 : 29 : break;
74 : : case fb_is_union:
75 : : case fb_is_enum:
76 : 12 : ++catalog->nenums;
77 : 12 : break;
78 : : default: return;
79 : : }
80 : : }
81 : :
82 : 69 : static void install_symbol(void *context, fb_symbol_t *sym)
83 : : {
84 : : catalog_t *catalog = context;
85 : : fb_ref_t *scope_name;
86 : : int n = 0;
87 : : char *s, *name;
88 : : fb_compound_type_t *ct;
89 : :
90 [ + + ]: 69 : if (!(ct = get_compound_if_visible(catalog->schema, sym))) {
91 : : return;
92 : : }
93 : :
94 : 41 : s = catalog->next_name;
95 : : name = s;
96 [ + - ]: 41 : if (catalog->qualify_names) {
97 : 41 : scope_name = ct->scope->name;
98 [ + + ]: 119 : while (scope_name) {
99 : 78 : n = scope_name->ident->len;
100 : 78 : memcpy(s, scope_name->ident->text, n);
101 : 78 : s += n;
102 : 78 : *s++ = '.';
103 : 78 : scope_name = scope_name->link;
104 : : }
105 : : }
106 : 41 : n = sym->ident->len;
107 : 41 : memcpy(s, sym->ident->text, n);
108 : 41 : s += n;
109 : 41 : *s++ = '\0';
110 : 41 : catalog->next_name = s;
111 : :
112 [ + + - ]: 41 : switch (sym->kind) {
113 : : case fb_is_struct:
114 : : case fb_is_table:
115 : 29 : catalog->next_object->ct = (fb_compound_type_t *)sym;
116 : 29 : catalog->next_object->name = name;
117 : 29 : catalog->next_object++;
118 : 29 : break;
119 : : case fb_is_union:
120 : : case fb_is_enum:
121 : 12 : catalog->next_enum->ct = (fb_compound_type_t *)sym;
122 : 12 : catalog->next_enum->name = name;
123 : 12 : catalog->next_enum++;
124 : 12 : break;
125 : : default: break;
126 : : }
127 : : }
128 : :
129 : 14 : static void count_symbols(void *context, fb_scope_t *scope)
130 : : {
131 : 14 : fb_symbol_table_visit(&scope->symbol_index, count_symbol, context);
132 : 14 : }
133 : :
134 : 14 : static void install_symbols(void *context, fb_scope_t *scope)
135 : : {
136 : 14 : fb_symbol_table_visit(&scope->symbol_index, install_symbol, context);
137 : 14 : }
138 : :
139 : 72 : static int compare_entries(const void *x, const void *y)
140 : : {
141 : 72 : return strcmp(((const entry_t *)x)->name, ((const entry_t *)y)->name);
142 : : }
143 : :
144 : 10 : static void sort_entries(entry_t *entries, int count)
145 : : {
146 : : int i;
147 : :
148 : 10 : qsort(entries, count, sizeof(entries[0]), compare_entries);
149 : :
150 [ + + ]: 51 : for (i = 0; i < count; ++i) {
151 : 41 : entries[i].ct->export_index = (size_t)i;
152 : : }
153 : 10 : }
154 : :
155 : 5 : static void clear_catalog(catalog_t *catalog)
156 : : {
157 [ + - ]: 5 : if (catalog->objects) {
158 : 5 : free(catalog->objects);
159 : : }
160 [ + - ]: 5 : if (catalog->enums) {
161 : 5 : free(catalog->enums);
162 : : }
163 [ + - ]: 5 : if (catalog->name_table) {
164 : 5 : free(catalog->name_table);
165 : : }
166 : 5 : memset(catalog, 0, sizeof(*catalog));
167 : 5 : }
168 : :
169 : 5 : static int build_catalog(catalog_t *catalog, fb_schema_t *schema, int qualify_names, fb_scope_table_t *index)
170 : : {
171 : 5 : memset(catalog, 0, sizeof(*catalog));
172 : 5 : catalog->qualify_names = qualify_names;
173 : 5 : catalog->schema = schema;
174 : :
175 : : /* Build support datastructures before export. */
176 : 5 : fb_scope_table_visit(index, count_symbols, catalog);
177 : 5 : catalog->objects = calloc(catalog->nobjects, sizeof(catalog->objects[0]));
178 : 5 : catalog->enums = calloc(catalog->nenums, sizeof(catalog->enums[0]));
179 : 5 : catalog->name_table = malloc(catalog->name_table_size);
180 : 5 : catalog->next_object = catalog->objects;
181 : 5 : catalog->next_enum = catalog->enums;
182 : 5 : catalog->next_name = catalog->name_table;
183 [ - + ][ # # ]: 5 : if ((!catalog->objects && catalog->nobjects > 0) ||
[ - + ]
184 [ # # ][ - + ]: 5 : (!catalog->enums && catalog->nenums > 0) ||
185 [ # # ]: 0 : (!catalog->name_table && catalog->name_table_size > 0)) {
186 : 0 : clear_catalog(catalog);
187 : 0 : return -1;
188 : : }
189 : 5 : fb_scope_table_visit(index, install_symbols, catalog);
190 : : /* Presort objects and enums because the sorted index is required in Type tables. */
191 : 5 : sort_entries(catalog->objects, catalog->nobjects);
192 : 5 : sort_entries(catalog->enums, catalog->nenums);
193 : 5 : return 0;
194 : : }
195 : :
196 : : #endif /* CATALOG_H */
|