]> git.mxchange.org Git - flightgear.git/commitdiff
* Introduce a root-node that can hold extra information which is necessary
authorehofman <ehofman>
Sat, 18 Apr 2009 21:25:23 +0000 (21:25 +0000)
committerTim Moore <timoore@redhat.com>
Fri, 1 May 2009 22:44:20 +0000 (00:44 +0200)
    for thread safety under windows
  * Add xmlErrorGetString, xmlErrorGetLineNo for syntax error detetction
  * Add xmlErrGetNo for detection of, and clearing the last error

utils/xmlgrep/ChangeLog
utils/xmlgrep/README
utils/xmlgrep/xml.c
utils/xmlgrep/xml.h
utils/xmlgrep/xmlgrep.c

index f4dd02d6a62eb76013a9022fd2aad8dff8d21177..0b24f5ee5dc99b6fb04f11079d1f86fcfaa3f88a 100644 (file)
@@ -1,3 +1,10 @@
+18-04-2009
+  * Make the code compiler correctly under windows
+  * Introduce a root-node that can hold extra information which is necessary
+    for thread safety under windows
+  * Add xmlErrorGetString, xmlErrorGetLineNo for syntax error detetction
+  * Add xmlErrGetNo for detection of, and clearing the last error
+
 16-04-2008
   * Rename xmlGetNode functions to xmlNodeGet for better consistancy
   * likewise for xmlCopyNode en xmlCompareNode
index 74cb6afd9b0b60271aac478f9a0eb2a3fd79a0aa..f2027636a5cac126c1d1a807294703b44a4beb52 100644 (file)
@@ -127,3 +127,15 @@ double xmlAttributeGetDouble(const void *, const char *);
 char *xmlAttributeGetString(const void *, const char *);
 size_t xmlAttributeCopyString(const void *, const char *, const char *, size_t);
 int xmlAttributeCompareString(const void *, const char *, const char *);
+
+#
+# Error detection and reporting functions
+#
+# char *err_str = xmlErrorGetString(id);
+# size_t err_lineno = xmlErrorGetLineNo(id);
+# int err = xmlErrorGetNo(id); /* clear last error */
+# if (err) printf("Error #%i at line #%u: '%s'\n", err, err_lineno, err_str);
+#
+int xmlErrorGetNo(const void *);
+size_t xmlErrorGetLineNo(const void *);
+const char *xmlErrorGetString(const void *);
index 760952e8a5552a4640c408f1d609babaff82a8c6..7c3386d062401ebf664a8f08e04d8505d21706ec 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (c) 2007, 2008 by Adalin B.V.
- * Copyright (c) 2007, 2008 by Erik Hofman
+/* Copyright (c) 2007-2009 by Adalin B.V.
+ * Copyright (c) 2007-2009 by Erik Hofman
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  */
 
 #ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <io.h>
 
 typedef struct
 {
-   HANDLE m;
-   void *p;
+    HANDLE m;
+    void *p;
 } SIMPLE_UNMMAP;
 
-static SIMPLE_UNMMAP un;
-
-/*
- * map 'filename' and return a pointer to it.
- */
-static void *simple_mmap(int, size_t, SIMPLE_UNMMAP *);
-static void simple_unmmap(SIMPLE_UNMMAP *);
-
-# define mmap(a,b,c,d,e,f)     simple_mmap((e), (b), &un)
-# define munmap(a,b)           simple_unmmap(&un)
-
-# include <io.h>
-# include <stdlib.h>
-
 #else  /* !WIN32 */
 # include <sys/mman.h>
 # include <unistd.h>
 #endif
 
-# include <fcntl.h>
+#ifndef NDEBUG
+# include <stdio.h>
+#endif
+#include <fcntl.h>
+#include <stdlib.h>    /* free, malloc */
+#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <assert.h>
 #include <ctype.h>
-#include <string.h>
 #ifndef _MSC_VER
-# include <strings.h>  /* strncasecmp */
+# include <strings.h>  /* strncasecmp */
 #else
 # define strncasecmp strnicmp
 #endif
-#ifndef NDEBUG
-#include <stdio.h>
+
+enum
+{
+    XML_NO_ERROR = 0,
+    XML_OUT_OF_MEMORY,
+    XML_FILE_NOT_FOUND,
+    XML_TRUNCATE_RESULT,
+    XML_ELEMENT_NO_OPENING_TAG,
+    XML_ELEMENT_NO_CLOSING_TAG,
+    XML_ATTRIB_NO_OPENING_QUOTE,
+    XML_ATTRIB_NO_CLOSING_QUOTE,
+    XML_MAX_ERROR
+};
+static const char *__xml_error_str[XML_MAX_ERROR];
+
+#ifndef XML_NONVALIDATING
+struct _xml_error
+{
+    char *pos;
+    int errno;
+};
+
+static void __xmlErrorSet(const void *, const char *, unsigned int);
+# define xmlErrorSet(a, b, c)  __xmlErrorSet(a, b, c)
+#else /* !XML_NONVALIDATING */
+# define xmlErrorSet(a, b, c)
 #endif
 
