source: subversion/applications/utils/export/osm2pgsql/osm2pgsql.c @ 12445

Last change on this file since 12445 was 10464, checked in by martinvoosterhout, 12 years ago

Turns all creates into modifies for osmChange files. Technically wrong but
it matches what osmosis does and should probably be the default until the
whole snapshot thing gets sorted out.

  • Property svn:keywords set to Rev
File size: 22.2 KB
Line 
1/*
2#-----------------------------------------------------------------------------
3# osm2pgsql - converts planet.osm file into PostgreSQL
4# compatible output suitable to be rendered by mapnik
5# Use: osm2pgsql planet.osm.bz2
6#-----------------------------------------------------------------------------
7# Original Python implementation by Artem Pavlenko
8# Re-implementation by Jon Burgess, Copyright 2006
9#
10# This program is free software; you can redistribute it and/or
11# modify it under the terms of the GNU General Public License
12# as published by the Free Software Foundation; either version 2
13# of the License, or (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 General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23#-----------------------------------------------------------------------------
24*/
25
26#define _GNU_SOURCE
27#include <stdio.h>
28#include <unistd.h>
29#include <stdlib.h>
30#include <string.h>
31#include <assert.h>
32#include <getopt.h>
33
34#include <libpq-fe.h>
35
36#include <libxml/xmlstring.h>
37#include <libxml/xmlreader.h>
38
39#include "osmtypes.h"
40#include "build_geometry.h"
41#include "keyvals.h"
42#include "middle-pgsql.h"
43#include "middle-ram.h"
44#include "output-pgsql.h"
45#include "sanitizer.h"
46#include "reprojection.h"
47#include "text-tree.h"
48#include "input.h"
49#include "sprompt.h"
50
51typedef enum { FILETYPE_NONE, FILETYPE_OSM, FILETYPE_OSMCHANGE } filetypes_t;
52typedef enum { ACTION_NONE, ACTION_CREATE, ACTION_MODIFY, ACTION_DELETE } actions_t;
53
54static int count_node,    max_node;
55static int count_way,     max_way;
56static int count_rel,     max_rel;
57
58struct output_t *out;
59
60/* Since {node,way} elements are not nested we can guarantee the
61   values in an end tag must match those of the corresponding
62   start tag and can therefore be cached.
63*/
64static double node_lon, node_lat;
65static struct keyval tags;
66static int *nds;
67static int nd_count, nd_max;
68static struct member *members;
69static int member_count, member_max;
70static int osm_id;
71
72#define INIT_MAX_MEMBERS 64
73#define INIT_MAX_NODES  4096
74
75int verbose;
76static void realloc_nodes();
77static void realloc_members();
78
79// Bounding box to filter imported data
80const char *bbox = NULL;
81static double minlon, minlat, maxlon, maxlat;
82
83static void printStatus(void)
84{
85    fprintf(stderr, "\rProcessing: Node(%dk) Way(%dk) Relation(%dk)",
86            count_node/1000, count_way/1000, count_rel/1000);
87}
88
89static int parse_bbox(void)
90{
91    int n;
92
93    if (!bbox)
94        return 0;
95
96    n = sscanf(bbox, "%lf,%lf,%lf,%lf", &minlon, &minlat, &maxlon, &maxlat);
97    if (n != 4) {
98        fprintf(stderr, "Bounding box must be specified like: minlon,minlat,maxlon,maxlat\n");
99        return 1;
100    }
101    if (maxlon <= minlon) {
102        fprintf(stderr, "Bounding box failed due to maxlon <= minlon\n");
103        return 1;
104    }
105    if (maxlat <= minlat) {
106        fprintf(stderr, "Bounding box failed due to maxlat <= minlat\n");
107        return 1;
108    }
109    printf("Applying Bounding box: %f,%f to %f,%f\n", minlon,minlat,maxlon,maxlat);
110    return 0;
111}
112
113static int node_wanted(double lat, double lon)
114{
115    if (!bbox)
116        return 1;
117
118    if (lat < minlat || lat > maxlat)
119        return 0;
120    if (lon < minlon || lon > maxlon)
121        return 0;
122    return 1;
123}
124
125static filetypes_t filetype = FILETYPE_NONE;
126static actions_t action = ACTION_NONE;
127
128/* Parses the action="foo" tags in JOSM change files. Obvisouly not useful from osmChange files */
129static actions_t ParseAction( xmlTextReaderPtr reader )
130{
131    if( filetype == FILETYPE_OSMCHANGE )
132        return action;
133    actions_t new_action = ACTION_NONE;
134    xmlChar *action = xmlTextReaderGetAttribute( reader, BAD_CAST "action" );
135    if( action == NULL )
136        new_action = ACTION_CREATE;
137    else if( strcmp((char *)action, "modify") == 0 )
138        new_action = ACTION_MODIFY;
139    else if( strcmp((char *)action, "delete") == 0 )
140        new_action = ACTION_DELETE;
141    else
142    {
143        fprintf( stderr, "Unknown value for action: %s\n", (char*)action );
144        exit_nicely();
145    }
146    return new_action;
147}
148
149void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
150{
151    xmlChar *xid, *xlat, *xlon, *xk, *xv, *xrole, *xtype;
152    char *k;
153
154    if (filetype == FILETYPE_NONE)
155    {
156        if (xmlStrEqual(name, BAD_CAST "osm"))
157        {
158            filetype = FILETYPE_OSM;
159            action = ACTION_CREATE;
160        }
161        else if (xmlStrEqual(name, BAD_CAST "osmChange"))
162        {
163            filetype = FILETYPE_OSMCHANGE;
164            action = ACTION_NONE;
165        }
166        else
167        {
168            fprintf( stderr, "Unknown XML document type: %s\n", name );
169            exit_nicely();
170        }
171        return;
172    }
173   
174    if (xmlStrEqual(name, BAD_CAST "node")) {
175        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
176        xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
177        xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
178        assert(xid); assert(xlon); assert(xlat);
179
180        osm_id  = strtol((char *)xid, NULL, 10);
181        node_lon = strtod((char *)xlon, NULL);
182        node_lat = strtod((char *)xlat, NULL);
183        action = ParseAction( reader );
184
185        if (osm_id > max_node)
186            max_node = osm_id;
187
188        count_node++;
189        if (count_node%10000 == 0)
190            printStatus();
191
192        xmlFree(xid);
193        xmlFree(xlon);
194        xmlFree(xlat);
195    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
196        xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
197        assert(xk);
198
199        /* 'created_by' and 'source' are common and not interesting to mapnik renderer */
200        if (strcmp((char *)xk, "created_by") && strcmp((char *)xk, "source")) {
201            char *p;
202            xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
203            assert(xv);
204            k  = (char *)xmlStrdup(xk);
205            while ((p = strchr(k, ' ')))
206                *p = '_';
207
208            addItem(&tags, k, (char *)xv, 0);
209            xmlFree(k);
210            xmlFree(xv);
211        }
212        xmlFree(xk);
213    } else if (xmlStrEqual(name, BAD_CAST "way")) {
214        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
215        assert(xid);
216        osm_id   = strtol((char *)xid, NULL, 10);
217        action = ParseAction( reader );
218
219        if (osm_id > max_way)
220            max_way = osm_id;
221
222        count_way++;
223        if (count_way%1000 == 0)
224            printStatus();
225
226        nd_count = 0;
227        xmlFree(xid);
228    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
229        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
230        assert(xid);
231
232        nds[nd_count++] = strtol( (char *)xid, NULL, 10 );
233
234        if( nd_count >= nd_max )
235          realloc_nodes();
236        xmlFree(xid);
237    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
238        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
239        assert(xid);
240        osm_id   = strtol((char *)xid, NULL, 10);
241        action = ParseAction( reader );
242
243        if (osm_id > max_rel)
244            max_rel = osm_id;
245
246        count_rel++;
247        if (count_rel%1000 == 0)
248            printStatus();
249
250        member_count = 0;
251        xmlFree(xid);
252    } else if (xmlStrEqual(name, BAD_CAST "member")) {
253        xrole = xmlTextReaderGetAttribute(reader, BAD_CAST "role");
254        assert(xrole);
255
256        xtype = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
257        assert(xtype);
258
259        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
260        assert(xid);
261
262        members[member_count].id   = strtol( (char *)xid, NULL, 0 );
263        members[member_count].role = strdup( (char *)xrole );
264       
265        /* Currently we are only interested in 'way' members since these form polygons with holes */
266        if (xmlStrEqual(xtype, BAD_CAST "way"))
267            members[member_count].type = OSMTYPE_WAY;
268        if (xmlStrEqual(xtype, BAD_CAST "node"))
269            members[member_count].type = OSMTYPE_NODE;
270        if (xmlStrEqual(xtype, BAD_CAST "relation"))
271            members[member_count].type = OSMTYPE_RELATION;
272        member_count++;
273
274        if( member_count >= member_max )
275          realloc_members();
276        xmlFree(xid);
277        xmlFree(xrole);
278        xmlFree(xtype);
279    } else if (xmlStrEqual(name, BAD_CAST "create")) {
280        action = ACTION_CREATE;
281        action = ACTION_MODIFY; // Turns all creates into modifies, makes it resiliant against inconsistant snapshots.
282    } else if (xmlStrEqual(name, BAD_CAST "modify")) {
283        action = ACTION_MODIFY;
284    } else if (xmlStrEqual(name, BAD_CAST "delete")) {
285        action = ACTION_DELETE;
286    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
287        /* ignore */
288    } else {
289        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
290    }
291}
292
293static void resetMembers()
294{
295  int i;
296  for(i=0; i<member_count; i++ )
297    free( members[i].role );
298}
299
300void EndElement(const xmlChar *name)
301{
302    if (xmlStrEqual(name, BAD_CAST "node")) {
303        if (node_wanted(node_lat, node_lon)) {
304            reproject(&node_lat, &node_lon);
305            if( action == ACTION_CREATE )
306                out->node_add(osm_id, node_lat, node_lon, &tags);
307            else if( action == ACTION_MODIFY )
308                out->node_modify(osm_id, node_lat, node_lon, &tags);
309            else if( action == ACTION_DELETE )
310                out->node_delete(osm_id);
311            else
312            {
313                fprintf( stderr, "Don't know action for node %d\n", osm_id );
314                exit_nicely();
315            }
316        }
317        resetList(&tags);
318    } else if (xmlStrEqual(name, BAD_CAST "way")) {
319        if( action == ACTION_CREATE )
320            out->way_add(osm_id, nds, nd_count, &tags );
321        else if( action == ACTION_MODIFY )
322            out->way_modify(osm_id, nds, nd_count, &tags );
323        else if( action == ACTION_DELETE )
324            out->way_delete(osm_id);
325        else
326        {
327            fprintf( stderr, "Don't know action for way %d\n", osm_id );
328            exit_nicely();
329        }
330        resetList(&tags);
331    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
332        if( action == ACTION_CREATE )
333            out->relation_add(osm_id, members, member_count, &tags);
334        else if( action == ACTION_MODIFY )
335            out->relation_modify(osm_id, members, member_count, &tags);
336        else if( action == ACTION_DELETE )
337            out->relation_delete(osm_id);
338        else
339        {
340            fprintf( stderr, "Don't know action for relation %d\n", osm_id );
341            exit_nicely();
342        }
343        resetList(&tags);
344        resetMembers();
345    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
346        /* ignore */
347    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
348        /* ignore */
349    } else if (xmlStrEqual(name, BAD_CAST "member")) {
350        /* ignore */
351    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
352        printStatus();
353        filetype = FILETYPE_NONE;
354    } else if (xmlStrEqual(name, BAD_CAST "osmChange")) {
355        printStatus();
356        filetype = FILETYPE_NONE;
357    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
358        /* ignore */
359    } else if (xmlStrEqual(name, BAD_CAST "create")) {
360        action = ACTION_NONE;
361    } else if (xmlStrEqual(name, BAD_CAST "modify")) {
362        action = ACTION_NONE;
363    } else if (xmlStrEqual(name, BAD_CAST "delete")) {
364        action = ACTION_NONE;
365    } else {
366        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
367    }
368}
369
370static void processNode(xmlTextReaderPtr reader) {
371    xmlChar *name;
372    name = xmlTextReaderName(reader);
373    if (name == NULL)
374        name = xmlStrdup(BAD_CAST "--");
375       
376    switch(xmlTextReaderNodeType(reader)) {
377        case XML_READER_TYPE_ELEMENT:
378            StartElement(reader, name);
379            if (xmlTextReaderIsEmptyElement(reader))
380                EndElement(name); /* No end_element for self closing tags! */
381            break;
382        case XML_READER_TYPE_END_ELEMENT:
383            EndElement(name);
384            break;
385        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
386            /* Ignore */
387            break;
388        default:
389            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
390            break;
391    }
392
393    xmlFree(name);
394}
395
396static int streamFile(char *filename, int sanitize) {
397    xmlTextReaderPtr reader;
398    int ret = 0;
399
400    if (sanitize)
401        reader = sanitizerOpen(filename);
402    else
403        reader = inputUTF8(filename);
404
405    if (reader != NULL) {
406        ret = xmlTextReaderRead(reader);
407        while (ret == 1) {
408            processNode(reader);
409            ret = xmlTextReaderRead(reader);
410        }
411
412        if (ret != 0) {
413            fprintf(stderr, "%s : failed to parse\n", filename);
414            return ret;
415        }
416
417        xmlFreeTextReader(reader);
418    } else {
419        fprintf(stderr, "Unable to open %s\n", filename);
420        return 1;
421    }
422    return 0;
423}
424
425void exit_nicely(void)
426{
427    fprintf(stderr, "Error occurred, cleaning up\n");
428    out->cleanup();
429    exit(1);
430}
431 
432static void usage(const char *arg0)
433{
434    int i;
435    const char *name = basename(arg0);
436
437    fprintf(stderr, "Usage:\n");
438    fprintf(stderr, "\t%s [options] planet.osm\n", name);
439    fprintf(stderr, "\t%s [options] planet.osm.{gz,bz2}\n", name);
440    fprintf(stderr, "\t%s [options] file1.osm file2.osm file3.osm\n", name);
441    fprintf(stderr, "\nThis will import the data from the OSM file(s) into a PostgreSQL database\n");
442    fprintf(stderr, "suitable for use by the Mapnik renderer\n");
443    fprintf(stderr, "\nOptions:\n");
444    fprintf(stderr, "   -a|--append\t\tAdd the OSM file into the database without removing\n");
445    fprintf(stderr, "              \t\texisting data.\n");
446    fprintf(stderr, "   -b|--bbox\t\tApply a bounding box filter on the imported data\n");
447    fprintf(stderr, "              \t\tMust be specified as: minlon,minlat,maxlon,maxlat\n");
448    fprintf(stderr, "              \t\te.g. --bbox -0.5,51.25,0.5,51.75\n");
449    fprintf(stderr, "   -c|--create\t\tRemove existing data from the database. This is the \n");
450    fprintf(stderr, "              \t\tdefault if --append is not specified.\n");
451    fprintf(stderr, "   -d|--database\tThe name of the PostgreSQL database to connect\n");
452    fprintf(stderr, "                \tto (default: gis).\n");
453    fprintf(stderr, "   -l|--latlong\t\tStore data in degrees of latitude & longitude.\n");
454    fprintf(stderr, "   -m|--merc\t\tStore data in proper spherical mercator (default)\n");
455    fprintf(stderr, "   -M|--oldmerc\t\tStore data in the legacy OSM mercator format\n");
456    fprintf(stderr, "   -E|--proj num\tUse projection EPSG:num\n");
457    fprintf(stderr, "   -u|--utf8-sanitize\tRepair bad UTF8 input data (present in planet\n");
458    fprintf(stderr, "                \tdumps prior to August 2007). Adds about 10%% overhead.\n");
459    fprintf(stderr, "   -p|--prefix\t\tPrefix for table names (default planet_osm)\n");
460    fprintf(stderr, "   -s|--slim\t\tStore temporary data in the database. This greatly\n");
461    fprintf(stderr, "            \t\treduces the RAM usage but is much slower.\n");
462    fprintf(stderr, "   -S|--style\t\tLocation of the style file. Defaults to ./default.style\n");
463    fprintf(stderr, "   -C|--cache\t\tOnly for slim mode: Use upto this many MB for caching nodes\n");
464    fprintf(stderr, "             \t\tDefault is 800\n");
465    fprintf(stderr, "   -U|--username\tPostgresql user name.\n");
466    fprintf(stderr, "   -W|--password\tForce password prompt.\n");
467    fprintf(stderr, "   -H|--host\t\tDatabase server hostname or socket location.\n");
468    fprintf(stderr, "   -P|--port\t\tDatabase server port.\n");
469    fprintf(stderr, "   -h|--help\t\tHelp information.\n");
470    fprintf(stderr, "   -v|--verbose\t\tVerbose output.\n");
471    fprintf(stderr, "\n");
472    if(!verbose)
473    {
474        fprintf(stderr, "Add -v to display supported projections.\n");
475        fprintf(stderr, "Use -E to access any espg projections (usually in /usr/share/proj/epsg)\n" );
476    }
477    else
478    {
479        fprintf(stderr, "Supported projections:\n" );
480        for(i=0; i<PROJ_COUNT; i++ )
481        {
482            fprintf( stderr, "%-20s(%2s) SRS:%6d %s\n", 
483                    Projection_Info[i].descr, Projection_Info[i].option, Projection_Info[i].srs, Projection_Info[i].proj4text);
484        }
485    }
486}
487
488const char *build_conninfo(const char *db, const char *username, const char *password, const char *host, const char *port)
489{
490    static char conninfo[1024];
491
492    conninfo[0]='\0';
493    strcat(conninfo, "dbname='");
494    strcat(conninfo, db);
495    strcat(conninfo, "'");
496
497    if (username) {
498        strcat(conninfo, " user='");
499        strcat(conninfo, username);
500        strcat(conninfo, "'");
501    }
502    if (password) {
503        strcat(conninfo, " password='");
504        strcat(conninfo, password);
505        strcat(conninfo, "'");
506    }
507    if (host) {
508        strcat(conninfo, " host='");
509        strcat(conninfo, host);
510        strcat(conninfo, "'");
511    }
512    if (port) {
513        strcat(conninfo, " port='");
514        strcat(conninfo, port);
515        strcat(conninfo, "'");
516    }
517
518    return conninfo;
519}
520
521static void realloc_nodes()
522{
523  if( nd_max == 0 )
524    nd_max = INIT_MAX_NODES;
525  else
526    nd_max <<= 1;
527   
528  nds = realloc( nds, nd_max * sizeof( nds[0] ) );
529  if( !nds )
530  {
531    fprintf( stderr, "Failed to expand node list to %d\n", nd_max );
532    exit_nicely();
533  }
534}
535
536static void realloc_members()
537{
538  if( member_max == 0 )
539    member_max = INIT_MAX_NODES;
540  else
541    member_max <<= 1;
542   
543  members = realloc( members, member_max * sizeof( members[0] ) );
544  if( !members )
545  {
546    fprintf( stderr, "Failed to expand member list to %d\n", member_max );
547    exit_nicely();
548  }
549}
550
551int main(int argc, char *argv[])
552{
553    int append=0;
554    int create=0;
555    int slim=0;
556    int sanitize=0;
557    int pass_prompt=0;
558    int projection = PROJ_SPHERE_MERC;
559    const char *db = "gis";
560    const char *username=NULL;
561    const char *host=NULL;
562    const char *password=NULL;
563    const char *port = "5432";
564    const char *conninfo = NULL;
565    const char *prefix = "planet_osm";
566    const char *style = "./default.style";
567    int cache = 800;
568    struct output_options options;
569    PGconn *sql_conn;
570
571    fprintf(stderr, "osm2pgsql SVN version %s $Rev: 10464 $ \n\n", VERSION);
572
573    while (1) {
574        int c, option_index = 0;
575        static struct option long_options[] = {
576            {"append",   0, 0, 'a'},
577            {"bbox",     1, 0, 'b'},
578            {"create",   0, 0, 'c'},
579            {"database", 1, 0, 'd'},
580            {"latlong",  0, 0, 'l'},
581            {"verbose",  0, 0, 'v'},
582            {"slim",     0, 0, 's'},
583            {"prefix",   1, 0, 'p'},
584            {"proj",     1, 0, 'E'},
585            {"merc",     0, 0, 'm'},
586            {"oldmerc",  0, 0, 'M'},
587            {"utf8-sanitize", 0, 0, 'u'},
588            {"cache",    1, 0, 'C'},
589            {"username", 1, 0, 'U'},
590            {"password", 0, 0, 'W'},
591            {"host",     1, 0, 'H'},
592            {"port",     1, 0, 'P'},
593            {"help",     0, 0, 'h'},
594            {"style",    1, 0, 'S'},
595            {0, 0, 0, 0}
596        };
597
598        c = getopt_long (argc, argv, "ab:cd:hlmMp:suvU:WH:P:E:C:S:", long_options, &option_index);
599        if (c == -1)
600            break;
601
602        switch (c) {
603            case 'a': append=1;   break;
604            case 'b': bbox=optarg; break;
605            case 'c': create=1;   break;
606            case 'v': verbose=1;  break;
607            case 's': slim=1;     break;
608            case 'u': sanitize=1; break;
609            case 'l': projection=PROJ_LATLONG;  break;
610            case 'm': projection=PROJ_SPHERE_MERC; break;
611            case 'M': projection=PROJ_MERC; break;
612            case 'E': projection=-atoi(optarg); break;
613            case 'p': prefix=optarg; break;
614            case 'd': db=optarg;  break;
615            case 'C': cache = atoi(optarg); break;
616            case 'U': username=optarg; break;
617            case 'W': pass_prompt=1; break;
618            case 'H': host=optarg; break;
619            case 'P': port=optarg; break;
620            case 'S': style=optarg; break;
621
622            case 'h':
623            case '?':
624            default:
625                usage(argv[0]);
626                exit(EXIT_FAILURE);
627        }
628    }
629
630    if (argc == optind) {  // No non-switch arguments
631        usage(argv[0]);
632        exit(EXIT_FAILURE);
633    }
634
635    if (append && create) {
636        fprintf(stderr, "Error: --append and --create options can not be used at the same time!\n");
637        exit(EXIT_FAILURE);
638    }
639   
640    if( cache < 0 ) cache = 0;
641
642    if (pass_prompt)
643        password = simple_prompt("Password:", 100, 0);
644
645    conninfo = build_conninfo(db, username, password, host, port);
646    sql_conn = PQconnectdb(conninfo);
647    if (PQstatus(sql_conn) != CONNECTION_OK) {
648        fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(sql_conn));
649        exit(EXIT_FAILURE);
650    }
651    PQfinish(sql_conn);
652
653    text_init();
654    initList(&tags);
655
656    count_node = max_node = 0;
657    count_way = max_way = 0;
658    count_rel = max_rel = 0;
659
660    LIBXML_TEST_VERSION
661
662    project_init(projection);
663    fprintf(stderr, "Using projection SRS %d (%s)\n", 
664        project_getprojinfo()->srs, project_getprojinfo()->descr );
665
666    if (parse_bbox())
667        return 1;
668
669    options.conninfo = conninfo;
670    options.prefix = prefix;
671    options.append = append;
672    options.slim = slim;
673    options.projection = project_getprojinfo()->srs;
674    options.scale = (projection==PROJ_LATLONG)?10000000:100;
675    options.mid = slim ? &mid_pgsql : &mid_ram;
676    options.cache = cache;
677    options.style = style;
678    out = &out_pgsql;
679
680    out->start(&options);
681
682    realloc_nodes();
683    realloc_members();
684
685    while (optind < argc) {
686        fprintf(stderr, "\nReading in file: %s\n", argv[optind]);
687        if (streamFile(argv[optind], sanitize) != 0)
688            exit_nicely();
689        optind++;
690    }
691
692    xmlCleanupParser();
693    xmlMemoryDump();
694   
695    if (count_node || count_way || count_rel) {
696        fprintf(stderr, "\n");
697        fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
698        fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
699        fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
700    }
701    out->stop();
702   
703    free(nds);
704    free(members);
705
706    project_exit();
707    text_exit();
708    fprintf(stderr, "\n");
709
710    return 0;
711}
Note: See TracBrowser for help on using the repository browser.