mirror of
https://github.com/doldecomp/melee.git
synced 2026-11-10 01:51:41 -10:00
194 lines
6.5 KiB
C
194 lines
6.5 KiB
C
/**
|
|
* @file
|
|
* Compiled native readers and archive roots generated by Rust.
|
|
*
|
|
* DatType supplies storage sizes, identity and callbacks. Field layouts,
|
|
* annotations and expressions are compiled into the callbacks; this
|
|
* interface contains no DWARF members or expression operator tree.
|
|
*/
|
|
|
|
#ifndef DAT_SCHEMA_H
|
|
#define DAT_SCHEMA_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/// No type and no name: index 0 of DatSchema::types and DatSchema::names.
|
|
#define DAT_NONE 0
|
|
|
|
typedef enum DatKind {
|
|
/// `void`, functions, and types without a definition: nothing to read.
|
|
DAT_KIND_VOID,
|
|
/// Integers, characters, booleans and enumerations.
|
|
DAT_KIND_INT,
|
|
DAT_KIND_FLOAT,
|
|
DAT_KIND_POINTER,
|
|
DAT_KIND_STRUCT,
|
|
DAT_KIND_UNION,
|
|
DAT_KIND_ARRAY,
|
|
} DatKind;
|
|
|
|
struct DatArchive;
|
|
struct DatContext;
|
|
struct DatParent;
|
|
struct DatScope;
|
|
struct DatVerify;
|
|
/// A compiled expression. Rust emits its evaluator as ordinary C.
|
|
typedef struct DatExpr {
|
|
/// Return 1 with a value, or 0 for unresolved/undefined operations.
|
|
/// Arithmetic wraps at 64 bits. Depth counts macro expansion only.
|
|
int (*evaluate)(const struct DatArchive*, const struct DatContext*,
|
|
unsigned, uint64_t*);
|
|
} DatExpr;
|
|
|
|
/// Names bound by a loader or DAT_BIND. Generated readers own their storage.
|
|
typedef struct DatScope {
|
|
int32_t name;
|
|
uint64_t value;
|
|
const struct DatScope* outer;
|
|
} DatScope;
|
|
|
|
/// An element's compiled binding function, using caller-provided storage.
|
|
typedef const DatScope* (*DatBinding)(struct DatArchive*, const DatScope*,
|
|
const struct DatParent*, uint64_t,
|
|
DatScope*);
|
|
|
|
/// Command lengths for `DAT_SCRIPT` and `DAT_BYTE_SCRIPT`.
|
|
typedef struct DatScript {
|
|
/// Word-script lengths in words, starting at opcode 10.
|
|
const uint8_t* table;
|
|
uint32_t table_size;
|
|
/// Length expression, using the command's first word or byte as
|
|
/// `_command`.
|
|
const DatExpr* length;
|
|
/// Set for byte scripts: lengths are in bytes and all commands use
|
|
/// `length`.
|
|
uint8_t bytes;
|
|
} DatScript;
|
|
|
|
/// Generated storage/read callbacks include no-ops for inapplicable
|
|
/// operations. Verification is test-only. Layout changes belong in Rust
|
|
/// codegen.
|
|
typedef struct DatType {
|
|
/// Apply this type's annotations and read at the archive offset. Native
|
|
/// may be NULL when only traversing; parent supplies union context.
|
|
void (*read)(struct DatArchive*, uint32_t, void*, const struct DatParent*);
|
|
/// Convert the resolved plain layout into non-NULL native storage.
|
|
void (*convert)(struct DatArchive*, uint32_t, void*);
|
|
/// Check relocation compatibility for the resolved layout.
|
|
int (*fits)(const struct DatArchive*, uint32_t);
|
|
/// Resolve a field name at a record's archive base; return 0 if absent.
|
|
int (*field)(const struct DatArchive*, uint32_t, int32_t, uint64_t*);
|
|
/// Search union members' fields in declaration order, for conditions.
|
|
int (*union_field)(const struct DatArchive*, uint32_t, int32_t, uint64_t*);
|
|
/// Resolved native storage size, including a bounded flexible tail.
|
|
size_t (*allocation_size)(struct DatArchive*, uint32_t);
|
|
#ifdef DAT_NATIVE_TESTING
|
|
/// Compare the resolved native layout with archive bytes.
|
|
void (*verify)(struct DatVerify*, uint32_t, const void*, int);
|
|
#endif
|
|
uint8_t conditioned;
|
|
/// The type's name, for traces.
|
|
const char* name;
|
|
/// The generator's id for it, which traces print.
|
|
uint32_t id;
|
|
uint8_t kind;
|
|
#ifdef DAT_NATIVE_TESTING
|
|
/// Readback widening and coverage exclusion.
|
|
uint8_t is_signed, raw;
|
|
#endif
|
|
/// Precomputed through typedefs/qualifiers: keep serialized bytes.
|
|
uint8_t opaque;
|
|
/// Whether any part of it is a pointer, not looking through pointers.
|
|
uint8_t has_pointers;
|
|
/// A struct whose last member is a `DAT_EXTENT` array.
|
|
uint8_t has_extent;
|
|
/// An array with a dimension without a bound.
|
|
uint8_t unbounded;
|
|
/// Its size in the archive.
|
|
uint32_t size;
|
|
/// Its size natively; 0 where the generator couldn't spell it.
|
|
uint32_t native_size;
|
|
/// Pointers: the type pointed to, `DAT_NONE` for `void`. Typedefs and
|
|
/// qualifiers: the type named. Arrays: the element type.
|
|
int32_t target;
|
|
/// Through typedefs and qualifiers: the type it is.
|
|
int32_t resolved;
|
|
/// Arrays: the number of elements, every dimension's together; a
|
|
/// dimension without a bound counts as one.
|
|
uint32_t count;
|
|
} DatType;
|
|
|
|
typedef enum DatCount {
|
|
DAT_COUNT_ONE,
|
|
DAT_COUNT_EXACTLY,
|
|
/// As many as fit before the next public symbol or pointer target.
|
|
DAT_COUNT_EXTENT,
|
|
/// Up to and including the first element whose first word (or whole
|
|
/// value, if smaller) is `n` and not a relocated pointer.
|
|
DAT_COUNT_TERMINATED,
|
|
} DatCount;
|
|
|
|
/// A root of an archive: a public symbol by name, or an alias at an
|
|
/// address.
|
|
typedef struct DatRoot {
|
|
const char* name;
|
|
/// For an alias: where it is in the first archive of the file.
|
|
uint8_t alias;
|
|
uint32_t address;
|
|
int32_t type;
|
|
uint8_t count_kind;
|
|
uint64_t count;
|
|
/// A command script nothing points to, for an alias; `NULL` otherwise.
|
|
const DatScript* script;
|
|
const DatScope* env;
|
|
} DatRoot;
|
|
|
|
/// The roots of one archive of a file, as `melee-dat` types them.
|
|
typedef struct DatFileRoots {
|
|
/// The file, relative to the game's files, e.g. `PlCo.dat`.
|
|
const char* file;
|
|
/// Which archive of the file, for files that pack several.
|
|
uint32_t archive;
|
|
/// Public symbols, then aliases.
|
|
const DatRoot* roots;
|
|
uint32_t nroots;
|
|
} DatFileRoots;
|
|
|
|
/// The files of a module, the first two letters of their names: `Pl`, `Gr`.
|
|
typedef struct DatModule {
|
|
const DatFileRoots* files;
|
|
uint32_t nfiles;
|
|
} DatModule;
|
|
|
|
typedef struct DatSchema {
|
|
/// By index; the first, `DAT_NONE`, is `NULL`.
|
|
const DatType* const* types;
|
|
uint32_t ntypes;
|
|
/// The names members and expressions refer to; the first, `DAT_NONE`,
|
|
/// is `NULL`.
|
|
const char* const* names;
|
|
uint32_t nnames;
|
|
const DatModule* modules;
|
|
uint32_t nmodules;
|
|
} DatSchema;
|
|
|
|
/* --- Writing descriptors --------------------------------------------------
|
|
*/
|
|
|
|
#define DAT_COUNTOF(array) (sizeof(array) / sizeof *(array))
|
|
|
|
/// A file's roots and a module's files.
|
|
#define DAT_FILE_ROOTS(array) .roots = (array), .nroots = DAT_COUNTOF(array)
|
|
#define DAT_MODULE(array) { .files = (array), .nfiles = DAT_COUNTOF(array) }
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|