
/* an implementation of a Lodestone-capable backend */
/* which just echoes all the data */

#include <stdio.h>
#include <string.h>
#include <map>
#include <iostream>

#include <GL/gl.h>
#include "lodestone.h"

#include "echoBackend.h"

/* some variable to return pseudo values */

static int nodeCount = 1;
static int stateCount = 1;
static int textureCount = 1;
static int lightCount = 1;

static int geoVCount;
static int geoNCount;
static int geoCCount;
static int geoTCount;

/* GL enum mapping */

using namespace std;

static map<GLenum,char*> enumMap;
char *mapEnum(GLenum en);

static map<GLenum,int> paramMap;
int mapParam(GLenum en);

/* General Interface Access */

static int getMajorVersion(void)
{
    return 0;
}

static int getMinorVersion(void)
{
    return 1;
}
    
static int hasExtension(const char *name)
{
    if(!strncmp(name,"bar",3))
    {
        printf("Extension %s supported.\n", name);
        return GL_TRUE;
    }
    
    printf("Extension %s not supported.\n", name);
       
    return GL_FALSE;
}

static void *getExtensionFunction(const char *name)
{
    if(!strncmp(name,"barFunc",7))
        return (void*)1;
        
    return NULL;
}

/* File Handling */

char *findFile(const char *name)
{
    char *n;
    
    printf("findFile: %s\n", name);
    
    n = (char*) malloc(strlen(name) + 1);
    
    strcpy(n,name);
    
    return n;
}

/* General Node Functions */

void setName(lsNode node, const char *name)
{
    printf("Node %d: set name to %s\n", (int)node, name);
}

/* Group Functions */

static lsGroup createGroup(void)
{
    printf("Group %d: Creating\n", nodeCount);
    return (void*)nodeCount++;
}

static void addChild(lsGroup group, lsNode node)
{
    printf("Group %d: Adding node %d\n", group, node);
}
    
/* Geometry Functions */
    
static lsGeometry createGeometry(void)
{
    printf("Geometry %d: Creating\n", nodeCount);
    return (void*)nodeCount++;
}

static void setVertexCount(lsGeometry geo, int n)
{
    printf("Geometry %d: Setting to %d vertices\n", (int)geo, n);
    geoVCount = n;
}

static void setVertices(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Setting vertices\n", (int)geo);
   
    for(i = 0; i < geoVCount; i++)
        printf("{%.2f,%.2f,%.2f} ", v[i*3+0], v[i*3+1], v[i*3+2]);
    printf("\n");
}

static void addVertex(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Adding vertex {%.2f,%.2f,%.2f}\n", (int)geo,
            v[0], v[1], v[2]);
}

static void setNormalCount(lsGeometry geo, int n)
{
    printf("Geometry %d: Setting to %d normals\n", (int)geo, n);
    geoNCount = n;
}

static void setNormals(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Setting normals\n", (int)geo);
   
    for(i = 0; i < geoNCount; i++)
        printf("{%.2f,%.2f,%.2f} ", v[i*3+0], v[i*3+1], v[i*3+2]);
    printf("\n");
}

static void addNormal(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Adding Normal {%.2f,%.2f,%.2f}\n", (int)geo,
            v[0], v[1], v[2]);
}

static void setColorCount(lsGeometry geo, int n)
{
    printf("Geometry %d: Setting to %d colors\n", (int)geo, n);
    geoCCount = n;
}

static void setColors(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Setting colors\n", (int)geo);
   
    for(i = 0; i < geoCCount; i++)
        printf("{%.2f,%.2f,%.2f} ", v[i*3+0], v[i*3+1], v[i*3+2]);
    printf("\n");
}

static void addColor(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Adding Color {%.2f,%.2f,%.2f,%.2f}\n", (int)geo,
            v[0], v[1], v[2], v[3]);
}

static void setTexCoordCount(lsGeometry geo, int n)
{
    printf("Geometry %d: Setting to %d TexCoords\n", (int)geo, n);
    geoTCount = n;
}

