header generator: analysis of structs

This commit is contained in:
nakst 2022-02-08 21:07:50 +00:00
parent 4224a1b670
commit 318624a1dc
8 changed files with 417 additions and 349 deletions

View File

@ -695,9 +695,9 @@ void AddREPLResult(ExecutionContext *context, EsElement *parent, Node *type, Val
EsPanel *table = EsPanelCreate(parent, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL | ES_PANEL_TABLE | ES_PANEL_H_SCROLL_AUTO, EsStyleIntern(&styleTable));
EsPanelSetBands(table, context->heap[listEntry->list[0].i].fieldCount);
EsPanelTableAddBandDecorator(table, { .index = 0, .repeatEvery = 0, .axis = 1, .appearance = &styleAppearanceRowHeader });
EsPanelTableAddBandDecorator(table, { .index = 1, .repeatEvery = 2, .axis = 1, .appearance = &styleAppearanceRowEven });
EsPanelTableAddBandDecorator(table, { .index = 2, .repeatEvery = 2, .axis = 1, .appearance = &styleAppearanceRowOdd });
EsPanelTableAddBandDecorator(table, { .index = 0, .repeatEvery = 0, .axis = 1, .appearance = styleAppearanceRowHeader });
EsPanelTableAddBandDecorator(table, { .index = 1, .repeatEvery = 2, .axis = 1, .appearance = styleAppearanceRowEven });
EsPanelTableAddBandDecorator(table, { .index = 2, .repeatEvery = 2, .axis = 1, .appearance = styleAppearanceRowOdd });
{
Node *field = type->firstChild->firstChild;

View File

@ -104,6 +104,18 @@ struct EsBundle {
ptrdiff_t bytes;
};
struct SystemConfigurationItem {
char *key, *value;
size_t keyBytes, valueBytes;
};
struct SystemConfigurationGroup {
char *section, *sectionClass;
size_t sectionBytes, sectionClassBytes;
SystemConfigurationItem *items;
size_t itemCount;
};
const EsBundle bundleDefault = {
.base = (const BundleHeader *) BUNDLE_FILE_MAP_ADDRESS,
.bytes = -1,
@ -183,7 +195,7 @@ struct APIInstance {
};
struct {
Array<EsSystemConfigurationGroup> systemConfigurationGroups;
Array<SystemConfigurationGroup> systemConfigurationGroups;
EsMutex systemConfigurationMutex;
EsHandle desktopRequestPipe, desktopResponsePipe;
@ -236,11 +248,11 @@ EsFileStore *FileStoreCreateFromHandle(EsHandle handle);
void FileStoreCloseHandle(EsFileStore *fileStore);
EsError NodeOpen(const char *path, size_t pathBytes, uint32_t flags, _EsNodeInformation *node);
const char *EnumLookupNameFromValue(const EnumString *array, int value);
EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, bool createIfNeeded = false);
EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptrdiff_t sectionBytes, bool createIfNeeded = false);
SystemConfigurationItem *SystemConfigurationGetItem(SystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, bool createIfNeeded = false);
SystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptrdiff_t sectionBytes, bool createIfNeeded = false);
uint8_t *ApplicationStartupInformationToBuffer(const _EsApplicationStartupInformation *information, size_t *dataBytes = nullptr);
char *SystemConfigurationGroupReadString(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, size_t *valueBytes = nullptr);
int64_t SystemConfigurationGroupReadInteger(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, int64_t defaultValue = 0);
char *SystemConfigurationGroupReadString(SystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, size_t *valueBytes = nullptr);
int64_t SystemConfigurationGroupReadInteger(SystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, int64_t defaultValue = 0);
bool NodeFindMountPoint(const char *prefix, size_t prefixBytes, EsMountPoint *result, bool mutexTaken);
EsError MountPointAdd(const char *prefix, size_t prefixBytes, EsHandle base, bool addedByApplication);
EsWindow *WindowFromWindowID(EsObjectID id);
@ -284,7 +296,7 @@ EsMessageDevice *EsDeviceEnumerate(size_t *count) {
return result;
}
EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, bool createIfNeeded) {
SystemConfigurationItem *SystemConfigurationGetItem(SystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, bool createIfNeeded) {
if (keyBytes == -1) keyBytes = EsCStringLength(key);
for (uintptr_t i = 0; i < group->itemCount; i++) {
@ -294,14 +306,14 @@ EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup
}
if (createIfNeeded) {
EsSystemConfigurationItem item = {};
SystemConfigurationItem item = {};
item.key = (char *) EsHeapAllocate(keyBytes, false);
if (!item.key) return nullptr;
item.keyBytes = keyBytes;
EsMemoryCopy(item.key, key, keyBytes);
Array<EsSystemConfigurationItem> items = { group->items };
EsSystemConfigurationItem *_item = items.Add(item);
Array<SystemConfigurationItem> items = { group->items };
SystemConfigurationItem *_item = items.Add(item);
group->items = items.array;
if (_item) {
@ -315,7 +327,7 @@ EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup
return nullptr;
}
EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptrdiff_t sectionBytes, bool createIfNeeded) {
SystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptrdiff_t sectionBytes, bool createIfNeeded) {
if (sectionBytes == -1) sectionBytes = EsCStringLength(section);
for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) {
@ -326,12 +338,12 @@ EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptr
}
if (createIfNeeded) {
EsSystemConfigurationGroup group = {};
SystemConfigurationGroup group = {};
group.section = (char *) EsHeapAllocate(sectionBytes, false);
if (!group.section) return nullptr;
group.sectionBytes = sectionBytes;
EsMemoryCopy(group.section, section, sectionBytes);
EsSystemConfigurationGroup *_group = api.systemConfigurationGroups.Add(group);
SystemConfigurationGroup *_group = api.systemConfigurationGroups.Add(group);
if (_group) {
return _group;
@ -343,8 +355,8 @@ EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptr
return nullptr;
}
char *SystemConfigurationGroupReadString(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, size_t *valueBytes) {
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, key, keyBytes);
char *SystemConfigurationGroupReadString(SystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, size_t *valueBytes) {
SystemConfigurationItem *item = SystemConfigurationGetItem(group, key, keyBytes);
if (!item) { if (valueBytes) *valueBytes = 0; return nullptr; }
if (valueBytes) *valueBytes = item->valueBytes;
char *copy = (char *) EsHeapAllocate(item->valueBytes + 1, false);
@ -354,8 +366,8 @@ char *SystemConfigurationGroupReadString(EsSystemConfigurationGroup *group, cons
return copy;
}
int64_t SystemConfigurationGroupReadInteger(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, int64_t defaultValue) {
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, key, keyBytes);
int64_t SystemConfigurationGroupReadInteger(SystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, int64_t defaultValue) {
SystemConfigurationItem *item = SystemConfigurationGetItem(group, key, keyBytes);
if (!item) return defaultValue;
return EsIntegerParse(item->value, item->valueBytes);
}
@ -363,7 +375,7 @@ int64_t SystemConfigurationGroupReadInteger(EsSystemConfigurationGroup *group, c
char *EsSystemConfigurationReadString(const char *section, ptrdiff_t sectionBytes, const char *key, ptrdiff_t keyBytes, size_t *valueBytes) {
EsMutexAcquire(&api.systemConfigurationMutex);
EsDefer(EsMutexRelease(&api.systemConfigurationMutex));
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(section, sectionBytes);
SystemConfigurationGroup *group = SystemConfigurationGetGroup(section, sectionBytes);
if (!group) { if (valueBytes) *valueBytes = 0; return nullptr; }
return SystemConfigurationGroupReadString(group, key, keyBytes, valueBytes);
}
@ -371,7 +383,7 @@ char *EsSystemConfigurationReadString(const char *section, ptrdiff_t sectionByte
int64_t EsSystemConfigurationReadInteger(const char *section, ptrdiff_t sectionBytes, const char *key, ptrdiff_t keyBytes, int64_t defaultValue) {
EsMutexAcquire(&api.systemConfigurationMutex);
EsDefer(EsMutexRelease(&api.systemConfigurationMutex));
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(section, sectionBytes);
SystemConfigurationGroup *group = SystemConfigurationGetGroup(section, sectionBytes);
if (!group) return defaultValue;
return SystemConfigurationGroupReadInteger(group, key, keyBytes, defaultValue);
}
@ -386,7 +398,7 @@ void SystemConfigurationUnload() {
EsHeapFree(api.systemConfigurationGroups[i].section);
EsHeapFree(api.systemConfigurationGroups[i].sectionClass);
Array<EsSystemConfigurationItem> items = { api.systemConfigurationGroups[i].items };
Array<SystemConfigurationItem> items = { api.systemConfigurationGroups[i].items };
items.Free();
}
@ -400,11 +412,11 @@ void SystemConfigurationLoad(const char *file, size_t fileBytes) {
s.buffer = (char *) file;
s.bytes = fileBytes;
EsSystemConfigurationGroup *group = nullptr;
SystemConfigurationGroup *group = nullptr;
while (EsINIParse(&s)) {
if (!s.keyBytes) {
EsSystemConfigurationGroup _group = {};
SystemConfigurationGroup _group = {};
api.systemConfigurationGroups.Add(_group);
group = &api.systemConfigurationGroups.Last();
group->section = (char *) EsHeapAllocate(s.sectionBytes, false);
@ -412,13 +424,13 @@ void SystemConfigurationLoad(const char *file, size_t fileBytes) {
group->sectionClass = (char *) EsHeapAllocate(s.sectionClassBytes, false);
EsMemoryCopy(group->sectionClass, s.sectionClass, (group->sectionClassBytes = s.sectionClassBytes));
} else if (group) {
EsSystemConfigurationItem item = {};
SystemConfigurationItem item = {};
item.key = (char *) EsHeapAllocate(s.keyBytes, false);
EsMemoryCopy(item.key, s.key, (item.keyBytes = s.keyBytes));
item.value = (char *) EsHeapAllocate(s.valueBytes + 1, false);
item.value[s.valueBytes] = 0;
EsMemoryCopy(item.value, s.value, (item.valueBytes = s.valueBytes));
Array<EsSystemConfigurationItem> items = { group->items };
Array<SystemConfigurationItem> items = { group->items };
items.Add(item);
group->items = items.array;
group->itemCount++;

View File

@ -2463,7 +2463,7 @@ void ConfigurationLoadApplications() {
for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) {
// Load information about installed applications.
EsSystemConfigurationGroup *group = &api.systemConfigurationGroups[i];
SystemConfigurationGroup *group = &api.systemConfigurationGroups[i];
if (0 != EsStringCompareRaw(group->sectionClass, group->sectionClassBytes, EsLiteral("application"))) {
continue;
@ -2523,7 +2523,7 @@ void ConfigurationWriteSectionsToBuffer(const char *sectionClass, const char *se
EsMutexAcquire(&api.systemConfigurationMutex);
for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) {
EsSystemConfigurationGroup *group = &api.systemConfigurationGroups[i];
SystemConfigurationGroup *group = &api.systemConfigurationGroups[i];
if ((sectionClass && EsStringCompareRaw(group->sectionClass, group->sectionClassBytes, sectionClass, -1))
|| (section && EsStringCompareRaw(group->section, group->sectionBytes, section, -1))) {
@ -2537,7 +2537,7 @@ void ConfigurationWriteSectionsToBuffer(const char *sectionClass, const char *se
EsBufferWrite(pipe, buffer, bytes);
for (uintptr_t i = 0; i < group->itemCount; i++) {
EsSystemConfigurationItem *item = group->items + i;
SystemConfigurationItem *item = group->items + i;
if ((!item->keyBytes || item->key[0] == ';') && !includeComments) {
continue;

View File

@ -3202,8 +3202,8 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
bounds.b = client.b - panel->style->insets.b;
}
EsDrawRectangle(message->painter, bounds, decorator.appearance->backgroundColor,
decorator.appearance->borderColor, decorator.appearance->borderSize);
EsDrawRectangle(message->painter, bounds, decorator.appearance.backgroundColor,
decorator.appearance.borderColor, decorator.appearance.borderSize);
if (!decorator.repeatEvery) break;
}
}

View File

@ -1193,7 +1193,7 @@ struct EsBuffer {
void *context;
EsFileStore *fileStore;
bool error, canGrow;
};
} @opaque();
struct EsElementPublic {
EsElementCallback messageUser;
@ -1205,36 +1205,36 @@ struct EsElementPublic {
EsWindow *window;
ES_INSTANCE_TYPE *instance;
uint64_t flags; // Bits 0-31: specific to the type of element; bits 32-63: common to all elements.
};
} @opaque();
private struct EsBatchCall {
EsSyscallType index;
bool stopBatchIfError;
union { uintptr_t argument0, returnValue; };
uintptr_t argument1, argument2, argument3;
}
};
struct EsThreadInformation {
EsHandle handle;
EsObjectID tid;
}
};
struct EsProcessInformation {
EsHandle handle;
uintptr_t pid;
EsThreadInformation mainThread;
}
};
struct EsUniqueIdentifier {
// Don't mess with this structure, it's used in filesystems.
uint8_t d[16];
}
};
struct EsFileInformation {
EsHandle handle;
EsFileOffset size;
EsError error;
}
};
struct EsDirectoryChild {
char name[ES_MAX_DIRECTORY_CHILD_NAME_LENGTH];
@ -1242,66 +1242,66 @@ struct EsDirectoryChild {
EsNodeType type;
EsFileOffsetDifference fileSize; // -1 if unsupported.
EsFileOffsetDifference directoryChildren; // ES_DIRECTORY_CHILDREN_UNKNOWN if unsupported.
}
};
struct EsPoint {
int32_t x;
int32_t y;
}
};
struct EsRectangle {
int32_t l; // Inclusive.
int32_t r; // Exclusive.
int32_t t; // Inclusive.
int32_t b; // Exclusive.
}
};
struct EsSpinlock {
volatile uint8_t state;
}
};
struct EsMutex {
EsHandle event;
EsSpinlock spinlock;
volatile uint8_t state;
volatile uint32_t queued;
}
};
struct EsCrashReason {
EsFatalError errorCode;
int32_t duringSystemCall;
}
};
struct EsProcessState {
EsCrashReason crashReason;
EsObjectID id;
uint8_t executableState;
uint8_t flags;
}
};
struct EsPainter {
EsRectangle clip;
int32_t offsetX, offsetY, width, height;
void *style;
EsPaintTarget *target;
}
} @opaque();
struct EsDebuggerMessage {
EsHandle process;
EsCrashReason reason;
}
};
struct EsSnapshotProcessesItem {
int64_t pid, memoryUsage, cpuTimeSlices, idleTimeSlices, handleCount, threadCount;
char name[ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH];
uint8_t nameBytes;
bool isKernel;
}
};
struct EsSnapshotProcesses {
size_t count;
EsSnapshotProcessesItem processes[];
}
};
struct EsProcessCreateData {
EsHandle systemData;
@ -1329,7 +1329,7 @@ struct EsProcessCreationArguments {
EsProcessCreateData data;
uint32_t flags;
uint64_t permissions;
};
} @array_in(handles, handleCount) @array_in(handleModes, handleCount);
struct EsInstance {
// Read-only variables.
@ -1339,12 +1339,12 @@ struct EsInstance {
// Read-write.
EsInstanceCallback callback;
};
} @opaque();
struct EsPanelBand {
int preferredSize, minimumSize, maximumSize;
int push, pull; // Similar to flex-grow and flex-shrink from CSS.
}
};
struct EsThemeMetrics {
uint64_t mask;
@ -1380,7 +1380,7 @@ struct EsFont {
EsFontFamily family;
uint8_t weight;
uint8_t flags;
}
};
struct EsTextStyle {
// TODO Indicating RTL/vertical writing modes.
@ -1434,7 +1434,7 @@ struct EsCommand {
EsCString cKeyboardShortcut;
EsGeneric data;
STRING title;
};
} @opaque();
struct EsApplicationStartupRequest {
int64_t id;
@ -1456,19 +1456,7 @@ private struct _EsApplicationStartupInformation {
struct EsINIState {
char *buffer, *sectionClass, *section, *key, *value;
size_t bytes, sectionClassBytes, sectionBytes, keyBytes, valueBytes;
};
struct EsSystemConfigurationItem {
char *key, *value;
size_t keyBytes, valueBytes;
};
struct EsSystemConfigurationGroup {
char *section, *sectionClass;
size_t sectionBytes, sectionClassBytes;
EsSystemConfigurationItem *items;
size_t itemCount;
};
} @opaque();
struct EsAnalogInput {
uint8_t x, y, z;
@ -1502,7 +1490,7 @@ struct EsAddress {
uint8_t d[20];
};
};
} @opaque();
struct EsConnection {
EsAddress address;
@ -1521,7 +1509,7 @@ struct EsConnection {
uintptr_t sendWritePointer;
EsHandle handle;
};
} @opaque();
struct EsFileMenuSettings {
};
@ -1682,7 +1670,7 @@ struct EsMessageGetItemData {
int64_t i;
double d;
};
};
} @opaque();
struct EsMessageGetIndent {
EsListViewIndex group;
@ -1797,7 +1785,7 @@ struct EsMessageTabOperation {
EsHandle handle;
union { size_t bytes; bool isSource; };
EsError error;
};
} @opaque();
struct EsMessageDevice {
EsObjectID id;
@ -1880,7 +1868,7 @@ struct EsMessage {
EsMessageDevice device;
EsObjectID embeddedWindowDestroyedID;
};
}
} @opaque();
private struct _EsMessageWithObject {
void *object;
@ -1969,7 +1957,7 @@ private struct EsMountPoint {
struct EsPanelBandDecorator {
uintptr_t index, repeatEvery;
uint8_t axis; // 0 for columns, 1 for rows.
const EsThemeAppearance *appearance; // Pointer must remain valid.
EsThemeAppearance appearance;
};
struct EsCornerRadii {
@ -1999,7 +1987,7 @@ function_pointer void EsWorkCallback(EsGeneric context);
function void EsApplicationStart(ES_INSTANCE_TYPE *instance, const EsApplicationStartupRequest *request) @in(request); // The instance is optional, used only for ES_APPLICATION_STARTUP_IN_SAME_CONTAINER.
function void EsApplicationRunTemporary(STRING path);
function EsHandle EsTakeSystemSnapshot(int type, size_t *bufferSize) @out(bufferSize);
function EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, STRING name = BLANK_STRING) @todo();
function EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, STRING name = BLANK_STRING);
function EsError EsHandleClose(EsHandle handle);
function void EsSystemShowShutdownDialog();
function void EsSystemShutdown(uint32_t action);
@ -2018,14 +2006,14 @@ function uintptr_t EsSystemGetOptimalWorkQueueThreadCount();
function int64_t EsSystemConfigurationReadInteger(STRING section, STRING key, int64_t defaultValue = 0);
function char *EsSystemConfigurationReadString(STRING section, STRING key, size_t *valueBytes = ES_NULL) @out(valueBytes) @heap_buffer_out(return, valueBytes*); // Free with EsHeapFree.
function void EsSystemConfigurationReadFileTypes(EsBuffer *buffer) @opaque(buffer); // Read the "file_type" sections of the system configuration INI to the buffer.
function void EsSystemConfigurationReadFileTypes(EsBuffer *buffer); // Read the "file_type" sections of the system configuration INI to the buffer.
// INI files.
function bool EsINIParse(EsINIState *s) @todo();
function bool EsINIPeek(EsINIState *s) @todo();
function size_t EsINIFormat(EsINIState *s, char *buffer, size_t bytes) @todo();
function void EsINIZeroTerminate(EsINIState *s) @todo();
function bool EsINIParse(EsINIState *s);
function bool EsINIPeek(EsINIState *s);
function size_t EsINIFormat(EsINIState *s, char *buffer, size_t bytes) @native();
function void EsINIZeroTerminate(EsINIState *s);
// File systems.
@ -2069,7 +2057,7 @@ function EsError EsMountPointAdd(STRING prefix, EsHandle base); // The system ma
function bool EsMountPointRemove(STRING prefix); // Returns false if the mount point does not exist. You can only remove mount points you added with EsMountPointAdd.
function void EsOpenDocumentQueryInformation(STRING filePath, EsOpenDocumentInformation *information) @out(information);
function void _EsPathAnnouncePathMoved(STRING oldPath, STRING newPath); // Set oldPathBytes = 0 to make the file manager refresh the path.
function void _EsOpenDocumentEnumerate(EsBuffer *outputBuffer) @opaque(outputBuffer);
function void _EsOpenDocumentEnumerate(EsBuffer *outputBuffer);
function EsMessageDevice *EsDeviceEnumerate(size_t *count) @out(count) @heap_array_out(return, count*); // This must be done with the message mutex acquired. As soon as EsMessageReceived is next called, or the message mutex is released, then the handles in this array are invalid.
function EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, void *dp, void *dq) @native();
@ -2096,15 +2084,15 @@ function bool EsWorkIsExiting();
// Memory.
function const void *EsBufferRead(EsBuffer *buffer, size_t readBytes) @native();
function bool EsBufferReadInto(EsBuffer *buffer, void *destination, size_t readBytes) @buffer_out(destination, readBytes) @opaque(buffer);
function bool EsBufferReadInto(EsBuffer *buffer, void *destination, size_t readBytes) @buffer_out(destination, readBytes);
function const void *EsBufferReadMany(EsBuffer *buffer, size_t a, size_t b) @native();
function int32_t EsBufferReadInt32Endian(EsBuffer *buffer, int32_t errorValue) @opaque(buffer);
function void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes) @buffer_in(source, writeBytes) @opaque(buffer) @todo();
function bool EsBufferWriteInt8(EsBuffer *buffer, int8_t value) @opaque(buffer);
function bool EsBufferWriteInt32Endian(EsBuffer *buffer, int32_t value) @opaque(buffer); // Changes byte order if big endian.
function int32_t EsBufferReadInt32Endian(EsBuffer *buffer, int32_t errorValue);
function void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes) @buffer_in(source, writeBytes) @todo();
function bool EsBufferWriteInt8(EsBuffer *buffer, int8_t value);
function bool EsBufferWriteInt32Endian(EsBuffer *buffer, int32_t value); // Changes byte order if big endian.
function void EsBufferFormat(EsBuffer *buffer, EsCString format, ...) @native(); // Appends.
function void EsBufferFormatV(EsBuffer *buffer, EsCString format, va_list arguments) @native(); // Appends.
function void EsBufferFlushToFileStore(EsBuffer *buffer) @opaque(buffer);
function void EsBufferFlushToFileStore(EsBuffer *buffer);
function EsHandle EsConstantBufferCreate(const void *data, size_t dataBytes, EsHandle targetProcess) @buffer_in(data, dataBytes);
function void EsConstantBufferRead(EsHandle constantBuffer, void *output) @todo();
@ -2174,30 +2162,30 @@ function bool EsColorConvertToHSV(uint32_t color, float *h, float *s, float *v)
function uint32_t EsColorParse(STRING string);
function uint32_t EsColorInterpolate(uint32_t from, uint32_t to, float progress);
function void EsDrawBitmap(EsPainter *painter, EsRectangle region, const uint32_t *bits, uintptr_t stride, uint16_t mode) @opaque(painter) @matrix_in(bits, region, stride); // OR mode with alpha.
function void EsDrawBitmapScaled(EsPainter *painter, EsRectangle destinationRegion, EsRectangle sourceRegion, const uint32_t *bits, uintptr_t stride, uint16_t alpha) @opaque(painter) @matrix_in(bits, sourceRegion, stride); // Set alpha to 0xFFFF if source is opaque.
function void EsDrawBlock(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor) @opaque(painter);
function void EsDrawClear(EsPainter *painter, EsRectangle bounds) @opaque(painter);
function void EsDrawContent(EsPainter *painter, EsElement *element, EsRectangle rectangle, STRING text, uint32_t iconID = 0, uint32_t flags = ES_FLAGS_DEFAULT, const EsTextSelection *selectionProperties = ES_NULL) @opaque(painter) @in(selectionProperties);
function void EsDrawInvert(EsPainter *painter, EsRectangle bounds) @opaque(painter);
function void EsDrawLine(EsPainter *painter, const float *vertices, size_t vertexCount, EsDeviceColor color, float width, uint32_t flags) @opaque(painter) @array_in(vertices, vertexCount); // Vertices are pairs of x,y coordinates.
function void EsDrawRectangle(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor, EsDeviceColor borderColor, EsRectangle borderSize) @opaque(painter);
function void EsDrawRoundedRectangle(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor, EsDeviceColor borderColor, EsRectangle borderSize, EsCornerRadii cornerRadii) @opaque(painter);
function bool EsDrawStandardIcon(EsPainter *painter, uint32_t id, int size, EsRectangle region, EsDeviceColor color) @opaque(painter);
function void EsDrawPaintTarget(EsPainter *painter, EsPaintTarget *source, EsRectangle destinationRegion, EsRectangle sourceRegion, uint8_t alpha) @opaque(painter);
function void EsDrawText(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, const EsRectangle *clip = ES_NULL, const EsTextSelection *selectionProperties = ES_NULL) @opaque(painter) @in(selectionProperties) @in(clip);
function void EsDrawTextSimple(EsPainter *painter, EsElement *element, EsRectangle bounds, STRING stringBytes, EsTextStyle style, uint32_t flags = ES_FLAGS_DEFAULT) @opaque(painter);
function void EsDrawTextThemed(EsPainter *painter, EsElement *element, EsRectangle bounds, STRING stringBytes, EsStyleID style, uint32_t flags = ES_FLAGS_DEFAULT) @opaque(painter); // The style must be one of the ES_STYLE_TEXT_... styles.
function void EsDrawTextLayers(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, const EsTextSelection *selectionProperties = ES_NULL) @opaque(painter) @in(selectionProperties);
function void EsDrawVectorFile(EsPainter *painter, EsRectangle bounds, const void *data, size_t dataBytes) @opaque(painter) @buffer_in(data, dataBytes);
function void EsDrawBitmap(EsPainter *painter, EsRectangle region, const uint32_t *bits, uintptr_t stride, uint16_t mode) @matrix_in(bits, region, stride); // OR mode with alpha.
function void EsDrawBitmapScaled(EsPainter *painter, EsRectangle destinationRegion, EsRectangle sourceRegion, const uint32_t *bits, uintptr_t stride, uint16_t alpha) @matrix_in(bits, sourceRegion, stride); // Set alpha to 0xFFFF if source is opaque.
function void EsDrawBlock(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor);
function void EsDrawClear(EsPainter *painter, EsRectangle bounds);
function void EsDrawContent(EsPainter *painter, EsElement *element, EsRectangle rectangle, STRING text, uint32_t iconID = 0, uint32_t flags = ES_FLAGS_DEFAULT, const EsTextSelection *selectionProperties = ES_NULL) @in(selectionProperties);
function void EsDrawInvert(EsPainter *painter, EsRectangle bounds);
function void EsDrawLine(EsPainter *painter, const float *vertices, size_t vertexCount, EsDeviceColor color, float width, uint32_t flags) @array_in(vertices, vertexCount); // Vertices are pairs of x,y coordinates.
function void EsDrawRectangle(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor, EsDeviceColor borderColor, EsRectangle borderSize);
function void EsDrawRoundedRectangle(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor, EsDeviceColor borderColor, EsRectangle borderSize, EsCornerRadii cornerRadii);
function bool EsDrawStandardIcon(EsPainter *painter, uint32_t id, int size, EsRectangle region, EsDeviceColor color);
function void EsDrawPaintTarget(EsPainter *painter, EsPaintTarget *source, EsRectangle destinationRegion, EsRectangle sourceRegion, uint8_t alpha);
function void EsDrawText(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, const EsRectangle *clip = ES_NULL, const EsTextSelection *selectionProperties = ES_NULL) @in(selectionProperties) @in(clip);
function void EsDrawTextSimple(EsPainter *painter, EsElement *element, EsRectangle bounds, STRING stringBytes, EsTextStyle style, uint32_t flags = ES_FLAGS_DEFAULT);
function void EsDrawTextThemed(EsPainter *painter, EsElement *element, EsRectangle bounds, STRING stringBytes, EsStyleID style, uint32_t flags = ES_FLAGS_DEFAULT); // The style must be one of the ES_STYLE_TEXT_... styles.
function void EsDrawTextLayers(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, const EsTextSelection *selectionProperties = ES_NULL) @in(selectionProperties);
function void EsDrawVectorFile(EsPainter *painter, EsRectangle bounds, const void *data, size_t dataBytes) @buffer_in(data, dataBytes);
function uint32_t EsIconIDFromString(STRING string = BLANK_STRING);
function uint32_t EsIconIDFromDriveType(uint8_t driveType);
function uint8_t *EsImageLoad(const void *file, size_t fileSize, uint32_t *width, uint32_t *height, int imageChannels) @out(width) @out(height) @buffer_in(file, fileSize) @heap_matrix_out(return, width*, height*);
function EsRectangle EsPainterBoundsClient(EsPainter *painter) @opaque(painter);
function EsRectangle EsPainterBoundsInset(EsPainter *painter) @opaque(painter);
function EsRectangle EsPainterBoundsClient(EsPainter *painter);
function EsRectangle EsPainterBoundsInset(EsPainter *painter);
function void EsPaintTargetClear(EsPaintTarget *target);
function void EsPaintTargetEndDirectAccess(EsPaintTarget *target);
@ -2226,13 +2214,13 @@ function EsStyleID EsStyleIntern(const EsStyle *style) @in(style); // Once a sty
// Networking.
function EsError EsAddressResolve(STRING domain, uint32_t flags, EsAddress *address) @todo();
function void EsConnectionClose(EsConnection *connection) @todo();
function void EsConnectionNotify(EsConnection *connection) @todo();
function EsError EsConnectionOpen(EsConnection *connection, uint32_t flags) @todo();
function void EsConnectionPoll(EsConnection *connection) @todo();
function EsError EsConnectionRead(EsConnection *connection, void *buffer, size_t bufferBytes, size_t *bytesRead) @buffer_out(buffer, bufferBytes) @out(bytesRead) @todo(); // Returns the number of bytes copied into the buffer.
function EsError EsConnectionWriteSync(EsConnection *connection, const void *data, size_t dataBytes) @todo(); // Waits until all the data has been written into the send buffer. This does *not* flush the send buffer.
function EsError EsAddressResolve(STRING domain, uint32_t flags, EsAddress *address);
function void EsConnectionClose(EsConnection *connection);
function void EsConnectionNotify(EsConnection *connection);
function EsError EsConnectionOpen(EsConnection *connection, uint32_t flags);
function void EsConnectionPoll(EsConnection *connection);
function EsError EsConnectionRead(EsConnection *connection, void *buffer, size_t bufferBytes, size_t *bytesRead) @buffer_out(buffer, bufferBytes) @out(bytesRead); // Returns the number of bytes copied into the buffer.
function EsError EsConnectionWriteSync(EsConnection *connection, const void *data, size_t dataBytes) @buffer_in(data, dataBytes); // Waits until all the data has been written into the send buffer. This does *not* flush the send buffer.
// Input.
@ -2391,12 +2379,12 @@ function ES_INSTANCE_TYPE *EsUndoGetInstance(EsUndoManager *manager);
// Instances and commands.
function void EsCommandAddButton(EsCommand *command, EsButton *button) @opaque(command);
function EsCommand *EsCommandByID(ES_INSTANCE_TYPE *instance, uint32_t stableID) @opaque(return);
function EsCommand *EsCommandRegister(EsCommand *command, ES_INSTANCE_TYPE *instance, STRING title, EsCommandCallback callback, uint32_t stableID, EsCString cDefaultKeyboardShortcut = ES_NULL, bool enabled = false) @opaque(return) @opaque(command) @todo(); // IDs >= 0xF0000000 reserved by the system.
function void EsCommandSetCallback(EsCommand *command, EsCommandCallback callback) @opaque(command) @todo();
function void EsCommandSetDisabled(EsCommand *command, bool disabled) @opaque(command);
function void EsCommandSetCheck(EsCommand *command, EsCheckState check, bool sendUpdatedMessage) @opaque(command);
function void EsCommandAddButton(EsCommand *command, EsButton *button);
function EsCommand *EsCommandByID(ES_INSTANCE_TYPE *instance, uint32_t stableID);
function EsCommand *EsCommandRegister(EsCommand *command, ES_INSTANCE_TYPE *instance, STRING title, EsCommandCallback callback, uint32_t stableID, EsCString cDefaultKeyboardShortcut = ES_NULL, bool enabled = false) @todo(); // IDs >= 0xF0000000 reserved by the system.
function void EsCommandSetCallback(EsCommand *command, EsCommandCallback callback) @todo();
function void EsCommandSetDisabled(EsCommand *command, bool disabled);
function void EsCommandSetCheck(EsCommand *command, EsCheckState check, bool sendUpdatedMessage);
function void EsInstanceOpenReference(ES_INSTANCE_TYPE *_instance);
function void EsInstanceCloseReference(ES_INSTANCE_TYPE *_instance); // Sends ES_MSG_INSTANCE_DESTROY when all references closed.
@ -2419,14 +2407,14 @@ function size_t EsMessageGetInputText(EsMessage *message, char *buffer) @todo();
function void EsMessageMutexAcquire();
function void EsMessageMutexCheck();
function void EsMessageMutexRelease();
function EsError EsMessagePost(EsElement *target, EsMessage *message) @todo();
function EsError EsMessagePostRemote(EsHandle process, EsMessage *message) @todo();
function int EsMessageSend(EsElement *object, EsMessage *message) @todo();
function EsMessage *EsMessageReceive() @todo();
function EsError EsMessagePost(EsElement *target, EsMessage *message);
function EsError EsMessagePostRemote(EsHandle process, EsMessage *message);
function int EsMessageSend(EsElement *object, EsMessage *message);
function EsMessage *EsMessageReceive();
// User interface elements.
function void EsElementDraw(EsElement *element, EsPainter *painter) @opaque(painter); // Actually draw an element onto a painter.
function void EsElementDraw(EsElement *element, EsPainter *painter); // Actually draw an element onto a painter.
function void EsElementFocus(EsElement *element, uint32_t flags = ES_FLAGS_DEFAULT);
function bool EsElementIsFocused(EsElement *element);
function void EsElementSetDisabled(EsElement *element, bool disabled = true);
@ -2435,7 +2423,7 @@ function bool EsElementIsHidden(EsElement *element);
function void EsElementSetCallback(EsElement *element, EsElementCallback callback) @todo();
function void EsElementGetSize(EsElement *element, int *width, int *height) @out(width) @out(height);
function void EsElementRepaint(EsElement *element, const EsRectangle *region = ES_NULL) @in(region); // Mark an element to be repainted. If region is null, then the whole element is repainted.
function void EsElementRepaintForScroll(EsElement *element, EsMessage *message, EsRectangle border) @todo(); // Minimal repaint for ES_MSG_SCROLL_X/Y.
function void EsElementRepaintForScroll(EsElement *element, EsMessage *message, EsRectangle border); // Minimal repaint for ES_MSG_SCROLL_X/Y.
function void EsElementRelayout(EsElement *element);
function void EsElementSetCellRange(EsElement *element, int xFrom, int yFrom, int xTo = -1, int yTo = -1); // Use only if the parent is a ES_PANEL_TABLE.
function EsRectangle EsElementGetInsets(EsElement *element);
@ -2460,7 +2448,7 @@ function EsRectangle EsElementGetScreenBounds(EsElement *element, bool client =
function EsElement *EsCustomElementCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, EsStyleID style = 0);
function EsScrollView *EsCustomScrollViewCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, EsStyleID style = 0);
function int EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message) @todo(); // You *must* call this *before* handling any messages. If this returns non-zero, immediately return that value from your message handler.
function int EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message); // You *must* call this *before* handling any messages. If this returns non-zero, immediately return that value from your message handler.
function void EsScrollViewSetup(EsScrollView *view, uint8_t xMode, uint8_t yMode, uint16_t flags);
function void EsScrollViewSetPosition(EsScrollView *view, int axis, double newPosition, bool sendMovedMessage = true);
function void EsScrollViewRefresh(EsScrollView *view);
@ -2483,7 +2471,7 @@ function void EsWindowAddSizeAlternative(EsWindow *window, EsElement *small, EsE
function EsMenu *EsMenuCreate(EsElement *source, uint64_t flags = ES_FLAGS_DEFAULT);
function EsElement *EsMenuGetSource(EsMenu *menu); // TODO Public property?
function void EsMenuAddItem(EsMenu *menu, uint64_t flags, STRING label = BLANK_STRING, EsMenuCallback callback = ES_NULL, EsGeneric context = ES_NULL) @todo();
function void EsMenuAddCommand(EsMenu *menu, uint64_t flags, STRING label, EsCommand *command) @opaque(command);
function void EsMenuAddCommand(EsMenu *menu, uint64_t flags, STRING label, EsCommand *command);
function void EsMenuAddSeparator(EsMenu *menu);
function void EsMenuNextColumn(EsMenu *menu, uint64_t flags = ES_FLAGS_DEFAULT);
function void EsMenuShow(EsMenu *menu, int fixedWidth = 0, int fixedHeight = 0);
@ -2555,7 +2543,7 @@ function EsCanvasPane *EsCanvasPaneCreate(EsElement *parent, uint64_t flags = ES
function void EsPanelSetBands(EsPanel *panel, size_t columnCount, size_t rowCount = 0, const EsPanelBand *columns = ES_NULL, const EsPanelBand *rows = ES_NULL) @array_in(columns, columnCount) @array_in(rows, rowCount);
function void EsPanelSetBandsAll(EsPanel *panel, const EsPanelBand *column = ES_NULL, const EsPanelBand *row = ES_NULL) @in(column) @in(row); // Set all the columns/rows to have the same properties. This must be called after the final number of bands has been determined/set!
function void EsPanelTableSetChildCells(EsPanel *panel); // Automatically set the child cells for items in a table. This is only necessary if the number of columns/rows is changed after adding items to a table.
function void EsPanelTableAddBandDecorator(EsPanel *panel, EsPanelBandDecorator decorator) @todo();
function void EsPanelTableAddBandDecorator(EsPanel *panel, EsPanelBandDecorator decorator);
function void EsPanelSwitchTo(EsPanel *panel, EsElement *targetChild, EsTransitionType transitionType, uint32_t flags = ES_FLAGS_DEFAULT, float timeMultiplier = 1); // TODO More customization of transitions?
function void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier = 1); // TODO More customization.
@ -2572,7 +2560,7 @@ function void EsIconDisplaySetIcon(EsIconDisplay *display, uint32_t iconID);
function EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, EsStyleID style = 0);
function void EsImageDisplayLoadBits(EsImageDisplay *display, const uint32_t *bits, size_t width, size_t height, size_t stride) @matrix_in(bits, width, height);
function void EsImageDisplayLoadFromMemory(EsImageDisplay *display, const void *buffer, size_t bufferBytes) @buffer_in(buffer, bufferBytes);
function void EsImageDisplayPaint(EsImageDisplay *display, EsPainter *painter, EsRectangle bounds) @opaque(painter);
function void EsImageDisplayPaint(EsImageDisplay *display, EsPainter *painter, EsRectangle bounds);
function EsTextDisplay *EsTextDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, EsStyleID style = 0, STRING label = BLANK_STRING);
function void EsTextDisplaySetContents(EsTextDisplay *display, STRING contents = BLANK_STRING);

