1
0
Fork 0

Point to the new location of the ZeroXML library that contains xmlgrep

This commit is contained in:
Erik Hofman 2012-05-24 20:24:21 +02:00
parent 2d267a5782
commit ecccfeb18a
11 changed files with 3 additions and 3872 deletions

View file

@ -1,111 +0,0 @@
24-05-2009
* Add a node cache that can be enabled at compile time.
the node cache prevents recursively walking the xml tree over and over
again to find the specified nodes.
05-05-2009
* Various bugfixes, required to get fgrun working
* add testxml as sort of a stress test application
30-04-2009
* Add support for CDATA
* Fix an off by one problem.
28-04-2009
* changes to the code to allow walking the xml-tree using "*" as a node name
* add printxml, an example utility that walks an xml-tree and prints it
contenst
27-04-2009
* add xmlInitBuffer() for processing of a preallocated buffer
* add xmlErrorGetColumnNo to get the column number of the syntax error
* pass an error at a higher level to lower levels
* detect a number of extra syntax errors
26-04-2009
* add support for comments inside xml-tags, e.g.: <test><!-- --></test>
25-04-2009
* add support for self-contained tags like <test/>
* fix a problem if a file could not be mmaped
* add a few comments which hopefully makes the code easier to understand
* code cleanups
20-04-2009
* fix a case where a single-element root path (e.g. "/printer") would not
pass xmlNodeGetPath
* fix a problem where attributes or elements starting with the same letter
sequence could give a false negative result
* Add a 'clear' attribute to the xmlErrorGet functions that indicates whether
the error should be cleared or not
* detect more xml syntax errors
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-2009
* Rename xmlGetNode functions to xmlNodeGet for better consistancy
* likewise for xmlCopyNode en xmlCompareNode
* add xmlAttributeGetDouble, xmlAttributeGetInt, xmlAttributeGetString
xmlAttributeCopyString and xmlAttributeCompareString functions
* fix some small bugs and problems along the way
* add support for filtering on attribute value in xmlgrep
21-07-2008
* change a number of function parameters to const where appropriate
* fix a problem where the wrong node-name length was returned
* xmlgrep now also works when only the -e options is specified
* fix xmlgrep to show the correct node-name (it reported the parent
node-name in the previous version)
20-07-2008
* fix __xmlSkipComment to properly find the end of comment tag.
* add the xmlGetNodeName and xmlCopyNodeName functions
* add the xmlCopyString function
* clean up some code
19-07-2008
* rewrite the code to always recursively walk the node tree when searching
for a particular node. this is required for cases where a node with a
particular name is located deeper in a node with the same name;
for example -r /configuration/device/reference/device would fail in the
previous verion
* rename xmlGetElement to xmlGetNodeNum and add the possibility to request
the nth node with this name
* rename xmlGetNumElements to xmlGetNumNodes
06-07-2008
* reorganize the code to be able to skip comment sections
* depreciate __xmlFindNextElement and use __xmlGetNode instead
* xmlGetNextElement now returns char* instead of void* for furute use
* add preliminary support for wildcards in the search path ('*' and '?')
01-07-2008
* fix a problem caused by removing the last unnecessary alloc
* strip leading-, and trailing spaces from the string before comparing
* fix a problem where trailing spaces weren't removed
30-06-2008:
* some small changes; fix some typo's and fix a small memory leak
* update the documentation in README
* remove the last unnecessary alloc
29-06-2008:
* rename xmlGet(Int/Double/String) to xmlGetNode(Int/Double/String)
* add new xmlGet(Int/Double/String) functions
* rename xmlCompareString to xmlCompareNodeString for consistency
* rename xmlCompareElement to xmlCompareString for consistency
* add a README file with short examples of various functions
27-06-2008:
* removed some memory allocation in xmlGetNode and XMLGetNextElement
* use the file-size for mmap and remove the root node from the xml-id
* rearrange xmlGetNode to work with complicated xml files
* add the xmlMarkId function to save the id before using xmlGetNextElement
* speed up xmlGetNextId
23-06-2008: Initial release

View file