static void setTexCoords(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Setting TexCoords\n", (int)geo);
   
    for(i = 0; i < geoTCount; i++)
        printf("{%.2f,%.2f,%.2f} ", v[i*3+0], v[i*3+1], v[i*3+2]);
    printf("\n");
}

static void addTexCoord(lsGeometry geo, float *v)
{
    int i;
    printf("Geometry %d: Adding TexCoord {%.2f,%.2f}\n", (int)geo,
            v[0], v[1]);
}

void addFace(lsGeometry geo, GLenum type, int n, unsigned int *indices)
{
    int i;
    
    printf("Geometry %d: Adding face type %s, %d vertices:", (int)geo,
        mapEnum(type), n);
   
    for(i = 0; i < n; i++)
        printf(" %ld", indices[i]);
    printf("\n");
}

static void closeGeometry(lsGeometry geo)
{
     printf("Geometry %d: Closing\n", (int)geo);
}
    
/* State Set Functions */
    
static lsStateSet createStateSet(void)
{
    printf("StateSet %d: Creating\n", stateCount);
    return (void*)stateCount++;
}

static void openStateSet(lsStateSet set)
{
    printf("StateSet %d: Opening\n", (int)set);
}
    
static void stateEnable(lsStateSet set, GLenum value)
{
    printf("StateSet %d: Enabling state %s\n", (int)set, mapEnum(value));
}

static void stateMaterialfv(lsStateSet set, GLenum face, GLenum pname, 
                          GLfloat *values)
{
    int i;
    printf("StateSet %d: Setting Material %s %s \n", (int)set, 
                    mapEnum(face), mapEnum(pname)); 

    for(i = 0; i < mapParam(pname); i++)
        printf(" %f", values[i]);
    printf("\n");
}

static void stateMaterialf(lsStateSet set, GLenum face, GLenum pname, 
                          GLfloat value)
{
    printf("StateSet %d: Setting Material %s %s to %f\n", 
                    (int)set, mapEnum(face), mapEnum(pname), value); 
}

static void stateColorMaterial(lsStateSet set, GLenum face, GLenum pname)
{
    printf("StateSet %d: Setting ColorMaterial face %s to %s.\n", 
                (int)set, mapEnum(face), mapEnum(pname)); 
}

static void statePolygonOffset(lsStateSet set, GLfloat factor, GLfloat bias)
{
    printf("StateSet %d: Setting PolygonOfset to %f %f.\n", 
                (int)set, factor, bias); 
}

static void statePolygonMode(lsStateSet set, GLenum face, GLenum value)
{
     printf("StateSet %d: Setting PolygonMode on face %s to %s.\n", 
                (int)set, mapEnum(face), mapEnum(value)); 
}

static void stateCullFace(lsStateSet set, GLenum face)
{
    printf("StateSet %d: Setting CullFace to %s\n", (int)set, mapEnum(face));
}

static void stateSetTexture(lsStateSet set, lsTexture tex)
{
    printf("StateSet %d: Setting Texture to %f\n", (int)set, (int)tex);
}

static void closeStateSet(lsStateSet set)
{
    printf("StateSet %d: Closing\n", (int)set);
}

static void activateStateSet(lsStateSet set)
{
    printf("StateSet %d: now active\n", (int)set);
}

   
/* Texture Functions */
    
lsTexture createTexture(void)
{
    printf("Texture %d: Creating\n", textureCount);
    return (void*)textureCount++;
}

void texSetImage(lsTexture tex, const char *filename)
{
    printf("Texture %d: Setting image to %s\n", (int)tex, filename);   
}

void texParameterf(lsTexture tex, GLenum pname, GLfloat value)
{
     printf("Texture %d: Setting texture parameter %s to %f.\n", 
                (int)tex, mapEnum(pname), value); 
}

