+ if(gpd->free_buf)
+ {
+ free(gpd->buffer);
+ free(gpd);
+ }
+ tmpfree();
+}
+
+static const char *print_array(const char *fmt, const void *data, unsigned elem_size, unsigned count)
+{
+ const char *cptr;
+ char type = 0;
+ char *buffer;
+ unsigned buf_size;
+ char *ptr;
+ unsigned i;
+
+ if(!data)
+ return "NULL";
+
+ for(cptr=fmt; (type<2 && *cptr); ++cptr)
+ {
+ if(*cptr=='%')
+ type = 1;
+ else if(type==1 && isalpha(*cptr))
+ type = *cptr;
+ }
+
+ count /= elem_size;
+ buf_size = count*20;
+ if(type=='s')
+ buf_size *= 50;
+ buffer = tmpalloc(buf_size);
+ ptr = buffer;
+ *ptr++ = '{';
+ for(i=0; i<count; ++i)
+ {
+ long long element = 0;
+ unsigned len;
+
+ if(i>0)
+ {
+ *ptr++ = ',';
+ *ptr++ = ' ';
+ }
+ memcpy(&element, (const char *)data+i*elem_size, elem_size);
+ if(type>='e' && type<='g' && elem_size==sizeof(float))
+ *(double *)&element = *(float *)&element;
+ len = snprintf(ptr, buf_size, fmt, element);
+ ptr += len;
+ buf_size -= len;
+ }
+ *ptr++ = '}';
+ *ptr = 0;
+
+ return buffer;
+}
+
+static const char *print_array_described(const char *(*describe)(GLenum, const char *), const char *categ, const void *data, unsigned elem_size, unsigned count)
+{
+ char *buffer;
+ unsigned buf_size;
+ char *ptr;
+ unsigned i;
+
+ if(!data)
+ return NULL;
+
+ count /= elem_size;
+ buf_size = count*50;
+ buffer = tmpalloc(buf_size);
+ ptr = buffer;
+ *ptr++ = '{';
+ for(i=0; i<count; ++i)
+ {
+ int element = 0;
+ unsigned len;
+
+ if(i>0)
+ {
+ *ptr++ = ',';
+ *ptr++ = ' ';
+ }
+ memcpy(&element, (const char *)data+i*elem_size, elem_size);
+ len = snprintf(ptr, buf_size, "%s", describe(element, categ));
+ ptr += len;
+ buf_size -= len;
+ }
+ *ptr++ = '}';
+ *ptr = 0;
+
+ return buffer;
+}
+
+static const char *print_parameter(int pname, int param)
+{
+ char *buffer;
+
+ // XXX Need to move the param names to flavor
+ switch(pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ return describe_enum(param, "");
+ }
+
+ buffer = tmpalloc(11);
+ snprintf(buffer, 11, "%i", param);
+ return buffer;
+}
+
+static const char *print_internal_format(int fmt)
+{
+ char *buffer;
+
+ if(fmt>4)
+ return describe_enum(fmt, "PixelFormat");
+
+ buffer = tmpalloc(2);
+ snprintf(buffer, 2, "%i", fmt);
+ return buffer;
+}
+
+static const char *print_data(const void *data, unsigned size)
+{
+ if(!data)
+ return "NULL";
+ else if((unsigned long)data<0x100000)
+ {
+ char *buffer = tmpalloc(20);
+ snprintf(buffer, 20, "%p", data);
+ return buffer;
+ }
+ else if(!size)
+ return "/* data */";
+ else
+ {
+ char *buffer = tmpalloc(50);
+ snprintf(buffer, 50, "/* data: %d bytes */", size);
+ return buffer;
+ }