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     &gtc_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     &gtm_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     &gtc_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