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