1 /*--------------------------------------------------------------------
2 *
3 * Copyright (c) 1991-2021 by the GMT Team (https://www.generic-mapping-tools.org/team.html)
4 * See LICENSE.TXT file for copying and redistribution conditions.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3 or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * Contact info: www.generic-mapping-tools.org
16 *--------------------------------------------------------------------*/
17 /*
18 * Author: Paul Wessel
19 * Date: 2-May-2013
20 * Version: 6 API
21 *
22 * Brief synopsis: gmt write lets us (read from memory and) write any of the 6 GMT resources.
23 *
24 */
25
26 #include "gmt_dev.h"
27
28 #define THIS_MODULE_CLASSIC_NAME "gmtwrite"
29 #define THIS_MODULE_MODERN_NAME "gmtwrite"
30 #define THIS_MODULE_LIB "core"
31 #define THIS_MODULE_PURPOSE "Write GMT objects from external API"
32 #define THIS_MODULE_KEYS "-T-,<?{,>?}"
33 #define THIS_MODULE_NEEDS ""
34 #define THIS_MODULE_OPTIONS "->RV"
35
36 /* Control structure for gmtwrite */
37
38 struct GMTWRITE_CTRL {
39 struct GMTWRITE_IO { /* Need two args with filenames */
40 bool active[2];
41 char *file[2];
42 } IO;
43 struct GMTWRITE_T { /* -T sets data type */
44 bool active;
45 enum GMT_enum_family mode;
46 } T;
47 };
48
New_Ctrl(struct GMT_CTRL * GMT)49 static void *New_Ctrl (struct GMT_CTRL *GMT) { /* Allocate and initialize a new control structure */
50 struct GMTWRITE_CTRL *C;
51
52 C = gmt_M_memory (GMT, NULL, 1, struct GMTWRITE_CTRL);
53
54 /* Initialize values whose defaults are not 0/false/NULL */
55
56 return (C);
57 }
58
Free_Ctrl(struct GMT_CTRL * GMT,struct GMTWRITE_CTRL * C)59 static void Free_Ctrl (struct GMT_CTRL *GMT, struct GMTWRITE_CTRL *C) { /* Deallocate control structure */
60 if (!C) return;
61 gmt_M_str_free (C->IO.file[GMT_IN]);
62 gmt_M_str_free (C->IO.file[GMT_OUT]);
63 gmt_M_free (GMT, C);
64 }
65
usage(struct GMTAPI_CTRL * API,int level)66 static int usage (struct GMTAPI_CTRL *API, int level) {
67 const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE);
68 if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR);
69 GMT_Message (API, GMT_TIME_NONE, "usage: %s <infile> <outfile> -Tc|d|g|i|p|u [%s] [%s]\n", name, GMT_Rx_OPT, GMT_V_OPT);
70
71 if (level == GMT_SYNOPSIS) return (GMT_MODULE_SYNOPSIS);
72
73 GMT_Message (API, GMT_TIME_NONE, "\t Specify input and output file names\n");
74 GMT_Message (API, GMT_TIME_NONE, "\t-T Specify data type. Choose among:\n");
75 GMT_Message (API, GMT_TIME_NONE, "\t c : CPT\n");
76 GMT_Message (API, GMT_TIME_NONE, "\t d : Dataset\n");
77 GMT_Message (API, GMT_TIME_NONE, "\t g : Grid\n");
78 GMT_Message (API, GMT_TIME_NONE, "\t i : Image\n");
79 GMT_Message (API, GMT_TIME_NONE, "\t p : PostScript\n");
80 GMT_Message (API, GMT_TIME_NONE, "\t u : Cube\n");
81 GMT_Message (API, GMT_TIME_NONE, "\n OPTIONAL ARGUMENTS:\n");
82 GMT_Option (API, "R,V,.");
83
84 return (GMT_MODULE_USAGE);
85 }
86
parse(struct GMT_CTRL * GMT,struct GMTWRITE_CTRL * Ctrl,struct GMT_OPTION * options)87 static int parse (struct GMT_CTRL *GMT, struct GMTWRITE_CTRL *Ctrl, struct GMT_OPTION *options) {
88
89 /* This parses the options provided to grdwrite and sets parameters in CTRL.
90 * Any GMT common options will override values set previously by other commands.
91 * It also replaces any file names specified as input or output with the data ID
92 * returned when registering these sources/destinations with the API.
93 */
94
95 unsigned int n_errors = 0, n_files = 0;
96 struct GMT_OPTION *opt = NULL;
97 struct GMTAPI_CTRL *API = GMT->parent;
98
99 for (opt = options; opt; opt = opt->next) { /* Process all the options given */
100
101 switch (opt->option) {
102 /* Processes program-specific parameters */
103
104 case GMT_OPT_INFILE: /* File args */
105 if (Ctrl->IO.active[GMT_OUT]) { /* User gave output as ->outfile and it was found on the command line earlier */
106 n_errors += gmt_M_repeated_module_option (API, Ctrl->IO.active[GMT_IN]);
107 Ctrl->IO.active[GMT_IN] = true;
108 Ctrl->IO.file[GMT_IN] = strdup (opt->arg);
109 }
110 else if (n_files < 2) { /* Encountered input file(s); the 2nd would be output */
111 n_errors += gmt_M_repeated_module_option (API, Ctrl->IO.active[n_files]);
112 Ctrl->IO.active[n_files] = true;
113 Ctrl->IO.file[n_files] = strdup (opt->arg);
114 }
115 n_files++;
116 break;
117 case GMT_OPT_OUTFILE: /* Got specific output argument */
118 n_errors += gmt_M_repeated_module_option (API, Ctrl->IO.active[GMT_OUT]);
119 Ctrl->IO.active[GMT_OUT] = true;
120 Ctrl->IO.file[GMT_OUT] = strdup (opt->arg);
121 n_files++;
122 break;
123 case 'T': /* Type */
124 n_errors += gmt_M_repeated_module_option (API, Ctrl->T.active);
125 Ctrl->T.active = true;
126 switch (opt->arg[0]) {
127 case 't':
128 if (gmt_M_compat_check (GMT, 5)) /* There is no longer a T type but we will honor T as D from GMT5 */
129 Ctrl->T.mode = GMT_IS_DATASET;
130 else {
131 GMT_Report (API, GMT_MSG_ERROR, "Unrecognized data type %c. Choose from c, d, g, i, p, and u\n", opt->arg[0]);
132 n_errors++;
133 }
134 break;
135 case 'd': Ctrl->T.mode = GMT_IS_DATASET; break;
136 case 'g': Ctrl->T.mode = GMT_IS_GRID; break;
137 case 'c': Ctrl->T.mode = GMT_IS_PALETTE; break;
138 case 'i': Ctrl->T.mode = GMT_IS_IMAGE; break;
139 case 'p': Ctrl->T.mode = GMT_IS_POSTSCRIPT; break;
140 case 'u': Ctrl->T.mode = GMT_IS_CUBE; break;
141 default:
142 GMT_Report (API, GMT_MSG_ERROR, "Unrecognized data type %c. Choose from c, d, g, i, p, and u\n", opt->arg[0]);
143 n_errors++;
144 break;
145 }
146 break;
147
148 default: /* Report bad options */
149 n_errors += gmt_default_error (GMT, opt->option);
150 break;
151 }
152 }
153
154 n_errors += gmt_M_check_condition (GMT, !(Ctrl->IO.active[GMT_IN] && Ctrl->IO.active[GMT_OUT]), "Must specify both input and output filenames\n");
155 n_errors += gmt_M_check_condition (GMT, Ctrl->IO.active[GMT_IN] && (!Ctrl->IO.file[GMT_IN] || !Ctrl->IO.file[GMT_IN][0]), "Must specify input filename\n");
156 n_errors += gmt_M_check_condition (GMT, Ctrl->IO.active[GMT_OUT] && (!Ctrl->IO.file[GMT_OUT] || !Ctrl->IO.file[GMT_OUT][0]), "Must specify output filename\n");
157 n_errors += gmt_M_check_condition (GMT, n_files != 2, "Must specify only two filenames (input and output)\n");
158 n_errors += gmt_M_check_condition (GMT, !Ctrl->T.active, "Option -T: Must specify a valid datatype\n");
159
160 return (n_errors ? GMT_PARSE_ERROR : GMT_NOERROR);
161 }
162
163 #define bailout(code) {gmt_M_free_options (mode); return (code);}
164 #define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); bailout (code);}
165
GMT_gmtwrite(void * V_API,int mode,void * args)166 EXTERN_MSC int GMT_gmtwrite (void *V_API, int mode, void *args) {
167 int error = 0;
168 struct GMTWRITE_CTRL *Ctrl = NULL;
169 struct GMT_CTRL *GMT = NULL, *GMT_cpy = NULL;
170 struct GMT_OPTION *options = NULL;
171 struct GMTAPI_CTRL *API = gmt_get_api_ptr (V_API); /* Cast from void to GMTAPI_CTRL pointer */
172
173 /*----------------------- Standard module initialization and parsing ----------------------*/
174
175 if (API == NULL) return (GMT_NOT_A_SESSION);
176 if (mode == GMT_MODULE_PURPOSE) return (usage (API, GMT_MODULE_PURPOSE)); /* Return the purpose of program */
177 options = GMT_Create_Options (API, mode, args); if (API->error) return (API->error); /* Set or get option list */
178
179 if ((error = gmt_report_usage (API, options, 0, usage)) != GMT_NOERROR) bailout (error); /* Give usage if requested */
180
181 /* Parse the command-line arguments */
182
183 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 */
184 if (GMT_Parse_Common (API, THIS_MODULE_OPTIONS, options)) Return (API->error);
185 Ctrl = New_Ctrl (GMT); /* Allocate and initialize a new control structure */
186 if ((error = parse (GMT, Ctrl, options)) != 0) Return (error);
187
188 /*---------------------------- This is the gmtwrite main code ----------------------------*/
189
190 error = gmt_copy (API, Ctrl->T.mode, GMT_OUT, Ctrl->IO.file[GMT_IN], Ctrl->IO.file[GMT_OUT]);
191 Return (error);
192 }
193