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