Improved raylib parser to export data as XML
- Improved command-line - Added XML support - Added sample outputs: DEFAULT, JSON, XML - Reviewed LoadFileText() bug - Removed trailing spaces
This commit is contained in:
parent
3e68059556
commit
d875891a3c
4 changed files with 13184 additions and 257 deletions
6668
parser/raylib_api.json
Normal file
6668
parser/raylib_api.json
Normal file
File diff suppressed because it is too large
Load diff
3568
parser/raylib_api.txt
Normal file
3568
parser/raylib_api.txt
Normal file
File diff suppressed because it is too large
Load diff
2509
parser/raylib_api.xml
Normal file
2509
parser/raylib_api.xml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,9 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
|
|
||||||
raylib parser - raylib header parser
|
raylib API parser
|
||||||
|
|
||||||
This parser scans raylib.h to get information about structs, enums and functions.
|
This parser scans raylib.h to get API information about structs, enums and functions.
|
||||||
All data is separated into parts, usually as strings. The following types are used for data:
|
All data is divided into pieces, usually as strings. The following types are used for data:
|
||||||
|
|
||||||
- struct FunctionInfo
|
- struct FunctionInfo
|
||||||
- struct StructInfo
|
- struct StructInfo
|
||||||
|
@ -38,13 +38,15 @@
|
||||||
<valueName[3]> <valueDesc[3]>
|
<valueName[3]> <valueDesc[3]>
|
||||||
} <name>;
|
} <name>;
|
||||||
|
|
||||||
NOTE: Multiple options are supported:
|
NOTE: Multiple options are supported for enums:
|
||||||
- If value is not provided, (<valueInteger[i -1]> + 1) is assigned
|
- If value is not provided, (<valueInteger[i -1]> + 1) is assigned
|
||||||
- Value description can be provided or not
|
- Value description can be provided or not
|
||||||
|
|
||||||
This parser could work with other C header files if mentioned constraints are followed.
|
OTHER NOTES:
|
||||||
|
|
||||||
This parser does not require <string.h> library, all data is parsed directly from char buffers.
|
- 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
|
LICENSE: zlib/libpng
|
||||||
|
|
||||||
|
@ -55,6 +57,8 @@
|
||||||
|
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), calloc(), realloc(), free(), atoi(), strtol()
|
#include <stdlib.h> // Required for: malloc(), calloc(), realloc(), free(), atoi(), strtol()
|
||||||
#include <stdio.h> // Required for: printf(), fopen(), fseek(), ftell(), fread(), fclose()
|
#include <stdio.h> // Required for: printf(), fopen(), fseek(), ftell(), fread(), fclose()
|
||||||
#include <stdbool.h> // Required for: bool
|
#include <stdbool.h> // Required for: bool
|
||||||
|
@ -66,8 +70,6 @@
|
||||||
#define MAX_LINE_LENGTH 512 // Maximum length of one line (including comments)
|
#define MAX_LINE_LENGTH 512 // Maximum length of one line (including comments)
|
||||||
#define MAX_STRUCT_LINE_LENGTH 2048 // Maximum length of one struct (multiple lines)
|
#define MAX_STRUCT_LINE_LENGTH 2048 // Maximum length of one struct (multiple lines)
|
||||||
|
|
||||||
enum OutputFormat { PlainText, JSON }; // Which format the header information should be in
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -79,6 +81,7 @@ typedef struct FunctionInfo {
|
||||||
int paramCount; // Number of function parameters
|
int paramCount; // Number of function parameters
|
||||||
char paramType[12][32]; // Parameters type (max: 12 parameters)
|
char paramType[12][32]; // Parameters type (max: 12 parameters)
|
||||||
char paramName[12][32]; // Parameters name (max: 12 parameters)
|
char paramName[12][32]; // Parameters name (max: 12 parameters)
|
||||||
|
char paramDesc[12][8]; // Parameters description (max: 12 parameters)
|
||||||
} FunctionInfo;
|
} FunctionInfo;
|
||||||
|
|
||||||
// Struct info data
|
// Struct info data
|
||||||
|
@ -101,54 +104,65 @@ typedef struct EnumInfo {
|
||||||
char valueDesc[128][64]; // Value description (max: 128 values)
|
char valueDesc[128][64]; // Value description (max: 128 values)
|
||||||
} EnumInfo;
|
} EnumInfo;
|
||||||
|
|
||||||
|
// Output format for parsed data
|
||||||
|
typedef enum { DEFAULT = 0, JSON, XML } OutputFormat;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static int funcCount = 0;
|
||||||
|
static int structCount = 0;
|
||||||
|
static int enumCount = 0;
|
||||||
|
static FunctionInfo *funcs = NULL;
|
||||||
|
static StructInfo *structs = NULL;
|
||||||
|
static EnumInfo *enums = NULL;
|
||||||
|
|
||||||
|
// Command line variables
|
||||||
|
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
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
char *LoadFileText(const char *fileName, int *length);
|
static void ShowCommandLineInfo(void); // Show command line usage info
|
||||||
char **GetTextLines(const char *buffer, int length, int *linesCount);
|
static void ProcessCommandLine(int argc, char *argv[]); // Process command line input
|
||||||
void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name);
|
|
||||||
bool IsTextEqual(const char *text1, const char *text2, unsigned int count);
|
|
||||||
void MemoryCopy(void *dest, const void *src, unsigned int count);
|
|
||||||
char* CharReplace(char* text, char search, char replace);
|
|
||||||
|
|
||||||
// Main entry point
|
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 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 void MemoryCopy(void *dest, const void *src, unsigned int count);
|
||||||
|
static char* CharReplace(char* text, char search, char replace);
|
||||||
|
|
||||||
|
static void ExportParsedData(const char *fileName, int format); // Export parsed data in desired format
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
// Help
|
if (argc > 1) ProcessCommandLine(argc, argv);
|
||||||
if (argv[1] != NULL && IsTextEqual(argv[1], "--help", 6)) {
|
|
||||||
printf("Usage:\n");
|
|
||||||
printf(" raylib_parser [--json]\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow changing the output format.
|
if (inFileName[0] == '\0') MemoryCopy(inFileName, "../src/raylib.h\0", 16);
|
||||||
int outputFormat = 0;
|
|
||||||
if (argv[1] != NULL && IsTextEqual(argv[1], "--json", 6)) {
|
|
||||||
outputFormat = JSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = 0;
|
int length = 0;
|
||||||
char *buffer = LoadFileText("../src/raylib.h", &length);
|
char *buffer = LoadFileText(inFileName, &length);
|
||||||
|
|
||||||
// Preprocess buffer to get separate lines
|
// Preprocess buffer to get separate lines
|
||||||
// NOTE: GetTextLines() also removes leading spaces/tabs
|
// NOTE: GetTextLines() also removes leading spaces/tabs
|
||||||
int linesCount = 0;
|
int linesCount = 0;
|
||||||
char **lines = GetTextLines(buffer, length, &linesCount);
|
char **lines = GetTextLines(buffer, length, &linesCount);
|
||||||
|
|
||||||
// Print buffer lines
|
|
||||||
//for (int i = 0; i < linesCount; i++) printf("_%s_\n", lines[i]);
|
|
||||||
|
|
||||||
// Function lines pointers, selected from buffer "lines"
|
// Function lines pointers, selected from buffer "lines"
|
||||||
int funcCount = 0;
|
|
||||||
char **funcLines = (char **)malloc(MAX_FUNCS_TO_PARSE*sizeof(char *));
|
char **funcLines = (char **)malloc(MAX_FUNCS_TO_PARSE*sizeof(char *));
|
||||||
|
|
||||||
// Structs data (multiple lines), selected from "buffer"
|
// Structs data (multiple lines), selected from "buffer"
|
||||||
int structCount = 0;
|
|
||||||
char **structLines = (char **)malloc(MAX_STRUCTS_TO_PARSE*sizeof(char *));
|
char **structLines = (char **)malloc(MAX_STRUCTS_TO_PARSE*sizeof(char *));
|
||||||
for (int i = 0; i < MAX_STRUCTS_TO_PARSE; i++) structLines[i] = (char *)calloc(MAX_STRUCT_LINE_LENGTH, sizeof(char));
|
for (int i = 0; i < MAX_STRUCTS_TO_PARSE; i++) structLines[i] = (char *)calloc(MAX_STRUCT_LINE_LENGTH, sizeof(char));
|
||||||
|
|
||||||
// Enums lines pointers, selected from buffer "lines"
|
// Enums lines pointers, selected from buffer "lines"
|
||||||
int enumCount = 0;
|
|
||||||
int *enumLines = (int *)malloc(MAX_ENUMS_TO_PARSE*sizeof(int));
|
int *enumLines = (int *)malloc(MAX_ENUMS_TO_PARSE*sizeof(int));
|
||||||
|
|
||||||
// Prepare required lines for parsing
|
// Prepare required lines for parsing
|
||||||
|
@ -166,9 +180,6 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print function lines
|
|
||||||
//for (int i = 0; i < funcCount; i++) printf("%s\n", funcLines[i]);
|
|
||||||
|
|
||||||
// Read structs data (multiple lines, read directly from buffer)
|
// Read structs data (multiple lines, read directly from buffer)
|
||||||
// TODO: Parse structs data from "lines" instead of "buffer" -> Easier to get struct definition
|
// TODO: Parse structs data from "lines" instead of "buffer" -> Easier to get struct definition
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
|
@ -245,7 +256,7 @@ int main(int argc, char* argv[])
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Structs info data
|
// Structs info data
|
||||||
StructInfo *structs = (StructInfo *)calloc(MAX_STRUCTS_TO_PARSE, sizeof(StructInfo));
|
structs = (StructInfo *)calloc(MAX_STRUCTS_TO_PARSE, sizeof(StructInfo));
|
||||||
|
|
||||||
for (int i = 0; i < structCount; i++)
|
for (int i = 0; i < structCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -318,7 +329,7 @@ int main(int argc, char* argv[])
|
||||||
free(structLines);
|
free(structLines);
|
||||||
|
|
||||||
// Enum info data
|
// Enum info data
|
||||||
EnumInfo *enums = (EnumInfo *)calloc(MAX_ENUMS_TO_PARSE, sizeof(EnumInfo));
|
enums = (EnumInfo *)calloc(MAX_ENUMS_TO_PARSE, sizeof(EnumInfo));
|
||||||
|
|
||||||
for (int i = 0; i < enumCount; i++)
|
for (int i = 0; i < enumCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -401,7 +412,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions info data
|
// Functions info data
|
||||||
FunctionInfo *funcs = (FunctionInfo *)calloc(MAX_FUNCS_TO_PARSE, sizeof(FunctionInfo));
|
funcs = (FunctionInfo *)calloc(MAX_FUNCS_TO_PARSE, sizeof(FunctionInfo));
|
||||||
|
|
||||||
for (int i = 0; i < funcCount; i++)
|
for (int i = 0; i < funcCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -471,7 +482,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < linesCount; i++) free(lines[i]);
|
//for (int i = 0; i < linesCount; i++) free(lines[i]);
|
||||||
free(lines);
|
free(lines);
|
||||||
free(funcLines);
|
free(funcLines);
|
||||||
|
|
||||||
|
@ -481,132 +492,16 @@ int main(int argc, char* argv[])
|
||||||
// enums[] -> We have all the enums decomposed into pieces for further analysis
|
// enums[] -> We have all the enums decomposed into pieces for further analysis
|
||||||
// funcs[] -> We have all the functions decomposed into pieces for further analysis
|
// funcs[] -> We have all the functions decomposed into pieces for further analysis
|
||||||
|
|
||||||
// Print structs info
|
// Process input file to output
|
||||||
switch (outputFormat)
|
if (outFileName[0] == '\0') MemoryCopy(outFileName, "raylib_api.txt\0", 15);
|
||||||
{
|
|
||||||
case PlainText: {
|
|
||||||
printf("\nStructures found: %i\n\n", structCount);
|
|
||||||
for (int i = 0; i < structCount; i++)
|
|
||||||
{
|
|
||||||
printf("Struct %02i: %s (%i fields)\n", i + 1, structs[i].name, structs[i].fieldCount);
|
|
||||||
//printf("Description: %s\n", structs[i].desc);
|
|
||||||
for (int f = 0; f < structs[i].fieldCount; f++) printf(" Fields %i: %s %s %s\n", f + 1, structs[i].fieldType[f], structs[i].fieldName[f], structs[i].fieldDesc[f]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print enums info
|
printf("\nInput file: %s", inFileName);
|
||||||
printf("\nEnums found: %i\n\n", enumCount);
|
printf("\nOutput file: %s", outFileName);
|
||||||
for (int i = 0; i < enumCount; i++)
|
if (outputFormat == DEFAULT) printf("\nOutput format: DEFAULT\n\n");
|
||||||
{
|
else if (outputFormat == JSON) printf("\nOutput format: JSON\n\n");
|
||||||
printf("Enum %02i: %s (%i values)\n", i + 1, enums[i].name, enums[i].valueCount);
|
else if (outputFormat == XML) printf("\nOutput format: XML\n\n");
|
||||||
//printf("Description: %s\n", enums[i].desc);
|
|
||||||
for (int e = 0; e < enums[i].valueCount; e++) printf(" Value %s: %i\n", enums[i].valueName[e], enums[i].valueInteger[e]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print function info
|
ExportParsedData(outFileName, outputFormat);
|
||||||
printf("\nFunctions found: %i\n\n", funcCount);
|
|
||||||
for (int i = 0; i < funcCount; i++)
|
|
||||||
{
|
|
||||||
printf("Function %03i: %s() (%i input parameters)\n", i + 1, funcs[i].name, funcs[i].paramCount);
|
|
||||||
printf(" Description: %s\n", funcs[i].desc);
|
|
||||||
printf(" Return type: %s\n", funcs[i].retType);
|
|
||||||
for (int p = 0; p < funcs[i].paramCount; p++) printf(" Param %i: %s (type: %s)\n", p + 1, funcs[i].paramName[p], funcs[i].paramType[p]);
|
|
||||||
if (funcs[i].paramCount == 0) printf(" No input parameters\n");
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case JSON: {
|
|
||||||
printf("{\n");
|
|
||||||
printf(" \"structs\": [\n");
|
|
||||||
for (int i = 0; i < structCount; i++)
|
|
||||||
{
|
|
||||||
printf(" {\n");
|
|
||||||
printf(" \"name\": \"%s\",\n", structs[i].name);
|
|
||||||
printf(" \"description\": \"%s\",\n", structs[i].desc);
|
|
||||||
printf(" \"fields\": [\n");
|
|
||||||
for (int f = 0; f < structs[i].fieldCount; f++)
|
|
||||||
{
|
|
||||||
printf(" {\n");
|
|
||||||
printf(" \"name\": \"%s\",\n", structs[i].fieldName[f]),
|
|
||||||
printf(" \"type\": \"%s\",\n", structs[i].fieldType[f]),
|
|
||||||
printf(" \"description\": \"%s\"\n", structs[i].fieldDesc[f] + 3),
|
|
||||||
printf(" }");
|
|
||||||
if (f < structs[i].fieldCount - 1)
|
|
||||||
printf(",\n");
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf(" ]\n");
|
|
||||||
printf(" }");
|
|
||||||
if (i < structCount - 1)
|
|
||||||
printf(",\n");
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf(" ],\n");
|
|
||||||
|
|
||||||
// Print enums info
|
|
||||||
printf(" \"enums\": [\n");
|
|
||||||
for (int i = 0; i < enumCount; i++)
|
|
||||||
{
|
|
||||||
printf(" {\n");
|
|
||||||
printf(" \"name\": \"%s\",\n", enums[i].name);
|
|
||||||
printf(" \"description\": \"%s\",\n", enums[i].desc + 3);
|
|
||||||
printf(" \"values\": [\n");
|
|
||||||
for (int e = 0; e < enums[i].valueCount; e++)
|
|
||||||
{
|
|
||||||
printf(" {\n");
|
|
||||||
printf(" \"name\": \"%s\",\n", enums[i].valueName[e]),
|
|
||||||
printf(" \"value\": %i,\n", enums[i].valueInteger[e]),
|
|
||||||
printf(" \"description\": \"%s\"\n", enums[i].valueDesc[e] + 3),
|
|
||||||
printf(" }");
|
|
||||||
if (e < enums[i].valueCount - 1)
|
|
||||||
printf(",\n");
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf(" ]\n");
|
|
||||||
printf(" }");
|
|
||||||
if (i < enumCount - 1)
|
|
||||||
printf(",\n");
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf(" ],\n");
|
|
||||||
|
|
||||||
// Print function info
|
|
||||||
printf(" \"functions\": [\n");
|
|
||||||
for (int i = 0; i < funcCount; i++)
|
|
||||||
{
|
|
||||||
printf(" {\n");
|
|
||||||
printf(" \"name\": \"%s\",\n", funcs[i].name);
|
|
||||||
printf(" \"description\": \"%s\",\n", CharReplace(funcs[i].desc, '\\', ' ') + 3);
|
|
||||||
printf(" \"returnType\": \"%s\"", funcs[i].retType);
|
|
||||||
|
|
||||||
if (funcs[i].paramCount == 0)
|
|
||||||
printf("\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(",\n \"params\": {\n");
|
|
||||||
for (int p = 0; p < funcs[i].paramCount; p++)
|
|
||||||
{
|
|
||||||
printf(" \"%s\": \"%s\"", funcs[i].paramName[p], funcs[i].paramType[p]);
|
|
||||||
if (p < funcs[i].paramCount - 1)
|
|
||||||
printf(",\n");
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf(" }\n");
|
|
||||||
}
|
|
||||||
printf(" }");
|
|
||||||
|
|
||||||
if (i < funcCount - 1)
|
|
||||||
printf(",\n");
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf(" ]\n");
|
|
||||||
printf("}\n");
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(funcs);
|
free(funcs);
|
||||||
free(structs);
|
free(structs);
|
||||||
|
@ -616,10 +511,84 @@ int main(int argc, char* argv[])
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition
|
// 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 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, .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\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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
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 printf("WARNING: No format parameters provided\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load text data from file, returns a '\0' terminated string
|
// Load text data from file, returns a '\0' terminated string
|
||||||
// NOTE: text chars array should be freed manually
|
// NOTE: text chars array should be freed manually
|
||||||
char *LoadFileText(const char *fileName, int *length)
|
static char *LoadFileText(const char *fileName, int *length)
|
||||||
{
|
{
|
||||||
char *text = NULL;
|
char *text = NULL;
|
||||||
|
|
||||||
|
@ -638,14 +607,17 @@ char *LoadFileText(const char *fileName, int *length)
|
||||||
|
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
{
|
{
|
||||||
*length = size;
|
|
||||||
|
|
||||||
text = (char *)calloc((size + 1), sizeof(char));
|
text = (char *)calloc((size + 1), sizeof(char));
|
||||||
unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
|
unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
|
||||||
|
|
||||||
// WARNING: \r\n is converted to \n on reading, so,
|
// WARNING: \r\n is converted to \n on reading, so,
|
||||||
// read bytes count gets reduced by the number of lines
|
// read bytes count gets reduced by the number of lines
|
||||||
if (count < (unsigned int)size) text = realloc(text, count + 1);
|
if (count < (unsigned int)size)
|
||||||
|
{
|
||||||
|
text = realloc(text, count + 1);
|
||||||
|
*length = count;
|
||||||
|
}
|
||||||
|
else *length = size;
|
||||||
|
|
||||||
// Zero-terminate the string
|
// Zero-terminate the string
|
||||||
text[count] = '\0';
|
text[count] = '\0';
|
||||||
|
@ -659,15 +631,13 @@ char *LoadFileText(const char *fileName, int *length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all lines from a text buffer (expecting lines ending with '\n')
|
// Get all lines from a text buffer (expecting lines ending with '\n')
|
||||||
char **GetTextLines(const char *buffer, int length, int *linesCount)
|
static char **GetTextLines(const char *buffer, int length, int *linesCount)
|
||||||
{
|
{
|
||||||
//#define MAX_LINE_LENGTH 512
|
|
||||||
|
|
||||||
// Get the number of lines in the text
|
// Get the number of lines in the text
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < length; i++) if (buffer[i] == '\n') count++;
|
for (int i = 0; i < length; i++) if (buffer[i] == '\n') count++;
|
||||||
|
|
||||||
//printf("Number of text lines in buffer: %i\n", count);
|
printf("Number of text lines in buffer: %i\n", count);
|
||||||
|
|
||||||
// Allocate as many pointers as lines
|
// Allocate as many pointers as lines
|
||||||
char **lines = (char **)malloc(count*sizeof(char **));
|
char **lines = (char **)malloc(count*sizeof(char **));
|
||||||
|
@ -699,7 +669,7 @@ char **GetTextLines(const char *buffer, int length, int *linesCount)
|
||||||
|
|
||||||
// Get data type and name from a string containing both
|
// Get data type and name from a string containing both
|
||||||
// NOTE: Useful to parse function parameters and struct fields
|
// NOTE: Useful to parse function parameters and struct fields
|
||||||
void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name)
|
static void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name)
|
||||||
{
|
{
|
||||||
for (int k = typeNameLen; k > 0; k--)
|
for (int k = typeNameLen; k > 0; k--)
|
||||||
{
|
{
|
||||||
|
@ -719,8 +689,18 @@ void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
// Custom memcpy() to avoid <string.h>
|
// Custom memcpy() to avoid <string.h>
|
||||||
void MemoryCopy(void *dest, const void *src, unsigned int count)
|
static void MemoryCopy(void *dest, const void *src, unsigned int count)
|
||||||
{
|
{
|
||||||
char *srcPtr = (char *)src;
|
char *srcPtr = (char *)src;
|
||||||
char *destPtr = (char *)dest;
|
char *destPtr = (char *)dest;
|
||||||
|
@ -729,7 +709,7 @@ void MemoryCopy(void *dest, const void *src, unsigned int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare two text strings, requires number of characters to compare
|
// Compare two text strings, requires number of characters to compare
|
||||||
bool IsTextEqual(const char *text1, const char *text2, unsigned int count)
|
static bool IsTextEqual(const char *text1, const char *text2, unsigned int count)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
|
@ -746,7 +726,7 @@ bool IsTextEqual(const char *text1, const char *text2, unsigned int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search and replace a character within a string.
|
// Search and replace a character within a string.
|
||||||
char* CharReplace(char* text, char search, char replace)
|
static char* CharReplace(char* text, char search, char replace)
|
||||||
{
|
{
|
||||||
for (int i = 0; text[i] != '\0'; i++)
|
for (int i = 0; text[i] != '\0'; i++)
|
||||||
if (text[i] == search)
|
if (text[i] == search)
|
||||||
|
@ -758,7 +738,7 @@ char* CharReplace(char* text, char search, char replace)
|
||||||
// Replace text string
|
// Replace text string
|
||||||
// REQUIRES: strlen(), strstr(), strncpy(), strcpy() -> TODO: Replace by custom implementations!
|
// REQUIRES: strlen(), strstr(), strncpy(), strcpy() -> TODO: Replace by custom implementations!
|
||||||
// WARNING: Returned buffer must be freed by the user (if return != NULL)
|
// WARNING: Returned buffer must be freed by the user (if return != NULL)
|
||||||
char *TextReplace(char *text, const char *replace, const char *by)
|
static char *TextReplace(char *text, const char *replace, const char *by)
|
||||||
{
|
{
|
||||||
// Sanity checks and initialization
|
// Sanity checks and initialization
|
||||||
if (!text || !replace || !by) return NULL;
|
if (!text || !replace || !by) return NULL;
|
||||||
|
@ -805,3 +785,205 @@ char *TextReplace(char *text, const char *replace, const char *by)
|
||||||
return result;
|
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 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 + 3);
|
||||||
|
for (int f = 0; f < structs[i].fieldCount; f++) fprintf(outFile, " Field[%i]: %s %s %s\n", f + 1, structs[i].fieldType[f], structs[i].fieldName[f], structs[i].fieldDesc[f]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 + 3);
|
||||||
|
for (int e = 0; e < enums[i].valueCount; e++) fprintf(outFile, " Value[%s]: %i\n", enums[i].valueName[e], enums[i].valueInteger[e]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 + 3);
|
||||||
|
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 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", structs[i].desc);
|
||||||
|
fprintf(outFile, " \"fields\": [\n");
|
||||||
|
for (int f = 0; f < structs[i].fieldCount; f++)
|
||||||
|
{
|
||||||
|
fprintf(outFile, " {\n");
|
||||||
|
fprintf(outFile, " \"name\": \"%s\",\n", structs[i].fieldName[f]),
|
||||||
|
fprintf(outFile, " \"type\": \"%s\",\n", structs[i].fieldType[f]),
|
||||||
|
fprintf(outFile, " \"description\": \"%s\"\n", structs[i].fieldDesc[f] + 3),
|
||||||
|
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 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", enums[i].desc + 3);
|
||||||
|
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", enums[i].valueDesc[e] + 3),
|
||||||
|
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 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", CharReplace(funcs[i].desc, '\\', ' ') + 3);
|
||||||
|
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, " \"%s\": \"%s\"", funcs[i].paramName[p], funcs[i].paramType[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 XML:
|
||||||
|
{
|
||||||
|
// XML format to export data:
|
||||||
|
/*
|
||||||
|
<?xml version="1.0" encoding="Windows-1252" ?>
|
||||||
|
<raylibAPI>
|
||||||
|
<Structs count="">
|
||||||
|
<Struct name="" fieldCount="" desc="">
|
||||||
|
<Field type="" name="" desc="">
|
||||||
|
<Field type="" name="" desc="">
|
||||||
|
</Struct>
|
||||||
|
<Structs>
|
||||||
|
<Enums count="">
|
||||||
|
<Enum name="" valueCount="" desc="">
|
||||||
|
<Value name="" integer="" desc="">
|
||||||
|
<Value name="" integer="" desc="">
|
||||||
|
</Enum>
|
||||||
|
</Enums>
|
||||||
|
<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 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 + 3);
|
||||||
|
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] + 3);
|
||||||
|
}
|
||||||
|
fprintf(outFile, " </Struct>\n");
|
||||||
|
}
|
||||||
|
fprintf(outFile, " </Structs>\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 + 3);
|
||||||
|
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] + 3);
|
||||||
|
}
|
||||||
|
fprintf(outFile, " </Enum>\n");
|
||||||
|
}
|
||||||
|
fprintf(outFile, " </Enums>\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 + 3);
|
||||||
|
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] + 3);
|
||||||
|
}
|
||||||
|
fprintf(outFile, " </Function>\n");
|
||||||
|
}
|
||||||
|
fprintf(outFile, " </Functions>\n");
|
||||||
|
|
||||||
|
fprintf(outFile, "</raylibAPI>\n");
|
||||||
|
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(outFile);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue