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