#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"
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)); \
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])
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)
#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;
_filenames = ptr;
}
- _filenames[pos] = strdup(opt);
+ alen = strlen(opt)+1;
+ _filenames[pos] = malloc(alen);
+ memcpy(_filenames[pos], opt, alen);
}
return 1;
void *xmid = xmlMarkId(xid);
if (xmid && _print)
{
- no_elements = xmlGetNumNodes(xid, _print);
+ no_elements = xmlNodeGetNum(xid, _print);
for (i=0; i<no_elements; i++)
{
- if (xmlGetNodeNum(xid, xmid, _print, i) != 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);
}
}
}
}
else if (xmid && _value)
{
- no_elements = xmlGetNumNodes(xmid, _element);
+ no_elements = xmlNodeGetNum(xmid, _element);
for (i=0; i<no_elements; i++)
{
- if ((xmlGetNodeNum(xid, xmid, _element, i) != 0)
- && (xmlCompareString(xmid, _value) == 0))
+ if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
{
- char *node = xmlGetNodeName(xid);
- printf("%s: <%s>%s</%s>\n",
- _filenames[num], node, _value, node);
- free(node);
+ 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");
}
xmid = xmlMarkId(xid);
if (xmid)
{
- if (next) *next++ = 0;
+ if (next)
+ {
+ *next++ = 0;
+ }
- no_elements = xmlGetNumNodes(xid, elem);
+ no_elements = xmlNodeGetNum(xid, elem);
for (i=0; i<no_elements; i++)
{
- if (xmlGetNodeNum(xid, xmid, elem, i) != 0)
+ if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
walk_the_tree(num, xmid, next);
}
- if (next) *--next = '/';
+ if (next)
+ {
+ *--next = '/';
+ }
free(xmid);
}
}
}
-
void grep_file(unsigned num)
{
void *xid;
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
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)
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);