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