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