Moved all the test and utility programs to a "utils" directory.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 12 Feb 2009 17:29:24 -0500
changeset 588 ef3d2efa822d
parent 587 202354e004fc
child 589 1cf3fc2c5e37
Moved all the test and utility programs to a "utils" directory.
CMakeLists.txt
assemble.c
availableprofiles.c
bestprofile.c
finderrors.c
glcaps.c
preprocess.c
testoutput.c
testparse.c
utils/assemble.c
utils/availableprofiles.c
utils/bestprofile.c
utils/finderrors.c
utils/glcaps.c
utils/preprocess.c
utils/testoutput.c
utils/testparse.c
--- a/CMakeLists.txt	Thu Feb 12 17:25:49 2009 -0500
+++ b/CMakeLists.txt	Thu Feb 12 17:29:24 2009 -0500
@@ -1,6 +1,8 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
 PROJECT(MojoShader)
 
+INCLUDE_DIRECTORIES(.)
+
 FIND_PROGRAM(HG hg DOC "Path to hg command line app: http://www.selenic.com/mercurial/")
 IF(NOT HG)
     MESSAGE(STATUS "Mercurial (hg) not found. You can go on, but version info will be wrong.")
@@ -73,23 +75,23 @@
 IF(SDL_FOUND)
     INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
     ADD_DEFINITIONS(-DFINDERRORS_COMPILE_SHADERS=1)
-    ADD_EXECUTABLE(glcaps glcaps.c)
+    ADD_EXECUTABLE(glcaps utils/glcaps.c)
     TARGET_LINK_LIBRARIES(glcaps ${SDL_LIBRARY})
-    ADD_EXECUTABLE(bestprofile bestprofile.c)
+    ADD_EXECUTABLE(bestprofile utils/bestprofile.c)
     TARGET_LINK_LIBRARIES(bestprofile mojoshader ${SDL_LIBRARY})
-    ADD_EXECUTABLE(availableprofiles availableprofiles.c)
+    ADD_EXECUTABLE(availableprofiles utils/availableprofiles.c)
     TARGET_LINK_LIBRARIES(availableprofiles mojoshader ${SDL_LIBRARY})
 ENDIF(SDL_FOUND)
 
-ADD_EXECUTABLE(testparse testparse.c)
+ADD_EXECUTABLE(testparse utils/testparse.c)
 TARGET_LINK_LIBRARIES(testparse mojoshader)
-ADD_EXECUTABLE(testoutput testoutput.c)
+ADD_EXECUTABLE(testoutput utils/testoutput.c)
 TARGET_LINK_LIBRARIES(testoutput mojoshader)
-ADD_EXECUTABLE(finderrors finderrors.c)
+ADD_EXECUTABLE(finderrors utils/finderrors.c)
 TARGET_LINK_LIBRARIES(finderrors mojoshader ${SDL_LIBRARY})
-ADD_EXECUTABLE(assemble assemble.c)
+ADD_EXECUTABLE(assemble utils/assemble.c)
 TARGET_LINK_LIBRARIES(assemble mojoshader)
-ADD_EXECUTABLE(preprocess preprocess.c)
+ADD_EXECUTABLE(preprocess utils/preprocess.c)
 TARGET_LINK_LIBRARIES(preprocess mojoshader)
 
 # End of CMakeLists.txt ...
