123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #ifndef SPEC_SYNTAX__H
- #define SPEC_SYNTAX__H
- /**
- * Copyright (C) 2011 Anders Sundman <anders@4zm.org>
- *
- * 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
|