View File

@ -125,14 +125,14 @@ bool SettingsPutValue(const char *cConfigurationSection, const char *cConfigurat
newValue = newValueDuplicate;
}
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(cConfigurationSection, -1, true);
SystemConfigurationGroup *group = SystemConfigurationGetGroup(cConfigurationSection, -1, true);
if (!group) {
EsHeapFree(newValue);
return false;
}
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, cConfigurationKey, -1, true);
SystemConfigurationItem *item = SystemConfigurationGetItem(group, cConfigurationKey, -1, true);
if (!item) {
EsHeapFree(newValue);

View File

@ -585,7 +585,7 @@ void FontInitialise() {
EsMutexAcquire(&api.systemConfigurationMutex);
for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) {
EsSystemConfigurationGroup *g = &api.systemConfigurationGroups[i];
SystemConfigurationGroup *g = &api.systemConfigurationGroups[i];
if (0 == EsStringCompareRaw(g->sectionClass, g->sectionClassBytes, EsLiteral("font"))) {
if (0 == EsStringCompareRaw(g->section, g->sectionBytes, EsLiteral(fontManagement.sansName))) {
@ -611,7 +611,7 @@ void FontInitialise() {
entry.id = fontManagement.database.Length();
for (uintptr_t i = 0; i < g->itemCount; i++) {
EsSystemConfigurationItem *item = g->items + i;
SystemConfigurationItem *item = g->items + i;
if (0 == EsStringCompareRaw(item->key, item->keyBytes, EsLiteral("category"))) {
entry.categoryBytes = MinimumInteger(item->valueBytes, sizeof(entry.category));

View File

@ -295,6 +295,54 @@ Entry ParseRecord(bool isUnion) {
return entry;
}
void ParseAnnotationsUntilSemicolon(Entry *entry) {
while (true) {
Token token = NextToken();
if (token.type == TOKEN_SEMICOLON) {
break;
} else if (token.type == TOKEN_ANNOTATE) {
Entry annotation = { 0 };
token = NextToken();
assert(token.type == TOKEN_IDENTIFIER);
annotation.name = TokenToString(token);
token = NextToken();
assert(token.type == TOKEN_LEFT_PAREN);
bool needComma = false;
Entry child = { 0 };
child.name = malloc(256);
child.name[0] = 0;
while (true) {
token = NextToken();
if (token.type == TOKEN_RIGHT_PAREN) {
if (child.name[0]) arrput(annotation.children, child);
break;
} else if (token.type == TOKEN_COMMA) {
if (child.name[0]) arrput(annotation.children, child);
child.name = malloc(256);
child.name[0] = 0;
assert(needComma);
needComma = false;
} else if (token.type == TOKEN_IDENTIFIER) {
strcat(child.name, TokenToString(token));
needComma = true;
} else if (token.type == TOKEN_ASTERISK) {
strcat(child.name, "*");
needComma = true;
} else {
assert(false);
}
}
arrput(entry->annotations, annotation);
} else {
assert(false);
}
}
}
void ParseFile(Entry *root, const char *name) {
if (outputDependencies.ready) {
FilePrintFormat(outputDependencies, "%s\n", name);
@ -368,6 +416,7 @@ void ParseFile(Entry *root, const char *name) {
Entry entry = ParseRecord(false);
entry.isPrivate = isPrivate;
entry.name = TokenToString(structName);
ParseAnnotationsUntilSemicolon(&entry);
arrput(root->children, entry);
} else if (token.type == TOKEN_FUNCTION || token.type == TOKEN_FUNCTION_NOT_IN_KERNEL
|| token.type == TOKEN_FUNCTION_POINTER) {
@ -391,52 +440,7 @@ void ParseFile(Entry *root, const char *name) {
firstVariable = false;
}
while (true) {
token = NextToken();
if (token.type == TOKEN_SEMICOLON) {
break;
} else if (token.type == TOKEN_ANNOTATE) {
Entry annotation = { 0 };
token = NextToken();
assert(token.type == TOKEN_IDENTIFIER);
annotation.name = TokenToString(token);
token = NextToken();
assert(token.type == TOKEN_LEFT_PAREN);
bool needComma = false;
Entry child = { 0 };
child.name = malloc(256);
child.name[0] = 0;
while (true) {
token = NextToken();
if (token.type == TOKEN_RIGHT_PAREN) {
if (child.name[0]) arrput(annotation.children, child);
break;
} else if (token.type == TOKEN_COMMA) {
if (child.name[0]) arrput(annotation.children, child);
child.name = malloc(256);
child.name[0] = 0;
assert(needComma);
needComma = false;
} else if (token.type == TOKEN_IDENTIFIER) {
strcat(child.name, TokenToString(token));
needComma = true;
} else if (token.type == TOKEN_ASTERISK) {
strcat(child.name, "*");
needComma = true;
} else {
assert(false);
}
}
arrput(entry.annotations, annotation);
} else {
assert(false);
}
}
ParseAnnotationsUntilSemicolon(&entry);
arrput(root->children, entry);
} else if (token.type == TOKEN_API_TYPE) {
Token name = NextToken(), parent = NextToken();
@ -1235,15 +1239,242 @@ void OutputZig(Entry *root) {
}
}
int AnalysisResolve(Entry *root, Entry e, Entry **unresolved, Entry *resolved, Entry *annotations) {
assert(e.type == ENTRY_VARIABLE);
if (e.variable.pointer == 0 && (0 == strcmp(e.variable.type, "uint64_t")
|| 0 == strcmp(e.variable.type, "int64_t")
|| 0 == strcmp(e.variable.type, "uint32_t")
|| 0 == strcmp(e.variable.type, "int32_t")
|| 0 == strcmp(e.variable.type, "uint16_t")
|| 0 == strcmp(e.variable.type, "int16_t")
|| 0 == strcmp(e.variable.type, "uint8_t")
|| 0 == strcmp(e.variable.type, "int8_t")
|| 0 == strcmp(e.variable.type, "char")
|| 0 == strcmp(e.variable.type, "size_t")
|| 0 == strcmp(e.variable.type, "intptr_t")
|| 0 == strcmp(e.variable.type, "uintptr_t")
|| 0 == strcmp(e.variable.type, "ptrdiff_t")
|| 0 == strcmp(e.variable.type, "unsigned")
|| 0 == strcmp(e.variable.type, "int")
|| 0 == strcmp(e.variable.type, "long")
|| 0 == strcmp(e.variable.type, "double")
|| 0 == strcmp(e.variable.type, "float")
|| 0 == strcmp(e.variable.type, "void")
|| 0 == strcmp(e.variable.type, "bool")
|| 0 == strcmp(e.variable.type, "EsCString")
|| 0 == strcmp(e.variable.type, "EsGeneric")
|| 0 == strcmp(e.variable.type, "STRING"))) {
return 1;
}
if (e.variable.pointer == 1 && !e.variable.isConst && (0 == strcmp(e.variable.type, "ES_INSTANCE_TYPE"))) {
return 1;
}
for (int k = 0; k < arrlen(root->children); k++) {
if (!root->children[k].name) continue;
if (strcmp(e.variable.type, root->children[k].name)) continue;
if (root->children[k].type == ENTRY_TYPE_NAME && e.variable.pointer == 0) {
return 1;
} else if (root->children[k].type == ENTRY_ENUM && e.variable.pointer == 0) {
return 1;
} else if (root->children[k].type == ENTRY_API_TYPE && e.variable.pointer == 1) {
return 1;
} else if (root->children[k].type == ENTRY_STRUCT) {
bool selfOpaque = false;
for (int i = 0; i < arrlen(root->children[k].annotations); i++) {
if (0 == strcmp(root->children[k].annotations[i].name, "opaque")) {
selfOpaque = true;
}
}
if (selfOpaque && e.variable.pointer == 1) {
return 1;
} else if (!selfOpaque && e.variable.pointer == 0) {
for (int i = 0; i < arrlen(root->children[k].children); i++) {
Entry f = root->children[k].children[i];
assert(f.type == ENTRY_VARIABLE);
char *old = f.name;
f.name = malloc(strlen(e.name) + 1 + strlen(old) + 1);
strcpy(f.name, e.name);
strcat(f.name, "*");
strcat(f.name, old);
arrput(*unresolved, f);
}
return 1;
}
}
}
for (int i = 0; i < arrlen(annotations); i++) {
Entry *annotation = annotations + i;
if (0 == strcmp(annotation->name, "in")
|| 0 == strcmp(annotation->name, "out")
|| 0 == strcmp(annotation->name, "in_out")) {
assert(1 == arrlen(annotation->children));
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer);
assert(e.variable.isConst == (0 == strcmp(annotation->name, "in")));
Entry f = e;
f.name = malloc(strlen(e.name) + 1 + 1);
strcpy(f.name, e.name);
strcat(f.name, "*");
f.variable.pointer--;
arrput(*unresolved, f);
return 1;
}
} else if (0 == strcmp(annotation->name, "buffer_out")
|| 0 == strcmp(annotation->name, "heap_buffer_out")
|| 0 == strcmp(annotation->name, "fixed_buffer_out")
|| 0 == strcmp(annotation->name, "buffer_in")) {
assert(2 == arrlen(annotation->children));
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer && (0 == strcmp(e.variable.type, "void")
|| 0 == strcmp(e.variable.type, "uint8_t")
|| 0 == strcmp(e.variable.type, "char")));
assert(e.variable.isConst == (0 == strcmp(annotation->name, "buffer_in")
|| 0 == strcmp(annotation->name, "fixed_buffer_out")));
bool foundSize = false;
for (int i = 0; i < arrlen(resolved); i++) {
if (0 == strcmp(resolved[i].name, annotation->children[1].name)) {
assert(!resolved[i].variable.pointer && (0 == strcmp(resolved[i].variable.type, "size_t")
|| 0 == strcmp(resolved[i].variable.type, "ptrdiff_t")));
foundSize = true;
}
}
if (!foundSize) {
arrins(*unresolved, 0, e);
return 2;
}
return 1;
}
} else if (0 == strcmp(annotation->name, "heap_array_out")
|| 0 == strcmp(annotation->name, "heap_matrix_out")
|| 0 == strcmp(annotation->name, "array_in")
|| 0 == strcmp(annotation->name, "matrix_in")
|| 0 == strcmp(annotation->name, "matrix_shared")) {
bool matrix = 0 == strcmp(annotation->name, "heap_matrix_out")
|| 0 == strcmp(annotation->name, "matrix_in")
|| 0 == strcmp(annotation->name, "matrix_shared");
bool input = 0 == strcmp(annotation->name, "array_in")
|| 0 == strcmp(annotation->name, "matrix_in");
int children = arrlen(annotation->children);
if (matrix) assert(children == 3 || children == 4); // (width, height) or (width, height, stride) or (rectangle, stride)
else assert(children == 2);
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer);
assert(e.variable.isConst == input);
int foundSize = 1;
for (int j = 1; j < children; j++) {
for (int i = 0; i < arrlen(resolved); i++) {
if (0 == strcmp(resolved[i].name, annotation->children[j].name)) {
assert(!resolved[i].variable.pointer && (0 == strcmp(resolved[i].variable.type, "size_t")
|| 0 == strcmp(resolved[i].variable.type, "ptrdiff_t")
|| 0 == strcmp(resolved[i].variable.type, "uintptr_t")
|| 0 == strcmp(resolved[i].variable.type, "uint32_t")
|| (0 == strcmp(resolved[i].variable.type, "EsRectangle") && matrix && j == 1)));
foundSize++;
break;
}
}
}
if (foundSize != children) {
arrins(*unresolved, 0, e);
return 2;
}
Entry f = e;
f.name = malloc(strlen(e.name) + 2 + 1);
strcpy(f.name, e.name);
strcat(f.name, "[]");
f.variable.pointer--;
arrput(*unresolved, f);
return 1;
}
}
}
return 0;
}
void Analysis(Entry *root) {
// TODO @optional() annotation.
// TODO Discriminated unions.
// TODO Error handling support.
// TODO Smarter errors.
// TODO Fixed sized array based strings in structs.
// TODO Callbacks.
// TODO Array size computation: text run arrays, EsFileWriteAllGather, EsConstantBufferRead.
// TODO Complex types: EsMessage, EsINIState, EsConnection.
// TODO Generating constructors, getters and setters for @opaque() types like EsMessage, EsINIState, EsConnection, etc.
// TODO Check all the annotations have been used.
for (int i = 0; i < arrlen(root->children); i++) {
Entry *entry = root->children + i;
if (entry->isPrivate || entry->type != ENTRY_STRUCT) continue;
Entry *resolved = NULL;
Entry *unresolved = NULL;
bool understood = true;
const char *unresolvableName = NULL;
bool selfOpaque = false;
for (int i = 0; i < arrlen(entry->annotations); i++) {
Entry *annotation = entry->annotations + i;
if (0 == strcmp(annotation->name, "opaque")) {
// Managed languages should treat this structure as opaque.
selfOpaque = true;
}
}
if (!selfOpaque) {
for (int i = 0; i < arrlen(entry->children); i++) {
Entry e = entry->children[i];
if (e.type != ENTRY_VARIABLE) {
assert(e.type == ENTRY_UNION);
unresolvableName = "(union)";
understood = false;
break;
}
arrput(unresolved, e);
}
}
while (understood && arrlen(unresolved)) {
Entry e = arrpop(unresolved);
int result = AnalysisResolve(root, e, &unresolved, resolved, entry->annotations);
if (result == 1) {
arrput(resolved, e);
} else if (result == 0) {
unresolvableName = e.name;
understood = false;
}
}
arrfree(resolved);
arrfree(unresolved);
if (!understood) {
Log("%s %s\n", entry->name, unresolvableName);
}
}
for (int i = 0; i < arrlen(root->children); i++) {
Entry *entry = root->children + i;
@ -1272,177 +1503,14 @@ void Analysis(Entry *root) {
while (arrlen(unresolved)) {
Entry e = arrpop(unresolved);
assert(e.type == ENTRY_VARIABLE);
int result = AnalysisResolve(root, e, &unresolved, resolved, entry->annotations);
if (e.variable.pointer == 0 && (0 == strcmp(e.variable.type, "uint64_t")
|| 0 == strcmp(e.variable.type, "int64_t")
|| 0 == strcmp(e.variable.type, "uint32_t")
|| 0 == strcmp(e.variable.type, "int32_t")
|| 0 == strcmp(e.variable.type, "uint16_t")
|| 0 == strcmp(e.variable.type, "int16_t")
|| 0 == strcmp(e.variable.type, "uint8_t")
|| 0 == strcmp(e.variable.type, "int8_t")
|| 0 == strcmp(e.variable.type, "char")
|| 0 == strcmp(e.variable.type, "size_t")
|| 0 == strcmp(e.variable.type, "intptr_t")
|| 0 == strcmp(e.variable.type, "uintptr_t")
|| 0 == strcmp(e.variable.type, "ptrdiff_t")
|| 0 == strcmp(e.variable.type, "unsigned")
|| 0 == strcmp(e.variable.type, "int")
|| 0 == strcmp(e.variable.type, "long")
|| 0 == strcmp(e.variable.type, "double")
|| 0 == strcmp(e.variable.type, "float")
|| 0 == strcmp(e.variable.type, "void")
|| 0 == strcmp(e.variable.type, "bool")
|| 0 == strcmp(e.variable.type, "EsCString")
|| 0 == strcmp(e.variable.type, "EsGeneric")
|| 0 == strcmp(e.variable.type, "STRING"))) {
goto resolved;
if (result == 1) {
arrput(resolved, e);
} else if (result == 0) {
unresolvableName = e.name;
goto end;
}
if (e.variable.pointer == 1 && !e.variable.isConst && (0 == strcmp(e.variable.type, "ES_INSTANCE_TYPE"))) {
goto resolved;
}
for (int k = 0; k < arrlen(root->children); k++) {
if (!root->children[k].name) continue;
if (strcmp(e.variable.type, root->children[k].name)) continue;
if (root->children[k].type == ENTRY_TYPE_NAME && e.variable.pointer == 0) {
goto resolved;
} else if (root->children[k].type == ENTRY_ENUM && e.variable.pointer == 0) {
goto resolved;
} else if (root->children[k].type == ENTRY_API_TYPE && e.variable.pointer == 1) {
goto resolved;
} else if (root->children[k].type == ENTRY_STRUCT && e.variable.pointer == 0) {
for (int i = 0; i < arrlen(root->children[k].children); i++) {
Entry f = root->children[k].children[i];
assert(f.type == ENTRY_VARIABLE);
char *old = f.name;
f.name = malloc(strlen(e.name) + 1 + strlen(old) + 1);
strcpy(f.name, e.name);
strcat(f.name, "*");
strcat(f.name, old);
arrput(unresolved, f);
}
goto resolved;
}
}
for (int i = 0; i < arrlen(entry->annotations); i++) {
Entry *annotation = entry->annotations + i;
if (0 == strcmp(annotation->name, "in")
|| 0 == strcmp(annotation->name, "out")
|| 0 == strcmp(annotation->name, "in_out")) {
assert(1 == arrlen(annotation->children));
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer);
assert(e.variable.isConst == (0 == strcmp(annotation->name, "in")));
Entry f = e;
f.name = malloc(strlen(e.name) + 1 + 1);
strcpy(f.name, e.name);
strcat(f.name, "*");
f.variable.pointer--;
arrput(unresolved, f);
goto resolved;
}
} else if (0 == strcmp(annotation->name, "opaque")) {
assert(1 == arrlen(annotation->children));
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer);
assert(!e.variable.isConst);
goto resolved;
}
} else if (0 == strcmp(annotation->name, "buffer_out")
|| 0 == strcmp(annotation->name, "heap_buffer_out")
|| 0 == strcmp(annotation->name, "fixed_buffer_out")
|| 0 == strcmp(annotation->name, "buffer_in")) {
assert(2 == arrlen(annotation->children));
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer && (0 == strcmp(e.variable.type, "void")
|| 0 == strcmp(e.variable.type, "uint8_t")
|| 0 == strcmp(e.variable.type, "char")));
assert(e.variable.isConst == (0 == strcmp(annotation->name, "buffer_in")
|| 0 == strcmp(annotation->name, "fixed_buffer_out")));
bool foundSize = false;
for (int i = 0; i < arrlen(resolved); i++) {
if (0 == strcmp(resolved[i].name, annotation->children[1].name)) {
assert(!resolved[i].variable.pointer && (0 == strcmp(resolved[i].variable.type, "size_t")
|| 0 == strcmp(resolved[i].variable.type, "ptrdiff_t")));
foundSize = true;
}
}
if (!foundSize) {
arrins(unresolved, 0, e);
goto tryAgain;
}
goto resolved;
}
} else if (0 == strcmp(annotation->name, "heap_array_out")
|| 0 == strcmp(annotation->name, "heap_matrix_out")
|| 0 == strcmp(annotation->name, "array_in")
|| 0 == strcmp(annotation->name, "matrix_in")
|| 0 == strcmp(annotation->name, "matrix_shared")) {
bool matrix = 0 == strcmp(annotation->name, "heap_matrix_out")
|| 0 == strcmp(annotation->name, "matrix_in")
|| 0 == strcmp(annotation->name, "matrix_shared");
bool input = 0 == strcmp(annotation->name, "array_in")
|| 0 == strcmp(annotation->name, "matrix_in");
int children = arrlen(annotation->children);
if (matrix) assert(children == 3 || children == 4); // (width, height) or (width, height, stride) or (rectangle, stride)
else assert(children == 2);
if (0 == strcmp(annotation->children[0].name, e.name)) {
assert(e.variable.pointer);
assert(e.variable.isConst == input);
int foundSize = 1;
for (int j = 1; j < children; j++) {
for (int i = 0; i < arrlen(resolved); i++) {
if (0 == strcmp(resolved[i].name, annotation->children[j].name)) {
assert(!resolved[i].variable.pointer && (0 == strcmp(resolved[i].variable.type, "size_t")
|| 0 == strcmp(resolved[i].variable.type, "ptrdiff_t")
|| 0 == strcmp(resolved[i].variable.type, "uintptr_t")
|| 0 == strcmp(resolved[i].variable.type, "uint32_t")
|| (0 == strcmp(resolved[i].variable.type, "EsRectangle") && matrix && j == 1)));
foundSize++;
break;
}
}
}
if (foundSize != children) {
arrins(unresolved, 0, e);
goto tryAgain;
}
Entry f = e;
f.name = malloc(strlen(e.name) + 2 + 1);
strcpy(f.name, e.name);
strcat(f.name, "[]");
f.variable.pointer--;
arrput(unresolved, f);
goto resolved;
}
}
}
unresolvableName = e.name;
goto end;
resolved:;
arrput(resolved, e);
tryAgain:;
}
understood = true;