remove old designer source

This commit is contained in:
nakst 2021-10-03 21:17:43 +01:00
parent 35f361a7e4
commit 291ba3f373
6 changed files with 2 additions and 7992 deletions

View File

@ -331,29 +331,9 @@ void BuildUtilities() {
BUILD_UTILITY("render_svg", "-lm", "");
BUILD_UTILITY("build_core", "-pthread -DPARALLEL_BUILD", "");
#ifndef __APPLE__ // Luigi doesn't support macOS.
BUILD_UTILITY("config_editor", "-lX11 -Wno-unused-parameter", "");
#endif
#ifndef __APPLE__ // Luigi doesn't support macOS.
BUILD_UTILITY("reflect_gen", "", "designer/");
if (CheckDependencies("Utilities.DesignerHeader")) {
if (!CallSystem("bin/reflect_gen util/designer/designer.rf > bin/designer.h")) {
FILE *f = fopen("bin/designer_header.d", "wb");
fprintf(f, ": util/designer/designer.rf bin/reflect_gen\n");
fclose(f);
ParseDependencies("bin/designer_header.d", "Utilities.DesignerHeader", false);
}
}
if (CheckDependencies("Utilities.OldDesigner1") || CheckDependencies("Utilities.OldDesigner2")) {
if (!CallSystem("gcc -MMD -o bin/designer.o -c util/designer/designer.c -g -std=c2x -fsanitize=address " WARNING_FLAGS_C)
&& !CallSystem("gcc -MMD -o bin/designer_luigi.o -c util/designer/designer_luigi.c -g -std=c2x " WARNING_FLAGS_C)
&& !CallSystem("gcc -o bin/designer -g bin/designer.o bin/designer_luigi.o -lX11 -lm -fsanitize=address ")) {
ParseDependencies("bin/designer.d", "Utilities.Designer1", false);
ParseDependencies("bin/designer_luigi.d", "Utilities.Designer2", false);
}
}
if (CheckDependencies("Utilities.Designer")) {
if (!CallSystem("g++ -MMD -D UI_LINUX util/designer2.cpp -o bin/designer2 -g -lX11 -Wno-unused-parameter " WARNING_FLAGS)) {
@ -1396,7 +1376,7 @@ void DoCommand(const char *l) {
LineCountFile("", "start.sh");
const char *folders[] = {
"desktop/", "boot/x86/", "drivers/", "kernel/", "apps/", "apps/file_manager/", "shared/", "util/", "util/designer/"
"desktop/", "boot/x86/", "drivers/", "kernel/", "apps/", "apps/file_manager/", "shared/", "util/"
};
for (uintptr_t i = 0; i < sizeof(folders) / sizeof(folders[0]); i++) {

File diff suppressed because it is too large Load Diff

View File

@ -1,432 +0,0 @@
type StyleColor_Type StyleColorOp;
type StyleString_Type StyleStringOp;
type StyleBool_Type StyleBoolOp;
type StyleArray_Type StyleArrayOp;
type StyleFloat_Type StyleFloatOp;
type StyleI8_Type StyleI8Op;
type StyleI16_Type StyleI16Op;
struct Property Property_Type PropertyOp {
rfNone "uint32_t *" path;
rfData RfData data;
};
struct Rectangle8 Rectangle8_Type Rectangle8Op {
StyleI8_Type int8_t l;
StyleI8_Type int8_t r;
StyleI8_Type int8_t t;
StyleI8_Type int8_t b;
};
struct Rectangle16 Rectangle16_Type Rectangle16Op {
StyleI16_Type int16_t l;
StyleI16_Type int16_t r;
StyleI16_Type int16_t t;
StyleI16_Type int16_t b;
};
struct Corners8 Corners8_Type Corners8Op {
StyleI8_Type int8_t tl;
StyleI8_Type int8_t tr;
StyleI8_Type int8_t bl;
StyleI8_Type int8_t br;
};
struct Gaps8 Gaps8_Type Gaps8Op {
StyleI8_Type int8_t major;
StyleI8_Type int8_t minor;
StyleI8_Type int8_t wrap;
};
struct Size16 Size16_Type Size16Op {
StyleI16_Type int16_t width;
StyleI16_Type int16_t height;
};
struct PaintSolid PaintSolid_Type PaintSolidOp {
StyleColor_Type uint32_t color #StringOption { "Color" };
};
struct PaintOverwrite PaintOverwrite_Type PaintOverwriteOp {
StyleColor_Type uint32_t color #StringOption { "Color" };
};
struct GradientStop GradientStop_Type GradientStopOp {
StyleColor_Type uint32_t color #StringOption { "Color" };
StyleI8_Type int8_t position #StringOption { "Position" };
};
enum GradientRepeat_Type StyleEnumOp {
GRADIENT_REPEAT_CLAMP #StringOption { "Clamp" };
GRADIENT_REPEAT_NORMAL #StringOption { "Normal" };
GRADIENT_REPEAT_MIRROR #StringOption { "Mirror" };
};
struct PaintLinearGradient PaintLinearGradient_Type PaintLinearGradientOp {
Rectangle16_Type Rectangle16 range #StringOption { "Range" } to 6;
StyleBool_Type bool useGammaInterpolation #StringOption { "Use gamma-accurate color interpolation" };
StyleArray_Type "GradientStop *" stops #RfItem { &GradientStop_Type, sizeof(GradientStop), &(StringOption) { "Stops: " } };
StyleBool_Type bool useDithering #StringOption { "Use dithering" } from 4;
GradientRepeat_Type uint8_t repeat #StringOption { "Repeat mode" } from 5;
StyleFloat_Type float transformX #StringOption { "Transform X" } from 6;
StyleFloat_Type float transformY #StringOption { "Transform Y" } from 6;
StyleFloat_Type float transformStart #StringOption { "Transform start" } from 6;
StyleBool_Type bool useSystemHue #StringOption { "Use system hue" } from 20;
StyleBool_Type bool _unused #StringOption { "_unused" } from 21;
};
struct PaintRadialGradient PaintRadialGradient_Type PaintRadialGradientOp {
StyleBool_Type bool useGammaInterpolation #StringOption { "Use gamma-accurate color interpolation" };
StyleArray_Type "GradientStop *" stops #RfItem { &GradientStop_Type, sizeof(GradientStop), &(StringOption) { "Stops: " } };
GradientRepeat_Type uint8_t repeat #StringOption { "Repeat mode" };
StyleFloat_Type float transform0 #StringOption { "Transform X scale" };
StyleFloat_Type float transform2 #StringOption { "Transform X offset" };
StyleFloat_Type float transform4 #StringOption { "Transform Y scale" };
StyleFloat_Type float transform5 #StringOption { "Transform Y offset" };
StyleFloat_Type float transform1 #StringOption { "Transform X skew" } from 8;
StyleFloat_Type float transform3 #StringOption { "Transform Y skew" } from 8;
};
struct Paint Paint_Type StyleUnionOp {
rfU32 uint32_t tag;
PaintSolid_Type PaintSolid solid #StringOption { "Solid" };
PaintLinearGradient_Type PaintLinearGradient linearGradient #StringOption { "Linear gradient" };
PaintOverwrite_Type PaintOverwrite overwrite #StringOption { "Overwrite" } from 2;
PaintRadialGradient_Type PaintRadialGradient radialGradient #StringOption { "Radial gradient" } from 7;
};
struct LayerBox LayerBox_Type LayerBoxOp {
Rectangle8_Type Rectangle8 borders #StringOption { "Borders" };
Corners8_Type Corners8 corners #StringOption { "Corners" };
Paint_Type Paint mainPaint #StringOption { "Main paint" };
Paint_Type Paint borderPaint #StringOption { "Border paint" };
StyleBool_Type bool blurred #StringOption { "Blurred" };
StyleBool_Type bool autoCorners #StringOption { "Auto corners" };
StyleBool_Type bool autoBorders #StringOption { "Auto borders" };
StyleBool_Type bool shadowHiding #StringOption { "Shadow hiding" };
StyleBool_Type bool shadowCut #StringOption { "Shadow cut (obsolete)" } from 13;
};
enum ClipMode_Type StyleEnumOp {
CLIP_MODE_ENABLED #StringOption { "Enabled" };
CLIP_MODE_DISABLED #StringOption { "Disabled" };
};
enum Cursor_Type StyleEnumOp {
CURSOR_NORMAL #StringOption { "Normal" };
CURSOR_TEXT #StringOption { "Text" };
CURSOR_RESIZE_VERTICAL #StringOption { "Resize vertical" };
CURSOR_RESIZE_HORIZONTAL #StringOption { "Resize horizontal" };
CURSOR_RESIZE_DIAGONAL_1 #StringOption { "Diagonal 1" };
CURSOR_RESIZE_DIAGONAL_2 #StringOption { "Diagonal 2" };
CURSOR_SPLIT_VERTICAL #StringOption { "Split vertical" };
CURSOR_SPLIT_HORIZONTAL #StringOption { "Split horizontal" };
CURSOR_HAND_HOVER #StringOption { "Hand hover" };
CURSOR_HAND_DRAG #StringOption { "Hand drag" };
CURSOR_HAND_POINT #StringOption { "Hand point" };
CURSOR_SCROLL_UP_LEFT #StringOption { "Scroll up-left" };
CURSOR_SCROLL_UP #StringOption { "Scroll up" };
CURSOR_SCROLL_UP_RIGHT #StringOption { "Scroll up-right" };
CURSOR_SCROLL_LEFT #StringOption { "Scroll left" };
CURSOR_SCROLL_CENTER #StringOption { "Scroll center" };
CURSOR_SCROLL_RIGHT #StringOption { "Scroll right" };
CURSOR_SCROLL_DOWN_LEFT #StringOption { "Scroll down-left" };
CURSOR_SCROLL_DOWN #StringOption { "Scroll down" };
CURSOR_SCROLL_DOWN_RIGHT #StringOption { "Scroll down-right" };
CURSOR_SELECT_LINES #StringOption { "Select lines" };
CURSOR_DROP_TEXT #StringOption { "Drop text" };
CURSOR_CROSS_HAIR_PICK #StringOption { "Cross hair pick" };
CURSOR_CROSS_HAIR_RESIZE #StringOption { "Cross hair resize" };
CURSOR_MOVE_HOVER #StringOption { "Move hover" };
CURSOR_MOVE_DRAG #StringOption { "Move drag" };
CURSOR_ROTATE_HOVER #StringOption { "Rotate hover" };
CURSOR_ROTATE_DRAG #StringOption { "Rotate drag" };
CURSOR_BLANK #StringOption { "Blank" };
};
enum Transition_Type StyleEnumOp {
TRANSITION_NONE #StringOption { "None" };
TRANSITION_SLIDE_UP #StringOption { "Slide up" };
TRANSITION_SLIDE_DOWN #StringOption { "Slide down" };
TRANSITION_COVER_UP #StringOption { "Cover up" };
TRANSITION_COVER_DOWN #StringOption { "Cover down" };
TRANSITION_SQUISH_UP #StringOption { "Squish up" };
TRANSITION_SQUISH_DOWN #StringOption { "Squish down" };
TRANSITION_REVEAL_UP #StringOption { "Reveal up" };
TRANSITION_REVEAL_DOWN #StringOption { "Reveal down" };
TRANSITION_ZOOM_OUT #StringOption { "Zoom out" };
TRANSITION_ZOOM_IN #StringOption { "Zoom in" };
TRANSITION_ZOOM_OUT_LIGHT #StringOption { "Zoom out (light)" };
TRANSITION_ZOOM_IN_LIGHT #StringOption { "Zoom in (light)" };
TRANSITION_FADE_OUT #StringOption { "Fade out" };
TRANSITION_FADE_IN #StringOption { "Fade in" };
};
enum Align_Type StyleEnumOp {
ALIGN_START #StringOption { "Start" };
ALIGN_CENTER #StringOption { "Center" };
ALIGN_END #StringOption { "End" };
};
enum FontFamily_Type StyleEnumOp {
FONT_FAMILY_SANS #StringOption { "Sans" };
FONT_FAMILY_SERIF #StringOption { "Serif" };
FONT_FAMILY_MONO #StringOption { "Mono" };
};
struct LayerMetrics LayerMetrics_Type LayerMetricsOp {
Rectangle8_Type Rectangle8 insets #StringOption { "Insets" };
ClipMode_Type uint32_t clipEnabled #StringOption { "Clipping: " };
Rectangle8_Type Rectangle8 clipInsets #StringOption { "Clip insets" };
Size16_Type Size16 preferredSize #StringOption { "Preferred size" };
Size16_Type Size16 minimumSize #StringOption { "Minimum size" };
Size16_Type Size16 maximumSize #StringOption { "Maximum size" };
Gaps8_Type Gaps8 gaps #StringOption { "Gaps" };
Cursor_Type uint32_t cursor #StringOption { "Cursor" };
Transition_Type uint32_t entranceTransition #StringOption { "Entrance transition" } to 21;
StyleI16_Type int16_t entranceDuration #StringOption { "Entrance duration (ms)" } to 21;
Transition_Type uint32_t exitTransition #StringOption { "Exit transition" } to 21;
StyleI16_Type int16_t exitDuration #StringOption { "Exit duration (ms)" } to 21;
Rectangle8_Type Rectangle8 globalOffset #StringOption { "Global offset" };
Align_Type uint32_t textVerticalAlign #StringOption { "Text vertical align: " };
Align_Type uint32_t textHorizontalAlign #StringOption { "Text horizontal align: " };
StyleI8_Type int8_t textSize #StringOption { "Font size" };
FontFamily_Type uint32_t fontFamily #StringOption { "Font family: " };
StyleI8_Type int8_t fontWeight #StringOption { "Font weight" };
StyleBool_Type bool italic #StringOption { "Italic" };
StyleBool_Type bool wrapText #StringOption { "Wrap text" };
StyleBool_Type bool ellipsis #StringOption { "Ellipsis" };
StyleColor_Type uint32_t textColor #StringOption { "Text color" };
StyleColor_Type uint32_t selectedBackground #StringOption { "Selected background" };
StyleColor_Type uint32_t selectedText #StringOption { "Selected text" };
StyleI8_Type int8_t iconSize #StringOption { "Icon size" };
StyleColor_Type uint32_t iconColor #StringOption { "Icon color" };
StyleString_Type RfData inheritText #StringOption { "Inherit text properties from:" } from 11;
};
struct LayerText LayerText_Type LayerTextOp {
StyleColor_Type uint32_t color #StringOption { "Color" };
StyleI8_Type int8_t blur #StringOption { "Blur radius" };
};
struct PathPoint PathPoint_Type PathPointOp {
StyleFloat_Type float x0 #StringOption { "x0" };
StyleFloat_Type float y0 #StringOption { "y0" };
StyleFloat_Type float x1 #StringOption { "x1" };
StyleFloat_Type float y1 #StringOption { "y1" };
StyleFloat_Type float x2 #StringOption { "x2" };
StyleFloat_Type float y2 #StringOption { "y2" };
};
struct PathFillSolid PathFillSolid_Type PathFillSolidOp {
};
enum JoinMode StyleEnumOp {
JOIN_MODE_MITER #StringOption { "Miter" };
JOIN_MODE_ROUND #StringOption { "Round" };
JOIN_MODE_BEVEL #StringOption { "Bevel" };
};
enum CapMode StyleEnumOp {
CAP_MODE_FLAT #StringOption { "Flat" };
CAP_MODE_ROUND #StringOption { "Round" };
CAP_MODE_SQUARE #StringOption { "Square" };
};
struct PathFillContour PathFillContour_Type PathFillContourOp {
StyleI8_Type int8_t internalWidth #StringOption { "Internal width" };
StyleI8_Type int8_t externalWidth #StringOption { "External width" };
StyleFloat_Type float miterLimit #StringOption { "Miter limit" };
JoinMode uint8_t joinMode #StringOption { "Join mode: " };
CapMode uint8_t capMode #StringOption { "Cap mode: " };
StyleBool_Type bool integerWidthsOnly #StringOption { "Integer widths only when scaling" } from 14;
};
struct PathFillDash PathFillDash_Type PathFillDashOp {
PathFillContour_Type PathFillContour contour;
StyleI8_Type int8_t length #StringOption { "Length" };
StyleI8_Type int8_t gap #StringOption { "Gap" };
};
struct PathFillDashed PathFillDashed_Type PathFillDashedOp {
StyleArray_Type "PathFillDash *" dashes #RfItem { &PathFillDash_Type, sizeof(PathFillDash), &(StringOption) { "Dashes: " } };
};
struct PathFillMode PathFillMode_Type StyleUnionOp {
rfU32 uint32_t tag;
PathFillSolid_Type PathFillSolid solid #StringOption { "Solid" };
PathFillContour_Type PathFillContour contour #StringOption { "Contour" };
PathFillDashed_Type PathFillDashed dashed #StringOption { "Dashed" };
};
struct PathFill PathFill_Type PathFillOp {
PathFillMode_Type PathFillMode mode #StringOption { "Mode" };
Paint_Type Paint paint #StringOption { "Paint" };
};
struct LayerPath LayerPath_Type LayerPathOp {
StyleBool_Type bool evenOdd #StringOption { "Even-odd fill rule" };
StyleBool_Type bool closed #StringOption { "Closed path" };
StyleI16_Type int16_t alpha #StringOption { "Alpha" };
StyleArray_Type "PathPoint *" points #RfItem { &PathPoint_Type, sizeof(PathPoint), &(StringOption) { "Points: " } };
StyleArray_Type "PathFill *" fills #RfItem { &PathFill_Type, sizeof(PathFill), &(StringOption) { "Fills: " } };
};
union LayerBase LayerBase_Type RfUnionOp {
LayerBox_Type LayerBox box;
LayerMetrics_Type LayerMetrics metrics;
rfNone bool _removed0;
rfNone bool _removed1;
LayerText_Type LayerText text;
LayerPath_Type LayerPath path;
};
type DesignerArray_Type DesignerArrayOp;
struct Keyframe Keyframe_Type RfStructOp {
StyleI8_Type int8_t progress #StringOption { "Progress (%)" };
DesignerArray_Type "Property *" properties #RfItem { &Property_Type, sizeof(Property), NULL };
};
enum PrimaryState_Type StyleEnumOp {
PRIMARY_STATE_ANY #StringOption { "Any" };
PRIMARY_STATE_IDLE #StringOption { "Idle" };
PRIMARY_STATE_HOVERED #StringOption { "Hovered" };
PRIMARY_STATE_PRESSED #StringOption { "Pressed" };
PRIMARY_STATE_DISABLED #StringOption { "Disabled" };
PRIMARY_STATE_INACTIVE #StringOption { "Inactive" };
};
struct Sequence Sequence_Type RfStructOp {
DesignerArray_Type "Keyframe **" keyframes #RfItem { &rfObject, sizeof(Keyframe *), &(RfItem) { &Keyframe_Type, sizeof(Keyframe), NULL } };
StyleI16_Type int16_t duration #StringOption { "Duration (ms)" };
PrimaryState_Type uint32_t primaryState #StringOption { "Primary state" };
StyleBool_Type bool flagFocused #StringOption { "Focused?" };
StyleBool_Type bool flagChecked #StringOption { "Checked?" };
StyleBool_Type bool flagIndeterminate #StringOption { "Indeterminate?" };
StyleBool_Type bool flagDefault #StringOption { "Default?" };
StyleBool_Type bool flagItemFocus #StringOption { "List item focus?" };
StyleBool_Type bool flagListFocus #StringOption { "List focus?" };
StyleBool_Type bool flagSelected #StringOption { "Selected?" };
StyleBool_Type bool flagBeforeEnter #StringOption { "Before enter?" };
StyleBool_Type bool flagAfterExit #StringOption { "After exit?" };
};
enum LayerMode_Type StyleEnumOp {
LAYER_MODE_BACKGROUND #StringOption { "Background" };
LAYER_MODE_SHADOW #StringOption { "Shadow" };
LAYER_MODE_CONTENT #StringOption { "Content" };
LAYER_MODE_OVERLAY #StringOption { "Overlay" };
};
struct Layer Layer_Type LayerOp {
rfU64 uint64_t id;
rfNone uint32_t exportOffset;
DesignerArray_Type "Sequence **" sequences #RfItem { &rfObject, sizeof(Sequence *), &(RfItem) { &Sequence_Type, sizeof(Sequence), NULL } };
StyleString_Type RfData name #StringOption { "Layer name" };
rfBool bool isMetricsLayer;
Rectangle8_Type Rectangle8 offset #StringOption { "Offset (dpx)" };
Rectangle8_Type Rectangle8 position #StringOption { "Position (%)" };
LayerMode_Type uint8_t mode #StringOption { "Mode: " };
LayerBase_Type LayerBase base;
};
struct Style Style_Type RfStructOp {
DesignerArray_Type "uint64_t *" layers #RfItem { &rfU64, sizeof(uint64_t), NULL };
rfData RfData name;
rfU64 uint64_t id from 15;
rfBool bool publicStyle from 16;
};
struct Constant Constant_Type RfStructOp {
rfData RfData key;
StyleString_Type RfData value;
StyleBool_Type bool scale from 9;
};
struct Color Color_Type RfStructOp {
rfData RfData key;
rfU32 uint32_t value;
rfU32 uint32_t id;
rfNone uint64_t object2ID;
};
struct StyleSet StyleSet_Type StyleSetOp {
rfU64 uint64_t lastID;
DesignerArray_Type "Style **" styles #RfItem { &rfObject, sizeof(Style *), &(RfItem) { &Style_Type, sizeof(Style), NULL } };
DesignerArray_Type "Layer **" layers #RfItem { &rfObject, sizeof(Layer *), &(RfItem) { &Layer_Type, sizeof(Layer), NULL } };
DesignerArray_Type "Constant **" constants #RfItem { &rfObject, sizeof(Constant *), &(RfItem) { &Constant_Type, sizeof(Constant), NULL } };
DesignerArray_Type "Color **" colors #RfItem { &rfObject, sizeof(Color *), &(RfItem) { &Color_Type, sizeof(Color), NULL } } from 17;
};
/////////////////////////////////////////////////////
struct ModAddLayer ModAddLayer_Type ModAddLayerOp {
rfObject "Layer *" layer #RfItem { &Layer_Type, sizeof(Layer), NULL };
rfI32 int index;
};
struct ModDeleteLayer ModDeleteLayer_Type ModDeleteLayerOp {
rfI32 int index;
};
struct ModSwapLayers ModSwapLayers_Type ModSwapLayersOp {
rfI32 int index;
};
struct ModSwapSequences ModSwapSequences_Type ModSwapSequencesOp {
rfI32 int index;
};
struct ModAddSequence ModAddSequence_Type ModAddSequenceOp {
rfObject "Sequence *" sequence #RfItem { &Sequence_Type, sizeof(Sequence), NULL };
rfI32 int index;
};
struct ModDeleteSequence ModDeleteSequence_Type ModDeleteSequenceOp {
rfI32 int index;
};
struct ModAddKeyframe ModAddKeyframe_Type ModAddKeyframeOp {
rfObject "Keyframe *" keyframe #RfItem { &Keyframe_Type, sizeof(Keyframe), NULL };
rfI32 int index;
};
struct ModDeleteKeyframe ModDeleteKeyframe_Type ModDeleteKeyframeOp {
rfI32 int index;
};
struct ModChangeProperty ModChangeProperty_Type ModChangePropertyOp {
Property_Type Property property;
rfNone "struct UIElement *" source;
};
struct ModArray ModArray_Type ModArrayOp {
Property_Type Property property;
rfBool bool isDelete;
};
struct ModDeleteOverride ModDeleteOverride_Type ModDeleteOverrideOp {
Property_Type Property property;
};
union ModData ModData_Type RfUnionOp {
ModAddLayer_Type ModAddLayer addLayer;
ModDeleteLayer_Type ModDeleteLayer deleteLayer;
ModSwapLayers_Type ModSwapLayers swapLayers;
ModSwapSequences_Type ModSwapSequences swapSequences;
ModAddSequence_Type ModAddSequence addSequence;
ModDeleteSequence_Type ModDeleteSequence deleteSequence;
ModAddKeyframe_Type ModAddKeyframe addKeyframe;
ModDeleteKeyframe_Type ModDeleteKeyframe deleteKeyframe;
ModChangeProperty_Type ModChangeProperty changeProperty;
ModArray_Type ModArray array;
ModDeleteOverride_Type ModDeleteOverride deleteOverride;
};
struct Mod Mod_Type RfStructOp {
rfNone ModContext context;
ModData_Type ModData data;
};

View File

@ -1,8 +0,0 @@
#ifdef _WIN32
#define UI_WINDOWS
#else
#define UI_LINUX
#endif
#define UI_IMPLEMENTATION
#include "../luigi.h"

View File

@ -1,654 +0,0 @@
// TODO Bitsets.
// TODO Versioning support for unions and enums.
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifndef RF_ASSERT
#include <assert.h>
#define RF_ASSERT assert
#endif
#ifndef RF_MEMZERO
#include <string.h>
#define RF_MEMZERO(pointer, byteCount) memset((pointer), 0, (byteCount))
#endif
#ifndef RF_MEMCPY
#include <string.h>
#define RF_MEMCPY(destination, source, byteCount) memcpy((destination), (source), (byteCount))
#endif
#ifndef RF_REALLOC
#include <stdlib.h>
#define RF_REALLOC(previous, byteCount) realloc((previous), (byteCount))
#endif
#define RF_SIZE_OF(containerType, field) sizeof(((containerType *) NULL)->field)
#define RF_FIELD(containerType, field, fieldRfType, ...) \
{ \
.item.type = &fieldRfType, \
.item.byteCount = RF_SIZE_OF(containerType, field), \
.cName = #field, \
.offset = offsetof(containerType, field), \
__VA_ARGS__ \
}
#define RF_OP_SAVE (-1) // Set access in RfState.
#define RF_OP_LOAD (-2) // Set access and allocate in RfState.
#define RF_OP_FREE (-3) // Set allocate in RfState.
#define RF_OP_ITERATE (-4) // Pass RfIterator; set index.
#define RF_OP_COUNT (-5) // Pass RfIterator; result saved in index.
// User-defined operations use positive integers.
typedef struct RfState {
bool error;
int16_t op;
uint32_t version, flags;
void *(*allocate)(struct RfState *state, void *previous, size_t byteCount);
void (*access)(struct RfState *state, void *buffer, size_t byteCount);
} RfState;
typedef struct RfItem {
struct RfType *type;
size_t byteCount;
void *options;
} RfItem;
typedef struct RfField {
RfItem item;
const char *cName;
ptrdiff_t offset;
uint32_t firstVersion, lastVersion;
uint32_t flagsInclude, flagsExclude;
} RfField;
typedef struct RfType {
void (*op)(RfState *state, RfItem *field, void *pointer);
const char *cName;
size_t fieldCount;
RfField *fields;
} RfType;
typedef struct RfIterator {
RfState s;
void *pointer;
RfItem item;
uint32_t index;
bool includeRemovedFields;
bool isRemoved;
} RfIterator;
typedef struct RfPath {
#define RF_PATH_TERMINATOR (0xFFFFFFFF)
uint32_t indices[1];
} RfPath;
typedef struct RfUnionHeader {
uint32_t tag;
} RfUnionHeader;
typedef struct RfArrayHeader {
size_t length, capacity;
// For compatability with stb_ds.h.
void *hashTable;
ptrdiff_t temporary;
} RfArrayHeader;
typedef struct RfData {
void *buffer;
size_t byteCount;
} RfData;
typedef struct RfGrowableBuffer {
RfState s;
RfData data;
// When writing - allocated space in data.
// When reading - position in data.
size_t position;
} RfGrowableBuffer;
extern RfType rfI8, rfI16, rfI32, rfI64,
rfU8, rfU16, rfU32, rfU64,
rfF32, rfF64,
rfChar, rfBool,
rfData, rfNone,
rfObject /* options - RfItem */,
rfArray /* options - RfItem */;
bool RfPathResolve(RfPath *path, RfItem *item, void **pointer); // Returns true if successful.
void RfBroadcast(RfState *state, RfItem *item, void *pointer, bool recurse);
void RfUnionSelect(RfState *state, RfItem *item, RfUnionHeader *header, uint32_t tag);
void RfReadGrowableBuffer(RfState /* RfGrowableBuffer */ *state, void *buffer, size_t byteCount);
void RfWriteGrowableBuffer(RfState /* RfGrowableBuffer */ *state, void *buffer, size_t byteCount);
void *RfRealloc(RfState *state, void *previous, size_t byteCount);
void RfStructOp(RfState *state, RfItem *item, void *pointer);
void RfUnionOp(RfState *state, RfItem *item, void *pointer);
void RfEnumOp(RfState *state, RfItem *item, void *pointer);
void RfBitSetOp(RfState *state, RfItem *item, void *pointer);
void RfEndianOp(RfState *state, RfItem *item, void *pointer);
void RfIntegerOp(RfState *state, RfItem *item, void *pointer);
void RfNoneOp(RfState *state, RfItem *item, void *pointer);
#ifdef REFLECT_IMPLEMENTATION
void RfIntegerSave(RfState *state, void *pointer, size_t inByteCount) {
uint8_t in[16];
RF_ASSERT(inByteCount < 16);
RF_MEMCPY(in, pointer, inByteCount);
bool negative = in[inByteCount - 1] & 0x80;
size_t inBitCount = 1;
for (int i = inByteCount - 1; i >= 0; i--) {
for (int j = 7; j >= 0; j--) {
if (((in[i] >> j) & 1) != negative) {
inBitCount = i * 8 + j + 2;
goto gotBitCount;
}
}
}
gotBitCount:;
size_t outByteCount = (inBitCount + 6) / 7;
uint8_t out[16];
RF_ASSERT(outByteCount < 16);
for (uintptr_t i = 0; i < outByteCount; i++) {
uint8_t b = 0;
for (uintptr_t j = 0; j < 7; j++) {
uintptr_t bitIndex = i * 7 + j;
bool inBit = negative;
if (bitIndex < 8 * inByteCount) inBit = in[bitIndex >> 3] & (1 << (bitIndex & 7));
if (inBit) b |= 1 << j;
}
out[i] = b;
}
out[outByteCount - 1] |= 0x80;
state->access(state, out, outByteCount);
}
void RfIntegerLoad(RfState *state, void *pointer, size_t byteCount) {
uint8_t out[16];
uintptr_t outIndex = 0;
RF_ASSERT(byteCount < 16);
RF_MEMZERO(out, byteCount);
while (!state->error) {
uint8_t b;
state->access(state, &b, 1);
for (uintptr_t i = 0; i < 7; i++) {
if (outIndex == byteCount * 8) break;
if (b & (1 << i)) out[outIndex >> 3] |= 1 << (outIndex & 7);
outIndex++;
}
if (b & 0x80) {
if (b & 0x40) {
for (uintptr_t i = outIndex; i < byteCount * 8; i++) {
out[i >> 3] |= 1 << (i & 7);
}
}
break;
}
}
if (!state->error && pointer) {
RF_MEMCPY(pointer, out, byteCount);
}
}
void RfStructOp(RfState *state, RfItem *item, void *pointer) {
RfType *type = item->type;
if (state->op == RF_OP_SAVE || state->op == RF_OP_LOAD || state->op == RF_OP_FREE) {
for (uintptr_t i = 0; i < type->fieldCount && !state->error; i++) {
RfField *field = type->fields + i;
if (state->flags & field->flagsExclude) continue;
if ((state->flags & field->flagsInclude) != field->flagsInclude) continue;
void *fieldPointer = pointer ? ((uint8_t *) pointer + field->offset) : NULL;
if (state->op == RF_OP_LOAD) {
if (state->version < field->firstVersion) {
// The field exists, but we're loading from a version where it did not exist.
// Ignore it.
continue;
} else if (field->lastVersion && state->version > field->lastVersion) {
// The field no longer exists, and we're from loading a version where it did not exist.
// Ignore it.
continue;
} else if (field->lastVersion) {
// The field no longer exists, but we're loading a version where it did.
// Skip over it.
fieldPointer = NULL;
} else {
// The field exists, and we're loading from a version where it exists.
}
} else {
if (field->lastVersion) {
continue;
}
}
field->item.type->op(state, &field->item, fieldPointer);
if (state->op == RF_OP_FREE) {
RF_MEMZERO(fieldPointer, field->item.byteCount);
}
}
} else if (state->op == RF_OP_COUNT) {
RfIterator *iterator = (RfIterator *) state;
uint32_t count = 0;
for (uintptr_t i = 0; i < type->fieldCount; i++) {
if (!type->fields[i].lastVersion) {
count++;
}
}
iterator->index = count;
} else if (state->op == RF_OP_ITERATE) {
RfIterator *iterator = (RfIterator *) state;
uint32_t count = 0;
for (uintptr_t i = 0; i < type->fieldCount; i++) {
iterator->isRemoved = type->fields[i].lastVersion;
if (!iterator->isRemoved || iterator->includeRemovedFields) {
if (iterator->index == count) {
iterator->pointer = (uint8_t *) pointer + type->fields[i].offset;
iterator->item = type->fields[i].item;
return;
}
count++;
}
}
state->error = true;
}
}
void RfUnionOp(RfState *state, RfItem *item, void *pointer) {
RfType *type = item->type;
RfUnionHeader *header = (RfUnionHeader *) pointer;
if (state->op == RF_OP_SAVE) {
state->access(state, &header->tag, sizeof(uint32_t));
if (header->tag) {
RfField *field = type->fields + header->tag - 1;
field->item.type->op(state, &field->item, (uint8_t *) pointer + field->offset);
}
} else if (state->op == RF_OP_LOAD) {
uint32_t tag = 0;
state->access(state, &tag, sizeof(uint32_t));
if (tag > type->fieldCount) {
tag = 0;
state->error = true;
} else if (tag) {
RfField *field = type->fields + tag - 1;
if (field->lastVersion) tag = 0;
field->item.type->op(state, &field->item, pointer && !field->lastVersion ? ((uint8_t *) pointer + field->offset) : NULL);
}
if (header) {
header->tag = tag;
}
} else if (state->op == RF_OP_FREE) {
if (header->tag) {
RfField *field = type->fields + header->tag - 1;
field->item.type->op(state, &field->item, (uint8_t *) pointer + field->offset);
}
header->tag = 0;
} else if (state->op == RF_OP_COUNT) {
RfIterator *iterator = (RfIterator *) state;
iterator->index = header->tag ? 1 : 0;
} else if (state->op == RF_OP_ITERATE) {
RfIterator *iterator = (RfIterator *) state;
if (!header->tag || iterator->index > 1) {
state->error = true;
} else {
RfField *field = type->fields + header->tag - 1;
iterator->pointer = (uint8_t *) pointer + field->offset;
iterator->item = field->item;
}
}
}
void RfUnionSelect(RfState *state, RfItem *item, RfUnionHeader *header, uint32_t tag) {
RF_ASSERT(header->tag < item->type->fieldCount && !item->type->fields[header->tag].lastVersion);
RF_ASSERT(tag < item->type->fieldCount && !item->type->fields[tag].lastVersion);
if (header->tag) {
RfField *field = item->type->fields + header->tag - 1;
field->item.type->op(state, &field->item, (uint8_t *) header + field->offset);
}
header->tag = tag + 1;
}
void RfEnumOp(RfState *state, RfItem *item, void *pointer) {
if (state->op == RF_OP_SAVE) {
RfIntegerSave(state, pointer, item->byteCount);
} else if (state->op == RF_OP_LOAD) {
RfIntegerLoad(state, pointer, item->byteCount);
if (pointer) {
uint32_t value = 0;
if (item->byteCount == 1) {
value = *(uint8_t *) pointer;
} else if (item->byteCount == 2) {
value = *(uint16_t *) pointer;
} else if (item->byteCount == 4) {
value = *(uint32_t *) pointer;
} else {
RF_ASSERT(false);
}
if (value >= item->type->fieldCount) {
state->error = true;
}
}
}
}
void RfEndianOp(RfState *state, RfItem *item, void *pointer) {
if (state->op == RF_OP_SAVE || state->op == RF_OP_LOAD) {
state->access(state, pointer, item->byteCount);
}
}
void RfBoolOp(RfState *state, RfItem *item, void *pointer) {
RfEndianOp(state, item, pointer);
if (state->op == RF_OP_LOAD) {
if (pointer && *(uint8_t *) pointer > 1) {
state->error = true;
}
}
}
void RfIntegerOp(RfState *state, RfItem *item, void *pointer) {
if (state->op == RF_OP_SAVE) {
RfIntegerSave(state, pointer, item->byteCount);
} else if (state->op == RF_OP_LOAD) {
RfIntegerLoad(state, pointer, item->byteCount);
}
}
void RfDataOp(RfState *state, RfItem *item, void *pointer) {
(void) item;
RfData *data = (RfData *) pointer;
if (state->op == RF_OP_SAVE) {
uint32_t byteCount = data->byteCount;
RfIntegerSave(state, &byteCount, sizeof(uint32_t));
state->access(state, data->buffer, data->byteCount);
} else if (state->op == RF_OP_LOAD) {
uint32_t byteCount = 0;
RfIntegerLoad(state, &byteCount, sizeof(uint32_t));
if (data) {
RF_ASSERT(!data->buffer);
data->buffer = state->allocate(state, NULL, byteCount);
if (!data->buffer) { state->error = true; return; }
data->byteCount = byteCount;
}
state->access(state, data ? data->buffer : NULL, data->byteCount);
} else if (state->op == RF_OP_FREE) {
state->allocate(state, data->buffer, 0);
data->buffer = NULL;
}
}
void RfObjectOp(RfState *state, RfItem *item, void *pointer) {
RfItem *objectItem = (RfItem *) item->options;
void **object = (void **) pointer;
if (state->op == RF_OP_SAVE) {
uint8_t present = *object != NULL;
state->access(state, &present, sizeof(uint8_t));
if (present) objectItem->type->op(state, objectItem, *object);
} else if (state->op == RF_OP_LOAD) {
uint8_t present = 0;
state->access(state, &present, sizeof(uint8_t));
if (object) {
RF_ASSERT(!(*object));
if (present) {
*object = state->allocate(state, NULL, objectItem->byteCount);
if (!(*object)) { state->error = true; return; }
RF_MEMZERO(*object, objectItem->byteCount);
objectItem->type->op(state, objectItem, *object);
}
} else if (present) {
objectItem->type->op(state, objectItem, NULL);
}
} else if (state->op == RF_OP_FREE) {
if (*object) {
objectItem->type->op(state, objectItem, *object);
state->allocate(state, *object, 0);
*object = NULL;
}
} else if (state->op == RF_OP_COUNT) {
RfIterator *iterator = (RfIterator *) state;
iterator->index = *object ? 1 : 0;
} else if (state->op == RF_OP_ITERATE) {
RfIterator *iterator = (RfIterator *) state;
if (!(*object) || iterator->index > 1) {
state->error = true;
} else {
iterator->pointer = *object;
iterator->item = *objectItem;
}
}
}
void RfNoneOp(RfState *state, RfItem *item, void *pointer) {
(void) state;
(void) item;
(void) pointer;
}
void RfArrayOp(RfState *state, RfItem *item, void *_pointer) {
RfArrayHeader **pointer = (RfArrayHeader **) _pointer;
RfItem *objectItem = (RfItem *) item->options;
if (state->op == RF_OP_SAVE) {
uint32_t length = 0;
if (*pointer) {
length = (*pointer)[-1].length;
}
RfIntegerSave(state, &length, sizeof(uint32_t));
for (uint32_t i = 0; i < length; i++) {
objectItem->type->op(state, objectItem, (uint8_t *) (*pointer) + i * objectItem->byteCount);
}
} else if (state->op == RF_OP_LOAD) {
RF_ASSERT(!pointer || !(*pointer));
uint32_t length = 0;
RfIntegerLoad(state, &length, sizeof(uint32_t));
if (length >= 0xFFFFFFFF / objectItem->byteCount) {
state->error = true;
return;
}
if (!length) {
return;
}
if (pointer) {
void *allocation = state->allocate(state, NULL, length * objectItem->byteCount + sizeof(RfArrayHeader));
if (!allocation) {
state->error = true;
return;
}
*pointer = (RfArrayHeader *) allocation + 1;
(*pointer)[-1].length = 0;
(*pointer)[-1].capacity = length;
(*pointer)[-1].hashTable = NULL;
(*pointer)[-1].temporary = 0;
}
for (uint32_t i = 0; i < length && !state->error; i++) {
if (pointer) {
uint32_t index = (*pointer)[-1].length;
(*pointer)[-1].length++;
uint8_t *p = (uint8_t *) (*pointer) + index * objectItem->byteCount;
RF_MEMZERO(p, objectItem->byteCount);
objectItem->type->op(state, objectItem, p);
} else {
objectItem->type->op(state, objectItem, NULL);
}
}
} else if (state->op == RF_OP_FREE) {
if (*pointer) {
state->allocate(state, (*pointer) - 1, 0);
(*pointer) = NULL;
}
} else if (state->op == RF_OP_COUNT) {
RfIterator *iterator = (RfIterator *) state;
iterator->index = *pointer ? (*pointer)[-1].length : 0;
} else if (state->op == RF_OP_ITERATE) {
RfIterator *iterator = (RfIterator *) state;
if (!(*pointer) || iterator->index > (*pointer)[-1].length) {
state->error = true;
} else {
iterator->pointer = (uint8_t *) (*pointer) + iterator->index * objectItem->byteCount;
iterator->item = *objectItem;
}
}
}
bool RfPathResolve(RfPath *path, RfItem *item, void **pointer) {
RfIterator iterator = { 0 };
iterator.s.op = RF_OP_ITERATE;
iterator.item = *item;
iterator.pointer = *pointer;
iterator.includeRemovedFields = true;
for (int i = 0; path->indices[i] != RF_PATH_TERMINATOR && !iterator.s.error; i++) {
iterator.index = path->indices[i];
RfItem _item = iterator.item;
_item.type->op(&iterator.s, &_item, iterator.pointer);
}
*item = iterator.item;
*pointer = iterator.pointer;
return !iterator.s.error;
}
void RfBroadcast(RfState *state, RfItem *item, void *pointer, bool recurse) {
RfIterator iterator = { 0 };
iterator.s.op = RF_OP_COUNT;
item->type->op(&iterator.s, item, pointer);
iterator.s.op = RF_OP_ITERATE;
uint32_t count = iterator.index;
for (uint32_t i = 0; i < count; i++) {
iterator.index = i;
item->type->op(&iterator.s, item, pointer);
if (iterator.s.error) return;
iterator.item.type->op(state, &iterator.item, iterator.pointer);
if (recurse) {
RfBroadcast(state, &iterator.item, iterator.pointer, true);
}
}
}
void RfWriteGrowableBuffer(RfState *state, void *source, size_t byteCount) {
if (state->error) return;
RfGrowableBuffer *destination = (RfGrowableBuffer *) state;
if (destination->data.byteCount + byteCount > destination->position) {
destination->position = destination->position * 2;
if (destination->data.byteCount + byteCount > destination->position) {
destination->position = destination->data.byteCount + byteCount + 64;
}
void *old = destination->data.buffer;
destination->data.buffer = state->allocate(state, destination->data.buffer, destination->position);
if (!destination->data.buffer) {
state->allocate(state, old, 0);
state->error = true;
return;
}
}
RF_MEMCPY((uint8_t *) destination->data.buffer + destination->data.byteCount, source, byteCount);
destination->data.byteCount += byteCount;
}
void RfReadGrowableBuffer(RfState *state, void *destination, size_t byteCount) {
if (state->error) return;
RfGrowableBuffer *source = (RfGrowableBuffer *) state;
if (source->position + byteCount > source->data.byteCount) {
state->error = true;
} else {
if (destination) {
RF_MEMCPY(destination, (uint8_t *) source->data.buffer + source->position, byteCount);
}
source->position += byteCount;
}
}
void *RfRealloc(RfState *state, void *previous, size_t byteCount) {
(void) state;
return RF_REALLOC(previous, byteCount);
}
RfType rfI8 = { .op = RfEndianOp, .cName = "I8" };
RfType rfI16 = { .op = RfIntegerOp, .cName = "I16" };
RfType rfI32 = { .op = RfIntegerOp, .cName = "I32" };
RfType rfI64 = { .op = RfIntegerOp, .cName = "I64" };
RfType rfU8 = { .op = RfEndianOp, .cName = "U8" };
RfType rfU16 = { .op = RfIntegerOp, .cName = "U16" };
RfType rfU32 = { .op = RfIntegerOp, .cName = "U32" };
RfType rfU64 = { .op = RfIntegerOp, .cName = "U64" };
RfType rfChar = { .op = RfEndianOp, .cName = "Char" };
RfType rfBool = { .op = RfBoolOp, .cName = "Bool" };
RfType rfF32 = { .op = RfEndianOp, .cName = "F32" };
RfType rfF64 = { .op = RfEndianOp, .cName = "F64" };
RfType rfData = { .op = RfDataOp, .cName = "Data" };
RfType rfObject = { .op = RfObjectOp, .cName = "Object" };
RfType rfArray = { .op = RfArrayOp, .cName = "Array" };
RfType rfNone = { .op = RfNoneOp, .cName = "None" };
#endif

View File

@ -1,531 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define STB_DS_IMPLEMENTATION
#include "../stb_ds.h"
#define TOKEN_BLOCK (0)
#define TOKEN_LEFT_BRACE (1)
#define TOKEN_RIGHT_BRACE (2)
#define TOKEN_LEFT_PAREN (3)
#define TOKEN_RIGHT_PAREN (4)
#define TOKEN_SEMICOLON (5)
#define TOKEN_IDENTIFIER (6)
#define TOKEN_STRING (7)
#define TOKEN_EOF (8)
#define TOKEN_COMMA (9)
#define TOKEN_NUMBER (10)
#define TOKEN_HASH (11)
#define TOKEN_QUESTION (12)
#define TOKEN_EQUALS (13)
#define TOKEN_LEFT_BRACKET (14)
#define TOKEN_RIGHT_BRACKET (15)
#define TOKEN_COLON (16)
#define TOKEN_EXCLAMATION (17)
typedef struct Parse {
const char *position;
int line;
bool success;
} Parse;
typedef struct Token {
int type;
double number;
char *string;
} Token;
typedef struct ParsedField {
char *rfType, *cTypeBefore, *fieldName, *cTypeAfter;
int firstVersion, lastVersion;
char **flagsInclude, **flagsExclude;
char *optionsType, *optionsBlock;
} ParsedField;
typedef struct ParsedType {
bool isStruct, isUnion, isCustom, isEnum;
char *cName, *rfName, *opFunction;
ParsedField *fields;
} ParsedType;
ParsedType *parsedTypes;
bool IsDigit(char c) { return (c >= '0' && c <= '9'); }
bool IsAlpha(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
bool IsAlnum(char c) { return (IsDigit(c) || IsAlpha(c)); }
bool _NextToken(Parse *parse, Token *token) {
if (!parse->success) return false;
while (true) {
char c = *parse->position;
parse->position++;
if (c == ' ' || c == '\t' || c == '\r') {
continue;
} else if (c == '\n') {
parse->line++;
continue;
} else if (c == '/' && *parse->position == '/') {
while (*parse->position != '\n') parse->position++;
continue;
} else if (c == '/' && *parse->position == '*') {
while (parse->position[0] != '*' || parse->position[1] != '/') parse->position++;
parse->position += 2;
continue;
#define PARSE_CHARACTER(a, b) \
} else if (c == a) { \
Token t = {}; \
t.type = b; \
*token = t; \
return true
PARSE_CHARACTER('{', TOKEN_LEFT_BRACE );
PARSE_CHARACTER('}', TOKEN_RIGHT_BRACE );
PARSE_CHARACTER('(', TOKEN_LEFT_PAREN );
PARSE_CHARACTER(')', TOKEN_RIGHT_PAREN );
PARSE_CHARACTER('[', TOKEN_LEFT_BRACKET );
PARSE_CHARACTER(']', TOKEN_RIGHT_BRACKET );
PARSE_CHARACTER(';', TOKEN_SEMICOLON );
PARSE_CHARACTER(':', TOKEN_COLON );
PARSE_CHARACTER(',', TOKEN_COMMA );
PARSE_CHARACTER('#', TOKEN_HASH );
PARSE_CHARACTER('?', TOKEN_QUESTION );
PARSE_CHARACTER('=', TOKEN_EQUALS );
PARSE_CHARACTER('!', TOKEN_EXCLAMATION );
} else if (IsAlpha(c) || c == '_') {
const char *start = parse->position - 1;
while (true) {
char c2 = *parse->position;
if (c2 == 0) break;
if (!IsAlnum(c2) && c2 != '_') break;
parse->position++;
}
Token _token = { 0 };
_token.type = TOKEN_IDENTIFIER;
_token.string = malloc(parse->position - start + 1);
if (!_token.string) { parse->success = false; return false; }
memcpy(_token.string, start, parse->position - start);
_token.string[parse->position - start] = 0;
*token = _token;
return true;
} else if (IsDigit(c) || c == '-') {
const char *start = parse->position - 1;
while (true) {
char c2 = *parse->position;
if (c2 == 0) break;
if (!IsAlnum(c2) && c2 != '.') break;
parse->position++;
}
Token _token = { 0 };
_token.type = TOKEN_NUMBER;
_token.string = malloc(parse->position - start + 1);
if (!_token.string) { parse->success = false; return false; }
memcpy(_token.string, start, parse->position - start);
_token.string[parse->position - start] = 0;
bool negate = _token.string[0] == '-';
bool afterDot = false;
bool hexadecimal = false;
double fraction = 0.1;
for (uintptr_t i = negate ? 1 : 0; _token.string[i]; i++) {
char c = _token.string[i];
if (c == '.') {
if (hexadecimal) {
parse->success = false;
return false;
}
afterDot = true;
} else if (c == 'x') {
if (i != 1 || _token.string[0] != '0' || afterDot) {
parse->success = false;
return false;
}
hexadecimal = true;
} else if (afterDot) {
if (!IsDigit(c)) {
parse->success = false;
return false;
}
_token.number += (c - '0') * fraction;
fraction *= 0.1;
} else {
if (hexadecimal) {
_token.number *= 16;
if (c >= '0' && c <= '9') {
_token.number += c - '0';
} else if (c >= 'a' && c <= 'f') {
_token.number += c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
_token.number += c - 'A' + 10;
} else {
parse->success = false;
return false;
}
} else {
if (!IsDigit(c)) {
parse->success = false;
return false;
}
_token.number *= 10;
_token.number += c - '0';
}
}
}
if (negate) _token.number = -_token.number;
*token = _token;
return true;
} else if (c == '"') {
const char *start = parse->position;
while (true) {
char c2 = *parse->position;
if (c2 == 0) break;
parse->position++;
if (c2 == '"') break;
}
Token _token = { 0 };
_token.type = TOKEN_STRING;
_token.string = (char *) malloc(parse->position - start);
if (!_token.string) { parse->success = false; return false; }
memcpy(_token.string, start, parse->position - start - 1);
_token.string[parse->position - start - 1] = 0;
*token = _token;
return true;
} else if (c == 0) {
Token t = {};
t.type = TOKEN_EOF;
*token = t;
return true;
} else {
parse->success = false;
return false;
}
}
}
Token NextToken(Parse *parse) {
Token token = { 0 };
bool success = _NextToken(parse, &token);
if (!success) {
fprintf(stderr, "error: invalid token on line %d\n", parse->line);
exit(1);
}
return token;
}
char *NextString(Parse *parse) {
Token token = NextToken(parse);
if (token.type == TOKEN_IDENTIFIER || token.type == TOKEN_STRING) {
return token.string;
} else {
fprintf(stderr, "error: expected string or identifier on line %d\n", parse->line);
exit(1);
return NULL;
}
}
Token ExpectToken(Parse *parse, int type) {
Token token = NextToken(parse);
if (token.type == type) {
return token;
} else {
fprintf(stderr, "error: expected token of type %d of line %d\n", type, parse->line);
exit(1);
return (Token) { 0 };
}
}
char *NextBlock(Parse *parse) {
ExpectToken(parse, TOKEN_LEFT_BRACE);
int depth = 1;
const char *start = parse->position;
while (depth) {
if (*parse->position == '{') {
depth++;
parse->position++;
} else if (*parse->position == '}') {
depth--;
parse->position++;
} else if (*parse->position == '"') {
ExpectToken(parse, TOKEN_STRING);
} else if (*parse->position == 0) {
fprintf(stderr, "error: unexpected end of file during block\n");
exit(1);
} else {
parse->position++;
}
}
char *result = malloc(parse->position - start);
memcpy(result, start, parse->position - start - 1);
result[parse->position - start - 1] = 0;
return result;
}
Token PeekToken(Parse *parse) {
Parse old = *parse;
Token token = NextToken(parse);
*parse = old;
return token;
}
char *LoadFile(const char *inputFileName, size_t *byteCount) {
FILE *inputFile = fopen(inputFileName, "rb");
if (!inputFile) {
return NULL;
}
fseek(inputFile, 0, SEEK_END);
size_t inputFileBytes = ftell(inputFile);
fseek(inputFile, 0, SEEK_SET);
char *inputBuffer = (char *) malloc(inputFileBytes + 1);
size_t inputBytesRead = fread(inputBuffer, 1, inputFileBytes, inputFile);
inputBuffer[inputBytesRead] = 0;
fclose(inputFile);
if (byteCount) *byteCount = inputBytesRead;
return inputBuffer;
}
void ParseAdditionalFieldInformation(Parse *parse, ParsedField *field) {
while (PeekToken(parse).type != TOKEN_SEMICOLON) {
Token token = NextToken(parse);
if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "from") && !field->firstVersion) {
field->firstVersion = ExpectToken(parse, TOKEN_NUMBER).number;
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "to") && !field->lastVersion) {
field->lastVersion = ExpectToken(parse, TOKEN_NUMBER).number;
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "if") && !field->flagsInclude && !field->flagsExclude) {
ExpectToken(parse, TOKEN_LEFT_PAREN);
while (PeekToken(parse).type != TOKEN_RIGHT_PAREN) {
if (PeekToken(parse).type == TOKEN_EXCLAMATION) {
ExpectToken(parse, TOKEN_EXCLAMATION);
arrput(field->flagsExclude, NextString(parse));
} else {
arrput(field->flagsInclude, NextString(parse));
}
}
ExpectToken(parse, TOKEN_RIGHT_PAREN);
} else if (token.type == TOKEN_HASH) {
field->optionsType = NextString(parse);
field->optionsBlock = NextBlock(parse);
} else {
fprintf(stderr, "error: unexpected token in field on line %d\n", parse->line);
exit(1);
}
}
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: reflect_gen <input file>\n");
return 1;
}
char *input = LoadFile(argv[1], NULL);
if (!input) {
fprintf(stderr, "error: could not open input file '%s'\n", argv[1]);
return 1;
}
Parse parse = { 0 };
parse.position = input;
parse.line = 1;
parse.success = true;
while (true) {
Token token = NextToken(&parse);
if (token.type == TOKEN_EOF) {
break;
}
if (token.type == TOKEN_IDENTIFIER && (0 == strcmp(token.string, "struct") || 0 == strcmp(token.string, "union"))) {
ParsedType type = { 0 };
type.isStruct = 0 == strcmp(token.string, "struct");
type.isUnion = 0 == strcmp(token.string, "union");
type.cName = NextString(&parse);
type.rfName = NextString(&parse);
type.opFunction = NextString(&parse);
ExpectToken(&parse, TOKEN_LEFT_BRACE);
while (PeekToken(&parse).type != TOKEN_RIGHT_BRACE) {
ParsedField field = { 0 };
field.rfType = NextString(&parse);
field.cTypeBefore = NextString(&parse);
field.fieldName = NextString(&parse);
if (PeekToken(&parse).type == TOKEN_STRING) {
field.cTypeAfter = NextString(&parse);
}
ParseAdditionalFieldInformation(&parse, &field);
ExpectToken(&parse, TOKEN_SEMICOLON);
arrput(type.fields, field);
}
ExpectToken(&parse, TOKEN_RIGHT_BRACE);
ExpectToken(&parse, TOKEN_SEMICOLON);
arrput(parsedTypes, type);
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "type")) {
ParsedType type = { 0 };
type.isCustom = true;
type.rfName = NextString(&parse);
type.opFunction = NextString(&parse);
ExpectToken(&parse, TOKEN_SEMICOLON);
arrput(parsedTypes, type);
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "enum")) {
ParsedType type = { 0 };
type.isEnum = true;
type.rfName = NextString(&parse);
type.opFunction = NextString(&parse);
ExpectToken(&parse, TOKEN_LEFT_BRACE);
while (PeekToken(&parse).type != TOKEN_RIGHT_BRACE) {
ParsedField field = { 0 };
field.fieldName = NextString(&parse);
ParseAdditionalFieldInformation(&parse, &field);
ExpectToken(&parse, TOKEN_SEMICOLON);
arrput(type.fields, field);
}
ExpectToken(&parse, TOKEN_RIGHT_BRACE);
ExpectToken(&parse, TOKEN_SEMICOLON);
arrput(parsedTypes, type);
} else {
fprintf(stderr, "error: unexpected token at root on line %d\n", parse.line);
exit(1);
}
}
// Output C type declarations.
for (uintptr_t i = 0; i < arrlenu(parsedTypes); i++) {
ParsedType *type = parsedTypes + i;
if (type->isCustom) {
continue;
} else if (type->isEnum) {
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
ParsedField *field = type->fields + j;
printf("#define %s (%d)\n", field->fieldName, (int) j);
}
printf("\n");
continue;
}
printf("typedef struct %s {\n", type->cName);
const char *indent = "\t";
if (type->isUnion) {
printf("\tuint32_t tag;\n\n\tunion {\n");
indent = "\t\t";
}
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
ParsedField *field = type->fields + j;
printf("%s%s %s %s;\n", indent, field->cTypeBefore, field->fieldName, field->cTypeAfter ? field->cTypeAfter : "");
}
if (type->isUnion) {
printf("\t};\n");
}
printf("} %s;\n\n", type->cName);
}
// Forward-declare op functions.
for (uintptr_t i = 0; i < arrlenu(parsedTypes); i++) {
ParsedType *type = parsedTypes + i;
printf("void %s(RfState *state, RfItem *item, void *pointer);\n", type->opFunction);
}
// Output reflect type information.
for (uintptr_t i = 0; i < arrlenu(parsedTypes); i++) {
ParsedType *type = parsedTypes + i;
printf("#ifdef REFLECT_IMPLEMENTATION\n");
printf("RfType %s = {\n", type->rfName);
printf("\t.op = %s,\n\t.cName = \"%s\",\n\t.fieldCount = %d,\n", type->opFunction, type->cName, (int) arrlen(type->fields));
if (arrlenu(type->fields)) {
printf("\n\t.fields = (RfField []) {\n");
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
ParsedField *field = type->fields + j;
if (type->isEnum) {
printf("\t\t{ .cName = \"%s\", ", field->fieldName);
} else {
printf("\t\t{ .item.type = &%s, .item.byteCount = RF_SIZE_OF(%s, %s), .cName = \"%s\", .offset = offsetof(%s, %s), ",
field->rfType, type->cName, field->fieldName, field->fieldName, type->cName, field->fieldName);
}
printf(".firstVersion = %d, .lastVersion = %d, .flagsInclude = 0", field->firstVersion, field->lastVersion);
for (uintptr_t k = 0; k < arrlenu(field->flagsInclude); k++) {
printf(" | %s", field->flagsInclude[k]);
}
printf(", .flagsExclude = 0");
for (uintptr_t k = 0; k < arrlenu(field->flagsExclude); k++) {
printf(" | %s", field->flagsExclude[k]);
}
if (field->optionsType) {
printf(", .item.options = &(%s) { %s }", field->optionsType, field->optionsBlock);
}
printf(" },\n");
}
printf("\t},\n");
}
printf("};\n\n");
printf("#else\nextern RfType %s;\n#endif\n", type->rfName);
if (!type->isEnum) {
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
ParsedField *field = type->fields + j;
printf("#define %s_%s (%d)\n", type->cName, field->fieldName, (int) j);
}
}
}
return 0;
}