-
Notifications
You must be signed in to change notification settings - Fork 36
/
spec_syntax.h
242 lines (203 loc) · 7.41 KB
/
spec_syntax.h
1
2
3
4
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#ifndef SPEC_SYNTAX__H
#define SPEC_SYNTAX__H
/**
* Copyright (C) 2011 Anders Sundman <[email protected]>
*
* This file is part of mfterm.
*
* mfterm 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.
*
* mfterm 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 mfterm. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
typedef enum {
COMPOSITE_TYPE,
BYTE_TYPE,
BIT_TYPE,
} type_category_t;
typedef enum {
PARTIAL_DECL,
COMPLETE_DECL,
} type_decl_status_t;
typedef struct type_t type_t;
typedef struct field_t field_t;
typedef struct field_list_t field_list_t;
typedef struct composite_type_extras_t composite_type_extras_t;
typedef struct type_table_t type_table_t;
typedef struct instance_t instance_t;
typedef struct instance_list_t instance_list_t;
// Parse the input file and set up type_root and instance_root.
// Return 0 on success.
int spec_import(FILE* input);
/**
* A struct representing a data type in the specification
* language. There are two primitive types, Bit and Bytte. All other
* types are user defined and use the composite_extras field to
* express the type details.
*
* The primitive types are allocated statically (constants), while all
* the composite types are allocated dynamically.
*/
struct type_t {
type_category_t type_category;
composite_type_extras_t* composite_extras;
};
// The primitive type instances
extern type_t byte_type;
extern type_t bit_type;
/**
* A composite type is made up of an ordered list of fields. A field
* is a named use of another type as an array. A field array of length
* 1 can be treated without the array syntax in the language; but is
* represented like all other fields.
*/
struct field_t {
char* name; // Field name
type_t* type;
size_t length;
};
/**
* Type representing the ordered list of fields in a composite type.
*/
struct field_list_t {
field_t* field;
field_list_t* next_;
};
/**
* This structure represents the content of a user defined type. It
* holds the name and the fields of the type.
*
* The type also has a flag to indicate if it has been fully
* declared. The specification language allows the use of types before
* they have been declared. Once the complete specification has been
* parsed, all types must be declared.
*/
struct composite_type_extras_t {
char* name; // Type name
type_decl_status_t decl_status;
field_list_t* fields; // All fields of the type or NULL.
};
// Allocate and return a composite type instance. The type will assume
// ownership of the heap allocated name.
type_t* make_composite_type(char* name);
// Free a composite type. This function will also free it's fields.
void free_composite_type(type_t* t);
// Allocate a new field with the given parameters. Anonymous '-'
// filler fields use NULL as name. The field will assume ownership of
// the heap allocated name.
field_t* make_field(char* name, type_t* type, size_t length);
// Free the memory used by a field.
void free_field(field_t* field);
// Add a field to an existing list of fields. The order of fields is
// significant and this function will append the field to the end of
// the field_list.
field_list_t* append_field(field_list_t* field_list, field_t* field);
// Search the field list for a field with the given name
field_t* get_field(field_list_t* field_list, const char* name);
/**
* A 'table' of all the types in the language. This is part of the
* output from the parsing process. The table is actually a list and
* operations are typically O(n^2); but since there will probably
* never be more than 50 types, this should be ok.
*/
struct type_table_t {
type_t* type;
type_table_t* next_;
};
// The global instance of the type table. If there isn't any, the
// variable will be NULL. All the type table operations (tt_) operate
// on this global variable.
extern type_table_t* type_table;
// The root type of the type hierarchy
extern type_t* type_root;
// Clear the type table - freeing the memory used by the table and by
// all the types.
void tt_clear();
// Add a type to the type table.
type_t* tt_add_type(type_t* t);
// Search the type table for a type with the given name. The first
// type found will be returned. If no type is found, NULL is returned.
type_t* tt_get_type(const char* type_name);
// Check if there are any partially declared types in the type
// table. Return a pointer to the first incomplete type or NULL if
// none exists.
type_t* tt_contains_partial_types();
/**
* Type representing instances of types in the spec language. The same
* type can be instantiated several times in different spec types and
* fields. The instances map agains type fields and thus contains a
* length field.
*
* The size field is inclusive of the instance and all it's child
* instances. The bit size field will be < 8; larger bit fields in the
* type spec will be included in the byte field.
*/
struct instance_t {
size_t offset_bytes;
size_t offset_bits;
size_t size_bytes;
size_t size_bits;
field_t* field;
instance_list_t* fields;
};
/**
* Type representing the ordered list of instance fields in a
* composite type instance.
*/
struct instance_list_t {
instance_t* instance;
instance_list_t* next_;
};
// The global variable representing the root instance; it is an
// instanciation of the '.' type.
extern instance_t* instance_root;
// Create an instance tree matching the type tree starting at
// root_type. The global instance tree is constructed with root_type '.'.
instance_t* make_instance_tree(type_t* root_type);
// Clear the global instance tree. Free it and set instance_tree NULL
void clear_instance_tree();
// Print a representation of the instance hierarchy
void print_instance_tree();
/**
* Get the child instance with a given name. Only look to children,
* not grand children. If no child with the given name exists, return
* null.
*/
instance_t* get_instance_child(instance_t* inst, const char* name);
/**
* Like get_instance_child(inst, name), but name does not have to be
* null terminated. Instead the length of the name string is given by
* the last argument.
*/
instance_t* get_instance_child_n(instance_t* inst, const char* name, size_t nlen);
/**
* Parse a specification path of the form '.fu.bar.baz' and return the
* instance pointed to by baz. In case the path doesn't point to a
* loaded instance, return NULL. */
instance_t* parse_spec_path(const char* path);
/**
* Parse the path to produce a parent section and an instance that
* points to the head of the parent.
*
* The format is .fu.bar.ba(z). Where .fu.bar.ba is the path, fu, bar
* and baz are nested fields. The function should return parent_end
* pointing into path to the point after the last '.', i.e. to the 'b'
* in the last 'ba'. parent_inst will point to bar.
*
* The function returns 0 on success.
*/
int parse_partial_spec_path(const char* path,
const char** parent_end,
instance_t** parent_inst);
// Return the number of fields the instance has. 0 if inst is NULL.
int instance_fields_count(instance_t* inst);
#endif