]> git.mxchange.org Git - flightgear.git/blobdiff - utils/xmlgrep/xmlgrep.c
Merge branch 'ehofman/version'
[flightgear.git] / utils / xmlgrep / xmlgrep.c
index f14dbf2ddf975db28c1ddc8e10c6e4f78266ab3f..23577b0c8d2415a25343817e413c1dcd33836cf1 100644 (file)
@@ -1,6 +1,19 @@
 #include <stdio.h>
+
+#define _GNU_SOURCE
 #include <stdlib.h>
 #include <string.h>
+#ifndef _MSC_VER
+# include <strings.h>
+# include <unistd.h>   /* read */
+#else
+# define strncasecmp strnicmp
+# include <stdlib.h>
+# include <io.h>
+#endif
+#include <assert.h>
+#include <sys/stat.h>  /* fstat */
+#include <fcntl.h>     /* open */
 
 #include "xml.h"
 
@@ -12,10 +25,15 @@ static char *_element = 0;
 static char *_value = 0;
 static char *_root = 0;
 static char *_print = 0;
+static char *_attribute = 0;
 static int print_filenames = 0;
 
 static void free_and_exit(int i);
 
+#define USE_BUFFER             0
+#define NODE_NAME_LEN          256
+#define STRING_LEN             2048
+
 #define SHOW_NOVAL(opt) \
 { \
     printf("option '%s' requires a value\n\n", (opt)); \
@@ -28,30 +46,35 @@ show_help ()
     printf("usage: xmlgrep [options] [file ...]\n\n");
     printf("Options:\n");
     printf("\t-h\t\tshow this help message\n");
+    printf("\t-a <string>\tprint this attribute as the output\n");
     printf("\t-e <id>\t\tshow sections that contain this element\n");
     printf("\t-p <id>\t\tprint this element as the output\n");
     printf("\t-r <path>\tspecify the XML search root\n");
-    printf("\t-v <string>\tshow sections where one of the elements has this ");
-    printf("value\n\n");
+    printf("\t-v <string>\tfilter sections that contain this vale\n\n");
     printf(" To print the contents of the 'type' element of the XML section ");
-    printf("that begins\n at '/printer/output' one would use the following ");
-    printf("syntax:\n\n\txmlgrep -r /printer/output -p type sample.xml\n\n");
+    printf("that begins\n at '/printer/output' use the following command:\n\n");
+    printf("\txmlgrep -r /printer/output -p type sample.xml\n\n");
+    printf(" To filter 'output' elements under '/printer' that have attribute");
+    printf(" 'n' set to '1'\n use the following command:\n\n");
+    printf("\txmlgrep -r /printer -p output -a n -v 1 sample.xml\n\n");
     printf(" To filter out sections that contain the 'driver' element with ");
-    printf("'generic' as\n it's value one would issue the following command:");
+    printf("'generic' as\n it's value use the following command:");
     printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
     printf("\n\n");
     free_and_exit(0);
 }
 
 void
