1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987 |
- /**********************************************************************************************
- raylib API parser
- This parser scans raylib.h to get API information about defines, structs, aliases, enums, callbacks and functions.
- All data is divided into pieces, usually as strings. The following types are used for data:
- - struct DefineInfo
- - struct StructInfo
- - struct AliasInfo
- - struct EnumInfo
- - struct FunctionInfo
- CONSTRAINTS:
- This parser is specifically designed to work with raylib.h, so, it has some constraints:
- - Functions are expected as a single line with the following structure:
- <retType> <name>(<paramType[0]> <paramName[0]>, <paramType[1]> <paramName[1]>); <desc>
- Be careful with functions broken into several lines, it breaks the process!
- - Structures are expected as several lines with the following form:
- <desc>
- typedef struct <name> {
- <fieldType[0]> <fieldName[0]>; <fieldDesc[0]>
- <fieldType[1]> <fieldName[1]>; <fieldDesc[1]>
- <fieldType[2]> <fieldName[2]>; <fieldDesc[2]>
- } <name>;
- - Enums are expected as several lines with the following form:
- <desc>
- typedef enum {
- <valueName[0]> = <valueInteger[0]>, <valueDesc[0]>
- <valueName[1]>,
- <valueName[2]>, <valueDesc[2]>
- <valueName[3]> <valueDesc[3]>
- } <name>;
- NOTE: Multiple options are supported for enums:
- - If value is not provided, (<valueInteger[i -1]> + 1) is assigned
- - Value description can be provided or not
- OTHER NOTES:
- - This parser could work with other C header files if mentioned constraints are followed.
- - This parser does not require <string.h> library, all data is parsed directly from char buffers.
- LICENSE: zlib/libpng
- raylib-parser is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
- BSD-like license that allows static linking with closed source software:
- Copyright (c) 2021-2023 Ramon Santamaria (@raysan5)
- **********************************************************************************************/
- #define _CRT_SECURE_NO_WARNINGS
- #include <stdlib.h> // Required for: malloc(), calloc(), realloc(), free(), atoi(), strtol()
- #include <stdio.h> // Required for: printf(), fopen(), fseek(), ftell(), fread(), fclose()
- #include <stdbool.h> // Required for: bool
- #include <ctype.h> // Required for: isdigit()
- #define MAX_DEFINES_TO_PARSE 2048 // Maximum number of defines to parse
- #define MAX_STRUCTS_TO_PARSE 64 // Maximum number of structures to parse
- #define MAX_ALIASES_TO_PARSE 64 // Maximum number of aliases to parse
- #define MAX_ENUMS_TO_PARSE 64 // Maximum number of enums to parse
- #define MAX_CALLBACKS_TO_PARSE 64 // Maximum number of callbacks to parse
- #define MAX_FUNCS_TO_PARSE 1024 // Maximum number of functions to parse
- #define MAX_LINE_LENGTH 512 // Maximum length of one line (including comments)
- #define MAX_STRUCT_FIELDS 64 // Maximum number of struct fields
- #define MAX_ENUM_VALUES 512 // Maximum number of enum values
- #define MAX_FUNCTION_PARAMETERS 12 // Maximum number of function parameters
- //----------------------------------------------------------------------------------
- // Types and Structures Definition
- //----------------------------------------------------------------------------------
- // Type of parsed define
- typedef enum {
- UNKNOWN = 0,
- MACRO,
- GUARD,
- INT,
- INT_MATH,
- LONG,
- LONG_MATH,
- FLOAT,
- FLOAT_MATH,
- DOUBLE,
- DOUBLE_MATH,
- CHAR,
- STRING,
- COLOR
- } DefineType;
- // Define info data
- typedef struct DefineInfo {
- char name[64]; // Define name
- int type; // Define type
- char value[256]; // Define value
- char desc[128]; // Define description
- bool isHex; // Define is hex number (for types INT, LONG)
- } DefineInfo;
- // Struct info data
- typedef struct StructInfo {
- char name[64]; // Struct name
- char desc[128]; // Struct type description
- int fieldCount; // Number of fields in the struct
- char fieldType[MAX_STRUCT_FIELDS][64]; // Field type
- char fieldName[MAX_STRUCT_FIELDS][64]; // Field name
- char fieldDesc[MAX_STRUCT_FIELDS][128]; // Field description
- } StructInfo;
- // Alias info data
- typedef struct AliasInfo {
- char type[64]; // Alias type
- char name[64]; // Alias name
- char desc[128]; // Alias description
- } AliasInfo;
- // Enum info data
- typedef struct EnumInfo {
- char name[64]; // Enum name
- char desc[128]; // Enum description
- int valueCount; // Number of values in enumerator
- char valueName[MAX_ENUM_VALUES][64]; // Value name definition
- int valueInteger[MAX_ENUM_VALUES]; // Value integer
- char valueDesc[MAX_ENUM_VALUES][128]; // Value description
- } EnumInfo;
- // Function info data
- typedef struct FunctionInfo {
- char name[64]; // Function name
- char desc[128]; // Function description (comment at the end)
- char retType[32]; // Return value type
- int paramCount; // Number of function parameters
- char paramType[MAX_FUNCTION_PARAMETERS][32]; // Parameters type
- char paramName[MAX_FUNCTION_PARAMETERS][32]; // Parameters name
- char paramDesc[MAX_FUNCTION_PARAMETERS][128]; // Parameters description
- } FunctionInfo;
- // Output format for parsed data
- typedef enum { DEFAULT = 0, JSON, XML, LUA, CODE } OutputFormat;
- //----------------------------------------------------------------------------------
- // Global Variables Definition
- //----------------------------------------------------------------------------------
- static int defineCount = 0;
- static int structCount = 0;
- static int aliasCount = 0;
- static int enumCount = 0;
- static int callbackCount = 0;
- static int funcCount = 0;
- static DefineInfo *defines = NULL;
- static StructInfo *structs = NULL;
- static AliasInfo *aliases = NULL;
- static EnumInfo *enums = NULL;
- static FunctionInfo *callbacks = NULL;
- static FunctionInfo *funcs = NULL;
- // Command line variables
- static char apiDefine[32] = { 0 }; // Functions define (i.e. RLAPI for raylib.h, RMDEF for raymath.h, etc.)
- static char truncAfter[32] = { 0 }; // Truncate marker (i.e. "RLGL IMPLEMENTATION" for rlgl.h)
- static char inFileName[512] = { 0 }; // Input file name (required in case of provided through CLI)
- static char outFileName[512] = { 0 }; // Output file name (required for file save/export)
- static int outputFormat = DEFAULT;
- //----------------------------------------------------------------------------------
- // Module Functions Declaration
- //----------------------------------------------------------------------------------
- static void ShowCommandLineInfo(void); // Show command line usage info
- static void ProcessCommandLine(int argc, char *argv[]); // Process command line input
- static char *LoadFileText(const char *fileName, int *length);
- static char **GetTextLines(const char *buffer, int length, int *linesCount);
- static void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name);
- static void GetDescription(const char *source, char *description);
- static void MoveArraySize(char *name, char *type); // Move array size from name to type
- static unsigned int TextLength(const char *text); // Get text length in bytes, check for \0 character
- static bool IsTextEqual(const char *text1, const char *text2, unsigned int count);
- static int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
- static void MemoryCopy(void *dest, const void *src, unsigned int count);
- static char *EscapeBackslashes(char *text); // Replace '\' by "\\" when exporting to JSON and XML
- static const char *StrDefineType(DefineType type); // Get string of define type
- static void ExportParsedData(const char *fileName, int format); // Export parsed data in desired format
- //----------------------------------------------------------------------------------
- // Program main entry point
- //----------------------------------------------------------------------------------
- int main(int argc, char* argv[])
- {
- if (argc > 1) ProcessCommandLine(argc, argv);
- if (inFileName[0] == '\0') MemoryCopy(inFileName, "../src/raylib.h\0", 16);
- if (outFileName[0] == '\0') MemoryCopy(outFileName, "raylib_api.txt\0", 15);
- if (apiDefine[0] == '\0') MemoryCopy(apiDefine, "RLAPI\0", 6);
- int length = 0;
- char *buffer = LoadFileText(inFileName, &length);
- if (buffer == NULL)
- {
- printf("Could not read input file: %s\n", inFileName);
- return 1;
- }
- // Preprocess buffer to get separate lines
- // NOTE: GetTextLines() also removes leading spaces/tabs
- int linesCount = 0;
- char **lines = GetTextLines(buffer, length, &linesCount);
- // Truncate lines
- if (truncAfter[0] != '\0')
- {
- int newCount = -1;
- for (int i = 0; i < linesCount; i++)
- {
- if (newCount > -1) free(lines[i]);
- else if (TextFindIndex(lines[i], truncAfter) > -1) newCount = i;
- }
- if (newCount > -1) linesCount = newCount;
- printf("Number of truncated text lines: %i\n", linesCount);
- }
- // Defines line indices
- int *defineLines = (int *)malloc(MAX_DEFINES_TO_PARSE*sizeof(int));
- // Structs line indices
- int *structLines = (int *)malloc(MAX_STRUCTS_TO_PARSE*sizeof(int));
- // Aliases line indices
- int *aliasLines = (int *)malloc(MAX_ALIASES_TO_PARSE*sizeof(int));
- // Enums line indices
- int *enumLines = (int *)malloc(MAX_ENUMS_TO_PARSE*sizeof(int));
- // Callbacks line indices
- int *callbackLines = (int *)malloc(MAX_CALLBACKS_TO_PARSE*sizeof(int));
- // Function line indices
- int *funcLines = (int *)malloc(MAX_FUNCS_TO_PARSE*sizeof(int));
- // Prepare required lines for parsing
- //----------------------------------------------------------------------------------
- // Read define lines
- for (int i = 0; i < linesCount; i++)
- {
- int j = 0;
- while ((lines[i][j] == ' ') || (lines[i][j] == '\t')) j++; // skip spaces and tabs in the begining
- // Read define line
- if (IsTextEqual(lines[i]+j, "#define ", 8))
- {
- // Keep the line position in the array of lines,
- // so, we can scan that position and following lines
- defineLines[defineCount] = i;
- defineCount++;
- }
- }
- // Read struct lines
- for (int i = 0; i < linesCount; i++)
- {
- // Find structs
- // starting with "typedef struct ... {" or "typedef struct ... ; \n struct ... {"
- // ending with "} ... ;"
- // i.e. excluding "typedef struct rAudioBuffer rAudioBuffer;" -> Typedef and forward declaration only
- if (IsTextEqual(lines[i], "typedef struct", 14))
- {
- bool validStruct = IsTextEqual(lines[i + 1], "struct", 6);
- if (!validStruct)
- {
- for (int c = 0; c < MAX_LINE_LENGTH; c++)
- {
- char v = lines[i][c];
- if (v == '{') validStruct = true;
- if ((v == '{') || (v == ';') || (v == '\0')) break;
- }
- }
- if (!validStruct) continue;
- structLines[structCount] = i;
- while (lines[i][0] != '}') i++;
- while (lines[i][0] != '\0') i++;
- structCount++;
- }
- }
- // Read alias lines
- for (int i = 0; i < linesCount; i++)
- {
- // Find aliases (lines with "typedef ... ...;")
- if (IsTextEqual(lines[i], "typedef", 7))
- {
- int spaceCount = 0;
- bool validAlias = false;
- for (int c = 0; c < MAX_LINE_LENGTH; c++)
- {
- char v = lines[i][c];
- if (v == ' ') spaceCount++;
- if ((v == ';') && (spaceCount == 2)) validAlias = true;
- if ((v == ';') || (v == '(') || (v == '\0')) break;
- }
- if (!validAlias) continue;
- aliasLines[aliasCount] = i;
- aliasCount++;
- }
- }
- // Read enum lines
- for (int i = 0; i < linesCount; i++)
- {
- // Read enum line
- if (IsTextEqual(lines[i], "typedef enum {", 14) && (lines[i][TextLength(lines[i])-1] != ';')) // ignore inline enums
- {
- // Keep the line position in the array of lines,
- // so, we can scan that position and following lines
- enumLines[enumCount] = i;
- enumCount++;
- }
- }
- // Read callback lines
- for (int i = 0; i < linesCount; i++)
- {
- // Find callbacks (lines with "typedef ... (* ... )( ... );")
- if (IsTextEqual(lines[i], "typedef", 7))
- {
- bool hasBeginning = false;
- bool hasMiddle = false;
- bool hasEnd = false;
- for (int c = 0; c < MAX_LINE_LENGTH; c++)
- {
- if ((lines[i][c] == '(') && (lines[i][c + 1] == '*')) hasBeginning = true;
- if ((lines[i][c] == ')') && (lines[i][c + 1] == '(')) hasMiddle = true;
- if ((lines[i][c] == ')') && (lines[i][c + 1] == ';')) hasEnd = true;
- if (hasEnd) break;
- }
- if (hasBeginning && hasMiddle && hasEnd)
- {
- callbackLines[callbackCount] = i;
- callbackCount++;
- }
- }
- }
- // Read function lines
- for (int i = 0; i < linesCount; i++)
- {
- // Read function line (starting with `define`, i.e. for raylib.h "RLAPI")
- if (IsTextEqual(lines[i], apiDefine, TextLength(apiDefine)))
- {
- funcLines[funcCount] = i;
- funcCount++;
- }
- }
- // At this point we have all raylib defines, structs, aliases, enums, callbacks, functions lines data to start parsing
- free(buffer); // Unload text buffer
- // Parsing raylib data
- //----------------------------------------------------------------------------------
- // Define info data
- defines = (DefineInfo *)calloc(MAX_DEFINES_TO_PARSE, sizeof(DefineInfo));
- int defineIndex = 0;
- for (int i = 0; i < defineCount; i++)
- {
- char *linePtr = lines[defineLines[i]];
- int j = 0;
- while ((linePtr[j] == ' ') || (linePtr[j] == '\t')) j++; // Skip spaces and tabs in the begining
- j += 8; // Skip "#define "
- while ((linePtr[j] == ' ') || (linePtr[j] == '\t')) j++; // Skip spaces and tabs after "#define "
- // Extract name
- int defineNameStart = j;
- int openBraces = 0;
- while (linePtr[j] != '\0')
- {
- if (((linePtr[j] == ' ') || (linePtr[j] == '\t')) && (openBraces == 0)) break;
- if (linePtr[j] == '(') openBraces++;
- if (linePtr[j] == ')') openBraces--;
- j++;
- }
- int defineNameEnd = j-1;
- // Skip duplicates
- unsigned int nameLen = defineNameEnd - defineNameStart + 1;
- bool isDuplicate = false;
- for (int k = 0; k < defineIndex; k++)
- {
- if ((nameLen == TextLength(defines[k].name)) && IsTextEqual(defines[k].name, &linePtr[defineNameStart], nameLen))
- {
- isDuplicate = true;
- break;
- }
- }
- if (isDuplicate) continue;
- MemoryCopy(defines[defineIndex].name, &linePtr[defineNameStart], nameLen);
- // Determine type
- if (linePtr[defineNameEnd] == ')') defines[defineIndex].type = MACRO;
- while ((linePtr[j] == ' ') || (linePtr[j] == '\t')) j++; // Skip spaces and tabs after name
- int defineValueStart = j;
- if ((linePtr[j] == '\0') || (linePtr[j] == '/')) defines[defineIndex].type = GUARD;
- if (linePtr[j] == '"') defines[defineIndex].type = STRING;
- else if (linePtr[j] == '\'') defines[defineIndex].type = CHAR;
- else if (IsTextEqual(linePtr+j, "CLITERAL(Color)", 15)) defines[defineIndex].type = COLOR;
- else if (isdigit(linePtr[j])) // Parsing numbers
- {
- bool isFloat = false, isNumber = true, isHex = false;
- while ((linePtr[j] != ' ') && (linePtr[j] != '\t') && (linePtr[j] != '\0'))
- {
- char ch = linePtr[j];
- if (ch == '.') isFloat = true;
- if (ch == 'x') isHex = true;
- if (!(isdigit(ch) ||
- ((ch >= 'a') && (ch <= 'f')) ||
- ((ch >= 'A') && (ch <= 'F')) ||
- (ch == 'x') ||
- (ch == 'L') ||
- (ch == '.') ||
- (ch == '+') ||
- (ch == '-'))) isNumber = false;
- j++;
- }
- if (isNumber)
- {
- if (isFloat)
- {
- defines[defineIndex].type = linePtr[j-1] == 'f' ? FLOAT : DOUBLE;
- }
- else
- {
- defines[defineIndex].type = linePtr[j-1] == 'L' ? LONG : INT;
- defines[defineIndex].isHex = isHex;
- }
- }
- }
- // Extracting value
- while ((linePtr[j] != '\\') && (linePtr[j] != '\0') && !((linePtr[j] == '/') && (linePtr[j+1] == '/'))) j++;
- int defineValueEnd = j-1;
- while ((linePtr[defineValueEnd] == ' ') || (linePtr[defineValueEnd] == '\t')) defineValueEnd--; // Remove trailing spaces and tabs
- if ((defines[defineIndex].type == LONG) || (defines[defineIndex].type == FLOAT)) defineValueEnd--; // Remove number postfix
- int valueLen = defineValueEnd - defineValueStart + 1;
- if (valueLen > 255) valueLen = 255;
- if (valueLen > 0) MemoryCopy(defines[defineIndex].value, &linePtr[defineValueStart], valueLen);
- // Extracting description
- if ((linePtr[j] == '/') && linePtr[j + 1] == '/')
- {
- j += 2;
- while (linePtr[j] == ' ') j++;
- int commentStart = j;
- while ((linePtr[j] != '\\') && (linePtr[j] != '\0')) j++;
- int commentEnd = j-1;
- int commentLen = commentEnd - commentStart + 1;
- if (commentLen > 127) commentLen = 127;
- MemoryCopy(defines[defineIndex].desc, &linePtr[commentStart], commentLen);
- }
- // Parse defines of type UNKNOWN to find calculated numbers
- if (defines[defineIndex].type == UNKNOWN)
- {
- int largestType = UNKNOWN;
- bool isMath = true;
- char *valuePtr = defines[defineIndex].value;
- for (unsigned int c = 0; c < TextLength(valuePtr); c++)
- {
- char ch = valuePtr[c];
- // Skip operators and whitespace
- if ((ch == '(') ||
- (ch == ')') ||
- (ch == '+') ||
- (ch == '-') ||
- (ch == '*') ||
- (ch == '/') ||
- (ch == ' ') ||
- (ch == '\t')) continue;
-
- // Read number operand
- else if (isdigit(ch))
- {
- bool isNumber = true, isFloat = false;
- while (!((ch == '(') ||
- (ch == ')') ||
- (ch == '*') ||
- (ch == '/') ||
- (ch == ' ') ||
- (ch == '\t') ||
- (ch == '\0')))
- {
- if (ch == '.') isFloat = true;
- if (!(isdigit(ch) ||
- ((ch >= 'a') && (ch <= 'f')) ||
- ((ch >= 'A') && (ch <= 'F')) ||
- (ch == 'x') ||
- (ch == 'L') ||
- (ch == '.') ||
- (ch == '+') ||
- (ch == '-')))
- {
- isNumber = false;
- break;
- }
- c++;
- ch = valuePtr[c];
- }
- if (isNumber)
- {
- // Found a valid number -> update largestType
- int numberType;
- if (isFloat) numberType = valuePtr[c - 1] == 'f' ? FLOAT_MATH : DOUBLE_MATH;
- else numberType = valuePtr[c - 1] == 'L' ? LONG_MATH : INT_MATH;
-
- if (numberType > largestType) largestType = numberType;
- }
- else
- {
- isMath = false;
- break;
- }
- }
- else // Read string operand
- {
- int operandStart = c;
- while (!((ch == '\0') ||
- (ch == ' ') ||
- (ch == '(') ||
- (ch == ')') ||
- (ch == '+') ||
- (ch == '-') ||
- (ch == '*') ||
- (ch == '/')))
- {
- c++;
- ch = valuePtr[c];
- }
- int operandEnd = c;
- int operandLength = operandEnd - operandStart;
- // Search previous defines for operand
- bool foundOperand = false;
- for (int previousDefineIndex = 0; previousDefineIndex < defineIndex; previousDefineIndex++)
- {
- if (IsTextEqual(defines[previousDefineIndex].name, &valuePtr[operandStart], operandLength))
- {
- if ((defines[previousDefineIndex].type >= INT) && (defines[previousDefineIndex].type <= DOUBLE_MATH))
- {
- // Found operand and it's a number -> update largestType
- if (defines[previousDefineIndex].type > largestType) largestType = defines[previousDefineIndex].type;
- foundOperand = true;
- }
- break;
- }
- }
- if (!foundOperand)
- {
- isMath = false;
- break;
- }
- }
- }
- if (isMath)
- {
- // Define is a calculated number -> update type
- if (largestType == INT) largestType = INT_MATH;
- else if (largestType == LONG) largestType = LONG_MATH;
- else if (largestType == FLOAT) largestType = FLOAT_MATH;
- else if (largestType == DOUBLE) largestType = DOUBLE_MATH;
- defines[defineIndex].type = largestType;
- }
- }
- defineIndex++;
- }
- defineCount = defineIndex;
- free(defineLines);
- // Structs info data
- structs = (StructInfo *)calloc(MAX_STRUCTS_TO_PARSE, sizeof(StructInfo));
- for (int i = 0; i < structCount; i++)
- {
- char **linesPtr = &lines[structLines[i]];
- // Parse struct description
- GetDescription(linesPtr[-1], structs[i].desc);
- // Get struct name: typedef struct name {
- const int TDS_LEN = 15; // length of "typedef struct "
- for (int c = TDS_LEN; c < 64 + TDS_LEN; c++)
- {
- if ((linesPtr[0][c] == '{') || (linesPtr[0][c] == ' '))
- {
- int nameLen = c - TDS_LEN;
- while (linesPtr[0][TDS_LEN + nameLen - 1] == ' ') nameLen--;
- MemoryCopy(structs[i].name, &linesPtr[0][TDS_LEN], nameLen);
- break;
- }
- }
- // Get struct fields and count them -> fields finish with ;
- int l = 1;
- while (linesPtr[l][0] != '}')
- {
- // WARNING: Some structs have empty spaces and comments -> OK, processed
- if ((linesPtr[l][0] != ' ') && (linesPtr[l][0] != '\0'))
- {
- // Scan one field line
- char *fieldLine = linesPtr[l];
- int fieldEndPos = 0;
- while (fieldLine[fieldEndPos] != ';') fieldEndPos++;
- if ((fieldLine[0] != '/') && !IsTextEqual(fieldLine, "struct", 6)) // Field line is not a comment and not a struct declaration
- {
- //printf("Struct field: %s_\n", fieldLine); // OK!
- // Get struct field type and name
- GetDataTypeAndName(fieldLine, fieldEndPos, structs[i].fieldType[structs[i].fieldCount], structs[i].fieldName[structs[i].fieldCount]);
- // Get the field description
- GetDescription(&fieldLine[fieldEndPos], structs[i].fieldDesc[structs[i].fieldCount]);
- structs[i].fieldCount++;
- // Split field names containing multiple fields (like Matrix)
- int additionalFields = 0;
- int originalIndex = structs[i].fieldCount - 1;
- for (unsigned int c = 0; c < TextLength(structs[i].fieldName[originalIndex]); c++)
- {
- if (structs[i].fieldName[originalIndex][c] == ',') additionalFields++;
- }
-
- if (additionalFields > 0)
- {
- int originalLength = -1;
- int lastStart;
- for (unsigned int c = 0; c < TextLength(structs[i].fieldName[originalIndex]) + 1; c++)
- {
- char v = structs[i].fieldName[originalIndex][c];
- bool isEndOfString = (v == '\0');
- if ((v == ',') || isEndOfString)
- {
- if (originalLength == -1)
- {
- // Save length of original field name
- // Don't truncate yet, still needed for copying
- originalLength = c;
- }
- else
- {
- // Copy field data from original field
- int nameLength = c - lastStart;
- MemoryCopy(structs[i].fieldName[structs[i].fieldCount], &structs[i].fieldName[originalIndex][lastStart], nameLength);
- MemoryCopy(structs[i].fieldType[structs[i].fieldCount], &structs[i].fieldType[originalIndex][0], TextLength(structs[i].fieldType[originalIndex]));
- MemoryCopy(structs[i].fieldDesc[structs[i].fieldCount], &structs[i].fieldDesc[originalIndex][0], TextLength(structs[i].fieldDesc[originalIndex]));
- structs[i].fieldCount++;
- }
- if (!isEndOfString)
- {
- // Skip comma and spaces
- c++;
- while (structs[i].fieldName[originalIndex][c] == ' ') c++;
- // Save position for next field
- lastStart = c;
- }
- }
- }
- // Set length of original field to truncate the first field name
- structs[i].fieldName[originalIndex][originalLength] = '\0';
- }
- // Split field types containing multiple fields (like MemNode)
- additionalFields = 0;
- originalIndex = structs[i].fieldCount - 1;
- for (unsigned int c = 0; c < TextLength(structs[i].fieldType[originalIndex]); c++)
- {
- if (structs[i].fieldType[originalIndex][c] == ',') additionalFields++;
- }
-
- if (additionalFields > 0)
- {
- // Copy original name to last additional field
- structs[i].fieldCount += additionalFields;
- MemoryCopy(structs[i].fieldName[originalIndex + additionalFields], &structs[i].fieldName[originalIndex][0], TextLength(structs[i].fieldName[originalIndex]));
- // Copy names from type to additional fields
- int fieldsRemaining = additionalFields;
- int nameStart = -1;
- int nameEnd = -1;
- for (int k = TextLength(structs[i].fieldType[originalIndex]); k > 0; k--)
- {
- char v = structs[i].fieldType[originalIndex][k];
- if ((v == '*') || (v == ' ') || (v == ','))
- {
- if (nameEnd != -1) {
- // Don't copy to last additional field
- if (fieldsRemaining != additionalFields)
- {
- nameStart = k + 1;
- MemoryCopy(structs[i].fieldName[originalIndex + fieldsRemaining], &structs[i].fieldType[originalIndex][nameStart], nameEnd - nameStart + 1);
- }
- nameEnd = -1;
- fieldsRemaining--;
- }
- }
- else if (nameEnd == -1) nameEnd = k;
- }
- // Truncate original field type
- int fieldTypeLength = nameStart;
- structs[i].fieldType[originalIndex][fieldTypeLength] = '\0';
- // Set field type and description of additional fields
- for (int j = 1; j <= additionalFields; j++)
- {
- MemoryCopy(structs[i].fieldType[originalIndex + j], &structs[i].fieldType[originalIndex][0], fieldTypeLength);
- MemoryCopy(structs[i].fieldDesc[originalIndex + j], &structs[i].fieldDesc[originalIndex][0], TextLength(structs[i].fieldDesc[originalIndex]));
- }
- }
- }
- }
- l++;
- }
- // Move array sizes from name to type
- for (int j = 0; j < structs[i].fieldCount; j++)
- {
- MoveArraySize(structs[i].fieldName[j], structs[i].fieldType[j]);
- }
- }
- free(structLines);
- // Alias info data
- aliases = (AliasInfo *)calloc(MAX_ALIASES_TO_PARSE, sizeof(AliasInfo));
- for (int i = 0; i < aliasCount; i++)
- {
- // Description from previous line
- GetDescription(lines[aliasLines[i] - 1], aliases[i].desc);
- char *linePtr = lines[aliasLines[i]];
- // Skip "typedef "
- int c = 8;
- // Type
- int typeStart = c;
- while(linePtr[c] != ' ') c++;
- int typeLen = c - typeStart;
- MemoryCopy(aliases[i].type, &linePtr[typeStart], typeLen);
- // Skip space
- c++;
- // Name
- int nameStart = c;
- while(linePtr[c] != ';') c++;
- int nameLen = c - nameStart;
- MemoryCopy(aliases[i].name, &linePtr[nameStart], nameLen);
- // Description
- GetDescription(&linePtr[c], aliases[i].desc);
- }
- free(aliasLines);
- // Enum info data
- enums = (EnumInfo *)calloc(MAX_ENUMS_TO_PARSE, sizeof(EnumInfo));
- for (int i = 0; i < enumCount; i++)
- {
- // Parse enum description
- // NOTE: This is not necessarily from the line immediately before,
- // some of the enums have extra lines between the "description"
- // and the typedef enum
- for (int j = enumLines[i] - 1; j > 0; j--)
- {
- char *linePtr = lines[j];
- if ((linePtr[0] != '/') || (linePtr[2] != ' '))
- {
- GetDescription(&lines[j + 1][0], enums[i].desc);
- break;
- }
- }
- for (int j = 1; j < MAX_ENUM_VALUES*2; j++) // Maximum number of lines following enum first line
- {
- char *linePtr = lines[enumLines[i] + j];
- if ((linePtr[0] >= 'A') && (linePtr[0] <= 'Z'))
- {
- // Parse enum value line, possible options:
- //ENUM_VALUE_NAME,
- //ENUM_VALUE_NAME
- //ENUM_VALUE_NAME = 99
- //ENUM_VALUE_NAME = 99,
- //ENUM_VALUE_NAME = 0x00000040, // Value description
- // We start reading the value name
- int c = 0;
- while ((linePtr[c] != ',') &&
- (linePtr[c] != ' ') &&
- (linePtr[c] != '=') &&
- (linePtr[c] != '\0'))
- {
- enums[i].valueName[enums[i].valueCount][c] = linePtr[c];
- c++;
- }
- // After the name we can have:
- // '=' -> value is provided
- // ',' -> value is equal to previous + 1, there could be a description if not '\0'
- // ' ' -> value is equal to previous + 1, there could be a description if not '\0'
- // '\0' -> value is equal to previous + 1
- // Let's start checking if the line is not finished
- if ((linePtr[c] != ',') && (linePtr[c] != '\0'))
- {
- // Two options:
- // '=' -> value is provided
- // ' ' -> value is equal to previous + 1, there could be a description if not '\0'
- bool foundValue = false;
- while ((linePtr[c] != '\0') && (linePtr[c] != '/'))
- {
- if (linePtr[c] == '=')
- {
- foundValue = true;
- break;
- }
- c++;
- }
- if (foundValue)
- {
- if (linePtr[c + 1] == ' ') c += 2;
- else c++;
- // Parse integer value
- int n = 0;
- char integer[16] = { 0 };
- while ((linePtr[c] != ',') && (linePtr[c] != ' ') && (linePtr[c] != '\0'))
- {
- integer[n] = linePtr[c];
- c++; n++;
- }
- if (integer[1] == 'x') enums[i].valueInteger[enums[i].valueCount] = (int)strtol(integer, NULL, 16);
- else enums[i].valueInteger[enums[i].valueCount] = atoi(integer);
- }
- else enums[i].valueInteger[enums[i].valueCount] = (enums[i].valueInteger[enums[i].valueCount - 1] + 1);
- }
- else enums[i].valueInteger[enums[i].valueCount] = (enums[i].valueInteger[enums[i].valueCount - 1] + 1);
- // Parse value description
- GetDescription(&linePtr[c], enums[i].valueDesc[enums[i].valueCount]);
- enums[i].valueCount++;
- }
- else if (linePtr[0] == '}')
- {
- // Get enum name from typedef
- int c = 0;
- while (linePtr[2 + c] != ';')
- {
- enums[i].name[c] = linePtr[2 + c];
- c++;
- }
- break; // Enum ended, break for() loop
- }
- }
- }
- free(enumLines);
- // Callback info data
- callbacks = (FunctionInfo *)calloc(MAX_CALLBACKS_TO_PARSE, sizeof(FunctionInfo));
- for (int i = 0; i < callbackCount; i++)
- {
- char *linePtr = lines[callbackLines[i]];
- // Skip "typedef "
- unsigned int c = 8;
- // Return type
- int retTypeStart = c;
- while(linePtr[c] != '(') c++;
- int retTypeLen = c - retTypeStart;
- while(linePtr[retTypeStart + retTypeLen - 1] == ' ') retTypeLen--;
- MemoryCopy(callbacks[i].retType, &linePtr[retTypeStart], retTypeLen);
- // Skip "(*"
- c += 2;
- // Name
- int nameStart = c;
- while(linePtr[c] != ')') c++;
- int nameLen = c - nameStart;
- MemoryCopy(callbacks[i].name, &linePtr[nameStart], nameLen);
- // Skip ")("
- c += 2;
- // Params
- int paramStart = c;
- for (; c < MAX_LINE_LENGTH; c++)
- {
- if ((linePtr[c] == ',') || (linePtr[c] == ')'))
- {
- // Get parameter type + name, extract info
- int paramLen = c - paramStart;
- GetDataTypeAndName(&linePtr[paramStart], paramLen, callbacks[i].paramType[callbacks[i].paramCount], callbacks[i].paramName[callbacks[i].paramCount]);
- callbacks[i].paramCount++;
- paramStart = c + 1;
- while(linePtr[paramStart] == ' ') paramStart++;
- }
- if (linePtr[c] == ')') break;
- }
- // Description
- GetDescription(&linePtr[c], callbacks[i].desc);
- // Move array sizes from name to type
- for (int j = 0; j < callbacks[i].paramCount; j++)
- {
- MoveArraySize(callbacks[i].paramName[j], callbacks[i].paramType[j]);
- }
- }
- free(callbackLines);
- // Functions info data
- funcs = (FunctionInfo *)calloc(MAX_FUNCS_TO_PARSE, sizeof(FunctionInfo));
- for (int i = 0; i < funcCount; i++)
- {
- char *linePtr = lines[funcLines[i]];
- int funcParamsStart = 0;
- int funcEnd = 0;
- // Get return type and function name from func line
- for (int c = 0; (c < MAX_LINE_LENGTH) && (linePtr[c] != '\n'); c++)
- {
- if (linePtr[c] == '(') // Starts function parameters
- {
- funcParamsStart = c + 1;
- // At this point we have function return type and function name
- char funcRetTypeName[128] = { 0 };
- int dc = TextLength(apiDefine) + 1;
- int funcRetTypeNameLen = c - dc; // Substract `define` ("RLAPI " for raylib.h)
- MemoryCopy(funcRetTypeName, &linePtr[dc], funcRetTypeNameLen);
- GetDataTypeAndName(funcRetTypeName, funcRetTypeNameLen, funcs[i].retType, funcs[i].name);
- break;
- }
- }
- // Get parameters from func line
- for (int c = funcParamsStart; c < MAX_LINE_LENGTH; c++)
- {
- if (linePtr[c] == ',') // Starts function parameters
- {
- // Get parameter type + name, extract info
- char funcParamTypeName[128] = { 0 };
- int funcParamTypeNameLen = c - funcParamsStart;
- MemoryCopy(funcParamTypeName, &linePtr[funcParamsStart], funcParamTypeNameLen);
- GetDataTypeAndName(funcParamTypeName, funcParamTypeNameLen, funcs[i].paramType[funcs[i].paramCount], funcs[i].paramName[funcs[i].paramCount]);
- funcParamsStart = c + 1;
- if (linePtr[c + 1] == ' ') funcParamsStart += 1;
- funcs[i].paramCount++; // Move to next parameter
- }
- else if (linePtr[c] == ')')
- {
- funcEnd = c + 2;
- // Check if previous word is void
- if ((linePtr[c - 4] == 'v') && (linePtr[c - 3] == 'o') && (linePtr[c - 2] == 'i') && (linePtr[c - 1] == 'd')) break;
- // Get parameter type + name, extract info
- char funcParamTypeName[128] = { 0 };
- int funcParamTypeNameLen = c - funcParamsStart;
- MemoryCopy(funcParamTypeName, &linePtr[funcParamsStart], funcParamTypeNameLen);
- GetDataTypeAndName(funcParamTypeName, funcParamTypeNameLen, funcs[i].paramType[funcs[i].paramCount], funcs[i].paramName[funcs[i].paramCount]);
- funcs[i].paramCount++; // Move to next parameter
- break;
- }
- }
- // Get function description
- GetDescription(&linePtr[funcEnd], funcs[i].desc);
- // Move array sizes from name to type
- for (int j = 0; j < funcs[i].paramCount; j++)
- {
- MoveArraySize(funcs[i].paramName[j], funcs[i].paramType[j]);
- }
- }
- free(funcLines);
- for (int i = 0; i < linesCount; i++) free(lines[i]);
- free(lines);
- // At this point, all raylib data has been parsed!
- //----------------------------------------------------------------------------------
- // defines[] -> We have all the defines decomposed into pieces for further analysis
- // structs[] -> We have all the structs decomposed into pieces for further analysis
- // aliases[] -> We have all the aliases decomposed into pieces for further analysis
- // enums[] -> We have all the enums decomposed into pieces for further analysis
- // callbacks[] -> We have all the callbacks decomposed into pieces for further analysis
- // funcs[] -> We have all the functions decomposed into pieces for further analysis
- printf("\nInput file: %s", inFileName);
- printf("\nOutput file: %s", outFileName);
- if (outputFormat == DEFAULT) printf("\nOutput format: DEFAULT\n\n");
- else if (outputFormat == JSON) printf("\nOutput format: JSON\n\n");
- else if (outputFormat == XML) printf("\nOutput format: XML\n\n");
- else if (outputFormat == LUA) printf("\nOutput format: LUA\n\n");
- else if (outputFormat == CODE) printf("\nOutput format: CODE\n\n");
- ExportParsedData(outFileName, outputFormat);
- free(defines);
- free(structs);
- free(aliases);
- free(enums);
- free(callbacks);
- free(funcs);
- }
- //----------------------------------------------------------------------------------
- // Module Functions Definition
- //----------------------------------------------------------------------------------
- // Show command line usage info
- static void ShowCommandLineInfo(void)
- {
- printf("\n//////////////////////////////////////////////////////////////////////////////////\n");
- printf("// //\n");
- printf("// raylib API parser //\n");
- printf("// //\n");
- printf("// more info and bugs-report: github.com/raysan5/raylib/parser //\n");
- printf("// //\n");
- printf("// Copyright (c) 2021-2023 Ramon Santamaria (@raysan5) //\n");
- printf("// //\n");
- printf("//////////////////////////////////////////////////////////////////////////////////\n\n");
- printf("USAGE:\n\n");
- printf(" > raylib_parser [--help] [--input <filename.h>] [--output <filename.ext>] [--format <type>]\n");
- printf("\nOPTIONS:\n\n");
- printf(" -h, --help : Show tool version and command line usage help\n\n");
- printf(" -i, --input <filename.h> : Define input header file to parse.\n");
- printf(" NOTE: If not specified, defaults to: raylib.h\n\n");
- printf(" -o, --output <filename.ext> : Define output file and format.\n");
- printf(" Supported extensions: .txt, .json, .xml, .lua, .h\n");
- printf(" NOTE: If not specified, defaults to: raylib_api.txt\n\n");
- printf(" -f, --format <type> : Define output format for parser data.\n");
- printf(" Supported types: DEFAULT, JSON, XML, LUA, CODE\n\n");
- printf(" -d, --define <DEF> : Define functions specifiers (i.e. RLAPI for raylib.h, RMDEF for raymath.h, etc.)\n");
- printf(" NOTE: If no specifier defined, defaults to: RLAPI\n\n");
- printf(" -t, --truncate <after> : Define string to truncate input after (i.e. \"RLGL IMPLEMENTATION\" for rlgl.h)\n");
- printf(" NOTE: If not specified, the full input file is parsed.\n\n");
- printf("\nEXAMPLES:\n\n");
- printf(" > raylib_parser --input raylib.h --output api.json\n");
- printf(" Process <raylib.h> to generate <api.json>\n\n");
- printf(" > raylib_parser --output raylib_data.info --format XML\n");
- printf(" Process <raylib.h> to generate <raylib_data.info> as XML text data\n\n");
- printf(" > raylib_parser --input raymath.h --output raymath_data.info --format XML\n");
- printf(" Process <raymath.h> to generate <raymath_data.info> as XML text data\n\n");
- }
- // Process command line arguments
- static void ProcessCommandLine(int argc, char *argv[])
- {
- for (int i = 1; i < argc; i++)
- {
- if (IsTextEqual(argv[i], "-h", 2) || IsTextEqual(argv[i], "--help", 6))
- {
- // Show info
- ShowCommandLineInfo();
- exit(0);
- }
- else if (IsTextEqual(argv[i], "-i", 2) || IsTextEqual(argv[i], "--input", 7))
- {
- // Check for valid argument and valid file extension
- if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
- {
- MemoryCopy(inFileName, argv[i + 1], TextLength(argv[i + 1])); // Read input filename
- i++;
- }
- else printf("WARNING: No input file provided\n");
- }
- else if (IsTextEqual(argv[i], "-o", 2) || IsTextEqual(argv[i], "--output", 8))
- {
- if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
- {
- MemoryCopy(outFileName, argv[i + 1], TextLength(argv[i + 1])); // Read output filename
- i++;
- }
- else printf("WARNING: No output file provided\n");
- }
- else if (IsTextEqual(argv[i], "-f", 2) || IsTextEqual(argv[i], "--format", 8))
- {
- if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
- {
- if (IsTextEqual(argv[i + 1], "DEFAULT\0", 8)) outputFormat = DEFAULT;
- else if (IsTextEqual(argv[i + 1], "JSON\0", 5)) outputFormat = JSON;
- else if (IsTextEqual(argv[i + 1], "XML\0", 4)) outputFormat = XML;
- else if (IsTextEqual(argv[i + 1], "LUA\0", 4)) outputFormat = LUA;
- else if (IsTextEqual(argv[i + 1], "CODE\0", 4)) outputFormat = CODE;
- }
- else printf("WARNING: No format parameters provided\n");
- }
- else if (IsTextEqual(argv[i], "-d", 2) || IsTextEqual(argv[i], "--define", 8))
- {
- if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
- {
- MemoryCopy(apiDefine, argv[i + 1], TextLength(argv[i + 1])); // Read functions define
- apiDefine[TextLength(argv[i + 1])] = '\0';
- i++;
- }
- else printf("WARNING: No define key provided\n");
- }
- else if (IsTextEqual(argv[i], "-t", 2) || IsTextEqual(argv[i], "--truncate", 10))
- {
- if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
- {
- MemoryCopy(truncAfter, argv[i + 1], TextLength(argv[i + 1])); // Read truncate marker
- truncAfter[TextLength(argv[i + 1])] = '\0';
- i++;
- }
- }
- }
- }
- // Load text data from file, returns a '\0' terminated string
- // NOTE: text chars array should be freed manually
- static char *LoadFileText(const char *fileName, int *length)
- {
- char *text = NULL;
- if (fileName != NULL)
- {
- FILE *file = fopen(fileName, "rt");
- if (file != NULL)
- {
- // WARNING: When reading a file as 'text' file,
- // text mode causes carriage return-linefeed translation...
- // ...but using fseek() should return correct byte-offset
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
- fseek(file, 0, SEEK_SET);
- if (size > 0)
- {
- text = (char *)calloc((size + 1), sizeof(char));
- unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
- // WARNING: \r\n is converted to \n on reading, so,
- // read bytes count gets reduced by the number of lines
- if (count < (unsigned int)size)
- {
- text = realloc(text, count + 1);
- *length = count;
- }
- else *length = size;
- // Zero-terminate the string
- text[count] = '\0';
- }
- fclose(file);
- }
- }
- return text;
- }
- // Get all lines from a text buffer (expecting lines ending with '\n')
- static char **GetTextLines(const char *buffer, int length, int *linesCount)
- {
- // Get the number of lines in the text
- int count = 0;
- for (int i = 0; i < length; i++) if (buffer[i] == '\n') count++;
- printf("Number of text lines in buffer: %i\n", count);
- // Allocate as many pointers as lines
- char **lines = (char **)malloc(count*sizeof(char **));
- char *bufferPtr = (char *)buffer;
- for (int i = 0; (i < count) || (bufferPtr[0] != '\0'); i++)
- {
- lines[i] = (char *)calloc(MAX_LINE_LENGTH, sizeof(char));
- // Remove line leading spaces
- // Find last index of space/tab character
- int index = 0;
- while ((bufferPtr[index] == ' ') || (bufferPtr[index] == '\t')) index++;
- int j = 0;
- while (bufferPtr[index + j] != '\n')
- {
- lines[i][j] = bufferPtr[index + j];
- j++;
- }
- bufferPtr += (index + j + 1);
- }
- *linesCount = count;
- return lines;
- }
- // Get data type and name from a string containing both
- // NOTE: Useful to parse function parameters and struct fields
- static void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name)
- {
- for (int k = typeNameLen; k > 0; k--)
- {
- if ((typeName[k] == ' ') && (typeName[k - 1] != ','))
- {
- // Function name starts at this point (and ret type finishes at this point)
- MemoryCopy(type, typeName, k);
- MemoryCopy(name, typeName + k + 1, typeNameLen - k - 1);
- break;
- }
- else if (typeName[k] == '*')
- {
- MemoryCopy(type, typeName, k + 1);
- MemoryCopy(name, typeName + k + 1, typeNameLen - k - 1);
- break;
- }
- else if ((typeName[k] == '.') && (typeNameLen == 3)) // Handle varargs ...);
- {
- MemoryCopy(type, "...", 3);
- MemoryCopy(name, "args", 4);
- break;
- }
- }
- }
- // Get comment from a line, do nothing if no comment in line
- static void GetDescription(const char *line, char *description)
- {
- int c = 0;
- int descStart = -1;
- int lastSlash = -2;
- bool isValid = false;
- while (line[c] != '\0')
- {
- if (isValid && (descStart == -1) && (line[c] != ' ')) descStart = c;
- else if (line[c] == '/')
- {
- if (lastSlash == c - 1) isValid = true;
- lastSlash = c;
- }
- c++;
- }
- if (descStart != -1) MemoryCopy(description, &line[descStart], c - descStart);
- }
- // Move array size from name to type
- static void MoveArraySize(char *name, char *type)
- {
- int nameLength = TextLength(name);
- if (name[nameLength - 1] == ']')
- {
- for (int k = nameLength; k > 0; k--)
- {
- if (name[k] == '[')
- {
- int sizeLength = nameLength - k;
- MemoryCopy(&type[TextLength(type)], &name[k], sizeLength);
- name[k] = '\0';
- }
- }
- }
- }
- // Get text length in bytes, check for \0 character
- static unsigned int TextLength(const char *text)
- {
- unsigned int length = 0;
- if (text != NULL) while (*text++) length++;
- return length;
- }
- // Compare two text strings, requires number of characters to compare
- static bool IsTextEqual(const char *text1, const char *text2, unsigned int count)
- {
- bool result = true;
- for (unsigned int i = 0; i < count; i++)
- {
- if (text1[i] != text2[i])
- {
- result = false;
- break;
- }
- }
- return result;
- }
- // Find first text occurrence within a string
- int TextFindIndex(const char *text, const char *find)
- {
- int textLen = TextLength(text);
- int findLen = TextLength(find);
- for (int i = 0; i <= textLen - findLen; i++)
- {
- if (IsTextEqual(&text[i], find, findLen)) return i;
- }
- return -1;
- }
- // Custom memcpy() to avoid <string.h>
- static void MemoryCopy(void *dest, const void *src, unsigned int count)
- {
- char *srcPtr = (char *)src;
- char *destPtr = (char *)dest;
- for (unsigned int i = 0; i < count; i++) destPtr[i] = srcPtr[i];
- }
- // Escape backslashes in a string, writing the escaped string into a static buffer
- static char *EscapeBackslashes(char *text)
- {
- static char buffer[256] = { 0 };
- int count = 0;
- for (int i = 0; (text[i] != '\0') && (i < 255); i++, count++)
- {
- buffer[count] = text[i];
- if (text[i] == '\\')
- {
- buffer[count + 1] = '\\';
- count++;
- }
- }
- buffer[count] = '\0';
- return buffer;
- }
- // Get string of define type
- static const char *StrDefineType(DefineType type)
- {
- switch (type)
- {
- case UNKNOWN: return "UNKNOWN";
- case GUARD: return "GUARD";
- case MACRO: return "MACRO";
- case INT: return "INT";
- case INT_MATH: return "INT_MATH";
- case LONG: return "LONG";
- case LONG_MATH: return "LONG_MATH";
- case FLOAT: return "FLOAT";
- case FLOAT_MATH: return "FLOAT_MATH";
- case DOUBLE: return "DOUBLE";
- case DOUBLE_MATH: return "DOUBLE_MATH";
- case CHAR: return "CHAR";
- case STRING: return "STRING";
- case COLOR: return "COLOR";
- }
- return "";
- }
- /*
- // Replace text string
- // REQUIRES: strlen(), strstr(), strncpy(), strcpy() -> TODO: Replace by custom implementations!
- // WARNING: Returned buffer must be freed by the user (if return != NULL)
- static char *TextReplace(char *text, const char *replace, const char *by)
- {
- // Sanity checks and initialization
- if (!text || !replace || !by) return NULL;
- char *result;
- char *insertPoint; // Next insert point
- char *temp; // Temp pointer
- int replaceLen; // Replace string length of (the string to remove)
- int byLen; // Replacement length (the string to replace replace by)
- int lastReplacePos; // Distance between replace and end of last replace
- int count; // Number of replacements
- replaceLen = strlen(replace);
- if (replaceLen == 0) return NULL; // Empty replace causes infinite loop during count
- byLen = strlen(by);
- // Count the number of replacements needed
- insertPoint = text;
- for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen;
- // Allocate returning string and point temp to it
- temp = result = (char *)malloc(strlen(text) + (byLen - replaceLen)*count + 1);
- if (!result) return NULL; // Memory could not be allocated
- // First time through the loop, all the variable are set correctly from here on,
- // - 'temp' points to the end of the result string
- // - 'insertPoint' points to the next occurrence of replace in text
- // - 'text' points to the remainder of text after "end of replace"
- while (count--)
- {
- insertPoint = strstr(text, replace);
- lastReplacePos = (int)(insertPoint - text);
- temp = strncpy(temp, text, lastReplacePos) + lastReplacePos;
- temp = strcpy(temp, by) + byLen;
- text += lastReplacePos + replaceLen; // Move to next "end of replace"
- }
- // Copy remaind text part after replacement to result (pointed by moving temp)
- strcpy(temp, text);
- return result;
- }
- */
- // Export parsed data in desired format
- static void ExportParsedData(const char *fileName, int format)
- {
- FILE *outFile = fopen(fileName, "wt");
- switch (format)
- {
- case DEFAULT:
- {
- // Print defines info
- fprintf(outFile, "\nDefines found: %i\n\n", defineCount);
- for (int i = 0; i < defineCount; i++)
- {
- fprintf(outFile, "Define %03i: %s\n", i + 1, defines[i].name);
- fprintf(outFile, " Name: %s\n", defines[i].name);
- fprintf(outFile, " Type: %s\n", StrDefineType(defines[i].type));
- fprintf(outFile, " Value: %s\n", defines[i].value);
- fprintf(outFile, " Description: %s\n", defines[i].desc);
- }
- // Print structs info
- fprintf(outFile, "\nStructures found: %i\n\n", structCount);
- for (int i = 0; i < structCount; i++)
- {
- fprintf(outFile, "Struct %02i: %s (%i fields)\n", i + 1, structs[i].name, structs[i].fieldCount);
- fprintf(outFile, " Name: %s\n", structs[i].name);
- fprintf(outFile, " Description: %s\n", structs[i].desc);
- for (int f = 0; f < structs[i].fieldCount; f++)
- {
- fprintf(outFile, " Field[%i]: %s %s ", f + 1, structs[i].fieldType[f], structs[i].fieldName[f]);
- if (structs[i].fieldDesc[f][0]) fprintf(outFile, "// %s\n", structs[i].fieldDesc[f]);
- else fprintf(outFile, "\n");
- }
- }
- // Print aliases info
- fprintf(outFile, "\nAliases found: %i\n\n", aliasCount);
- for (int i = 0; i < aliasCount; i++)
- {
- fprintf(outFile, "Alias %03i: %s\n", i + 1, aliases[i].name);
- fprintf(outFile, " Type: %s\n", aliases[i].type);
- fprintf(outFile, " Name: %s\n", aliases[i].name);
- fprintf(outFile, " Description: %s\n", aliases[i].desc);
- }
- // Print enums info
- fprintf(outFile, "\nEnums found: %i\n\n", enumCount);
- for (int i = 0; i < enumCount; i++)
- {
- fprintf(outFile, "Enum %02i: %s (%i values)\n", i + 1, enums[i].name, enums[i].valueCount);
- fprintf(outFile, " Name: %s\n", enums[i].name);
- fprintf(outFile, " Description: %s\n", enums[i].desc);
- for (int e = 0; e < enums[i].valueCount; e++) fprintf(outFile, " Value[%s]: %i\n", enums[i].valueName[e], enums[i].valueInteger[e]);
- }
- // Print callbacks info
- fprintf(outFile, "\nCallbacks found: %i\n\n", callbackCount);
- for (int i = 0; i < callbackCount; i++)
- {
- fprintf(outFile, "Callback %03i: %s() (%i input parameters)\n", i + 1, callbacks[i].name, callbacks[i].paramCount);
- fprintf(outFile, " Name: %s\n", callbacks[i].name);
- fprintf(outFile, " Return type: %s\n", callbacks[i].retType);
- fprintf(outFile, " Description: %s\n", callbacks[i].desc);
- for (int p = 0; p < callbacks[i].paramCount; p++) fprintf(outFile, " Param[%i]: %s (type: %s)\n", p + 1, callbacks[i].paramName[p], callbacks[i].paramType[p]);
- if (callbacks[i].paramCount == 0) fprintf(outFile, " No input parameters\n");
- }
- // Print functions info
- fprintf(outFile, "\nFunctions found: %i\n\n", funcCount);
- for (int i = 0; i < funcCount; i++)
- {
- fprintf(outFile, "Function %03i: %s() (%i input parameters)\n", i + 1, funcs[i].name, funcs[i].paramCount);
- fprintf(outFile, " Name: %s\n", funcs[i].name);
- fprintf(outFile, " Return type: %s\n", funcs[i].retType);
- fprintf(outFile, " Description: %s\n", funcs[i].desc);
- for (int p = 0; p < funcs[i].paramCount; p++) fprintf(outFile, " Param[%i]: %s (type: %s)\n", p + 1, funcs[i].paramName[p], funcs[i].paramType[p]);
- if (funcs[i].paramCount == 0) fprintf(outFile, " No input parameters\n");
- }
- } break;
- case JSON:
- {
- fprintf(outFile, "{\n");
- // Print defines info
- fprintf(outFile, " \"defines\": [\n");
- for (int i = 0; i < defineCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"name\": \"%s\",\n", defines[i].name);
- fprintf(outFile, " \"type\": \"%s\",\n", StrDefineType(defines[i].type));
- if (defines[i].isHex) // INT or LONG
- {
- fprintf(outFile, " \"value\": %ld,\n", strtol(defines[i].value, NULL, 16));
- }
- else if ((defines[i].type == INT) ||
- (defines[i].type == LONG) ||
- (defines[i].type == FLOAT) ||
- (defines[i].type == DOUBLE) ||
- (defines[i].type == STRING))
- {
- fprintf(outFile, " \"value\": %s,\n", defines[i].value);
- }
- else
- {
- fprintf(outFile, " \"value\": \"%s\",\n", defines[i].value);
- }
- fprintf(outFile, " \"description\": \"%s\"\n", defines[i].desc);
- fprintf(outFile, " }");
- if (i < defineCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ],\n");
- // Print structs info
- fprintf(outFile, " \"structs\": [\n");
- for (int i = 0; i < structCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"name\": \"%s\",\n", structs[i].name);
- fprintf(outFile, " \"description\": \"%s\",\n", EscapeBackslashes(structs[i].desc));
- fprintf(outFile, " \"fields\": [\n");
- for (int f = 0; f < structs[i].fieldCount; f++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"type\": \"%s\",\n", structs[i].fieldType[f]);
- fprintf(outFile, " \"name\": \"%s\",\n", structs[i].fieldName[f]);
- fprintf(outFile, " \"description\": \"%s\"\n", EscapeBackslashes(structs[i].fieldDesc[f]));
- fprintf(outFile, " }");
- if (f < structs[i].fieldCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ]\n");
- fprintf(outFile, " }");
- if (i < structCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ],\n");
- // Print aliases info
- fprintf(outFile, " \"aliases\": [\n");
- for (int i = 0; i < aliasCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"type\": \"%s\",\n", aliases[i].type);
- fprintf(outFile, " \"name\": \"%s\",\n", aliases[i].name);
- fprintf(outFile, " \"description\": \"%s\"\n", aliases[i].desc);
- fprintf(outFile, " }");
- if (i < aliasCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ],\n");
- // Print enums info
- fprintf(outFile, " \"enums\": [\n");
- for (int i = 0; i < enumCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"name\": \"%s\",\n", enums[i].name);
- fprintf(outFile, " \"description\": \"%s\",\n", EscapeBackslashes(enums[i].desc));
- fprintf(outFile, " \"values\": [\n");
- for (int e = 0; e < enums[i].valueCount; e++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"name\": \"%s\",\n", enums[i].valueName[e]);
- fprintf(outFile, " \"value\": %i,\n", enums[i].valueInteger[e]);
- fprintf(outFile, " \"description\": \"%s\"\n", EscapeBackslashes(enums[i].valueDesc[e]));
- fprintf(outFile, " }");
- if (e < enums[i].valueCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ]\n");
- fprintf(outFile, " }");
- if (i < enumCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ],\n");
- // Print callbacks info
- fprintf(outFile, " \"callbacks\": [\n");
- for (int i = 0; i < callbackCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"name\": \"%s\",\n", callbacks[i].name);
- fprintf(outFile, " \"description\": \"%s\",\n", EscapeBackslashes(callbacks[i].desc));
- fprintf(outFile, " \"returnType\": \"%s\"", callbacks[i].retType);
- if (callbacks[i].paramCount == 0) fprintf(outFile, "\n");
- else
- {
- fprintf(outFile, ",\n \"params\": [\n");
- for (int p = 0; p < callbacks[i].paramCount; p++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"type\": \"%s\",\n", callbacks[i].paramType[p]);
- fprintf(outFile, " \"name\": \"%s\"\n", callbacks[i].paramName[p]);
- fprintf(outFile, " }");
- if (p < callbacks[i].paramCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ]\n");
- }
- fprintf(outFile, " }");
- if (i < callbackCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ],\n");
- // Print functions info
- fprintf(outFile, " \"functions\": [\n");
- for (int i = 0; i < funcCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"name\": \"%s\",\n", funcs[i].name);
- fprintf(outFile, " \"description\": \"%s\",\n", EscapeBackslashes(funcs[i].desc));
- fprintf(outFile, " \"returnType\": \"%s\"", funcs[i].retType);
- if (funcs[i].paramCount == 0) fprintf(outFile, "\n");
- else
- {
- fprintf(outFile, ",\n \"params\": [\n");
- for (int p = 0; p < funcs[i].paramCount; p++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " \"type\": \"%s\",\n", funcs[i].paramType[p]);
- fprintf(outFile, " \"name\": \"%s\"\n", funcs[i].paramName[p]);
- fprintf(outFile, " }");
- if (p < funcs[i].paramCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ]\n");
- }
- fprintf(outFile, " }");
- if (i < funcCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " ]\n");
- fprintf(outFile, "}\n");
- } break;
- case XML:
- {
- // XML format to export data:
- /*
- <?xml version="1.0" encoding="Windows-1252" ?>
- <raylibAPI>
- <Defines count="">
- <Define name="" type="" value="" desc="" />
- </Defines>
- <Structs count="">
- <Struct name="" fieldCount="" desc="">
- <Field type="" name="" desc="" />
- <Field type="" name="" desc="" />
- </Struct>
- <Structs>
- <Aliases count="">
- <Alias type="" name="" desc="" />
- </Aliases>
- <Enums count="">
- <Enum name="" valueCount="" desc="">
- <Value name="" integer="" desc="" />
- <Value name="" integer="" desc="" />
- </Enum>
- </Enums>
- <Callbacks count="">
- <Callback name="" retType="" paramCount="" desc="">
- <Param type="" name="" desc="" />
- <Param type="" name="" desc="" />
- </Callback>
- </Callbacks>
- <Functions count="">
- <Function name="" retType="" paramCount="" desc="">
- <Param type="" name="" desc="" />
- <Param type="" name="" desc="" />
- </Function>
- </Functions>
- </raylibAPI>
- */
- fprintf(outFile, "<?xml version=\"1.0\" encoding=\"Windows-1252\" ?>\n");
- fprintf(outFile, "<raylibAPI>\n");
- // Print defines info
- fprintf(outFile, " <Defines count=\"%i\">\n", defineCount);
- for (int i = 0; i < defineCount; i++)
- {
- fprintf(outFile, " <Define name=\"%s\" type=\"%s\" ", defines[i].name, StrDefineType(defines[i].type));
- if (defines[i].type == STRING)
- {
- fprintf(outFile, "value=%s", defines[i].value);
- }
- else
- {
- fprintf(outFile, "value=\"%s\"", defines[i].value);
- }
- fprintf(outFile, " desc=\"%s\" />\n", defines[i].desc);
- }
- fprintf(outFile, " </Defines>\n");
- // Print structs info
- fprintf(outFile, " <Structs count=\"%i\">\n", structCount);
- for (int i = 0; i < structCount; i++)
- {
- fprintf(outFile, " <Struct name=\"%s\" fieldCount=\"%i\" desc=\"%s\">\n", structs[i].name, structs[i].fieldCount, structs[i].desc);
- for (int f = 0; f < structs[i].fieldCount; f++)
- {
- fprintf(outFile, " <Field type=\"%s\" name=\"%s\" desc=\"%s\" />\n", structs[i].fieldType[f], structs[i].fieldName[f], structs[i].fieldDesc[f]);
- }
- fprintf(outFile, " </Struct>\n");
- }
- fprintf(outFile, " </Structs>\n");
- // Print aliases info
- fprintf(outFile, " <Aliases count=\"%i\">\n", aliasCount);
- for (int i = 0; i < aliasCount; i++)
- {
- fprintf(outFile, " <Alias type=\"%s\" name=\"%s\" desc=\"%s\" />\n", aliases[i].name, aliases[i].type, aliases[i].desc);
- }
- fprintf(outFile, " </Aliases>\n");
- // Print enums info
- fprintf(outFile, " <Enums count=\"%i\">\n", enumCount);
- for (int i = 0; i < enumCount; i++)
- {
- fprintf(outFile, " <Enum name=\"%s\" valueCount=\"%i\" desc=\"%s\">\n", enums[i].name, enums[i].valueCount, enums[i].desc);
- for (int v = 0; v < enums[i].valueCount; v++)
- {
- fprintf(outFile, " <Value name=\"%s\" integer=\"%i\" desc=\"%s\" />\n", enums[i].valueName[v], enums[i].valueInteger[v], enums[i].valueDesc[v]);
- }
- fprintf(outFile, " </Enum>\n");
- }
- fprintf(outFile, " </Enums>\n");
- // Print callbacks info
- fprintf(outFile, " <Callbacks count=\"%i\">\n", callbackCount);
- for (int i = 0; i < callbackCount; i++)
- {
- fprintf(outFile, " <Callback name=\"%s\" retType=\"%s\" paramCount=\"%i\" desc=\"%s\">\n", callbacks[i].name, callbacks[i].retType, callbacks[i].paramCount, callbacks[i].desc);
- for (int p = 0; p < callbacks[i].paramCount; p++)
- {
- fprintf(outFile, " <Param type=\"%s\" name=\"%s\" desc=\"%s\" />\n", callbacks[i].paramType[p], callbacks[i].paramName[p], callbacks[i].paramDesc[p]);
- }
- fprintf(outFile, " </Callback>\n");
- }
- fprintf(outFile, " </Callbacks>\n");
- // Print functions info
- fprintf(outFile, " <Functions count=\"%i\">\n", funcCount);
- for (int i = 0; i < funcCount; i++)
- {
- fprintf(outFile, " <Function name=\"%s\" retType=\"%s\" paramCount=\"%i\" desc=\"%s\">\n", funcs[i].name, funcs[i].retType, funcs[i].paramCount, funcs[i].desc);
- for (int p = 0; p < funcs[i].paramCount; p++)
- {
- fprintf(outFile, " <Param type=\"%s\" name=\"%s\" desc=\"%s\" />\n", funcs[i].paramType[p], funcs[i].paramName[p], funcs[i].paramDesc[p]);
- }
- fprintf(outFile, " </Function>\n");
- }
- fprintf(outFile, " </Functions>\n");
- fprintf(outFile, "</raylibAPI>\n");
- } break;
- case LUA:
- {
- fprintf(outFile, "return {\n");
- // Print defines info
- fprintf(outFile, " defines = {\n");
- for (int i = 0; i < defineCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " name = \"%s\",\n", defines[i].name);
- fprintf(outFile, " type = \"%s\",\n", StrDefineType(defines[i].type));
- if ((defines[i].type == INT) ||
- (defines[i].type == LONG) ||
- (defines[i].type == FLOAT) ||
- (defines[i].type == DOUBLE) ||
- (defines[i].type == STRING))
- {
- fprintf(outFile, " value = %s,\n", defines[i].value);
- }
- else
- {
- fprintf(outFile, " value = \"%s\",\n", defines[i].value);
- }
- fprintf(outFile, " description = \"%s\"\n", defines[i].desc);
- fprintf(outFile, " }");
- if (i < defineCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " },\n");
- // Print structs info
- fprintf(outFile, " structs = {\n");
- for (int i = 0; i < structCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " name = \"%s\",\n", structs[i].name);
- fprintf(outFile, " description = \"%s\",\n", EscapeBackslashes(structs[i].desc));
- fprintf(outFile, " fields = {\n");
- for (int f = 0; f < structs[i].fieldCount; f++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " type = \"%s\",\n", structs[i].fieldType[f]);
- fprintf(outFile, " name = \"%s\",\n", structs[i].fieldName[f]);
- fprintf(outFile, " description = \"%s\"\n", EscapeBackslashes(structs[i].fieldDesc[f]));
- fprintf(outFile, " }");
- if (f < structs[i].fieldCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " }\n");
- fprintf(outFile, " }");
- if (i < structCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " },\n");
- // Print aliases info
- fprintf(outFile, " aliases = {\n");
- for (int i = 0; i < aliasCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " type = \"%s\",\n", aliases[i].type);
- fprintf(outFile, " name = \"%s\",\n", aliases[i].name);
- fprintf(outFile, " description = \"%s\"\n", aliases[i].desc);
- fprintf(outFile, " }");
- if (i < aliasCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " },\n");
- // Print enums info
- fprintf(outFile, " enums = {\n");
- for (int i = 0; i < enumCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " name = \"%s\",\n", enums[i].name);
- fprintf(outFile, " description = \"%s\",\n", EscapeBackslashes(enums[i].desc));
- fprintf(outFile, " values = {\n");
- for (int e = 0; e < enums[i].valueCount; e++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " name = \"%s\",\n", enums[i].valueName[e]);
- fprintf(outFile, " value = %i,\n", enums[i].valueInteger[e]);
- fprintf(outFile, " description = \"%s\"\n", EscapeBackslashes(enums[i].valueDesc[e]));
- fprintf(outFile, " }");
- if (e < enums[i].valueCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " }\n");
- fprintf(outFile, " }");
- if (i < enumCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " },\n");
- // Print callbacks info
- fprintf(outFile, " callbacks = {\n");
- for (int i = 0; i < callbackCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " name = \"%s\",\n", callbacks[i].name);
- fprintf(outFile, " description = \"%s\",\n", EscapeBackslashes(callbacks[i].desc));
- fprintf(outFile, " returnType = \"%s\"", callbacks[i].retType);
- if (callbacks[i].paramCount == 0) fprintf(outFile, "\n");
- else
- {
- fprintf(outFile, ",\n params = {\n");
- for (int p = 0; p < callbacks[i].paramCount; p++)
- {
- fprintf(outFile, " {type = \"%s\", name = \"%s\"}", callbacks[i].paramType[p], callbacks[i].paramName[p]);
- if (p < callbacks[i].paramCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " }\n");
- }
- fprintf(outFile, " }");
- if (i < callbackCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " },\n");
- // Print functions info
- fprintf(outFile, " functions = {\n");
- for (int i = 0; i < funcCount; i++)
- {
- fprintf(outFile, " {\n");
- fprintf(outFile, " name = \"%s\",\n", funcs[i].name);
- fprintf(outFile, " description = \"%s\",\n", EscapeBackslashes(funcs[i].desc));
- fprintf(outFile, " returnType = \"%s\"", funcs[i].retType);
- if (funcs[i].paramCount == 0) fprintf(outFile, "\n");
- else
- {
- fprintf(outFile, ",\n params = {\n");
- for (int p = 0; p < funcs[i].paramCount; p++)
- {
- fprintf(outFile, " {type = \"%s\", name = \"%s\"}", funcs[i].paramType[p], funcs[i].paramName[p]);
- if (p < funcs[i].paramCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " }\n");
- }
- fprintf(outFile, " }");
- if (i < funcCount - 1) fprintf(outFile, ",\n");
- else fprintf(outFile, "\n");
- }
- fprintf(outFile, " }\n");
- fprintf(outFile, "}\n");
- } break;
- case CODE:
- default: break;
- }
- fclose(outFile);
- }
|