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