/* parsegl.c Author: Patrick Baggett 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 #include #include #include #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 \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; inrArgs; 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 \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; inrArgs; 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; inrArgs; i++) { fprintf(fp, "(%c)%s", 'a'+i, i < func->nrArgs-1?",":""); } fprintf(fp, ")\n"); func = func->next; } fprintf(fp, " \n#endif\n\n"); }