]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Add support for loading XML from QuakeC
authorMattia Basaglia <mattia.basaglia@gmail.com>
Wed, 19 Nov 2014 18:01:51 +0000 (19:01 +0100)
committerMattia Basaglia <mattia.basaglia@gmail.com>
Wed, 19 Nov 2014 18:01:51 +0000 (19:01 +0100)
(Requires libxml)

makefile
makefile.inc
progsvm.h
prvm_cmds.c
svvm_cmds.c
xml.c [new file with mode: 0644]
xml.h [new file with mode: 0644]

index bbd0a76d6ba04eabf5d13d1f4b38f0173805fe57..838919363fbb0277eb8150aa0a62cffdb4c3d6d4 100644 (file)
--- a/makefile
+++ b/makefile
@@ -334,6 +334,9 @@ ifeq ($(DP_LINK_CRYPTO_RIJNDAEL), dlopen)
        CFLAGS_CRYPTO_RIJNDAEL=
 endif
 
+LIB_XML=$(shell xml2-config --libs)
+CFLAGS_LIBXML=$(shell xml2-config --cflags)
+
 ##### Sound configuration #####
 
 ifndef DP_SOUND_API
index c7e98d22ab8a1d60112496e8cf9c31067972c9a3..5140e9a4521e69852fdca52749e8259424c31e00 100644 (file)
@@ -158,6 +158,7 @@ OBJ_COMMON= \
        view.o \
        wad.o \
        world.o \
+       xml.o \
        zone.o
 
 OBJ_MENU= \
