Add:Core:Added svn version in navit -v output
[navit-package] / navit / osm2navit.c
index 1033a7b..67e272d 100644 (file)
@@ -36,6 +36,9 @@
 #include "item.h"
 #include "zipfile.h"
 #include "config.h"
+#ifdef HAVE_POSTGRESQL
+#include <libpq-fe.h>
+#endif
 
 #define BUFFER_SIZE 1280
 
@@ -47,8 +50,6 @@
 #define debug_tile(x) (!strcmp(x,"bcdbd") || !strcmp(x,"bcdbd") || !strcmp(x,"bcdbda") || !strcmp(x,"bcdbdb") || !strcmp(x,"bcdbdba") || !strcmp(x,"bcdbdbb") || !strcmp(x,"bcdbdbba") || !strcmp(x,"bcdbdbaa") || !strcmp(x,"bcdbdbacaa") || !strcmp(x,"bcdbdbacab") || !strcmp(x,"bcdbdbacaba") || !strcmp(x,"bcdbdbacabaa") || !strcmp(x,"bcdbdbacabab") || !strcmp(x,"bcdbdbacababb") || !strcmp(x,"bcdbdbacababba") || !strcmp(x,"bcdbdbacababbb") || !strcmp(x,"bcdbdbacababbd") || !strcmp(x,"bcdbdbacababaa") || !strcmp(x,"bcdbdbacababab") || !strcmp(x,"bcdbdbacababac") || !strcmp(x,"bcdbdbacababad") || !strcmp(x,"bcdbdbacabaaa") || !strcmp(x,"bcdbdbacabaaba") || !strcmp(x,"bcdbdbacabaabb") || !strcmp(x,"bcdbdbacabaabc") || !strcmp(x,"bcdbdbacabaabd") || !strcmp(x,"bcdbdbacabaaaa") || !strcmp(x,"bcdbdbacabaaab") || !strcmp(x,"bcdbdbacabaaac") || !strcmp(x,"bcdbdbacabaaad") || 0)
 #endif
 
-#define IS_TOWN(item) ((item).type >= type_town_label && (item).type <= type_town_label_1e7)
-#define IS_STREET(item) ((item).type >= type_street_nopass && (item).type <= type_ferry)
 
 static GHashTable *dedupe_ways_hash;
 
