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

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

Commit parser changes to support the loading of diffs. Supports both
osmChange and JOSM though it doesn't support placeholders (it's not clear
that's useful in this context). Anything other than creating still results
in an error so far, so it doesn't change anything from a practical point of
view yet.

In passing, fix a bug where the append option didn't work in slim mode.

  • 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: 8863 $ \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 (username || 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.