+/*
+ * It is required for both the rood node and the normal xml nodes to both
+ * have 'char *name' defined as the first entry. The code tests whether
+ * name == 0 to detect the root node.
+ */
+struct _root_id
+{
+    char *name;
+    char *start;
+    size_t len;
+    int fd;
+#ifndef XML_NONVALIDATING
+    struct _xml_error *info;
+#endif
+# ifdef WIN32
+    SIMPLE_UNMMAP un;
+# endif
+};
 
 struct _xml_id
 {
-    size_t len;
-    char *start;
     char *name;
-    union {
-       size_t name_len;
-       int fd;
-    } node;
+    char *start;
+    size_t len;
+    size_t name_len;
+#ifndef XML_NONVALIDATING
+    struct _root_id *root;
+#endif
 };
 
 static char *__xmlNodeCopy(const char *, size_t, const char *);
 static char *__xmlNodeGetPath(const char *, size_t *, char **, size_t *);
 static char *__xmlNodeGet(const char *, size_t *, char **, size_t *, size_t *);
 static char *__xmlCommentSkip(const char *, size_t);
-static char *__xmlInfoSkip(const char *, size_t);
+static char *__xmlInfoProcess(const char *, size_t);
 
 static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
 
-#define PRINT(a, b, c) { \
+#ifdef WIN32
+/*
+ * map 'filename' and return a pointer to it.
+ */
+static void *simple_mmap(int, size_t, SIMPLE_UNMMAP *);
+static void simple_unmmap(SIMPLE_UNMMAP *);
+
+# define mmap(a,b,c,d,e,f)       simple_mmap((e), (b), &rid->un)
+# define munmap(a,b)             simple_unmmap(&rid->un)
+#endif
+
+#ifndef NDEBUG
+# define PRINT(a, b, c) { \
    if (a) { \
       size_t q, len = c; \
       if (b < c) len = b; \
@@ -100,111 +145,126 @@ static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
       } else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
    } else printf("NULL pointer at line %i\n", __LINE__); \
 }
+#endif
 
 void *
 xmlOpen(const char *filename)
 {
-    struct _xml_id *id = 0;
+    struct _root_id *rid = 0;
 
     if (filename)
     {
         int fd = open(filename, O_RDONLY);
         if (fd > 0)
         {
-            id = malloc(sizeof(struct _xml_id));
-            if (id)
+            rid = malloc(sizeof(struct _root_id));
+            if (rid)
             {
                 struct stat statbuf;
 
                 fstat(fd, &statbuf);
 
-                id->node.fd = fd;
-                id->len = statbuf.st_size;
-                id->start = mmap(0, id->len, PROT_READ, MAP_PRIVATE, fd, 0L);
-                id->name = 0;
+                rid->fd = fd;
+                rid->len = statbuf.st_size;
+                rid->start = mmap(0, rid->len, PROT_READ, MAP_PRIVATE, fd, 0L);
+                rid->name = 0;
+#ifndef XML_NONVALIDATING
+                rid->info = 0;
+                __xmlErrorSet(rid, 0, 0);
+#endif
             }
         }
     }
 
-    return (void *)id;
+    return (void *)rid;
 }
 
 void
 xmlClose(void *id)
 {
-    if (id)
-    {
-        struct _xml_id *xid = (struct _xml_id *)id;
-        assert(xid->name == 0);
+     struct _root_id *rid = (struct _root_id *)id;
 
-        munmap(xid->start, xid->len);
-        close(xid->node.fd);
-        free(id);
-        id = 0;
-    }
+     assert(rid != 0);
+     assert(rid->name == 0);
+
+     munmap(rid->start, rid->len);
+     close(rid->fd);
+     free(id);
+     id = 0;
 }
 
 void *
 xmlNodeGet(const void *id, const char *path)
 {
-   struct _xml_id *xsid = 0;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    struct _xml_id *xsid = 0;
+    size_t len, slen;
+    char *ptr, *node;
 
-   if (id && path)
-   {
-      struct _xml_id *xid = (struct _xml_id *)id;
-      size_t len, slen;
-      char *ptr, *node;
-
-      node = (char *)path;
-      len = xid->len;
-      slen = strlen(path);
-      ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
-      if (ptr)
-      {
-         xsid = malloc(sizeof(struct _xml_id));
-         if (xsid)
-         {
+    assert(id != 0);
+    assert(path != 0);
+
+    node = (char *)path;
+    len = xid->len;
+    slen = strlen(path);
+    ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+    if (ptr)
+    {
+        xsid = malloc(sizeof(struct _xml_id));
+        if (xsid)
+        {
              xsid->len = len;
              xsid->start = ptr;
-             xsid->node.name_len = slen;
+             xsid->name_len = slen;
              xsid->name = node;
-         }
-      }
-   }
+#ifndef XML_NONVALIDATING
+             if (xid->name)
+                xsid->root = xid->root;
+             else
+                xsid->root = (struct _root_id *)xid;
+#endif
+        }
+        else
+            xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
+    }
 
-   return (void *)xsid;
+    return (void *)xsid;
 }
 
 void *
 xmlNodeCopy(const void *id, const char *path)
 {
+    struct _xml_id *xid = (struct _xml_id *)id;
     struct _xml_id *xsid = 0;
-
-    if (id && path)
+    char *ptr, *node, *p;
+    size_t slen, len;
+
+    node = (char *)path;
+    len = xid->len;
+    slen = strlen(path);
+    ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+    if (ptr)
     {
-        struct _xml_id *xid = (struct _xml_id *)id;
-        char *ptr, *node, *p;
-        size_t slen, len;
-
-        node = (char *)path;
-        len = xid->len;
-        slen = strlen(path);
-        ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
-        if (ptr)
+        xsid = malloc(sizeof(struct _xml_id) + len);
+        if (xsid)
         {
-            xsid = malloc(sizeof(struct _xml_id) + len);
-            if (xsid)
-            {
-                p = (char *)xsid + sizeof(struct _xml_id);
-
-                xsid->len = len;
-                xsid->start = p;
-                xsid->node.name_len = slen;
-                xsid->name = node;
+            p = (char *)xsid + sizeof(struct _xml_id);
+
+            xsid->len = len;
+            xsid->start = p;
+            xsid->name_len = slen;
+            xsid->name = node;
+#ifndef XML_NONVALIDATING
+            if (xid->name)
+                xsid->root = xid->root;
+            else
+                xsid->root = (struct _root_id *)xid;
+#endif
 
-                memcpy(xsid->start, ptr, len);
-           }
-       }
+            memcpy(xsid->start, ptr, len);
+        }
+        else
+            xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
    }
 
    return (void *)xsid;