void texEnvf(lsTexture tex, GLenum pname, GLfloat value)
{
     printf("Texture %d: Setting texture env %s to %f.\n", 
                (int)tex, mapEnum(pname), value); 
}

void texEnvfv(lsTexture tex, GLenum pname, GLfloat *values)
{
    int i;
    printf("Texture %d: Setting texture env %s to", 
                (int)tex, mapEnum(pname));

    for(i = 0; i < mapParam(pname); i++)
        printf(" %f", values[i]);
    printf("\n");
}

void texGenf(lsTexture tex, GLenum coord, GLenum pname, GLfloat value)
{
     printf("Texture %d: Setting texgen coord %s %s to %f.\n", 
                (int)tex, mapEnum(coord), mapEnum(pname), value); 
}

void texGenfv(lsTexture tex, GLenum coord, GLenum pname, GLfloat *values)
{
    int i;
    printf("Texture %d: Setting texgen coord %s %s to", 
                (int)tex, mapEnum(coord), mapEnum(pname)); 

    for(i = 0; i < mapParam(pname); i++)
        printf(" %f", values[i]);
    printf("\n");
}

void closeTexture(lsTexture tex)
{
    printf("Texture %d: Closing\n", tex);
}

/* Transformation Functions */
    
lsTransformation createTransformation(void)
{
    printf("Transformation %d: Creating\n", nodeCount);
    return (void*)nodeCount++;
}
  
void setTransformation(lsTransformation trans, GLdouble *matrix)
{
    int i;
    
    printf("Transform %d: Setting matrix to\n", (int)trans);
    
    for(int i = 0; i < 16; i++)
        printf("%.2f ", matrix[i]);
}
 

/* Light Source Functions */
    
lsLightSource createLightSource(void)
{
    printf("LightSource %d: Creating\n", nodeCount);
    return (void*)nodeCount++;
}

void lightfv(lsLightSource source, GLenum pname, GLfloat *values)
{
    int i;
    printf("LightSource %d: Setting parameters %s to", (int)source,
            mapEnum(pname));

    for(i = 0; i < mapParam(pname); i++)
        printf(" %f", values[i]);
    printf("\n");
}

void lightf(lsLightSource source, GLenum pname, GLfloat value)
{
    printf("LightSource %d: Setting parameter %s to %f\n", (int)source,
            mapEnum(pname), value);
}
   
void closeLightSource(lsLightSource source)
{
    printf("LightSource %d: Closing\n", source);
}



/* Interface Structure */

static lsInterface echoInterface =
{
    /* General Interface Access */
    getMajorVersion,
    getMinorVersion,
    
    hasExtension,
    getExtensionFunction,
  
    /* File Handling */
    
    findFile,
   
    /* General Node Functions */
    
    setName,
    
    /* Group Functions */
    
    createGroup,
    addChild,
    
    /* Geometry Functions */
    
    createGeometry,

    setVertexCount,
    setVertices,
    addVertex,
    setNormalCount,
    setNormals,
    addNormal,
    setColorCount,
    setColors,
    addColor,
    setTexCoordCount,
    setTexCoords,
    addTexCoord,
    addFace,   
    closeGeometry,
    
    /* State Set Functions */
    
    createStateSet,
    
    openStateSet,
    
    stateEnable,
    stateMaterialfv,
    stateMaterialf,
    stateColorMaterial,
    statePolygonOffset,
    statePolygonMode,
    stateCullFace,
    stateSetTexture,
        
    closeStateSet,
    
    activateStateSet,
   
    /* Texture Functions */
    
    createTexture,
    
    texSetImage,
    texParameterf,
    texEnvf,
    texEnvfv,
    texGenf,
    texGenfv,
    
    closeTexture,
    

    /* Transformation Functions */
    
    createTransformation,
    
    setTransformation,
 
    
    /* Light Source Functions */
    
    createLightSource,

    lightfv,
    lightf,
    
    closeLightSource
};


