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