1 /*--------------------------------------------------------------------
2 *
3 * Copyright (c) 2004-2021 by the GMT Team (https://www.generic-mapping-tools.org/team.html)
4 * See README file for copying and redistribution conditions.
5 *--------------------------------------------------------------------*/
6 /*
7 * mgd77path accepts MGD77 cruise names and returns the full system
8 * path to the file(s).
9 *
10 * Author: Paul Wessel
11 * Date: 26-AUG-2004
12 * Version: 1.0 Based on the old gmtpath.c
13 *
14 *
15 */
16
17 #include "gmt_dev.h"
18 #include "mgd77.h"
19
20 #define THIS_MODULE_CLASSIC_NAME "mgd77path"
21 #define THIS_MODULE_MODERN_NAME "mgd77path"
22 #define THIS_MODULE_LIB "mgd77"
23 #define THIS_MODULE_PURPOSE "Return paths to MGD77 cruises and directories"
24 #define THIS_MODULE_KEYS ">D}"
25 #define THIS_MODULE_NEEDS ""
26 #define THIS_MODULE_OPTIONS "-V"
27
28 struct MGD77PATH_CTRL { /* All control options for this program (except common args) */
29 /* active is true if the option has been activated */
30 struct MGD77PATH_A { /* -A */
31 bool active;
32 bool mode;
33 } A;
34 struct MGD77PATH_D { /* -D */
35 bool active;
36 } D;
37 struct MGD77PATH_I { /* -I */
38 bool active;
39 unsigned int n;
40 char code[3];
41 } I;
42 };
43
New_Ctrl(struct GMT_CTRL * GMT)44 static void *New_Ctrl (struct GMT_CTRL *GMT) { /* Allocate and initialize a new control structure */
45 struct MGD77PATH_CTRL *C = NULL;
46
47 C = gmt_M_memory (GMT, NULL, 1, struct MGD77PATH_CTRL);
48
49 /* Initialize values whose defaults are not 0/false/NULL */
50
51 return (C);
52 }
53
Free_Ctrl(struct GMT_CTRL * GMT,struct MGD77PATH_CTRL * C)54 static void Free_Ctrl (struct GMT_CTRL *GMT, struct MGD77PATH_CTRL *C) { /* Deallocate control structure */
55 if (!C) return;
56 gmt_M_free (GMT, C);
57 }
58
usage(struct GMTAPI_CTRL * API,int level)59 static int usage (struct GMTAPI_CTRL *API, int level) {
60 const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE);
61 if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR);
62 GMT_Usage (API, 0, "usage: %s <cruise(s)> [-A[c]] [-D] [-Ia|c|m|t] [%s] [%s]\n", name, GMT_V_OPT, GMT_PAR_OPT);
63
64 if (level == GMT_SYNOPSIS) return (GMT_MODULE_SYNOPSIS);
65
66 GMT_Message (API, GMT_TIME_NONE, " REQUIRED ARGUMENTS:\n");
67 MGD77_Cruise_Explain (API->GMT);
68 GMT_Message (API, GMT_TIME_NONE, "\n OPTIONAL ARGUMENTS:\n");
69 GMT_Usage (API, 1, "\n-A[c]");
70 GMT_Usage (API, -2, "List full cruise pAths [Default]. Append c to only get cruise names.");
71 GMT_Usage (API, 1, "\n-D List all directories with MGD77 files instead.");
72 GMT_Usage (API, 1, "\n-Ia|c|m|t");
73 GMT_Usage (API, -2, "Ignore certain data file formats from consideration. Append combination of acmt to ignore [Default ignores none]:");
74 GMT_Usage (API, 3, "a: MGD77 ASCII table.");
75 GMT_Usage (API, 3, "c: MGD77+ netCDF table.");
76 GMT_Usage (API, 3, "m: MGD77T ASCII table.");
77 GMT_Usage (API, 3, "t: Plain table.");
78 GMT_Option (API, "V,.");
79
80 return (GMT_MODULE_USAGE);
81 }
82
parse(struct GMT_CTRL * GMT,struct MGD77PATH_CTRL * Ctrl,struct GMT_OPTION * options)83 static int parse (struct GMT_CTRL *GMT, struct MGD77PATH_CTRL *Ctrl, struct GMT_OPTION *options) {
84 /* This parses the options provided to mgd77path and sets parameters in CTRL.
85 * Any GMT common options will override values set previously by other commands.
86 * It also replaces any file names specified as input or output with the data ID
87 * returned when registering these sources/destinations with the API.
88 */
89
90 unsigned int n_errors = 0;
91 struct GMT_OPTION *opt = NULL;
92 struct GMTAPI_CTRL *API = GMT->parent;
93
94 for (opt = options; opt; opt = opt->next) {
95 switch (opt->option) {
96
97 case '<': /* Skip input files */
98 case '#': /* Skip input files confused as numbers (e.g. 123456) */
99 break;
100
101 /* Processes program-specific parameters */
102
103 case 'P':
104 if (gmt_M_compat_check (GMT, 4)) {
105 GMT_Report (API, GMT_MSG_COMPAT, "-P is deprecated; use -A instead mext time.\n");
106 Ctrl->A.active = true;
107 /* Purposfully falling through to catch 'A' instead */
108 }
109 else {
110 n_errors += gmt_default_error (GMT, opt->option);
111 break;
112 }
113 /* Intentionally fall through */
114 case 'A': /* Show list of paths to MGD77 files */
115 n_errors += gmt_M_repeated_module_option (API, Ctrl->A.active);
116 Ctrl->A.active = true;
117 if (opt->arg[0] == 'c' || opt->arg[0] == '-') Ctrl->A.mode = true;
118 break;
119
120 case 'D': /* Show list of directories with MGD77 files */
121 n_errors += gmt_M_repeated_module_option (API, Ctrl->D.active);
122 Ctrl->D.active = true;
123 break;
124
125 case 'I':
126 n_errors += gmt_M_repeated_module_option (API, Ctrl->I.active);
127 Ctrl->I.active = true;
128 if (Ctrl->I.n < 3) {
129 if (strchr ("acmt", (int)opt->arg[0]))
130 Ctrl->I.code[Ctrl->I.n++] = opt->arg[0];
131 else {
132 GMT_Report (API, GMT_MSG_ERROR, "Option -I Bad modifier (%c). Use -Ia|c|m|t!\n", opt->arg[0]);
133 n_errors++;
134 }
135 }
136 else {
137 GMT_Report (API, GMT_MSG_ERROR, "Option -I: Can only be applied 0-2 times\n");
138 n_errors++;
139 }
140 break;
141
142 default: /* Report bad options */
143 n_errors += gmt_default_error (GMT, opt->option);
144 break;
145 }
146 }
147 n_errors += gmt_M_check_condition (GMT, Ctrl->A.active && Ctrl->D.active, "Only one of -A -D may be used\n");
148
149 return (n_errors ? GMT_PARSE_ERROR : GMT_NOERROR);
150 }
151
152 #define bailout(code) {gmt_M_free_options (mode); return (code);}
153 #define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); bailout (code);}
154
GMT_mgd77path(void * V_API,int mode,void * args)155 EXTERN_MSC int GMT_mgd77path (void *V_API, int mode, void *args) {
156 uint64_t n_cruises = 0, i, n_paths = 0;
157 int error = 0;
158
159 char path[PATH_MAX] = {""}, **list = NULL;
160
161 struct MGD77_CONTROL M;
162 struct MGD77PATH_CTRL *Ctrl = NULL;
163 struct GMT_CTRL *GMT = NULL, *GMT_cpy = NULL;
164 struct GMT_OPTION *options = NULL;
165 struct GMTAPI_CTRL *API = gmt_get_api_ptr (V_API); /* Cast from void to GMTAPI_CTRL pointer */
166
167 /*----------------------- Standard module initialization and parsing ----------------------*/
168
169 if (API == NULL) return (GMT_NOT_A_SESSION);
170 if (mode == GMT_MODULE_PURPOSE) return (usage (API, GMT_MODULE_PURPOSE)); /* Return the purpose of program */
171 options = GMT_Create_Options (API, mode, args); if (API->error) return (API->error); /* Set or get option list */
172
173 if ((error = gmt_report_usage (API, options, 0, usage)) != GMT_NOERROR) bailout (error); /* Give usage if requested */
174
175 /* Parse the command-line arguments */
176
177 if ((GMT = gmt_init_module (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_KEYS, THIS_MODULE_NEEDS, NULL, &options, &GMT_cpy)) == NULL) bailout (API->error); /* Save current state */
178 if (GMT_Parse_Common (API, THIS_MODULE_OPTIONS, options)) Return (API->error);
179 Ctrl = New_Ctrl (GMT); /* Allocate and initialize a new control structure */
180 if ((error = parse (GMT, Ctrl, options)) != 0) Return (error);
181
182 /*---------------------------- This is the mgd77path main code ----------------------------*/
183
184 MGD77_Init (GMT, &M); /* Initialize MGD77 Machinery */
185
186 if (Ctrl->I.active) MGD77_Process_Ignore (GMT, 'I', Ctrl->I.code);
187
188 if (Ctrl->D.active) { /* Just list the current active MGD77 data directories and exit */
189 printf ("# Currently, your $MGD77_HOME is set to: %s\n", M.MGD77_HOME);
190 printf ("# $MGD77_HOME/mgd77_paths.txt contains these directories:\n");
191 for (i = 0; i < M.n_MGD77_paths; i++) printf ("%s\n", M.MGD77_datadir[i]);
192 Return (GMT_NOERROR);
193 }
194
195 error = MGD77_Path_Expand (GMT, &M, options, &list); /* Get list of requested IDs */
196
197 if (error <= 0) {
198 GMT_Report (API, GMT_MSG_ERROR, "No cruises found\n");
199 MGD77_Path_Free (GMT, n_paths, list);
200 Return (GMT_NO_INPUT);
201 }
202 n_paths = (uint64_t)error;
203
204 for (i = 0; i < n_paths; i++) { /* Process each ID */
205 if (MGD77_Get_Path (GMT, path, list[i], &M))
206 GMT_Report (API, GMT_MSG_ERROR, "Cannot find cruise %s\n", list[i]);
207 else if (Ctrl->A.mode) {
208 printf ("%s\n", list[i]);
209 n_cruises++;
210 }
211 else {
212 printf ("%s\n", path);
213 n_cruises++;
214 }
215 }
216
217 GMT_Report (API, GMT_MSG_INFORMATION, "Found %" PRIu64 " cruises\n", n_cruises);
218
219 MGD77_Path_Free (GMT, n_paths, list);
220 MGD77_end (GMT, &M);
221
222 Return (GMT_NOERROR);
223 }
224