@@ -138,7 +139,25 @@ static char *attrmap={
        "n      railway=level_crossing          poi_level_crossing\n"
        "n      railway=station         poi_rail_station\n"
        "n      railway=tram_stop               poi_rail_tram_stop\n"
+       "n      amenity=park_bench              poi_bench\n"
+       "n      amenity=bench           poi_bench\n"
+       "n      amenity=biergarten              poi_biergarten\n"
+       "n      historic=boundary_stone         poi_boundary_stone\n"
+       "n      historic=castle         poi_castle\n"
+       "n      historic=ruins          poi_ruins\n"
+       "n      Annehmlichkeit=Hochsitz         poi_hunting_stand\n"
+       "n      amenity=hunting_stand           poi_hunting_stand\n"
+       "n      historic=memorial               poi_memorial\n"
+       "n      historic=monument               poi_monument\n"
+       "n      amenity=shelter         poi_shelter\n"
+       "n      amenity=fountain                poi_fountain\n"
+       "n      amenity=drinking_water          poi_potable_water\n"
+       "n      amenity=toilets         poi_toilets\n"
+       "n      tourism=viewpoint               poi_viewpoint\n"
        "w      *=*                     street_unkn\n"
+       "w      contour_ext=elevation_major     height_line_1\n"
+       "w      contour_ext=elevation_medium    height_line_2\n"
+       "w      contour_ext=elevation_minor     height_line_3\n"
        "w      amenity=place_of_worship        poly_building\n"
        "w      building=*      poly_building\n"
        "w      aeroway=aerodrome       poly_airport\n"
@@ -147,10 +166,29 @@ static char *attrmap={
        "w      aeroway=taxiway         aeroway_taxiway\n"
        "w      aeroway=terminal        poly_terminal\n"
        "w      highway=bridleway       bridleway\n"
+       "w      highway=path,horse=designated   bridleway\n"
        "w      highway=cycleway        cycleway\n"
        "w      highway=cyclepath       cycleway\n"
+       "w      highway=path,bicycle=designated cycleway\n"
        "w      highway=footway         footway\n"
-       "w      highway=steps           steps\n"
+       "w      piste:type=nordic       piste_nordic\n"
+       "w      highway=footway,piste:type=nordic       footway_and_piste_nordic\n"
+       "w      route=ski       piste_nordic\n"
+       "w      piste:type=downhill,piste:difficulty=novice     piste_downhill_novice\n"
+       "w      piste:type=downhill,piste:difficulty=easy       piste_downhill_easy\n"
+       "w      piste:type=downhill,piste:difficulty=intermediate       piste_downhill_intermediate\n"
+       "w      piste:type=downhill,piste:difficulty=advanced   piste_downhill_advanced\n"
+       "w      piste:type=downhill,piste:difficulty=expert     piste_downhill_expert\n"
+       "w      piste:type=downhill,piste:difficulty=freeride   piste_downhill_freeride\n"
+       "w      highway=path,foot=designated    footway\n"
+       "w      highway=steps   steps\n"
+       "w      highway=path    path\n"
+       "w      highway=path,sac_scale=hiking   hiking\n"
+       "w      highway=path,sac_scale=mountain_hiking  hiking_mountain\n"
+       "w      highway=path,sac_scale=demanding_mountain_hiking        hiking_mountain_demanding\n"
+       "w      highway=path,sac_scale=alpine_hiking    hiking_alpine\n"
+       "w      highway=path,sac_scale=demanding_alpine_hiking  hiking_alpine_demanding\n"
+       "w      highway=path,sac_scale=difficult_alpine_hiking  hiking_alpine_difficult\n"
        "w      highway=unsurfaced      track_gravelled\n"
        "w      highway=track           track_gravelled\n"
        "w      highway=track,tracktype=grade1          track_paved\n"
@@ -163,19 +201,28 @@ static char *attrmap={
        "w      highway=track,surface=ground            track_ground\n"
        "w      highway=track,tracktype=grade5          track_grass\n"
        "w      highway=track,surface=grass             track_grass\n"
+       "w      highway=parking_lane    street_parking_lane\n"
+       "w      highway=service,service=parking_aisle   street_parking_lane\n"
        "w      highway=service         street_service\n"
+       "w      highway=service,area=1  poly_service\n"
        "w      highway=construction            street_construction\n"
        "w      highway=pedestrian      street_pedestrian\n"
        "w      highway=pedestrian,area=1       poly_pedestrian\n"
        "w      highway=plaza   poly_plaza\n"
        "w      landuse=plaza   poly_plaza\n"
        "w      highway=residential     street_1_city\n"
+       "w      highway=residential,area=1      poly_street_1\n"
        "w      highway=living_street           living_street\n"
        "w      highway=unclassified    street_1_city\n"
+       "w      highway=unclassified,area=1     poly_street_1\n"
        "w      highway=road    street_1_city\n"
        "w      highway=minor           street_1_land\n"
        "w      highway=tertiary        street_2_city\n"
+       "w      highway=tertiary,area=1 poly_street_2\n"
+       "w      highway=tertiary_link   ramp\n"
        "w      highway=secondary       street_3_city\n"
+       "w      highway=secondary,area=1        poly_street_3\n"
+       "w      highway=secondary_link  ramp\n"
        "w      highway=primary         street_4_city\n"
        "w      highway=primary_link    ramp\n"
        "w      highway=trunk           street_4_city\n"
@@ -192,6 +239,7 @@ static char *attrmap={
        "w      landuse=industrial      poly_industry\n"
        "w      landuse=residential     poly_town\n"
        "w      landuse=residential,area=1      poly_town\n"
+       "w      landuse=farmyard        poly_town\n"
        "w      amenity=college poly_college\n"
        "w      amenity=university      poly_university\n"
        "w      tourism=camp_site       poly_camp_site\n"
@@ -224,6 +272,7 @@ static char *attrmap={
        "w      landuse=basin   poly_basin\n"
        "w      landuse=reservoir       poly_reservoir\n"
        "w      landuse=farm    poly_farm\n"
+       "w      landuse=farmland        poly_farm\n"
        "w      landuse=vineyard        poly_farm\n"
        "w      leisure=park            poly_park\n"
        "w      landuse=village_green           poly_village_green\n"
@@ -306,11 +355,20 @@ struct country_table {
        int count;
        struct rect r;
 } country_table[] = {
-       { 40,"Austria,Österreich,AUT"},
+       { 40,"Austria,�sterreich,AUT"},
        {124,"Canada"},
+       {208,"Denmark,Danmark,DK"},
+       {246,"Finland,Suomi"},
+       {250,"France,R�publique fran�aise,FR"},
        {276,"Germany,Deutschland,Bundesrepublik Deutschland"},
+       {380,"Italy,Italia"},
        {528,"Nederland,The Netherlands,Niederlande,NL"},
-       {756,"Schweiz"},
+       {578,"Norway,Norge,Noreg,NO"},
+       {724,"Spain,Espana,Espana,Reino de Espana"},
+       {752,"Sweden,Sverige,Konungariket Sverige,SE"},
+       {756,"Schweiz"}, 
+       {826,"United Kingdom,UK"},
+       {840,"USA"} 
 };
 
 static GHashTable *country_table_hash;
@@ -601,6 +659,14 @@ add_tag(char *k, char *v)
                strcpy(is_in_buffer, v);
                level=5;
        }
+       if (! strcmp(k,"gnis:ST_alpha")) {
+               /*      assume a gnis tag means it is part of the USA:
+                       http://en.wikipedia.org/wiki/Geographic_Names_Information_System
+                       many US towns do not have is_in tags
+               */
+               strcpy(is_in_buffer, "USA");
+               level=5;
+       }
        if (! strcmp(k,"lanes")) {
                level=5;
        }
@@ -898,6 +964,46 @@ parse_relation(char *p)
 }
 
 static void
+item_buffer_set_type(char *buffer, enum item_type type)
+{
+       struct item_bin *ib=(struct item_bin *) buffer;
+       ib->clen=0;
+       ib->len=2;
+       ib->type=type;
+}
+
+static void
+item_buffer_add_coord(char *buffer, struct coord *c, int count)
+{
+       struct item_bin *ib=(struct item_bin *) buffer;
+       struct coord *c2=(struct coord *)(ib+1);
+       c2+=ib->clen/2;
+       memcpy(c2, c, count*sizeof(struct coord));
+       ib->clen+=count*2;
+       ib->len+=count*2;
+}
+
+static void
+item_buffer_add_attr(char *buffer, struct attr *attr)
+{
+       struct item_bin *ib=(struct item_bin *) buffer;
+       struct attr_bin *ab=(struct attr_bin *)((int *)ib+ib->len+1);
+       if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) {
+               ab->type=attr->type;
+               strcpy((char *)(ab+1),attr->u.str);
+               pad_text_attr(ab, (char *)(ab+1));
+               ib->len+=ab->len+1;
+       }
+}
+
+static void
+item_buffer_write(char *buffer, FILE *out)
+{
+       struct item_bin *ib=(struct item_bin *) buffer;
+       fwrite(buffer, (ib->len+1)*4, 1, out);
+}
+
+static void
 write_attr(FILE *out, struct attr_bin *attr, void *buffer)
 {
        if (attr->len) {
@@ -961,13 +1067,13 @@ end_way(FILE *out)
                item.type=types[0];
        else
                item.type=type_street_unkn;
-       if (coverage && IS_STREET(item))
+       if (coverage && item_is_street(item))
                item.type=type_coverage;
        item.clen=coord_count*2;
        item.len=item.clen+2+alen;
        fwrite(&item, sizeof(item), 1, out);
        fwrite(coord_buffer, coord_count*sizeof(struct coord), 1, out);
-       if (IS_STREET(item)) {
+       if (item_is_street(item)) {
                street_name_attr.len=label_attr.len;
                write_attr(out, &street_name_attr, label_attr_buffer);
        } else
@@ -999,14 +1105,14 @@ end_node(FILE *out)
        item.len=item.clen+2+alen;
        fwrite(&item, sizeof(item), 1, out);
        fwrite(&ni->c, 1*sizeof(struct coord), 1, out);
-       if (IS_TOWN(item)) {
+       if (item_is_town(item)) {
                town_name_attr.len=label_attr.len;
                write_attr(out, &town_name_attr, label_attr_buffer);
        } else
                write_attr(out, &label_attr, label_attr_buffer);
        write_attr(out, &debug_attr, debug_attr_buffer);
 #ifdef GENERATE_INDEX
-       if (IS_TOWN(item) && town_name_attr.len) {
+       if (item_is_town(item) && town_name_attr.len) {
                char *tok,*buf=is_in_buffer;
                while ((tok=strtok(buf, ","))) {
                        while (*tok==' ')
@@ -1236,7 +1342,201 @@ phase1(FILE *in, FILE *out_ways, FILE *out_nodes)
        return 1;
 }
 
-static char buffer[150000];
+#ifdef HAVE_POSTGRESQL
+static int
+phase1_db(char *dbstr, FILE *out_ways, FILE *out_nodes)
+{
+       PGconn *conn;
+       PGresult *res,*node,*way,*tag;
+       int count,tagged,i,j,k;
+       long min, max, id, tag_id, node_id;
+       char query[256];
+       
+       sig_alrm(0);
+       conn=PQconnectdb(dbstr);
+       if (! conn) {
+               fprintf(stderr,"Failed to connect to database with '%s'\n",dbstr);
+               exit(1);
+       }
+       res=PQexec(conn, "begin");
+       if (! res) {
+               fprintf(stderr, "Cannot begin transaction: %s\n", PQerrorMessage(conn));
+               PQclear(res);
+               exit(1);
+       }
+       res=PQexec(conn, "set transaction isolation level serializable");
+       if (! res) {
+               fprintf(stderr, "Cannot set isolation level: %s\n", PQerrorMessage(conn));
+               PQclear(res);
+               exit(1);
+       }
+       res=PQexec(conn, "declare node cursor for select id,x(coordinate),y(coordinate) from node order by id");
+       if (! res) {
+               fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
+               PQclear(res);
+               exit(1);
+       }
+       res=PQexec(conn, "declare way cursor for select id from way order by id");
+       if (! res) {
+               fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
+               PQclear(res);
+               exit(1);
+       }
+       res=PQexec(conn, "declare relation cursor for select id from relation order by id");
+       if (! res) {
+               fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
+               PQclear(res);
+               exit(1);
+       }
+       for (;;) {
+               node=PQexec(conn, "fetch 100000 from node");
+               if (! node) {
+                       fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
+                       PQclear(node);
+                       exit(1);
+               }
+               count=PQntuples(node);
+               if (! count)
+                       break;
+               min=atol(PQgetvalue(node, 0, 0));
+               max=atol(PQgetvalue(node, count-1, 0));
+               sprintf(query,"select node_id,name,value from node_tag where node_id >= %ld and node_id <= %ld order by node_id", min, max);
+               tag=PQexec(conn, query);
+               if (! tag) {
+                       fprintf(stderr, "Cannot query node_tag: %s\n", PQerrorMessage(conn));
+                       exit(1);
+               }
+               j=0;
+               for (i = 0 ; i < count ; i++) {
+                       id=atol(PQgetvalue(node, i, 0));
+                       add_node(id, atof(PQgetvalue(node, i, 1)), atof(PQgetvalue(node, i, 2)));
+                       tagged=0;
+                       in_node=1;
+                       processed_nodes++;
+                       while (j < PQntuples(tag)) {
+                               tag_id=atol(PQgetvalue(tag, j, 0));
+                               if (tag_id == id) {
+                                       add_tag(PQgetvalue(tag, j, 1), PQgetvalue(tag, j, 2));
+                                       tagged=1;
+                                       j++;
+                               }
+                               if (tag_id < id)
+                                       j++;
+                               if (tag_id > id)
+                                       break;
+                       }
+                       if (tagged)
+                               end_node(out_nodes);
+                       in_node=0;
+               }
+               PQclear(tag);
+               PQclear(node);
+       }
+       for (;;) {
+               way=PQexec(conn, "fetch 100000 from way");
+               if (! way) {
+                       fprintf(stderr, "Cannot setup cursor for ways: %s\n", PQerrorMessage(conn));
+                       PQclear(node);
+                       exit(1);
+               }
+               count=PQntuples(way);
+               if (! count)
+                       break;
+               min=atol(PQgetvalue(way, 0, 0));
+               max=atol(PQgetvalue(way, count-1, 0));
+               sprintf(query,"select way_id,node_id from way_node where way_id >= %ld and way_id <= %ld order by way_id,sequence_id", min, max);
+               node=PQexec(conn, query);
+               if (! node) {
+                       fprintf(stderr, "Cannot query way_node: %s\n", PQerrorMessage(conn));
+                       exit(1);
+               }
+               sprintf(query,"select way_id,name,value from way_tag where way_id >= %ld and way_id <= %ld order by way_id", min, max);
+               tag=PQexec(conn, query);
+               if (! tag) {
+                       fprintf(stderr, "Cannot query way_tag: %s\n", PQerrorMessage(conn));
+                       exit(1);
+               }
+               j=0;
+               k=0;
+               for (i = 0 ; i < count ; i++) {
+                       id=atol(PQgetvalue(way, i, 0));
+                       add_way(id);
+                       tagged=0;
+                       in_way=1;
+                       processed_ways++;
+                       while (k < PQntuples(node)) {
+                               node_id=atol(PQgetvalue(node, k, 0));
+                               if (node_id == id) {
+                                       add_nd("",atol(PQgetvalue(node, k, 1)));
+                                       tagged=1;
+                                       k++;
+                               }
+                               if (node_id < id)
+                                       k++;
+                               if (node_id > id)
+                                       break;
+                       }
+                       while (j < PQntuples(tag)) {
+                               tag_id=atol(PQgetvalue(tag, j, 0));
+                               if (tag_id == id) {
+                                       add_tag(PQgetvalue(tag, j, 1), PQgetvalue(tag, j, 2));
+                                       tagged=1;
+                                       j++;
+                               }
+                               if (tag_id < id)
+                                       j++;
+                               if (tag_id > id)
+                                       break;
+                       }
+                       if (tagged)
+                               end_way(out_ways);
+                       in_way=0;
+               }
+               PQclear(tag);
+               PQclear(node);
+               PQclear(way);
+       }
+
+       res=PQexec(conn, "commit");
+       if (! res) {
+               fprintf(stderr, "Cannot commit transaction: %s\n", PQerrorMessage(conn));
+               PQclear(res);
+               exit(1);
+       }
+       sig_alrm(0);
+       alarm(0);
+       return 1;
+}
+#endif
+
+static char buffer[200000];
+
+static void
+phase1_map(struct map *map, FILE *out_ways, FILE *out_nodes)
+{
+       struct map_rect *mr=map_rect_new(map, NULL);
+       struct item *item;
+       int count,max=16384;
+       struct coord ca[max];
+       struct item_bin ib;
+       struct attr attr;
+       FILE *file;
+
+       while ((item = map_rect_get_item(mr))) {
+               count=item_coord_get(item, ca, item->type < type_line ? 1: max);
+               item_buffer_set_type(buffer, item->type);
+               item_buffer_add_coord(buffer, ca, count);
+               while (item_attr_get(item, attr_any, &attr)) {
+                       item_buffer_add_attr(buffer, &attr);
+               }
+                if (item->type >= type_line) 
+                       item_buffer_write(buffer, out_ways);
+               else
+                       item_buffer_write(buffer, out_nodes);
+       }
+       map_rect_destroy(mr);
+}
+
 
 int bytes_read=0;
 
@@ -1249,7 +1549,7 @@ read_item(FILE *in)
        if (r != 1)
                return NULL;
        bytes_read+=r;
-       assert((ib->len+1) < sizeof(buffer));
+       assert((ib->len+1)*4 < sizeof(buffer));
        s=(ib->len+1)*4-sizeof(*ib);
        r=fread(ib+1, s, 1, in);
        if (r != 1)
@@ -1521,7 +1821,6 @@ write_item(char *tile, struct item_bin *ib)
        }
 }
 
-
 static void
 write_item_part(FILE *out, struct item_bin *orig, int first, int last)
 {
@@ -1566,7 +1865,7 @@ phase2(FILE *in, FILE *out)
                                fprintf(stderr,"ni=%p\n", ni);
 #endif
                                c[i]=ni->c;
-                               if (ni->ref_way > 1 && i != 0 && i != ccount-1 && IS_STREET(*ib)) {
+                               if (ni->ref_way > 1 && i != 0 && i != ccount-1 && item_is_street(*ib)) {
                                        write_item_part(out, ib, last, i);
                                        last=i;
                                }
@@ -1614,7 +1913,7 @@ phase34_process_file(int phase, FILE *in)
 struct index_item {
        struct item_bin item;
        struct rect r;
-       struct attr_bin attr_order_limit;
+       struct attr_bin attr_order;
        short min;
        short max;
        struct attr_bin attr_zipfile_ref;
@@ -1642,8 +1941,8 @@ index_submap_add(int phase, struct tile_head *th, GList **tiles_list)
        ii.item.type=type_submap;
        ii.item.clen=4;
 
-       ii.attr_order_limit.len=2;
-       ii.attr_order_limit.type=attr_order_limit;
+       ii.attr_order.len=2;
+       ii.attr_order.type=attr_order;
 
        ii.attr_zipfile_ref.len=2;
        ii.attr_zipfile_ref.type=attr_zipfile_ref;
@@ -2010,6 +2309,53 @@ phase34(int phase, int maxnamelen, FILE *ways_in, FILE *nodes_in, FILE *tilesdir
 
 }
 
+static void
+dump_coord(struct coord *c)
+{
+       printf("0x%x 0x%x",c->x, c->y);
+}
+
+static void
+dump(FILE *in)
+{
+       struct item_bin *ib;
+       struct coord *c;
+       struct attr_bin *a;
+       struct attr attr;
+       int *attr_start;
+       int *attr_end;
+       int i;
+       char *str;
+       while ((ib=read_item(in))) {
+               c=(struct coord *)(ib+1);
+               if (ib->type < type_line) {
+                       dump_coord(c);
+                       printf(" ");
+               }
+               attr_start=(int *)(ib+1)+ib->clen;
+               attr_end=(int *)ib+ib->len+1;
+               printf("type=%s", item_to_name(ib->type));
+               while (attr_start < attr_end) {
+                       a=(struct attr_bin *)(attr_start);
+                       attr_start+=a->len+1;
+                       attr.type=a->type;
+                       attr_data_set(&attr, (a+1));
+                       str=attr_to_text(&attr, NULL, 1);
+                       printf(" %s=\"%s\"", attr_to_name(a->type), str);
+                       g_free(str);
+               }
+               printf(" debug=\"length=%d\"", ib->len);
+               printf("\n");
+               if (ib->type >= type_line) {
+                       for (i = 0 ; i < ib->clen/2 ; i++) {
+                               dump_coord(c+i);
+                               printf("\n");
+                       }
+                       
+               }
+       }
+}
+
 static int
 phase3(FILE *ways_in, FILE *nodes_in, FILE *tilesdir_out)
 {
@@ -2093,6 +2439,7 @@ write_zipmember(FILE *out, FILE *dir_out, char *name, int filelen, char *data, i
 
        crc=crc32(0, NULL, 0);
        crc=crc32(crc, (unsigned char *)data, data_size);
+#ifdef HAVE_ZLIB
        if (compression_level) {
                error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, compression_level);
                if (error == Z_OK) {
@@ -2104,6 +2451,7 @@ write_zipmember(FILE *out, FILE *dir_out, char *name, int filelen, char *data, i
                        fprintf(stderr,"compress2 returned %d\n", error);
                }
        }
+#endif
        lfh.zipcrc=crc;
        lfh.zipsize=comp_size;
        lfh.zipuncmp=data_size;
@@ -2254,6 +2602,7 @@ phase4(FILE *ways_in, FILE *nodes_in, FILE *out, FILE *dir_out, int compression_
 static void
 usage(FILE *f)
 {
+       /* DEVELOPPERS : don't forget to update the manpage if you modify theses options */
        fprintf(f,"\n");
        fprintf(f,"osm2navit - parse osm textfile and converts to NavIt binfile format\n\n");
        fprintf(f,"Usage :\n");
@@ -2264,6 +2613,9 @@ usage(FILE *f)
        fprintf(f,"-W (--ways-only)         : process only ways\n");
        fprintf(f,"-a (--attr-debug-level)  : control which data is included in the debug attribute\n");
        fprintf(f,"-c (--dump-coordinates)  : dump coordinates after phase 1\n");
+#ifdef HAVE_POSTGRESQL
+       fprintf(f,"-d (--db)                : get osm data out of a postgresql database with osm simple scheme and given connect string\n");
+#endif
        fprintf(f,"-e (--end)               : end at specified phase\n");
        fprintf(f,"-k (--keep-tmpfiles)     : do not delete tmp files after processing. useful to reuse them\n\n");
        fprintf(f,"-o (--coverage)          : map every street to item overage\n");
@@ -2274,17 +2626,34 @@ usage(FILE *f)
        exit(1);
 }
 
+static void
+process_binfile(FILE *in, FILE *out)
+{
+       struct item_bin *ib;
+       while ((ib=read_item(in))) {
+               fwrite(ib, (ib->len+1)*4, 1, out);
+       }
+}
+
 int main(int argc, char **argv)
 {
        FILE *ways=NULL,*ways_split=NULL,*nodes=NULL,*tilesdir,*zipdir,*res;
        char *map=g_strdup(attrmap);
-       int c,start=1,end=4,dump_coordinates=0;
+       int i,c,start=1,end=4,dump_coordinates=0;
        int keep_tmpfiles=0;
        int process_nodes=1, process_ways=1;
+#ifdef HAVE_ZLIB
        int compression_level=9;
-       char *result;
+#else
+       int compression_level=0;
+#endif
+       int output=0;
+       int input=0;
+       char *result,*dbstr=NULL;
        FILE* input_file = stdin;
-
+       struct plugins *plugins=NULL;
+       struct attr **attrs;
+       struct map *map_handle=NULL;
 
        while (1) {
 #if 0
@@ -2293,23 +2662,38 @@ int main(int argc, char **argv)
                int option_index = 0;
                static struct option long_options[] = {
                        {"attr-debug-level", 1, 0, 'a'},
+                       {"binfile", 0, 0, 'b'},
                        {"compression-level", 1, 0, 'z'},
                        {"coverage", 0, 0, 'o'},
+#ifdef HAVE_POSTGRESQL
+                       {"db", 1, 0, 'd'},
+#endif
                        {"dedupe-ways", 0, 0, 'w'},
+                       {"dump", 0, 0, 'D'},
+                       {"dump-coordinates", 0, 0, 'c'},
                        {"end", 1, 0, 'e'},
                        {"help", 0, 0, 'h'},
                        {"keep-tmpfiles", 0, 0, 'k'},
                        {"nodes-only", 0, 0, 'N'},
+                       {"map", 1, 0, 'm'},
+                       {"plugin", 1, 0, 'p'},
                        {"start", 1, 0, 's'},
                        {"input-file", 1, 0, 'i'},
                        {"ignore-unknown", 0, 0, 'n'},
                        {"ways-only", 0, 0, 'W'},
                        {0, 0, 0, 0}
                };
-               c = getopt_long (argc, argv, "Nni:Wa:ce:hks:w", long_options, &option_index);
+               c = getopt_long (argc, argv, "DNWa:bc"
+#ifdef HAVE_POSTGRESQL
+                                             "d:"
+#endif
+                                             "e:hi:knm:p:s:w", long_options, &option_index);
                if (c == -1)
                        break;
                switch (c) {
+               case 'D':
+                       output=1;
+                       break;
                case 'N':
                        process_ways=0;
                        break;
@@ -2319,15 +2703,31 @@ int main(int argc, char **argv)
                case 'a':
                        attr_debug_level=atoi(optarg);
                        break;
+               case 'b':
+                       input=1;
+                       break;
                case 'c':
                        dump_coordinates=1;
                        break;
+#ifdef HAVE_POSTGRESQL
+               case 'd':
+                       dbstr=optarg;
+                       break;
+#endif
                case 'e':
                        end=atoi(optarg);
                        break;
                case 'h':
                        usage(stdout);
                        break;
+               case 'm':
+                       attrs=(struct attr*[]){
+                               &(struct attr){attr_type,{"textfile"}},
+                               &(struct attr){attr_data,{"bookmark.txt"}},
+                               NULL};
+                       map_handle=map_new(attrs);
+                       fprintf(stderr,"optarg=%s\n", optarg);
+                       break;  
                case 'n':
                        fprintf(stderr,"I will IGNORE unknown types\n");
                        ignore_unkown=1;
@@ -2339,6 +2739,13 @@ int main(int argc, char **argv)
                case 'o':
                        coverage=1;
                        break;
+               case 'p':
+                       if (! plugins)
+                               plugins=plugins_new();
+                       fprintf(stderr,"optarg=%s\n",optarg);
+                       attrs=(struct attr*[]){&(struct attr){attr_path,{optarg}},NULL};
+                       plugins_add_path(plugins, attrs);       
+                       break;
                case 's':
                        start=atoi(optarg);
                        break;
@@ -2353,9 +2760,11 @@ int main(int argc, char **argv)
                            exit( -1 );
                        }
                        break;
+#ifdef HAVE_ZLIB
                case 'z':
                        compression_level=atoi(optarg);
                        break;
+#endif
                case '?':
                        usage(stderr);
                        break;
@@ -2364,8 +2773,10 @@ int main(int argc, char **argv)
                }
 
        }
-       if (optind != argc-1)
+       if (optind != argc-(output == 1 ? 0:1))
                usage(stderr);
+       if (plugins)
+               plugins_init(plugins);
        result=argv[optind];
        build_attrmap(map);
 #ifdef GENERATE_INDEX
@@ -2373,6 +2784,7 @@ int main(int argc, char **argv)
 #endif
 
 
+       if (input == 0) {
        if (start == 1) {
                if (process_ways)
                        ways=fopen("ways.tmp","wb+");
@@ -2380,7 +2792,17 @@ int main(int argc, char **argv)
                        nodes=fopen("nodes.tmp","wb+");
                phase=1;
                fprintf(stderr,"PROGRESS: Phase 1: collecting data\n");
-               phase1(input_file,ways,nodes);
+#ifdef HAVE_POSTGRESQL
+               if (dbstr) 
+                       phase1_db(dbstr,ways,nodes);
+               else
+#endif
+               if (map_handle) {
+                       phase1_map(map_handle,ways,nodes);
+                       map_destroy(map_handle);
+               }
+               else
+                       phase1(input_file,ways,nodes);
                if (ways)
                        fclose(ways);
                if (nodes)
@@ -2416,6 +2838,29 @@ int main(int argc, char **argv)
        node_buffer.size=0;
        if (end == 2)
                exit(0);
+       } else {
+               ways_split=fopen("ways_split.tmp","wb+");
+               process_binfile(stdin, ways_split);
+               fclose(ways_split);
+       }
+       if (output == 1) {
+               fprintf(stderr,"PROGRESS: Phase 3: dumping\n");
+               if (process_nodes) {
+                       nodes=fopen("nodes.tmp","rb");
+                       if (nodes) {
+                               dump(nodes);
+                               fclose(nodes);
+                       }
+               }
+               if (process_ways) {
+                       ways_split=fopen("ways_split.tmp","rb");
+                       if (ways_split) {
+                               dump(ways_split);
+                               fclose(ways_split);
+                       }
+               }
+               exit(0);
+       }
        if (start <= 3) {
                phase=3;
                fprintf(stderr,"PROGRESS: Phase 3: generating tiles\n");