@ -1,146 +1,6 @@
This library is specially designed for reading xml configuration files and
to be as low on memory management as possible. Modifying or writing xml files
is not planned for the future. In most situations being able to gather data
by reading an xml file is more than enough and the read-only decision
provides a number of advantages over a one-size fits all approach. For isntance
the memory footprint can be kept low and the library can be kept simple.
To achieve these goals the mmap function is used to map the configuration file
to a memory region. The only places where memory is allocated is when creating
a new XML-id, when requesting a string from a node, when requestiong the node
name or when a request is made to copy a node into a new memory region.
The xmlgrep utility is part op the ZeroXML package which is now hosted at:
http://www.adalin.com
Using this library should be pretty simple for most tasks; just open a file,
read every parameter one by one and close the id again.
{
void *xid;
Any further development will take place there.
xid = xmlOpen("/tmp/file.xml");
xpos = xmlNodeGetDouble(xid, "/configuration/x-pos");
ypos = xmlNodeGetDouble(xid, "/configuration/y-pos");
zpos = xmlNodeGetDouble(xid, "/configuration/z-pos");
xmlClose(xid);
}
While it is certainly possible to access every node directly by calling the
xmlNodeGet(Int/Double/String) functions, when more than one node need to be
gathered from a parent node it is advised to get the id of the parent node
and work from there since the XML-id holds the boundaries of the (parent)node
which limits the searching area resulting in improved searching speed.
{
void *xnid;
char *s;
xnid = xmlNodeGet(id, "/configuration/setup/");
version = xmlNodeGetDouble(xnid, "version");
s = xmlNodeGetString(xnid, "author");
if (s) author = s;
free(s);
free(xnid);
}
Overview of the available functions:
-----------------------------------------------------------------------------
#
# Functions to Open and Close the XML file
# e.g.
# id = xmlOpen("/tmp/file.xml");
# xmlClose(id);
#
void *xmlOpen(const char *filename);
void *xmlInitBuffer(const char *buffer, size_t size);
void xmlClose(void *xid);
#
# Get the Id of a node at the specified path
# e.g.
# xnid = xmlNodeGet(id, "/path/to/specified/node");
#
void *xmlNodeGet(const void *xid, const char *path);
void *xmlNodeCopy(const void *xid, const char *path);
#
# Functions to walk the node tree and process them one by one.
# e.g.
# xmid = xmlMarkId(id);
# num = xmlNodeGetNum(xmid, "node");
# for (i=0; i<num; i++) {
# if (xmlNodeGetPos(id, xmid, "element", i) != 0) {
# if ((s = xmlGetString(xmid)) != 0) {
# printf("%s\n", s);
# free(s);
# }
# }
# }
# free(xmid);
#
void *xmlMarkId(const void *xid);
unsigned int xmlNodeGetNum(const void *xid, const char *path);
void *xmlNodeGetPos(const void *pid, void *xid, const char *element, int pos);
#
# Get the name of the current node
#
char *xmlNodeGetName(const void *xid);
size_t xmlNodeCopyName(const void *xid, const char *buffer, size_t size);
#
# These functions work on the current node.
# e.g.
# xnid = xmlNodeGet(id, "/path/to/last/node");
# i = xmlGetInt(xnid);
# or
# xnid = xmlNodeGet(id, "/path/to/specified/node");
# if (xmlCompareString(xnid, "value") == 0) printf("We have a match!\n");
#
long int xmlGetInt(const void *xid);
double xmlGetDouble(const void *xid);
char *xmlGetString(const void *xid);
size_t xmlCopyString(const void *xid, char *buffer, const size_t size);
int xmlCompareString(const void *xid, const char *str);
#
# These functions work on a specified node path
# e.g.
# d = xmlNodeGetDouble(id, "/path/to/node");
# or
# xnid = xmlNodeGet(id, "/path/to");
# i = xmlNodeGetInt(xnid, "node");
#
long int xmlNodeGetInt(const void *xid, const char *path);
double xmlNodeGetDouble(const void *xid, const char *path);
char *xmlNodeGetString(const void *xid, const char *path);
size_t xmlNodeCopyString(const void *xid, const char *path,
char *buffer, const size_t size);
int xmlNodeCompareString(const void *xid, const char *path, const char *str);
#
# These functions work on a specified atribute
# e.g.
# i = xmlAttributeGetInt(id, "n");
#
# or
# s = xmlAttributeGetString(id, "type");
# if (s) printf("node is of type '%s'\n", s);
# free(s);
#
long int xmlAttributeGetInt(const void *xid, const char *attr);
double xmlAttributeGetDouble(const void *xid, const char *attr);
char *xmlAttributeGetString(const void *xid, const char *attr);
size_t xmlAttributeCopyString(const void *xid, const char *attr,
const char *buffer, size_t size);
int xmlAttributeCompareString(const void *xid, const char *attr,
const char *str);
#
# Error detection and reporting functions
#
# char *err_str = xmlErrorGetString(id, 0);
# size_t err_lineno = xmlErrorGetLineNo(id, 0);
# int err = xmlErrorGetNo(id, 1); /* clear last error */
# if (err) printf("Error #%i at line %u: '%s'\n", err, err_lineno, err_str);
#
int xmlErrorGetNo(const void *xid, int clear);
size_t xmlErrorGetLineNo(const void *xid, int clear);
size_t xmlErrorGetColumnNo(const void *xid, int clear);
const char *xmlErrorGetString(const void *xid, int clear);

View file