--- a/assemble.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "mojoshader.h"
-
-static int assemble(const char *fname, const char *buf, int len,
-                    const char *outfile)
-{
-    FILE *io = fopen(outfile, "wb");
-    if (io == NULL)
-    {
-        printf(" ... fopen('%s') failed.\n", outfile);
-        return 0;
-    } // if
-
-    const MOJOSHADER_parseData *pd;
-    int retval = 0;
-
-    pd = MOJOSHADER_assemble(fname, buf, len, NULL, 0, NULL, 0,
-                             NULL, 0, NULL, NULL, NULL, NULL, NULL);
-    if (pd->error_count > 0)
-    {
-        int i;
-        for (i = 0; i < pd->error_count; i++)
-        {
-            printf("%s:%d: ERROR: %s\n",
-                    pd->errors[i].filename ? pd->errors[i].filename : "???",
-                    pd->errors[i].error_position,
-                    pd->errors[i].error);
-        } // for
-    } // if
-    else
-    {
-        if (pd->output != NULL)
-        {
-            if (fwrite(pd->output, pd->output_len, 1, io) != 1)
-                printf(" ... fwrite('%s') failed.\n", outfile);
-            else if (fclose(io) == EOF)
-                printf(" ... fclose('%s') failed.\n", outfile);
-            else
-                retval = 1;
-        } // if
-    } // else
-    MOJOSHADER_freeParseData(pd);
-
-    return retval;
-} // assemble
-
-
-int main(int argc, char **argv)
-{
-    int retval = 1;
-
-    if (argc != 3)
-        printf("\n\nUSAGE: %s <inputfile> <outputfile>\n\n", argv[0]);
-    else
-    {
-        const char *infile = argv[1];
-        const char *outfile = argv[2];
-        FILE *io = fopen(infile, "rb");
-        if (io == NULL)
-            printf(" ... fopen('%s') failed.\n", infile);
-        else
-        {
-            char *buf = (char *) malloc(1000000);
-            int rc = fread(buf, 1, 1000000, io);
-            fclose(io);
-            if (rc == EOF)
-                printf(" ... fread('%s') failed.\n", infile);
-            else
-            {
-                if (assemble(infile, buf, rc, outfile))
-                    retval = 0;
-                else
-                    remove(outfile);
-                free(buf);
-            } // else
-        } // for
-    } // else
-
-    return retval;
-} // main
-
-// end of assemble.c ...
-
--- a/availableprofiles.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include "mojoshader.h"
-#include "SDL.h"
-
-static int check_available(void)
-{
-    const char **avail = NULL;
-    int total = MOJOSHADER_glAvailableProfiles(SDL_GL_GetProcAddress, NULL, 0);
-    if (total > 0)
-    {
-        avail = (const char **) alloca(sizeof (const char *) * total);
-        total = MOJOSHADER_glAvailableProfiles(SDL_GL_GetProcAddress, avail, total);
-    } // if
-
-    if (total <= 0)
-        fprintf(stderr, "No profiles available.\n");
-    else
-    {
-        int i;
-        for (i = 0; i < total; i++)
-        {
-            printf("%s (Shader Model %d)\n", avail[i],
-                   MOJOSHADER_maxShaderModel(avail[i]));
-        } // for
-    } // else
-
-    return 0;
-} // check_available
-
-
-int main(int argc, char **argv)
-{
-    int retval = 1;
-
-    #if 0
-    printf("MojoShader availableprofile\n");
-    printf("Compiled against version %d\n", MOJOSHADER_VERSION);
-    printf("Linked against version %d\n", MOJOSHADER_version());
-    printf("\n");
-    #endif
-
-    if (SDL_Init(SDL_INIT_VIDEO) == -1)
-        fprintf(stderr, "SDL_Init(SDL_INIT_VIDEO) error: %s\n", SDL_GetError());
-    else
-    {
-        SDL_GL_LoadLibrary(NULL);
-        if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL)
-            fprintf(stderr, "SDL_SetVideoMode() error: %s\n", SDL_GetError());
-        else
-            retval = check_available();
-        SDL_Quit();
-    } // else
-
-    return retval;
-} // main
-
-// end of availableprofiles.c ...
-
--- a/bestprofile.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include "mojoshader.h"
-#include "SDL.h"
-
-int main(int argc, char **argv)
-{
-    int retval = 1;
-
-    #if 0
-    printf("MojoShader bestprofile\n");
-    printf("Compiled against version %d\n", MOJOSHADER_VERSION);
-    printf("Linked against version %d\n", MOJOSHADER_version());
-    printf("\n");
-    #endif
-
-    if (SDL_Init(SDL_INIT_VIDEO) == -1)
-        fprintf(stderr, "SDL_Init(SDL_INIT_VIDEO) error: %s\n", SDL_GetError());
-    else
-    {
-        SDL_GL_LoadLibrary(NULL);
-        if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL)
-            fprintf(stderr, "SDL_SetVideoMode() error: %s\n", SDL_GetError());
-        else
-        {
-            const char *best = MOJOSHADER_glBestProfile(SDL_GL_GetProcAddress);
-            MOJOSHADER_glContext *ctx;
-            ctx = MOJOSHADER_glCreateContext(best, SDL_GL_GetProcAddress, 0, 0, 0);
-            if (ctx == NULL)
-                printf("MOJOSHADER_glCreateContext() fail: %s\n", MOJOSHADER_glGetError());
-            else
-            {
-                printf("%s\n", best);
-                retval = 0;  // success.
-                MOJOSHADER_glDestroyContext(ctx);
-            } // else
-        } // else
-        SDL_Quit();
-    } // else
-
-    return retval;
-} // main
-
-// end of bestprofile.c ...
-
--- a/finderrors.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#include "mojoshader.h"
-
-#if FINDERRORS_COMPILE_SHADERS
-#include "SDL.h"
-#endif
-
-#ifdef _MSC_VER
-#define WIN32_LEAN_AND_MEAN 1
-#include <windows.h>
-#include <malloc.h>  // for alloca().
-#define snprintf _snprintf
-#else
-#include <dirent.h>
-#endif
-
-#define report printf
-
-static int do_file(const char *profile, const char *dname, const char *fn, int *total)
-{
-    int do_quit = 0;
-
-    #if FINDERRORS_COMPILE_SHADERS
-    SDL_Event e;  // pump event queue to keep OS happy.
-    while (SDL_PollEvent(&e))
-    {
-        if (e.type == SDL_QUIT)
-            do_quit = 1;
-    } // while
-    SDL_GL_SwapBuffers();
-    #endif
-
-    if (do_quit)
-    {
-        report("FAIL: user requested quit!\n");
-        return 0;
-    } // if
-
-    int assembly = 0;
-    if (strstr(fn, ".bytecode") != NULL)
-        assembly = 0;
-    else if (strstr(fn, ".disasm") != NULL)
-        assembly = 1;
-    else
-        return 1;
-
-    (*total)++;
-
-    char *fname = (char *) alloca(strlen(fn) + strlen(dname) + 1);
-    sprintf(fname, "%s/%s", dname, fn);
-    FILE *io = fopen(fname, "rb");
-    if (io == NULL)
-    {
-        report("FAIL: %s fopen() failed.\n", fname);
-        return 1;
-    } // if
-
-    static unsigned char buf[1024 * 256];
-    int rc = fread(buf, 1, sizeof (buf), io);
-    fclose(io);
-    if (rc == -1)
-    {
-        report("FAIL: %s %s\n", fname, strerror(errno));
-        return 1;
-    } // if
-
-    if (assembly)
-    {
-        const MOJOSHADER_parseData *a;
-
-        buf[rc] = '\0';  // make sure the source is null-terminated.
-        a = MOJOSHADER_assemble(fname, (char *) buf, rc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
-        if (a->error_count > 0)
-        {
-            report("FAIL: %s (line %d) %s\n",
-                a->errors[0].filename ? a->errors[0].filename : "???",
-                a->errors[0].error_position,
-                a->errors[0].error);
-            return 1;
-        } // if
-
-        else if (a->output_len > sizeof (buf))
-        {
-            report("FAIL: %s buffer overflow in finderrors.c\n", fname);
-            return 1;
-        } // if
-
-        rc = a->output_len;
-        memcpy(buf, a->output, rc);
-        MOJOSHADER_freeParseData(a);
-    } // if
-
-    #if FINDERRORS_COMPILE_SHADERS
-    MOJOSHADER_glShader *shader = MOJOSHADER_glCompileShader(buf, rc, NULL, 0);
-    if (shader == NULL)
-        report("FAIL: %s %s\n", fname, MOJOSHADER_glGetError());
-    else
-    {
-        const MOJOSHADER_parseData *pd = MOJOSHADER_glGetShaderParseData(shader);
-        MOJOSHADER_glShader *v = (pd->shader_type == MOJOSHADER_TYPE_VERTEX) ? shader : NULL;
-        MOJOSHADER_glShader *p = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? shader : NULL;
-        MOJOSHADER_glProgram *program = MOJOSHADER_glLinkProgram(v, p);
-        if (program == NULL)
-            report("FAIL: %s %s\n", fname, MOJOSHADER_glGetError());
-        else
-        {
-            report("PASS: %s\n", fname);
-            MOJOSHADER_glDeleteProgram(program);
-        } // else
-        MOJOSHADER_glDeleteShader(shader);
-    }
-    #else
-    const MOJOSHADER_parseData *pd = MOJOSHADER_parse(profile, buf, rc, NULL, 0, NULL, NULL, NULL);
-    if (pd->error != NULL)
-        report("FAIL: %s (position %d) %s\n", fname, pd->error_position, pd->error);
-    else
-        report("PASS: %s\n", fname);
-    MOJOSHADER_freeParseData(pd);
-    #endif
-
-    return 1;
-} // do_file
-
-
-static int do_dir(const char *dname, const char *profile)
-{
-    int total = 0;
-
-#ifdef _MSC_VER
-    WIN32_FIND_DATA dent;
-    HANDLE dirp = INVALID_HANDLE_VALUE;
-    FindFirstFileA(dname, &dent);
-    if (dirp != INVALID_HANDLE_VALUE)
-    {
-        do
-        {
-            if (!do_file(profile, dname, dent.cFileName, &total))
-                break;
-        } while (FindNextFileA(dirp, &dent) != 0);
-        CloseHandle(dirp);
-    } // if
-#else
-    struct dirent *dent = NULL;
-    DIR *dirp = opendir(dname);
-    if (dirp != NULL)
-    {
-        while ((dent = readdir(dirp)) != NULL)
-        {
-            if (!do_file(profile, dname, dent->d_name, &total))
-                break;
-        } // while
-        closedir(dirp);
-    } // if
-#endif
-
-    return total;
-} // do_dir
-
-
-int main(int argc, char **argv)
-{
-    //printf("MojoShader finderrors\n");
-    //printf("Compiled against version %d\n", MOJOSHADER_VERSION);
-    //printf("Linked against version %d\n", MOJOSHADER_version());
-    //printf("\n");
-
-    if (argc <= 2)
-        printf("\n\nUSAGE: %s <profile> [dir1] ... [dirN]\n\n", argv[0]);
-    else
-    {
-        int total = 0;
-        int i;
-        const char *profile = argv[1];
-
-        #if FINDERRORS_COMPILE_SHADERS
-        SDL_Init(SDL_INIT_VIDEO);
-        SDL_GL_LoadLibrary(NULL);
-        SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
-        printf("Best profile is '%s'\n", MOJOSHADER_glBestProfile(SDL_GL_GetProcAddress));
-        MOJOSHADER_glContext *ctx;
-        ctx = MOJOSHADER_glCreateContext(profile, SDL_GL_GetProcAddress, 0, 0, 0);
-        if (ctx == NULL)
-        {
-            printf("MOJOSHADER_glCreateContext() fail: %s\n", MOJOSHADER_glGetError());
-            SDL_Quit();
-            return 1;
-        } // if
-        MOJOSHADER_glMakeContextCurrent(ctx);
-        #endif
-
-        for (i = 2; i < argc; i++)
-            total += do_dir(argv[i], profile);
-
-        printf("Saw %d files.\n", total);
-
-        #if FINDERRORS_COMPILE_SHADERS
-        MOJOSHADER_glDestroyContext(ctx);
-        SDL_Quit();
-        #endif
-    } // else
-
-    return 0;
-} // main
-
-// end of finderrors.c ...
-
--- a/glcaps.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-#ifdef _WINDOWS
-#define WIN32_LEAN_AND_MEAN 1
-#include <windows.h>
-#endif
-
-#include <stdio.h>
-#define GL_GLEXT_LEGACY 1
-#include "GL/gl.h"
-#include "GL/glext.h"
-#include "SDL.h"
-
-#ifndef WINGDIAPI
-#define WINGDIAPI
-#endif
-
-typedef WINGDIAPI void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
-typedef WINGDIAPI const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
-
-#ifndef GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT
-#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
-#endif
-#ifndef GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT
-#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
-#endif
-#ifndef GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT
-#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
-#endif
-#ifndef GL_MAX_BINDABLE_UNIFORM_SIZE_EXT
-#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
-#endif
-
-
-int main(int argc, char **argv)
-{
-    GLint val = 0;
-    const char *str = NULL;
-
-    SDL_Init(SDL_INIT_VIDEO);
-    SDL_GL_LoadLibrary(NULL);
-    SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
-
-    PFNGLGETSTRINGPROC pglGetString = (PFNGLGETSTRINGPROC) SDL_GL_GetProcAddress("glGetString");
-    PFNGLGETINTEGERVPROC pglGetIntegerv = (PFNGLGETINTEGERVPROC) SDL_GL_GetProcAddress("glGetIntegerv");
-    PFNGLGETPROGRAMIVARBPROC pglGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) SDL_GL_GetProcAddress("glGetProgramivARB");
-
-    printf("Basic strings...\n\n");
-
-    #define getval(x) printf(#x ": %s\n", pglGetString(x))
-
-    getval(GL_RENDERER);
-    getval(GL_VERSION);
-    getval(GL_VENDOR);
-
-    #undef getval
-
-    printf("\nExtensions...\n\n");
-
-    const GLubyte *ext = pglGetString(GL_EXTENSIONS);
-    while (*ext)
-    {
-        fputc((*ext == ' ') ? '\n' : ((int) *ext), stdout);
-        ext++;
-    } // while
-
-    ext--;
-    if (*ext != ' ')
-        printf("\n");
-
-    printf("\nARB1 values...\n\n");
-
-    if (pglGetProgramivARB == NULL)
-        printf("  (unsupported.)\n");
-    else
-    {
-        #define getval(x) \
-            val = -1; \
-            pglGetProgramivARB(GL_VERTEX_PROGRAM_ARB, x, &val); \
-            printf(#x ": %d\n", (int) val);
-
-        getval(GL_MAX_PROGRAM_INSTRUCTIONS_ARB);
-        getval(GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
-        getval(GL_MAX_PROGRAM_TEMPORARIES_ARB);
-        getval(GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
-        getval(GL_MAX_PROGRAM_PARAMETERS_ARB);
-        getval(GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
-        getval(GL_MAX_PROGRAM_ATTRIBS_ARB);
-        getval(GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
-        getval(GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
-        getval(GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
-        getval(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
-        getval(GL_MAX_PROGRAM_ENV_PARAMETERS_ARB);
-        getval(GL_MAX_PROGRAM_PARAMETERS_ARB);
-
-        #undef getval
-    } // else
-
-    printf("\nGLSL values...\n\n");
-
-    #define getval(x) \
-        val = -1; \
-        pglGetIntegerv(x, &val); \
-        printf(#x ": %d\n", (int) val);
-
-    str = (const char *) pglGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
-    printf("GL_SHADING_LANGUAGE_VERSION_ARB: %s\n", str);
-    getval(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB);
-    getval(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB);
-    getval(GL_MAX_VARYING_FLOATS_ARB);
-    getval(GL_MAX_VERTEX_ATTRIBS_ARB);
-    getval(GL_MAX_TEXTURE_IMAGE_UNITS_ARB);
-    getval(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB);
-    getval(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB);
-    getval(GL_MAX_TEXTURE_COORDS_ARB);
-
-    printf("\nGL_EXT_bindable_uniform values...\n\n");
-
-    getval(GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT);
-    getval(GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT);
-    getval(GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT);
-    getval(GL_MAX_BINDABLE_UNIFORM_SIZE_EXT);
-
-    #undef getval
-
-    SDL_Quit();
-    printf("\n");
-
-    return 0;
-}
-
-
--- a/preprocess.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "mojoshader.h"
-
-static int preprocess(const char *fname, const char *buf, int len,
-                      const char *outfile)
-{
-    FILE *io = fopen(outfile, "wb");
-    if (io == NULL)
-    {
-        printf(" ... fopen('%s') failed.\n", outfile);
-        return 0;
-    } // if
-
-    const MOJOSHADER_preprocessData *pd;
-    int retval = 0;
-
-    pd = MOJOSHADER_preprocess(fname, buf, len, NULL, 0, NULL,
-                               NULL, NULL, NULL, NULL);
-
-    if (pd->error_count > 0)
-    {
-        int i;
-        for (i = 0; i < pd->error_count; i++)
-        {
-            printf("%s:%d: ERROR: %s\n",
-                    pd->errors[i].filename ? pd->errors[i].filename : "???",
-                    pd->errors[i].error_position,
-                    pd->errors[i].error);
-        } // for
-    } // if
-    else
-    {
-        if (pd->output != NULL)
-        {
-            if (fwrite(pd->output, pd->output_len, 1, io) != 1)
-                printf(" ... fwrite('%s') failed.\n", outfile);
-            else if (fclose(io) == EOF)
-                printf(" ... fclose('%s') failed.\n", outfile);
-            else
-                retval = 1;
-        } // if
-    } // else
-    MOJOSHADER_freePreprocessData(pd);
-
-    return retval;
-} // preprocess
-
-
-int main(int argc, char **argv)
-{
-    int retval = 1;
-
-    if (argc != 3)
-        printf("\n\nUSAGE: %s <inputfile> <outputfile>\n\n", argv[0]);
-    else
-    {
-        const char *infile = argv[1];
-        const char *outfile = argv[2];
-        FILE *io = fopen(infile, "rb");
-        if (io == NULL)
-            printf(" ... fopen('%s') failed.\n", infile);
-        else
-        {
-            char *buf = (char *) malloc(1000000);
-            int rc = fread(buf, 1, 1000000, io);
-            fclose(io);
-            if (rc == EOF)
-                printf(" ... fread('%s') failed.\n", infile);
-            else
-            {
-                if (preprocess(infile, buf, rc, outfile))
-                    retval = 0;
-                else
-                    remove(outfile);
-                free(buf);
-            } // else
-        } // for
-    } // else
-
-    return retval;
-} // main
-
-// end of preprocess.c ...
-
--- a/testoutput.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "mojoshader.h"
-
-static int do_parse(const unsigned char *buf, const int len, const char *prof)
-{
-    const MOJOSHADER_parseData *pd;
-    int retval = 0;
-
-    pd = MOJOSHADER_parse(prof, buf, len, NULL, 0, NULL, NULL, NULL);
-    if (pd->error_count > 0)
-    {
-        int i;
-        for (i = 0; i < pd->error_count; i++)
-        {
-            printf("%s:%d: ERROR: %s\n",
-                    pd->errors[i].filename ? pd->errors[i].filename : "???",
-                    pd->errors[i].error_position,
-                    pd->errors[i].error);
-        } // for
-    } // if
-    else
-    {
-        retval = 1;
-        if (pd->output != NULL)
-        {
-            int i;
-            for (i = 0; i < pd->output_len; i++)
-                putchar((int) pd->output[i]);
-            printf("\n");
-        } // if
-    } // else
-    printf("\n\n");
-    MOJOSHADER_freeParseData(pd);
-
-    return retval;
-} // do_parse
-
-
-int main(int argc, char **argv)
-{
-    int retval = 0;
-
-    if (argc <= 2)
-        printf("\n\nUSAGE: %s <profile> [file1] ... [fileN]\n\n", argv[0]);
-    else
-    {
-        const char *profile = argv[1];
-        int i;
-
-        for (i = 2; i < argc; i++)
-        {
-            FILE *io = fopen(argv[i], "rb");
-            if (io == NULL)
-                printf(" ... fopen('%s') failed.\n", argv[i]);
-            else
-            {
-                unsigned char *buf = (unsigned char *) malloc(1000000);
-                int rc = fread(buf, 1, 1000000, io);
-                fclose(io);
-                if (!do_parse(buf, rc, profile))
-                    retval = 1;
-                free(buf);
-            } // else
-        } // for
-    } // else
-
-    return retval;
-} // main
-
-// end of testoutput.c ...
-
--- a/testparse.c	Thu Feb 12 17:25:49 2009 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-/**
- * MojoShader; generate shader programs from bytecode of compiled
- *  Direct3D shaders.
- *
- * Please see the file LICENSE.txt in the source's root directory.
- *
- *  This file written by Ryan C. Gordon.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "mojoshader.h"
-
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
-
-#if MOJOSHADER_DEBUG_MALLOC
-static void *Malloc(int len)
-{
-    void *ptr = malloc(len + sizeof (int));
-    int *store = (int *) ptr;
-    printf("malloc() %d bytes (%p)\n", len, ptr);
-    if (ptr == NULL) return NULL;
-    *store = len;
-    return (void *) (store + 1);
-} // Malloc
-
-
-static void Free(void *_ptr)
-{
-    int *ptr = (((int *) _ptr) - 1);
-    int len = *ptr;
-    printf("free() %d bytes (%p)\n", len, ptr);
-    free(ptr);
-} // Free
-#else
-#define Malloc NULL
-#define Free NULL
-#endif
-
-static const char *shader_type(const MOJOSHADER_shaderType s)
-{
-    switch (s)
-    {
-        case MOJOSHADER_TYPE_UNKNOWN: return "unknown";
-        case MOJOSHADER_TYPE_PIXEL: return "pixel";
-        case MOJOSHADER_TYPE_VERTEX: return "vertex";
-        case MOJOSHADER_TYPE_GEOMETRY: return "geometry";
-        default: return "(bogus value?)";
-    } // switch
-
-    return NULL;  // shouldn't hit this.
-} // shader_type
-
-
-static int do_parse(const unsigned char *buf, const int len, const char *prof)
-{
-    const MOJOSHADER_parseData *pd;
-    int retval = 0;
-
-    pd = MOJOSHADER_parse(prof, buf, len, NULL, 0, Malloc, Free, NULL);
-    printf("PROFILE: %s\n", prof);
-    if (pd->error_count > 0)
-    {
-        int i;
-        for (i = 0; i < pd->error_count; i++)
-        {
-            printf("%s:%d: ERROR: %s\n",
-                    pd->errors[i].filename ? pd->errors[i].filename : "???",
-                    pd->errors[i].error_position,
-                    pd->errors[i].error);
-        } // for
-    } // if
-    else
-    {
-        retval = 1;
-        printf("SHADER TYPE: %s\n", shader_type(pd->shader_type));
-        printf("VERSION: %d.%d\n", pd->major_ver, pd->minor_ver);
-        printf("INSTRUCTION COUNT: %d\n", (int) pd->instruction_count);
-
-        printf("ATTRIBUTES:");
-        if (pd->attribute_count == 0)
-            printf(" (none.)\n");
-        else
-        {
-            int i;
-            printf("\n");
-            for (i = 0; i < pd->attribute_count; i++)
-            {
-                static const char *usagenames[] = {
-                    "position", "blendweight", "blendindices", "normal",
-                    "psize", "texcoord", "tangent", "binormal", "tessfactor",
-                    "positiont", "color", "fog", "depth", "sample"
-                };
-                const MOJOSHADER_attribute *a = &pd->attributes[i];
-                char numstr[16] = { 0 };
-                if (a->index != 0)
-                    snprintf(numstr, sizeof (numstr), "%d", a->index);
-                printf("    * %s%s", usagenames[(int) a->usage], numstr);
-                if (a->name != NULL)
-                    printf(" (\"%s\")", a->name);
-                printf("\n");
-            } // for
-        } // else
-
-        printf("CONSTANTS:");
-        if (pd->constant_count == 0)
-            printf(" (none.)\n");
-        else
-        {
-            int i;
-            printf("\n");
-            for (i = 0; i < pd->constant_count; i++)
-            {
-                static const char *typenames[] = { "float", "int", "bool" };
-                const MOJOSHADER_constant *c = &pd->constants[i];
-                printf("    * %d: %s (", c->index, typenames[(int) c->type]);
-                if (c->type == MOJOSHADER_UNIFORM_FLOAT)
-                {
-                    printf("%f %f %f %f", c->value.f[0], c->value.f[1],
-                                          c->value.f[2], c->value.f[3]);
-                } // if
-                else if (c->type == MOJOSHADER_UNIFORM_INT)
-                {
-                    printf("%d %d %d %d", c->value.i[0], c->value.i[1],
-                                          c->value.i[2], c->value.i[3]);
-                } // else if
-                else if (c->type == MOJOSHADER_UNIFORM_BOOL)
-                {
-                    printf("%s", c->value.b ? "true" : "false");
-                } // else if
-                else
-                {
-                    printf("???");
-                } // else
-                printf(")\n");
-            } // for
-        } // else
-
-        printf("UNIFORMS:");
-        if (pd->uniform_count == 0)
-            printf(" (none.)\n");
-        else
-        {
-            int i;
-            printf("\n");
-            for (i = 0; i < pd->uniform_count; i++)
-            {
-                static const char *typenames[] = { "float", "int", "bool" };
-                const MOJOSHADER_uniform *u = &pd->uniforms[i];
-                const char *arrayof = "";
-                const char *constant = u->constant ? "const " : "";
-                char arrayrange[64] = { '\0' };
-                if (u->array_count > 0)
-                {
-                    arrayof = "array[";
-                    snprintf(arrayrange, sizeof (arrayrange), "%d] ",
-                             u->array_count);
-                } // if
-
-                printf("    * %d: %s%s%s%s", u->index, constant, arrayof,
-                        arrayrange, typenames[(int) u->type]);
-                if (u->name != NULL)
-                    printf(" (\"%s\")", u->name);
-                printf("\n");
-            } // for
-        } // else
-
-        printf("SAMPLERS:");
-        if (pd->sampler_count == 0)
-            printf(" (none.)\n");
-        else
-        {
-            int i;
-            printf("\n");
-            for (i = 0; i < pd->sampler_count; i++)
-            {
-                static const char *typenames[] = { "2d", "cube", "volume" };
-                const MOJOSHADER_sampler *s = &pd->samplers[i];
-                printf("    * %d: %s", s->index, typenames[(int) s->type]);
-                if (s->name != NULL)
-                    printf(" (\"%s\")", s->name);
-                printf("\n");
-            } // for
-        } // else
-
-        if (pd->output != NULL)
-        {
-            int i;
-            printf("OUTPUT:\n");
-            for (i = 0; i < pd->output_len; i++)
-                putchar((int) pd->output[i]);
-            printf("\n");
-        } // if
-    } // else
-    printf("\n\n");
-    MOJOSHADER_freeParseData(pd);
-
-    return retval;
-} // do_parse
-
-
-int main(int argc, char **argv)
-{
-    int retval = 0;
-
-    printf("MojoShader testparse\n");
-    printf("Compiled against version %d\n", MOJOSHADER_VERSION);
-    printf("Linked against version %d\n", MOJOSHADER_version());
-    printf("\n");
-
-    if (argc <= 2)
-        printf("\n\nUSAGE: %s <profile> [file1] ... [fileN]\n\n", argv[0]);
-    else
-    {
-        const char *profile = argv[1];
-        int i;
-
-        for (i = 2; i < argc; i++)
-        {
-            FILE *io = fopen(argv[i], "rb");
-            printf("FILE: %s\n", argv[i]);
-            if (io == NULL)
-                printf(" ... fopen('%s') failed.\n", argv[i]);
-            else
-            {
-                unsigned char *buf = (unsigned char *) malloc(1000000);
-                int rc = fread(buf, 1, 1000000, io);
-                fclose(io);
-                if (!do_parse(buf, rc, profile))
-                    retval = 1;
-                free(buf);
-            } // else
-        } // for
-    } // else
-
-    return retval;
-} // main
-
-// end of testparse.c ...
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/assemble.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,93 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mojoshader.h"
+
+static int assemble(const char *fname, const char *buf, int len,
+                    const char *outfile)
+{
+    FILE *io = fopen(outfile, "wb");
+    if (io == NULL)
+    {
+        printf(" ... fopen('%s') failed.\n", outfile);
+        return 0;
+    } // if
+
+    const MOJOSHADER_parseData *pd;
+    int retval = 0;
+
+    pd = MOJOSHADER_assemble(fname, buf, len, NULL, 0, NULL, 0,
+                             NULL, 0, NULL, NULL, NULL, NULL, NULL);
+    if (pd->error_count > 0)
+    {
+        int i;
+        for (i = 0; i < pd->error_count; i++)
+        {
+            printf("%s:%d: ERROR: %s\n",
+                    pd->errors[i].filename ? pd->errors[i].filename : "???",
+                    pd->errors[i].error_position,
+                    pd->errors[i].error);
+        } // for
+    } // if
+    else
+    {
+        if (pd->output != NULL)
+        {
+            if (fwrite(pd->output, pd->output_len, 1, io) != 1)
+                printf(" ... fwrite('%s') failed.\n", outfile);
+            else if (fclose(io) == EOF)
+                printf(" ... fclose('%s') failed.\n", outfile);
+            else
+                retval = 1;
+        } // if
+    } // else
+    MOJOSHADER_freeParseData(pd);
+
+    return retval;
+} // assemble
+
+
+int main(int argc, char **argv)
+{
+    int retval = 1;
+
+    if (argc != 3)
+        printf("\n\nUSAGE: %s <inputfile> <outputfile>\n\n", argv[0]);
+    else
+    {
+        const char *infile = argv[1];
+        const char *outfile = argv[2];
+        FILE *io = fopen(infile, "rb");
+        if (io == NULL)
+            printf(" ... fopen('%s') failed.\n", infile);
+        else
+        {
+            char *buf = (char *) malloc(1000000);
+            int rc = fread(buf, 1, 1000000, io);
+            fclose(io);
+            if (rc == EOF)
+                printf(" ... fread('%s') failed.\n", infile);
+            else
+            {
+                if (assemble(infile, buf, rc, outfile))
+                    retval = 0;
+                else
+                    remove(outfile);
+                free(buf);
+            } // else
+        } // for
+    } // else
+
+    return retval;
+} // main
+
+// end of assemble.c ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/availableprofiles.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,67 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include "mojoshader.h"
+#include "SDL.h"
+
+static int check_available(void)
+{
+    const char **avail = NULL;
+    int total = MOJOSHADER_glAvailableProfiles(SDL_GL_GetProcAddress, NULL, 0);
+    if (total > 0)
+    {
+        avail = (const char **) alloca(sizeof (const char *) * total);
+        total = MOJOSHADER_glAvailableProfiles(SDL_GL_GetProcAddress, avail, total);
+    } // if
+
+    if (total <= 0)
+        fprintf(stderr, "No profiles available.\n");
+    else
+    {
+        int i;
+        for (i = 0; i < total; i++)
+        {
+            printf("%s (Shader Model %d)\n", avail[i],
+                   MOJOSHADER_maxShaderModel(avail[i]));
+        } // for
+    } // else
+
+    return 0;
+} // check_available
+
+
+int main(int argc, char **argv)
+{
+    int retval = 1;
+
+    #if 0
+    printf("MojoShader availableprofile\n");
+    printf("Compiled against version %d\n", MOJOSHADER_VERSION);
+    printf("Linked against version %d\n", MOJOSHADER_version());
+    printf("\n");
+    #endif
+
+    if (SDL_Init(SDL_INIT_VIDEO) == -1)
+        fprintf(stderr, "SDL_Init(SDL_INIT_VIDEO) error: %s\n", SDL_GetError());
+    else
+    {
+        SDL_GL_LoadLibrary(NULL);
+        if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL)
+            fprintf(stderr, "SDL_SetVideoMode() error: %s\n", SDL_GetError());
+        else
+            retval = check_available();
+        SDL_Quit();
+    } // else
+
+    return retval;
+} // main
+
+// end of availableprofiles.c ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/bestprofile.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,53 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include "mojoshader.h"
+#include "SDL.h"
+
+int main(int argc, char **argv)
+{
+    int retval = 1;
+
+    #if 0
+    printf("MojoShader bestprofile\n");
+    printf("Compiled against version %d\n", MOJOSHADER_VERSION);
+    printf("Linked against version %d\n", MOJOSHADER_version());
+    printf("\n");
+    #endif
+
+    if (SDL_Init(SDL_INIT_VIDEO) == -1)
+        fprintf(stderr, "SDL_Init(SDL_INIT_VIDEO) error: %s\n", SDL_GetError());
+    else
+    {
+        SDL_GL_LoadLibrary(NULL);
+        if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL)
+            fprintf(stderr, "SDL_SetVideoMode() error: %s\n", SDL_GetError());
+        else
+        {
+            const char *best = MOJOSHADER_glBestProfile(SDL_GL_GetProcAddress);
+            MOJOSHADER_glContext *ctx;
+            ctx = MOJOSHADER_glCreateContext(best, SDL_GL_GetProcAddress, 0, 0, 0);
+            if (ctx == NULL)
+                printf("MOJOSHADER_glCreateContext() fail: %s\n", MOJOSHADER_glGetError());
+            else
+            {
+                printf("%s\n", best);
+                retval = 0;  // success.
+                MOJOSHADER_glDestroyContext(ctx);
+            } // else
+        } // else
+        SDL_Quit();
+    } // else
+
+    return retval;
+} // main
+
+// end of bestprofile.c ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/finderrors.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,222 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include "mojoshader.h"
+
+#if FINDERRORS_COMPILE_SHADERS
+#include "SDL.h"
+#endif
+
+#ifdef _MSC_VER
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#include <malloc.h>  // for alloca().
+#define snprintf _snprintf
+#else
+#include <dirent.h>
+#endif
+
+#define report printf
+
+static int do_file(const char *profile, const char *dname, const char *fn, int *total)
+{
+    int do_quit = 0;
+
+    #if FINDERRORS_COMPILE_SHADERS
+    SDL_Event e;  // pump event queue to keep OS happy.
+    while (SDL_PollEvent(&e))
+    {
+        if (e.type == SDL_QUIT)
+            do_quit = 1;
+    } // while
+    SDL_GL_SwapBuffers();
+    #endif
+
+    if (do_quit)
+    {
+        report("FAIL: user requested quit!\n");
+        return 0;
+    } // if
+
+    int assembly = 0;
+    if (strstr(fn, ".bytecode") != NULL)
+        assembly = 0;
+    else if (strstr(fn, ".disasm") != NULL)
+        assembly = 1;
+    else
+        return 1;
+
+    (*total)++;
+
+    char *fname = (char *) alloca(strlen(fn) + strlen(dname) + 1);
+    sprintf(fname, "%s/%s", dname, fn);
+    FILE *io = fopen(fname, "rb");
+    if (io == NULL)
+    {
+        report("FAIL: %s fopen() failed.\n", fname);
+        return 1;
+    } // if
+
+    static unsigned char buf[1024 * 256];
+    int rc = fread(buf, 1, sizeof (buf), io);
+    fclose(io);
+    if (rc == -1)
+    {
+        report("FAIL: %s %s\n", fname, strerror(errno));
+        return 1;
+    } // if
+
+    if (assembly)
+    {
+        const MOJOSHADER_parseData *a;
+
+        buf[rc] = '\0';  // make sure the source is null-terminated.
+        a = MOJOSHADER_assemble(fname, (char *) buf, rc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+        if (a->error_count > 0)
+        {
+            report("FAIL: %s (line %d) %s\n",
+                a->errors[0].filename ? a->errors[0].filename : "???",
+                a->errors[0].error_position,
+                a->errors[0].error);
+            return 1;
+        } // if
+
+        else if (a->output_len > sizeof (buf))
+        {
+            report("FAIL: %s buffer overflow in finderrors.c\n", fname);
+            return 1;
+        } // if
+
+        rc = a->output_len;
+        memcpy(buf, a->output, rc);
+        MOJOSHADER_freeParseData(a);
+    } // if
+
+    #if FINDERRORS_COMPILE_SHADERS
+    MOJOSHADER_glShader *shader = MOJOSHADER_glCompileShader(buf, rc, NULL, 0);
+    if (shader == NULL)
+        report("FAIL: %s %s\n", fname, MOJOSHADER_glGetError());
+    else
+    {
+        const MOJOSHADER_parseData *pd = MOJOSHADER_glGetShaderParseData(shader);
+        MOJOSHADER_glShader *v = (pd->shader_type == MOJOSHADER_TYPE_VERTEX) ? shader : NULL;
+        MOJOSHADER_glShader *p = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? shader : NULL;
+        MOJOSHADER_glProgram *program = MOJOSHADER_glLinkProgram(v, p);
+        if (program == NULL)
+            report("FAIL: %s %s\n", fname, MOJOSHADER_glGetError());
+        else
+        {
+            report("PASS: %s\n", fname);
+            MOJOSHADER_glDeleteProgram(program);
+        } // else
+        MOJOSHADER_glDeleteShader(shader);
+    }
+    #else
+    const MOJOSHADER_parseData *pd = MOJOSHADER_parse(profile, buf, rc, NULL, 0, NULL, NULL, NULL);
+    if (pd->error != NULL)
+        report("FAIL: %s (position %d) %s\n", fname, pd->error_position, pd->error);
+    else
+        report("PASS: %s\n", fname);
+    MOJOSHADER_freeParseData(pd);
+    #endif
+
+    return 1;
+} // do_file
+
+
+static int do_dir(const char *dname, const char *profile)
+{
+    int total = 0;
+
+#ifdef _MSC_VER
+    WIN32_FIND_DATA dent;
+    HANDLE dirp = INVALID_HANDLE_VALUE;
+    FindFirstFileA(dname, &dent);
+    if (dirp != INVALID_HANDLE_VALUE)
+    {
+        do
+        {
+            if (!do_file(profile, dname, dent.cFileName, &total))
+                break;
+        } while (FindNextFileA(dirp, &dent) != 0);
+        CloseHandle(dirp);
+    } // if
+#else
+    struct dirent *dent = NULL;
+    DIR *dirp = opendir(dname);
+    if (dirp != NULL)
+    {
+        while ((dent = readdir(dirp)) != NULL)
+        {
+            if (!do_file(profile, dname, dent->d_name, &total))
+                break;
+        } // while
+        closedir(dirp);
+    } // if
+#endif
+
+    return total;
+} // do_dir
+
+
+int main(int argc, char **argv)
+{
+    //printf("MojoShader finderrors\n");
+    //printf("Compiled against version %d\n", MOJOSHADER_VERSION);
+    //printf("Linked against version %d\n", MOJOSHADER_version());
+    //printf("\n");
+
+    if (argc <= 2)
+        printf("\n\nUSAGE: %s <profile> [dir1] ... [dirN]\n\n", argv[0]);
+    else
+    {
+        int total = 0;
+        int i;
+        const char *profile = argv[1];
+
+        #if FINDERRORS_COMPILE_SHADERS
+        SDL_Init(SDL_INIT_VIDEO);
+        SDL_GL_LoadLibrary(NULL);
+        SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
+        printf("Best profile is '%s'\n", MOJOSHADER_glBestProfile(SDL_GL_GetProcAddress));
+        MOJOSHADER_glContext *ctx;
+        ctx = MOJOSHADER_glCreateContext(profile, SDL_GL_GetProcAddress, 0, 0, 0);
+        if (ctx == NULL)
+        {
+            printf("MOJOSHADER_glCreateContext() fail: %s\n", MOJOSHADER_glGetError());
+            SDL_Quit();
+            return 1;
+        } // if
+        MOJOSHADER_glMakeContextCurrent(ctx);
+        #endif
+
+        for (i = 2; i < argc; i++)
+            total += do_dir(argv[i], profile);
+
+        printf("Saw %d files.\n", total);
+
+        #if FINDERRORS_COMPILE_SHADERS
+        MOJOSHADER_glDestroyContext(ctx);
+        SDL_Quit();
+        #endif
+    } // else
+
+    return 0;
+} // main
+
+// end of finderrors.c ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/glcaps.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,130 @@
+#ifdef _WINDOWS
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#include <stdio.h>
+#define GL_GLEXT_LEGACY 1
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "SDL.h"
+
+#ifndef WINGDIAPI
+#define WINGDIAPI
+#endif
+
+typedef WINGDIAPI void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
+typedef WINGDIAPI const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+
+#ifndef GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#endif
+#ifndef GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#endif
+#ifndef GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#endif
+#ifndef GL_MAX_BINDABLE_UNIFORM_SIZE_EXT
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#endif
+
+
+int main(int argc, char **argv)
+{
+    GLint val = 0;
+    const char *str = NULL;
+
+    SDL_Init(SDL_INIT_VIDEO);
+    SDL_GL_LoadLibrary(NULL);
+    SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
+
+    PFNGLGETSTRINGPROC pglGetString = (PFNGLGETSTRINGPROC) SDL_GL_GetProcAddress("glGetString");
+    PFNGLGETINTEGERVPROC pglGetIntegerv = (PFNGLGETINTEGERVPROC) SDL_GL_GetProcAddress("glGetIntegerv");
+    PFNGLGETPROGRAMIVARBPROC pglGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) SDL_GL_GetProcAddress("glGetProgramivARB");
+
+    printf("Basic strings...\n\n");
+
+    #define getval(x) printf(#x ": %s\n", pglGetString(x))
+
+    getval(GL_RENDERER);
+    getval(GL_VERSION);
+    getval(GL_VENDOR);
+
+    #undef getval
+
+    printf("\nExtensions...\n\n");
+
+    const GLubyte *ext = pglGetString(GL_EXTENSIONS);
+    while (*ext)
+    {
+        fputc((*ext == ' ') ? '\n' : ((int) *ext), stdout);
+        ext++;
+    } // while
+
+    ext--;
+    if (*ext != ' ')
+        printf("\n");
+
+    printf("\nARB1 values...\n\n");
+
+    if (pglGetProgramivARB == NULL)
+        printf("  (unsupported.)\n");
+    else
+    {
+        #define getval(x) \
+            val = -1; \
+            pglGetProgramivARB(GL_VERTEX_PROGRAM_ARB, x, &val); \
+            printf(#x ": %d\n", (int) val);
+
+        getval(GL_MAX_PROGRAM_INSTRUCTIONS_ARB);
+        getval(GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
+        getval(GL_MAX_PROGRAM_TEMPORARIES_ARB);
+        getval(GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
+        getval(GL_MAX_PROGRAM_PARAMETERS_ARB);
+        getval(GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
+        getval(GL_MAX_PROGRAM_ATTRIBS_ARB);
+        getval(GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
+        getval(GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
+        getval(GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
+        getval(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
+        getval(GL_MAX_PROGRAM_ENV_PARAMETERS_ARB);
+        getval(GL_MAX_PROGRAM_PARAMETERS_ARB);
+
+        #undef getval
+    } // else
+
+    printf("\nGLSL values...\n\n");
+
+    #define getval(x) \
+        val = -1; \
+        pglGetIntegerv(x, &val); \
+        printf(#x ": %d\n", (int) val);
+
+    str = (const char *) pglGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
+    printf("GL_SHADING_LANGUAGE_VERSION_ARB: %s\n", str);
+    getval(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB);
+    getval(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB);
+    getval(GL_MAX_VARYING_FLOATS_ARB);
+    getval(GL_MAX_VERTEX_ATTRIBS_ARB);
+    getval(GL_MAX_TEXTURE_IMAGE_UNITS_ARB);
+    getval(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB);
+    getval(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB);
+    getval(GL_MAX_TEXTURE_COORDS_ARB);
+
+    printf("\nGL_EXT_bindable_uniform values...\n\n");
+
+    getval(GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT);
+    getval(GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT);
+    getval(GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT);
+    getval(GL_MAX_BINDABLE_UNIFORM_SIZE_EXT);
+
+    #undef getval
+
+    SDL_Quit();
+    printf("\n");
+
+    return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/preprocess.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,94 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mojoshader.h"
+
+static int preprocess(const char *fname, const char *buf, int len,
+                      const char *outfile)
+{
+    FILE *io = fopen(outfile, "wb");
+    if (io == NULL)
+    {
+        printf(" ... fopen('%s') failed.\n", outfile);
+        return 0;
+    } // if
+
+    const MOJOSHADER_preprocessData *pd;
+    int retval = 0;
+
+    pd = MOJOSHADER_preprocess(fname, buf, len, NULL, 0, NULL,
+                               NULL, NULL, NULL, NULL);
+
+    if (pd->error_count > 0)
+    {
+        int i;
+        for (i = 0; i < pd->error_count; i++)
+        {
+            printf("%s:%d: ERROR: %s\n",
+                    pd->errors[i].filename ? pd->errors[i].filename : "???",
+                    pd->errors[i].error_position,
+                    pd->errors[i].error);
+        } // for
+    } // if
+    else
+    {
+        if (pd->output != NULL)
+        {
+            if (fwrite(pd->output, pd->output_len, 1, io) != 1)
+                printf(" ... fwrite('%s') failed.\n", outfile);
+            else if (fclose(io) == EOF)
+                printf(" ... fclose('%s') failed.\n", outfile);
+            else
+                retval = 1;
+        } // if
+    } // else
+    MOJOSHADER_freePreprocessData(pd);
+
+    return retval;
+} // preprocess
+
+
+int main(int argc, char **argv)
+{
+    int retval = 1;
+
+    if (argc != 3)
+        printf("\n\nUSAGE: %s <inputfile> <outputfile>\n\n", argv[0]);
+    else
+    {
+        const char *infile = argv[1];
+        const char *outfile = argv[2];
+        FILE *io = fopen(infile, "rb");
+        if (io == NULL)
+            printf(" ... fopen('%s') failed.\n", infile);
+        else
+        {
+            char *buf = (char *) malloc(1000000);
+            int rc = fread(buf, 1, 1000000, io);
+            fclose(io);
+            if (rc == EOF)
+                printf(" ... fread('%s') failed.\n", infile);
+            else
+            {
+                if (preprocess(infile, buf, rc, outfile))
+                    retval = 0;
+                else
+                    remove(outfile);
+                free(buf);
+            } // else
+        } // for
+    } // else
+
+    return retval;
+} // main
+
+// end of preprocess.c ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/testoutput.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,81 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mojoshader.h"
+
+static int do_parse(const unsigned char *buf, const int len, const char *prof)
+{
+    const MOJOSHADER_parseData *pd;
+    int retval = 0;
+
+    pd = MOJOSHADER_parse(prof, buf, len, NULL, 0, NULL, NULL, NULL);
+    if (pd->error_count > 0)
+    {
+        int i;
+        for (i = 0; i < pd->error_count; i++)
+        {
+            printf("%s:%d: ERROR: %s\n",
+                    pd->errors[i].filename ? pd->errors[i].filename : "???",
+                    pd->errors[i].error_position,
+                    pd->errors[i].error);
+        } // for
+    } // if
+    else
+    {
+        retval = 1;
+        if (pd->output != NULL)
+        {
+            int i;
+            for (i = 0; i < pd->output_len; i++)
+                putchar((int) pd->output[i]);
+            printf("\n");
+        } // if
+    } // else
+    printf("\n\n");
+    MOJOSHADER_freeParseData(pd);
+
+    return retval;
+} // do_parse
+
+
+int main(int argc, char **argv)
+{
+    int retval = 0;
+
+    if (argc <= 2)
+        printf("\n\nUSAGE: %s <profile> [file1] ... [fileN]\n\n", argv[0]);
+    else
+    {
+        const char *profile = argv[1];
+        int i;
+
+        for (i = 2; i < argc; i++)
+        {
+            FILE *io = fopen(argv[i], "rb");
+            if (io == NULL)
+                printf(" ... fopen('%s') failed.\n", argv[i]);
+            else
+            {
+                unsigned char *buf = (unsigned char *) malloc(1000000);
+                int rc = fread(buf, 1, 1000000, io);
+                fclose(io);
+                if (!do_parse(buf, rc, profile))
+                    retval = 1;
+                free(buf);
+            } // else
+        } // for
+    } // else
+
+    return retval;
+} // main
+
+// end of testoutput.c ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/testparse.c	Thu Feb 12 17:29:24 2009 -0500
@@ -0,0 +1,242 @@
+/**
+ * MojoShader; generate shader programs from bytecode of compiled
+ *  Direct3D shaders.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  This file written by Ryan C. Gordon.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mojoshader.h"
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#if MOJOSHADER_DEBUG_MALLOC
+static void *Malloc(int len)
+{
+    void *ptr = malloc(len + sizeof (int));
+    int *store = (int *) ptr;
+    printf("malloc() %d bytes (%p)\n", len, ptr);
+    if (ptr == NULL) return NULL;
+    *store = len;
+    return (void *) (store + 1);
+} // Malloc
+
+
+static void Free(void *_ptr)
+{
+    int *ptr = (((int *) _ptr) - 1);
+    int len = *ptr;
+    printf("free() %d bytes (%p)\n", len, ptr);
+    free(ptr);
+} // Free
+#else
+#define Malloc NULL
+#define Free NULL
+#endif
+
+static const char *shader_type(const MOJOSHADER_shaderType s)
+{
+    switch (s)
+    {
+        case MOJOSHADER_TYPE_UNKNOWN: return "unknown";
+        case MOJOSHADER_TYPE_PIXEL: return "pixel";
+        case MOJOSHADER_TYPE_VERTEX: return "vertex";
+        case MOJOSHADER_TYPE_GEOMETRY: return "geometry";
+        default: return "(bogus value?)";
+    } // switch
+
+    return NULL;  // shouldn't hit this.
+} // shader_type
+
+
+static int do_parse(const unsigned char *buf, const int len, const char *prof)
+{
+    const MOJOSHADER_parseData *pd;
+    int retval = 0;
+
+    pd = MOJOSHADER_parse(prof, buf, len, NULL, 0, Malloc, Free, NULL);
+    printf("PROFILE: %s\n", prof);
+    if (pd->error_count > 0)
+    {
+        int i;
+        for (i = 0; i < pd->error_count; i++)
+        {
+            printf("%s:%d: ERROR: %s\n",
+                    pd->errors[i].filename ? pd->errors[i].filename : "???",
+                    pd->errors[i].error_position,
+                    pd->errors[i].error);
+        } // for
+    } // if
+    else
+    {
+        retval = 1;
+        printf("SHADER TYPE: %s\n", shader_type(pd->shader_type));
+        printf("VERSION: %d.%d\n", pd->major_ver, pd->minor_ver);
+        printf("INSTRUCTION COUNT: %d\n", (int) pd->instruction_count);
+
+        printf("ATTRIBUTES:");
+        if (pd->attribute_count == 0)
+            printf(" (none.)\n");
+        else
+        {
+            int i;
+            printf("\n");
+            for (i = 0; i < pd->attribute_count; i++)
+            {
+                static const char *usagenames[] = {
+                    "position", "blendweight", "blendindices", "normal",
+                    "psize", "texcoord", "tangent", "binormal", "tessfactor",
+                    "positiont", "color", "fog", "depth", "sample"
+                };
+                const MOJOSHADER_attribute *a = &pd->attributes[i];
+                char numstr[16] = { 0 };
+                if (a->index != 0)
+                    snprintf(numstr, sizeof (numstr), "%d", a->index);
+                printf("    * %s%s", usagenames[(int) a->usage], numstr);
+                if (a->name != NULL)
+                    printf(" (\"%s\")", a->name);
+                printf("\n");
+            } // for
+        } // else
+
+        printf("CONSTANTS:");
+        if (pd->constant_count == 0)
+            printf(" (none.)\n");
+        else
+        {
+            int i;
+            printf("\n");
+            for (i = 0; i < pd->constant_count; i++)
+            {
+                static const char *typenames[] = { "float", "int", "bool" };
+                const MOJOSHADER_constant *c = &pd->constants[i];
+                printf("    * %d: %s (", c->index, typenames[(int) c->type]);
+                if (c->type == MOJOSHADER_UNIFORM_FLOAT)
+                {
+                    printf("%f %f %f %f", c->value.f[0], c->value.f[1],
+                                          c->value.f[2], c->value.f[3]);
+                } // if
+                else if (c->type == MOJOSHADER_UNIFORM_INT)
+                {
+                    printf("%d %d %d %d", c->value.i[0], c->value.i[1],
+                                          c->value.i[2], c->value.i[3]);
+                } // else if
+                else if (c->type == MOJOSHADER_UNIFORM_BOOL)
+                {
+                    printf("%s", c->value.b ? "true" : "false");
+                } // else if
+                else
+                {
+                    printf("???");
+                } // else
+                printf(")\n");
+            } // for
+        } // else
+
+        printf("UNIFORMS:");
+        if (pd->uniform_count == 0)
+            printf(" (none.)\n");
+        else
+        {
+            int i;
+            printf("\n");
+            for (i = 0; i < pd->uniform_count; i++)
+            {
+                static const char *typenames[] = { "float", "int", "bool" };
+                const MOJOSHADER_uniform *u = &pd->uniforms[i];
+                const char *arrayof = "";
+                const char *constant = u->constant ? "const " : "";
+                char arrayrange[64] = { '\0' };
+                if (u->array_count > 0)
+                {
+                    arrayof = "array[";
+                    snprintf(arrayrange, sizeof (arrayrange), "%d] ",
+                             u->array_count);
+                } // if
+
+                printf("    * %d: %s%s%s%s", u->index, constant, arrayof,
+                        arrayrange, typenames[(int) u->type]);
+                if (u->name != NULL)
+                    printf(" (\"%s\")", u->name);
+                printf("\n");
+            } // for
+        } // else
+
+        printf("SAMPLERS:");
+        if (pd->sampler_count == 0)
+            printf(" (none.)\n");
+        else
+        {
+            int i;
+            printf("\n");
+            for (i = 0; i < pd->sampler_count; i++)
+            {
+                static const char *typenames[] = { "2d", "cube", "volume" };
+                const MOJOSHADER_sampler *s = &pd->samplers[i];
+                printf("    * %d: %s", s->index, typenames[(int) s->type]);
+                if (s->name != NULL)
+                    printf(" (\"%s\")", s->name);
+                printf("\n");
+            } // for
+        } // else
+
+        if (pd->output != NULL)
+        {
+            int i;
+            printf("OUTPUT:\n");
+            for (i = 0; i < pd->output_len; i++)
+                putchar((int) pd->output[i]);
+            printf("\n");
+        } // if
+    } // else
+    printf("\n\n");
+    MOJOSHADER_freeParseData(pd);
+
+    return retval;
+} // do_parse
+
+
+int main(int argc, char **argv)
+{
+    int retval = 0;
+
+    printf("MojoShader testparse\n");
+    printf("Compiled against version %d\n", MOJOSHADER_VERSION);
+    printf("Linked against version %d\n", MOJOSHADER_version());
+    printf("\n");
+
+    if (argc <= 2)
+        printf("\n\nUSAGE: %s <profile> [file1] ... [fileN]\n\n", argv[0]);
+    else
+    {
+        const char *profile = argv[1];
+        int i;
+
+        for (i = 2; i < argc; i++)
+        {
+            FILE *io = fopen(argv[i], "rb");
+            printf("FILE: %s\n", argv[i]);
+            if (io == NULL)
+                printf(" ... fopen('%s') failed.\n", argv[i]);
+            else
+            {
+                unsigned char *buf = (unsigned char *) malloc(1000000);
+                int rc = fread(buf, 1, 1000000, io);
+                fclose(io);
+                if (!do_parse(buf, rc, profile))
+                    retval = 1;
+                free(buf);
+            } // else
+        } // for
+    } // else
+
+    return retval;
+} // main
+
+// end of testparse.c ...
+