lsInterface *echoGetLSInterface(void)
{
    return &echoInterface;
}

/* some init stuff... */

#define pushEnum(en)   enumMap[en] = #en
#define pushParam(en,cnt)  paramMap[en] = cnt

static void init(void)
{
    /* These enums are just copied from gl.h, many of those will not make
       sense for a loader. */
       
    /* Data types */
    pushEnum(GL_BYTE);
    pushEnum(GL_UNSIGNED_BYTE);
    pushEnum(GL_SHORT);
    pushEnum(GL_UNSIGNED_SHORT);
    pushEnum(GL_INT);
    pushEnum(GL_UNSIGNED_INT);
    pushEnum(GL_FLOAT);
    pushEnum(GL_DOUBLE);
    pushEnum(GL_2_BYTES);
    pushEnum(GL_3_BYTES);
    pushEnum(GL_4_BYTES);

    /* Primitives */
    pushEnum(GL_LINES);
    pushEnum(GL_POINTS);
    pushEnum(GL_LINE_STRIP);
    pushEnum(GL_LINE_LOOP);
    pushEnum(GL_TRIANGLES);
    pushEnum(GL_TRIANGLE_STRIP);
    pushEnum(GL_TRIANGLE_FAN);
    pushEnum(GL_QUADS);
    pushEnum(GL_QUAD_STRIP);
    pushEnum(GL_POLYGON);
    pushEnum(GL_EDGE_FLAG);

    /* Points */
    pushEnum(GL_POINT_SMOOTH);
    pushEnum(GL_POINT_SIZE);
    pushEnum(GL_POINT_SIZE_GRANULARITY );
    pushEnum(GL_POINT_SIZE_RANGE);

    /* Lines */
    pushEnum(GL_LINE_SMOOTH);
    pushEnum(GL_LINE_STIPPLE);
    pushEnum(GL_LINE_STIPPLE_PATTERN);
    pushEnum(GL_LINE_STIPPLE_REPEAT);
    pushEnum(GL_LINE_WIDTH);
    pushEnum(GL_LINE_WIDTH_GRANULARITY);
    pushEnum(GL_LINE_WIDTH_RANGE);

    /* Polygons */
    pushEnum(GL_POINT);
    pushEnum(GL_LINE);
    pushEnum(GL_FILL);
    pushEnum(GL_CCW);
    pushEnum(GL_CW);
    pushEnum(GL_FRONT);
    pushEnum(GL_BACK);
    pushEnum(GL_CULL_FACE);
    pushEnum(GL_CULL_FACE_MODE);
    pushEnum(GL_POLYGON_SMOOTH);
    pushEnum(GL_POLYGON_STIPPLE);
    pushEnum(GL_FRONT_FACE);
    pushEnum(GL_POLYGON_MODE);
    pushEnum(GL_POLYGON_OFFSET_FACTOR);
    pushEnum(GL_POLYGON_OFFSET_UNITS);
    pushEnum(GL_POLYGON_OFFSET_POINT);
    pushEnum(GL_POLYGON_OFFSET_LINE);
    pushEnum(GL_POLYGON_OFFSET_FILL);

    /* Depth buffer */
    pushEnum(GL_NEVER);
    pushEnum(GL_LESS);
    pushEnum(GL_GEQUAL);
    pushEnum(GL_LEQUAL);
    pushEnum(GL_GREATER);
    pushEnum(GL_NOTEQUAL);
    pushEnum(GL_EQUAL);
    pushEnum(GL_ALWAYS);
    pushEnum(GL_DEPTH_TEST);
    pushEnum(GL_DEPTH_BITS);
    pushEnum(GL_DEPTH_CLEAR_VALUE);
    pushEnum(GL_DEPTH_FUNC);
    pushEnum(GL_DEPTH_RANGE);
    pushEnum(GL_DEPTH_WRITEMASK);
    pushEnum(GL_DEPTH_COMPONENT);

    /* Lighting */
    pushEnum(GL_LIGHTING);
    pushEnum(GL_LIGHT0);
    pushEnum(GL_LIGHT1);
    pushEnum(GL_LIGHT2);
    pushEnum(GL_LIGHT3);
    pushEnum(GL_LIGHT4);
    pushEnum(GL_LIGHT5);
    pushEnum(GL_LIGHT6);
    pushEnum(GL_LIGHT7);
    pushEnum(GL_SPOT_EXPONENT);
    pushEnum(GL_SPOT_CUTOFF);
    pushEnum(GL_CONSTANT_ATTENUATION);
    pushEnum(GL_LINEAR_ATTENUATION);
    pushEnum(GL_QUADRATIC_ATTENUATION);
    pushEnum(GL_AMBIENT);
    pushEnum(GL_DIFFUSE);
    pushEnum(GL_SPECULAR);
    pushEnum(GL_SHININESS);
    pushEnum(GL_EMISSION);
    pushEnum(GL_POSITION);
    pushEnum(GL_SPOT_DIRECTION);
    pushEnum(GL_AMBIENT_AND_DIFFUSE);
    pushEnum(GL_COLOR_INDEXES);
    pushEnum(GL_LIGHT_MODEL_TWO_SIDE);
    pushEnum(GL_LIGHT_MODEL_LOCAL_VIEWER);
    pushEnum(GL_LIGHT_MODEL_AMBIENT);
    pushEnum(GL_FRONT_AND_BACK);
    pushEnum(GL_SHADE_MODEL);
    pushEnum(GL_FLAT);
    pushEnum(GL_SMOOTH);
    pushEnum(GL_COLOR_MATERIAL);
    pushEnum(GL_COLOR_MATERIAL_FACE);
    pushEnum(GL_COLOR_MATERIAL_PARAMETER);
    pushEnum(GL_NORMALIZE);

    /* Alpha testing */
    pushEnum(GL_ALPHA_TEST);
    pushEnum(GL_ALPHA_TEST_REF);
    pushEnum(GL_ALPHA_TEST_FUNC);

    /* Blending */
    pushEnum(GL_BLEND);
    pushEnum(GL_BLEND_SRC);
    pushEnum(GL_BLEND_DST);
    pushEnum(GL_ZERO);
    pushEnum(GL_ONE);
    pushEnum(GL_SRC_COLOR);
    pushEnum(GL_ONE_MINUS_SRC_COLOR);
    pushEnum(GL_DST_COLOR);
    pushEnum(GL_ONE_MINUS_DST_COLOR);
    pushEnum(GL_SRC_ALPHA);
    pushEnum(GL_ONE_MINUS_SRC_ALPHA);
    pushEnum(GL_DST_ALPHA);
    pushEnum(GL_ONE_MINUS_DST_ALPHA);
    pushEnum(GL_SRC_ALPHA_SATURATE);
    pushEnum(GL_CONSTANT_COLOR);
    pushEnum(GL_ONE_MINUS_CONSTANT_COLOR);
    pushEnum(GL_CONSTANT_ALPHA);
    pushEnum(GL_ONE_MINUS_CONSTANT_ALPHA);

    /* Fog */
    pushEnum(GL_FOG);
    pushEnum(GL_FOG_MODE);
    pushEnum(GL_FOG_DENSITY);
    pushEnum(GL_FOG_COLOR);
    pushEnum(GL_FOG_INDEX);
    pushEnum(GL_FOG_START);
    pushEnum(GL_FOG_END);
    pushEnum(GL_LINEAR);
    pushEnum(GL_EXP);
    pushEnum(GL_EXP2);

    /* Logic Ops */
    pushEnum(GL_LOGIC_OP);
    pushEnum(GL_INDEX_LOGIC_OP);
    pushEnum(GL_COLOR_LOGIC_OP);
    pushEnum(GL_LOGIC_OP_MODE);
    pushEnum(GL_CLEAR);
    pushEnum(GL_SET);
    pushEnum(GL_COPY);
    pushEnum(GL_COPY_INVERTED);
    pushEnum(GL_NOOP);
    pushEnum(GL_INVERT);
    pushEnum(GL_AND);
    pushEnum(GL_NAND);
    pushEnum(GL_OR);
    pushEnum(GL_NOR);
    pushEnum(GL_XOR);
    pushEnum(GL_EQUIV);
    pushEnum(GL_AND_REVERSE);
    pushEnum(GL_AND_INVERTED);
    pushEnum(GL_OR_REVERSE);
    pushEnum(GL_OR_INVERTED);

    /* Stencil */
    pushEnum(GL_STENCIL_TEST);
    pushEnum(GL_STENCIL_WRITEMASK);
    pushEnum(GL_STENCIL_BITS);
    pushEnum(GL_STENCIL_FUNC);
    pushEnum(GL_STENCIL_VALUE_MASK);
    pushEnum(GL_STENCIL_REF);
    pushEnum(GL_STENCIL_FAIL);
    pushEnum(GL_STENCIL_PASS_DEPTH_PASS);
    pushEnum(GL_STENCIL_PASS_DEPTH_FAIL);
    pushEnum(GL_STENCIL_CLEAR_VALUE);
    pushEnum(GL_STENCIL_INDEX);
    pushEnum(GL_KEEP);
    pushEnum(GL_REPLACE);
    pushEnum(GL_INCR);
    pushEnum(GL_DECR);

    /* Pixel Mode / Transfer */
    pushEnum(GL_MAP_COLOR);
    pushEnum(GL_MAP_STENCIL);
    pushEnum(GL_INDEX_SHIFT);
    pushEnum(GL_INDEX_OFFSET);
    pushEnum(GL_RED_SCALE);
    pushEnum(GL_RED_BIAS);
    pushEnum(GL_GREEN_SCALE);
    pushEnum(GL_GREEN_BIAS);
    pushEnum(GL_BLUE_SCALE);
    pushEnum(GL_BLUE_BIAS);
    pushEnum(GL_ALPHA_SCALE);
    pushEnum(GL_ALPHA_BIAS);
    pushEnum(GL_DEPTH_SCALE);
    pushEnum(GL_DEPTH_BIAS);
    pushEnum(GL_PIXEL_MAP_S_TO_S_SIZE);
    pushEnum(GL_PIXEL_MAP_I_TO_I_SIZE);
    pushEnum(GL_PIXEL_MAP_I_TO_R_SIZE);
    pushEnum(GL_PIXEL_MAP_I_TO_G_SIZE);
    pushEnum(GL_PIXEL_MAP_I_TO_B_SIZE);
    pushEnum(GL_PIXEL_MAP_I_TO_A_SIZE);
    pushEnum(GL_PIXEL_MAP_R_TO_R_SIZE);
    pushEnum(GL_PIXEL_MAP_G_TO_G_SIZE);
    pushEnum(GL_PIXEL_MAP_B_TO_B_SIZE);
    pushEnum(GL_PIXEL_MAP_A_TO_A_SIZE);
    pushEnum(GL_PIXEL_MAP_S_TO_S);
    pushEnum(GL_PIXEL_MAP_I_TO_I);
    pushEnum(GL_PIXEL_MAP_I_TO_R);
    pushEnum(GL_PIXEL_MAP_I_TO_G);
    pushEnum(GL_PIXEL_MAP_I_TO_B);
    pushEnum(GL_PIXEL_MAP_I_TO_A);
    pushEnum(GL_PIXEL_MAP_R_TO_R);
    pushEnum(GL_PIXEL_MAP_G_TO_G);
    pushEnum(GL_PIXEL_MAP_B_TO_B);
    pushEnum(GL_PIXEL_MAP_A_TO_A);
    pushEnum(GL_PACK_ALIGNMENT);
    pushEnum(GL_PACK_LSB_FIRST);
    pushEnum(GL_PACK_ROW_LENGTH);
    pushEnum(GL_PACK_SKIP_PIXELS);
    pushEnum(GL_PACK_SKIP_ROWS);
    pushEnum(GL_PACK_SWAP_BYTES);
    pushEnum(GL_UNPACK_ALIGNMENT);
    pushEnum(GL_UNPACK_LSB_FIRST);
    pushEnum(GL_UNPACK_ROW_LENGTH);
    pushEnum(GL_UNPACK_SKIP_PIXELS);
    pushEnum(GL_UNPACK_SKIP_ROWS);
    pushEnum(GL_UNPACK_SWAP_BYTES);
    pushEnum(GL_ZOOM_X);
    pushEnum(GL_ZOOM_Y);

    /* Texture mapping */
    pushEnum(GL_TEXTURE_ENV);
    pushEnum(GL_TEXTURE_ENV_MODE);
    pushEnum(GL_TEXTURE_1D);
    pushEnum(GL_TEXTURE_2D);
    pushEnum(GL_TEXTURE_WRAP_S);
    pushEnum(GL_TEXTURE_WRAP_T);
    pushEnum(GL_TEXTURE_MAG_FILTER);
    pushEnum(GL_TEXTURE_MIN_FILTER);
    pushEnum(GL_TEXTURE_ENV_COLOR);
    pushEnum(GL_TEXTURE_GEN_S);
    pushEnum(GL_TEXTURE_GEN_T);
    pushEnum(GL_TEXTURE_GEN_MODE);
    pushEnum(GL_TEXTURE_BORDER_COLOR);
    pushEnum(GL_TEXTURE_WIDTH);
    pushEnum(GL_TEXTURE_HEIGHT);
    pushEnum(GL_TEXTURE_BORDER);
    pushEnum(GL_TEXTURE_COMPONENTS);
    pushEnum(GL_TEXTURE_RED_SIZE);
    pushEnum(GL_TEXTURE_GREEN_SIZE);
    pushEnum(GL_TEXTURE_BLUE_SIZE);
    pushEnum(GL_TEXTURE_ALPHA_SIZE);
    pushEnum(GL_TEXTURE_LUMINANCE_SIZE);
    pushEnum(GL_TEXTURE_INTENSITY_SIZE);
    pushEnum(GL_NEAREST_MIPMAP_NEAREST);
    pushEnum(GL_NEAREST_MIPMAP_LINEAR);
    pushEnum(GL_LINEAR_MIPMAP_NEAREST);
    pushEnum(GL_LINEAR_MIPMAP_LINEAR);
    pushEnum(GL_OBJECT_LINEAR);
    pushEnum(GL_OBJECT_PLANE);
    pushEnum(GL_EYE_LINEAR);
    pushEnum(GL_EYE_PLANE);
    pushEnum(GL_SPHERE_MAP);
    pushEnum(GL_DECAL);
    pushEnum(GL_MODULATE);
    pushEnum(GL_NEAREST);
    pushEnum(GL_REPEAT);
    pushEnum(GL_CLAMP);
    pushEnum(GL_S);
    pushEnum(GL_T);
    pushEnum(GL_R);
    pushEnum(GL_Q);
    pushEnum(GL_TEXTURE_GEN_R);
    pushEnum(GL_TEXTURE_GEN_Q);

    /* Internal texture formats (GL 1.1) */
    pushEnum(GL_ALPHA4);
    pushEnum(GL_ALPHA8);
    pushEnum(GL_ALPHA12);
    pushEnum(GL_ALPHA16);
    pushEnum(GL_LUMINANCE4);
    pushEnum(GL_LUMINANCE8);
    pushEnum(GL_LUMINANCE12);
    pushEnum(GL_LUMINANCE16);
    pushEnum(GL_LUMINANCE4_ALPHA4);
    pushEnum(GL_LUMINANCE6_ALPHA2);
    pushEnum(GL_LUMINANCE8_ALPHA8);
    pushEnum(GL_LUMINANCE12_ALPHA4);
    pushEnum(GL_LUMINANCE12_ALPHA12);
    pushEnum(GL_LUMINANCE16_ALPHA16);
    pushEnum(GL_INTENSITY);
    pushEnum(GL_INTENSITY4);
    pushEnum(GL_INTENSITY8);
    pushEnum(GL_INTENSITY12);
    pushEnum(GL_INTENSITY16);
    pushEnum(GL_R3_G3_B2);
    pushEnum(GL_RGB4);
    pushEnum(GL_RGB5);
    pushEnum(GL_RGB8);
    pushEnum(GL_RGB10);
    pushEnum(GL_RGB12);
    pushEnum(GL_RGB16);
    pushEnum(GL_RGBA2);
    pushEnum(GL_RGBA4);
    pushEnum(GL_RGB5_A1);
    pushEnum(GL_RGBA8);
    pushEnum(GL_RGB10_A2);
    pushEnum(GL_RGBA12);
    pushEnum(GL_RGBA16);

    /* GL_EXT_blend_minmax and GL_EXT_blend_color */
    pushEnum(GL_CONSTANT_COLOR_EXT);
    pushEnum(GL_ONE_MINUS_CONSTANT_COLOR_EXT);
    pushEnum(GL_CONSTANT_ALPHA_EXT);
    pushEnum(GL_ONE_MINUS_CONSTANT_ALPHA_EXT);
    pushEnum(GL_BLEND_EQUATION_EXT);
    pushEnum(GL_MIN_EXT);
    pushEnum(GL_MAX_EXT);
    pushEnum(GL_FUNC_ADD_EXT);
    pushEnum(GL_FUNC_SUBTRACT_EXT);
    pushEnum(GL_FUNC_REVERSE_SUBTRACT_EXT);
    pushEnum(GL_BLEND_COLOR_EXT);

    /* GL_EXT_polygon_offset */
    pushEnum(GL_POLYGON_OFFSET_EXT);
    pushEnum(GL_POLYGON_OFFSET_FACTOR_EXT);
    pushEnum(GL_POLYGON_OFFSET_BIAS_EXT);

    /* GL_EXT_texture3D */
    pushEnum(GL_PACK_SKIP_IMAGES_EXT);
    pushEnum(GL_PACK_IMAGE_HEIGHT_EXT);
    pushEnum(GL_UNPACK_SKIP_IMAGES_EXT);
    pushEnum(GL_UNPACK_IMAGE_HEIGHT_EXT);
    pushEnum(GL_TEXTURE_3D_EXT);
    pushEnum(GL_PROXY_TEXTURE_3D_EXT);
    pushEnum(GL_TEXTURE_DEPTH_EXT);
    pushEnum(GL_TEXTURE_WRAP_R_EXT);
    pushEnum(GL_MAX_3D_TEXTURE_SIZE_EXT);
    pushEnum(GL_TEXTURE_3D_BINDING_EXT);

    /* Parameter Counts */
    pushParam(GL_AMBIENT,4);
    pushParam(GL_DIFFUSE,4);
    pushParam(GL_SPECULAR,4);
    pushParam(GL_EMISSION,4);

    pushParam(GL_POSITION,4);

    pushParam(GL_OBJECT_PLANE,4);
    pushParam(GL_EYE_PLANE,4);
    
}

char *mapEnum(GLenum en)
{
    static bool inited = false;
    
    if(!inited)
        init();
        
    map<GLenum,char*>::iterator iter = enumMap.find(en);
    
    if(iter->second)
        return iter->second;
    
    return "unknown";
}


int mapParam(GLenum en)
{
    static bool inited = false;
    
    if(!inited)
        init();
        
    map<GLenum,int>::iterator iter = paramMap.find(en);
    
    if(iter->second)
        return iter->second;
    
    return -1;
}