@ -1,96 +0,0 @@
#include <stdio.h>
#include <malloc.h>
#include "xml.h"
void print_xml(void *, char *, unsigned int);
int main(int argc, char **argv)
{
if (argc < 1)
{
printf("usage: printtree <filename>\n\n");
}
else
{
void *rid;
rid = xmlOpen(argv[1]);
if (xmlErrorGetNo(rid, 0) != XML_NO_ERROR)
{
printf("%s\n", xmlErrorGetString(rid, 1));
}
else if (rid)
{
unsigned int i, num;
void *xid;
xid = xmlMarkId(rid);
num = xmlNodeGetNum(xid, "*");
for (i=0; i<num; i++)
{
if (xmlNodeGetPos(rid, xid, "*", i) != 0)
{
char name[4096] = "";
print_xml(xid, (char *)&name, 0);
}
}
free(xid);
xmlClose(rid);
}
else
{
printf("Error while opening file for reading: '%s'\n", argv[1]);
}
}
}
void print_xml(void *id, char *name, unsigned int len)
{
void *xid = xmlMarkId(id);
unsigned int i, num;
num = xmlNodeGetNum(xid, "*");
if (num == 0)
{
char *s;
s = xmlGetString(xid);
if (s)
{
name[len] = 0;
printf("%s = %s\n", name, s);
free(s);
}
}
else
{
unsigned int i, q;
name[len++] = '/';
for (i=0; i<num; i++)
{
if (xmlNodeGetPos(id, xid, "*", i) != 0)
{
unsigned int res, i = 4096 - len;
res = xmlNodeCopyName(xid, (char *)&name[len], i);
if (res)
{
unsigned int index = xmlAttributeGetInt(xid, "n");
if (index)
{
unsigned int pos = len+res;
name[pos++] = '[';
i = snprintf((char *)&name[pos], 4096-pos, "%i", index);
name[pos+i] = ']';
res += i+2;
}
}
print_xml(xid, name, len+res);
}
else printf("error\n");
}
}
}

View file

@ -1,95 +0,0 @@
#include <stdio.h>
#include <malloc.h>
#include "xml.h"
void print_xml(void *);
int main(int argc, char **argv)
{
if (argc < 1)
{
printf("usage: printxml <filename>\n\n");
}
else
{
void *rid;
rid = xmlOpen(argv[1]);
if (xmlErrorGetNo(rid, 0) != XML_NO_ERROR)
{
printf("%s\n", xmlErrorGetString(rid, 1));
}
else if (rid)
{
unsigned int i, num;
void *xid;
xid = xmlMarkId(rid);
num = xmlNodeGetNum(xid, "*");
for (i=0; i<num; i++)
{
if (xmlNodeGetPos(rid, xid, "*", i) != 0)
{
char name[256];
xmlNodeCopyName(xid, (char *)&name, 256);
printf("<%s>\n", name);
print_xml(xid);
printf("\n</%s>\n", name);
}
}
free(xid);
xmlClose(rid);
}
else
{
printf("Error while opening file for reading: '%s'\n", argv[1]);
}
}
}
void print_xml(void *id)
{
static int level = 1;
void *xid = xmlMarkId(id);
unsigned int i, num;
num = xmlNodeGetNum(xid, "*");
if (num == 0)
{
char *s;
s = xmlGetString(xid);
if (s)
{
printf("%s", s);
free(s);
}
}
else
{
unsigned int i, q;
for (i=0; i<num; i++)
{
if (xmlNodeGetPos(id, xid, "*", i) != 0)
{
char name[256];
int r;
xmlNodeCopyName(xid, (char *)&name, 256);
printf("\n");
for(q=0; q<level; q++) printf(" ");
printf("<%s>", name);
level++;
print_xml(xid);
level--;
printf("</%s>", name);
}
else printf("error\n");
}
printf("\n");
for(q=1; q<level; q++) printf(" ");
}
}

View file

