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

Last change on this file since 9211 was 9211, checked in by tomhughes, 12 years ago

Only prompt for a password if -W/--password is given. This is what
psql does and it allows for implicit authentication as a different
user using -U without -W.

  • Property svn:keywords set to Rev
File size: 21.8 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    } else if (xmlStrEqual(name, BAD_CAST "modify")) {
282        action = ACTION_MODIFY;
283    } else if (xmlStrEqual(name, BAD_CAST "delete")) {
284        action = ACTION_DELETE;
285    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
286        /* ignore */
287    } else {
288        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
289    }
290}
291
292static void resetMembers()
293{
294  int i;
295  for(i=0; i<member_count; i++ )
296    free( members[i].role );
297}
298
299void EndElement(const xmlChar *name)
300{
301    if (xmlStrEqual(name, BAD_CAST "node")) {
302        if (node_wanted(node_lat, node_lon)) {
303            reproject(&node_lat, &node_lon);
304            if( action == ACTION_CREATE )
305                out->node_add(osm_id, node_lat, node_lon, &tags);
306            else if( action == ACTION_MODIFY )
307                out->node_modify(osm_id, node_lat, node_lon, &tags);
308            else if( action == ACTION_DELETE )
309                out->node_delete(osm_id);
310            else
311            {
312                fprintf( stderr, "Don't know action for node %d\n", osm_id );
313                exit_nicely();
314            }
315        }
316        resetList(&tags);
317    } else if (xmlStrEqual(name, BAD_CAST "way")) {
318        if( action == ACTION_CREATE )
319            out->way_add(osm_id, nds, nd_count, &tags );
320        else if( action == ACTION_MODIFY )
321            out->way_modify(osm_id, nds, nd_count, &tags );
322        else if( action == ACTION_DELETE )
323            out->way_delete(osm_id);
324        else
325        {
326            fprintf( stderr, "Don't know action for way %d\n", osm_id );
327            exit_nicely();
328        }
329        resetList(&tags);
330    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
331        if( action == ACTION_CREATE )
332            out->relation_add(osm_id, members, member_count, &tags);
333        else if( action == ACTION_MODIFY )
334            out->relation_modify(osm_id, members, member_count, &tags);
335        else if( action == ACTION_DELETE )
336            out->relation_delete(osm_id);
337        else
338        {
339            fprintf( stderr, "Don't know action for relation %d\n", osm_id );
340            exit_nicely();
341        }
342        resetList(&tags);
343        resetMembers();
344    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
345        /* ignore */
346    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
347        /* ignore */
348    } else if (xmlStrEqual(name, BAD_CAST "member")) {
349        /* ignore */
350    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
351        printStatus();
352        filetype = FILETYPE_NONE;
353    } else if (xmlStrEqual(name, BAD_CAST "osmChange")) {
354        printStatus();
355        filetype = FILETYPE_NONE;
356    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
357        /* ignore */
358    } else if (xmlStrEqual(name, BAD_CAST "create")) {
359        action = ACTION_NONE;
360    } else if (xmlStrEqual(name, BAD_CAST "modify")) {
361        action = ACTION_NONE;
362    } else if (xmlStrEqual(name, BAD_CAST "delete")) {
363        action = ACTION_NONE;
364    } else {
365        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
366    }
367}
368
369static void processNode(xmlTextReaderPtr reader) {
370    xmlChar *name;
371    name = xmlTextReaderName(reader);
372    if (name == NULL)
373        name = xmlStrdup(BAD_CAST "--");
374       
375    switch(xmlTextReaderNodeType(reader)) {
376        case XML_READER_TYPE_ELEMENT:
377            StartElement(reader, name);
378            if (xmlTextReaderIsEmptyElement(reader))
379                EndElement(name); /* No end_element for self closing tags! */
380            break;
381        case XML_READER_TYPE_END_ELEMENT:
382            EndElement(name);
383            break;
384        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
385            /* Ignore */
386            break;
387        default:
388            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
389            break;
390    }
391
392    xmlFree(name);
393}
394
395static int streamFile(char *filename, int sanitize) {
396    xmlTextReaderPtr reader;
397    int ret = 0;
398
399    if (sanitize)
400        reader = sanitizerOpen(filename);
401    else
402        reader = inputUTF8(filename);
403
404    if (reader != NULL) {
405        ret = xmlTextReaderRead(reader);
406        while (ret == 1) {
407            processNode(reader);
408            ret = xmlTextReaderRead(reader);
409        }
410
411        if (ret != 0) {
412            fprintf(stderr, "%s : failed to parse\n", filename);
413            return ret;
414        }
415
416        xmlFreeTextReader(reader);
417    } else {
418        fprintf(stderr, "Unable to open %s\n", filename);
419        return 1;
420    }
421    return 0;
422}
423
424void exit_nicely(void)
425{
426    fprintf(stderr, "Error occurred, cleaning up\n");
427    out->cleanup();
428    exit(1);
429}
430 
431static void usage(const char *arg0)
432{
433    int i;
434    const char *name = basename(arg0);
435
436    fprintf(stderr, "Usage:\n");
437    fprintf(stderr, "\t%s [options] planet.osm\n", name);
438    fprintf(stderr, "\t%s [options] planet.osm.{gz,bz2}\n", name);
439    fprintf(stderr, "\t%s [options] file1.osm file2.osm file3.osm\n", name);
440    fprintf(stderr, "\nThis will import the data from the OSM file(s) into a PostgreSQL database\n");
441    fprintf(stderr, "suitable for use by the Mapnik renderer\n");
442    fprintf(stderr, "\nOptions:\n");
443    fprintf(stderr, "   -a|--append\t\tAdd the OSM file into the database without removing\n");
444    fprintf(stderr, "              \t\texisting data.\n");
445    fprintf(stderr, "   -b|--bbox\t\tApply a bounding box filter on the imported data\n");
446    fprintf(stderr, "              \t\tMust be specified as: minlon,minlat,maxlon,maxlat\n");
447    fprintf(stderr, "              \t\te.g. --bbox -0.5,51.25,0.5,51.75\n");
448    fprintf(stderr, "   -c|--create\t\tRemove existing data from the database. This is the \n");
449    fprintf(stderr, "              \t\tdefault if --append is not specified.\n");
450    fprintf(stderr, "   -d|--database\tThe name of the PostgreSQL database to connect\n");
451    fprintf(stderr, "                \tto (default: gis).\n");
452    fprintf(stderr, "   -l|--latlong\t\tStore data in degrees of latitude & longitude.\n");
453    fprintf(stderr, "   -m|--merc\t\tStore data in proper spherical mercator (default)\n");
454    fprintf(stderr, "   -M|--oldmerc\t\tStore data in the legacy OSM mercator format\n");
455    fprintf(stderr, "   -E|--proj num\tUse projection EPSG:num\n");
456    fprintf(stderr, "   -u|--utf8-sanitize\tRepair bad UTF8 input data (present in planet\n");
457    fprintf(stderr, "                \tdumps prior to August 2007). Adds about 10%% overhead.\n");
458    fprintf(stderr, "   -p|--prefix\t\tPrefix for table names (default planet_osm)\n");
459    fprintf(stderr, "   -s|--slim\t\tStore temporary data in the database. This greatly\n");
460    fprintf(stderr, "            \t\treduces the RAM usage but is much slower.\n");
461    fprintf(stderr, "   -C|--cache\t\tOnly for slim mode: Use upto this many MB for caching nodes\n");
462    fprintf(stderr, "             \t\tDefault is 800\n");
463    fprintf(stderr, "   -U|--username\tPostgresql user name.\n");
464    fprintf(stderr, "   -W|--password\tForce password prompt.\n");
465    fprintf(stderr, "   -H|--host\t\tDatabase server hostname or socket location.\n");
466    fprintf(stderr, "   -P|--port\t\tDatabase server port.\n");
467    fprintf(stderr, "   -h|--help\t\tHelp information.\n");
468    fprintf(stderr, "   -v|--verbose\t\tVerbose output.\n");
469    fprintf(stderr, "\n");
470    if(!verbose)
471    {
472        fprintf(stderr, "Add -v to display supported projections.\n");
473        fprintf(stderr, "Use -E to access any espg projections (usually in /usr/share/proj/epsg)\n" );
474    }
475    else
476    {
477        fprintf(stderr, "Supported projections:\n" );
478        for(i=0; i<PROJ_COUNT; i++ )
479        {
480            fprintf( stderr, "%-20s(%2s) SRS:%6d %s\n", 
481                    Projection_Info[i].descr, Projection_Info[i].option, Projection_Info[i].srs, Projection_Info[i].proj4text);
482        }
483    }
484}
485
486const char *build_conninfo(const char *db, const char *username, const char *password, const char *host, const char *port)
487{
488    static char conninfo[1024];
489
490    conninfo[0]='\0';
491    strcat(conninfo, "dbname='");
492    strcat(conninfo, db);
493    strcat(conninfo, "'");
494
495    if (username) {
496        strcat(conninfo, " user='");
497        strcat(conninfo, username);
498        strcat(conninfo, "'");
499    }
500    if (password) {
501        strcat(conninfo, " password='");
502        strcat(conninfo, password);
503        strcat(conninfo, "'");
504    }
505    if (host) {
506        strcat(conninfo, " host='");
507        strcat(conninfo, host);
508        strcat(conninfo, "'");
509    }
510    if (port) {
511        strcat(conninfo, " port='");
512        strcat(conninfo, port);
513        strcat(conninfo, "'");
514    }
515
516    return conninfo;
517}
518
519static void realloc_nodes()
520{
521  if( nd_max == 0 )
522    nd_max = INIT_MAX_NODES;
523  else
524    nd_max <<= 1;
525   
526  nds = realloc( nds, nd_max * sizeof( nds[0] ) );
527  if( !nds )
528  {
529    fprintf( stderr, "Failed to expand node list to %d\n", nd_max );
530    exit_nicely();
531  }
532}
533
534static void realloc_members()
535{
536  if( member_max == 0 )
537    member_max = INIT_MAX_NODES;
538  else
539    member_max <<= 1;
540   
541  members = realloc( members, member_max * sizeof( members[0] ) );
542  if( !members )
543  {
544    fprintf( stderr, "Failed to expand member list to %d\n", member_max );
545    exit_nicely();
546  }
547}
548
549int main(int argc, char *argv[])
550{
551    int append=0;
552    int create=0;
553    int slim=0;
554    int sanitize=0;
555    int pass_prompt=0;
556    int projection = PROJ_SPHERE_MERC;
557    const char *db = "gis";
558    const char *username=NULL;
559    const char *host=NULL;
560    const char *password=NULL;
561    const char *port = "5432";
562    const char *conninfo = NULL;
563    const char *prefix = "planet_osm";
564    int cache = 800;
565    struct output_options options;
566    PGconn *sql_conn;
567
568    fprintf(stderr, "osm2pgsql SVN version %s $Rev: 9211 $ \n\n", VERSION);
569
570    while (1) {
571        int c, option_index = 0;
572        static struct option long_options[] = {
573            {"append",   0, 0, 'a'},
574            {"bbox",     1, 0, 'b'},
575            {"create",   0, 0, 'c'},
576            {"database", 1, 0, 'd'},
577            {"latlong",  0, 0, 'l'},
578            {"verbose",  0, 0, 'v'},
579            {"slim",     0, 0, 's'},
580            {"prefix",   1, 0, 'p'},
581            {"proj",     1, 0, 'E'},
582            {"merc",     0, 0, 'm'},
583            {"oldmerc",  0, 0, 'M'},
584            {"utf8-sanitize", 0, 0, 'u'},
585            {"cache",    1, 0, 'C'},
586            {"username", 1, 0, 'U'},
587            {"password", 0, 0, 'W'},
588            {"host",     1, 0, 'H'},
589            {"port",     1, 0, 'P'},
590            {"help",     0, 0, 'h'},
591            {0, 0, 0, 0}
592        };
593
594        c = getopt_long (argc, argv, "ab:cd:hlmMp:suvU:WH:P:E:C:", long_options, &option_index);
595        if (c == -1)
596            break;
597
598        switch (c) {
599            case 'a': append=1;   break;
600            case 'b': bbox=optarg; break;
601            case 'c': create=1;   break;
602            case 'v': verbose=1;  break;
603            case 's': slim=1;     break;
604            case 'u': sanitize=1; break;
605            case 'l': projection=PROJ_LATLONG;  break;
606            case 'm': projection=PROJ_SPHERE_MERC; break;
607            case 'M': projection=PROJ_MERC; break;
608            case 'E': projection=-atoi(optarg); break;
609            case 'p': prefix=optarg; break;
610            case 'd': db=optarg;  break;
611            case 'C': cache = atoi(optarg); break;
612            case 'U': username=optarg; break;
613            case 'W': pass_prompt=1; break;
614            case 'H': host=optarg; break;
615            case 'P': port=optarg; break;
616
617            case 'h':
618            case '?':
619            default:
620                usage(argv[0]);
621                exit(EXIT_FAILURE);
622        }
623    }
624
625    if (argc == optind) {  // No non-switch arguments
626        usage(argv[0]);
627        exit(EXIT_FAILURE);
628    }
629
630    if (append && create) {
631        fprintf(stderr, "Error: --append and --create options can not be used at the same time!\n");
632        exit(EXIT_FAILURE);
633    }
634   
635    if( cache < 0 ) cache = 0;
636
637    if (pass_prompt)
638        password = simple_prompt("Password:", 100, 0);
639
640    conninfo = build_conninfo(db, username, password, host, port);
641    sql_conn = PQconnectdb(conninfo);
642    if (PQstatus(sql_conn) != CONNECTION_OK) {
643        fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(sql_conn));
644        exit(EXIT_FAILURE);
645    }
646    PQfinish(sql_conn);
647
648    text_init();
649    initList(&tags);
650
651    count_node = max_node = 0;
652    count_way = max_way = 0;
653    count_rel = max_rel = 0;
654
655    LIBXML_TEST_VERSION
656
657    project_init(projection);
658    fprintf(stderr, "Using projection SRS %d (%s)\n", 
659        project_getprojinfo()->srs, project_getprojinfo()->descr );
660
661    if (parse_bbox())
662        return 1;
663
664    options.conninfo = conninfo;
665    options.prefix = prefix;
666    options.append = append;
667    options.slim = slim;
668    options.projection = project_getprojinfo()->srs;
669    options.scale = (projection==PROJ_LATLONG)?10000000:100;
670    options.mid = slim ? &mid_pgsql : &mid_ram;
671    options.cache = cache;
672    out = &out_pgsql;
673
674    out->start(&options);
675
676    realloc_nodes();
677    realloc_members();
678
679    while (optind < argc) {
680        fprintf(stderr, "\nReading in file: %s\n", argv[optind]);
681        if (streamFile(argv[optind], sanitize) != 0)
682            exit_nicely();
683        optind++;
684    }
685
686    xmlCleanupParser();
687    xmlMemoryDump();
688   
689    if (count_node || count_way || count_rel) {
690        fprintf(stderr, "\n");
691        fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
692        fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
693        fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
694    }
695    out->stop();
696   
697    free(nds);
698    free(members);
699
700    project_exit();
701    text_exit();
702    fprintf(stderr, "\n");
703
704    return 0;
705}
Note: See TracBrowser for help on using the repository browser.