Files
libsst/libsst-glapi/parsegl.c
2026-04-03 00:22:39 -05:00

357 lines
6.8 KiB
C

/*
parsegl.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 12/12/2012
Purpose:
Parse GL function definitions and generate libsst-glapi code/headers
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define DEFS "gl33.txt"
typedef struct GLFunc
{
char name[64]; /* Name of OpenGL function, sans "gl" prefix */
char returnType[64]; /* C return value type */
char argTypes[16][64]; /* C argument type */
unsigned int constBitmask; /* If bit 'n' is set, then parameter 'n' is a const parameter. highest bit is return type */
unsigned int nrArgs; /* Number of arguments in the function */
struct GLFunc* next; /* Next function in the list */
} GLFunc;
/* These test if parameter is marked as "const" */
#define ISCONST(func, n) (func->constBitmask & (1u << n))
#define ISCONSTRETURN(func) ISCONST(func, 31u)
/* Linked list of functions parsed */
GLFunc* first = NULL;
GLFunc* last = NULL;
unsigned int totalParsed = 0;
/******************************************************************************/
static void parseLine(const char* line);
static void genStruct(FILE* fp);
static void genLinkCode(FILE* fp);
static void genMacros(FILE* fp);
static void autogenHeader(FILE* fp) { fprintf(fp, "/* AUTOGENERATED BY parsegl.c -- DO NOT MODIFY */\n"); }
/******************************************************************************/
int main()
{
char line[1024];
FILE* fp = fopen(DEFS, "r");
int c;
int eolFound = 0;
int k = 0;
/* Can't open GL function definitions? */
if(fp == NULL)
{
printf("Could not open file \"%s\" for reading\n", DEFS);
exit(1);
}
/* Read each line of text until EOF */
do
{
c = fgetc(fp);
switch(c)
{
/* These end a line */
case 0x0A:
case 0x0D:
eolFound = 1;
line[k] = '\0';
k=0;
break;
case EOF:
break;
/* Otherwise, copy the line */
default:
line[k] = (char)c;
k++;
break;
}
/* Time to parse a line? */
if(eolFound)
{
parseLine(line);
eolFound = 0;
}
} while(c != EOF);
fclose(fp);
printf("%u GL functions parsed\n", totalParsed);
/* Write API structure */
fp = fopen("SST_GLAPIStruct.h", "w");
if(fp != NULL)
{
autogenHeader(fp);
genStruct(fp);
fclose(fp);
}
/* Write runtime API resolution */
fp = fopen("SST_GLAPIStruct.c", "w");
if(fp != NULL)
{
autogenHeader(fp);
genLinkCode(fp);
fclose(fp);
}
/* Write canonical glDoThing() macros */
fp = fopen("SST_GLAPIMacros.h", "w");
if(fp != NULL)
{
autogenHeader(fp);
genMacros(fp);
fclose(fp);
}
/* Done */
return 0;
}
/******************************************************************************/
/* Read the line and parse out any GL function definitions */
static void parseLine(const char* line)
{
int exitTime;
int k = 0;
int nrFound = 0;
char word[64];
char* s = word;
GLFunc* func;
/* Ignore leading whitespace */
while(isspace(*line))
line++;
/* Nothing to parse? */
if(strlen(line) == 0)
return;
/* Ignore comment lines */
if(line[0] == '/' && line[1] == '/')
return;
memset(word, 0, sizeof(word));
func = (GLFunc*)calloc(1, sizeof(*func));
/* Pull words out of the line */
exitTime = 0;
do
{
if(line[k] == '\0')
{
exitTime = 1;
*s = '\0';
}
if(isspace(line[k]))
*s = '\0';
else
*s = line[k];
k++;
/* Parse word time? */
if(*s == '\0')
{
s = word;
/* Skip all blank spaces */
while(isspace(*s))
s++;
/* Non-zero lengths only, please */
if(strlen(s) >= 0)
{
/* First word is the return value type */
if(nrFound == 0)
{
if(strstr(s, "const_"))
{
func->constBitmask |= (1u << 31);
s += strlen("const_");
}
strcpy(func->returnType, s);
}
else if (nrFound == 1) /* Second word is the function name */
strcpy(func->name, s);
else /* Remaining words are arguments */
{
int arg = nrFound - 2;
/* Is it a const arg? */
if(strstr(s, "const_"))
{
func->constBitmask |= (1u << arg);
s += strlen("const_");
}
strcpy(func->argTypes[arg], s);
func->nrArgs++;
}
nrFound++;
} /* non-zero length string */
s = word;
} /* Done parsing word */
else
s++;
} while(!exitTime);
/* Store */
if(first == NULL)
first = func;
if(last != NULL)
last->next = func;
last = func;
totalParsed++;
}
/******************************************************************************/
static void genStruct(FILE* fp)
{
const GLFunc* func = first;
fprintf(fp,
"#ifndef _SST_GLAPISTRUCT_H\n"
"#define _SST_GLAPISTRUCT_H\n\n");
fprintf(fp, "#include <SST/SST_GLAPIDefs.h>\n\n");
fprintf(fp, "typedef struct SST_GLAPI\n{\n");
while(func)
{
unsigned int i;
/* Return value and name of function */
fprintf(fp, "\t%s%s (OGLCALL* %s)(",
ISCONSTRETURN(func) ? "const " : "",
func->returnType,
func->name);
/* Run through each valid argument */
for(i=0; i<func->nrArgs; i++)
{
if(ISCONST(func, i))
fprintf(fp, "const ");
fprintf(fp, "%s", func->argTypes[i]);
if(i != func->nrArgs-1)
fprintf(fp, ", ");
}
fprintf(fp, ");\n");
func = func->next;
}
fprintf(fp, "\t/*======================================*/\n");
fprintf(fp, "\tvoid* libGL; /* OpenGL library handle */\n");
fprintf(fp, "\tchar* libGLName; /* OpenGL library name */\n");
fprintf(fp, "} SST_GLAPI;\n#endif\n\n");
}
static void genLinkCode(FILE* fp)
{
const GLFunc* func = first;
fprintf(fp, "#include <SST/SST_GLAPIStruct.h>\n");
fprintf(fp, "#include \"GLAPIPrivate.h\"\n\n");
fprintf(fp, "void resolveGLAPI(const GLAPIResolver* resolver, struct SST_GLAPI* api)\n{\n");
while(func)
{
unsigned int i;
/* Resolve it */
fprintf(fp, "\tapi->%s = resolveGLSymbol(resolver, \"gl%s\");\n",
func->name, func->name);
func = func->next;
}
fprintf(fp, "\n}\n");
}
static void genMacros(FILE* fp)
{
const GLFunc* func = first;
fprintf(fp,
"#ifndef _SST_GLAPIMACROS_H\n"
"#define _SST_GLAPIMACROS_H\n\n");
while(func)
{
unsigned int i;
/* #define a macro for it */
fprintf(fp, "#define gl%s(",func->name);
/* Label macro arguments as 'a', 'b', 'c', ... */
for(i=0; i<func->nrArgs; i++)
{
fprintf(fp, "%c%s",
'a'+i,
i < func->nrArgs-1?",":"");
}
fprintf(fp, ") __sstglctx->%s(", func->name);
/* Label macro arguments as 'a', 'b', 'c', ... */
for(i=0; i<func->nrArgs; i++)
{
fprintf(fp, "(%c)%s",
'a'+i,
i < func->nrArgs-1?",":"");
}
fprintf(fp, ")\n");
func = func->next;
}
fprintf(fp, " \n#endif\n\n");
}