-free_and_exit(int i)
+free_and_exit(int ret)
 {
     if (_root && _root != _static_root) free(_root);
     if (_element && _element != _static_element) free(_element);
     if (_value) free(_value);
     if (_print) free(_print);
+    if (_attribute) free(_attribute);
     if (_filenames)
     {
+        unsigned int i;
         for (i=0; i < _fcount; i++)
         {
             if (_filenames[i])
@@ -63,17 +86,18 @@ free_and_exit(int i)
         free(_filenames);
     }
  
-    exit(i);
+    exit(ret);
 }
 
 int
 parse_option(char **args, int n, int max)
 {
     char *opt, *arg = 0;
-    int sz;
+    unsigned int alen = 0;
+    unsigned int olen;
 
     opt = args[n];
-    if (opt[0] == '-' && opt[1] == '-')
+    if (strncmp(opt, "--", 2) == 0)
         opt++;
 
     if ((arg = strchr(opt, '=')) != NULL)
@@ -89,36 +113,57 @@ parse_option(char **args, int n, int max)
 #endif
     }
 
-    sz = strlen(opt);
-    if (strncmp(opt, "-help", sz) == 0)
+    olen = strlen(opt);
+    if (strncmp(opt, "-help", olen) == 0)
     {
         show_help();
     }
-    else if (strncmp(opt, "-root", sz) == 0)
+    else if (strncmp(opt, "-root", olen) == 0)
+    {
+        if (arg == 0) SHOW_NOVAL(opt);
+        alen = strlen(arg)+1;
+        if (_root) free(_root);
+        _root = malloc(alen);
+        memcpy(_root, arg, alen);
+        return 2;
+    }
+    else if (strncmp(opt, "-element", olen) == 0)
     {
         if (arg == 0) SHOW_NOVAL(opt);
-        _root = strdup(arg);
+        alen = strlen(arg)+1;
+        if (_element) free(_element);
+        _element = malloc(alen);
+        memcpy(_element, arg, alen);
         return 2;
     }
-    else if (strncmp(opt, "-element", sz) == 0)
+    else if (strncmp(opt, "-value", olen) == 0)
     {
         if (arg == 0) SHOW_NOVAL(opt);
-        _element = strdup(arg);
+        alen = strlen(arg)+1;
+        if (_value) free(_value);
+        _value = malloc(alen);
+        memcpy(_value, arg, alen);
         return 2;
     }
-    else if (strncmp(opt, "-value", sz) == 0)
+    else if (strncmp(opt, "-print", olen) == 0)
     {
         if (arg == 0) SHOW_NOVAL(opt);
-        _value = strdup(arg);
+        alen = strlen(arg)+1;
+        if (_print) free(_print);
+        _print = malloc(alen);
+        memcpy(_print, arg, alen);
         return 2;
     }
-    else if (strncmp(opt, "-print", sz) == 0)
+    else if (strncmp(opt, "-attribute", olen) == 0)
     {
         if (arg == 0) SHOW_NOVAL(opt);
-        _print = strdup(arg);
+        alen = strlen(arg)+1;
+        if (_attribute) free(_attribute);
+        _attribute = malloc(alen);
+        memcpy(_attribute, arg, alen);
         return 2;
     }
-    else if (strncmp(opt, "-list-filenames", sz) == 0)
+    else if (strncmp(opt, "-list-filenames", olen) == 0)
     { /* undocumented test argument */
         print_filenames = 1;
         return 1;
@@ -146,7 +191,9 @@ parse_option(char **args, int n, int max)
            _filenames = ptr;
         }
 
-        _filenames[pos] = strdup(opt);
+        alen = strlen(opt)+1;
+        _filenames[pos] = malloc(alen);
+        memcpy(_filenames[pos], opt, alen);
     }
 
     return 1;
@@ -161,17 +208,33 @@ void walk_the_tree(size_t num, void *xid, char *tree)
         void *xmid = xmlMarkId(xid);
         if (xmid && _print)
         {
-            no_elements = xmlGetNumElements(xmid, _print);
+            no_elements = xmlNodeGetNum(xid, _print);
             for (i=0; i<no_elements; i++)
             {
-                if (xmlGetNextElement(xid, xmid, _print) != 0)
+                if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
                 {
-                    char *value = xmlGetString(xmid);
-                    if (value)
+                    char *value;
+
+                    value = xmlGetString(xmid);
+                    if (_value && _attribute && value)
                     {
-                        printf("%s: <%s>%s</%s>\n",
-                               _filenames[num], _print, value, _print);
-                        free(value);
+#if 1
+                       char *a = xmlAttributeGetString(xmid, _attribute);
+                       if (a && !strcmp(a, _value))
+#else
+                       if (!xmlAttributeCompareString(xmid, _attribute, _value))
+#endif
+                       {
+                          printf("%s: <%s %s=\"%s\">%s</%s>\n",
+                                 _filenames[num], _print, _attribute, _value,
+                                                  value, _print);
+                       }
+                       if (value) free(value);
+                    }
+                    else
+                    {
+                       printf("%s: <%s>%s</%s>\n",
+                              _filenames[num], _print, value, _print);
                     }
                 }
             }
@@ -179,24 +242,51 @@ void walk_the_tree(size_t num, void *xid, char *tree)
         }
         else if (xmid && _value)
         {
-            no_elements = xmlGetNumElements(xmid, _element);
+            no_elements = xmlNodeGetNum(xmid, _element);
             for (i=0; i<no_elements; i++)
             {
-                if ((xmlGetNextElement(xid, xmid, _element) != 0)
-                    && (xmlCompareString(xmid, _value) == 0))
+                if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
                 {
-                    printf("%s: <%s>%s</%s>\n",
-                           _filenames[num], _element, _value, _element);
+                    char nodename[NODE_NAME_LEN];
+
+                    xmlNodeCopyName(xmid, (char *)&nodename, NODE_NAME_LEN);
+                    if (xmlCompareString(xmid, _value) == 0)
+                    {
+                        printf("%s: <%s>%s</%s>\n",
+                               _filenames[num], nodename, _value, nodename);
+                    }
                 }
             }
             free(xmid);
         }
         else if (xmid && _element)
         {
+            char parentname[NODE_NAME_LEN];
+
+            xmlNodeCopyName(xid, (char *)&parentname, NODE_NAME_LEN);
+
+            no_elements = xmlNodeGetNum(xmid, _element);
+            for (i=0; i<no_elements; i++)
+            {
+                if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
+                {
+                    char nodename[NODE_NAME_LEN];
+
+                    xmlNodeCopyName(xmid, (char *)&nodename, NODE_NAME_LEN);
+                    if (!strncasecmp((char*)&nodename, _element, NODE_NAME_LEN))
+                    {
+                        char value[NODE_NAME_LEN];
+                        xmlCopyString(xmid, (char *)&value, NODE_NAME_LEN);
+                        printf("%s: <%s> <%s>%s</%s> </%s>\n",
+                                _filenames[num], parentname, nodename, value,
+                                                 nodename, parentname);
+                    }
+                }
+            }
         }
         else printf("Error executing xmlMarkId\n");
     }
