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