@@ -217,30 +277,38 @@ xmlNodeGetName(const void *id)
     size_t len;
     char *ret;
 
-    len = xid->node.name_len;
+    assert(xid != 0);
+
+    len = xid->name_len;
     ret = malloc(len+1);
     if (ret)
     {
         memcpy(ret, xid->name, len);
         *(ret + len) = 0;
     }
+    else
+        xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
 
     return ret;
 }
 
 size_t
-xmlNodeCopyName(const void *id, char *buf, size_t len)
+xmlNodeCopyName(const void *id, char *buf, size_t buflen)
 {
     struct _xml_id *xid = (struct _xml_id *)id;
     size_t slen = 0;
  
-    if (buf)
+    assert(buf != 0);
+    assert(buflen > 0);
+
+    slen = buflen-1;
+    if (slen > xid->name_len)
     {
-        slen = len-1;
-        if (slen > xid->node.name_len) slen = xid->node.name_len;
-        memcpy(buf, xid->name, slen);
-        *(buf + slen) = 0;
+        slen = xid->name_len;
+        xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
     }
+    memcpy(buf, xid->name, slen);
+    *(buf + slen) = 0;
 
     return slen;
 }
@@ -251,7 +319,10 @@ xmlNodeGetNum(const void *id, const char *path)
     struct _xml_id *xid = (struct _xml_id *)id;
     size_t num = 0;
 
