static VSFileSystem::VSError getProgramSource(const std::string &path, std::vector<std::string> &lines, std::set<std::string> &processed_includes, char *buf, size_t buflen)
{
    std::string dirname = path.substr(0,path.find_last_of('/'));
    
    VSFileSystem::VSFile f;
    VSFileSystem::VSError err = f.OpenReadOnly( path.c_str(), UnknownFile );
    
    const char *include_directive = "#include \"";
    const size_t include_directive_len = 10;
    size_t lineno = 0;
    
    if (err <= Ok) {
        processed_includes.insert(path);
        
        while (Ok == f.ReadLine(buf, buflen)) {
            ++lineno;
            if (strncmp(buf, include_directive, include_directive_len) == 0) {
                // Process include directives
                char *eos = strchr(buf+include_directive_len, '\"');
                if (eos != NULL) {
                    *eos = 0;
                    std::string includepath = dirname + "/" + std::string(buf+include_directive_len);
                    if (processed_includes.count(includepath) == 0) {
                        // Set up line numbers for include file
                        lines.push_back("#line 0\n");
                        
                        VSFileSystem::VSError ierr = getProgramSource(includepath, lines, processed_includes, buf, buflen);
                        if (ierr > Ok) {
                            f.Close();
                            VSFileSystem::vs_fprintf(stderr, "ERROR: included from %s\n", path.c_str());
                            return ierr;
                        } else {
                            // Append a blank line to avoid issues and restore line numbers
                            lines.push_back("\n");
                            snprintf(buf, buflen, "#line %lu\n", lineno);
                            lines.push_back(buf);
                        }
                    } else {
                        // Insert blank line to keep line numbers consistent
                        lines.push_back("\n");
                    }
                } else {
                    VSFileSystem::vs_fprintf(stderr, "WARNING: broken include directive at file %s, line %d - skipping\n",
                        path.c_str(), lineno);
                }
            } else {
                // Append a line to the list
                lines.push_back(buf);
            }
        }
        
        f.Close();
    } else {
        VSFileSystem::vs_fprintf(stderr, "ERROR: at %s\n", path.c_str());
    }
    return err;
}
void Screenshot( const KBData&, KBSTATE state )
{
    if (state == PRESS) {
        GLint xywh[4] = {0, 0, 0, 0};
        xywh[2] = g_game.x_resolution;
        xywh[3] = g_game.y_resolution;
        glGetIntegerv( GL_VIEWPORT, xywh );
        unsigned char *tmp = (unsigned char*) malloc( xywh[2]*xywh[3]*4*sizeof (unsigned char) );
        //memset(tmp,0x7f,xywh[2]*xywh[3]*4*sizeof(char));
        glPixelStorei( GL_PACK_ALIGNMENT, 1 );
        glPixelStorei( GL_PACK_ROW_LENGTH, xywh[2] );
        glFinish();
        glReadPixels( 0, 0, xywh[2], xywh[3], GL_RGB, GL_UNSIGNED_BYTE, tmp );
        glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
        ::VSImage image;
        VSFileSystem::VSFile f;
        static int  count    = 0;
        std::string filename = "Screenshot"+XMLSupport::tostring( count )+".png";
        for (;;) {
            if (f.OpenReadOnly( filename, TextureFile ) <= VSFileSystem::Ok) {
                f.Close();
                filename = "Screenshot"+XMLSupport::tostring( ++count )+".png";
            } else {break; }}
        char *tmpchar = strdup( filename.c_str() );
        image.WriteImage( tmpchar, tmp, PngImage, xywh[2], xywh[3], false, 8, TextureFile, true );
        free( tmpchar );
    }
}
bool VSFileXMLSerializer::importXML( const std::string &path, VSFileSystem::VSFileType fileType )
{
    VSFileSystem::VSFile file;
    if (file.OpenReadOnly( path, fileType ) > VSFileSystem::Ok) 
        throw Audio::FileOpenException( string("Cannot open \"" )+path+"\"" );
    char   buffer[4096];
    size_t rode;
    while ( ( rode = file.Read( buffer, 4096 ) ) )
        parse( buffer, rode );
    file.Close();
    return true;
}