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