1 /*
2 Describe vectors containing file operations.
3
4 Copyright (C) 2002, 2004, 2005, 2006, 2007 Robert Lipe, robertlipe@usa.net
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
19
20 */
21
22 #include <stdio.h>
23 #include "defs.h"
24 #include "csv_util.h"
25 #include "inifile.h"
26 #include "gbversion.h"
27
28 #define MYNAME "vecs.c"
29
30 typedef struct {
31 ff_vecs_t *vec;
32 const char *name;
33 const char *desc;
34 const char *extension;
35 const char *parent;
36 } vecs_t;
37
38 extern ff_vecs_t an1_vecs;
39 extern ff_vecs_t axim_gpb_vecs;
40 extern ff_vecs_t bcr_vecs;
41 extern ff_vecs_t brauniger_iq_vecs;
42 extern ff_vecs_t cetus_vecs;
43 extern ff_vecs_t coastexp_vecs;
44 extern ff_vecs_t compegps_vecs;
45 extern ff_vecs_t copilot_vecs;
46 extern ff_vecs_t coto_vecs;
47 extern ff_vecs_t cst_vecs;
48 extern ff_vecs_t delbin_vecs;
49 extern ff_vecs_t dg100_vecs;
50 extern ff_vecs_t dg200_vecs;
51 extern ff_vecs_t easygps_vecs;
52 extern ff_vecs_t garmin_vecs;
53 extern ff_vecs_t garmin_txt_vecs;
54 extern ff_vecs_t gcdb_vecs;
55 extern ff_vecs_t gdb_vecs;
56 extern ff_vecs_t geoniche_vecs;
57 extern ff_vecs_t geo_vecs;
58 extern ff_vecs_t glogbook_vecs;
59 extern ff_vecs_t google_vecs;
60 extern ff_vecs_t gpilots_vecs;
61 extern ff_vecs_t gpl_vecs;
62 extern ff_vecs_t gpssim_vecs;
63 extern ff_vecs_t gpspilot_vecs;
64 extern ff_vecs_t gpsutil_vecs;
65 extern ff_vecs_t gpx_vecs;
66 extern ff_vecs_t gtm_vecs;
67 extern ff_vecs_t hiketech_vecs;
68 extern ff_vecs_t holux_vecs;
69 extern ff_vecs_t HsaEndeavourNavigator_vecs;
70 extern ff_vecs_t html_vecs;
71 extern ff_vecs_t igc_vecs;
72 extern ff_vecs_t ignr_vecs;
73 extern ff_vecs_t igo8_vecs;
74 extern ff_vecs_t kml_vecs;
75 extern ff_vecs_t lowranceusr_vecs;
76 extern ff_vecs_t lowranceusr4_vecs;
77 extern ff_vecs_t mag_fvecs;
78 extern ff_vecs_t maggeo_vecs;
79 extern ff_vecs_t magnav_vec;
80 extern ff_vecs_t magpdb_vecs;
81 extern ff_vecs_t mag_svecs;
82 extern ff_vecs_t magX_fvecs;
83 extern ff_vecs_t mapsend_vecs;
84 extern ff_vecs_t mps_vecs;
85 extern ff_vecs_t msroute_vecs;
86 extern ff_vecs_t mtk_vecs;
87 extern ff_vecs_t mtk_fvecs;
88 extern ff_vecs_t mtk_m241_vecs;
89 extern ff_vecs_t mtk_m241_fvecs;
90 extern ff_vecs_t navicache_vecs;
91 extern ff_vecs_t netstumbler_vecs;
92 extern ff_vecs_t nmea_vecs;
93 extern ff_vecs_t nmn4_vecs;
94 extern ff_vecs_t overlay_vecs;
95 extern ff_vecs_t ozi_vecs;
96 extern ff_vecs_t palmdoc_vecs;
97 extern ff_vecs_t pcx_vecs;
98 extern ff_vecs_t ppdb_vecs;
99 extern ff_vecs_t psit_vecs; /* MRCB */
100 extern ff_vecs_t psp_vecs;
101 extern ff_vecs_t quovadis_vecs;
102 extern ff_vecs_t saroute_vecs;
103 extern ff_vecs_t shape_vecs;
104 extern ff_vecs_t skytraq_vecs;
105 extern ff_vecs_t skytraq_fvecs;
106 extern ff_vecs_t miniHomer_vecs;
107 #if CSVFMTS_ENABLED
108 extern ff_vecs_t stmsdf_vecs;
109 #endif
110 #if CSVFMTS_ENABLED
111 extern ff_vecs_t stmwpp_vecs;
112 #endif
113 extern ff_vecs_t tef_xml_vecs;
114 extern ff_vecs_t text_vecs;
115 extern ff_vecs_t tiger_vecs;
116 extern ff_vecs_t tmpro_vecs;
117 extern ff_vecs_t tomtom_vecs;
118 extern ff_vecs_t tpg_vecs;
119 extern ff_vecs_t tpo2_vecs;
120 extern ff_vecs_t tpo3_vecs;
121 extern ff_vecs_t unicsv_vecs;
122 extern ff_vecs_t vcf_vecs;
123 extern ff_vecs_t vitosmt_vecs;
124 extern ff_vecs_t wfff_xml_vecs;
125 extern ff_vecs_t xcsv_vecs;
126 extern ff_vecs_t yahoo_vecs;
127 extern ff_vecs_t wbt_svecs;
128 extern ff_vecs_t wbt_fvecs;
129 extern ff_vecs_t gtc_vecs;
130 extern ff_vecs_t dmtlog_vecs;
131 extern ff_vecs_t raymarine_vecs;
132 extern ff_vecs_t alanwpr_vecs;
133 extern ff_vecs_t alantrl_vecs;
134 extern ff_vecs_t vitovtt_vecs;
135 extern ff_vecs_t ggv_log_vecs;
136 extern ff_vecs_t g7towin_vecs;
137 extern ff_vecs_t garmin_gpi_vecs;
138 extern ff_vecs_t lmx_vecs;
139 extern ff_vecs_t random_vecs;
140 extern ff_vecs_t xol_vecs;
141 extern ff_vecs_t navilink_vecs;
142 extern ff_vecs_t ik3d_vecs;
143 extern ff_vecs_t osm_vecs;
144 extern ff_vecs_t destinator_poi_vecs;
145 extern ff_vecs_t destinator_trl_vecs;
146 extern ff_vecs_t destinator_itn_vecs;
147 extern ff_vecs_t exif_vecs;
148 extern ff_vecs_t vidaone_vecs;
149 extern ff_vecs_t gopal_vecs;
150 extern ff_vecs_t humminbird_vecs;
151 extern ff_vecs_t humminbird_ht_vecs;
152 extern ff_vecs_t mapasia_tr7_vecs;
153 extern ff_vecs_t gnav_trl_vecs;
154 extern ff_vecs_t navitel_trk_vecs;
155 extern ff_vecs_t ggv_ovl_vecs;
156 #if CSVFMTS_ENABLED
157 extern ff_vecs_t jtr_vecs;
158 #endif
159 extern ff_vecs_t itracku_vecs;
160 extern ff_vecs_t itracku_fvecs;
161 extern ff_vecs_t sbp_vecs;
162 extern ff_vecs_t ng_vecs;
163 extern ff_vecs_t sbn_vecs;
164 extern ff_vecs_t mmo_vecs;
165 extern ff_vecs_t bushnell_vecs;
166 extern ff_vecs_t bushnell_trl_vecs;
167 extern ff_vecs_t skyforce_vecs;
168 extern ff_vecs_t v900_vecs;
169 extern ff_vecs_t pocketfms_bc_vecs;
170 extern ff_vecs_t pocketfms_fp_vecs;
171 extern ff_vecs_t pocketfms_wp_vecs;
172 extern ff_vecs_t enigma_vecs;
173 extern ff_vecs_t vpl_vecs;
174 extern ff_vecs_t teletype_vecs;
175 extern ff_vecs_t jogmap_vecs;
176 extern ff_vecs_t wintec_tes_vecs;
177 extern ff_vecs_t subrip_vecs;
178 extern ff_vecs_t format_garmin_xt_vecs;
179 extern ff_vecs_t format_fit_vecs;
180
181 static
182 vecs_t vec_list[] = {
183 #if CSVFMTS_ENABLED
184 /* XCSV must be the first entry in this table. */
185 {
186 &xcsv_vecs,
187 "xcsv",
188 "? Character Separated Values",
189 NULL
190 },
191 #endif
192 {
193 &geo_vecs,
194 "geo",
195 "Geocaching.com .loc",
196 "loc"
197 },
198 {
199 &gpx_vecs,
200 "gpx",
201 "GPX XML",
202 "gpx"
203 },
204 {
205 &mag_svecs,
206 "magellan",
207 "Magellan serial protocol",
208 NULL
209 },
210 {
211 &mag_fvecs,
212 "magellan",
213 "Magellan SD files (as for Meridian)",
214 NULL
215 },
216 {
217 &magX_fvecs,
218 "magellanx",
219 "Magellan SD files (as for eXplorist)",
220 "upt"
221 },
222 {
223 &garmin_vecs,
224 "garmin",
225 "Garmin serial/USB protocol",
226 NULL
227 },
228 {
229 &gdb_vecs,
230 "gdb",
231 "Garmin MapSource - gdb",
232 "gdb"
233 },
234 {
235 >c_vecs,
236 "gtrnctr",
237 "Garmin Training Center",
238 "xml"
239 },
240 {
241 &mapsend_vecs,
242 "mapsend",
243 "Magellan Mapsend",
244 NULL
245 },
246 {
247 &mps_vecs,
248 "mapsource",
249 "Garmin MapSource - mps",
250 "mps"
251 },
252 {
253 &nmea_vecs,
254 "nmea",
255 "NMEA 0183 sentences",
256 NULL
257 },
258 {
259 &ozi_vecs,
260 "ozi",
261 "OziExplorer",
262 NULL
263 },
264 {
265 &pcx_vecs,
266 "pcx",
267 "Garmin PCX5",
268 "pcx"
269 },
270 {
271 &kml_vecs,
272 "kml",
273 "Google Earth (Keyhole) Markup Language",
274 "kml"
275 },
276 #if MAXIMAL_ENABLED
277 {
278 &gpsutil_vecs,
279 "gpsutil",
280 "gpsutil",
281 NULL
282 },
283 {
284 &psp_vecs,
285 "psp",
286 "MS PocketStreets 2002 Pushpin",
287 "psp"
288 },
289 {
290 &lowranceusr_vecs,
291 "lowranceusr",
292 "Lowrance USR",
293 "usr"
294 },
295 {
296 &lowranceusr4_vecs,
297 "lowranceusr4",
298 "Lowrance USR version 4",
299 "usr"
300 },
301 #if PDBFMTS_ENABLED
302 {
303 &cetus_vecs,
304 "cetus",
305 "Cetus for Palm/OS",
306 "pdb"
307 },
308 {
309 &copilot_vecs,
310 "copilot",
311 "CoPilot Flight Planner for Palm/OS",
312 "pdb"
313 },
314 {
315 &gpspilot_vecs,
316 "gpspilot",
317 "GPSPilot Tracker for Palm/OS",
318 "pdb"
319 },
320 {
321 &magnav_vec,
322 "magnav",
323 "Magellan NAV Companion for Palm/OS",
324 "pdb"
325 },
326 #endif /* PDBFMTS_ENABLED */
327 {
328 &holux_vecs,
329 "holux",
330 "Holux (gm-100) .wpo Format",
331 "wpo"
332 },
333 {
334 &tpg_vecs,
335 "tpg",
336 "National Geographic Topo .tpg (waypoints)",
337 "tpg"
338 },
339 {
340 &tpo2_vecs,
341 "tpo2",
342 "National Geographic Topo 2.x .tpo",
343 "tpo"
344 },
345 {
346 &tpo3_vecs,
347 "tpo3",
348 "National Geographic Topo 3.x/4.x .tpo",
349 "tpo"
350 },
351 {
352 &tmpro_vecs,
353 "tmpro",
354 "TopoMapPro Places File",
355 "tmpro"
356 },
357 #if PDBFMTS_ENABLED
358 {
359 &gcdb_vecs,
360 "gcdb",
361 "GeocachingDB for Palm/OS",
362 "pdb"
363 },
364 #endif
365 {
366 &tiger_vecs,
367 "tiger",
368 "U.S. Census Bureau Tiger Mapping Service",
369 NULL
370 },
371 {
372 &easygps_vecs,
373 "easygps",
374 "EasyGPS binary format",
375 "loc"
376 },
377 #if PDBFMTS_ENABLED
378 {
379 &quovadis_vecs,
380 "quovadis",
381 "Quovadis",
382 "pdb"
383 },
384 {
385 &gpilots_vecs,
386 "gpilots",
387 "GpilotS",
388 "pdb"
389 },
390 #endif
391 {
392 &saroute_vecs,
393 "saroute",
394 "DeLorme Street Atlas Route",
395 "anr"
396 },
397 {
398 &navicache_vecs,
399 "navicache",
400 "Navicache.com XML",
401 NULL
402 },
403 {
404 &coastexp_vecs,
405 "coastexp",
406 "CoastalExplorer XML",
407 NULL
408 },
409 { /* MRCB */
410 &psit_vecs,
411 "psitrex",
412 "KuDaTa PsiTrex text",
413 NULL
414 },
415 #if SHAPELIB_ENABLED
416 {
417 &shape_vecs,
418 "shape",
419 "ESRI shapefile",
420 "shp"
421 },
422 #endif
423 #if PDBFMTS_ENABLED
424 {
425 &geoniche_vecs,
426 "geoniche",
427 "GeoNiche .pdb",
428 "pdb"
429 },
430 #endif
431 {
432 &gpl_vecs,
433 "gpl",
434 "DeLorme GPL",
435 "gpl"
436 },
437 {
438 &text_vecs,
439 "text",
440 "Textual Output",
441 "txt"
442 },
443 {
444 &html_vecs,
445 "html",
446 "HTML Output",
447 "html"
448 },
449 #if PDBFMTS_ENABLED
450 {
451 &palmdoc_vecs,
452 "palmdoc",
453 "PalmDoc Output",
454 "pdb"
455 },
456 #endif
457 {
458 &netstumbler_vecs,
459 "netstumbler",
460 "NetStumbler Summary File (text)",
461 NULL
462 },
463 {
464 &HsaEndeavourNavigator_vecs,
465 "hsandv",
466 "HSA Endeavour Navigator export File",
467 NULL
468 },
469 {
470 &igc_vecs,
471 "igc",
472 "FAI/IGC Flight Recorder Data Format",
473 NULL
474 },
475 {
476 &brauniger_iq_vecs,
477 "baroiq",
478 "Brauniger IQ Series Barograph Download",
479 NULL
480 },
481 {
482 &mtk_vecs,
483 "mtk",
484 "MTK Logger (iBlue 747,Qstarz BT-1000,...) download",
485 NULL
486 },
487 {
488 &mtk_fvecs,
489 "mtk-bin",
490 "MTK Logger (iBlue 747,...) Binary File Format",
491 "bin"
492 },
493 {
494 &mtk_m241_vecs,
495 "m241",
496 "Holux M-241 (MTK based) download",
497 NULL
498 },
499 {
500 &mtk_m241_fvecs,
501 "m241-bin",
502 "Holux M-241 (MTK based) Binary File Format",
503 "bin"
504 },
505 #endif // MAXIMAL_ENABLED
506 {
507 &wbt_svecs,
508 "wbt",
509 "Wintec WBT-100/200 GPS Download",
510 NULL
511 },
512 #if MAXIMAL_ENABLED
513 {
514 &vpl_vecs,
515 "vpl",
516 "Honda/Acura Navigation System VP Log File Format",
517 NULL
518 },
519 {
520 &wbt_fvecs,
521 "wbt-bin",
522 "Wintec WBT-100/200 Binary File Format",
523 "bin"
524 },
525 {
526 &wbt_fvecs,
527 "wbt-tk1",
528 "Wintec WBT-201/G-Rays 2 Binary File Format",
529 "tk1"
530 },
531 {
532 &hiketech_vecs,
533 "hiketech",
534 "HikeTech",
535 "gps"
536 },
537 {
538 &glogbook_vecs,
539 "glogbook",
540 "Garmin Logbook XML",
541 "xml"
542 },
543 {
544 &vcf_vecs,
545 "vcard",
546 "Vcard Output (for iPod)",
547 "vcf",
548 },
549 #if 0
550 {
551 &overlay_vecs,
552 "overlay",
553 "Geogrid-Viewer",
554 "ovl"
555 },
556 #endif
557 {
558 &google_vecs,
559 "google",
560 "Google Maps XML",
561 "xml"
562 },
563 {
564 &maggeo_vecs,
565 "maggeo",
566 "Magellan Explorist Geocaching",
567 "gs"
568 },
569 {
570 &an1_vecs,
571 "an1",
572 "DeLorme .an1 (drawing) file",
573 "an1"
574 },
575 {
576 &tomtom_vecs,
577 "tomtom",
578 "TomTom POI file (.ov2)",
579 "ov2"
580 },
581 {
582 &tef_xml_vecs,
583 "tef",
584 "Map&Guide 'TourExchangeFormat' XML",
585 "xml"
586 },
587 #if PDBFMTS_ENABLED
588 {
589 &ppdb_vecs,
590 "pathaway",
591 "PathAway Database for Palm/OS",
592 "pdb"
593 },
594 #endif
595 {
596 &vitosmt_vecs,
597 "vitosmt",
598 "Vito Navigator II tracks",
599 "smt"
600 },
601 {
602 &wfff_xml_vecs,
603 "wfff",
604 "WiFiFoFum 2.0 for PocketPC XML",
605 "xml"
606 },
607 {
608 &bcr_vecs,
609 "bcr",
610 "Motorrad Routenplaner (Map&Guide) .bcr files",
611 "bcr"
612 },
613 #if PDBFMTS_ENABLED
614 {
615 &coto_vecs,
616 "coto",
617 "cotoGPS for Palm/OS",
618 "pdb"
619 },
620 #endif
621 {
622 &ignr_vecs,
623 "ignrando",
624 "IGN Rando track files",
625 "rdn"
626 },
627 #if CSVFMTS_ENABLED
628 {
629 &stmsdf_vecs,
630 "stmsdf",
631 "Suunto Trek Manager (STM) .sdf files",
632 "sdf"
633 },
634 #endif
635 #if CSVFMTS_ENABLED
636 {
637 &stmwpp_vecs,
638 "stmwpp",
639 "Suunto Trek Manager (STM) WaypointPlus files",
640 "txt"
641 },
642 #endif // CSVFMTS_ENABLED
643 {
644 &msroute_vecs,
645 "msroute",
646 "Microsoft AutoRoute 2002 (pin/route reader)",
647 "axe"
648 },
649 {
650 &msroute_vecs,
651 "msroute",
652 "Microsoft Streets and Trips (pin/route reader)" ,
653 "est"
654 },
655 {
656 &cst_vecs,
657 "cst",
658 "CarteSurTable data file",
659 "cst"
660 },
661 {
662 &nmn4_vecs,
663 "nmn4",
664 "Navigon Mobile Navigator .rte files",
665 "rte"
666 },
667 #if PDBFMTS_ENABLED
668 {
669 &magpdb_vecs,
670 "mag_pdb",
671 "Map&Guide to Palm/OS exported files (.pdb)",
672 "pdb"
673 },
674 #endif
675 #if CSVFMTS_ENABLED
676 {
677 &compegps_vecs,
678 "compegps",
679 "CompeGPS data files (.wpt/.trk/.rte)",
680 NULL
681 },
682 #endif //CSVFMTS_ENABLED
683 {
684 &yahoo_vecs,
685 "yahoo",
686 "Yahoo Geocode API data",
687 NULL
688 },
689 {
690 &unicsv_vecs,
691 "unicsv",
692 "Universal csv with field structure in first line",
693 NULL
694 },
695 {
696 >m_vecs,
697 "gtm",
698 "GPS TrackMaker",
699 "gtm"
700 },
701 {
702 &gpssim_vecs,
703 "gpssim",
704 "Franson GPSGate Simulation",
705 "gpssim"
706 },
707 #if CSVFMTS_ENABLED
708 {
709 &garmin_txt_vecs,
710 "garmin_txt",
711 "Garmin MapSource - txt (tab delimited)",
712 "txt"
713 },
714 #endif // CSVFMTS_ENABLED
715 {
716 &axim_gpb_vecs,
717 "axim_gpb",
718 "Dell Axim Navigation System (.gpb) file format",
719 "gpb"
720 },
721 {
722 >c_vecs,
723 "gtrnctr",
724 "Garmin Training Center (.tcx)",
725 "xml"
726 },
727 {
728 &dmtlog_vecs,
729 "dmtlog",
730 "TrackLogs digital mapping (.trl)",
731 "trl"
732 },
733 {
734 &raymarine_vecs,
735 "raymarine",
736 "Raymarine Waypoint File (.rwf)",
737 "rwf"
738 },
739 {
740 &alanwpr_vecs,
741 "alanwpr",
742 "Alan Map500 waypoints and routes (.wpr)",
743 "wpr"
744 },
745 {
746 &alantrl_vecs,
747 "alantrl",
748 "Alan Map500 tracklogs (.trl)",
749 "trl"
750 },
751 {
752 &vitovtt_vecs,
753 "vitovtt",
754 "Vito SmartMap tracks (.vtt)",
755 "vtt"
756 },
757 {
758 &ggv_log_vecs,
759 "ggv_log",
760 "Geogrid-Viewer tracklogs (.log)",
761 "log"
762 },
763 #if CSVFMTS_ENABLED
764 {
765 &g7towin_vecs,
766 "g7towin",
767 "G7ToWin data files (.g7t)",
768 "g7t"
769 },
770 #endif
771 {
772 &garmin_gpi_vecs,
773 "garmin_gpi",
774 "Garmin Points of Interest (.gpi)",
775 "gpi"
776 },
777 {
778 &lmx_vecs,
779 "lmx",
780 "Nokia Landmark Exchange",
781 NULL
782 },
783 {
784 &random_vecs,
785 "random",
786 "Internal GPS data generator",
787 NULL
788 },
789 {
790 &xol_vecs,
791 "xol",
792 "Swiss Map 25/50/100 (.xol)",
793 "xol"
794 },
795 {
796 &dg100_vecs,
797 "dg-100",
798 "GlobalSat DG-100/BT-335 Download",
799 NULL
800 },
801 {
802 &dg200_vecs,
803 "dg-200",
804 "GlobalSat DG-200 Download",
805 NULL
806 },
807 {
808 &navilink_vecs,
809 "navilink",
810 "NaviGPS GT-11/BGT-11 Download",
811 NULL
812 },
813 {
814 &ik3d_vecs,
815 "ik3d",
816 "MagicMaps IK3D project file (.ikt)",
817 "ikt"
818 },
819 {
820 &osm_vecs,
821 "osm",
822 "OpenStreetMap data files",
823 "osm"
824 },
825 {
826 &destinator_poi_vecs,
827 "destinator_poi",
828 "Destinator Points of Interest (.dat)",
829 "dat"
830 },
831 {
832 &destinator_itn_vecs,
833 "destinator_itn",
834 "Destinator Itineraries (.dat)",
835 "dat"
836 },
837 {
838 &destinator_trl_vecs,
839 "destinator_trl",
840 "Destinator TrackLogs (.dat)",
841 "dat"
842 },
843 {
844 &exif_vecs,
845 "exif",
846 "Embedded Exif-GPS data (.jpg)",
847 "jpg"
848 },
849 {
850 &vidaone_vecs,
851 "vidaone",
852 "VidaOne GPS for Pocket PC (.gpb)",
853 "gpb"
854 },
855 {
856 &igo8_vecs,
857 "igo8",
858 "IGO8 .trk",
859 "trk"
860 },
861 {
862 &gopal_vecs,
863 "gopal",
864 "GoPal GPS track log (.trk)",
865 "trk"
866 },
867 {
868 &humminbird_vecs,
869 "humminbird",
870 "Humminbird waypoints and routes (.hwr)",
871 "hwr"
872 },
873 {
874 &humminbird_ht_vecs,
875 "humminbird_ht",
876 "Humminbird tracks (.ht)",
877 "ht"
878 },
879 {
880 &mapasia_tr7_vecs,
881 "mapasia_tr7",
882 "MapAsia track file (.tr7)",
883 "tr7"
884 },
885 {
886 &gnav_trl_vecs,
887 "gnav_trl",
888 "Google Navigator Tracklines (.trl)",
889 "trl"
890 },
891 {
892 &navitel_trk_vecs,
893 "navitel_trk",
894 "Navitel binary track (.bin)",
895 "bin"
896 },
897 {
898 &ggv_ovl_vecs,
899 "ggv_ovl",
900 "Geogrid-Viewer ascii overlay file (.ovl)",
901 "ovl"
902 },
903 #if CSVFMTS_ENABLED
904 {
905 &jtr_vecs,
906 "jtr",
907 "Jelbert GeoTagger data file",
908 "jtr"
909 },
910 #endif
911 {
912 &itracku_vecs,
913 "itracku",
914 "XAiOX iTrackU Logger",
915 NULL
916 },
917
918 {
919 &itracku_fvecs,
920 "itracku-bin",
921 "XAiOX iTrackU Logger Binary File Format",
922 "bin"
923 },
924 {
925 &sbp_vecs,
926 "sbp",
927 "NaviGPS GT-31/BGT-31 datalogger (.sbp)",
928 "sbp"
929 },
930 {
931 &sbn_vecs,
932 "sbn",
933 "NaviGPS GT-31/BGT-31 SiRF binary logfile (.sbn)",
934 "sbn"
935 },
936 {
937 &mmo_vecs,
938 "mmo",
939 "Memory-Map Navigator overlay files (.mmo)",
940 "mmo"
941 },
942 {
943 &bushnell_vecs,
944 "bushnell",
945 "Bushnell GPS Waypoint file",
946 "wpt"
947 },
948 {
949 &bushnell_trl_vecs,
950 "bushnell_trl",
951 "Bushnell GPS Trail file",
952 "trl"
953 },
954 {
955 &skyforce_vecs,
956 "skyforce",
957 "Skymap / KMD150 ascii files",
958 NULL
959 },
960 {
961 &pocketfms_bc_vecs,
962 "pocketfms_bc",
963 "PocketFMS breadcrumbs",
964 NULL
965 },
966 {
967 &pocketfms_fp_vecs,
968 "pocketfms_fp",
969 "PocketFMS flightplan (.xml)",
970 "xml"
971 },
972 {
973 &pocketfms_wp_vecs,
974 "pocketfms_wp",
975 "PocketFMS waypoints (.txt)",
976 "txt"
977 },
978 {
979 &v900_vecs,
980 "v900",
981 "Columbus/Visiontac V900 files (.csv)",
982 NULL
983 },
984 {
985 &ng_vecs,
986 "naviguide",
987 "Naviguide binary route file (.twl)",
988 "twl"
989 },
990 {
991 &enigma_vecs,
992 "enigma",
993 "Enigma binary waypoint file (.ert)",
994 "ert"
995 },
996 {
997 &delbin_vecs,
998 "delbin",
999 "DeLorme PN-20/PN-30/PN-40 USB protocol",
1000 NULL
1001 },
1002 {
1003 &skytraq_vecs,
1004 "skytraq",
1005 "SkyTraq Venus based loggers (download)",
1006 NULL
1007 },
1008 {
1009 &teletype_vecs,
1010 "teletype",
1011 "Teletype [ Get Jonathon Johnson to describe",
1012 NULL
1013 },
1014 {
1015 &skytraq_fvecs,
1016 "skytraq-bin",
1017 "SkyTraq Venus based loggers Binary File Format",
1018 "bin"
1019 },
1020 {
1021 &miniHomer_vecs,
1022 "miniHomer",
1023 "MiniHomer, a skyTraq Venus 6 based logger (download tracks, waypoints and get/set POI)",
1024 NULL
1025 },
1026 {
1027 &jogmap_vecs,
1028 "jogmap",
1029 "Jogmap.de XML format",
1030 "xml"
1031 },
1032 {
1033 &wintec_tes_vecs,
1034 "wintec_tes",
1035 "Wintec TES file",
1036 "tes"
1037 },
1038 {
1039 &subrip_vecs,
1040 "subrip",
1041 "SubRip subtitles for video mapping (.srt)",
1042 "srt"
1043 },
1044 {
1045 &format_garmin_xt_vecs,
1046 "garmin_xt",
1047 "Mobile Garmin XT Track files",
1048 NULL
1049 },
1050 {
1051 &format_fit_vecs,
1052 "garmin_fit",
1053 "Flexible and Interoperable Data Transfer (FIT) Activity file"
1054 "fit"
1055 },
1056 #endif // MAXIMAL_ENABLED
1057 {
1058 NULL,
1059 NULL,
1060 NULL,
1061 NULL
1062 }
1063 };
1064
1065 void
init_vecs(void)1066 init_vecs(void)
1067 {
1068 vecs_t *vec = vec_list;
1069 while (vec->vec) {
1070 arglist_t *ap;
1071 if (vec->vec->args) {
1072 for (ap = vec->vec->args; ap->argstring; ap++) {
1073 ap->argvalptr = NULL;
1074 if (ap->argval) {
1075 *ap->argval = NULL;
1076 }
1077 }
1078 }
1079 vec++;
1080 }
1081 }
1082
1083 int
is_integer(const char * c)1084 is_integer(const char *c)
1085 {
1086 return isdigit(c[0]) || ((c[0] == '+' || c[0] == '-') && isdigit(c[1]));
1087 }
1088
1089 void
exit_vecs(void)1090 exit_vecs(void)
1091 {
1092 vecs_t *vec = vec_list;
1093 while (vec->vec) {
1094 arglist_t *ap;
1095 if (vec->vec->exit) {
1096 (*vec->vec->exit)();
1097 }
1098 if (vec->vec->args) {
1099 for (ap = vec->vec->args; ap->argstring; ap++) {
1100 if (ap->defaultvalue &&
1101 (ap->argtype == ARGTYPE_INT) &&
1102 ! is_integer(ap->defaultvalue)) {
1103 warning("%s: not an integer\n", ap->argstring);
1104 }
1105 if (ap->argvalptr) {
1106 xfree(ap->argvalptr);
1107 *ap->argval = ap->argvalptr = NULL;
1108 }
1109 }
1110 }
1111 vec++;
1112 }
1113 }
1114
1115 void
assign_option(const char * module,arglist_t * ap,const char * val)1116 assign_option(const char *module, arglist_t *ap, const char *val)
1117 {
1118 char *c;
1119
1120 if (ap->argval == NULL) {
1121 fatal("%s: No local variable defined for option \"%s\"!", module, ap->argstring);
1122 }
1123
1124 if (ap->argvalptr != NULL) {
1125 xfree(ap->argvalptr);
1126 ap->argvalptr = NULL;
1127 }
1128 if (ap->argval) {
1129 *ap->argval = NULL;
1130 }
1131
1132 if (val == NULL) {
1133 return;
1134 }
1135
1136 if (case_ignore_strcmp(val, ap->argstring) == 0) {
1137 c = "";
1138 } else {
1139 c = (char *)val;
1140 }
1141
1142 switch (ap->argtype & ARGTYPE_TYPEMASK) {
1143 case ARGTYPE_INT:
1144 if (*c == '\0') {
1145 c = "0";
1146 } else {
1147 int test;
1148 is_fatal(1 != sscanf(c, "%d", &test),
1149 "%s: Invalid parameter value %s for option %s", module, val, ap->argstring);
1150 }
1151 break;
1152 case ARGTYPE_FLOAT:
1153 if (*c == '\0') {
1154 c = "0";
1155 } else {
1156 double test;
1157 is_fatal(1 != sscanf(c, "%lf", &test),
1158 "%s: Invalid parameter value %s for option %s", module, val, ap->argstring);
1159 }
1160 break;
1161 case ARGTYPE_BOOL:
1162 if (*c == '\0') {
1163 c = "1";
1164 } else {
1165 switch (*c) {
1166 case 'Y':
1167 case 'y':
1168 c = "1";
1169 break;
1170 case 'N':
1171 case 'n':
1172 c = "0";
1173 break;
1174 default:
1175 if (isdigit(*c)) {
1176 if (*c == '0') {
1177 c = "0";
1178 } else {
1179 c = "1";
1180 }
1181 } else {
1182 warning(MYNAME ": Invalid logical value '%s' (%s)!\n", c, module);
1183 c = "0";
1184 }
1185 break;
1186 }
1187 }
1188 break;
1189 }
1190
1191 /* for bool options without default: don't set argval if "FALSE" */
1192
1193 if (((ap->argtype & ARGTYPE_TYPEMASK) == ARGTYPE_BOOL) &&
1194 (*c == '0') && (ap->defaultvalue == NULL)) {
1195 return;
1196 }
1197 *ap->argval = ap->argvalptr = xstrdup(c);
1198 }
1199
1200 void
disp_vec_options(const char * vecname,arglist_t * ap)1201 disp_vec_options(const char *vecname, arglist_t *ap)
1202 {
1203 for (ap = ap; ap && ap->argstring; ap++) {
1204 if (*ap->argval && ap->argval) {
1205 printf("options: module/option=value: %s/%s=\"%s\"",
1206 vecname, ap->argstring, *ap->argval);
1207 if (ap->defaultvalue && (case_ignore_strcmp(ap->defaultvalue, *ap->argval) == 0)) {
1208 printf(" (=default)");
1209 }
1210 printf("\n");
1211 }
1212 }
1213 }
1214
1215 ff_vecs_t *
find_vec(char * const vecname,char ** opts)1216 find_vec(char *const vecname, char **opts)
1217 {
1218 vecs_t *vec = vec_list;
1219 style_vecs_t *svec = style_list;
1220 char *v = xstrdup(vecname);
1221 char *svecname = strtok(v, ",");
1222 int found = 0;
1223
1224 if (vecname == NULL) {
1225 fatal("A format name is required.\n");
1226 }
1227
1228 while (vec->vec) {
1229 arglist_t *ap;
1230 char *res;
1231
1232 if (case_ignore_strcmp(svecname, vec->name)) {
1233 vec++;
1234 continue;
1235 }
1236
1237 res = strchr(vecname, ',');
1238 if (res) {
1239 *opts = strchr(vecname, ',')+1;
1240 } else {
1241 *opts = NULL;
1242 }
1243
1244 if (vec->vec->args) {
1245 for (ap = vec->vec->args; ap->argstring; ap++) {
1246 const char *opt;
1247
1248 if (res) {
1249 opt = get_option(*opts, ap->argstring);
1250 if (opt) {
1251 found = 1;
1252 assign_option(svecname, ap, opt);
1253 xfree((char *)opt);
1254 continue;
1255 }
1256 }
1257 opt = inifile_readstr(global_opts.inifile, vec->name, ap->argstring);
1258 if (opt == NULL) {
1259 opt = inifile_readstr(global_opts.inifile, "Common format settings", ap->argstring);
1260 }
1261 if (opt == NULL) {
1262 opt = ap->defaultvalue;
1263 }
1264 assign_option(vec->name, ap, opt);
1265 }
1266 }
1267 if (opts && opts[0] && !found) {
1268 warning("'%s' is an unknown option to %s.\n", *opts, vec->name);
1269 }
1270
1271 if (global_opts.debug_level >= 1) {
1272 disp_vec_options(vec->name, vec->vec->args);
1273 }
1274
1275 #if CSVFMTS_ENABLED
1276 // xcsv_setup_internal_style( NULL );
1277 #endif // CSVFMTS_ENABLED
1278 xfree(v);
1279 vec->vec->name = vec->name; /* needed for session information */
1280 return vec->vec;
1281
1282 }
1283
1284 /*
1285 * Didn't find it in the table of "real" file types, so plan B
1286 * is to search the list of xcsv styles.
1287 */
1288 while (svec->name) {
1289 arglist_t *ap;
1290 char *res;
1291
1292 if (case_ignore_strcmp(svecname, svec->name)) {
1293 svec++;
1294 continue;
1295 }
1296
1297 res = strchr(vecname, ',');
1298 if (res) {
1299 *opts = strchr(vecname, ',') + 1;
1300 } else {
1301 *opts = NULL;
1302 }
1303
1304 if (vec_list[0].vec->args) {
1305 for (ap = vec_list[0].vec->args; ap->argstring; ap++) {
1306 const char *opt;
1307
1308 if (res) {
1309 opt = get_option(*opts, ap->argstring);
1310 if (opt) {
1311 found = 1;
1312 assign_option(svecname, ap, opt);
1313 xfree((char *)opt);
1314 continue;
1315 }
1316 }
1317 opt = inifile_readstr(global_opts.inifile, svec->name, ap->argstring);
1318 if (opt == NULL) {
1319 opt = inifile_readstr(global_opts.inifile, "Common format settings", ap->argstring);
1320 }
1321 if (opt == NULL) {
1322 opt = ap->defaultvalue;
1323 }
1324 assign_option(svec->name, ap, opt);
1325 }
1326 }
1327
1328 if (opts && opts[0] && !found) {
1329 warning("'%s' is an unknown option to %s.\n", *opts, svec->name);
1330 }
1331
1332 if (global_opts.debug_level >= 1) {
1333 disp_vec_options(svec->name, vec_list[0].vec->args);
1334 }
1335 #if CSVFMTS_ENABLED
1336 xcsv_setup_internal_style(svec->style_buf);
1337 #endif // CSVFMTS_ENABLED
1338
1339 xfree(v);
1340 vec_list[0].vec->name = svec->name; /* needed for session information */
1341 return vec_list[0].vec;
1342 }
1343
1344 /*
1345 * Not found.
1346 */
1347 xfree(v);
1348 return NULL;
1349 }
1350
1351 /*
1352 * Find and return a specific argument in an arg list.
1353 * Modelled approximately after getenv.
1354 */
1355 char *
1356 #ifdef DEBUG_MEM
GET_OPTION(const char * iarglist,const char * argname,DEBUG_PARAMS)1357 GET_OPTION(const char *iarglist, const char *argname, DEBUG_PARAMS)
1358 #else
1359 get_option(const char *iarglist, const char *argname)
1360 #endif
1361 {
1362 size_t arglen = strlen(argname);
1363 char *arglist;
1364 char *rval = NULL;
1365 char *arg;
1366 char *argp;
1367
1368 if (!iarglist) {
1369 return NULL;
1370 }
1371
1372 arglen = strlen(argname);
1373 arglist = xstrdup(iarglist);
1374
1375 for (arg = arglist; argp = strtok(arg, ","), NULL != argp; arg = NULL) {
1376 if (0 == case_ignore_strncmp(argp, argname, arglen)) {
1377 /*
1378 * If we have something of the form "foo=bar"
1379 * return "bar". Otherwise, we assume we have
1380 * simply "foo" so we return that.
1381 */
1382 if (argp[arglen] == '=') {
1383 rval = argp + arglen + 1;
1384 break;
1385 } else if (argp[arglen] == '\0') {
1386 rval = argp;
1387 break;
1388 }
1389 }
1390 }
1391 /*
1392 * Return an offset into the allocated copy.
1393 * The caller mustn't free or otherwise get froggy with
1394 * this data.
1395 */
1396 if (rval) {
1397 rval = xxstrdup(rval,file, line);
1398 }
1399 xfree(arglist);
1400 return rval;
1401 }
1402
1403 /*
1404 * Display the available formats in a format that's easy for humans to
1405 * parse for help on available command line options.
1406 */
1407 static signed int
alpha(const void * a,const void * b)1408 alpha(const void *a, const void *b)
1409 {
1410
1411 const vecs_t *const *ap = (const vecs_t *const*) a;
1412 const vecs_t *const *bp = (const vecs_t *const*) b;
1413
1414 return case_ignore_strcmp((*ap)->desc , (*bp)->desc);
1415 }
1416
1417 /*
1418 * Smoosh the vecs list and style lists together and sort them
1419 * alphabetically. Returns an allocated copy of a style_vecs_array
1420 * that's populated and sorted.
1421 */
1422 vecs_t **
sort_and_unify_vecs(int * ctp)1423 sort_and_unify_vecs(int *ctp)
1424 {
1425 int vc;
1426 vecs_t **svp;
1427 vecs_t *vec;
1428 #if CSVFMTS_ENABLED
1429 style_vecs_t *svec;
1430 #endif
1431 int i = 0;
1432
1433 /* Get a count from both the vec (normal) and the svec (csv) lists */
1434
1435 #if CSVFMTS_ENABLED
1436 extern size_t nstyles;
1437 vc = sizeof vec_list / sizeof vec_list[0] - 1 + nstyles;
1438 #else
1439 vc = sizeof vec_list / sizeof vec_list[0] - 1;
1440 #endif // CSVFMTS_ENABLED
1441
1442
1443 svp = (vecs_t **)xcalloc(vc, sizeof(style_vecs_t *));
1444 /* Normal vecs are easy; populate the first part of the array. */
1445 for (vec = vec_list; vec->vec; vec++, i++) {
1446 svp[i] = vec;
1447 if (svp[i]->parent == NULL) {
1448 svp[i]->parent = svp[i]->name;
1449 }
1450 }
1451
1452 #if CSVFMTS_ENABLED
1453 /* Walk the style list, parse the entries, dummy up a "normal" vec */
1454 for (svec = style_list; svec->name; svec++, i++) {
1455 xcsv_read_internal_style(svec->style_buf);
1456 svp[i] = (vecs_t*) xcalloc(1, sizeof **svp);
1457 svp[i]->name = svec->name;
1458 svp[i]->vec = (ff_vecs_t*) xmalloc(sizeof(*svp[i]->vec));
1459 svp[i]->extension = xcsv_file.extension;
1460 *svp[i]->vec = *vec_list[0].vec; /* Interits xcsv opts */
1461 /* Reset file type to inherit ff_type from xcsv for everything
1462 * except the xcsv format itself, which we leave as "internal"
1463 */
1464 if (case_ignore_strcmp(svec->name, "xcsv")) {
1465 svp[i]->vec->type = xcsv_file.type;
1466 /* Skip over the first help entry for all but the
1467 * actual 'xcsv' format - so we don't expose the
1468 * 'full path to xcsv style file' argument to any
1469 * GUIs for an internal format.
1470 */
1471 svp[i]->vec->args++;
1472 }
1473 memset(&svp[i]->vec->cap, 0, sizeof(svp[i]->vec->cap));
1474 switch (xcsv_file.datatype) {
1475 case 0:
1476 case wptdata:
1477 svp[i]->vec->cap[ff_cap_rw_wpt] = (ff_cap)(ff_cap_read | ff_cap_write);
1478 break;
1479 case trkdata:
1480 svp[i]->vec->cap[ff_cap_rw_trk] = (ff_cap)(ff_cap_read | ff_cap_write);
1481 break;
1482 case rtedata:
1483 svp[i]->vec->cap[ff_cap_rw_rte] = (ff_cap)(ff_cap_read | ff_cap_write);
1484 break;
1485 default:
1486 ;
1487 }
1488 svp[i]->desc = xcsv_file.description;
1489 svp[i]->parent = "xcsv";
1490 }
1491 #endif // CSVFMTS_ENABLED
1492
1493 /* Now that we have everything in an array, alphabetize them */
1494 qsort(svp, vc, sizeof(*svp), alpha);
1495
1496 *ctp = i;
1497 return svp;
1498 }
1499
1500 #define VEC_FMT " %-20.20s %-.50s\n"
1501
1502 void
disp_vecs(void)1503 disp_vecs(void)
1504 {
1505 vecs_t **svp;
1506 arglist_t *ap;
1507 int vc;
1508 int i = 0;
1509
1510 svp = sort_and_unify_vecs(&vc);
1511 for (i=0; i<vc; i++) {
1512 if (svp[i]->vec->type == ff_type_internal) {
1513 continue;
1514 }
1515 printf(VEC_FMT, svp[i]->name, svp[i]->desc);
1516 for (ap = svp[i]->vec->args; ap && ap->argstring; ap++) {
1517 if (!(ap->argtype & ARGTYPE_HIDDEN))
1518 printf(" %-18.18s %s%-.50s %s\n",
1519 ap->argstring,
1520 (ap->argtype & ARGTYPE_TYPEMASK) ==
1521 ARGTYPE_BOOL ? "(0/1) " : "",
1522 ap->helpstring,
1523 (ap->argtype & ARGTYPE_REQUIRED)?"(required)":"");
1524 }
1525 }
1526 xfree(svp);
1527 return;
1528 }
1529
1530 void
disp_vec(const char * vecname)1531 disp_vec(const char *vecname)
1532 {
1533 vecs_t **svp;
1534 arglist_t *ap;
1535 int vc;
1536 int i = 0;
1537
1538 svp = sort_and_unify_vecs(&vc);
1539 for (i=0; i<vc; i++) {
1540 if (case_ignore_strcmp(svp[i]->name, vecname)) {
1541 continue;
1542 }
1543 printf(VEC_FMT, svp[i]->name, svp[i]->desc);
1544 for (ap = svp[i]->vec->args; ap && ap->argstring; ap++) {
1545 if (!(ap->argtype & ARGTYPE_HIDDEN))
1546 printf(" %-18.18s %s%-.50s %s\n",
1547 ap->argstring,
1548 (ap->argtype & ARGTYPE_TYPEMASK) ==
1549 ARGTYPE_BOOL ? "(0/1) " : "",
1550 ap->helpstring,
1551 (ap->argtype & ARGTYPE_REQUIRED)?"(required)":"");
1552 }
1553 }
1554 xfree(svp);
1555 return;
1556 }
1557
1558 /*
1559 * Additional information for V1.
1560 * Output format type at front of line.
1561 */
1562 static void
disp_v1(ff_type t)1563 disp_v1(ff_type t)
1564 {
1565 char *tstring;
1566
1567 switch (t) {
1568 case ff_type_file:
1569 tstring = "file";
1570 break;
1571 case ff_type_serial:
1572 tstring = "serial";
1573 break;
1574 case ff_type_internal:
1575 tstring = "internal";
1576 break;
1577 default:
1578 tstring = "unknown";
1579 break;
1580 }
1581 printf("%s\t", tstring);
1582 }
1583
1584 static void
disp_v2(ff_vecs_t * v)1585 disp_v2(ff_vecs_t *v)
1586 {
1587 int i;
1588 for (i = 0; i < 3; i++) {
1589 putchar(v->cap[i] & ff_cap_read ? 'r' : '-');
1590 putchar(v->cap[i] & ff_cap_write ? 'w' : '-');
1591 }
1592 putchar('\t');
1593 }
1594
1595 const char *
name_option(long type)1596 name_option(long type)
1597 {
1598 const char *at[] = {
1599 "unknown",
1600 "integer",
1601 "float",
1602 "string",
1603 "boolean",
1604 "file",
1605 "outfile"
1606 };
1607
1608 if ((type & ARGTYPE_TYPEMASK) <= 6) {
1609 return at[type & ARGTYPE_TYPEMASK];
1610 }
1611 return at[0];
1612 }
1613
1614 static
disp_help_url(const vecs_t * vec,arglist_t * arg)1615 void disp_help_url(const vecs_t *vec, arglist_t *arg)
1616 {
1617 printf("\t" WEB_DOC_DIR "/fmt_%s.html", vec->name);
1618 if (arg) {
1619 printf("#fmt_%s_o_%s",vec->name, arg->argstring);
1620 }
1621 printf("\n");
1622 }
1623
1624
1625 static void
disp_v3(const vecs_t * vec)1626 disp_v3(const vecs_t *vec)
1627 {
1628 arglist_t *ap;
1629
1630 disp_help_url(vec, NULL);
1631 for (ap = vec->vec->args; ap && ap->argstring; ap++) {
1632 if (!(ap->argtype & ARGTYPE_HIDDEN)) {
1633 printf("option\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
1634 vec->name,
1635 ap->argstring,
1636 ap->helpstring,
1637 name_option(ap->argtype),
1638 ap->defaultvalue? ap->defaultvalue : "",
1639 ap->minvalue? ap->minvalue : "",
1640 ap->maxvalue? ap->maxvalue : "");
1641 }
1642 disp_help_url(vec, ap);
1643 printf("\n");
1644 }
1645 }
1646
1647 /*
1648 * Display the available formats in a format that's easy to machine
1649 * parse. Typically invoked by programs like graphical wrappers to
1650 * determine what formats are supported.
1651 */
1652 void
disp_formats(int version)1653 disp_formats(int version)
1654 {
1655 vecs_t **svp;
1656 vecs_t *vec;
1657 int i, vc = 0;
1658
1659 switch (version) {
1660 case 0:
1661 case 1:
1662 case 2:
1663 case 3:
1664 svp = sort_and_unify_vecs(&vc);
1665 for (i=0; i<vc; i++,vec++) {
1666 vec = svp[i];
1667
1668 /* Version 1 displays type at front of all types.
1669 * Version 0 skips internal types.
1670 */
1671 if (version > 0) {
1672 disp_v1(vec->vec->type);
1673 } else {
1674 if (vec->vec->type == ff_type_internal) {
1675 continue;
1676 }
1677 }
1678 if (version >= 2) {
1679 disp_v2(vec->vec);
1680 }
1681 printf("%s\t%s\t%s%s%s\n", vec->name,
1682 vec->extension? vec->extension : "",
1683 vec->desc,
1684 version >= 3 ? "\t" : "",
1685 version >= 3 ? vec->parent : "");
1686 if (version >= 3) {
1687 disp_v3(vec);
1688 }
1689 }
1690 xfree(svp);
1691 break;
1692 default:
1693 ;
1694 }
1695 }
1696