Add:Ticket 197:Added some countries for osm2navit
[navit-package] / navit / osm2navit.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20
21 #define _FILE_OFFSET_BITS 64
22 #define _LARGEFILE_SOURCE
23 #define _LARGEFILE64_SOURCE
24 #include <glib.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <math.h>
31 #include <getopt.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <sys/stat.h>
35 #include <zlib.h>
36 #include "item.h"
37 #include "zipfile.h"
38 #include "config.h"
39 #ifdef HAVE_POSTGRESQL
40 #include <libpq-fe.h>
41 #endif
42
43 #define BUFFER_SIZE 1280
44
45 #define GENERATE_INDEX
46
47 #if 1
48 #define debug_tile(x) 0
49 #else
50 #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)
51 #endif
52
53
54 static GHashTable *dedupe_ways_hash;
55
56 static int attr_debug_level=1;
57 static int nodeid,wayid;
58 static int report,phase;
59 static int ignore_unkown = 0, coverage=0;
60
61 static char *attrmap={
62         "n      *=*                     point_unkn\n"
63         "n      amenity=hospital        poi_hospital\n"
64         "n      amenity=atm             poi_bank\n"
65         "n      amenity=bank            poi_bank\n"
66         "n      amenity=pub             poi_bar\n"
67         "n      amenity=cafe            poi_cafe\n"
68         "n      amenity=bus_station     poi_bus_station\n"
69         "n      amenity=parking         poi_car_parking\n"
70         "n      amenity=cinema          poi_cinema\n"
71         "n      amenity=fire_station    poi_firebrigade\n"
72         "n      amenity=fuel            poi_fuel\n"
73         "n      amenity=courthouse      poi_justice\n"
74         "n      amenity=library         poi_library\n"
75         "n      amenity=pharmacy        poi_pharmacy\n"
76         "n      amenity=place_of_worship,religion=christian     poi_church\n"
77         "n      amenity=police          poi_police\n"
78         "n      amenity=post_office     poi_post\n"
79         "n      amenity=post_box        poi_post\n"
80         "n      amenity=public_building poi_public_office\n"
81         "n      amenity=restaurant      poi_restaurant\n"
82         "n      amenity=fast_food       poi_fastfood\n"
83         "n      amenity=toilets         poi_restroom\n"
84         "n      amenity=school          poi_school\n"
85         "n      amenity=university      poi_school\n"
86         "n      amenity=college         poi_school\n"
87         "n      amenity=telephone       poi_telephone\n"
88         "n      amenity=theatre         poi_theater\n"
89         "n      amenity=townhall                poi_townhall\n"
90         "n      highway=bus_stop        poi_bus_stop\n"
91         "n      highway=mini_roundabout mini_roundabout\n"
92         "n      highway=motorway_junction       highway_exit\n"
93         "n      highway=traffic_signals traffic_signals\n"
94         "n      highway=turning_circle  turning_circle\n"
95         "n      leisure=slipway         poi_boat_ramp\n"
96         "n      leisure=fishing         poi_fish\n"
97         "n      sport=golf      poi_golf\n"
98         "n      leisure=golf_course     poi_golf\n"
99         "n      leisure=marina          poi_marine\n"
100         "n      leisure=sports_centre   poi_sport\n"
101         "n      leisure=stadium         poi_stadium\n"
102         "n      shop=supermarket        poi_shopping\n"
103         "n      shop=convenience        poi_shop_grocery\n"
104         "n      tourism=attraction      poi_attraction\n"
105         "n      tourism=camp_site       poi_camp_rv\n"
106         "n      tourism=caravan_site    poi_camp_rv\n"
107         "n      tourism=hotel           poi_hotel\n"
108         "n      tourism=motel           poi_hotel\n"
109         "n      tourism=guest_house     poi_hotel\n"
110         "n      tourism=hostel          poi_hotel\n"
111         "n      tourism=information     poi_information\n"
112         "n      tourism=museum          poi_museum_history\n"
113         "n      tourism=picnic_site     poi_picnic\n"
114         "n      tourism=theme_park      poi_resort\n"
115         "n      tourism=zoo             poi_zoo\n"
116         "n      amenity=grave_yard      poi_cemetery\n"
117         "n      landuse=cemetery        poi_cemetery\n"
118         "n      military=airfield       poi_military\n"
119         "n      military=bunker         poi_military\n"
120         "n      military=barracks       poi_military\n"
121         "n      military=range          poi_military\n"
122         "n      military=danger_area    poi_danger_area\n"
123         "n      sport=swimming  poi_swimming\n"
124         "n      sport=skiing            poi_skiing\n"
125         "n      aeroway=aerodrome       poi_airport\n"
126         "n      aeroway=airport         poi_airport\n"
127         "n      aeroway=terminal        poi_airport\n"
128         "n      aeroway=helipad         poi_heliport\n"
129         "n      man_made=tower  poi_tower\n"
130         "n      natural=bay             poi_bay\n"
131         "n      natural=peak            poi_peak\n"
132         "n      place=suburb            district_label\n"
133         "n      place=city              town_label_2e5\n"
134         "n      place=town              town_label_2e4\n"
135         "n      place=village           town_label_2e3\n"
136         "n      place=hamlet            town_label_2e2\n"
137         "n      place=locality          town_label_2e0\n"
138         "n      railway=halt            poi_rail_halt\n"
139         "n      railway=level_crossing          poi_level_crossing\n"
140         "n      railway=station         poi_rail_station\n"
141         "n      railway=tram_stop               poi_rail_tram_stop\n"
142         "n      amenity=park_bench              poi_bench\n"
143         "n      amenity=bench           poi_bench\n"
144         "n      amenity=biergarten              poi_biergarten\n"
145         "n      historic=boundary_stone         poi_boundary_stone\n"
146         "n      historic=castle         poi_castle\n"
147         "n      Annehmlichkeit=Hochsitz         poi_hunting_stand\n"
148         "n      amenity=hunting_stand           poi_hunting_stand\n"
149         "n      historic=memorial               poi_memorial\n"
150         "n      historic=monument               poi_monument\n"
151         "n      amenity=shelter         poi_shelter\n"
152         "n      amenity=fountain                poi_fountain\n"
153         "n      amenity=drinking_water          poi_potable_water\n"
154         "n      amenity=toilets         poi_toilets\n"
155         "n      tourism=viewpoint               poi_viewpoint\n"
156         "w      *=*                     street_unkn\n"
157         "w      amenity=place_of_worship        poly_building\n"
158         "w      building=*      poly_building\n"
159         "w      aeroway=aerodrome       poly_airport\n"
160         "w      aeroway=apron           poly_apron\n"
161         "w      aeroway=runway          aeroway_runway\n"
162         "w      aeroway=taxiway         aeroway_taxiway\n"
163         "w      aeroway=terminal        poly_terminal\n"
164         "w      highway=bridleway       bridleway\n"
165         "w      highway=path,horse=designated   bridleway\n"
166         "w      highway=cycleway        cycleway\n"
167         "w      highway=cyclepath       cycleway\n"
168         "w      highway=path,bicycle=designated cycleway\n"
169         "w      highway=footway         footway\n"
170         "w      piste:type=nordic       piste_nordic\n"
171         "w      route=ski       piste_nordic\n"
172         "w      piste:type=downhill,piste:difficulty=novice     piste_downhill_novice\n"
173         "w      piste:type=downhill,piste:difficulty=easy       piste_downhill_easy\n"
174         "w      piste:type=downhill,piste:difficulty=intermediate       piste_downhill_intermediate\n"
175         "w      piste:type=downhill,piste:difficulty=advanced   piste_downhill_advanced\n"
176         "w      piste:type=downhill,piste:difficulty=expert     piste_downhill_expert\n"
177         "w      piste:type=downhill,piste:difficulty=freeride   piste_downhill_freeride\n"
178         "w      highway=path,foot=designated    footway\n"
179         "w      highway=steps   steps\n"
180         "w      highway=path    path\n"
181         "w      highway=path,sac_scale=hiking   hiking\n"
182         "w      highway=path,sac_scale=mountain_hiking  hiking_mountain\n"
183         "w      highway=path,sac_scale=demanding_mountain_hiking        hiking_mountain_demanding\n"
184         "w      highway=path,sac_scale=alpine_hiking    hiking_alpine\n"
185         "w      highway=path,sac_scale=demanding_alpine_hiking  hiking_alpine_demanding\n"
186         "w      highway=path,sac_scale=difficult_alpine_hiking  hiking_alpine_difficult\n"
187         "w      highway=unsurfaced      track_gravelled\n"
188         "w      highway=track           track_gravelled\n"
189         "w      highway=track,tracktype=grade1          track_paved\n"
190         "w      highway=track,surface=paved             track_paved\n"
191         "w      highway=track,tracktype=grade2          track_gravelled\n"
192         "w      highway=track,surface=gravel            track_gravelled\n"
193         "w      highway=track,tracktype=grade3          track_unpaved\n"
194         "w      highway=track,surface=unpaved           track_unpaved\n"
195         "w      highway=track,tracktype=grade4          track_ground\n"
196         "w      highway=track,surface=ground            track_ground\n"
197         "w      highway=track,tracktype=grade5          track_grass\n"
198         "w      highway=track,surface=grass             track_grass\n"
199         "w      highway=parking_lane    street_parking_lane\n"
200         "w      highway=service         street_service\n"
201         "w      highway=service,area=1  poly_service\n"
202         "w      highway=construction            street_construction\n"
203         "w      highway=pedestrian      street_pedestrian\n"
204         "w      highway=pedestrian,area=1       poly_pedestrian\n"
205         "w      highway=plaza   poly_plaza\n"
206         "w      landuse=plaza   poly_plaza\n"
207         "w      highway=residential     street_1_city\n"
208         "w      highway=residential,area=1      poly_street_1\n"
209         "w      highway=living_street           living_street\n"
210         "w      highway=unclassified    street_1_city\n"
211         "w      highway=unclassified,area=1     poly_street_1\n"
212         "w      highway=road    street_1_city\n"
213         "w      highway=minor           street_1_land\n"
214         "w      highway=tertiary        street_2_city\n"
215         "w      highway=tertiary,area=1 poly_street_2\n"
216         "w      highway=tertiary_link   ramp\n"
217         "w      highway=secondary       street_3_city\n"
218         "w      highway=secondary,area=1        poly_street_3\n"
219         "w      highway=secondary_link  ramp\n"
220         "w      highway=primary         street_4_city\n"
221         "w      highway=primary_link    ramp\n"
222         "w      highway=trunk           street_4_city\n"
223         "w      highway=trunk_link      ramp\n"
224         "w      highway=motorway        highway_city\n"
225         "w      highway=motorway_link   ramp\n"
226         "w      historic=town gate      poly_building\n"
227         "w      cycleway=track          cycleway\n"
228         "w      amenity=parking         poly_car_parking\n"
229         "w      landuse=allotments      poly_allotments\n"
230         "w      landuse=cemetery        poly_cemetery\n"
231         "w      amenity=grave_yard      poly_cemetery\n"
232         "w      landuse=forest          poly_wood\n"
233         "w      landuse=industrial      poly_industry\n"
234         "w      landuse=residential     poly_town\n"
235         "w      landuse=residential,area=1      poly_town\n"
236         "w      landuse=farmyard        poly_town\n"
237         "w      amenity=college poly_college\n"
238         "w      amenity=university      poly_university\n"
239         "w      tourism=camp_site       poly_camp_site\n"
240         "w      tourism=caravan_site    poly_caravan_site\n"
241         "w      tourism=picnic_site     poly_picnic_site\n"
242         "w      tourism=theme_park      poly_theme_park\n"
243         "w      tourism=attraction      poly_attraction\n"
244         "w      tourism=zoo     poly_zoo\n"
245         "w      tourism=artwork poly_artwork\n"
246         "w      historic=archaeological_site    poly_archaeological_site\n"
247         "w      historic=ruins  poly_ruins\n"
248         "w      historic=battlefield    poly_battlefield\n"
249         "w      landuse=quarry  poly_quarry\n"
250         "w      landuse=landfill        poly_landfill\n"
251         "w      landuse=retail  poly_retail\n"
252         "w      landuse=commercial      poly_commercial\n"
253         "w      landuse=brownfield      poly_brownfield\n"
254         "w      landuse=greenfield      poly_greenfield\n"
255         "w      landuse=construction    poly_construction\n"
256         "w      landuse=railway poly_railway\n"
257         "w      natural=glacier poly_glacier\n"
258         "w      natural=scree   poly_scree\n"
259         "w      natural=scrub   poly_scrub\n"
260         "w      natural=fell    poly_fell\n"
261         "w      natural=heath   poly_heath\n"
262         "w      natural=marsh   poly_marsh\n"
263         "w      natural=mud     poly_mud\n"
264         "w      natural=beach   poly_beach\n"
265         "w      natural=land    poly_land\n"
266         "w      landuse=basin   poly_basin\n"
267         "w      landuse=reservoir       poly_reservoir\n"
268         "w      landuse=farm    poly_farm\n"
269         "w      landuse=farmland        poly_farm\n"
270         "w      landuse=vineyard        poly_farm\n"
271         "w      leisure=park            poly_park\n"
272         "w      landuse=village_green           poly_village_green\n"
273         "w      landuse=recreation_ground               poly_recreation_ground\n"
274         "w      natural=wood            poly_wood\n"
275         "w      natural=water           poly_water\n"
276         "w      natural=coastline       water_line\n"
277         "w      place=suburb            poly_town\n"
278         "w      place=town              poly_town\n"
279         "w      landuse=military        poly_military\n"
280         "w      military=airfield       poly_airfield\n"
281         "w      military=barracks       poly_barracks\n"
282         "w      military=danger_area    poly_danger_area\n"
283         "w      military=range  poly_range\n"
284         "w      military=naval_base     poly_naval_base\n"
285         "w      power=line      powerline\n"
286         "w      railway=rail            rail\n"
287         "w      railway=narrow_gauge    rail_narrow_gauge\n"
288         "w      railway=light_rail              rail_light\n"
289         "w      railway=subway          rail_subway\n"
290         "w      railway=tram            rail_tram\n"
291         "w      railway=monorail                rail_mono\n"
292         "w      railway=preserved               rail_preserved\n"
293         "w      railway=disused         rail_disused\n"
294         "w      railway=abandoned               rail_abandoned\n"
295         "w      aerialway=cable_car             lift_cable_car\n"
296         "w      aerialway=chair_lift            lift_chair\n"
297         "w      aerialway=drag_lift             lift_drag\n"
298         "w      leisure=golf_course     poly_golf_course\n"
299         "w      sport=*         poly_sport\n"
300         "w      leisure=sports_centre           poly_sport\n"
301         "w      leisure=stadium         poly_sports_stadium\n"
302         "w      leisure=track           poly_sports_track\n"
303         "w      leisure=pitch           poly_sports_pitch\n"
304         "w      leisure=water_park              poly_water_park\n"
305         "w      leisure=marina          poly_marina\n"
306         "w      leisure=fishing         poly_fishing\n"
307         "w      leisure=garden          poly_garden\n"
308         "w      leisure=common          poly_common\n"
309         "w      leisure=playground              poly_playground\n"
310         "w      leisure=nature_reserve          poly_nature_reserve\n"
311         "w      waterway=canal          water_canal\n"
312         "w      waterway=river          water_river\n"
313         "w      waterway=stream         water_stream\n"
314         "w      waterway=drain          water_drain\n"
315         "w      waterway=riverbank      poly_water\n"
316         "w      boundary=administrative border_country\n"
317         "w      boundary=civil  border_civil\n"
318         "w      boundary=political      border_political\n"
319         "w      boundary=national_park  border_national_park\n"
320         "w      route=ferry             ferry\n"
321         "w      highway=bus_guideway            bus_guideway\n"
322 };
323
324 struct coord {
325         int x;
326         int y;
327 } coord_buffer[65536];
328
329 #define IS_REF(c) ((c).x >= (1 << 30))
330 #define REF(c) ((c).y)
331 #define SET_REF(c,ref) do { (c).x = 1 << 30; (c).y = ref ; } while(0)
332
333 struct rect {
334         struct coord l,h;
335 };
336
337 static void bbox_extend(struct coord *c, struct rect *r);
338
339 #ifdef GENERATE_INDEX
340
341 static GHashTable *aux_tile_hash;
342 GList *aux_tile_list;
343
344 struct country_table {
345         int countryid;
346         char *names;
347         FILE *file;
348         int size;
349         int count;
350         struct rect r;
351 } country_table[] = {
352         { 40,"Austria,Österreich,AUT"}, 
353         {124,"Canada"}, 
354         {208,"Denmark,Danmark,DK"}, 
355         {246,"Finland,Suomi"}, 
356         {250,"France,République française,FR"}, 
357         {276,"Germany,Deutschland,Bundesrepublik Deutschland"}, 
358         {380,"Italy,Italia"}, 
359         {578,"Norway,Norge,Noreg,NO"}, 
360         {752,"Sweden,Sverige,Konungariket Sverige,SE"}, 
361         {528,"Nederland,The Netherlands,Niederlande,NL"}, 
362         {724,"Spain,Espana,Espana,Reino de Espana"}, 
363         {756,"Schweiz"}, 
364         {840,"USA"} 
365 };
366
367 static GHashTable *country_table_hash;
368 #endif
369
370 struct attr_mapping {
371         enum item_type type;
372         int attr_present_idx_count;
373         int attr_present_idx[0];        
374 };
375
376 static struct attr_mapping **attr_mapping_node;
377 static int attr_mapping_node_count;
378 static struct attr_mapping **attr_mapping_way;
379 static int attr_mapping_way_count;
380
381 static char *attr_present;
382 static int attr_present_count;
383 static GHashTable *attr_hash;
384
385
386 static GHashTable *strings_hash = NULL;
387
388
389 static char* string_hash_lookup( const char* key )
390 {
391         char* key_ptr = NULL;
392
393         if ( strings_hash == NULL ) {
394                 strings_hash = g_hash_table_new(g_str_hash, g_str_equal);
395         }
396
397         if ( ( key_ptr = g_hash_table_lookup(strings_hash, key )) == NULL ) {
398                 key_ptr = g_strdup( key );
399                 g_hash_table_insert(strings_hash, key_ptr,  (gpointer)key_ptr );
400
401         }
402         return key_ptr;
403 }
404
405 static void
406 build_attrmap_line(char *line)
407 {
408         char *t=NULL,*kvl=NULL,*i=NULL,*p,*kv;
409         struct attr_mapping ***attr_mapping_curr,*attr_mapping=g_malloc0(sizeof(struct attr_mapping));
410         int idx,attr_mapping_count=0,*attr_mapping_curr_count;
411         t=line;
412         p=strchr(t,'\t');
413         if (p) {
414                 while (*p == '\t')
415                         *p++='\0';
416                 kvl=p;
417                 p=strchr(kvl,'\t');
418         }
419         if (p) {
420                 while (*p == '\t')
421                         *p++='\0';
422                 i=p;
423         }
424         if (t[0] == 'w') {
425                 if (! i)
426                         i="street_unkn";
427                 attr_mapping_curr=&attr_mapping_way;
428                 attr_mapping_curr_count=&attr_mapping_way_count;
429         } else {
430                 if (! i)
431                         i="point_unkn";
432                 attr_mapping_curr=&attr_mapping_node;
433                 attr_mapping_curr_count=&attr_mapping_node_count;
434         }
435         attr_mapping->type=item_from_name(i);
436         while ((kv=strtok(kvl, ","))) {
437                 kvl=NULL;
438                 if (!(idx=(int)g_hash_table_lookup(attr_hash, kv))) {
439                         idx=attr_present_count++;
440                         g_hash_table_insert(attr_hash, kv, (gpointer) idx);
441                 }
442                 attr_mapping=g_realloc(attr_mapping, sizeof(struct attr_mapping)+(attr_mapping_count+1)*sizeof(int));
443                 attr_mapping->attr_present_idx[attr_mapping_count++]=idx;
444                 attr_mapping->attr_present_idx_count=attr_mapping_count;
445         }
446         *attr_mapping_curr=g_realloc(*attr_mapping_curr, sizeof(**attr_mapping_curr)*(*attr_mapping_curr_count+1));
447         (*attr_mapping_curr)[(*attr_mapping_curr_count)++]=attr_mapping;
448 }
449
450 static void
451 build_attrmap(char *map)
452 {
453         char *p;
454         attr_hash=g_hash_table_new(g_str_hash, g_str_equal);
455         attr_present_count=1;
456         while (map) {
457                 p=strchr(map,'\n');
458                 if (p)
459                         *p++='\0';
460                 if (strlen(map))
461                         build_attrmap_line(map);
462                 map=p;
463         }
464         attr_present=g_malloc0(sizeof(*attr_present)*attr_present_count);
465 }
466
467 #ifdef GENERATE_INDEX
468 static void
469 build_countrytable(void)
470 {
471         int i;
472         char *names,*str,*tok;
473         country_table_hash=g_hash_table_new(g_str_hash, g_str_equal);
474         for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
475                 names=g_strdup(country_table[i].names);
476                 str=names;
477                 while ((tok=strtok(str, ","))) {
478                         str=NULL;
479                         g_hash_table_insert(country_table_hash, tok,  (gpointer)&country_table[i]);
480                 }
481         }
482 }
483 #endif
484
485
486
487 static int processed_nodes, processed_nodes_out, processed_ways, processed_relations, processed_tiles;
488 static int in_way, in_node, in_relation;
489
490 static void
491 sig_alrm(int sig)
492 {
493 #ifndef _WIN32
494         signal(SIGALRM, sig_alrm);
495 #endif
496         alarm(30);
497         fprintf(stderr,"PROGRESS%d: Processed %d nodes (%d out) %d ways %d relations %d tiles\n", phase, processed_nodes, processed_nodes_out, processed_ways, processed_relations, processed_tiles);
498 }
499
500 struct item_bin {
501         int len;
502         enum item_type type;
503         int clen;
504 } item;
505
506 struct attr_bin {
507         int len;
508         enum attr_type type;
509 };
510
511 struct attr_bin label_attr = {
512         0, attr_label
513 };
514 char label_attr_buffer[BUFFER_SIZE];
515
516 struct attr_bin town_name_attr = {
517         0, attr_town_name
518 };
519
520 struct attr_bin street_name_attr = {
521         0, attr_street_name
522 };
523
524 struct attr_bin street_name_systematic_attr = {
525         0, attr_street_name_systematic
526 };
527 char street_name_systematic_attr_buffer[BUFFER_SIZE];
528
529 struct attr_bin debug_attr = {
530         0, attr_debug
531 };
532 char debug_attr_buffer[BUFFER_SIZE];
533
534 struct attr_bin flags_attr = {
535         0, attr_flags
536 };
537 int flags_attr_value;
538
539 char is_in_buffer[BUFFER_SIZE];
540
541
542 static void write_zipmember(FILE *out, FILE *dir_out, char *name, int filelen, char *data, int data_size, int compression_level);
543
544 static void
545 pad_text_attr(struct attr_bin *a, char *buffer)
546 {
547         int l;
548         if (buffer && buffer[0]) {
549                 l=strlen(buffer)+1;
550                 while (l % 4)
551                         buffer[l++]='\0';
552                 a->len=l/4+1;
553         } else
554                 a->len=0;
555 }
556
557 static int
558 xml_get_attribute(char *xml, char *attribute, char *buffer, int buffer_size)
559 {
560         int len=strlen(attribute);
561         char *pos,*i,s,attr[len+2];
562         strcpy(attr, attribute);
563         strcpy(attr+len, "=");
564         pos=strstr(xml, attr);
565         if (! pos)
566                 return 0;
567         pos+=len+1;
568         s=*pos++;
569         if (! s)
570                 return 0;
571         i=strchr(pos, s);
572         if (! i)
573                 return 0;
574         if (i - pos > buffer_size) {
575                 fprintf(stderr,"Buffer overflow %d vs %d\n", i-pos, buffer_size);
576                 return 0;
577         }
578         strncpy(buffer, pos, i-pos);
579         buffer[i-pos]='\0';
580         return 1;
581 }
582
583 static int node_is_tagged;
584
585 static void
586 add_tag(char *k, char *v)
587 {
588         GHashTable *value_hash;
589         enum item_type type;
590         int idx,level=2;
591         char buffer[BUFFER_SIZE*2+2];
592         if (! strcmp(k,"ele"))
593                 level=9;
594         if (! strcmp(k,"time"))
595                 level=9;
596         if (! strcmp(k,"created_by"))
597                 level=9;
598         if (! strncmp(k,"tiger:",6) || !strcmp(k,"AND_nodes"))
599                 level=9;
600         if (! strcmp(k,"converted_by") || ! strcmp(k,"source"))
601                 level=8;
602         if (! strncmp(k,"osmarender:",11) || !strncmp(k,"svg:",4))
603                 level=8;
604         if (! strcmp(k,"layer"))
605                 level=7;
606         if (! strcasecmp(v,"true") || ! strcasecmp(v,"yes"))
607                 v="1";
608         if (! strcmp(k,"oneway")) {
609                 if (!strcmp(v,"1")) {
610                         flags_attr_value=AF_ONEWAY;
611                         flags_attr.len=2;
612                 }
613                 if (! strcmp(v,"-1")) {
614                         flags_attr_value=AF_ONEWAYREV;
615                         flags_attr.len=2;
616                 }
617                 if (!in_way)
618                         level=6;
619                 else
620                         level=5;
621         }
622         if (! strcmp(k,"junction")) {
623                 if (! strcmp(v,"roundabout")) {
624                         flags_attr_value=AF_ONEWAY;
625                         flags_attr.len=2;
626                 }
627         }
628         if (! strcmp(k,"maxspeed")) {
629                 level=5;
630         }
631         if (! strcmp(k,"bicycle")) {
632                 level=5;
633         }
634         if (! strcmp(k,"foot")) {
635                 level=5;
636         }
637         if (! strcmp(k,"note"))
638                 level=5;
639         if (! strcmp(k,"name")) {
640                 strcpy(label_attr_buffer, v);
641                 pad_text_attr(&label_attr, label_attr_buffer);
642                 level=5;
643         }
644         if (! strcmp(k,"ref")) {
645                 if (in_way) {
646                         strcpy(street_name_systematic_attr_buffer, v);
647                         pad_text_attr(&street_name_systematic_attr, street_name_systematic_attr_buffer);
648                 }
649                 level=5;
650         }
651         if (! strcmp(k,"is_in")) {
652                 strcpy(is_in_buffer, v);
653                 level=5;
654         }
655         if (! strcmp(k,"gnis:ST_alpha")) {
656                 /*      assume a gnis tag means it is part of the USA:
657                         http://en.wikipedia.org/wiki/Geographic_Names_Information_System
658                         many US towns do not have is_in tags
659                 */
660                 strcpy(is_in_buffer, "USA");
661                 level=5;
662         }
663         if (! strcmp(k,"lanes")) {
664                 level=5;
665         }
666         if (attr_debug_level >= level) {
667                 int bytes_left = sizeof( debug_attr_buffer ) - strlen(debug_attr_buffer) - 1;
668                 if ( bytes_left > 0 )
669                 {
670                         snprintf(debug_attr_buffer+strlen(debug_attr_buffer), bytes_left,  " %s=%s", k, v);
671                         debug_attr_buffer[ sizeof( debug_attr_buffer ) -  1 ] = '\0';
672                         node_is_tagged=1;
673                 }
674         }
675         if (level < 6)
676                 node_is_tagged=1;
677         if (level >= 5)
678                 return;
679
680         strcpy(buffer,"*=*");
681         if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
682                 attr_present[idx]=1;
683
684         sprintf(buffer,"%s=*", k);
685         if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
686                 attr_present[idx]=2;
687
688         sprintf(buffer,"*=%s", v);
689         if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
690                 attr_present[idx]=2;
691
692         sprintf(buffer,"%s=%s", k, v);
693         if ((idx=(int)g_hash_table_lookup(attr_hash, buffer)))
694                 attr_present[idx]=4;
695 }
696
697 struct entity {
698         char *entity;
699         char c;
700 } entities[]= {
701         {"&quot;",'"'},
702         {"&apos;",'\''},
703         {"&amp;",'&'},
704         {"&lt;",'<'},
705         {"&gt;",'>'},
706 };
707
708 static void
709 decode_entities(char *buffer)
710 {
711         char *pos=buffer;
712         int i,len,found;
713
714         while ((pos=strchr(pos, '&'))) {
715                 found=0;
716                 for (i = 0 ; i < sizeof(entities)/sizeof(struct entity); i++) {
717                         len=strlen(entities[i].entity);
718                         if (!strncmp(pos, entities[i].entity, len)) {
719                                 *pos=entities[i].c;
720                                 memmove(pos+1, pos+len, strlen(pos+len)+1);
721                                 found=1;
722                                 break;
723                         }
724                 }
725                 pos++;
726         }
727 }
728
729 static int
730 parse_tag(char *p)
731 {
732         char k_buffer[BUFFER_SIZE];
733         char v_buffer[BUFFER_SIZE];
734         if (!xml_get_attribute(p, "k", k_buffer, BUFFER_SIZE))
735                 return 0;
736         if (!xml_get_attribute(p, "v", v_buffer, BUFFER_SIZE))
737                 return 0;
738         decode_entities(v_buffer);
739         add_tag(k_buffer, v_buffer);
740         return 1;
741 }
742
743
744 struct buffer {
745         int malloced_step;
746         size_t malloced;
747         unsigned char *base;
748         size_t size;
749 };
750
751 static struct tile_head {
752         int num_subtiles;
753         int total_size;
754         char *name;
755         char *zip_data;
756         int total_size_used;
757         int zipnum;
758         int process;
759         struct tile_head *next;
760         // char subtiles[0];
761 } *tile_head_root;
762
763
764 int coord_count;
765
766 struct node_item {
767         int id;
768         char ref_node;
769         char ref_way;
770         char ref_ref;
771         char dummy;
772         struct coord c;
773 };
774
775 static struct buffer node_buffer = {
776         64*1024*1024,
777 };
778
779
780 static char** th_get_subtile( const struct tile_head* th, int idx )
781 {
782         char* subtile_ptr = NULL;
783         subtile_ptr = (char*)th + sizeof( struct tile_head ) + idx * sizeof( char *);
784         return (char**)subtile_ptr;
785 }
786
787 static void
788 extend_buffer(struct buffer *b)
789 {
790         b->malloced+=b->malloced_step;
791         b->base=realloc(b->base, b->malloced);
792         if (b->base == NULL) {
793                 fprintf(stderr,"realloc of %d bytes failed\n",b->malloced);
794                 exit(1);
795         }
796
797 }
798
799 int nodeid_last;
800 GHashTable *node_hash;
801
802 static void
803 node_buffer_to_hash(void)
804 {
805         int i,count=node_buffer.size/sizeof(struct node_item);
806         struct node_item *ni=(struct node_item *)node_buffer.base;
807         for (i = 0 ; i < count ; i++)
808                 g_hash_table_insert(node_hash, (gpointer)(ni[i].id), (gpointer)i);
809 }
810
811 static struct node_item *ni;
812
813 static void
814 add_node(int id, double lat, double lon)
815 {
816         if (node_buffer.size + sizeof(struct node_item) > node_buffer.malloced)
817                 extend_buffer(&node_buffer);
818         node_is_tagged=0;
819         nodeid=id;
820         item.type=type_point_unkn;
821         label_attr.len=0;
822         town_name_attr.len=0;
823         debug_attr.len=0;
824         is_in_buffer[0]='\0';
825         sprintf(debug_attr_buffer,"nodeid=%d", nodeid);
826         ni=(struct node_item *)(node_buffer.base+node_buffer.size);
827         ni->id=id;
828         ni->ref_node=0;
829         ni->ref_way=0;
830         ni->ref_ref=0;
831         ni->dummy=0;
832         ni->c.x=lon*6371000.0*M_PI/180;
833         ni->c.y=log(tan(M_PI_4+lat*M_PI/360))*6371000.0;
834         node_buffer.size+=sizeof(struct node_item);
835         if (! node_hash) {
836                 if (ni->id > nodeid_last) {
837                         nodeid_last=ni->id;
838                 } else {
839                         fprintf(stderr,"INFO: Nodes out of sequence (new %d vs old %d), adding hash\n", ni->id, nodeid_last);
840                         node_hash=g_hash_table_new(NULL, NULL);
841                         node_buffer_to_hash();
842                 }
843         } else
844                 if (!g_hash_table_lookup(node_hash, (gpointer)(ni->id)))
845                         g_hash_table_insert(node_hash, (gpointer)(ni->id), (gpointer)(ni-(struct node_item *)node_buffer.base));
846                 else {
847                         node_buffer.size-=sizeof(struct node_item);
848                         nodeid=0;
849                 }
850
851 }
852
853 static int
854 parse_node(char *p)
855 {
856         char id_buffer[BUFFER_SIZE];
857         char lat_buffer[BUFFER_SIZE];
858         char lon_buffer[BUFFER_SIZE];
859         if (!xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
860                 return 0;
861         if (!xml_get_attribute(p, "lat", lat_buffer, BUFFER_SIZE))
862                 return 0;
863         if (!xml_get_attribute(p, "lon", lon_buffer, BUFFER_SIZE))
864                 return 0;
865         add_node(atoi(id_buffer), atof(lat_buffer), atof(lon_buffer));
866         return 1;
867 }
868
869
870 static struct node_item *
871 node_item_get(int id)
872 {
873         struct node_item *ni=(struct node_item *)(node_buffer.base);
874         int count=node_buffer.size/sizeof(struct node_item);
875         int interval=count/4;
876         int p=count/2;
877         if (node_hash) {
878                 int i;
879                 i=(int)(g_hash_table_lookup(node_hash, (gpointer)id));
880                 return ni+i;
881         }
882         while (ni[p].id != id) {
883 #if 0
884                 fprintf(stderr,"p=%d count=%d interval=%d id=%d ni[p].id=%d\n", p, count, interval, id, ni[p].id);
885 #endif
886                 if (ni[p].id < id) {
887                         p+=interval;
888                         if (interval == 1) {
889                                 if (p >= count)
890                                         return NULL;
891                                 if (ni[p].id > id)
892                                         return NULL;
893                         } else {
894                                 if (p >= count)
895                                         p=count-1;
896                         }
897                 } else {
898                         p-=interval;
899                         if (interval == 1) {
900                                 if (p < 0)
901                                         return NULL;
902                                 if (ni[p].id < id)
903                                         return NULL;
904                         } else {
905                                 if (p < 0)
906                                         p=0;
907                         }
908                 }
909                 if (interval > 1)
910                         interval/=2;
911         }
912
913         return &ni[p];
914 }
915
916 static void
917 node_ref_way(int id)
918 {
919         struct node_item *ni=node_item_get(id);
920         if (! ni) {
921                 fprintf(stderr,"WARNING: node id %d not found\n", id);
922                 return;
923         }
924         ni->ref_way++;
925 }
926
927
928 static void
929 add_way(int id)
930 {
931         wayid=id;
932         coord_count=0;
933         item.type=type_street_unkn;
934         label_attr.len=0;
935         street_name_attr.len=0;
936         street_name_systematic_attr.len=0;
937         debug_attr.len=0;
938         flags_attr.len=0;
939         sprintf(debug_attr_buffer,"wayid=%d", wayid);
940 }
941
942 static int
943 parse_way(char *p)
944 {
945         char id_buffer[BUFFER_SIZE];
946         if (!xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
947                 return 0;
948         add_way(atoi(id_buffer));
949         return 1;
950 }
951
952 static int
953 parse_relation(char *p)
954 {
955         debug_attr_buffer[0]='\0';
956         return 1;
957 }
958
959 static void
960 write_attr(FILE *out, struct attr_bin *attr, void *buffer)
961 {
962         if (attr->len) {
963                 fwrite(attr, sizeof(*attr), 1, out);
964                 fwrite(buffer, (attr->len-1)*4, 1, out);
965         }
966 }
967
968 static int
969 attr_longest_match(struct attr_mapping **mapping, int mapping_count, enum item_type *types, int types_count)
970 {
971         int i,j,longest=0,ret=0,sum,val;
972         struct attr_mapping *curr;
973         for (i = 0 ; i < mapping_count ; i++) {
974                 sum=0;
975                 curr=mapping[i];
976                 for (j = 0 ; j < curr->attr_present_idx_count ; j++) {
977                         val=attr_present[curr->attr_present_idx[j]];
978                         if (val)
979                                 sum+=val;
980                         else {
981                                 sum=-1;
982                                 break;
983                         }
984                 }
985                 if (sum > longest) {
986                         longest=sum;
987                         ret=0;
988                 }
989                 if (sum > 0 && sum == longest && ret < types_count) 
990                         types[ret++]=curr->type;
991         }
992         memset(attr_present, 0, sizeof(*attr_present)*attr_present_count);
993         return ret;
994 }
995
996 static void
997 end_way(FILE *out)
998 {
999         int alen=0,count;
1000         enum item_type types[5];
1001
1002         if (! out)
1003                 return;
1004         if (dedupe_ways_hash) {
1005                 if (g_hash_table_lookup(dedupe_ways_hash, (gpointer)wayid))
1006                         return;
1007                 g_hash_table_insert(dedupe_ways_hash, (gpointer)wayid, (gpointer)1);
1008         }
1009         count=attr_longest_match(attr_mapping_way, attr_mapping_way_count, types, sizeof(types)/sizeof(enum item_type));
1010         pad_text_attr(&debug_attr, debug_attr_buffer);
1011         if (label_attr.len)
1012                 alen+=label_attr.len+1;
1013         if (street_name_systematic_attr.len)
1014                 alen+=street_name_systematic_attr.len+1;
1015         if (debug_attr.len)
1016                 alen+=debug_attr.len+1;
1017         if (flags_attr.len)
1018                 alen+=flags_attr.len+1;
1019         if (count)
1020                 item.type=types[0];
1021         else
1022                 item.type=type_street_unkn;
1023         if (coverage && item_is_street(item))
1024                 item.type=type_coverage;
1025         item.clen=coord_count*2;
1026         item.len=item.clen+2+alen;
1027         fwrite(&item, sizeof(item), 1, out);
1028         fwrite(coord_buffer, coord_count*sizeof(struct coord), 1, out);
1029         if (item_is_street(item)) {
1030                 street_name_attr.len=label_attr.len;
1031                 write_attr(out, &street_name_attr, label_attr_buffer);
1032         } else
1033                 write_attr(out, &label_attr, label_attr_buffer);
1034         write_attr(out, &street_name_systematic_attr, street_name_systematic_attr_buffer);
1035         write_attr(out, &debug_attr, debug_attr_buffer);
1036         write_attr(out, &flags_attr, &flags_attr_value);
1037 }
1038
1039 static void
1040 end_node(FILE *out)
1041 {
1042         int alen=0,conflict=0,count;
1043         enum item_type types[5];
1044         struct country_table *result=NULL, *lookup;
1045         if (!out || ! node_is_tagged || ! nodeid)
1046                 return;
1047         count=attr_longest_match(attr_mapping_node, attr_mapping_node_count, types, sizeof(types)/sizeof(enum item_type));
1048         pad_text_attr(&debug_attr, debug_attr_buffer);
1049         if (label_attr.len)
1050                 alen+=label_attr.len+1;
1051         if (debug_attr.len)
1052                 alen+=debug_attr.len+1;
1053         if (count)
1054                 item.type=types[0];
1055         else
1056                 item.type=type_point_unkn;
1057         item.clen=2;
1058         item.len=item.clen+2+alen;
1059         fwrite(&item, sizeof(item), 1, out);
1060         fwrite(&ni->c, 1*sizeof(struct coord), 1, out);
1061         if (item_is_town(item)) {
1062                 town_name_attr.len=label_attr.len;
1063                 write_attr(out, &town_name_attr, label_attr_buffer);
1064         } else
1065                 write_attr(out, &label_attr, label_attr_buffer);
1066         write_attr(out, &debug_attr, debug_attr_buffer);
1067 #ifdef GENERATE_INDEX
1068         if (item_is_town(item) && town_name_attr.len) {
1069                 char *tok,*buf=is_in_buffer;
1070                 while ((tok=strtok(buf, ","))) {
1071                         while (*tok==' ')
1072                                 tok++;
1073                         lookup=g_hash_table_lookup(country_table_hash,tok);
1074                         if (lookup) {
1075                                 if (result && result->countryid != lookup->countryid) {
1076                                         fprintf(stderr,"conflict for %s %s country %d vs %d\n", label_attr_buffer, debug_attr_buffer, lookup->countryid, result->countryid);
1077                                         conflict=1;
1078                                 } else
1079                                         result=lookup;
1080                         }
1081                         buf=NULL;
1082                 }
1083                 if (result && !conflict) {
1084                         if (!result->file) {
1085                                 char *name=g_strdup_printf("country_%d.bin.unsorted", result->countryid);
1086                                 result->file=fopen(name,"w");
1087                                 g_free(name);
1088                         }
1089                         if (result->file) {
1090                                 item.clen=2;
1091                                 item.len=item.clen+2+label_attr.len+1;
1092                                 fwrite(&item, sizeof(item), 1, result->file);
1093                                 fwrite(&ni->c, 1*sizeof(struct coord), 1, result->file);
1094                                 write_attr(result->file, &town_name_attr, label_attr_buffer);
1095                                 result->count++;
1096                                 result->size+=(item.clen+3+label_attr.len+1)*4;
1097                         }
1098                         
1099                 }
1100         }
1101 #endif
1102         processed_nodes_out++;
1103 }
1104
1105 static int
1106 sort_countries_compare(const void *p1, const void *p2)
1107 {
1108         struct item_bin *ib1=*((struct item_bin **)p1),*ib2=*((struct item_bin **)p2);
1109         struct attr_bin *attr1,*attr2;
1110         char *s1,*s2;
1111         assert(ib1->clen==2);
1112         assert(ib2->clen==2);
1113         attr1=(struct attr_bin *)((int *)(ib1+1)+ib1->clen);
1114         attr2=(struct attr_bin *)((int *)(ib2+1)+ib1->clen);
1115         assert(attr1->type == attr_town_name);
1116         assert(attr2->type == attr_town_name);
1117         s1=(char *)(attr1+1);
1118         s2=(char *)(attr2+1);
1119         return strcmp(s1, s2);
1120 #if 0
1121         fprintf(stderr,"sort_countries_compare p1=%p p2=%p %s %s\n",p1,p2,s1,s2);
1122 #endif
1123         return 0;
1124 }
1125
1126 #ifdef GENERATE_INDEX
1127 static void
1128 sort_countries(void)
1129 {
1130         int i,j;
1131         struct country_table *co;
1132         struct coord *c;
1133         struct item_bin *ib;
1134         FILE *f;
1135         char *p,*buffer,**idx,*name;
1136         for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
1137                 co=&country_table[i];
1138                 if (co->file) {
1139                         fclose(co->file);
1140                         co->file=NULL;
1141                 }
1142                 if (co->size) {
1143                         buffer=malloc(co->size);
1144                         assert(buffer != NULL);
1145                         idx=malloc(co->count*sizeof(void *));
1146                         assert(idx != NULL);
1147                         name=g_strdup_printf("country_%d.bin.unsorted", co->countryid);
1148                         f=fopen(name,"r");
1149                         assert(f != NULL);
1150                         fread(buffer, co->size, 1, f);
1151                         fclose(f);
1152                         unlink(name);
1153                         g_free(name);
1154                         p=buffer;
1155                         for (j = 0 ; j < co->count ; j++) {
1156                                 idx[j]=p;
1157                                 p+=(*((int *)p)+1)*4;
1158                         }
1159                         qsort(idx, co->count, sizeof(void *), sort_countries_compare);
1160                         name=g_strdup_printf("country_%d.bin", co->countryid);
1161                         f=fopen(name,"w");
1162                         for (j = 0 ; j < co->count ; j++) {
1163                                 ib=(struct item_bin *)(idx[j]);
1164                                 c=(struct coord *)(ib+1);
1165                                 fwrite(ib, (ib->len+1)*4, 1, f);
1166                                 if (j) 
1167                                         bbox_extend(c, &co->r);
1168                                 else
1169                                         co->r.l=*c;
1170                                         co->r.h=*c;
1171                         }
1172                         fclose(f);
1173                 }
1174         }
1175 }
1176 #endif
1177
1178 static void
1179 add_nd(char *p, int ref)
1180 {
1181         int len;
1182         struct node_item *ni;
1183         ni=node_item_get(ref);
1184         if (ni) {
1185 #if 0
1186                 coord_buffer[coord_count++]=ni->c;
1187 #else
1188                 SET_REF(coord_buffer[coord_count], ref);
1189                 coord_count++;
1190 #endif
1191                 ni->ref_way++;
1192         } else {
1193                 len=strlen(p);
1194                 if (len > 0 && p[len-1]=='\n')
1195                         p[len-1]='\0';
1196                 fprintf(stderr,"WARNING: way %d: node %d not found (%s)\n",wayid,ref,p);
1197         }
1198         if (coord_count > 65536) {
1199                 fprintf(stderr,"ERROR: Overflow\n");
1200                 exit(1);
1201         }
1202 }
1203
1204 static int
1205 parse_nd(char *p)
1206 {
1207         char ref_buffer[BUFFER_SIZE];
1208         if (!xml_get_attribute(p, "ref", ref_buffer, BUFFER_SIZE))
1209                 return 0;
1210         add_nd(p, atoi(ref_buffer));
1211         return 1;
1212 }
1213
1214
1215 static void
1216 save_buffer(char *filename, struct buffer *b)
1217 {
1218         FILE *f;
1219         f=fopen(filename,"wb+");
1220         fwrite(b->base, b->size, 1, f);
1221         fclose(f);
1222 }
1223
1224 static void
1225 load_buffer(char *filename, struct buffer *b)
1226 {
1227         FILE *f;
1228         if (b->base)
1229                 free(b->base);
1230         b->malloced=0;
1231         f=fopen(filename,"rb");
1232         fseek(f, 0, SEEK_END);
1233         b->size=b->malloced=ftell(f);
1234         fprintf(stderr,"reading %d bytes from %s\n", b->size, filename);
1235         fseek(f, 0, SEEK_SET);
1236         b->base=malloc(b->size);
1237         assert(b->base != NULL);
1238         fread(b->base, b->size, 1, f);
1239         fclose(f);
1240 }
1241
1242 static int
1243 phase1(FILE *in, FILE *out_ways, FILE *out_nodes)
1244 {
1245         int size=4096;
1246         char buffer[size];
1247         char *p;
1248         sig_alrm(0);
1249         while (fgets(buffer, size, in)) {
1250                 p=strchr(buffer,'<');
1251                 if (! p) {
1252                         fprintf(stderr,"WARNING: wrong line %s\n", buffer);
1253                         continue;
1254                 }
1255                 if (!strncmp(p, "<?xml ",6)) {
1256                 } else if (!strncmp(p, "<osm ",5)) {
1257                 } else if (!strncmp(p, "<bound ",7)) {
1258                 } else if (!strncmp(p, "<node ",6)) {
1259                         if (!parse_node(p))
1260                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1261                         in_node=1;
1262                         processed_nodes++;
1263                 } else if (!strncmp(p, "<tag ",5)) {
1264                         if (!parse_tag(p))
1265                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1266                 } else if (!strncmp(p, "<way ",5)) {
1267                         in_way=1;
1268                         if (!parse_way(p))
1269                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1270                         processed_ways++;
1271                 } else if (!strncmp(p, "<nd ",4)) {
1272                         if (!parse_nd(p))
1273                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1274                 } else if (!strncmp(p, "<relation ",10)) {
1275                         in_relation=1;
1276                         if (!parse_relation(p))
1277                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
1278                         processed_relations++;
1279                 } else if (!strncmp(p, "<member ",8)) {
1280                 } else if (!strncmp(p, "</node>",7)) {
1281                         in_node=0;
1282                         end_node(out_nodes);
1283                 } else if (!strncmp(p, "</way>",6)) {
1284                         in_way=0;
1285                         end_way(out_ways);
1286                 } else if (!strncmp(p, "</relation>",11)) {
1287                         in_relation=0;
1288                 } else if (!strncmp(p, "</osm>",6)) {
1289                 } else {
1290                         fprintf(stderr,"WARNING: unknown tag in %s\n", buffer);
1291                 }
1292         }
1293         sig_alrm(0);
1294         alarm(0);
1295         return 1;
1296 }
1297
1298 #ifdef HAVE_POSTGRESQL
1299 static int
1300 phase1_db(char *dbstr, FILE *out_ways, FILE *out_nodes)
1301 {
1302         PGconn *conn;
1303         PGresult *res,*node,*way,*tag;
1304         int count,tagged,i,j,k;
1305         long min, max, id, tag_id, node_id;
1306         char query[256];
1307         
1308         sig_alrm(0);
1309         conn=PQconnectdb(dbstr);
1310         if (! conn) {
1311                 fprintf(stderr,"Failed to connect to database with '%s'\n",dbstr);
1312                 exit(1);
1313         }
1314         res=PQexec(conn, "begin");
1315         if (! res) {
1316                 fprintf(stderr, "Cannot begin transaction: %s\n", PQerrorMessage(conn));
1317                 PQclear(res);
1318                 exit(1);
1319         }
1320         res=PQexec(conn, "set transaction isolation level serializable");
1321         if (! res) {
1322                 fprintf(stderr, "Cannot set isolation level: %s\n", PQerrorMessage(conn));
1323                 PQclear(res);
1324                 exit(1);
1325         }
1326         res=PQexec(conn, "declare node cursor for select id,x(coordinate),y(coordinate) from node order by id");
1327         if (! res) {
1328                 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1329                 PQclear(res);
1330                 exit(1);
1331         }
1332         res=PQexec(conn, "declare way cursor for select id from way order by id");
1333         if (! res) {
1334                 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1335                 PQclear(res);
1336                 exit(1);
1337         }
1338         res=PQexec(conn, "declare relation cursor for select id from relation order by id");
1339         if (! res) {
1340                 fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1341                 PQclear(res);
1342                 exit(1);
1343         }
1344         for (;;) {
1345                 node=PQexec(conn, "fetch 100000 from node");
1346                 if (! node) {
1347                         fprintf(stderr, "Cannot setup cursor for nodes: %s\n", PQerrorMessage(conn));
1348                         PQclear(node);
1349                         exit(1);
1350                 }
1351                 count=PQntuples(node);
1352                 if (! count)
1353                         break;
1354                 min=atol(PQgetvalue(node, 0, 0));
1355                 max=atol(PQgetvalue(node, count-1, 0));
1356                 sprintf(query,"select node_id,name,value from node_tag where node_id >= %ld and node_id <= %ld order by node_id", min, max);
1357                 tag=PQexec(conn, query);
1358                 if (! tag) {
1359                         fprintf(stderr, "Cannot query node_tag: %s\n", PQerrorMessage(conn));
1360                         exit(1);
1361                 }
1362                 j=0;
1363                 for (i = 0 ; i < count ; i++) {
1364                         id=atol(PQgetvalue(node, i, 0));
1365                         add_node(id, atof(PQgetvalue(node, i, 1)), atof(PQgetvalue(node, i, 2)));
1366                         tagged=0;
1367                         in_node=1;
1368                         processed_nodes++;
1369                         while (j < PQntuples(tag)) {
1370                                 tag_id=atol(PQgetvalue(tag, j, 0));
1371                                 if (tag_id == id) {
1372                                         add_tag(PQgetvalue(tag, j, 1), PQgetvalue(tag, j, 2));
1373                                         tagged=1;
1374                                         j++;
1375                                 }
1376                                 if (tag_id < id)
1377                                         j++;
1378                                 if (tag_id > id)
1379                                         break;
1380                         }
1381                         if (tagged)
1382                                 end_node(out_nodes);
1383                         in_node=0;
1384                 }
1385                 PQclear(tag);
1386                 PQclear(node);
1387         }
1388         for (;;) {
1389                 way=PQexec(conn, "fetch 100000 from way");
1390                 if (! way) {
1391                         fprintf(stderr, "Cannot setup cursor for ways: %s\n", PQerrorMessage(conn));
1392                         PQclear(node);
1393                         exit(1);
1394                 }
1395                 count=PQntuples(way);
1396                 if (! count)
1397                         break;
1398                 min=atol(PQgetvalue(way, 0, 0));
1399                 max=atol(PQgetvalue(way, count-1, 0));
1400                 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);
1401                 node=PQexec(conn, query);
1402                 if (! node) {
1403                         fprintf(stderr, "Cannot query way_node: %s\n", PQerrorMessage(conn));
1404                         exit(1);
1405                 }
1406                 sprintf(query,"select way_id,name,value from way_tag where way_id >= %ld and way_id <= %ld order by way_id", min, max);
1407                 tag=PQexec(conn, query);
1408                 if (! tag) {
1409                         fprintf(stderr, "Cannot query way_tag: %s\n", PQerrorMessage(conn));
1410                         exit(1);
1411                 }
1412                 j=0;
1413                 k=0;
1414                 for (i = 0 ; i < count ; i++) {
1415                         id=atol(PQgetvalue(way, i, 0));
1416                         add_way(id);
1417                         tagged=0;
1418                         in_way=1;
1419                         processed_ways++;
1420                         while (k < PQntuples(node)) {
1421                                 node_id=atol(PQgetvalue(node, k, 0));
1422                                 if (node_id == id) {
1423                                         add_nd("",atol(PQgetvalue(node, k, 1)));
1424                                         tagged=1;
1425                                         k++;
1426                                 }
1427                                 if (node_id < id)
1428                                         k++;
1429                                 if (node_id > id)
1430                                         break;
1431                         }
1432                         while (j < PQntuples(tag)) {
1433                                 tag_id=atol(PQgetvalue(tag, j, 0));
1434                                 if (tag_id == id) {
1435                                         add_tag(PQgetvalue(tag, j, 1), PQgetvalue(tag, j, 2));
1436                                         tagged=1;
1437                                         j++;
1438                                 }
1439                                 if (tag_id < id)
1440                                         j++;
1441                                 if (tag_id > id)
1442                                         break;
1443                         }
1444                         if (tagged)
1445                                 end_way(out_ways);
1446                         in_way=0;
1447                 }
1448                 PQclear(tag);
1449                 PQclear(node);
1450                 PQclear(way);
1451         }
1452
1453         res=PQexec(conn, "commit");
1454         if (! res) {
1455                 fprintf(stderr, "Cannot commit transaction: %s\n", PQerrorMessage(conn));
1456                 PQclear(res);
1457                 exit(1);
1458         }
1459         sig_alrm(0);
1460         alarm(0);
1461         return 1;
1462 }
1463 #endif
1464
1465 static char buffer[150000];
1466
1467 int bytes_read=0;
1468
1469 static struct item_bin *
1470 read_item(FILE *in)
1471 {
1472         struct item_bin *ib=(struct item_bin *) buffer;
1473         int r,s;
1474         r=fread(ib, sizeof(*ib), 1, in);
1475         if (r != 1)
1476                 return NULL;
1477         bytes_read+=r;
1478         assert((ib->len+1) < sizeof(buffer));
1479         s=(ib->len+1)*4-sizeof(*ib);
1480         r=fread(ib+1, s, 1, in);
1481         if (r != 1)
1482                 return NULL;
1483         bytes_read+=r;
1484         return ib;
1485 }
1486
1487 static void
1488 bbox_extend(struct coord *c, struct rect *r)
1489 {
1490         if (c->x < r->l.x)
1491                 r->l.x=c->x;
1492         if (c->y < r->l.y)
1493                 r->l.y=c->y;
1494         if (c->x > r->h.x)
1495                 r->h.x=c->x;
1496         if (c->y > r->h.y)
1497                 r->h.y=c->y;
1498 }
1499
1500 static void
1501 bbox(struct coord *c, int count, struct rect *r)
1502 {
1503         if (! count)
1504                 return;
1505         r->l=*c;
1506         r->h=*c;
1507         while (--count) {
1508                 c++;
1509                 bbox_extend(c, r);
1510         }
1511 }
1512
1513 static int
1514 contains_bbox(int xl, int yl, int xh, int yh, struct rect *r)
1515 {
1516         if (r->h.x < xl || r->h.x > xh) {
1517                 return 0;
1518         }
1519         if (r->l.x > xh || r->l.x < xl) {
1520                 return 0;
1521         }
1522         if (r->h.y < yl || r->h.y > yh) {
1523                 return 0;
1524         }
1525         if (r->l.y > yh || r->l.y < yl) {
1526                 return 0;
1527         }
1528         return 1;
1529
1530 }
1531 struct rect world_bbox = {
1532         { -20000000, -20000000},
1533         {  20000000,  20000000},
1534 };
1535
1536 static void
1537 tile(struct rect *r, char *ret, int max)
1538 {
1539         int x0,x1,x2,x3,x4;
1540         int y0,y1,y2,y3,y4;
1541         int i;
1542         x0=world_bbox.l.x;
1543         y0=world_bbox.l.y;
1544         x4=world_bbox.h.x;
1545         y4=world_bbox.h.y;
1546         for (i = 0 ; i < max ; i++) {
1547                 x2=(x0+x4)/2;
1548                 y2=(y0+y4)/2;
1549                 x1=(x0+x2)/2;
1550                 y1=(y0+y2)/2;
1551                 x3=(x2+x4)/2;
1552                 y3=(y2+y4)/2;
1553                 if (     contains_bbox(x0,y0,x2,y2,r)) {
1554                         strcat(ret,"d");
1555                         x4=x2;
1556                         y4=y2;
1557                 } else if (contains_bbox(x2,y0,x4,y2,r)) {
1558                         strcat(ret,"c");
1559                         x0=x2;
1560                         y4=y2;
1561                 } else if (contains_bbox(x0,y2,x2,y4,r)) {
1562                         strcat(ret,"b");
1563                         x4=x2;
1564                         y0=y2;
1565                 } else if (contains_bbox(x2,y2,x4,y4,r)) {
1566                         strcat(ret,"a");
1567                         x0=x2;
1568                         y0=y2;
1569                 } else
1570                         return;
1571         }
1572 }
1573
1574 static void
1575 tile_bbox(char *tile, struct rect *r)
1576 {
1577         struct coord c;
1578         *r=world_bbox;
1579         while (*tile) {
1580                 c.x=(r->l.x+r->h.x)/2;
1581                 c.y=(r->l.y+r->h.y)/2;
1582                 switch (*tile) {
1583                 case 'a':
1584                         r->l.x=c.x;
1585                         r->l.y=c.y;
1586                         break;
1587                 case 'b':
1588                         r->h.x=c.x;
1589                         r->l.y=c.y;
1590                         break;
1591                 case 'c':
1592                         r->l.x=c.x;
1593                         r->h.y=c.y;
1594                         break;
1595                 case 'd':
1596                         r->h.x=c.x;
1597                         r->h.y=c.y;
1598                         break;
1599                 }
1600                 tile++;
1601         }
1602 }
1603
1604 GHashTable *tile_hash;
1605 GHashTable *tile_hash2;
1606
1607 static void
1608 tile_extend(char *tile, struct item_bin *ib, GList **tiles_list)
1609 {
1610         struct tile_head *th=NULL;
1611         if (debug_tile(tile))
1612                 fprintf(stderr,"Tile:Writing %d bytes to '%s' (%p,%p)\n", (ib->len+1)*4, tile, g_hash_table_lookup(tile_hash, tile), tile_hash2 ? g_hash_table_lookup(tile_hash2, tile) : NULL);
1613         if (tile_hash2)
1614                 th=g_hash_table_lookup(tile_hash2, tile);
1615         if (!th)
1616                 th=g_hash_table_lookup(tile_hash, tile);
1617         if (! th) {
1618                 th=malloc(sizeof(struct tile_head)+ sizeof( char* ) );
1619                 assert(th != NULL);
1620                 // strcpy(th->subtiles, tile);
1621                 th->num_subtiles=1;
1622                 th->total_size=0;
1623                 th->total_size_used=0;
1624                 th->zipnum=0;
1625                 th->zip_data=NULL;
1626                 th->name=string_hash_lookup(tile);
1627                 *th_get_subtile( th, 0 ) = th->name;
1628
1629                 if (tile_hash2)
1630                         g_hash_table_insert(tile_hash2, string_hash_lookup( th->name ), th);
1631                 if (tiles_list)
1632                         *tiles_list=g_list_append(*tiles_list, string_hash_lookup( th->name ) );
1633                 processed_tiles++;
1634                 if (debug_tile(tile))
1635                         fprintf(stderr,"new '%s'\n", tile);
1636         }
1637         th->total_size+=ib->len*4+4;
1638         if (debug_tile(tile))
1639                 fprintf(stderr,"New total size of %s(%p):%d\n", th->name, th, th->total_size);
1640         g_hash_table_insert(tile_hash, string_hash_lookup( th->name ), th);
1641 }
1642
1643 static int
1644 tile_data_size(char *tile)
1645 {
1646         struct tile_head *th;
1647         th=g_hash_table_lookup(tile_hash, tile);
1648         if (! th)
1649                 return 0;
1650         return th->total_size;
1651 }
1652
1653 static int
1654 merge_tile(char *base, char *sub)
1655 {
1656         struct tile_head *thb, *ths;
1657         thb=g_hash_table_lookup(tile_hash, base);
1658         ths=g_hash_table_lookup(tile_hash, sub);
1659         if (! ths)
1660                 return 0;
1661         if (debug_tile(base) || debug_tile(sub))
1662                 fprintf(stderr,"merging '%s'(%p) (%d) with '%s'(%p) (%d)\n", base, thb, thb ? thb->total_size : 0, sub, ths, ths->total_size);
1663         if (! thb) {
1664                 thb=ths;
1665                 g_hash_table_remove(tile_hash, sub);
1666                 thb->name=string_hash_lookup(base);
1667                 g_hash_table_insert(tile_hash, string_hash_lookup( thb->name ), thb);
1668
1669         } else {
1670                 thb=realloc(thb, sizeof(struct tile_head)+( ths->num_subtiles+thb->num_subtiles ) * sizeof( char*) );
1671                 assert(thb != NULL);
1672                 memcpy( th_get_subtile( thb, thb->num_subtiles ), th_get_subtile( ths, 0 ), ths->num_subtiles * sizeof( char*) );
1673                 thb->num_subtiles+=ths->num_subtiles;
1674                 thb->total_size+=ths->total_size;
1675                 g_hash_table_insert(tile_hash, string_hash_lookup( thb->name ), thb);
1676                 g_hash_table_remove(tile_hash, sub);
1677                 g_free(ths);
1678         }
1679         return 1;
1680 }
1681
1682
1683 static void
1684 get_tiles_list_func(char *key, struct tile_head *th, GList **list)
1685 {
1686         *list=g_list_prepend(*list, key);
1687 }
1688
1689 static GList *
1690 get_tiles_list(void)
1691 {
1692         GList *ret=NULL;
1693         g_hash_table_foreach(tile_hash, (GHFunc)get_tiles_list_func, &ret);
1694         return ret;
1695 }
1696
1697 #if 0
1698 static void
1699 write_tile(char *key, struct tile_head *th, gpointer dummy)
1700 {
1701         FILE *f;
1702         char buffer[1024];
1703         fprintf(stderr,"DEBUG: Writing %s\n", key);
1704         strcpy(buffer,"tiles/");
1705         strcat(buffer,key);
1706 #if 0
1707         strcat(buffer,".bin");
1708 #endif
1709         f=fopen(buffer, "wb+");
1710         while (th) {
1711                 fwrite(th->data, th->size, 1, f);
1712                 th=th->next;
1713         }
1714         fclose(f);
1715 }
1716 #endif
1717
1718 static void
1719 write_item(char *tile, struct item_bin *ib)
1720 {
1721         struct tile_head *th;
1722         int size;
1723
1724         th=g_hash_table_lookup(tile_hash2, tile);
1725         if (! th)
1726                 th=g_hash_table_lookup(tile_hash, tile);
1727         if (th) {
1728                 if (th->process != 0 && th->process != 1) {
1729                         fprintf(stderr,"error with tile '%s' of length %d\n", tile, strlen(tile));
1730                         abort();
1731                 }
1732                 if (! th->process)
1733                         return;
1734                 if (debug_tile(tile))
1735                         fprintf(stderr,"Data:Writing %d bytes to '%s' (%p,%p)\n", (ib->len+1)*4, tile, g_hash_table_lookup(tile_hash, tile), tile_hash2 ? g_hash_table_lookup(tile_hash2, tile) : NULL);
1736                 size=(ib->len+1)*4;
1737                 if (th->total_size_used+size > th->total_size) {
1738                         fprintf(stderr,"Overflow in tile %s (used %d max %d item %d)\n", tile, th->total_size_used, th->total_size, size);
1739                         exit(1);
1740                         return;
1741                 }
1742                 memcpy(th->zip_data+th->total_size_used, ib, size);
1743                 th->total_size_used+=size;
1744         } else {
1745                 fprintf(stderr,"no tile hash found for %s\n", tile);
1746                 exit(1);
1747         }
1748 }
1749
1750
1751 static void
1752 write_item_part(FILE *out, struct item_bin *orig, int first, int last)
1753 {
1754         struct item_bin new;
1755         struct coord *c=(struct coord *)(orig+1);
1756         char *attr=(char *)(c+orig->clen/2);
1757         int attr_len=orig->len-orig->clen-2;
1758         processed_ways++;
1759         new.type=orig->type;
1760         new.clen=(last-first+1)*2;
1761         new.len=new.clen+attr_len+2;
1762 #if 0
1763         fprintf(stderr,"first %d last %d type 0x%x len %d clen %d attr_len %d\n", first, last, new.type, new.len, new.clen, attr_len);
1764 #endif
1765         fwrite(&new, sizeof(new), 1, out);
1766         fwrite(c+first, new.clen*4, 1, out);
1767         fwrite(attr, attr_len*4, 1, out);
1768 }
1769
1770 static int
1771 phase2(FILE *in, FILE *out)
1772 {
1773         struct coord *c;
1774         int i,ccount,last,ndref;
1775         struct item_bin *ib;
1776         struct node_item *ni;
1777
1778         processed_nodes=processed_nodes_out=processed_ways=processed_relations=processed_tiles=0;
1779         sig_alrm(0);
1780         while ((ib=read_item(in))) {
1781 #if 0
1782                 fprintf(stderr,"type 0x%x len %d clen %d\n", ib->type, ib->len, ib->clen);
1783 #endif
1784                 ccount=ib->clen/2;
1785                 c=(struct coord *)(ib+1);
1786                 last=0;
1787                 for (i = 0 ; i < ccount ; i++) {
1788                         if (IS_REF(c[i])) {
1789                                 ndref=REF(c[i]);
1790                                 ni=node_item_get(ndref);
1791 #if 0
1792                                 fprintf(stderr,"ni=%p\n", ni);
1793 #endif
1794                                 c[i]=ni->c;
1795                                 if (ni->ref_way > 1 && i != 0 && i != ccount-1 && item_is_street(*ib)) {
1796                                         write_item_part(out, ib, last, i);
1797                                         last=i;
1798                                 }
1799                         }
1800                 }
1801                 write_item_part(out, ib, last, ccount-1);
1802         }
1803         sig_alrm(0);
1804         alarm(0);
1805         return 0;
1806 }
1807
1808 static void
1809 phase34_process_file(int phase, FILE *in)
1810 {
1811         struct item_bin *ib;
1812         struct rect r;
1813         char buffer[1024];
1814         int max;
1815
1816         while ((ib=read_item(in))) {
1817                 if (ib->type < 0x80000000)
1818                         processed_nodes++;
1819                 else
1820                         processed_ways++;
1821                 bbox((struct coord *)(ib+1), ib->clen/2, &r);
1822                 buffer[0]='\0';
1823                 max=14;
1824                 if (ib->type == type_street_n_lanes || ib->type == type_highway_city || ib->type == type_highway_land || ib->type == type_ramp)
1825                         max=8;
1826                 if (ib->type == type_street_3_city || ib->type == type_street_4_city || ib->type == type_street_3_land || ib->type == type_street_4_land)
1827                         max=12;
1828
1829                 tile(&r, buffer, max);
1830 #if 0
1831                 fprintf(stderr,"%s\n", buffer);
1832 #endif
1833                 if (phase == 3)
1834                         tile_extend(buffer, ib, NULL);
1835                 else
1836                         write_item(buffer, ib);
1837         }
1838 }
1839
1840 struct index_item {
1841         struct item_bin item;
1842         struct rect r;
1843         struct attr_bin attr_order;
1844         short min;
1845         short max;
1846         struct attr_bin attr_zipfile_ref;
1847         int zipfile_ref;
1848 };
1849
1850 static void
1851 index_submap_add(int phase, struct tile_head *th, GList **tiles_list)
1852 {
1853         struct index_item ii;
1854         int len=strlen(th->name);
1855         char index_tile[len+1];
1856
1857         ii.min=(len > 4) ? len-4 : 0;
1858         ii.max=255;
1859         strcpy(index_tile, th->name);
1860         if (len > 6)
1861                 len=6;
1862         else
1863                 len=0;
1864         index_tile[len]=0;
1865         tile_bbox(th->name, &ii.r);
1866
1867         ii.item.len=sizeof(ii)/4-1;
1868         ii.item.type=type_submap;
1869         ii.item.clen=4;
1870
1871         ii.attr_order.len=2;
1872         ii.attr_order.type=attr_order;
1873
1874         ii.attr_zipfile_ref.len=2;
1875         ii.attr_zipfile_ref.type=attr_zipfile_ref;
1876         ii.zipfile_ref=th->zipnum;
1877
1878         if (phase == 3)
1879                 tile_extend(index_tile, (struct item_bin *)&ii, tiles_list);
1880         else
1881                 write_item(index_tile, (struct item_bin *)&ii);
1882 #if 0
1883         unsigned int *c=(unsigned int *)&ii;
1884         int i;
1885         for (i = 0 ; i < sizeof(ii)/4 ; i++) {
1886                 fprintf(stderr,"%08x ", c[i]);
1887         }
1888         fprintf(stderr,"\n");
1889 #endif
1890 }
1891
1892 static int
1893 add_tile_hash(struct tile_head *th)
1894 {
1895         int idx,len,maxnamelen=0;
1896         char **data;
1897
1898 #if 0
1899         g_hash_table_insert(tile_hash2, string_hash_lookup( th->name ), th);
1900 #endif
1901         for( idx = 0; idx < th->num_subtiles; idx++ ) {
1902
1903         data = th_get_subtile( th, idx );
1904
1905                 if (debug_tile(data) || debug_tile(th->name)) {
1906                         fprintf(stderr,"Parent for '%s' is '%s'\n", *data, th->name);
1907                 }
1908
1909                 g_hash_table_insert(tile_hash2, *data, th);
1910
1911                 len = strlen( *data );
1912
1913                 if (len > maxnamelen) {
1914                         maxnamelen=len;
1915                 }
1916         }
1917         return maxnamelen;
1918 }
1919
1920
1921 static int
1922 create_tile_hash(void)
1923 {
1924         struct tile_head *th;
1925         int len,maxnamelen=0;
1926
1927         tile_hash2=g_hash_table_new(g_str_hash, g_str_equal);
1928         th=tile_head_root;
1929         while (th) {
1930                 len=add_tile_hash(th);
1931                 if (len > maxnamelen)
1932                         maxnamelen=len;
1933                 th=th->next;
1934         }
1935         return maxnamelen;
1936 }
1937
1938 static void
1939 create_tile_hash_list(GList *list)
1940 {
1941         GList *next;
1942         struct tile_head *th;
1943
1944         tile_hash2=g_hash_table_new(g_str_hash, g_str_equal);
1945
1946         fprintf(stderr,"list=%p\n", list);
1947         next=g_list_first(list);
1948         while (next) {
1949                 th=g_hash_table_lookup(tile_hash, next->data);
1950                 if (!th) {
1951                         fprintf(stderr,"No tile found for '%s'\n", (char *)(next->data));
1952                 }
1953                 add_tile_hash(th);
1954                 next=g_list_next(next);
1955         }
1956 }
1957
1958 static void
1959 destroy_tile_hash(void)
1960 {
1961         g_hash_table_destroy(tile_hash2);
1962         tile_hash2=NULL;
1963 }
1964
1965 static int zipnum;
1966
1967 static void write_countrydir(int phase, int maxnamelen);
1968
1969 static void
1970 write_tilesdir(int phase, int maxlen, FILE *out)
1971 {
1972         int idx,len;
1973         GList *tiles_list,*next;
1974         char **data;
1975         struct tile_head *th,**last=NULL;
1976         zipnum=0;
1977
1978         tiles_list=get_tiles_list();
1979         if (phase == 3)
1980                 create_tile_hash_list(tiles_list);
1981         next=g_list_first(tiles_list);
1982         last=&tile_head_root;
1983         if (! maxlen) {
1984                 while (next) {
1985                         if (strlen(next->data) > maxlen)
1986                                 maxlen=strlen(next->data);
1987                         next=g_list_next(next);
1988                 }
1989         }
1990         len=maxlen;
1991         while (len >= 0) {
1992 #if 0
1993                 fprintf(stderr,"PROGRESS: collecting tiles with len=%d\n", len);
1994 #endif
1995 #ifdef GENERATE_INDEX
1996                 if (! len)
1997                         write_countrydir(phase, maxlen);
1998 #endif
1999                 next=g_list_first(tiles_list);
2000                 while (next) {
2001                         if (strlen(next->data) == len) {
2002                                 th=g_hash_table_lookup(tile_hash, next->data);
2003                                 if (phase == 3) {
2004                                         *last=th;
2005                                         last=&th->next;
2006                                         th->next=NULL;
2007                                         th->zipnum=zipnum;
2008                                         fprintf(out,"%s:%d",(char *)next->data,th->total_size);
2009
2010                                         for ( idx = 0; idx< th->num_subtiles; idx++ ){
2011                         data= th_get_subtile( th, idx );
2012                                                 fprintf(out,":%s", *data);
2013                                         }
2014
2015                                         fprintf(out,"\n");
2016                                 }
2017                                 if (th->name[0])
2018                                         index_submap_add(phase, th, &tiles_list);
2019                                 zipnum++;
2020                                 processed_tiles++;
2021                         }
2022                         next=g_list_next(next);
2023                 }
2024                 len--;
2025         }
2026 }
2027
2028 static void
2029 merge_tiles(void)
2030 {
2031         struct tile_head *th;
2032         char basetile[1024];
2033         char subtile[1024];
2034         GList *tiles_list_sorted,*last;
2035         int i,i_min,len,size_all,size[5],size_min,work_done;
2036         long long zip_size;
2037
2038         do {
2039                 tiles_list_sorted=get_tiles_list();
2040                 fprintf(stderr,"PROGRESS: sorting %d tiles\n", g_list_length(tiles_list_sorted));
2041                 tiles_list_sorted=g_list_sort(tiles_list_sorted, (GCompareFunc)strcmp);
2042                 fprintf(stderr,"PROGRESS: sorting %d tiles done\n", g_list_length(tiles_list_sorted));
2043                 last=g_list_last(tiles_list_sorted);
2044                 zip_size=0;
2045                 while (last) {
2046                         th=g_hash_table_lookup(tile_hash, last->data);
2047                         zip_size+=th->total_size;
2048                         last=g_list_previous(last);
2049                 }
2050                 fprintf(stderr,"DEBUG: size=%Ld\n", zip_size);
2051                 last=g_list_last(tiles_list_sorted);
2052                 work_done=0;
2053                 while (last) {
2054                         processed_tiles++;
2055                         len=strlen(last->data);
2056                         if (len >= 1) {
2057                                 strcpy(basetile,last->data);
2058                                 basetile[len-1]='\0';
2059                                 strcpy(subtile,last->data);
2060                                 for (i = 0 ; i < 4 ; i++) {
2061                                         subtile[len-1]='a'+i;
2062                                         size[i]=tile_data_size(subtile);
2063                                 }
2064                                 size[4]=tile_data_size(basetile);
2065                                 size_all=size[0]+size[1]+size[2]+size[3]+size[4];
2066                                 if (size_all < 65536 && size_all > 0 && size_all != size[4]) {
2067                                         for (i = 0 ; i < 4 ; i++) {
2068                                                 subtile[len-1]='a'+i;
2069                                                 work_done+=merge_tile(basetile, subtile);
2070                                         }
2071                                 } else {
2072                                         for (;;) {
2073                                                 size_min=size_all;
2074                                                 i_min=-1;
2075                                                 for (i = 0 ; i < 4 ; i++) {
2076                                                         if (size[i] && size[i] < size_min) {
2077                                                                 size_min=size[i];
2078                                                                 i_min=i;
2079                                                         }
2080                                                 }
2081                                                 if (i_min == -1)
2082                                                         break;
2083                                                 if (size[4]+size_min >= 65536)
2084                                                         break;
2085                                                 subtile[len-1]='a'+i_min;
2086                                                 work_done+=merge_tile(basetile, subtile);
2087                                                 size[4]+=size[i_min];
2088                                                 size[i_min]=0;
2089                                         }
2090                                 }
2091                         }
2092                         last=g_list_previous(last);
2093                 }
2094                 g_list_free(tiles_list_sorted);
2095                 fprintf(stderr,"PROGRESS: merged %d tiles\n", work_done);
2096         } while (work_done);
2097 }
2098
2099 struct country_index_item {
2100         struct item_bin item;
2101         struct attr_bin attr_country_id;
2102         int country_id;
2103         struct attr_bin attr_zipfile_ref;
2104         int zipfile_ref;
2105 };
2106
2107 static void
2108 index_country_add(int phase, int country_id, int zipnum)
2109 {
2110         struct country_index_item ii;
2111         char *index_tile="";
2112
2113         ii.item.len=sizeof(ii)/4-1;
2114         ii.item.type=type_countryindex;
2115         ii.item.clen=0;
2116
2117         ii.attr_country_id.len=2;
2118         ii.attr_country_id.type=attr_country_id;
2119         ii.country_id=country_id;
2120
2121         ii.attr_zipfile_ref.len=2;
2122         ii.attr_zipfile_ref.type=attr_zipfile_ref;
2123         ii.zipfile_ref=zipnum;
2124
2125         if (phase == 3)
2126                 tile_extend(index_tile, (struct item_bin *)&ii, NULL);
2127         else 
2128                 write_item(index_tile, (struct item_bin *)&ii);
2129 }
2130
2131 #ifdef GENERATE_INDEX
2132 struct aux_tile {
2133         char *name;
2134         char *filename;
2135         int size;
2136 };
2137
2138 static int
2139 add_aux_tile(int phase, char *name, char *filename, int size)
2140 {
2141         struct aux_tile *at;
2142         if (phase == 3) {
2143                 at=g_new0(struct aux_tile, 1);
2144                 at->name=g_strdup(name);
2145                 at->filename=g_strdup(filename);
2146                 at->size=size;
2147                 aux_tile_list=g_list_append(aux_tile_list, at);
2148         }
2149         return zipnum++;
2150 }
2151
2152 static int
2153 write_aux_tiles(FILE *out, FILE *dir_out, int compression_level, int namelen)
2154 {
2155         GList *l=aux_tile_list;
2156         struct aux_tile *at;
2157         char *buffer;
2158         FILE *f;
2159         int count=0;
2160         
2161         while (l) {
2162                 at=l->data;
2163                 buffer=malloc(at->size);
2164                 assert(buffer != NULL);
2165                 f=fopen(at->filename,"r");
2166                 assert(f != NULL);
2167                 fread(buffer, at->size, 1, f);
2168                 fclose(f);
2169                 write_zipmember(out, dir_out, at->name, namelen, buffer, at->size, compression_level);
2170                 count++;
2171                 l=g_list_next(l);
2172         }
2173         return count;
2174 }
2175
2176 static void
2177 write_countrydir(int phase, int maxnamelen)
2178 {
2179         int i,zipnum;
2180         int max=11;
2181         char tilename[32];
2182         char searchtile[32];
2183         char filename[32];
2184         struct country_table *co;
2185         for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
2186                 co=&country_table[i];
2187                 if (co->size) {
2188                         tilename[0]='\0';
2189                         tile(&co->r, tilename, max);
2190                         sprintf(searchtile,"%ss%d", tilename, 0);
2191                         sprintf(filename,"country_%d.bin", co->countryid);
2192                         zipnum=add_aux_tile(phase, searchtile, filename, co->size);
2193                         index_country_add(phase,co->countryid,zipnum);
2194                 }
2195         }
2196 }
2197
2198 static void
2199 remove_countryfiles(void)
2200 {
2201         int i;
2202         char filename[32];
2203         struct country_table *co;
2204
2205         for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
2206                 co=&country_table[i];
2207                 if (co->size) {
2208                         sprintf(filename,"country_%d.bin", co->countryid);
2209                         unlink(filename);
2210                 }
2211         }
2212 }
2213 #endif
2214
2215 static int
2216 phase34(int phase, int maxnamelen, FILE *ways_in, FILE *nodes_in, FILE *tilesdir_out)
2217 {
2218
2219         processed_nodes=processed_nodes_out=processed_ways=processed_relations=processed_tiles=0;
2220         bytes_read=0;
2221         sig_alrm(0);
2222         if (phase == 3)
2223                 tile_hash=g_hash_table_new(g_str_hash, g_str_equal);
2224         if (ways_in)
2225                 phase34_process_file(phase, ways_in);
2226         if (nodes_in)
2227                 phase34_process_file(phase, nodes_in);
2228         fprintf(stderr,"read %d bytes\n", bytes_read);
2229         if (phase == 3)
2230                 merge_tiles();
2231         sig_alrm(0);
2232         alarm(0);
2233         write_tilesdir(phase, maxnamelen, tilesdir_out);
2234
2235         return 0;
2236
2237 }
2238
2239 static void
2240 dump_coord(struct coord *c)
2241 {
2242         printf("0x%x 0x%x",c->x, c->y);
2243 }
2244
2245 static void
2246 dump(FILE *in)
2247 {
2248         struct item_bin *ib;
2249         struct coord *c;
2250         struct attr_bin *a;
2251         struct attr attr;
2252         int *attr_start;
2253         int *attr_end;
2254         int i;
2255         char *str;
2256         while ((ib=read_item(in))) {
2257                 c=(struct coord *)(ib+1);
2258                 if (ib->type < type_line) {
2259                         dump_coord(c);
2260                         printf(" ");
2261                 }
2262                 attr_start=(int *)(ib+1)+ib->clen;
2263                 attr_end=(int *)ib+ib->len+1;
2264                 printf("type=%s", item_to_name(ib->type));
2265                 while (attr_start < attr_end) {
2266                         a=(struct attr_bin *)(attr_start);
2267                         attr_start+=a->len+1;
2268                         attr.type=a->type;
2269                         attr_data_set(&attr, (a+1));
2270                         str=attr_to_text(&attr, NULL, 1);
2271                         printf(" %s=\"%s\"", attr_to_name(a->type), str);
2272                         g_free(str);
2273                 }
2274                 printf(" debug=\"length=%d\"", ib->len);
2275                 printf("\n");
2276                 if (ib->type >= type_line) {
2277                         for (i = 0 ; i < ib->clen/2 ; i++) {
2278                                 dump_coord(c+i);
2279                                 printf("\n");
2280                         }
2281                         
2282                 }
2283         }
2284 }
2285
2286 static int
2287 phase3(FILE *ways_in, FILE *nodes_in, FILE *tilesdir_out)
2288 {
2289         return phase34(3, 0, ways_in, nodes_in, tilesdir_out);
2290 }
2291
2292 static long long zipoffset;
2293 static int zipdir_size;
2294
2295 static int
2296 compress2_int(Byte *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
2297 {
2298         z_stream stream;
2299         int err;
2300
2301         stream.next_in = (Bytef*)source;
2302         stream.avail_in = (uInt)sourceLen;
2303         stream.next_out = dest;
2304         stream.avail_out = (uInt)*destLen;
2305         if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
2306
2307         stream.zalloc = (alloc_func)0;
2308         stream.zfree = (free_func)0;
2309         stream.opaque = (voidpf)0;
2310
2311         err = deflateInit2(&stream, level, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);
2312         if (err != Z_OK) return err;
2313
2314         err = deflate(&stream, Z_FINISH);
2315         if (err != Z_STREAM_END) {
2316                 deflateEnd(&stream);
2317                 return err == Z_OK ? Z_BUF_ERROR : err;
2318         }
2319         *destLen = stream.total_out;
2320
2321         err = deflateEnd(&stream);
2322         return err;
2323 }
2324
2325 static void
2326 write_zipmember(FILE *out, FILE *dir_out, char *name, int filelen, char *data, int data_size, int compression_level)
2327 {
2328         struct zip_lfh lfh = {
2329                 0x04034b50,
2330                 0x0a,
2331                 0x0,
2332                 0x0,
2333                 0xbe2a,
2334                 0x5d37,
2335                 0x0,
2336                 0x0,
2337                 0x0,
2338                 filelen,
2339                 0x0,
2340         };
2341         struct zip_cd cd = {
2342                 0x02014b50,
2343                 0x17,
2344                 0x00,
2345                 0x0a,
2346                 0x00,
2347                 0x0000,
2348                 0x0,
2349                 0xbe2a,
2350                 0x5d37,
2351                 0x0,
2352                 0x0,
2353                 0x0,
2354                 filelen,
2355                 0x0000,
2356                 0x0000,
2357                 0x0000,
2358                 0x0000,
2359                 0x0,
2360                 zipoffset,
2361         };
2362         char filename[filelen+1];
2363         int error,crc,len,comp_size=data_size;
2364         uLongf destlen=data_size+data_size/500+12;
2365         char compbuffer[destlen];
2366
2367         crc=crc32(0, NULL, 0);
2368         crc=crc32(crc, (unsigned char *)data, data_size);
2369         if (compression_level) {
2370                 error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, compression_level);
2371                 if (error == Z_OK) {
2372                         if (destlen < data_size) {
2373                                 data=compbuffer;
2374                                 comp_size=destlen;
2375                         }
2376                 } else {
2377                         fprintf(stderr,"compress2 returned %d\n", error);
2378                 }
2379         }
2380         lfh.zipcrc=crc;
2381         lfh.zipsize=comp_size;
2382         lfh.zipuncmp=data_size;
2383         lfh.zipmthd=compression_level ? 8:0;
2384         cd.zipccrc=crc;
2385         cd.zipcsiz=comp_size;
2386         cd.zipcunc=data_size;
2387         cd.zipcmthd=compression_level ? 8:0;
2388         strcpy(filename, name);
2389         len=strlen(filename);
2390         while (len < filelen) {
2391                 filename[len++]='_';
2392         }
2393         filename[filelen]='\0';
2394         fwrite(&lfh, sizeof(lfh), 1, out);
2395         fwrite(filename, filelen, 1, out);
2396         fwrite(data, comp_size, 1, out);
2397         zipoffset+=sizeof(lfh)+filelen+comp_size;
2398         fwrite(&cd, sizeof(cd), 1, dir_out);
2399         fwrite(filename, filelen, 1, dir_out);
2400         zipdir_size+=sizeof(cd)+filelen;
2401 }
2402
2403 static int
2404 process_slice(FILE *ways_in, FILE *nodes_in, int size, int maxnamelen, FILE *out, FILE *dir_out, int compression_level)
2405 {
2406         struct tile_head *th;
2407         char *slice_data,*zip_data;
2408         int zipfiles=0;
2409
2410         slice_data=malloc(size);
2411         assert(slice_data != NULL);
2412         zip_data=slice_data;
2413         th=tile_head_root;
2414         while (th) {
2415                 if (th->process) {
2416                         th->zip_data=zip_data;
2417                         zip_data+=th->total_size;
2418                 }
2419                 th=th->next;
2420         }
2421         if (ways_in)
2422                 fseek(ways_in, 0, SEEK_SET);
2423         if (nodes_in)
2424                 fseek(nodes_in, 0, SEEK_SET);
2425         phase34(4, maxnamelen, ways_in, nodes_in, NULL);
2426
2427         th=tile_head_root;
2428         while (th) {
2429                 if (th->process) {
2430 #ifdef GENERATE_INDEX
2431                         if (! strlen(th->name)) 
2432                                 zipfiles+=write_aux_tiles(out, dir_out, compression_level, maxnamelen);
2433 #endif
2434                         if (th->total_size != th->total_size_used) {
2435                                 fprintf(stderr,"Size error '%s': %d vs %d\n", th->name, th->total_size, th->total_size_used);
2436                                 exit(1);
2437                         } else {
2438                                 if (strlen(th->name))
2439                                         write_zipmember(out, dir_out, th->name, maxnamelen, th->zip_data, th->total_size, compression_level);
2440                                 else {
2441                                         write_zipmember(out, dir_out, "index", sizeof("index")-1, th->zip_data, th->total_size, compression_level);
2442                                 }
2443                                 zipfiles++;
2444                         }
2445                 }
2446                 th=th->next;
2447         }
2448         free(slice_data);
2449
2450         return zipfiles;
2451 }
2452
2453 static void
2454 cat(FILE *in, FILE *out)
2455 {
2456         size_t size;
2457         char buffer[4096];
2458         while ((size=fread(buffer, 1, 4096, in)))
2459                 fwrite(buffer, 1, size, out);
2460 }
2461
2462 static int
2463 phase4(FILE *ways_in, FILE *nodes_in, FILE *out, FILE *dir_out, int compression_level)
2464 {
2465         int slice_size=1024*1024*1024;
2466         int maxnamelen,size,slices;
2467         int zipfiles=0;
2468         struct tile_head *th,*th2;
2469         struct zip_eoc eoc = {
2470                 0x06054b50,
2471                 0x0000,
2472                 0x0000,
2473                 0x0000,
2474                 0x0000,
2475                 0x0,
2476                 0x0,
2477                 0x0,
2478         };
2479
2480         maxnamelen=create_tile_hash();
2481
2482         th=tile_head_root;
2483         size=0;
2484         slices=0;
2485         fprintf(stderr, "Maximum slice size %d\n", slice_size);
2486         while (th) {
2487                 if (size + th->total_size > slice_size) {
2488                         fprintf(stderr,"Slice %d is of size %d\n", slices, size);
2489                         size=0;
2490                         slices++;
2491                 }
2492                 size+=th->total_size;
2493                 th=th->next;
2494         }
2495         if (size)
2496                 fprintf(stderr,"Slice %d is of size %d\n", slices, size);
2497         th=tile_head_root;
2498         size=0;
2499         slices=0;
2500         while (th) {
2501                 th2=tile_head_root;
2502                 while (th2) {
2503                         th2->process=0;
2504                         th2=th2->next;
2505                 }
2506                 size=0;
2507                 while (th && size+th->total_size < slice_size) {
2508                         size+=th->total_size;
2509                         th->process=1;
2510                         th=th->next;
2511                 }
2512                 zipfiles+=process_slice(ways_in, nodes_in, size, maxnamelen, out, dir_out, compression_level);
2513                 slices++;
2514         }
2515         fseek(dir_out, 0, SEEK_SET);
2516         cat(dir_out, out);
2517         eoc.zipenum=zipfiles;
2518         eoc.zipecenn=zipfiles;
2519         eoc.zipecsz=zipdir_size;
2520         eoc.zipeofst=zipoffset;
2521         fwrite(&eoc, sizeof(eoc), 1, out);
2522         sig_alrm(0);
2523         alarm(0);
2524         return 0;
2525 }
2526
2527 static void
2528 usage(FILE *f)
2529 {
2530         fprintf(f,"\n");
2531         fprintf(f,"osm2navit - parse osm textfile and converts to NavIt binfile format\n\n");
2532         fprintf(f,"Usage :\n");
2533         fprintf(f,"bzcat planet.osm.bz2 | osm2navit mymap.bin\n");
2534         fprintf(f,"Available switches:\n");
2535         fprintf(f,"-h (--help)              : this screen\n");
2536         fprintf(f,"-N (--nodes-only)        : process only nodes\n");
2537         fprintf(f,"-W (--ways-only)         : process only ways\n");
2538         fprintf(f,"-a (--attr-debug-level)  : control which data is included in the debug attribute\n");
2539         fprintf(f,"-c (--dump-coordinates)  : dump coordinates after phase 1\n");
2540 #ifdef HAVE_POSTGRESQL
2541         fprintf(f,"-d (--db)                : get osm data out of a postgresql database with osm simple scheme and given connect string\n");
2542 #endif
2543         fprintf(f,"-e (--end)               : end at specified phase\n");
2544         fprintf(f,"-k (--keep-tmpfiles)     : do not delete tmp files after processing. useful to reuse them\n\n");
2545         fprintf(f,"-o (--coverage)          : map every street to item overage\n");
2546         fprintf(f,"-s (--start)             : start at specified phase\n");
2547         fprintf(f,"-i (--input-file)        : specify the input file name (OSM), overrules default stdin\n");
2548         fprintf(f,"-w (--dedupe-ways)       : ensure no duplicate ways or nodes. useful when using several input files\n");
2549         fprintf(f,"-z (--compression-level) : set the compression level\n");
2550         exit(1);
2551 }
2552
2553 static void
2554 process_binfile(FILE *in, FILE *out)
2555 {
2556         struct item_bin *ib;
2557         while ((ib=read_item(in))) {
2558                 fwrite(ib, (ib->len+1)*4, 1, out);
2559         }
2560 }
2561
2562 int main(int argc, char **argv)
2563 {
2564         FILE *ways=NULL,*ways_split=NULL,*nodes=NULL,*tilesdir,*zipdir,*res;
2565         char *map=g_strdup(attrmap);
2566         int i,c,start=1,end=4,dump_coordinates=0;
2567         int keep_tmpfiles=0;
2568         int process_nodes=1, process_ways=1;
2569         int compression_level=9;
2570         int output=0;
2571         int input=0;
2572         char *result,*dbstr=NULL;
2573         FILE* input_file = stdin;
2574         struct plugins *plugins=NULL;
2575         struct attr **attrs;
2576
2577         while (1) {
2578 #if 0
2579                 int this_option_optind = optind ? optind : 1;
2580 #endif
2581                 int option_index = 0;
2582                 static struct option long_options[] = {
2583                         {"attr-debug-level", 1, 0, 'a'},
2584                         {"binfile", 0, 0, 'b'},
2585                         {"compression-level", 1, 0, 'z'},
2586                         {"coverage", 0, 0, 'o'},
2587 #ifdef HAVE_POSTGRESQL
2588                         {"db", 1, 0, 'd'},
2589 #endif
2590                         {"dedupe-ways", 0, 0, 'w'},
2591                         {"dump", 0, 0, 'D'},
2592                         {"end", 1, 0, 'e'},
2593                         {"help", 0, 0, 'h'},
2594                         {"keep-tmpfiles", 0, 0, 'k'},
2595                         {"nodes-only", 0, 0, 'N'},
2596                         {"map", 1, 0, 'm'},
2597                         {"plugin", 1, 0, 'p'},
2598                         {"start", 1, 0, 's'},
2599                         {"input-file", 1, 0, 'i'},
2600                         {"ignore-unknown", 0, 0, 'n'},
2601                         {"ways-only", 0, 0, 'W'},
2602                         {0, 0, 0, 0}
2603                 };
2604                 c = getopt_long (argc, argv, "DNWa:bc"
2605 #ifdef HAVE_POSTGRESQL
2606                                               "d:"
2607 #endif
2608                                               "e:hi:knm:ps:w", long_options, &option_index);
2609                 if (c == -1)
2610                         break;
2611                 switch (c) {
2612                 case 'D':
2613                         output=1;
2614                         break;
2615                 case 'N':
2616                         process_ways=0;
2617                         break;
2618                 case 'W':
2619                         process_nodes=0;
2620                         break;
2621                 case 'a':
2622                         attr_debug_level=atoi(optarg);
2623                         break;
2624                 case 'b':
2625                         input=1;
2626                         break;
2627                 case 'c':
2628                         dump_coordinates=1;
2629                         break;
2630 #ifdef HAVE_POSTGRESQL
2631                 case 'd':
2632                         dbstr=optarg;
2633                         break;
2634 #endif
2635                 case 'e':
2636                         end=atoi(optarg);
2637                         break;
2638                 case 'h':
2639                         usage(stdout);
2640                         break;
2641                 case 'm':
2642                         attrs=(struct attr*[]){
2643                                 &(struct attr){attr_type,{"textfile"}},
2644                                 &(struct attr){attr_data,{"bookmark.txt"}},
2645                                 NULL};
2646                         map_new(attrs);
2647                         fprintf(stderr,"optarg=%s\n", optarg);
2648                         break;  
2649                 case 'n':
2650                         fprintf(stderr,"I will IGNORE unknown types\n");
2651                         ignore_unkown=1;
2652                         break;
2653                 case 'k':
2654                         fprintf(stderr,"I will KEEP tmp files\n");
2655                         keep_tmpfiles=1;
2656                         break;
2657                 case 'o':
2658                         coverage=1;
2659                         break;
2660                 case 'p':
2661                         if (! plugins)
2662                                 plugins=plugins_new();
2663                         attrs=(struct attr*[]){&(struct attr){attr_path,{optarg}},NULL};
2664                         plugins_add_path(plugins, attrs);       
2665                         break;
2666                 case 's':
2667                         start=atoi(optarg);
2668                         break;
2669                 case 'w':
2670                         dedupe_ways_hash=g_hash_table_new(NULL, NULL);
2671                         break;
2672                 case 'i':
2673                         input_file = fopen( optarg, "r" );
2674                         if ( input_file ==  NULL )
2675                         {
2676                             fprintf( stderr, "\nInput file (%s) not found\n", optarg );
2677                             exit( -1 );
2678                         }
2679                         break;
2680                 case 'z':
2681                         compression_level=atoi(optarg);
2682                         break;
2683                 case '?':
2684                         usage(stderr);
2685                         break;
2686                 default:
2687                         fprintf(stderr,"c=%d\n", c);
2688                 }
2689
2690         }
2691         if (optind != argc-(output == 1 ? 0:1))
2692                 usage(stderr);
2693         if (plugins)
2694                 plugins_init(plugins);
2695         result=argv[optind];
2696         build_attrmap(map);
2697 #ifdef GENERATE_INDEX
2698         build_countrytable();
2699 #endif
2700
2701
2702         if (input == 0) {
2703         if (start == 1) {
2704                 if (process_ways)
2705                         ways=fopen("ways.tmp","wb+");
2706                 if (process_nodes)
2707                         nodes=fopen("nodes.tmp","wb+");
2708                 phase=1;
2709                 fprintf(stderr,"PROGRESS: Phase 1: collecting data\n");
2710 #ifdef HAVE_POSTGRESQL
2711                 if (dbstr) 
2712                         phase1_db(dbstr,ways,nodes);
2713                 else
2714 #endif
2715                         phase1(input_file,ways,nodes);
2716                 if (ways)
2717                         fclose(ways);
2718                 if (nodes)
2719                         fclose(nodes);
2720 #ifdef GENERATE_INDEX
2721                 fprintf(stderr,"PROGRESS: Phase 1: sorting countries\n");
2722                 sort_countries();
2723 #endif
2724         }
2725         if (end == 1 || dump_coordinates)
2726                 save_buffer("coords.tmp",&node_buffer);
2727         if (end == 1)
2728                 exit(0);
2729         if (start == 2)
2730                 load_buffer("coords.tmp",&node_buffer);
2731         if (start <= 2) {
2732                 if (process_ways) {
2733                         ways=fopen("ways.tmp","rb");
2734                         ways_split=fopen("ways_split.tmp","wb+");
2735                         phase=2;
2736                         fprintf(stderr,"PROGRESS: Phase 2: finding intersections\n");
2737                         phase2(ways,ways_split);
2738                         fclose(ways_split);
2739                         fclose(ways);
2740                         if(!keep_tmpfiles)
2741                                 remove("ways.tmp");
2742                 } else
2743                         fprintf(stderr,"PROGRESS: Skipping Phase 2\n");
2744         }
2745         free(node_buffer.base);
2746         node_buffer.base=NULL;
2747         node_buffer.malloced=0;
2748         node_buffer.size=0;
2749         if (end == 2)
2750                 exit(0);
2751         } else {
2752                 ways_split=fopen("ways_split.tmp","wb+");
2753                 process_binfile(stdin, ways_split);
2754                 fclose(ways_split);
2755         }
2756         if (output == 1) {
2757                 fprintf(stderr,"PROGRESS: Phase 3: dumping\n");
2758                 if (process_nodes) {
2759                         nodes=fopen("nodes.tmp","rb");
2760                         if (nodes) {
2761                                 dump(nodes);
2762                                 fclose(nodes);
2763                         }
2764                 }
2765                 if (process_ways) {
2766                         ways_split=fopen("ways_split.tmp","rb");
2767                         if (ways_split) {
2768                                 dump(ways_split);
2769                                 fclose(ways_split);
2770                         }
2771                 }
2772                 exit(0);
2773         }
2774         if (start <= 3) {
2775                 phase=3;
2776                 fprintf(stderr,"PROGRESS: Phase 3: generating tiles\n");
2777                 if (process_ways)
2778                         ways_split=fopen("ways_split.tmp","rb");
2779                 if (process_nodes)
2780                         nodes=fopen("nodes.tmp","rb");
2781                 tilesdir=fopen("tilesdir.tmp","wb+");
2782                 phase3(ways_split,nodes,tilesdir);
2783                 fclose(tilesdir);
2784                 if (nodes)
2785                         fclose(nodes);
2786                 if (ways_split)
2787                         fclose(ways_split);
2788         }
2789         if (end == 3)
2790                 exit(0);
2791         if (start <= 4) {
2792                 phase=4;
2793                 fprintf(stderr,"PROGRESS: Phase 4: assembling map\n");
2794                 if (process_ways)
2795                         ways_split=fopen("ways_split.tmp","rb");
2796                 if (process_nodes)
2797                         nodes=fopen("nodes.tmp","rb");
2798                 res=fopen(result,"wb+");
2799                 zipdir=fopen("zipdir.tmp","wb+");
2800                 phase4(ways_split,nodes,res,zipdir,compression_level);
2801                 fclose(zipdir);
2802                 fclose(res);
2803                 if (nodes)
2804                         fclose(nodes);
2805                 if (ways_split)
2806                         fclose(ways_split);
2807                 if(!keep_tmpfiles) {
2808                         remove("nodes.tmp");
2809                         remove("ways_split.tmp");
2810                         remove("tilesdir.tmp");
2811                         remove("zipdir.tmp");
2812 #ifdef GENERATE_INDEX
2813                         remove_countryfiles();
2814 #endif
2815                 }
2816         }
2817         return 0;
2818 }