-    if (xid && xid->len && path)
+    assert(xid != 0);
+    assert(path != 0);
+
+    if (xid->len)
     {
         char *nodename, *pathname;
         size_t len, slen;
@@ -291,27 +362,27 @@ xmlNodeGetNum(const void *id, const char *path)
 void *
 xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
 {
+    struct _xml_id *xpid = (struct _xml_id *)pid;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    size_t len, slen;
+    char *ptr, *node;
     void *ret = 0;
 
-    if (pid && element)
-    {
-        struct _xml_id *xpid = (struct _xml_id *)pid;
-        struct _xml_id *xid = (struct _xml_id *)id;
-        size_t len, slen;
-        char *ptr, *node;
+    assert(xpid != 0);
+    assert(xid != 0);
+    assert(element != 0);
 
-        len = xpid->len;
-        slen = strlen(element);
-        node = (char *)element;
-        ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
-        if (ptr)
-        {
-             xid->len = len;
-             xid->start = ptr;
-             xid->name = node;
-             xid->node.name_len = slen;
-             ret = xid;
-        }
+    len = xpid->len;
+    slen = strlen(element);
+    node = (char *)element;
+    ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
+    if (ptr)
+    {
+         xid->len = len;
+         xid->start = ptr;
+         xid->name = node;
+         xid->name_len = slen;
+         ret = xid;
     }
 
     return ret;
@@ -323,7 +394,9 @@ xmlGetString(const void *id)
     struct _xml_id *xid = (struct _xml_id *)id;
     char *str = 0;
 
-    if (xid && xid->len)
+    assert(xid != 0);
+
+    if (xid->len)
     {
         char *ps, *pe, *pend;
         int nlen;
@@ -344,6 +417,8 @@ xmlGetString(const void *id)
                 memcpy(str, ps, nlen);
                 *(str+nlen) = 0;
             }
+            else
+                xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
         }
     }
 
@@ -355,8 +430,12 @@ xmlCopyString(const void *id, char *buffer, size_t buflen)
 {
     struct _xml_id *xid = (struct _xml_id *)id;
     size_t ret = 0;
+    assert(xid != 0);
+    assert(buffer != 0);
+    assert(buflen > 0);
 
-    if (xid && xid->len && buffer && buflen)
+    if (xid->len)
     {
         char *ps, *pe, *pend;
         size_t slen, nlen;
@@ -375,7 +454,11 @@ xmlCopyString(const void *id, char *buffer, size_t buflen)
 
         if (nlen)
         {
-            if (nlen >= buflen) nlen = buflen-1;
+            if (nlen >= buflen)
+            {
+                nlen = buflen-1;
+                xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
+            }
             memcpy(buffer, ps, nlen);
             *(buffer+nlen) = 0;
             ret = nlen;
@@ -391,7 +474,10 @@ xmlCompareString(const void *id, const char *s)
     struct _xml_id *xid = (struct _xml_id *)id;
     int ret = -1;
 
-    if (xid && xid->len && s && (strlen(s) > 0))
+    assert(xid != 0);
+    assert(s != 0);
+
+    if (xid->len && (strlen(s) > 0))
     {
         char *ps, *pe;
 
@@ -415,7 +501,10 @@ xmlNodeGetString(const void *id, const char *path)
     struct _xml_id *xid = (struct _xml_id *)id;
     char *str = 0;
 
-    if (xid && xid->len && path)
+    assert(xid != 0);
+    assert(path != 0);
+
+    if (xid->len)
     {
         str = __xmlNodeCopy(xid->start, xid->len, path);
         if (str)
@@ -447,7 +536,12 @@ xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
     struct _xml_id *xid = (struct _xml_id *)id;
     size_t ret = 0;
 
-    if (xid && xid->len && path && buffer && buflen)
+    assert(xid != 0);
+    assert(path != 0);
+    assert(buffer != 0);
+    assert(buflen > 0);
+
+    if (xid->len)
     {
         char *str, *node;
         size_t slen, nlen;
@@ -468,7 +562,11 @@ xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
             while ((pe>ps) && isspace(*pe)) pe--;
 
             nlen = (pe-ps)+1;
-            if (nlen >= buflen) nlen = buflen-1;
+            if (nlen >= buflen)
+            {
+                nlen = buflen-1;
+                xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
+            }
 
             memcpy(buffer, ps, nlen);
             *(buffer + nlen) = '\0';
@@ -485,7 +583,11 @@ xmlNodeCompareString(const void *id, const char *path, const char *s)
     struct _xml_id *xid = (struct _xml_id *)id;
     int ret = -1;
 
-    if (xid && xid->len && path && s && (strlen(s) > 0))
+    assert(xid != 0);
+    assert(path != 0);
+    assert(s != 0);
+
+    if (xid->len && (strlen(s) > 0))
     {
         char *node, *str, *ps, *pe;
         size_t len, slen;
@@ -517,7 +619,9 @@ xmlGetInt(const void *id)
     struct _xml_id *xid = (struct _xml_id *)id;
     long int li = 0;
 
-    if (xid && xid->len)
+    assert(xid != 0);
+
+    if (xid->len)
     {
         char *end = xid->start + xid->len;
         li = strtol(xid->start, &end, 10);
@@ -532,7 +636,10 @@ xmlNodeGetInt(const void *id, const char *path)
     struct _xml_id *xid = (struct _xml_id *)id;
     long int li = 0;
 
-    if (path && xid && xid->len)
+    assert(xid != 0);
+    assert(path != 0);
+
+    if (xid->len)
     {
         size_t len, slen;
         char *str, *node;
@@ -557,7 +664,9 @@ xmlGetDouble(const void *id)
     struct _xml_id *xid = (struct _xml_id *)id;
     double d = 0.0;
 
-    if (xid && xid->len)
+    assert(xid != 0);
+
+    if (xid->len)
     {
         char *end = xid->start + xid->len;
         d = strtod(xid->start, &end);
@@ -572,7 +681,10 @@ xmlNodeGetDouble(const void *id, const char *path)
     struct _xml_id *xid = (struct _xml_id *)id;
     double d = 0.0;
 
-    if (path && xid && xid->len)
+    assert(xid != 0);
+    assert(path != 0);
+
+    if (xid->len)
     {
         size_t len, slen;
         char *str, *node;
@@ -594,294 +706,506 @@ xmlNodeGetDouble(const void *id, const char *path)
 void *
 xmlMarkId(const void *id)
 {
-   struct _xml_id *xmid = 0;
+    struct _xml_id *xmid = 0;
 
-   if (id)
-   {
-      xmid = malloc(sizeof(struct _xml_id));
-      if (xmid)
-      {
-          memcpy(xmid, id, sizeof(struct _xml_id));
-      }
-   }
+    assert(id != 0);
+
+    xmid = malloc(sizeof(struct _xml_id));
+    if (xmid)
+    {
+        struct _root_id *xrid = (struct _root_id *)id;
+        if (xrid->name == 0)
+        {
+            xmid->name = "";
+            xmid->start = xrid->start;
+            xmid->len = xrid->len;
+            xmid->name_len = 0;
+#ifndef XML_NONVALIDATING
+            xmid->root = xrid;
+#endif
+        }
+        else
+        {
+            struct _xml_id *xid = (struct _xml_id *)id;
+
+            xmid->name = xid->name;
+            xmid->start = xid->start;
+            xmid->len = xid->len;
+            xmid->name_len = xid->name_len;
+#ifndef XML_NONVALIDATING
+            xmid->root = xid->root;
+#endif
+        }
+    }
+    else
+        xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
 
-   return (void *)xmid;
+    return (void *)xmid;
 }
 
 double
 xmlAttributeGetDouble(const void *id, const char *name)
 {
-   struct _xml_id *xid = (struct _xml_id *)id;
-   double ret = 0.0;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    double ret = 0.0;
 
-   if (xid && xid->start && xid->len && xid->node.name_len)
-   {
-       char *p, *end, *new = 0;
-
-       assert(xid->start > xid->name);
-
-       p = xid->name + xid->node.name_len;
-       end = xid->start-1;
-
-       while ((p<end) && isspace(*p)) p++;
-       while (p<end)
-       {
-          size_t elementlen = strlen(name);
-          size_t restlen = end-p;
-          char *element = (char *)name;
-
-          new = __xml_memncasecmp(p, &restlen, &element, &elementlen);
-          if (new)
-          {
-             restlen = end-p;
-             new = memchr(p, '=', restlen);
-             if (new)
-             {
-                new++;
-                if (*new == '"') new++;
-                restlen -= (new-p);
-                end = new+restlen;
-                ret = strtod(new, &end);
-             }
-             break;
-          }
+    assert(xid != 0);
+    assert(name != 0);
 
-          while ((p<end) && !isspace(*p)) p++;
-          if (p<end)
-             while ((p<end) && isspace(*p)) p++;
-       }
-   }
+    if (xid->len && xid->name_len)
+    {
+        char *ps, *pe;
+
+        assert(xid->start > xid->name);
+
+        ps = xid->name + xid->name_len + 1;
+        pe = xid->start - 1;
 
-   return ret;
+        while ((ps<pe) && isspace(*ps)) ps++;
+        while (ps<pe)
+        {
+            size_t slen = strlen(name);
+            size_t restlen = pe-ps;
+
+            if ((restlen > slen) && (strncasecmp(ps, name, slen) == 0))
+            {
+                ps += slen;
+                if ((ps<pe) && (*ps == '='))
+                {
+                    char *start;
+
+                    ps++;
+                    if (*ps == '"' || *ps == '\'') ps++;
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
+                        return 0;
+                    }
+
+                    start = ps;
+                    while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
+                    if (ps<pe)
+                        ret = strtod(start, &ps);
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
+                        return 0;
+                    }
+                }
+                break;
+            }
+
+            while ((ps<pe) && !isspace(*ps)) ps++;
+            if (ps<pe)
+                while ((ps<pe) && isspace(*ps)) ps++;
+        }
+    }
+
+    return ret;
 }
 
 long int
 xmlAttributeGetInt(const void *id, const char *name)
 {
-   struct _xml_id *xid = (struct _xml_id *)id;
-   long int ret = 0;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    long int ret = 0;
 
-   if (xid && xid->start && xid->len && xid->node.name_len)
-   {
-       char *p, *end, *new = 0;
-
-       assert(xid->start > xid->name);
-
-       p = xid->name + xid->node.name_len;
-       end = xid->start-1;
-
-       while ((p<end) && isspace(*p)) p++;
-       while (p<end)
-       {
-          size_t elementlen = strlen(name);
-          size_t restlen = end-p;
-          char *element = (char *)name;
-
-          new = __xml_memncasecmp(p, &restlen, &element, &elementlen);
-          if (new)
-          {
-             restlen = end-p;
-             new = memchr(p, '=', restlen);
-             if (new)
-             {
-                new++;
-                if (*new == '"') new++;
-                restlen -= (new-p);
-                end = new+restlen;
-                ret = strtol(new, &end, 10);
-             }
-             break;
-          }
+    assert(xid != 0);
+    assert(name != 0);
 
-          while ((p<end) && !isspace(*p)) p++;
-          if (p<end)
-             while ((p<end) && isspace(*p)) p++;
-       }
-   }
+    if (xid->len && xid->name_len)
+    {
+        char *ps, *pe;
+
+        assert(xid->start > xid->name);
+
+        ps = xid->name + xid->name_len + 1;
+        pe = xid->start - 1;
 
-   return ret;
+        while ((ps<pe) && isspace(*ps)) ps++;
+        while (ps<pe)
+        {
+            size_t slen = strlen(name);
+            size_t restlen = pe-ps;
+
+            if ((restlen > slen) && (strncasecmp(ps, name, slen) == 0))
+            {
+                ps += slen;
+                if ((ps<pe) && (*ps == '='))
+                {
+                    char *start;
+
+                    ps++;
+                    if (*ps == '"' || *ps == '\'') ps++;
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
+                        return 0;
+                    }
+
+                    start = ps;
+                    while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
+                    if (ps<pe)
+                        ret = strtol(start, &ps, 10);
+                    else
+                    {
+                       xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
+                       return 0;
+                   }
+               }
+               break;
+           }
+
+           while ((ps<pe) && !isspace(*ps)) ps++;
+           if (ps<pe)
+               while ((ps<pe) && isspace(*ps)) ps++;
+        }
+    }
+
+    return ret;
 }
 
 char *
 xmlAttributeGetString(const void *id, const char *name)
 {
-   struct _xml_id *xid = (struct _xml_id *)id;
-   char *ret = 0;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    char *ret = 0;
 
-   if (xid && xid->start && xid->len && xid->node.name_len)
-   {
-       char *p, *end, *new = 0;
-
-       assert(xid->start > xid->name);
-
-       p = xid->name + xid->node.name_len;
-       end = xid->start-1;
-
-       while ((p<end) && isspace(*p)) p++;
-       while (p<end)
-       {
-          size_t elementlen = strlen(name);
-          size_t restlen = end-p;
-          char *element = (char *)name;
-
-          new = __xml_memncasecmp(p, &restlen, &element, &elementlen);
-          if (new)
-          {
-             restlen = end-p;
-             new = memchr(p, '=', restlen);
-             if (new)
+    assert(xid != 0);
+    assert(name != 0);
+
+    if (xid->len && xid->name_len)
+    {
+        char *ps, *pe;
+
+        assert(xid->start > xid->name);
+
+        ps = xid->name + xid->name_len + 1;
+        pe = xid->start - 1;
+
+        while ((ps<pe) && isspace(*ps)) ps++;
+        while (ps<pe)
+        {
+             size_t slen = strlen(name);
+             size_t restlen = pe-ps;
+
+             if ((restlen > slen) && (strncasecmp(ps, name, slen) == 0))
              {
-                new++;
-                if (*new == '"') new++;
-                p = new;
-                while ((p<end) && (*p != '"') && (*p != ' ')) p++;
-                if (p<end)
-                {
-                   ret = calloc(1, p-new);
-                   memcpy(ret, new, (p-new));
-                }
+                 ps += slen;
+                 if ((ps<pe) && (*ps == '='))
+                 {
+                     char *start;
+
+                     ps++;
+                     if (*ps == '"' || *ps == '\'') ps++;
+                     else
+                     {
+                         xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
+                         return 0;
+                     }
+
+                     start = ps;
+                     while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
+                     if (ps<pe)
+                     {
+                         ret = malloc(ps-start);
+                         if (ret)
+                         {
+                             memcpy(ret, start, (ps-start));
+                             *(ret+(ps-start)) = '\0';
+                         }
+                         else
+                             xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
+                     }
+                     else
+                     {
+                         xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
+                        return 0;
+                     }
+                 }
+                 break;
              }
-             break;
-          }
 
-          while ((p<end) && !isspace(*p)) p++;
-          if (p<end)
-             while ((p<end) && isspace(*p)) p++;
-       }
-   }
+             while ((ps<pe) && !isspace(*ps)) ps++;
+             if (ps<pe)
+                 while ((ps<pe) && isspace(*ps)) ps++;
+        }
+    }
 
-   return ret;
+    return ret;
 }
 
 size_t
 xmlAttributeCopyString(const void *id, const char *name,
                                        char *buffer, size_t buflen)
 {
-   struct _xml_id *xid = (struct _xml_id *)id;
-   size_t ret = 0;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    size_t ret = 0;
 
-   if (xid && xid->start && xid->len && xid->node.name_len
-       && buffer && buflen)
-   {
-       char *ps, *pe;
+    assert(xid != 0);
+    assert(name != 0);
+    assert(buffer != 0);
+    assert(buflen > 0);
 
-       *buffer = '\0';
-       ps = xid->name + xid->node.name_len + 1;
-       pe = xid->start - 1;
+    if (xid->len && xid->name_len)
+    {
+        char *ps, *pe;
 
-       assert((int)(pe-ps) > 0);
+        assert(xid->start > xid->name);
 
-       while ((ps<pe) && isspace(*ps)) ps++;
-       while (ps<pe)
-       {
-          size_t slen = strlen(name);
-          size_t restlen = pe-ps;
+        *buffer = '\0';
+        ps = xid->name + xid->name_len + 1;
+        pe = xid->start - 1;
 
-          if ((restlen >= slen) && (strncasecmp(ps, name, slen) == 0))
-          {
-             char *new;
+        while ((ps<pe) && isspace(*ps)) ps++;
+        while (ps<pe)
+        {
+            size_t slen = strlen(name);
+            size_t restlen = pe-ps;
 
-             restlen = pe-ps;
-             new = memchr(ps, '=', restlen);
-             if (new)
-             {
-                new++;
-                if (*new == '"') new++;
-                ps = new;
-                while ((ps<pe) && (*ps != '"') && (*ps != ' ')) ps++;
-                if (ps<pe)
+            if ((restlen > slen) && (strncasecmp(ps, name, slen) == 0))
+            {
+                ps += slen;
+                if ((ps<pe) && (*ps == '='))
                 {
-                   restlen = ps-new;
-                   if (restlen >= buflen) restlen = buflen-1;
-                   memcpy(buffer, new, restlen);
-                   *(buffer+restlen) = 0;
-                   ret = restlen;
+                    char *start;
+
+                    ps++;
+                    if (*ps == '"' || *ps == '\'') ps++;
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
+                        return 0;
+                    }
+
+                    start = ps;
+                    while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
+                    if (ps<pe)
+                    {
+                        restlen = ps-start;
+                        if (restlen >= buflen)
+                        {
+                            restlen = buflen-1;
+                            xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
+                        }
+
+                        memcpy(buffer, start, restlen);
+                        *(buffer+restlen) = 0;
+                        ret = restlen;
+                    }
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
+                        return 0;
+                    }
                 }
-             }
-             break;
-          }
+                break;
+            }
 
-          while ((ps<pe) && !isspace(*ps)) ps++;
-          if (ps<pe)
-             while ((ps<pe) && isspace(*ps)) ps++;
-       }
-   }
+            while ((ps<pe) && !isspace(*ps)) ps++;
+            if (ps<pe)
+                while ((ps<pe) && isspace(*ps)) ps++;
+        }
+    }
 
-   return ret;
+    return ret;
 }
 
 int
 xmlAttributeCompareString(const void *id, const char *name, const char *s)
 {
-   struct _xml_id *xid = (struct _xml_id *)id;
-   int ret = -1;
-
-   if (xid && xid->start && xid->len && xid->node.name_len
-       && s && strlen(s))
-   {
-      char *ps, *pe;
+    struct _xml_id *xid = (struct _xml_id *)id;
+    int ret = -1;
+    assert(xid != 0);
+    assert(name != 0);
+    assert(s != 0);
 
-       ps = xid->name + xid->node.name_len + 1;
-       pe = xid->start - 1;
+    if (xid->len && xid->name_len && strlen(s))
+    {
+        char *ps, *pe;
 
-       assert((int)(pe-ps) > 0);
+        assert(xid->start > xid->name);
 
-       while ((ps<pe) && isspace(*ps)) ps++;
-       while (ps<pe)
-       {
-          size_t slen = strlen(name);
-          size_t restlen = pe-ps;
+        ps = xid->name + xid->name_len + 1;
+        pe = xid->start - 1;
 
-          if ((restlen >= slen) && (strncasecmp(ps, name, slen) == 0))
-          {
-             char *new;
+        while ((ps<pe) && isspace(*ps)) ps++;
+        while (ps<pe)
+        {
+            size_t slen = strlen(name);
+            size_t restlen = pe-ps;
 
-             restlen = pe-ps;
-             new = memchr(ps, '=', restlen);
-             if (new)
-             {
-                new++;
-                if (*new == '"') new++;
-                ps = new;
-                while ((ps<pe) && (*ps != '"') && (*ps != ' ')) ps++;
-                if (ps<pe)
+            if ((restlen > slen) && (strncasecmp(ps, name, slen) == 0))
+            {
+                ps += slen;
+                if ((ps<pe) && (*ps == '='))
                 {
-                   int alen = ps-new;
-                   ret = strncasecmp(new, s, alen);
+                    char *start;
+
+                    ps++;
+                    if (*ps == '"' || *ps == '\'') ps++;
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
+                        return 0;
+                    }
+
+                    start = ps;
+                    while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
+                    if (ps<pe)
+                        ret = strncasecmp(start, s, ps-start);
+                    else
+                    {
+                        xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
+                        return 0;
+                    }
                 }
-             }
-             break;
-          }
+                break;
+            }
 
-          while ((ps<pe) && !isspace(*ps)) ps++;
-          if (ps<pe)
-             while ((ps<pe) && isspace(*ps)) ps++;
-       }
-   }
+            while ((ps<pe) && !isspace(*ps)) ps++;
+            if (ps<pe)
+                while ((ps<pe) && isspace(*ps)) ps++;
+        }
+    }
 
-   return ret;
+    return ret;
 }
 
 
+#ifndef XML_NONVALIDATING
+int
+xmlErrorGetNo(const void *id)
+{
+    int ret = 0;
+
+    if (id)
+    {
+        struct _xml_id *xid = (struct _xml_id *)id;
+        struct _root_id *rid;
+
+        if (xid->name) rid = xid->root;
+        else rid = (struct _root_id *)xid;
+
+        assert(rid != 0);
+
+        if (rid->info)
+        {
+            struct _xml_error *err = rid->info;
+
+            ret = err->errno;
+            err->errno = 0;
+        }
+    }
+
+    return ret;
+}
+
+size_t
+xmlErrorGetLineNo(const void *id)
+{
+    size_t ret = 0;
+
+    if (id)
+    {
+        struct _xml_id *xid = (struct _xml_id *)id;
+        struct _root_id *rid;
+
+        if (xid->name) rid = xid->root;
+        else rid = (struct _root_id *)xid;
+
+        assert(rid != 0);
+
+        if (rid->info)
+        {
+            struct _xml_error *err = rid->info;
+            char *ps = rid->start;
+            char *pe = err->pos;
+            char *new;
+
+            while (ps<pe)
+            {
+               new = memchr(ps, '\n', pe-ps);
+               if (new)
+               {
+                  ps = new;
+                  ret++;
+               }
+               ps++;
+            }       
+        }
+    }
+
+    return ret;
+}
+
+const char *
+xmlErrorGetString(const void *id)
+{
+    char *ret = 0;
+
+    if (id)
+    {
+        struct _xml_id *xid = (struct _xml_id *)id;
+        struct _root_id *rid;
+
+        if (xid->name) rid = xid->root;
+        else rid = (struct _root_id *)xid;
+
+        assert(rid != 0);
+
+        if (rid->info)
+        {
+            struct _xml_error *err = rid->info;
+            if (XML_NO_ERROR <= err->errno && err->errno < XML_MAX_ERROR)
+               ret = (char *)__xml_error_str[err->errno];
+            else
+               ret = "incorrect error number.";
+        }
+    }
+
+    return ret;
+}
+#endif
+
 /* -------------------------------------------------------------------------- */
 
-static char *
+static const char *__xml_error_str[XML_MAX_ERROR] =
+{
+    "no error.",
+    "unable to allocate enough memory.",
+    "unable to open file for reading.",
+    "provided buffer us too small to hold the result, truncating.",
+    "incompatible opening tag for element.",
+    "missing or invalid closing tag for element.",
+    "missing or invalid opening quote for attribute.",
+    "missing or invalid closing quote for attribute."
+};
+
+char *
 __xmlNodeCopy(const char *start, size_t len, const char *path)
 {
-   char *node, *p, *ret = 0;
-   size_t rlen, slen;
-
-   rlen = len;
-   slen = strlen(path);
-   node = (char *)path;
-   p = __xmlNodeGetPath(start, &rlen, &node, &slen);
-   if (p && rlen)
-   {
-      ret = calloc(1, rlen+1);
-      memcpy(ret, p, rlen);
-   }
+     char *node, *p, *ret = 0;
+     size_t rlen, slen;
+
+     rlen = len;
+     slen = strlen(path);
+     node = (char *)path;
+     p = __xmlNodeGetPath(start, &rlen, &node, &slen);
+     if (p && rlen)
+     {
+         ret = malloc(rlen+1);
+         if (ret)
+         {
+             memcpy(ret, p, rlen);
+             *(ret+rlen+1) = '\0';
+         }
+         else
+             xmlErrorSet(0, 0, XML_OUT_OF_MEMORY);
+     }
 
-   return ret;
+     return ret;
 }
 
 char *
@@ -917,8 +1241,8 @@ __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
         ret = __xmlNodeGet(start, len, &node, &plen, &num);
         if (ret && path)
         {
-           plen = slen - (path - *name);
-           ret = __xmlNodeGetPath(ret, len, &path, &plen);
+            plen = slen - (path - *name);
+            ret = __xmlNodeGetPath(ret, len, &path, &plen);
         }
 
         *name = path;
@@ -974,7 +1298,7 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
         }
         else if (*cur == '?')
         {
-            new = __xmlInfoSkip(cur, restlen);
+            new = __xmlInfoProcess(cur, restlen);
             if (!new) return 0;
 
             restlen -= new-cur;
@@ -1099,7 +1423,7 @@ __xmlCommentSkip(const char *start, size_t len)
 }
 
 char *
-__xmlInfoSkip(const char *start, size_t len)
+__xmlInfoProcess(const char *start, size_t len)
 {
     char *cur, *new;
 
@@ -1183,6 +1507,33 @@ __xml_memncasecmp(const char *haystack, size_t *haystacklen,
     return rptr;
 }
 
+#ifndef XML_NONVALIDATING
+void
+__xmlErrorSet(const void *id, const char *pos, unsigned int errno)
+{
+   struct _xml_id *xid = (struct _xml_id *)id;
+   struct _root_id *rid;
+
+   assert(xid != 0);
+
+   if (xid->name) rid = xid->root;
+   else rid = (struct _root_id *)xid;
+
+   assert(rid != 0);
+
+   if (rid->info == 0)
+      rid->info = malloc(sizeof(struct _xml_error));
+
+   if (rid->info)
+   {
+      struct _xml_error *err = rid->info;
+
+      err->pos = (char *)pos;
+      err->errno = errno;
+   }
+}
+#endif
+
 #ifdef WIN32
 /* Source:
  * https://mollyrocket.com/forums/viewtopic.php?p=2529
@@ -1220,7 +1571,7 @@ simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
 void
 simple_unmmap(SIMPLE_UNMMAP *un)
 {
-   UnmapViewOfFile(un->p);
-   CloseHandle(un->m);
+    UnmapViewOfFile(un->p);
+    CloseHandle(un->m);
 }
 #endif
index d9829d83ae5b8aeb62bdd9bc9e576286ba017100..06f073a453ffc16ecc631ff25cc4f01409f25699 100644 (file)
@@ -223,6 +223,7 @@ char *xmlAttributeGetString(const void *, const char *);
  * @param buffer the buffer to copy the string to
  * @param buflen length of the destination buffer
  * @return the length of the string
+ */
 size_t xmlAttributeCopyString(const void *, const char *, const char *, size_t);
 
 /**
@@ -235,7 +236,6 @@ size_t xmlAttributeCopyString(const void *, const char *, const char *, size_t);
  * @return an integer less than, equal to, ro greater than zero if the value
  * of the node is found, respectively, to be less than, to match, or be greater
  * than str
- */
 int xmlAttributeCompareString(const void *, const char *, const char *);
 
 
@@ -283,7 +283,6 @@ double xmlGetDouble(const void *);
  */
 double xmlNodeGetDouble(const void *, const char *);
 
-
 /**
  * Get the double value from the named attribute.
  *
@@ -293,5 +292,32 @@ double xmlNodeGetDouble(const void *, const char *);
  */
 double xmlAttributeGetDouble(const void *, const char *);
 
+
+#ifndef XML_NONVALIDATING
+/**
+ * Get the error number of the last error and clear it.
+ *
+ * @param xid XML-id
+ * @return the numer of the last error, 0 means no error detected.
+ */
+int xmlErrorGetNo(const void *);
+
+/**
+ * Get the line number of the last detected syntax error in the xml file.
+ *
+ * @param xid XML-id
+ * @return the line number of the detected syntax error.
+ */
+size_t xmlErrorGetLineNo(const void *);
+
+/**
+ * Get a string that explains the last error.
+ *
+ * @param xid XML-id
+ * @return a string that explains the last error.
+ */
+const char *xmlErrorGetString(const void *);
+#endif
+
 #endif /* __XML_CONFIG */
 
index 532db40ddaa86cf3344547c3f2f74d366f46a85c..074d4cc720e89288fbc8c8ef310de4395e13e68f 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 
 #define _GNU_SOURCE
+#include <stdlib.h>
 #include <string.h>
 #ifndef _MSC_VER
 # include <strings.h>
@@ -311,7 +312,16 @@ void grep_file(unsigned num)
     if (xid)
     {
        void *xrid = xmlMarkId(xid);
+       size_t n = 0;
+       char *s = 0;
+       int r = 0;
        walk_the_tree(num, xrid, _root);
+
+       s = xmlErrorGetString(xrid);
+       n = xmlErrorGetLineNo(xrid);
+       r = xmlErrorGetNo(xrid);
+       if (r) printf("Error #%i at line #%u: '%s'\n", r, n, s);
+
        free(xrid);
     }
     else