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