@ -1,68 +0,0 @@
<?xml version="1.0"?>
<Configuration>
<output>
<frequency-hz>48000</frequency-hz>
<interval-hz>20</interval-hz>
<num-speakers>2</num-speakers>
<tmp><!-- --></tmp>
<test n="0" ëlémènt="bjôrn"/>
<test n="1"/>
<test n="2"/>
<menu><name>* Traffic, # taxiing to runway (.</name></menu>
<sample><test> * Traffic, # taxiing to runway (. </test></sample>
<!--
- x is positive to the right
- y is positive upwards
- z is positive backwards
-->
<speaker n="0">
<channel>0</channel>
<volume-norm>1.0</volume-norm>
<desc><!-- empty --></desc>
</speaker>
<speaker n="1">
<channel>1</channel>
<volume-norm>1.0</volume-norm>
<desc>
<!--
empty --></desc>
</speaker>
<script><![CDATA[
getprop(call(sprintf, size(arg));
c--; x >>= 33;
// --> comment ]>
;]]></script>
</output>
<backend>
<name type="stereo">ALSA Hardware</name>
<Output>
<renderer>hw:0</renderer>
<channels>2</channels>
<!-- periods>16</periods -->
<frequency-hz>44100</frequency-hz>
<bits-per-sample>16</bits-per-sample>
</Output>
<Input>
<renderer>default</renderer>
<frequency-hz>44100</frequency-hz>
</Input>
</backend>
<nasal>
<YF23>
<script><![CDATA[
# If the ground-roll-heading-hold has been reset (<-999) set:
if(agl > 50) {};
]]></script>
</YF23>
</nasal>
</Configuration>

View file

@ -1,188 +0,0 @@
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include "xml.h"
#define ROOTNODE "/Configuration/output/menu"
#define LEAFNODE "name"
#define PATH ROOTNODE"/"LEAFNODE
#define BUFLEN 4096
#define PRINT_ERROR_AND_EXIT(id) \
if (xmlErrorGetNo(id, 0) != XML_NO_ERROR) { \
const char *errstr = xmlErrorGetString(id, 0); \
size_t column = xmlErrorGetColumnNo(id, 0); \
size_t lineno = xmlErrorGetLineNo(id, 1); \
printf("Error at line %i, column %i: %s\n", lineno, column, errstr); \
exit(-1); \
}
int main()
{
void *root_id;
root_id = xmlOpen("sample.xml");
if (root_id)
{
void *path_id, *node_id;
char *s;
printf("\nTesting xmlNodeGetString for /*/*/test:\t\t\t\t\t");
s = xmlNodeGetString(root_id , "/*/*/test");
if (s)
{
printf("failed.\n\t'%s' should be empty\n", s);
free(s);
}
else
printf("succes.\n");
printf("Testing xmlGetString for /Configuration/output/test:\t\t\t");
path_id = xmlNodeGet(root_id, "/Configuration/output/test");
if (path_id)
{
s = xmlGetString(path_id);
if (s)
{
printf("failed.\n\t'%s' should be empty\n", s);
free(s);
}
else
printf("succes.\n");
}
else
PRINT_ERROR_AND_EXIT(root_id);
path_id = xmlNodeGet(root_id, PATH);
node_id = xmlNodeGet(root_id, ROOTNODE);
if (path_id && node_id)
{
char buf[BUFLEN];
size_t len;
xmlCopyString(path_id, buf, BUFLEN);
printf("Testing xmlNodeCopyString against xmlGetString:\t\t\t\t");
if ((s = xmlGetString(path_id)) != 0)
{
if (strcmp(s, buf)) /* not the same */
printf("failed.\n\t'%s' differs from '%s'\n", s, buf);
else
printf("succes.\n");
printf("Testing xmlCopyString against xmlGetString:\t\t\t\t");
xmlCopyString(path_id, buf, BUFLEN);
if (strcmp(s, buf)) /* not the same */
printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
}
else
PRINT_ERROR_AND_EXIT(path_id);
printf("Testing xmlCopyString against xmlCompareString:\t\t\t\t");
if (xmlCompareString(path_id, buf)) /* not the same */
printf ("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
printf("Testing xmlCopyString against xmlNodeCompareString:\t\t\t");
if (xmlNodeCompareString(node_id, LEAFNODE, buf)) /* not the same */
printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
if (s) free(s);
printf("Testing xmlCopyString against xmlNodeGetString:\t\t\t\t");
if ((s = xmlNodeGetString(node_id, LEAFNODE)) != 0)
{
if (strcmp(s, buf)) /* not the same */
printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
free(s);
}
else
PRINT_ERROR_AND_EXIT(node_id);
free(path_id);
path_id = xmlNodeGet(root_id, "/Configuration/backend/name");
if (path_id)
{
printf("Testing xmlAttributeCopyString against xmlAttributeCompareString:\t");
xmlAttributeCopyString(path_id, "type", buf, BUFLEN);
if (xmlAttributeCompareString(path_id, "type", buf)) /* no match */
printf("failed.\n\t'%s' differs\n", buf);
else
printf("succes.\n");
printf("Testing xmlAttributeCopyString against xmlAttributeGetString:\t\t");
if ((s = xmlAttributeGetString(path_id, "type")) != 0)
{
if (strcmp(s, buf)) /* not the same */
printf("failed.\n\t'%s' differs from '%s'\n", s, buf);
else
printf("succes.\n");
free(s);
}
else
PRINT_ERROR_AND_EXIT(path_id);
}
else
PRINT_ERROR_AND_EXIT(root_id);
free(node_id);
free(path_id);
path_id = xmlNodeGet(root_id, "Configuration/output/sample/test");
if (path_id)
{
xmlNodeCopyString(root_id ,"Configuration/output/menu/name", buf, BUFLEN);
printf("Testing xmlCompareString against a fixed string: \t\t\t");
if (xmlCompareString(path_id, buf)) /* no match */
printf("failed.\n\t'%s' differs\n", buf);
else
printf("succes.\n");
s = xmlGetString(path_id);
if (s)
{
printf("Testing xmlGetString against a fixed string: \t\t\t\t");
if (strcmp(s, buf)) /* mismatch */
printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
printf("Testing xmlCopyString gainst a fixed string: \t\t\t\t");
xmlCopyString(path_id, buf, BUFLEN);
if (strcmp(s, buf)) /* mismatch */
printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
free(s);
}
else
PRINT_ERROR_AND_EXIT(path_id);
free(path_id);
}
}
if (xmlErrorGetNo(root_id, 0) != XML_NO_ERROR)
{
const char *errstr = xmlErrorGetString(root_id, 0);
size_t column = xmlErrorGetColumnNo(root_id, 0);
size_t lineno = xmlErrorGetLineNo(root_id, 1);
printf("Error at line %i, column %i: %s\n", lineno, column, errstr);
}
xmlClose(root_id);
}
printf("\n");
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,434 +0,0 @@
/* 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
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of (any of) the copyrightholder(s) nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __XML_CONFIG
#define __XML_CONFIG 1
#ifdef __cplusplus
extern "C" {
#endif
#undef XML_NONVALIDATING
#ifdef XML_USE_NODECACHE
#include "xml_cache.h"
#else
void *cacheGet(void *);
#endif
enum
{
XML_NO_ERROR = 0,
XML_OUT_OF_MEMORY,
XML_FILE_NOT_FOUND,
XML_INVALID_NODE_NAME,
XML_UNEXPECTED_EOF,
XML_TRUNCATE_RESULT,
XML_INVALID_COMMENT,
XML_INVALID_INFO_BLOCK,
XML_ELEMENT_NO_OPENING_TAG,
XML_ELEMENT_NO_CLOSING_TAG,
XML_ATTRIB_NO_OPENING_QUOTE,
XML_ATTRIB_NO_CLOSING_QUOTE,
XML_MAX_ERROR
};
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
typedef struct
{
HANDLE m;
void *p;
} SIMPLE_UNMMAP;
#endif
#ifndef XML_NONVALIDATING
struct _xml_error
{
char *pos;
int err_no;
};
#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;
#ifdef XML_USE_NODECACHE
void *node;
#endif
#ifndef XML_NONVALIDATING
struct _xml_error *info;
#endif
#ifdef WIN32
SIMPLE_UNMMAP un;
#endif
};
struct _xml_id
{
char *name;
char *start;
size_t len;
size_t name_len;
#ifndef XML_NONVALIDATING
struct _root_id *root;
#endif
#ifdef XML_USE_NODECACHE
void *node;
#endif
};
/**
* Open an XML file for processing.
*
* @param fname path to the file
* @return XML-id which is used for further processing
*/
void *xmlOpen(const char *);
/**
* Process a section of XML code in a preallocated buffer.
* The buffer may not be free'd until xmlClose has been called.
*
* @param buffer pointer to the buffer
* @param size size of the buffer
* @return XML-id which is used for further processing
*/
void *xmlInitBuffer(const char *, size_t);
/**
* Close the XML file after which no further processing is possible.
*
* @param xid XML-id
*/
void xmlClose(void *);
/**
* Locate a subsection of the xml tree for further processing.
* This adds processing speed since the reuired nodes will only be searched
* in the subsection.
*
* The memory allocated for the XML-subsection-id has to be freed by the
* calling process.
*
* @param xid XML-id
* @param node path to the node containing the subsection
* @return XML-subsection-id for further processing
*/
void *xmlNodeGet(const void *, const char *);
/**
* Copy a subsection of the xml tree for further processing.
* This is useful when it's required to process a section of the XML code
* after the file has been closed. The drawback is the added memory
* requirements.
*
* The memory allocated for the XML-subsection-id has to be freed by the
* calling process.
*
* @param xid XML-id
* @param node path to the node containing the subsection
* @return XML-subsection-id for further processing
*/
void *xmlNodeCopy(const void *, const char *);
/**
* Return the name of this node.
* The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @return a newly alocated string containing the node name
*/
char *xmlNodeGetName(const void *);
/**
* Copy the name of this node in a pre-allocated buffer.
*
* @param xid XML-id
* @param buffer the buffer to copy the string to
* @param buflen length of the destination buffer
* @return the length of the node name
*/
size_t xmlNodeCopyName(const void *, char *, size_t);
/**
* Create a marker XML-id that starts out with the same settings as the
* refference XML-id.
*
* Marker id's are required when xmlNodeGetNum() and xmlNodeGetPos() are used
* to walk a number of nodes. The xmlNodeGetPos function adjusts the contents
* of the provided XML-id to keep track of it's position within the xml section.
* The returned XML-id is limited to the boundaries of the requested XML tag
* and has to be freed by the calling process.
*
* @param xid reference XML-id
* @return a copy of the reference XML-id
*/
void *xmlMarkId(const void *);
/**
* Get the number of nodes with the same name from a specified xml path.
*
* @param xid XML-id
* @param path path to the xml node
* @return the number count of the nodename
*/
unsigned int xmlNodeGetNum(const void *, const char *);
/**
* Get the nth occurrence of node in the parent node.
* The return value should never be altered or freed by the caller.
*
* @param pid XML-id of the parent node of this node
* @param xid XML-id
* @param node name of the node to search for
* @param num specify which occurence to return
* @return XML-subsection-id for further processing or NULL if unsuccessful
*/
void *xmlNodeGetPos(const void *, void *, const char *, size_t);
/**
* Get a string of characters from the current node.
* The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @return a newly alocated string containing the contents of the node
*/
char *xmlGetString(const void *);
/**
* Get a string of characters from the current node.
* This function has the advantage of not allocating its own return buffer,
* keeping the memory management to an absolute minimum but the disadvantage
* is that it's unreliable in multithread environments.
*
* @param xid XML-id
* @param buffer the buffer to copy the string to
* @param buflen length of the destination buffer
* @return the length of the string
*/
size_t xmlCopyString(const void *, char *, size_t);
/**
* Compare the value of this node to a reference string.
* Comparing is done in a case insensitive way.
*
* @param xid XML-id
* @param str the string to compare to
* @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 xmlCompareString(const void *, const char *);
/**
* Get a string of characters from a specified xml path.
* The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @param path path to the xml node
* @return a newly alocated string containing the contents of the node
*/
char *xmlNodeGetString(const void *, const char *);
/**
* Get a string of characters from a specified xml path.
* This function has the advantage of not allocating its own return buffer,
* keeping the memory management to an absolute minimum but the disadvantage
* is that it's unreliable in multithread environments.
*
* @param xid XML-id
* @param path path to the xml node
* @param buffer the buffer to copy the string to
* @param buflen length of the destination buffer
* @return the length of the string
*/
size_t xmlNodeCopyString(const void *, const char *, char *, size_t);
/**
* Compare the value of a node to a reference string.
* Comparing is done in a case insensitive way.
*
* @param xid XML-id
* @param path path to the xml node to compare to
* @param str the string to compare to
* @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 xmlNodeCompareString(const void *, const char *, const char *);
/**
* Get a string of characters from a named attribute.
* The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @param name name of the attribute to acquire
* @return the contents of the node converted to an integer value
*/
char *xmlAttributeGetString(const void *, const char *);
/**
* Get a string of characters from a named attribute.
* This function has the advantage of not allocating its own return buffer,
* keeping the memory management to an absolute minimum but the disadvantage
* is that it's unreliable in multithread environments.
*
* @param xid XML-id
* @param name name of the attribute to acquire.
* @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 *, char *, size_t);
/**
* Compare the value of an attribute to a reference string.
* Comparing is done in a case insensitive way.
*
* @param xid XML-id
* @param name name of the attribute to acquire.
* @param str the string to compare to
* @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 *);
/**
* Get the integer value from the current node/
*
* @param xid XML-id
* @return the contents of the node converted to an integer value
*/
long int xmlGetInt(const void *);
/**
* Get an integer value from a specified xml path.
*
* @param xid XML-id
* @param path path to the xml node
* @return the contents of the node converted to an integer value
*/
long int xmlNodeGetInt(const void *, const char *);
/**
* Get the integer value from the named attribute.
*
* @param xid XML-id
* @param name name of the attribute to acquire
* @return the contents of the node converted to an integer value
*/
long int xmlAttributeGetInt(const void *, const char *);
/**
* Get the double value from the curent node/
*
* @param xid XML-id
* @return the contents of the node converted to a double value
*/
double xmlGetDouble(const void *);
/**
* Get a double value from a specified xml path/
*
* @param xid XML-id
* @param path path to the xml node
* @return the contents of the node converted to a double value
*/
double xmlNodeGetDouble(const void *, const char *);
/**
* Get the double value from the named attribute.
*
* @param xid XML-id
* @param name name of the attribute to acquire
* @return the contents of the node converted to an integer value
*/
double xmlAttributeGetDouble(const void *, const char *);
/**
* Get the error number of the last error and clear it.
*
* @param xid XML-id
* @param clear clear the error state if non zero
* @return the numer of the last error, 0 means no error detected.
*/
int xmlErrorGetNo(const void *, int);
/**
* Get the line number of the last detected syntax error in the xml file.
*
* @param xid XML-id
* @param clear clear the error state if non zero
* @return the line number of the detected syntax error.
*/
size_t xmlErrorGetLineNo(const void *, int);
/**
* Get the column number of the last detected syntax error in the xml file.
*
* @param xid XML-id
* @param clear clear the error state if non zero
* @return the line number of the detected syntax error.
*/
size_t xmlErrorGetColumnNo(const void *, int);
/**
* Get a string that explains the last error.
*
* @param xid XML-id
* @param clear clear the error state if non zero
* @return a string that explains the last error.
*/
const char *xmlErrorGetString(const void *, int);
#ifdef __cplusplus
}
#endif
#endif /* __XML_CONFIG */

View file

@ -1,250 +0,0 @@
/* 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
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of (any of) the copyrightholder(s) nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <assert.h>
#include "xml.h"
#ifndef NDEBUG
# define PRINT(a, b, c) { \
size_t l1 = (b), l2 = (c); \
char *s = (a); \
if (s) { \
size_t q, len = l2; \
if (l1 < l2) len = l1; \
if (len < 50000) { \
printf("(%i) '", len); \
for (q=0; q<len; q++) printf("%c", s[q]); \
printf("'\n"); \
} else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
} else printf("NULL pointer at line %i\n", __LINE__); \
}
#endif
#if !defined(XML_USE_NODECACHE)
void *
cacheNodeGet(void *id, const char *node)
{
return 0;
}
#else
#define NODE_BLOCKSIZE 16
struct _xml_node
{
void *parent;
char *name;
size_t name_len;
char *data;
size_t data_len;
void **node;
size_t no_nodes;
size_t first_free;
};
char *
__xmlNodeGetFromCache(void **nc, const char *start, size_t *len,
char **element, size_t *elementlen , size_t *nodenum)
{
struct _xml_node *cache;
size_t num = *nodenum;
char *name = *element;
void *rv = 0;
assert(nc != 0);
cache = (struct _xml_node *)*nc;
assert(cache != 0);
assert((cache->first_free > num) || (cache->first_free == 0));
if (cache->first_free == 0) /* leaf node */
{
rv = cache->data;
*len = cache->data_len;
*element = cache->name;
*elementlen = cache->name_len;
*nodenum = 0;
}
else if (*name == '*')
{
struct _xml_node *node = cache->node[num];
*nc = node;
rv = node->data;
*len = node->data_len;
*element = node->name;
*elementlen = node->name_len;
*nodenum = cache->first_free;
}
else
{
size_t namelen = *elementlen;
size_t i, pos = 0;
for (i=0; i<cache->first_free; i++)
{
struct _xml_node *node = cache->node[i];
assert(node);
if ((node->name_len == namelen) &&
(!strncasecmp(node->name, name, namelen)))
{
if (pos == num)
{
*nc = node;
rv = node->data;
*element = node->name;
*elementlen = node->name_len;
*len = node->data_len;
*nodenum = cache->first_free;
break;
}
pos++;
}
}
}
return rv;
}
void *
cacheInit()
{
return calloc(1, sizeof(struct _xml_node));
}
void
cacheInitLevel(void *nc)
{
struct _xml_node *cache = (struct _xml_node *)nc;
assert(cache != 0);
cache->node = calloc(NODE_BLOCKSIZE, sizeof(struct _xml_node *));
cache->no_nodes = NODE_BLOCKSIZE;
}
void
cacheFree(void *nc)
{
struct _xml_node *cache = (struct _xml_node *)nc;
assert(nc != 0);
if (cache->first_free)
{
struct _xml_node **node = (struct _xml_node **)cache->node;
size_t i = 0;
while(i < cache->first_free)
{
cacheFree(node[i++]);
}
free(node);
}
free(cache);
}
void *
cacheNodeGet(void *id)
{
struct _xml_id *xid = (struct _xml_id *)id;
struct _xml_node *cache = 0;
assert(xid != 0);
if (xid->name)
{
cache = xid->node;
}
else
{
struct _root_id *rid = (struct _root_id *)xid;
cache = rid->node;
}
return cache;
}
void *
cacheNodeNew(void *nc)
{
struct _xml_node *cache = (struct _xml_node *)nc;
struct _xml_node *rv = 0;
size_t i = 0;
assert(nc != 0);
i = cache->first_free;
if (i == cache->no_nodes)
{
size_t size, no_nodes;
void *p;
no_nodes = cache->no_nodes + NODE_BLOCKSIZE;
size = no_nodes * sizeof(struct _xml_node *);
p = realloc(cache->node, size);
if (!p) return 0;
cache->node = p;
cache->no_nodes = no_nodes;
}
rv = calloc(1, sizeof(struct _xml_node));
if (rv) rv->parent = cache;
cache->node[i] = rv;
cache->first_free++;
return rv;
}
void
cacheDataSet(void *n, char *name, size_t namelen, char *data, size_t datalen)
{
struct _xml_node *node = (struct _xml_node *)n;
assert(node != 0);
assert(name != 0);
assert(namelen != 0);
assert(data != 0);
node->name = name;
node->name_len = namelen;
node->data = data;
node->data_len = datalen;
}
#endif

View file

@ -1,50 +0,0 @@
/* 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
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of (any of) the copyrightholder(s) nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __XML_NODECACHE
#define __XML_NODECACHE 1
#ifdef __cplusplus
extern "C" {
#endif
void *cacheInit();
void cacheInitLevel(void *);
void cacheFree(void *);
void *cacheNodeNew(void *);
void *cacheNodeGet(void *);
void cacheDataSet(void *, char *, size_t, char *, size_t);
char *__xmlNodeGetFromCache(void **, const char *, size_t *, char **, size_t *, size_t *);
#ifdef __cplusplus
}
#endif
#endif /* __XML_NODECACHE */

View file

@ -1,442 +0,0 @@
#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 const char *_static_root = "/";
static const char *_static_element = "*";
static unsigned int _fcount = 0;
static char **_filenames = 0;
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)); \
free_and_exit(-1); \
}
void
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>\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' 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 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 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])
{
if (print_filenames) printf("%s\n", _filenames[i]);
free(_filenames[i]);
}
}
free(_filenames);
}
exit(ret);
}
int
parse_option(char **args, int n, int max)
{
char *opt, *arg = 0;
unsigned int alen = 0;
unsigned int olen;
opt = args[n];
if (strncmp(opt, "--", 2) == 0)
opt++;
if ((arg = strchr(opt, '=')) != NULL)
{
*arg++ = 0;
}
else if (++n < max)
{
arg = args[n];
#if 0
if (arg && arg[0] == '-')
arg = 0;
#endif
}
olen = strlen(opt);
if (strncmp(opt, "-help", olen) == 0)
{
show_help();
}
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);
alen = strlen(arg)+1;
if (_element) free(_element);
_element = malloc(alen);
memcpy(_element, arg, alen);
return 2;
}
else if (strncmp(opt, "-value", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
alen = strlen(arg)+1;
if (_value) free(_value);
_value = malloc(alen);
memcpy(_value, arg, alen);
return 2;
}
else if (strncmp(opt, "-print", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
alen = strlen(arg)+1;
if (_print) free(_print);
_print = malloc(alen);
memcpy(_print, arg, alen);
return 2;
}
else if (strncmp(opt, "-attribute", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
alen = strlen(arg)+1;
if (_attribute) free(_attribute);
_attribute = malloc(alen);
memcpy(_attribute, arg, alen);
return 2;
}
else if (strncmp(opt, "-list-filenames", olen) == 0)
{ /* undocumented test argument */
print_filenames = 1;
return 1;
}
else if (opt[0] == '-')
{
printf("Unknown option %s\n", opt);
free_and_exit(-1);
}
else
{
int pos = _fcount++;
if (_filenames == 0)
{
_filenames = (char **)malloc(sizeof(char*));
}
else
{
char **ptr = (char **)realloc(_filenames, _fcount*sizeof(char*));
if (ptr == 0)
{
printf("Out of memory.\n\n");
free_and_exit(-1);
}
_filenames = ptr;
}
alen = strlen(opt)+1;
_filenames[pos] = malloc(alen);
memcpy(_filenames[pos], opt, alen);
}
return 1;
}
void walk_the_tree(size_t num, void *xid, char *tree)
{
unsigned int i, no_elements;
if (!tree) /* last node from the tree */
{
void *xmid = xmlMarkId(xid);
if (xmid && _print)
{
no_elements = xmlNodeGetNum(xid, _print);
for (i=0; i<no_elements; i++)
{
if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
{
char *value;
value = xmlGetString(xmid);
if (_value && _attribute && 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);
}
}
}
free(xmid);
}
else if (xmid && _value)
{
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 (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 */
{
char *elem, *next;
void *xmid;
elem = tree;
if (*elem == '/') elem++;
next = strchr(elem, '/');
xmid = xmlMarkId(xid);
if (xmid)
{
if (next)
{
*next++ = 0;
}
no_elements = xmlNodeGetNum(xid, elem);
for (i=0; i<no_elements; i++)
{
if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
walk_the_tree(num, xmid, next);
}
if (next)
{
*--next = '/';
}
free(xmid);
}
else printf("Error executing xmlMarkId\n");
}
}
void grep_file(unsigned num)
{
void *xid;
xid = xmlOpen(_filenames[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
{
fprintf(stderr, "Error reading file '%s'\n", _filenames[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)
show_help();
for (i=1; i<argc;)
{
int ret = parse_option(argv, i, argc);
i += ret;
}
if (_root == 0) _root = (char *)_static_root;
if (_element == 0) _element = (char *)_static_element;
for (u=0; u<_fcount; u++)
#if USE_BUFFER
grep_file_buffer(u);
#else
grep_file(u);
#endif
free_and_exit(0);
return 0;
}