Imported Upstream version 1.5
[routino] / src / tagmodifier.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/tagmodifier.c,v 1.7 2010/09/05 18:26:01 amb Exp $
3
4  Test application for OSM XML file parser / tagging rule testing.
5
6  Part of the Routino routing software.
7  ******************/ /******************
8  This file Copyright 2010 Andrew M. Bishop
9
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Affero General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU Affero General Public License for more details.
19
20  You should have received a copy of the GNU Affero General Public License
21  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  ***************************************/
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <errno.h>
30
31 #include "files.h"
32 #include "xmlparse.h"
33 #include "tagging.h"
34
35
36 /* Local variables */
37
38 static long nnodes=0,nways=0,nrelations=0;
39 TagList *current_tags=NULL;
40
41
42 /* Local functions */
43
44 static void print_usage(int detail);
45
46
47 /* The XML tag processing function prototypes */
48
49 static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
50 static int osmType_function(const char *_tag_,int _type_,const char *version,const char *generator);
51 static int relationType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action);
52 static int wayType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action);
53 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
54 static int ndType_function(const char *_tag_,int _type_,const char *ref);
55 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action);
56 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
57 static int boundType_function(const char *_tag_,int _type_,const char *box,const char *origin);
58 static int boundsType_function(const char *_tag_,int _type_,const char *minlat,const char *minlon,const char *maxlat,const char *maxlon,const char *origin);
59
60
61 /* The XML tag definitions */
62
63 /*+ The boundsType type tag. +*/
64 static xmltag boundsType_tag=
65               {"bounds",
66                5, {"minlat","minlon","maxlat","maxlon","origin"},
67                boundsType_function,
68                {NULL}};
69
70 /*+ The boundType type tag. +*/
71 static xmltag boundType_tag=
72               {"bound",
73                2, {"box","origin"},
74                boundType_function,
75                {NULL}};
76
77 /*+ The tagType type tag. +*/
78 static xmltag tagType_tag=
79               {"tag",
80                2, {"k","v"},
81                tagType_function,
82                {NULL}};
83
84 /*+ The nodeType type tag. +*/
85 static xmltag nodeType_tag=
86               {"node",
87                9, {"id","lat","lon","timestamp","uid","user","visible","version","action"},
88                nodeType_function,
89                {&tagType_tag,NULL}};
90
91 /*+ The ndType type tag. +*/
92 static xmltag ndType_tag=
93               {"nd",
94                1, {"ref"},
95                ndType_function,
96                {NULL}};
97
98 /*+ The memberType type tag. +*/
99 static xmltag memberType_tag=
100               {"member",
101                3, {"type","ref","role"},
102                memberType_function,
103                {NULL}};
104
105 /*+ The wayType type tag. +*/
106 static xmltag wayType_tag=
107               {"way",
108                7, {"id","timestamp","uid","user","visible","version","action"},
109                wayType_function,
110                {&ndType_tag,&tagType_tag,NULL}};
111
112 /*+ The relationType type tag. +*/
113 static xmltag relationType_tag=
114               {"relation",
115                7, {"id","timestamp","uid","user","visible","version","action"},
116                relationType_function,
117                {&memberType_tag,&tagType_tag,NULL}};
118
119 /*+ The osmType type tag. +*/
120 static xmltag osmType_tag=
121               {"osm",
122                2, {"version","generator"},
123                osmType_function,
124                {&boundsType_tag,&boundType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
125
126 /*+ The xmlDeclaration type tag. +*/
127 static xmltag xmlDeclaration_tag=
128               {"xml",
129                2, {"version","encoding"},
130                xmlDeclaration_function,
131                {NULL}};
132
133
134 /*+ The complete set of tags at the top level. +*/
135 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
136
137
138 /* The XML tag processing functions */
139
140
141 /*++++++++++++++++++++++++++++++++++++++
142   The function that is called when the boundsType XSD type is seen
143
144   int boundsType_function Returns 0 if no error occured or something else otherwise.
145
146   const char *_tag_ Set to the name of the element tag that triggered this function call.
147
148   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
149
150   const char *minlat The contents of the 'minlat' attribute (or NULL if not defined).
151
152   const char *minlon The contents of the 'minlon' attribute (or NULL if not defined).
153
154   const char *maxlat The contents of the 'maxlat' attribute (or NULL if not defined).
155
156   const char *maxlon The contents of the 'maxlon' attribute (or NULL if not defined).
157
158   const char *origin The contents of the 'origin' attribute (or NULL if not defined).
159   ++++++++++++++++++++++++++++++++++++++*/
160
161 static int boundsType_function(const char *_tag_,int _type_,const char *minlat,const char *minlon,const char *maxlat,const char *maxlon,const char *origin)
162 {
163  printf("  <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
164  if(minlat) printf(" minlat=\"%s\"",ParseXML_Encode_Safe_XML(minlat));
165  if(minlon) printf(" minlon=\"%s\"",ParseXML_Encode_Safe_XML(minlon));
166  if(maxlat) printf(" maxlat=\"%s\"",ParseXML_Encode_Safe_XML(maxlat));
167  if(maxlon) printf(" maxlon=\"%s\"",ParseXML_Encode_Safe_XML(maxlon));
168  if(origin) printf(" origin=\"%s\"",ParseXML_Encode_Safe_XML(origin));
169  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
170  return(0);
171 }
172
173
174 /*++++++++++++++++++++++++++++++++++++++
175   The function that is called when the boundType XSD type is seen
176
177   int boundType_function Returns 0 if no error occured or something else otherwise.
178
179   const char *_tag_ Set to the name of the element tag that triggered this function call.
180
181   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
182
183   const char *box The contents of the 'box' attribute (or NULL if not defined).
184
185   const char *origin The contents of the 'origin' attribute (or NULL if not defined).
186   ++++++++++++++++++++++++++++++++++++++*/
187
188 static int boundType_function(const char *_tag_,int _type_,const char *box,const char *origin)
189 {
190  printf("  <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
191  if(box) printf(" box=\"%s\"",ParseXML_Encode_Safe_XML(box));
192  if(origin) printf(" origin=\"%s\"",ParseXML_Encode_Safe_XML(origin));
193  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
194  return(0);
195 }
196
197
198 /*++++++++++++++++++++++++++++++++++++++
199   The function that is called when the tagType XSD type is seen
200
201   int tagType_function Returns 0 if no error occured or something else otherwise.
202
203   const char *_tag_ Set to the name of the element tag that triggered this function call.
204
205   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
206
207   const char *k The contents of the 'k' attribute (or NULL if not defined).
208
209   const char *v The contents of the 'v' attribute (or NULL if not defined).
210   ++++++++++++++++++++++++++++++++++++++*/
211
212 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
213 {
214  if(_type_&XMLPARSE_TAG_START)
215    {
216     XMLPARSE_ASSERT_STRING(_tag_,k);
217     XMLPARSE_ASSERT_STRING(_tag_,v);
218
219     AppendTag(current_tags,k,v);
220    }
221
222  return(0);
223 }
224
225
226 /*++++++++++++++++++++++++++++++++++++++
227   The function that is called when the nodeType XSD type is seen
228
229   int nodeType_function Returns 0 if no error occured or something else otherwise.
230
231   const char *_tag_ Set to the name of the element tag that triggered this function call.
232
233   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
234
235   const char *id The contents of the 'id' attribute (or NULL if not defined).
236
237   const char *lat The contents of the 'lat' attribute (or NULL if not defined).
238
239   const char *lon The contents of the 'lon' attribute (or NULL if not defined).
240
241   const char *timestamp The contents of the 'timestamp' attribute (or NULL if not defined).
242
243   const char *uid The contents of the 'uid' attribute (or NULL if not defined).
244
245   const char *user The contents of the 'user' attribute (or NULL if not defined).
246
247   const char *visible The contents of the 'visible' attribute (or NULL if not defined).
248
249   const char *version The contents of the 'version' attribute (or NULL if not defined).
250
251   const char *action The contents of the 'action' attribute (or NULL if not defined).
252   ++++++++++++++++++++++++++++++++++++++*/
253
254 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action)
255 {
256  if(_type_&XMLPARSE_TAG_START)
257    {
258     nnodes++;
259
260     if(!(nnodes%1000))
261        fprintf(stderr,"\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
262
263     current_tags=NewTagList();
264    }
265
266  if(_type_&XMLPARSE_TAG_END)
267    {
268     TagList *result=ApplyTaggingRules(&NodeRules,current_tags);
269     int i;
270
271     for(i=0;i<result->ntags;i++)
272       {
273        printf("    <tag");
274        printf(" k=\"%s\"",ParseXML_Encode_Safe_XML(result->k[i]));
275        printf(" v=\"%s\"",ParseXML_Encode_Safe_XML(result->v[i]));
276        printf(" />\n");
277       }
278
279     DeleteTagList(current_tags);
280     DeleteTagList(result);
281    }
282
283  printf("  <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
284  if(id) printf(" id=\"%s\"",ParseXML_Encode_Safe_XML(id));
285  if(lat) printf(" lat=\"%s\"",ParseXML_Encode_Safe_XML(lat));
286  if(lon) printf(" lon=\"%s\"",ParseXML_Encode_Safe_XML(lon));
287  if(timestamp) printf(" timestamp=\"%s\"",ParseXML_Encode_Safe_XML(timestamp));
288  if(uid) printf(" uid=\"%s\"",ParseXML_Encode_Safe_XML(uid));
289  if(user) printf(" user=\"%s\"",ParseXML_Encode_Safe_XML(user));
290  if(visible) printf(" visible=\"%s\"",ParseXML_Encode_Safe_XML(visible));
291  if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
292  if(action) printf(" action=\"%s\"",ParseXML_Encode_Safe_XML(action));
293  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
294  return(0);
295 }
296
297
298 /*++++++++++++++++++++++++++++++++++++++
299   The function that is called when the ndType XSD type is seen
300
301   int ndType_function Returns 0 if no error occured or something else otherwise.
302
303   const char *_tag_ Set to the name of the element tag that triggered this function call.
304
305   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
306
307   const char *ref The contents of the 'ref' attribute (or NULL if not defined).
308   ++++++++++++++++++++++++++++++++++++++*/
309
310 static int ndType_function(const char *_tag_,int _type_,const char *ref)
311 {
312  printf("    <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
313  if(ref) printf(" ref=\"%s\"",ParseXML_Encode_Safe_XML(ref));
314  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
315  return(0);
316 }
317
318
319 /*++++++++++++++++++++++++++++++++++++++
320   The function that is called when the memberType XSD type is seen
321
322   int memberType_function Returns 0 if no error occured or something else otherwise.
323
324   const char *_tag_ Set to the name of the element tag that triggered this function call.
325
326   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
327
328   const char *type The contents of the 'type' attribute (or NULL if not defined).
329
330   const char *ref The contents of the 'ref' attribute (or NULL if not defined).
331
332   const char *role The contents of the 'role' attribute (or NULL if not defined).
333   ++++++++++++++++++++++++++++++++++++++*/
334
335 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
336 {
337  printf("    <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
338  if(type) printf(" type=\"%s\"",ParseXML_Encode_Safe_XML(type));
339  if(ref) printf(" ref=\"%s\"",ParseXML_Encode_Safe_XML(ref));
340  if(role) printf(" role=\"%s\"",ParseXML_Encode_Safe_XML(role));
341  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
342  return(0);
343 }
344
345
346 /*++++++++++++++++++++++++++++++++++++++
347   The function that is called when the wayType XSD type is seen
348
349   int wayType_function Returns 0 if no error occured or something else otherwise.
350
351   const char *_tag_ Set to the name of the element tag that triggered this function call.
352
353   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
354
355   const char *id The contents of the 'id' attribute (or NULL if not defined).
356
357   const char *timestamp The contents of the 'timestamp' attribute (or NULL if not defined).
358
359   const char *uid The contents of the 'uid' attribute (or NULL if not defined).
360
361   const char *user The contents of the 'user' attribute (or NULL if not defined).
362
363   const char *visible The contents of the 'visible' attribute (or NULL if not defined).
364
365   const char *version The contents of the 'version' attribute (or NULL if not defined).
366
367   const char *action The contents of the 'action' attribute (or NULL if not defined).
368   ++++++++++++++++++++++++++++++++++++++*/
369
370 static int wayType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action)
371 {
372  if(_type_&XMLPARSE_TAG_START)
373    {
374     nways++;
375
376     if(!(nways%1000))
377        fprintf(stderr,"\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
378
379     current_tags=NewTagList();
380    }
381
382  if(_type_&XMLPARSE_TAG_END)
383    {
384     TagList *result=ApplyTaggingRules(&WayRules,current_tags);
385     int i;
386
387     for(i=0;i<result->ntags;i++)
388       {
389        printf("    <tag");
390        printf(" k=\"%s\"",ParseXML_Encode_Safe_XML(result->k[i]));
391        printf(" v=\"%s\"",ParseXML_Encode_Safe_XML(result->v[i]));
392        printf(" />\n");
393       }
394
395     DeleteTagList(current_tags);
396     DeleteTagList(result);
397    }
398
399  printf("  <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
400  if(id) printf(" id=\"%s\"",ParseXML_Encode_Safe_XML(id));
401  if(timestamp) printf(" timestamp=\"%s\"",ParseXML_Encode_Safe_XML(timestamp));
402  if(uid) printf(" uid=\"%s\"",ParseXML_Encode_Safe_XML(uid));
403  if(user) printf(" user=\"%s\"",ParseXML_Encode_Safe_XML(user));
404  if(visible) printf(" visible=\"%s\"",ParseXML_Encode_Safe_XML(visible));
405  if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
406  if(action) printf(" action=\"%s\"",ParseXML_Encode_Safe_XML(action));
407  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
408  return(0);
409 }
410
411
412 /*++++++++++++++++++++++++++++++++++++++
413   The function that is called when the relationType XSD type is seen
414
415   int relationType_function Returns 0 if no error occured or something else otherwise.
416
417   const char *_tag_ Set to the name of the element tag that triggered this function call.
418
419   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
420
421   const char *id The contents of the 'id' attribute (or NULL if not defined).
422
423   const char *timestamp The contents of the 'timestamp' attribute (or NULL if not defined).
424
425   const char *uid The contents of the 'uid' attribute (or NULL if not defined).
426
427   const char *user The contents of the 'user' attribute (or NULL if not defined).
428
429   const char *visible The contents of the 'visible' attribute (or NULL if not defined).
430
431   const char *version The contents of the 'version' attribute (or NULL if not defined).
432
433   const char *action The contents of the 'action' attribute (or NULL if not defined).
434   ++++++++++++++++++++++++++++++++++++++*/
435
436 static int relationType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action)
437 {
438  if(_type_&XMLPARSE_TAG_START)
439    {
440     nrelations++;
441
442     if(!(nrelations%1000))
443        fprintf(stderr,"\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
444
445     current_tags=NewTagList();
446    }
447
448  if(_type_&XMLPARSE_TAG_END)
449    {
450     TagList *result=ApplyTaggingRules(&RelationRules,current_tags);
451     int i;
452
453     for(i=0;i<result->ntags;i++)
454       {
455        printf("    <tag");
456        printf(" k=\"%s\"",ParseXML_Encode_Safe_XML(result->k[i]));
457        printf(" v=\"%s\"",ParseXML_Encode_Safe_XML(result->v[i]));
458        printf(" />\n");
459       }
460
461     DeleteTagList(current_tags);
462     DeleteTagList(result);
463    }
464
465  printf("  <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
466  if(id) printf(" id=\"%s\"",ParseXML_Encode_Safe_XML(id));
467  if(timestamp) printf(" timestamp=\"%s\"",ParseXML_Encode_Safe_XML(timestamp));
468  if(uid) printf(" uid=\"%s\"",ParseXML_Encode_Safe_XML(uid));
469  if(user) printf(" user=\"%s\"",ParseXML_Encode_Safe_XML(user));
470  if(visible) printf(" visible=\"%s\"",ParseXML_Encode_Safe_XML(visible));
471  if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
472  if(action) printf(" action=\"%s\"",ParseXML_Encode_Safe_XML(action));
473  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
474  return(0);
475 }
476
477
478 /*++++++++++++++++++++++++++++++++++++++
479   The function that is called when the osmType XSD type is seen
480
481   int osmType_function Returns 0 if no error occured or something else otherwise.
482
483   const char *_tag_ Set to the name of the element tag that triggered this function call.
484
485   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
486
487   const char *version The contents of the 'version' attribute (or NULL if not defined).
488
489   const char *generator The contents of the 'generator' attribute (or NULL if not defined).
490   ++++++++++++++++++++++++++++++++++++++*/
491
492 static int osmType_function(const char *_tag_,int _type_,const char *version,const char *generator)
493 {
494  printf("<%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
495  if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
496  if(generator) printf(" generator=\"%s\"",ParseXML_Encode_Safe_XML(generator));
497  printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
498  return(0);
499 }
500
501
502 /*++++++++++++++++++++++++++++++++++++++
503   The function that is called when the XML declaration is seen
504
505   int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
506
507   const char *_tag_ Set to the name of the element tag that triggered this function call.
508
509   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
510
511   const char *version The contents of the 'version' attribute (or NULL if not defined).
512
513   const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
514   ++++++++++++++++++++++++++++++++++++++*/
515
516 static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
517 {
518  printf("<?%s",_tag_);
519  if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
520  if(encoding) printf(" encoding=\"%s\"",ParseXML_Encode_Safe_XML(encoding));
521  printf(" ?>\n");
522  return(0);
523 }
524
525
526 /*++++++++++++++++++++++++++++++++++++++
527   The main program for the planetsplitter.
528   ++++++++++++++++++++++++++++++++++++++*/
529
530 int main(int argc,char **argv)
531 {
532  char *tagging=NULL,*filename=NULL;
533  FILE *file;
534  int arg,retval;
535
536  /* Parse the command line arguments */
537
538  for(arg=1;arg<argc;arg++)
539    {
540     if(!strcmp(argv[arg],"--help"))
541        print_usage(1);
542     else if(!strncmp(argv[arg],"--tagging=",10))
543        tagging=&argv[arg][10];
544     else if(argv[arg][0]=='-' && argv[arg][1]=='-')
545        print_usage(0);
546     else if(filename)
547        print_usage(0);
548     else
549        filename=argv[arg];
550    }
551
552  /* Check the specified command line options */
553
554  if(tagging)
555    {
556     if(!ExistsFile(tagging))
557       {
558        fprintf(stderr,"Error: The '--tagging' option specifies a file that does not exist.\n");
559        return(1);
560       }
561    }
562  else
563    {
564     if(ExistsFile("tagging.xml"))
565        tagging="tagging.xml";
566     else
567       {
568        fprintf(stderr,"Error: The '--tagging' option was not used and the default 'tagging.xml' does not exist.\n");
569        return(1);
570       }
571    }
572
573  if(ParseXMLTaggingRules(tagging))
574    {
575     fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
576     return(1);
577    }
578
579  /* Open the input file */
580
581  if(filename)
582    {
583     file=fopen(filename,"rb");
584
585     if(!file)
586       {
587        fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",argv[arg],strerror(errno));
588        exit(EXIT_FAILURE);
589       }
590    }
591  else
592     file=stdin;
593
594  /* Parse the file */
595
596  fprintf(stderr,"\rReading: Lines=0 Nodes=0 Ways=0 Relations=0");
597
598  retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
599
600  fprintf(stderr,"\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld   \n",ParseXML_LineNumber(),nnodes,nways,nrelations);
601
602  /* Tidy up */
603
604  if(filename)
605     fclose(file);
606
607  return(retval);
608 }
609
610
611 /*++++++++++++++++++++++++++++++++++++++
612   Print out the usage information.
613
614   int detail The level of detail to use - 0 = low, 1 = high.
615   ++++++++++++++++++++++++++++++++++++++*/
616
617 static void print_usage(int detail)
618 {
619  fprintf(stderr,
620          "Usage: tagmodifier [--help]\n"
621          "                   [--tagging=<filename>]\n"
622          "                   [<filename.osm>]\n");
623
624  if(detail)
625     fprintf(stderr,
626             "\n"
627             "--help                    Prints this information.\n"
628             "\n"
629             "--tagging=<filename>      The name of the XML file containing the tagging rules\n"
630             "                          (defaults to 'tagging.xml' in current directory).\n"
631             "\n"
632             "<filename.osm>            The name of the file to process (by default data is\n"
633             "                          read from standard input).\n");
634
635  exit(!detail);
636 }