-    else if (xid)                               /* walk the rest of the tree */
+    else if (xid)                       /* walk the rest of the tree */
     {
         char *elem, *next;
         void *xmid;
@@ -209,16 +299,22 @@ void walk_the_tree(size_t num, void *xid, char *tree)
         xmid = xmlMarkId(xid);
         if (xmid)
         {
-            if (next) *next++ = 0;
+            if (next)
+            {
+               *next++ = 0;
+            }
 
-            no_elements = xmlGetNumElements(xid, elem);
+            no_elements = xmlNodeGetNum(xid, elem);
             for (i=0; i<no_elements; i++)
             {
-                if (xmlGetNextElement(xid, xmid, elem) != 0)
+                if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
                     walk_the_tree(num, xmid, next);
             }
 
-            if (next) *--next = '/';
+            if (next)
+            {
+               *--next = '/';
+            }
 
             free(xmid);
         }
@@ -226,7 +322,6 @@ void walk_the_tree(size_t num, void *xid, char *tree)
     }
 }
 
-
 void grep_file(unsigned num)
 {
     void *xid;
@@ -235,7 +330,19 @@ void grep_file(unsigned num)
     if (xid)
     {
        void *xrid = xmlMarkId(xid);
+       int r = 0;
+
        walk_the_tree(num, xrid, _root);
+
+       r = xmlErrorGetNo(xrid, 0);
+       if (r)
+       {
+            size_t n = xmlErrorGetLineNo(xrid, 0);
+            size_t c = xmlErrorGetColumnNo(xrid, 0);
+            const char *s = xmlErrorGetString(xrid, 1); /* clear the error */
+            printf("%s: at line %u, column %u: '%s'\n",_filenames[num], n,c, s);
+       }
+
        free(xrid);
     }
     else
@@ -246,9 +353,68 @@ void grep_file(unsigned num)
     xmlClose(xid);
 }
 
+
+void grep_file_buffer(unsigned num)
+{
+    struct stat st;
+    void *xid, *buf;
+    int fd, res;
+
+    fd = open(_filenames[num], O_RDONLY);
+    if (fd == -1)
+    {
+        printf("read error opening file '%s'\n", _filenames[num]);
+        return;
+    }
+    
+    fstat(fd, &st);
+    buf = malloc(st.st_size);
+    if (!buf)
+    {
+        printf("unable to allocate enough memory for reading.\n");
+        return;
+    }
+
+    res = read(fd, buf, st.st_size);
+    if (res == -1)
+    {
+        printf("unable to read from file '%s'.\n", _filenames[num]);
+        return;
+    }
+    close(fd);
+
+    xid = xmlInitBuffer(buf, st.st_size);
+    if (xid)
+    {
+       void *xrid = xmlMarkId(xid);
+       int r = 0;
+
+       walk_the_tree(num, xrid, _root);
+
+       r = xmlErrorGetNo(xrid, 0);
+       if (r)
+       {
+            size_t n = xmlErrorGetLineNo(xrid, 0);
+            size_t c = xmlErrorGetColumnNo(xrid, 0);
+            const char *s = xmlErrorGetString(xrid, 1); /* clear the error */
+            printf("%s: at line %u, column %u: '%s'\n",_filenames[num], n,c, s);
+       }
+
+       free(xrid);
+    }
+    else
+    {
+        fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
+    }
+
+    xmlClose(xid);
+    free(buf);
+}
+
 int
 main (int argc, char **argv)
 {
+    unsigned int u;
     int i;
 
     if (argc == 1)
@@ -263,8 +429,12 @@ main (int argc, char **argv)
     if (_root == 0) _root = (char *)_static_root;
     if (_element == 0) _element = (char *)_static_element;
 
-    for (i=0; i<_fcount; i++)
-        grep_file(i);
+    for (u=0; u<_fcount; u++)
+#if USE_BUFFER
+        grep_file_buffer(u);
+#else
+        grep_file(u);
+#endif
 
     free_and_exit(0);