]> git.mxchange.org Git - flightgear.git/blob - utils/xmlgrep/xmlgrep.c
fe4782e0fd607639284c85496bf0996391bca228
[flightgear.git] / utils / xmlgrep / xmlgrep.c
1 #include <stdio.h>
2
3 #define _GNU_SOURCE
4 #include <string.h>
5 #include <strings.h>
6 #include <assert.h>
7
8 #include "xml.h"
9
10 static const char *_static_root = "/";
11 static const char *_static_element = "*";
12 static unsigned int _fcount = 0;
13 static char **_filenames = 0;
14 static char *_element = 0;
15 static char *_value = 0;
16 static char *_root = 0;
17 static char *_print = 0;
18 static char *_attribute = 0;
19 static int print_filenames = 0;
20
21 static void free_and_exit(int i);
22
23 #define SHOW_NOVAL(opt) \
24 { \
25     printf("option '%s' requires a value\n\n", (opt)); \
26     free_and_exit(-1); \
27 }
28
29 void
30 show_help ()
31 {
32     printf("usage: xmlgrep [options] [file ...]\n\n");
33     printf("Options:\n");
34     printf("\t-h\t\tshow this help message\n");
35     printf("\t-a <string>\tprint this attribute as the output\n");
36     printf("\t-e <id>\t\tshow sections that contain this element\n");
37     printf("\t-p <id>\t\tprint this element as the output\n");
38     printf("\t-r <path>\tspecify the XML search root\n");
39     printf("\t-v <string>\tfilter sections that contain this vale\n\n");
40     printf(" To print the contents of the 'type' element of the XML section ");
41     printf("that begins\n at '/printer/output' use the following command:\n\n");
42     printf("\txmlgrep -r /printer/output -p type sample.xml\n\n");
43     printf(" To filter 'output' elements under '/printer' that have attribute");
44     printf(" 'n' set to '1'\n use the following command:\n\n");
45     printf("\txmlgrep -r /printer -p output -a n -v 1 sample.xml\n\n");
46     printf(" To filter out sections that contain the 'driver' element with ");
47     printf("'generic' as\n it's value use the following command:");
48     printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
49     printf("\n\n");
50     free_and_exit(0);
51 }
52
53 void
54 free_and_exit(int ret)
55 {
56     if (_root && _root != _static_root) free(_root);
57     if (_element && _element != _static_element) free(_element);
58     if (_value) free(_value);
59     if (_print) free(_print);
60     if (_attribute) free(_attribute);
61     if (_filenames)
62     {
63         unsigned int i;
64         for (i=0; i < _fcount; i++)
65         {
66             if (_filenames[i])
67             {
68                 if (print_filenames) printf("%s\n", _filenames[i]);
69                 free(_filenames[i]);
70             }
71         }
72         free(_filenames);
73     }
74  
75     exit(ret);
76 }
77
78 int
79 parse_option(char **args, int n, int max)
80 {
81     char *opt, *arg = 0;
82     unsigned int alen = 0;
83     unsigned int olen;
84
85     opt = args[n];
86     if (strncmp(opt, "--", 2) == 0)
87         opt++;
88
89     if ((arg = strchr(opt, '=')) != NULL)
90     {
91         *arg++ = 0;
92     }
93     else if (++n < max)
94     {
95         arg = args[n];
96 #if 0
97         if (arg && arg[0] == '-')
98             arg = 0;
99 #endif
100     }
101
102     olen = strlen(opt);
103     if (strncmp(opt, "-help", olen) == 0)
104     {
105         show_help();
106     }
107     else if (strncmp(opt, "-root", olen) == 0)
108     {
109         if (arg == 0) SHOW_NOVAL(opt);
110         alen = strlen(arg)+1;
111         _root = malloc(alen);
112         memcpy(_root, arg, alen);
113         return 2;
114     }
115     else if (strncmp(opt, "-element", olen) == 0)
116     {
117         if (arg == 0) SHOW_NOVAL(opt);
118         alen = strlen(arg)+1;
119         _element = malloc(alen);
120         memcpy(_element, arg, alen);
121         return 2;
122     }
123     else if (strncmp(opt, "-value", olen) == 0)
124     {
125         if (arg == 0) SHOW_NOVAL(opt);
126         alen = strlen(arg)+1;
127         _value = malloc(alen);
128         memcpy(_value, arg, alen);
129         return 2;
130     }
131     else if (strncmp(opt, "-print", olen) == 0)
132     {
133         if (arg == 0) SHOW_NOVAL(opt);
134         alen = strlen(arg)+1;
135         _print = malloc(alen);
136         memcpy(_print, arg, alen);
137         return 2;
138     }
139     else if (strncmp(opt, "-attribute", olen) == 0)
140     {
141         if (arg == 0) SHOW_NOVAL(opt);
142         alen = strlen(arg)+1;
143         _attribute = malloc(alen);
144         memcpy(_attribute, arg, alen);
145         return 2;
146     }
147     else if (strncmp(opt, "-list-filenames", olen) == 0)
148     { /* undocumented test argument */
149         print_filenames = 1;
150         return 1;
151     }
152     else if (opt[0] == '-')
153     {
154         printf("Unknown option %s\n", opt);
155         free_and_exit(-1);
156     }
157     else
158     {
159         int pos = _fcount++;
160         if (_filenames == 0)
161         {
162             _filenames = (char **)malloc(sizeof(char*));
163         }
164         else
165         {
166             char **ptr = (char **)realloc(_filenames, _fcount*sizeof(char*));
167             if (ptr == 0)
168             {
169                 printf("Out of memory.\n\n");
170                 free_and_exit(-1);
171             }
172            _filenames = ptr;
173         }
174
175         alen = strlen(opt)+1;
176         _filenames[pos] = malloc(alen);
177         memcpy(_filenames[pos], opt, alen);
178     }
179
180     return 1;
181 }
182
183 void walk_the_tree(size_t num, void *xid, char *tree)
184 {
185     unsigned int i, no_elements;
186
187     if (!tree)                                  /* last node from the tree */
188     {
189         void *xmid = xmlMarkId(xid);
190         if (xmid && _print)
191         {
192             no_elements = xmlNodeGetNum(xid, _print);
193             for (i=0; i<no_elements; i++)
194             {
195                 if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
196                 {
197                     char value[1024];
198
199                     xmlCopyString(xmid, (char *)&value, 1024);
200                     if (_value && _attribute)
201                     {
202                        if (!xmlAttributeCompareString(xmid, _attribute, _value))
203                        {
204                           printf("%s: <%s %s=\"%s\">%s</%s>\n",
205                                  _filenames[num], _print, _attribute, _value,
206                                                   value, _print);
207                        }
208                     }
209                     else
210                     {
211                        printf("%s: <%s>%s</%s>\n",
212                               _filenames[num], _print, value, _print);
213                     }
214                 }
215             }
216             free(xmid);
217         }
218         else if (xmid && _value)
219         {
220             no_elements = xmlNodeGetNum(xmid, _element);
221             for (i=0; i<no_elements; i++)
222             {
223                 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
224                 {
225                     char nodename[64];
226
227                     xmlNodeCopyName(xmid, (char *)&nodename, 64);
228                     if (xmlCompareString(xmid, _value) == 0)
229                     {
230                         printf("%s: <%s>%s</%s>\n",
231                                _filenames[num], nodename, _value, nodename);
232                     }
233                 }
234             }
235             free(xmid);
236         }
237         else if (xmid && _element)
238         {
239             char parentname[64];
240
241             xmlNodeCopyName(xid, (char *)&parentname, 64);
242
243             no_elements = xmlNodeGetNum(xmid, _element);
244             for (i=0; i<no_elements; i++)
245             {
246                 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
247                 {
248                     char nodename[64];
249
250                     xmlNodeCopyName(xmid, (char *)&nodename, 64);
251                     if (strncasecmp((char *)&nodename, _element, 64) == 0)
252                     {
253                         char value[64];
254                         xmlCopyString(xmid, (char *)&value, 64);
255                         printf("%s: <%s> <%s>%s</%s> </%s>\n",
256                                 _filenames[num], parentname, nodename, value,
257                                                  nodename, parentname);
258                     }
259                 }
260             }
261         }
262         else printf("Error executing xmlMarkId\n");
263     }
264     else if (xid)                        /* walk the rest of the tree */
265     {
266         char *elem, *next;
267         void *xmid;
268
269         elem = tree;
270         if (*elem == '/') elem++;
271
272         next = strchr(elem, '/');
273         
274         xmid = xmlMarkId(xid);
275         if (xmid)
276         {
277             if (next)
278             {
279                *next++ = 0;
280             }
281
282             no_elements = xmlNodeGetNum(xid, elem);
283             for (i=0; i<no_elements; i++)
284             {
285                 if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
286                     walk_the_tree(num, xmid, next);
287             }
288
289             if (next)
290             {
291                *--next = '/';
292             }
293
294             free(xmid);
295         }
296         else printf("Error executing xmlMarkId\n");
297     }
298 }
299
300
301 void grep_file(unsigned num)
302 {
303     void *xid;
304
305     xid = xmlOpen(_filenames[num]);
306     if (xid)
307     {
308        void *xrid = xmlMarkId(xid);
309        walk_the_tree(num, xrid, _root);
310        free(xrid);
311     }
312     else
313     {
314         fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
315     }
316
317     xmlClose(xid);
318 }
319
320 int
321 main (int argc, char **argv)
322 {
323     unsigned int i;
324
325     if (argc == 1)
326         show_help();
327
328     for (i=1; i<argc;)
329     {
330         int ret = parse_option(argv, i, argc);
331         i += ret;
332     }
333
334     if (_root == 0) _root = (char *)_static_root;
335     if (_element == 0) _element = (char *)_static_element;
336
337     for (i=0; i<_fcount; i++)
338         grep_file(i);
339
340     free_and_exit(0);
341
342     return 0;
343 }