@@ -172,7 +173,7 @@ OBJ_SDL= builddate.c sys_sdl.o vid_sdl.o thread_sdl.o $(OBJ_MENU) $(OBJ_SND_COMM
 
 
 # Compilation
-CFLAGS_COMMON=$(CFLAGS_MAKEDEP) $(CFLAGS_PRELOAD) $(CFLAGS_FS) $(CFLAGS_WARNINGS) $(CFLAGS_LIBZ) $(CFLAGS_LIBJPEG) $(CFLAGS_D3D) -D_FILE_OFFSET_BITS=64 -D__KERNEL_STRICT_NAMES -I../../../
+CFLAGS_COMMON=$(CFLAGS_MAKEDEP) $(CFLAGS_PRELOAD) $(CFLAGS_FS) $(CFLAGS_WARNINGS) $(CFLAGS_LIBZ) $(CFLAGS_LIBJPEG) $(CFLAGS_D3D) -D_FILE_OFFSET_BITS=64 -D__KERNEL_STRICT_NAMES -I../../../ $(CFLAGS_LIBXML)
 CFLAGS_CLIENT=-DCONFIG_MENU -DCONFIG_CD $(CFLAGS_VIDEO_CAPTURE)
 CFLAGS_SERVER=
 CFLAGS_DEBUG=-ggdb
@@ -205,7 +206,7 @@ LDFLAGS_RELEASE=$(OPTIM_RELEASE) -DSVNREVISION=`{ test -d .svn && svnversion; }
 
 OBJ_GLX= builddate.c sys_linux.o vid_glx.o thread_pthread.o keysym2ucs.o $(OBJ_MENU) $(OBJ_SOUND) $(OBJ_CD) $(OBJ_VIDEO_CAPTURE) $(OBJ_COMMON)
 
-LDFLAGS_UNIXCOMMON=-lm $(LIB_ODE) $(LIB_Z) $(LIB_JPEG) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL)
+LDFLAGS_UNIXCOMMON=-lm $(LIB_ODE) $(LIB_Z) $(LIB_JPEG) $(LIB_CRYPTO) $(LIB_CRYPTO_RIJNDAEL) $(LIB_XML)
 LDFLAGS_UNIXCL=-L$(UNIX_X11LIBPATH) -lX11 -lXpm -lXext -lXxf86vm -pthread $(LIB_SOUND)
 LDFLAGS_UNIXCL_PRELOAD=-lz -ljpeg -lpng -logg -ltheora -lvorbis -lvorbisenc -lvorbisfile -lcurl
 LDFLAGS_UNIXSV_PRELOAD=-lz -ljpeg -lpng -lcurl
index 02cb4beadab9ba924ebba202b7a7c58984ac7cc5..36a84ff96902ebdce740364a06f0ba9724dbe1bf 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -630,6 +630,7 @@ typedef struct prvm_prog_s
        fssearch_t                      *opensearches[PRVM_MAX_OPENSEARCHES];
        const char *         opensearches_origin[PRVM_MAX_OPENSEARCHES];
        skeleton_t                      *skeletons[MAX_EDICTS];
+       void*                            open_xml_files[PRVM_MAX_OPENFILES];
 
        // buffer for storing all tempstrings created during one invocation of ExecuteProgram
        sizebuf_t                       tempstringsbuf;
index 187930b23835891bd0f4d881c252251d46b4966f..14dcf0491a568b8fe0a7c0da39dfa774e066bdef 100644 (file)
@@ -1760,7 +1760,10 @@ void VM_Files_Init(prvm_prog_t *prog)
 {
        int i;
        for (i = 0;i < PRVM_MAX_OPENFILES;i++)
+       {
                prog->openfiles[i] = NULL;
+               prog->open_xml_files[i] = NULL;
+       }
 }
 
 void VM_Files_CloseAll(prvm_prog_t *prog)
@@ -1771,6 +1774,7 @@ void VM_Files_CloseAll(prvm_prog_t *prog)
                if (prog->openfiles[i])
                        FS_Close(prog->openfiles[i]);
                prog->openfiles[i] = NULL;
+               XML_Close(prog,i);
        }
 }
 
index ff55c4fde46479e66de9f4ae38559fc6b2d974d5..16d91e9cf2484beeaf8980cf1b8374d2527f7e6a 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "prvm_cmds.h"
 #include "jpeg.h"
+#include "xml.h"
 
 //============================================================================
 // Server
@@ -3308,17 +3309,17 @@ NULL,                                                   // #124
 NULL,                                                  // #125
 NULL,                                                  // #126
 NULL,                                                  // #127
-NULL,                                                  // #128
-NULL,                                                  // #129
-NULL,                                                  // #130
-NULL,                                                  // #131
-NULL,                                                  // #132
-NULL,                                                  // #133
-NULL,                                                  // #134
-NULL,                                                  // #135
-NULL,                                                  // #136
-NULL,                                                  // #137
-NULL,                                                  // #138
+VM_xml_open,                                   // #128
+VM_xml_close,                                  // #129
+VM_xml_tree_name,                              // #130
+VM_xml_tree_text,                              // #131
+VM_xml_tree_leaf,                              // #132
+VM_xml_tree_child,                             // #133
+VM_xml_tree_parent,                            // #134
+VM_xml_tree_has_sibling,               // #135
+VM_xml_tree_next,                              // #136
+VM_xml_tree_type,                              // #137
+VM_xml_tree_root,                              // #138
 NULL,                                                  // #139
 NULL,                                                  // #140
 NULL,                                                  // #141
diff --git a/xml.c b/xml.c
new file mode 100644 (file)
index 0000000..2efd692
--- /dev/null
+++ b/xml.c
@@ -0,0 +1,256 @@
+#include "xml.h" 
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+typedef struct
+{
+       xmlDocPtr  doc;
+       xmlNodePtr node;
+       xmlAttrPtr attribute;
+} qxml_t;
+
+typedef qxml_t* qxml_p;
+
+static qxml_p VM_Xml_Data(prvm_prog_t *prog, int index)
+{
+       if (index < 0 || index >= PRVM_MAX_OPENFILES)
+       {
+               Con_Printf("VM_Xml_Data: invalid file handle %i used in %s\n", index, prog->name);
+               return NULL;
+       }
+       if (prog->open_xml_files[index] == NULL)
+       {
+               Con_Printf("VM_Xml_Data: no such file handle %i (or file has been closed) in %s\n", index, prog->name);
+               return NULL;
+       }
+       return (qxml_p)prog->open_xml_files[index];
+}
+
+void XML_Close(prvm_prog_t *prog, int index)
+{
+       if ( prog->open_xml_files[index] != NULL )
+       {
+               qxml_p xml = (qxml_p)prog->open_xml_files[index];
+               xmlFreeDoc(xml->doc);
+               free(xml);
+               prog->open_xml_files[index] = NULL;
+       }
+}
+
+void VM_xml_open(prvm_prog_t *prog)
+{
+       const char* filename;
+       
+       char* data;
+       size_t datasize;
+       qfile_t* filepointer;
+       char vabuf[1024];
+       
+       xmlDocPtr doc;
+       int docid;
+       qxml_p xml;
+       
+       VM_SAFEPARMCOUNT(1,VM_xmlopen);
+       filename = PRVM_G_STRING(OFS_PARM0);
+       
+       
+       for (docid = 0; docid < PRVM_MAX_OPENFILES; docid++)
+               if (prog->open_xml_files[docid] == NULL)
+                       break;
+       if (docid >= PRVM_MAX_OPENFILES)
+       {
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
+               VM_Warning(prog, "VM_xmlopen: %s ran out of file handles (%i)\n", prog->name, PRVM_MAX_OPENFILES);
+               return;
+       }
+       
+       filepointer = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false);
+       if (filepointer == NULL)
+               filepointer = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false);
+       
+       if ( filepointer == NULL )
+       {
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
+               VM_Warning(prog, "VM_xmlopen: Failed to open: %s\n", filename);
+               return;
+       }
+       
+       datasize = FS_FileSize(filepointer);
+       data = malloc(datasize);
+       FS_Read(filepointer,data,datasize);
+       FS_Close(filepointer);
+
+       doc = xmlParseMemory(data,datasize);
+       free(data);
+       
+       if (doc == NULL) 
+       {
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
+               VM_Warning(prog, "VM_xmlopen: Failed to load XML: %s\n", filename);
+               return;
+       }
+       
+       xml = malloc(sizeof(qxml_t));
+       xml->doc = doc;
+       xml->node = xmlDocGetRootElement(doc);
+       xml->attribute = NULL;
+       prog->open_xml_files[docid] = xml;
+       
+       PRVM_G_FLOAT(OFS_RETURN) = docid+1; // ensure non-zero file id in QuakeC
+}
+
+void VM_xml_close(prvm_prog_t *prog)
+{
+       int fileindex;
+       VM_SAFEPARMCOUNT(1,VM_xmlclose);
+       fileindex = PRVM_G_FLOAT(OFS_PARM0);
+       XML_Close(prog,fileindex-1);
+}
+
+// TODO find out if errorreturn is really needed to return 0...
+#define VM_XML_CHECK_RETURN(funcname, errorreturn) \
+       VM_SAFEPARMCOUNT(1,#funcname); \
+       xml = VM_Xml_Data(prog,PRVM_G_FLOAT(OFS_PARM0)-1); \
+       if ( !xml ) {\
+               errorreturn; \
+               return; \
+       }\
+       if ( !xml->node ) { \
+               VM_Warning(prog, #funcname": null node in %s\n",prog->name); \
+               errorreturn; \
+               return; \
+       } \
+       Con_Printf(#funcname":\n\tnode: %s\n\ttype: %d\n\tattr: %s\n\tnext: %s\n\tprev: %s\n\tprnt: %s\n\tchld: %s\n",\
+               xml->node->name, \
+               xml->node->type, \
+               xml->attribute ? (char*)xml->attribute->name : "NULL", \
+               xml->node->next ? (char*)xml->node->next->name : "NULL", \
+               xml->node->prev ? (char*)xml->node->prev->name : "NULL", \
+               xml->node->parent ? (char*)xml->node->parent->name : "NULL", \
+               xml->node->children ? (char*)xml->node->children->name : "NULL" \
+               );
+#define VM_XML_CHECK(funcname) VM_XML_CHECK_RETURN(funcname,)
+
+void VM_xml_tree_name(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       const xmlChar* xs;
+       char s[VM_STRINGTEMP_LENGTH] = { 0 };
+       VM_XML_CHECK(VM_xml_tree_name);
+       if ( xml->attribute )
+               xs = xml->attribute->name;
+       else
+               xs = xml->node->name;
+       memcpy(s,xs,xmlStrlen(xs));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
+}
+
+void VM_xml_tree_text(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       xmlChar* xs;
+       char s[VM_STRINGTEMP_LENGTH] = { 0 };
+       VM_XML_CHECK(VM_xml_tree_text);
+       
+       if ( xml->attribute )
+       {
+               xs = xmlGetProp(xml->node,xml->attribute->name);
+               memcpy(s,xs,xmlStrlen(xs));
+               xmlFree(xs);
+       }
+       else if ( xml->node->type == XML_ELEMENT_NODE )
+       {
+               xs = xmlNodeListGetString(xml->doc,xml->node->children,1);
+               memcpy(s,xs,xmlStrlen(xs));
+               xmlFree(xs);
+       }
+       else
+               memcpy(s,xml->node->content,xmlStrlen(xml->node->content));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
+}
+
+void VM_xml_tree_leaf(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_XML_CHECK_RETURN(VM_xml_tree_leaf, PRVM_G_FLOAT(OFS_RETURN) = 0);
+       if ( xml->attribute )
+               PRVM_G_FLOAT(OFS_RETURN) = 1;
+       else
+               PRVM_G_FLOAT(OFS_RETURN) = !xml->node->children;
+}
+
+void VM_xml_tree_child(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_XML_CHECK(VM_xml_tree_child);
+       if ( xml->attribute )
+               VM_Warning(prog, "VM_xml_tree_child: trying to get the child of attribute \"%s\"!\n",
+                                  xml->attribute->name);
+       else if ( xml->node->children )
+               xml->node = xml->node->children;
+       else
+               VM_Warning(prog, "VM_xml_tree_child: trying to get the child of leaf element \"%s\"!\n",
+                                  xml->node->name);    
+}
+
+void VM_xml_tree_parent(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_XML_CHECK(VM_xml_tree_parent);
+       if ( xml->attribute )
+               xml->attribute = NULL;
+       else if ( xml->node->parent )
+               xml->node = xml->node->parent;
+       else
+               VM_Warning(prog, "VM_xml_tree_parent: trying to get the parent of root element \"%s\"!\n",
+                                  xml->node->name);
+}
+
+void VM_xml_tree_has_sibling(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_XML_CHECK_RETURN(VM_xml_tree_has_sibling, PRVM_G_FLOAT(OFS_RETURN) = 0);
+       if ( xml->attribute )
+               PRVM_G_FLOAT(OFS_RETURN) = !!xml->attribute->next;
+       else
+               PRVM_G_FLOAT(OFS_RETURN) = !!xml->node->next;
+}
+
+void VM_xml_tree_next(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_XML_CHECK(VM_xml_tree_next);
+       if ( xml->attribute )
+       {
+               if ( xml->attribute->next )
+                       xml->attribute = xml->attribute->next;
+               else
+                       VM_Warning(prog,"VM_xml_tree_next: trying to get next sibling of last attribute \"%s\"!\n",
+                                  xml->attribute->name);
+       }
+       else if ( xml->node->next )
+               xml->node = xml->node->next;
+       else
+               VM_Warning(prog,"VM_xml_tree_next: trying to get next sibling of last element \"%s\"!\n",
+                               xml->node->name);
+}
+
+void VM_xml_tree_type(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_XML_CHECK_RETURN(VM_xml_tree_type, PRVM_G_FLOAT(OFS_RETURN) = 0);
+       if ( xml->attribute )
+               PRVM_G_FLOAT(OFS_RETURN) = XML_ATTRIBUTE_NODE;
+       else
+               PRVM_G_FLOAT(OFS_RETURN) = xml->node->type;
+}
+
+void VM_xml_tree_root(prvm_prog_t *prog)
+{
+       qxml_p xml;
+       VM_SAFEPARMCOUNT(1,VM_xml_tree_root);
+       xml = VM_Xml_Data(prog,PRVM_G_FLOAT(OFS_PARM0)-1); 
+       if ( !xml )
+               return;
+       xml->node = xmlDocGetRootElement(xml->doc);
+}
\ No newline at end of file
diff --git a/xml.h b/xml.h
new file mode 100644 (file)
index 0000000..e0155cd
--- /dev/null
+++ b/xml.h
@@ -0,0 +1,20 @@
+#ifndef XML_H
+#define XML_H
+
+#include "prvm_cmds.h"
+
+void VM_xml_open(prvm_prog_t *prog);
+void VM_xml_close(prvm_prog_t *prog);
+void VM_xml_tree_name(prvm_prog_t *prog);
+void VM_xml_tree_text(prvm_prog_t *prog);
+void VM_xml_tree_leaf(prvm_prog_t *prog);
+void VM_xml_tree_child(prvm_prog_t *prog);
+void VM_xml_tree_parent(prvm_prog_t *prog);
+void VM_xml_tree_has_sibling(prvm_prog_t *prog);
+void VM_xml_tree_next(prvm_prog_t *prog);
+void VM_xml_tree_type(prvm_prog_t *prog);
+void VM_xml_tree_root(prvm_prog_t *prog);
+
+void XML_Close(prvm_prog_t *prog, int index);
+
+#endif