SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsmxref.c
Go to the documentation of this file.
1/**
2 * @file sddsmxref.c
3 * @brief Merges two SDDS data sets by adding data from the second set to the first based on matching or filtering column data.
4 *
5 * @details
6 * This program merges data from two SDDS files. It transfers parameters, columns, and arrays from the second input
7 * file to the first based on user-specified criteria for matching, filtering, and name transformations. The resulting
8 * data set can be output to a new file or overwrite the first input file.
9 *
10 * @section Usage
11 * ```
12 * sddsmxref [<input1>] <input2> [<output>]
13 * [-pipe[=input][,output]]
14 * [-ifis={column|parameter|array},<name>[,...]]
15 * [-ifnot={column|parameter|array},<name>[,...]]
16 * [-transfer={parameter|array},<name>[,...]]
17 * [-take=<column-name>[,...]]
18 * [-leave=<column-name>[,...]]
19 * [-fillIn]
20 * [-match=<column-name>[=<column-name>][,...]]
21 * [-equate=<column-name>[=<column-name>][,<tol>][,...]]
22 * [-reuse[=[rows][,page]]]
23 * [-rename={column|parameter|array},<old>=<new>[,...]]
24 * [-editnames={column|parameter|array},<wild>,<edit>]
25 * [-majorOrder=row|column]
26 * ```
27 *
28 * @section Options
29 * | Option | Description |
30 * |---------------------------------------|---------------------------------------------------------------------------------------|
31 * | `-pipe` | Use standard input and/or output instead of files. |
32 * | `-ifis` | Specifies items that must exist in `<input1>`. |
33 * | `-ifnot` | Specifies items that must not exist in `<input1>`. |
34 * | `-transfer` | Specifies parameters or arrays to transfer from `<input2>`. |
35 * | `-take` | Specifies columns to take from `<input2>`. |
36 * | `-leave` | Specifies columns to exclude from `<input2>` (overrides `-take` for overlapping columns). |
37 * | `-fillIn` | Fills in NULL or 0 for unmatched rows. |
38 * | `-match` | Matches rows between `<input1>` and `<input2>` based on column values. |
39 * | `-equate` | Equates rows with specified tolerances. |
40 * | `-reuse` | Allows reuse of rows or pages from `<input2>`. |
41 * | `-rename` | Renames items in the output data set. |
42 * | `-editnames` | Edits names matching the wildcard string. |
43 * | `-majorOrder` | Specifies the output's major order. |
44 *
45 * @subsection Incompatibilities
46 * - `-take` is incompatible with `-leave` for overlapping column names.
47 * - `-reuse=page` cannot be used if `-match` or `-equate` is not specified.
48 *
49 * @subsection spec_req Specific Requirements
50 * - For `-match`, the matching column(s) must exist in both `<input1>` and `<input2>`.
51 * - For `-equate`, equated columns must be numeric in both inputs.
52 * - For `-transfer`, specified parameters or arrays must exist in `<input2>`.
53 *
54 * @copyright
55 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
56 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
57 *
58 * @license
59 * This file is distributed under the terms of the Software License Agreement
60 * found in the file LICENSE included with this distribution.
61 *
62 * @author
63 * M. Borland, C. Saunders, R. Soliday, H. Shang
64 */
65
66#include "mdb.h"
67#include "SDDS.h"
68#include "SDDSaps.h"
69#include "scan.h"
70
71/* Enumeration for option types */
72enum option_type {
73 SET_TAKE_COLUMNS,
74 SET_LEAVE_COLUMNS,
75 SET_MATCH_COLUMNS,
76 SET_EQUATE_COLUMNS,
77 SET_TRANSFER,
78 SET_REUSE,
79 SET_IFNOT,
80 SET_NOWARNINGS,
81 SET_IFIS,
82 SET_PIPE,
83 SET_FILLIN,
84 SET_RENAME,
85 SET_EDIT,
86 SET_MAJOR_ORDER,
87 N_OPTIONS
88};
89
90char *option[N_OPTIONS] = {
91 "take",
92 "leave",
93 "match",
94 "equate",
95 "transfer",
96 "reuse",
97 "ifnot",
98 "nowarnings",
99 "ifis",
100 "pipe",
101 "fillin",
102 "rename",
103 "editnames",
104 "majorOrder",
105};
106
107#define PARAMETER_TRANSFER 0
108#define ARRAY_TRANSFER 1
109#define TRANSFER_TYPES 2
110static char *transfer_type[TRANSFER_TYPES] = {
111 "parameter", "array"};
112
113typedef struct
114{
115 char *name;
116 long type;
118
119typedef struct
120{
121 char **new_column;
122 char **new_parameter;
123 char **new_array;
124 char **orig_column;
125 char **orig_parameter;
126 char **orig_array;
127 int32_t columns;
128 long parameters;
129 long arrays;
130} REFDATA;
131
132/* Structure for getting edit names */
133typedef struct
134{
137
138#define COLUMN_MODE 0
139#define PARAMETER_MODE 1
140#define ARRAY_MODE 2
141#define MODES 3
142static char *mode_name[MODES] = {
143 "column",
144 "parameter",
145 "array",
146};
147
148long expandTransferRequests(char ***match, long *matches, long type, TRANSFER_DEFINITION *transfer, long transfers, SDDS_DATASET *inSet);
149void process_newnames(SDDS_DATASET *SDDS_dataset, REFDATA *take_RefData, REFDATA rename_data,
150 EDIT_NAME_REQUEST *edit_column_request, long edit_column_requests,
151 EDIT_NAME_REQUEST *edit_parameter_request, long edit_parameter_requests,
152 EDIT_NAME_REQUEST *edit_array_request, long edit_array_requests);
153char **process_editnames(char **orig_name, long **orig_flags, long orig_names, EDIT_NAME_REQUEST *edit_request, long edit_requests);
154long CopyRowToNewColumn(SDDS_DATASET *target, int64_t target_row, SDDS_DATASET *source, int64_t source_row,
155 REFDATA new_data, long columns, char *input2);
156long CopyArraysFromSecondInput(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, REFDATA new_data);
157long CopyParametersFromSecondInput(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, REFDATA new_data);
158void free_refdata(REFDATA *refData, long rename);
159void free_edit_request(EDIT_NAME_REQUEST *edit_request, long edit_requests);
160
161typedef char *STRING_PAIR[2];
162
163long rows_equate(SDDS_DATASET *SDDS1, int64_t row1, SDDS_DATASET *SDDS2, int64_t row2, long equate_columns, STRING_PAIR *equate_column,
164 double *equate_tolerance);
165
166char *USAGE = "Usage:\n"
167 " sddsmxref [<input1>] <input2> [<output>] [options]\n"
168 " [-pipe[=input][,output]]\n"
169 " [-ifis={column|parameter|array},<name>[,...]]\n"
170 " [-ifnot={column|parameter|array},<name>[,...]]\n"
171 " [-transfer={parameter|array},<name>[,...]]\n"
172 " [-take=<column-name>[,...]]\n"
173 " [-leave=<column-name>[,...]]\n"
174 " [-fillIn]\n"
175 " [-match=<column-name>[=<column-name>][,...]]\n"
176 " [-equate=<column-name>[=<column-name>][,<tol>][,...]]\n"
177 " [-reuse[=[rows][,page]]]\n"
178 " [-rename={column|parameter|array},<old>=<new>[,...]]\n"
179 " [-editnames={column|parameter|array},<wild>,<edit>]\n"
180 " [-majorOrder=row|column]\n"
181 "Options:\n"
182 " -pipe[=input][,output] Use standard input and/or output instead of files.\n"
183 " -ifis={column|parameter|array},<name>[,...] Specify names that must exist in <input1>.\n"
184 " -ifnot={column|parameter|array},<name>[,...] Specify names that must not exist in <input1>.\n"
185 " -transfer={parameter|array},<name>[,...] Specify parameters or arrays to transfer from <input2>.\n"
186 " -take=<column-name>[,...] Specify columns to take from <input2>.\n"
187 " -leave=<column-name>[,...] Specify columns not to take from <input2>.\n"
188 " Overrides -take if both specify the same column.\n"
189 " Use -leave=* to exclude all columns.\n"
190 " -fillIn Fill in NULL and 0 values for unmatched rows.\n"
191 " -match=<column-name>[=<column-name>][,...] Specify columns to match between <input1> and <input2>.\n"
192 " -equate=<column-name>[=<column-name>][,<tol>][,...] Specify columns to equate with an optional tolerance.\n"
193 " -reuse[=[rows][,page]] Allow reuse of rows from <input2>.\n"
194 " -rename={column|parameter|array},<old>=<new>[,...] Rename entities in the output data set.\n"
195 " -editnames={column|parameter|array},<wild>,<edit> Edit names of entities matching the wildcard.\n"
196 " -majorOrder=row|column Specify output major order.\n\n"
197 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
198
199int main(int argc, char **argv) {
200 SDDS_DATASET SDDS_1, SDDS_2, SDDS_output;
201 long i_arg, reuse, reusePage;
202 int64_t i, j, k, rows1, rows2, n;
203 SCANNED_ARG *s_arg;
204 char s[200], *ptr;
205 char **take_column, **leave_column, **output_column;
206 STRING_PAIR *match_column, *equate_column;
207 double *equate_tolerance;
208 long take_columns, leave_columns, match_columns, equate_columns, leave_all_columns;
209 int32_t output_columns;
210 char *input1, *input2, *output, *match_value;
211 long tmpfile_used, retval1, retval2;
212 long *row_used;
213 TRANSFER_DEFINITION *transfer;
214 long transfers;
215 long warnings, fillIn;
216 IFITEM_LIST ifnot_item, ifis_item;
217 unsigned long pipeFlags, majorOrderFlag;
218 REFDATA rename_data, take_RefData;
219 EDIT_NAME_REQUEST *edit_column_request, *edit_parameter_request, *edit_array_request;
220 long edit_column_requests, edit_parameter_requests, edit_array_requests;
221 short columnMajorOrder = -1;
222
224 argc = scanargs(&s_arg, argc, argv);
225 if (argc < 3) {
226 fprintf(stderr, "%s\n", USAGE);
227 exit(EXIT_FAILURE);
228 }
229
230 input1 = input2 = output = NULL;
231 take_column = leave_column = NULL;
232 match_column = equate_column = NULL;
233 equate_tolerance = NULL;
234 take_columns = leave_columns = match_columns = equate_columns = reuse = reusePage = 0;
235 tmpfile_used = 0;
236 transfer = NULL;
237 transfers = 0;
238 ifnot_item.items = ifis_item.items = 0;
239 warnings = 1;
240 pipeFlags = 0;
241 fillIn = 0;
242 leave_all_columns = 0;
243
244 rename_data.columns = rename_data.parameters = rename_data.arrays = 0;
245 rename_data.new_column = rename_data.orig_column = rename_data.new_parameter = rename_data.orig_parameter = rename_data.new_array = rename_data.orig_array = NULL;
246 edit_column_request = edit_parameter_request = edit_array_request = NULL;
247 edit_column_requests = edit_parameter_requests = edit_array_requests = 0;
248 take_RefData.columns = take_RefData.parameters = take_RefData.arrays = 0;
249 take_RefData.orig_column = take_RefData.new_column = take_RefData.orig_parameter = take_RefData.new_parameter = take_RefData.orig_array = take_RefData.new_array = NULL;
250
251 for (i_arg = 1; i_arg < argc; i_arg++) {
252 if (s_arg[i_arg].arg_type == OPTION) {
253 delete_chars(s_arg[i_arg].list[0], "_");
254 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
255 case SET_MAJOR_ORDER:
256 majorOrderFlag = 0;
257 s_arg[i_arg].n_items--;
258 if (s_arg[i_arg].n_items > 0 && (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
259 SDDS_Bomb("invalid -majorOrder syntax/values");
260 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
261 columnMajorOrder = 1;
262 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
263 columnMajorOrder = 0;
264 break;
265 case SET_LEAVE_COLUMNS:
266 if (s_arg[i_arg].n_items < 2) {
267 fprintf(stderr, "%s\n", USAGE);
268 exit(EXIT_FAILURE);
269 }
270 leave_column = trealloc(leave_column, sizeof(*leave_column) * (leave_columns + s_arg[i_arg].n_items - 1));
271 for (i = 1; i < s_arg[i_arg].n_items; i++)
272 leave_column[i - 1 + leave_columns] = s_arg[i_arg].list[i];
273 leave_columns += s_arg[i_arg].n_items - 1;
274 break;
275 case SET_TAKE_COLUMNS:
276 if (s_arg[i_arg].n_items < 2) {
277 fprintf(stderr, "%s\n", USAGE);
278 exit(EXIT_FAILURE);
279 }
280 take_column = trealloc(take_column, sizeof(*take_column) * (take_columns + s_arg[i_arg].n_items - 1));
281 for (i = 1; i < s_arg[i_arg].n_items; i++)
282 take_column[i - 1 + take_columns] = s_arg[i_arg].list[i];
283 take_columns += s_arg[i_arg].n_items - 1;
284 break;
285 case SET_MATCH_COLUMNS:
286 if (s_arg[i_arg].n_items < 2) {
287 fprintf(stderr, "%s\n", USAGE);
288 exit(EXIT_FAILURE);
289 }
290 match_column = trealloc(match_column, sizeof(*match_column) * (match_columns + s_arg[i_arg].n_items - 1));
291 for (i = 1; i < s_arg[i_arg].n_items; i++) {
292 if ((ptr = strchr(s_arg[i_arg].list[i], '=')))
293 *ptr++ = 0;
294 else
295 ptr = s_arg[i_arg].list[i];
296 match_column[i - 1 + match_columns][0] = s_arg[i_arg].list[i];
297 match_column[i - 1 + match_columns][1] = ptr;
298 }
299 match_columns += s_arg[i_arg].n_items - 1;
300 break;
301 case SET_EQUATE_COLUMNS:
302 if (s_arg[i_arg].n_items < 2)
303 SDDS_Bomb("invalid -equate syntax");
304 equate_column = trealloc(equate_column, sizeof(*equate_column) * (equate_columns + s_arg[i_arg].n_items - 1));
305 equate_tolerance = trealloc(equate_tolerance, sizeof(*equate_tolerance) * (equate_columns + s_arg[i_arg].n_items - 1));
306 for (i = 1; i < s_arg[i_arg].n_items; i++) {
307 if (!tokenIsNumber(s_arg[i_arg].list[i])) {
308 if ((ptr = strchr(s_arg[i_arg].list[i], '=')))
309 *ptr++ = 0;
310 else
311 ptr = s_arg[i_arg].list[i];
312 equate_column[equate_columns][0] = s_arg[i_arg].list[i];
313 equate_column[equate_columns][1] = ptr;
314 equate_tolerance[equate_columns] = 0;
315 equate_columns += 1;
316 } else {
317 sscanf(s_arg[i_arg].list[i], "%le", &equate_tolerance[equate_columns - 1]);
318 }
319 }
320 break;
321 case SET_TRANSFER:
322 if (s_arg[i_arg].n_items < 3)
323 SDDS_Bomb("invalid -transfer syntax");
324 transfer = trealloc(transfer, sizeof(*transfer) * (transfers + s_arg[i_arg].n_items - 2));
325 switch (match_string(s_arg[i_arg].list[1], transfer_type, TRANSFER_TYPES, 0)) {
326 case PARAMETER_TRANSFER:
327 for (i = 2; i < s_arg[i_arg].n_items; i++) {
328 transfer[i - 2 + transfers].type = PARAMETER_TRANSFER;
329 transfer[i - 2 + transfers].name = s_arg[i_arg].list[i];
330 }
331 break;
332 case ARRAY_TRANSFER:
333 for (i = 2; i < s_arg[i_arg].n_items; i++) {
334 transfer[i - 2 + transfers].type = ARRAY_TRANSFER;
335 transfer[i - 2 + transfers].name = s_arg[i_arg].list[i];
336 }
337 break;
338 default:
339 SDDS_Bomb("unknown type of transfer");
340 break;
341 }
342 transfers += s_arg[i_arg].n_items - 2;
343 break;
344 case SET_REUSE:
345 if (s_arg[i_arg].n_items == 1)
346 reuse = 1;
347 else {
348 char *reuseOptions[2] = {"rows", "page"};
349 for (i = 1; i < s_arg[i_arg].n_items; i++) {
350 switch (match_string(s_arg[i_arg].list[i], reuseOptions, 2, 0)) {
351 case 0:
352 reuse = 1;
353 break;
354 case 1:
355 reusePage = 1;
356 break;
357 default:
358 SDDS_Bomb("unknown reuse keyword");
359 break;
360 }
361 }
362 }
363 break;
364 case SET_IFNOT:
365 if (s_arg[i_arg].n_items < 3)
366 SDDS_Bomb("invalid -ifnot usage");
367 add_ifitem(&ifnot_item, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1);
368 break;
369 case SET_NOWARNINGS:
370 warnings = 0;
371 break;
372 case SET_IFIS:
373 if (s_arg[i_arg].n_items < 3)
374 SDDS_Bomb("invalid -ifis usage");
375 add_ifitem(&ifis_item, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1);
376 break;
377 case SET_PIPE:
378 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
379 SDDS_Bomb("invalid -pipe syntax");
380 break;
381 case SET_FILLIN:
382 fillIn = 1;
383 break;
384 case SET_RENAME:
385 if (s_arg[i_arg].n_items < 3)
386 SDDS_Bomb("invalid -rename syntax");
387 switch (match_string(s_arg[i_arg].list[1], mode_name, MODES, 0)) {
388 case COLUMN_MODE:
389 k = rename_data.columns;
390 rename_data.new_column = trealloc(rename_data.new_column, sizeof(char *) * (k + s_arg[i_arg].n_items - 2));
391 rename_data.orig_column = trealloc(rename_data.orig_column, sizeof(char *) * (k + s_arg[i_arg].n_items - 2));
392 for (i = 2; i < s_arg[i_arg].n_items; i++) {
393 if (!(ptr = strchr(s_arg[i_arg].list[i], '=')))
394 SDDS_Bomb("invalid -rename syntax");
395 *ptr++ = 0;
396 rename_data.orig_column[k + i - 2] = s_arg[i_arg].list[i];
397 rename_data.new_column[k + i - 2] = ptr;
398 }
399 rename_data.columns += s_arg[i_arg].n_items - 2;
400 break;
401 case PARAMETER_MODE:
402 k = rename_data.parameters;
403 rename_data.new_parameter = trealloc(rename_data.new_parameter, sizeof(char *) * (k + s_arg[i_arg].n_items - 2));
404 rename_data.orig_parameter = trealloc(rename_data.orig_parameter, sizeof(char *) * (k + s_arg[i_arg].n_items - 2));
405 for (i = 2; i < s_arg[i_arg].n_items; i++) {
406 if (!(ptr = strchr(s_arg[i_arg].list[i], '=')))
407 SDDS_Bomb("invalid -rename syntax");
408 *ptr++ = 0;
409 rename_data.orig_parameter[k + i - 2] = s_arg[i_arg].list[i];
410 rename_data.new_parameter[k + i - 2] = ptr;
411 }
412 rename_data.parameters += s_arg[i_arg].n_items - 2;
413 break;
414 case ARRAY_MODE:
415 k = rename_data.arrays;
416 rename_data.new_array = trealloc(rename_data.new_array, sizeof(char *) * (k + s_arg[i_arg].n_items - 2));
417 rename_data.orig_array = trealloc(rename_data.orig_array, sizeof(char *) * (k + s_arg[i_arg].n_items - 2));
418 for (i = 2; i < s_arg[i_arg].n_items; i++) {
419 if (!(ptr = strchr(s_arg[i_arg].list[i], '=')))
420 SDDS_Bomb("invalid -rename syntax");
421 *ptr++ = 0;
422 rename_data.orig_array[k + i - 2] = s_arg[i_arg].list[i];
423 rename_data.new_array[k + i - 2] = ptr;
424 }
425 rename_data.arrays += s_arg[i_arg].n_items - 2;
426 break;
427 default:
428 SDDS_Bomb("invalid -rename syntax: specify column, parameter, or array keyword");
429 break;
430 }
431 break;
432 case SET_EDIT:
433 if (s_arg[i_arg].n_items != 4)
434 SDDS_Bomb("invalid -editnames syntax");
435 switch (match_string(s_arg[i_arg].list[1], mode_name, MODES, 0)) {
436 case COLUMN_MODE:
437 edit_column_request = trealloc(edit_column_request, sizeof(*edit_column_request) * (edit_column_requests + 1));
438 SDDS_CopyString(&edit_column_request[edit_column_requests].match_string, s_arg[i_arg].list[2]);
439 SDDS_CopyString(&edit_column_request[edit_column_requests].edit_string, s_arg[i_arg].list[3]);
440 edit_column_requests++;
441 break;
442 case PARAMETER_MODE:
443 edit_parameter_request = trealloc(edit_parameter_request, sizeof(*edit_parameter_request) * (edit_parameter_requests + 1));
444 SDDS_CopyString(&edit_parameter_request[edit_parameter_requests].match_string, s_arg[i_arg].list[2]);
445 SDDS_CopyString(&edit_parameter_request[edit_parameter_requests].edit_string, s_arg[i_arg].list[3]);
446 edit_parameter_requests++;
447 break;
448 case ARRAY_MODE:
449 edit_array_request = trealloc(edit_array_request, sizeof(*edit_array_request) * (edit_array_requests + 1));
450 SDDS_CopyString(&edit_array_request[edit_array_requests].match_string, s_arg[i_arg].list[2]);
451 SDDS_CopyString(&edit_array_request[edit_array_requests].edit_string, s_arg[i_arg].list[3]);
452 edit_array_requests++;
453 break;
454 default:
455 SDDS_Bomb("invalid -editnames syntax: specify column, parameter, or array keyword");
456 break;
457 }
458 break;
459 default:
460 fprintf(stderr, "Error: Unknown switch: %s\n%s\n", s_arg[i_arg].list[0], USAGE);
461 SDDS_Bomb(NULL);
462 break;
463 }
464 } else {
465 if (input1 == NULL)
466 input1 = s_arg[i_arg].list[0];
467 else if (input2 == NULL)
468 input2 = s_arg[i_arg].list[0];
469 else if (output == NULL)
470 output = s_arg[i_arg].list[0];
471 else {
472 fprintf(stderr, "Error: Too many filenames specified.\n%s\n", USAGE);
473 SDDS_Bomb("too many filenames");
474 }
475 }
476 }
477
478 if (pipeFlags & USE_STDIN && input1) {
479 if (output) {
480 fprintf(stderr, "Error: Too many filenames specified with -pipe option.\n%s\n", USAGE);
481 SDDS_Bomb("too many filenames (sddsmxref)");
482 }
483 output = input2;
484 input2 = input1;
485 input1 = NULL;
486 }
487 processFilenames("sddsmxref", &input1, &output, pipeFlags, !warnings, &tmpfile_used);
488 if (!input2) {
489 SDDS_Bomb("Second input file not specified");
490 exit(EXIT_FAILURE);
491 }
492
493 if (!SDDS_InitializeInput(&SDDS_1, input1)) {
494 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
495 exit(EXIT_FAILURE);
496 }
497 if (!check_ifitems(&SDDS_1, &ifnot_item, 0, warnings) || !check_ifitems(&SDDS_1, &ifis_item, 1, warnings))
498 exit(EXIT_SUCCESS);
499 if (!SDDS_InitializeInput(&SDDS_2, input2)) {
500 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
501 exit(EXIT_FAILURE);
502 }
503 /* Get parameter and array names from transfer */
504 if (transfers) {
505 if (!expandTransferRequests(&take_RefData.orig_parameter, &take_RefData.parameters, PARAMETER_TRANSFER, transfer, transfers, &SDDS_2) ||
506 !expandTransferRequests(&take_RefData.orig_array, &take_RefData.arrays, ARRAY_TRANSFER, transfer, transfers, &SDDS_2))
507 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
508 }
509 if (SDDS_ColumnCount(&SDDS_2)) {
510 SDDS_SetColumnFlags(&SDDS_2, 1);
511 if (take_columns) {
512 SDDS_SetColumnFlags(&SDDS_2, 0);
513 for (i = 0; i < take_columns; i++) {
514 if (!has_wildcards(take_column[i]) && SDDS_GetColumnIndex(&SDDS_2, take_column[i]) < 0) {
515 sprintf(s, "Error: Column '%s' not found in file '%s'", take_column[i], input2);
516 SDDS_SetError(s);
517 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
518 }
519 if (!SDDS_SetColumnsOfInterest(&SDDS_2, SDDS_MATCH_STRING, take_column[i], SDDS_OR))
520 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
521 }
522 }
523
524 leave_all_columns = 0;
525 if (leave_columns == 1 && strcmp(leave_column[0], "*") == 0)
526 leave_all_columns = 1;
527 else {
528 if (!take_columns)
529 SDDS_SetColumnFlags(&SDDS_2, 1);
530 for (i = 0; i < leave_columns; i++) {
531 if (!has_wildcards(leave_column[i]) &&
532 SDDS_GetColumnIndex(&SDDS_2, leave_column[i]) < 0)
533 continue;
534 if (!SDDS_SetColumnsOfInterest(&SDDS_2, SDDS_MATCH_STRING, leave_column[i], SDDS_AND | SDDS_NEGATE_MATCH))
535 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
536 }
537 if (leave_columns)
538 free(leave_column);
539 if (take_columns)
540 free(take_column);
541
542 if (!(take_RefData.orig_column = SDDS_GetColumnNames(&SDDS_2, &take_RefData.columns))) {
543 SDDS_SetError("Error: No columns selected to take from input file.");
544 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
545 }
546 }
547
548 for (i = 0; i < match_columns; i++) {
549 if ((j = SDDS_GetColumnIndex(&SDDS_1, match_column[i][0])) < 0 ||
550 SDDS_GetColumnType(&SDDS_1, j) != SDDS_STRING) {
551 sprintf(s, "Error: Column '%s' not found or not of string type in file '%s'.", match_column[i][0], input1 ? input1 : "stdin");
552 SDDS_SetError(s);
553 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
554 }
555 if ((j = SDDS_GetColumnIndex(&SDDS_2, match_column[i][1])) < 0 ||
556 SDDS_GetColumnType(&SDDS_2, j) != SDDS_STRING) {
557 sprintf(s, "Error: Column '%s' not found or not of string type in file '%s'.", match_column[i][1], input2);
558 SDDS_SetError(s);
559 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
560 }
561 }
562 for (i = 0; i < equate_columns; i++) {
563 if ((j = SDDS_GetColumnIndex(&SDDS_1, equate_column[i][0])) < 0 ||
565 sprintf(s, "Error: Column '%s' not found or not of numeric type in file '%s'.", equate_column[i][0], input1 ? input1 : "stdin");
566 SDDS_SetError(s);
567 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
568 }
569 if ((j = SDDS_GetColumnIndex(&SDDS_2, equate_column[i][1])) < 0 ||
571 sprintf(s, "Error: Column '%s' not found or not of numeric type in file '%s'.", equate_column[i][1], input2);
572 SDDS_SetError(s);
573 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
574 }
575 }
576
577 } else {
578 take_columns = 0;
579 take_RefData.columns = 0;
580 leave_all_columns = 1;
581 }
582 if (!take_RefData.columns && !leave_all_columns && warnings)
583 fprintf(stderr, "Warning: No columns being taken from '%s' that are not already in '%s'.\n",
584 input1 ? input1 : "stdin", input2);
585 if (leave_all_columns) {
586 take_RefData.columns = 0;
587 take_columns = 0;
588 }
589
590 if (output && (pipeFlags & USE_STDOUT))
591 SDDS_Bomb("Too many filenames specified with -pipe option.");
592 if (!output && !(pipeFlags & USE_STDOUT)) {
593 if (warnings)
594 fprintf(stderr, "Warning: Existing file '%s' will be replaced.\n", input1 ? input1 : "stdin");
595 tmpfile_used = 1;
596 cp_str(&output, tmpname(NULL));
597 }
598 if (!SDDS_InitializeCopy(&SDDS_output, &SDDS_1, output, "w")) {
599 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
600 exit(EXIT_FAILURE);
601 }
602 if (columnMajorOrder != -1)
603 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
604 else
605 SDDS_output.layout.data_mode.column_major = SDDS_1.layout.data_mode.column_major;
606
607 /* Process new names for take RefData */
608 process_newnames(&SDDS_2, &take_RefData, rename_data, edit_column_request, edit_column_requests,
609 edit_parameter_request, edit_parameter_requests, edit_array_request, edit_array_requests);
610
611 for (i = 0; i < take_RefData.columns; i++) {
612 if (SDDS_GetColumnIndex(&SDDS_output, take_RefData.new_column[i]) >= 0) {
613 if (warnings)
614 fprintf(stderr, "Warning: Column '%s' already exists in the first input file. No data will be taken from column '%s' of the second input file.\n",
615 take_RefData.new_column[i], take_RefData.orig_column[i]);
616 free(take_RefData.new_column[i]);
617 free(take_RefData.orig_column[i]);
618 for (j = i; j < take_RefData.columns - 1; j++) {
619 take_RefData.new_column[j] = take_RefData.new_column[j + 1];
620 take_RefData.orig_column[j] = take_RefData.orig_column[j + 1];
621 }
622
623 take_RefData.columns -= 1;
624 i--;
625 if (take_RefData.columns == 0)
626 break;
627 } else {
628 if (!SDDS_TransferColumnDefinition(&SDDS_output, &SDDS_2, take_RefData.orig_column[i], take_RefData.new_column[i]))
629 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
630 }
631 }
632 if (!(output_column = (char **)SDDS_GetColumnNames(&SDDS_output, &output_columns)) || output_columns == 0) {
633 SDDS_SetError("Error: Problem getting output column names.");
634 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
635 }
636
637 for (i = 0; i < take_RefData.parameters; i++) {
638 if (SDDS_GetParameterIndex(&SDDS_output, take_RefData.new_parameter[i]) >= 0) {
639 free(take_RefData.orig_parameter[i]);
640 free(take_RefData.new_parameter[i]);
641 for (j = i; j < take_RefData.parameters - 1; j++)
642 take_RefData.orig_parameter[j] = take_RefData.orig_parameter[j + 1];
643 take_RefData.parameters -= 1;
644 i--;
645 if (take_RefData.parameters == 0)
646 break;
647 } else {
648 if (!SDDS_TransferParameterDefinition(&SDDS_output, &SDDS_2, take_RefData.orig_parameter[i], take_RefData.new_parameter[i]))
649 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
650 }
651 }
652
653 for (i = 0; i < take_RefData.arrays; i++) {
654 if (SDDS_GetArrayIndex(&SDDS_output, take_RefData.new_array[i]) < 0) {
655 free(take_RefData.orig_array[i]);
656 free(take_RefData.new_array[i]);
657 for (j = i; j < take_RefData.arrays - 1; j++)
658 take_RefData.orig_array[j] = take_RefData.orig_array[j + 1];
659 take_RefData.arrays -= 1;
660 i--;
661 if (take_RefData.arrays == 0)
662 break;
663 } else {
664 if (!SDDS_TransferArrayDefinition(&SDDS_output, &SDDS_2, take_RefData.orig_array[i], take_RefData.new_array[i]))
665 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
666 }
667 }
668 if (!SDDS_WriteLayout(&SDDS_output))
669 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
670 if (!take_RefData.columns && !leave_all_columns && warnings)
671 fprintf(stderr, "Warning: No columns being taken from '%s' that are not already in '%s'.\n", input2, input1 ? input1 : "stdin");
672 if (output_columns) {
673 for (i = 0; i < output_columns; i++)
674 free(output_column[i]);
675 free(output_column);
676 }
677 row_used = NULL;
678 while ((retval1 = SDDS_ReadPage(&SDDS_1)) > 0) {
679 if (!reusePage) {
680 if ((retval2 = SDDS_ReadPage(&SDDS_2)) <= 0) {
681 fprintf(stderr, "Warning: <input2> ends before <input1>.\n");
682 break;
683 }
684 } else {
685 if (retval1 == 1 && (retval2 = SDDS_ReadPage(&SDDS_2)) <= 0)
686 SDDS_Bomb("<input2> has no data");
687 SDDS_SetRowFlags(&SDDS_2, 1);
688 }
689 if (take_RefData.columns &&
690 (!SDDS_SetColumnFlags(&SDDS_2, 0) ||
691 !SDDS_SetColumnsOfInterest(&SDDS_2, SDDS_NAME_ARRAY, take_RefData.columns, take_RefData.orig_column)))
692 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
693 rows1 = SDDS_CountRowsOfInterest(&SDDS_1);
694 if ((rows2 = SDDS_CountRowsOfInterest(&SDDS_2))) {
695 row_used = SDDS_Realloc(row_used, sizeof(*row_used) * rows2);
696 SDDS_ZeroMemory(row_used, rows2 * sizeof(*row_used));
697 }
698 if (!SDDS_StartPage(&SDDS_output, rows1)) {
699 SDDS_SetError("Error: Problem starting output table.");
700 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
701 }
702 if (fillIn && !SDDS_ClearPage(&SDDS_output)) {
703 SDDS_SetError("Error: Problem clearing output table.");
704 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
705 }
706 /* Copy parameters and arrays */
707 if (!CopyParametersFromSecondInput(&SDDS_output, &SDDS_2, take_RefData)) {
708 SDDS_SetError("Error: Problem copying parameters from second input file.");
709 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
710 }
711 if (!CopyArraysFromSecondInput(&SDDS_output, &SDDS_2, take_RefData)) {
712 SDDS_SetError("Error: Problem copying arrays from second input file.");
713 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
714 }
715 if (!SDDS_CopyParameters(&SDDS_output, &SDDS_1) ||
716 !SDDS_CopyArrays(&SDDS_output, &SDDS_1)) {
717 SDDS_SetError("Error: Problem copying parameters or arrays from first input file.");
718 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
719 }
720 for (j = 0; j < rows1; j++) {
721 if (!SDDS_CopyRowDirect(&SDDS_output, j, &SDDS_1, j)) {
722 sprintf(s, "Error: Problem copying row %" PRId64 " of first data set.", j);
723 SDDS_SetError(s);
724 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
725 }
726 SDDS_output.row_flag[j] = 1;
727 if (!match_columns && !equate_columns && !leave_all_columns) {
728 if (j >= rows2) {
729 if (warnings)
730 fprintf(stderr, "Warning: No match for row %" PRId64 " (value %s)\n", j, match_value);
731 SDDS_output.row_flag[j] = 0;
732 continue;
733 }
734 if (!CopyRowToNewColumn(&SDDS_output, j, &SDDS_2, j, take_RefData, take_RefData.columns, input2)) {
735 fprintf(stderr, "Error: Failed to copy data to output.\n");
736 exit(EXIT_FAILURE);
737 }
738 continue;
739 }
740 if (!leave_all_columns) {
741 SDDS_SetRowFlags(&SDDS_2, 1);
742 for (i = 0; i < match_columns; i++) {
743 if (!SDDS_GetValue(&SDDS_1, match_column[i][0], j, &match_value)) {
744 sprintf(s, "Error: Problem getting column '%s' from file '%s'.", match_column[i][0], input1 ? input1 : "stdin");
745 SDDS_SetError(s);
746 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
747 }
748 if (SDDS_MatchRowsOfInterest(&SDDS_2, match_column[i][1], match_value, SDDS_AND) < 0) {
749 sprintf(s, "Error: Problem setting rows of interest for column '%s'.", match_column[i][1]);
750 SDDS_SetError(s);
751 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
752 }
753 free(match_value);
754 }
755 if (!(n = SDDS_CountRowsOfInterest(&SDDS_2))) {
756 if (warnings)
757 fprintf(stderr, "Warning: No match for row %" PRId64 "\n", j);
758 SDDS_output.row_flag[j] = 0;
759 continue;
760 }
761 i = -1; /* Counter for rows-of-interest in file 2 */
762 for (k = 0; k < rows2; k++) {
763 if (!SDDS_2.row_flag[k])
764 continue;
765 i++;
766 if (!row_used[k] && rows_equate(&SDDS_1, j, &SDDS_2, k, equate_columns, equate_column, equate_tolerance)) {
767 row_used[k] = reuse ? 0 : 1;
768 if (!CopyRowToNewColumn(&SDDS_output, j, &SDDS_2, k, take_RefData, take_RefData.columns, input2)) {
769 fprintf(stderr, "Error: Failed to copy data to output.\n");
770 exit(EXIT_FAILURE);
771 }
772 break;
773 }
774 }
775 if (k == rows2) {
776 if (warnings)
777 fprintf(stderr, "Warning: No match for row %" PRId64 "\n", j);
778 if (!fillIn)
779 SDDS_output.row_flag[j] = 0;
780 continue;
781 }
782 }
783 }
784 if (!SDDS_WritePage(&SDDS_output)) {
785 SDDS_SetError("Error: Problem writing data to output file.");
786 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
787 }
788 }
789
790 if (!SDDS_Terminate(&SDDS_1) || !SDDS_Terminate(&SDDS_2) || !SDDS_Terminate(&SDDS_output)) {
791 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
792 exit(EXIT_FAILURE);
793 }
794 if (tmpfile_used && !replaceFileAndBackUp(input1, output))
795 exit(EXIT_FAILURE);
796 free_scanargs(&s_arg, argc);
797 if (row_used)
798 free(row_used);
799
800 free_refdata(&take_RefData, 0);
801 free_refdata(&rename_data, 1);
802
803 free_edit_request(edit_column_request, edit_column_requests);
804 free_edit_request(edit_parameter_request, edit_parameter_requests);
805 free_edit_request(edit_array_request, edit_array_requests);
806 if (match_columns)
807 free(match_column);
808 if (equate_columns)
809 free(equate_column);
810
811 return EXIT_SUCCESS;
812}
813
814void free_refdata(REFDATA *refData, long rename) {
815 long i;
816 if (!rename) {
817 for (i = 0; i < refData->columns; i++) {
818 free(refData->orig_column[i]);
819 free(refData->new_column[i]);
820 }
821 for (i = 0; i < refData->parameters; i++) {
822 free(refData->orig_parameter[i]);
823 free(refData->new_parameter[i]);
824 }
825 for (i = 0; i < refData->arrays; i++) {
826 free(refData->orig_array[i]);
827 free(refData->new_array[i]);
828 }
829 }
830 if (refData->columns) {
831 free(refData->orig_column);
832 free(refData->new_column);
833 }
834 if (refData->parameters) {
835 free(refData->orig_parameter);
836 free(refData->new_parameter);
837 }
838 if (refData->arrays) {
839 free(refData->orig_array);
840 free(refData->new_array);
841 }
842}
843
844long rows_equate(SDDS_DATASET *SDDS1, int64_t row1, SDDS_DATASET *SDDS2, int64_t row2, long equate_columns, STRING_PAIR *equate_column, double *equate_tolerance) {
845 char *data1, *data2;
846 long index1, index2, size, type1, type2, i;
847 char s[SDDS_MAXLINE];
848 index2 = 0;
849 for (i = 0; i < equate_columns; i++) {
850 if ((index1 = SDDS_GetColumnIndex(SDDS1, equate_column[i][0])) < 0 ||
851 (index2 = SDDS_GetColumnIndex(SDDS2, equate_column[i][1])) < 0) {
852 SDDS_SetError("Problem equating rows");
853 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
854 }
855 type1 = SDDS1->layout.column_definition[index1].type;
856 type2 = SDDS2->layout.column_definition[index2].type;
857 if (equate_tolerance[i] == 0) {
858 if (type1 != type2) {
859 sprintf(s, "Problem equating rows--types don't match for column '%s'='%s'", equate_column[i][0], equate_column[i][1]);
860 SDDS_SetError(s);
861 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
862 }
863 size = SDDS_GetTypeSize(type1);
864 data1 = (char *)SDDS1->data[index1] + size * row1;
865 data2 = (char *)SDDS2->data[index2] + size * row2;
866 if (memcmp(data1, data2, size) != 0)
867 return 0;
868 } else {
869 double d1, d2;
870 SDDS_CastValue(SDDS1->data, index1, type1, SDDS_DOUBLE, &d1);
871 SDDS_CastValue(SDDS2->data, index2, type2, SDDS_DOUBLE, &d2);
872 if (fabs(d1 - d2) > equate_tolerance[i])
873 return 0;
874 }
875 }
876 return 1;
877}
878
879long expandTransferRequests(char ***match, long *matches, long type, TRANSFER_DEFINITION *transfer, long transfers, SDDS_DATASET *inSet) {
880 long i, first;
881 int32_t (*matchRoutine)(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode, ...);
882
883 *matches = 0;
884 *match = NULL;
885 switch (type) {
886 case PARAMETER_TRANSFER:
887 matchRoutine = SDDS_MatchParameters;
888 break;
889 case ARRAY_TRANSFER:
890 matchRoutine = SDDS_MatchArrays;
891 break;
892 default:
893 SDDS_Bomb("Invalid transfer type--this shouldn't happen");
894 exit(EXIT_FAILURE);
895 break;
896 }
897 first = 0;
898 for (i = 0; i < transfers; i++) {
899 if (transfer[i].type == type) {
900 if ((*matches = (*matchRoutine)(inSet, match, SDDS_MATCH_STRING, FIND_ANY_TYPE, transfer[i].name, SDDS_OR | (first ? SDDS_0_PREVIOUS : 0))) == -1) {
901 return 0;
902 }
903 first = 0;
904 }
905 }
906 return 1;
907}
908
909void process_newnames(SDDS_DATASET *SDDS_dataset, REFDATA *take_RefData, REFDATA rename_data,
910 EDIT_NAME_REQUEST *edit_column_request, long edit_column_requests,
911 EDIT_NAME_REQUEST *edit_parameter_request, long edit_parameter_requests,
912 EDIT_NAME_REQUEST *edit_array_request, long edit_array_requests) {
913 long i, k = 0, *orig_columnflags;
914 long *orig_parameterflags, *orig_arrayflags;
915 char **column_names, **parameter_names, **array_names, **new_names;
916 int32_t columns, parameters, arrays;
917
918 columns = parameters = arrays = 0;
919 column_names = parameter_names = array_names = new_names = NULL;
920 orig_columnflags = orig_parameterflags = orig_arrayflags = NULL;
921
922 if (take_RefData->columns)
923 take_RefData->new_column = (char **)malloc(sizeof(*(take_RefData->new_column)) * take_RefData->columns);
924 if (take_RefData->parameters)
925 take_RefData->new_parameter = (char **)malloc(sizeof(*(take_RefData->new_parameter)) * take_RefData->parameters);
926 if (take_RefData->arrays)
927 take_RefData->new_array = (char **)malloc(sizeof(*(take_RefData->new_array)) * take_RefData->arrays);
928
929 /* Transfer renames to take_RefData */
930 for (i = 0; i < take_RefData->columns; i++)
931 if ((k = match_string(take_RefData->orig_column[i], rename_data.orig_column, rename_data.columns, EXACT_MATCH)) >= 0)
932 SDDS_CopyString(&take_RefData->new_column[i], rename_data.new_column[k]);
933 else
934 SDDS_CopyString(&take_RefData->new_column[i], take_RefData->orig_column[i]);
935
936 for (i = 0; i < take_RefData->parameters; i++)
937 if ((k = match_string(take_RefData->orig_parameter[i], rename_data.orig_parameter, rename_data.parameters, EXACT_MATCH)) >= 0)
938 SDDS_CopyString(&take_RefData->new_parameter[i], rename_data.new_parameter[k]);
939 else
940 SDDS_CopyString(&take_RefData->new_parameter[i], take_RefData->orig_parameter[i]);
941 for (i = 0; i < take_RefData->arrays; i++)
942 if ((k = match_string(take_RefData->orig_array[i], rename_data.orig_array, rename_data.arrays, EXACT_MATCH)) >= 0)
943 SDDS_CopyString(&take_RefData->new_array[i], rename_data.new_array[k]);
944 else
945 SDDS_CopyString(&take_RefData->new_array[i], take_RefData->orig_array[i]);
946
947 if (!(column_names = SDDS_GetColumnNames(SDDS_dataset, &columns))) {
948 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
949 exit(EXIT_FAILURE);
950 }
951 if (!(parameter_names = SDDS_GetParameterNames(SDDS_dataset, &parameters))) {
952 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
953 exit(EXIT_FAILURE);
954 }
955
956 if (!(array_names = SDDS_GetArrayNames(SDDS_dataset, &arrays))) {
957 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
958 exit(EXIT_FAILURE);
959 }
960
961 /* Process edit names */
962 if (edit_column_requests) {
963 if ((new_names = process_editnames(column_names, &orig_columnflags, columns, edit_column_request, edit_column_requests))) {
964 for (i = 0; i < columns; i++) {
965 if (orig_columnflags[i]) {
966 if ((k = match_string(column_names[i], take_RefData->orig_column, take_RefData->columns, EXACT_MATCH)) >= 0)
967 SDDS_CopyString(&take_RefData->new_column[k], new_names[i]);
968 }
969 free(new_names[i]);
970 }
971 free(new_names);
972 }
973 }
974 if (edit_parameter_requests) {
975 if ((new_names = process_editnames(parameter_names, &orig_parameterflags, parameters, edit_parameter_request, edit_parameter_requests))) {
976 for (i = 0; i < parameters; i++) {
977 if (orig_parameterflags[i]) {
978 if ((k = match_string(parameter_names[i], take_RefData->orig_parameter, take_RefData->parameters, EXACT_MATCH)) >= 0)
979 SDDS_CopyString(&take_RefData->new_parameter[k], new_names[i]);
980 }
981 free(new_names[i]);
982 }
983 free(new_names);
984 }
985 }
986
987 if (edit_array_requests) {
988 if ((new_names = process_editnames(array_names, &orig_arrayflags, arrays, edit_array_request, edit_array_requests))) {
989 for (i = 0; i < arrays; i++) {
990 if (orig_arrayflags[i]) {
991 if ((k = match_string(array_names[i], take_RefData->orig_array, take_RefData->arrays, EXACT_MATCH)) >= 0)
992 SDDS_CopyString(&take_RefData->new_array[k], new_names[i]);
993 }
994 free(new_names[i]);
995 }
996 free(new_names);
997 }
998 }
999 if (orig_columnflags)
1000 free(orig_columnflags);
1001 if (orig_parameterflags)
1002 free(orig_parameterflags);
1003 if (orig_arrayflags)
1004 free(orig_arrayflags);
1005 for (i = 0; i < columns; i++)
1006 free(column_names[i]);
1007 free(column_names);
1008 for (i = 0; i < parameters; i++)
1009 free(parameter_names[i]);
1010 free(parameter_names);
1011 for (i = 0; i < arrays; i++)
1012 free(array_names[i]);
1013 free(array_names);
1014}
1015
1016char **process_editnames(char **orig_name, long **orig_flags, long orig_names, EDIT_NAME_REQUEST *edit_request, long edit_requests) {
1017 long i, j;
1018 char **new_name, s[1024];
1019 char *ptr, **editstr;
1020 char edit_buffer[1024];
1021
1022 *orig_flags = NULL;
1023
1024 *orig_flags = tmalloc(sizeof(**orig_flags) * orig_names);
1025 new_name = tmalloc(sizeof(*new_name) * orig_names);
1026
1027 editstr = (char **)malloc(sizeof(*editstr) * edit_requests);
1028 ptr = malloc(sizeof(char) * 256);
1029 sprintf(s, "%" PRId32, 2);
1030
1031 for (i = 0; i < edit_requests; i++) {
1032 SDDS_CopyString(&editstr[i], edit_request[i].edit_string);
1033 if (strstr(editstr[i], "%%ld"))
1034 replace_string(ptr, editstr[i], "%%ld", "%ld");
1035 else if (strstr(editstr[i], "%ld"))
1036 replace_string(ptr, editstr[i], "%ld", s);
1037 else
1038 continue;
1039 free(editstr[i]);
1040 SDDS_CopyString(&editstr[i], ptr);
1041 }
1042 free(ptr);
1043 ptr = NULL;
1044 for (j = 0; j < orig_names; j++) {
1045 (*orig_flags)[j] = 0;
1046 SDDS_CopyString(&new_name[j], orig_name[j]);
1047 for (i = 0; i < edit_requests; i++) {
1048 ptr = expand_ranges(edit_request[i].match_string);
1049 free(edit_request[i].match_string);
1050 edit_request[i].match_string = ptr;
1051 if (wild_match(new_name[j], edit_request[i].match_string)) {
1052 strcpy(edit_buffer, new_name[j]);
1053 if (!edit_string(edit_buffer, editstr[i]))
1054 SDDS_Bomb("Error editing name");
1055 free(new_name[j]);
1056 SDDS_CopyString(&new_name[j], edit_buffer);
1057 (*orig_flags)[j] = 1;
1058 }
1059 }
1060 }
1061
1062 for (i = 0; i < edit_requests; i++)
1063 free(editstr[i]);
1064 free(editstr);
1065 return new_name;
1066}
1067
1068long CopyParametersFromSecondInput(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, REFDATA new_data) {
1069 long i, j, k;
1070 char s[1024];
1071
1072 if (new_data.parameters == 0)
1073 return 1;
1074 for (i = 0; i < new_data.parameters; i++) {
1075 if ((j = SDDS_GetParameterIndex(SDDS_source, new_data.orig_parameter[i])) < 0) {
1076 continue;
1077 }
1078
1079 if ((k = SDDS_GetParameterIndex(SDDS_target, new_data.new_parameter[i])) < 0) {
1080 fprintf(stderr, "Warning: Parameter '%s' not defined in output.\n", new_data.new_parameter[i]);
1081 continue;
1082 }
1083 if (!SDDS_SetParameters(SDDS_target, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, k, SDDS_source->parameter[j], -1)) {
1084 sprintf(s, "Unable to copy parameters for parameter '%s'", new_data.new_parameter[i]);
1085 SDDS_SetError(s);
1086 return 0;
1087 }
1088 }
1089 return 1;
1090}
1091
1092long CopyArraysFromSecondInput(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, REFDATA new_data) {
1093 long i, j, k, m;
1094 char s[1024];
1095
1096 if (new_data.arrays == 0)
1097 return 1;
1098 for (i = 0; i < new_data.arrays; i++) {
1099 if ((j = SDDS_GetArrayIndex(SDDS_source, new_data.orig_array[i])) < 0)
1100 continue;
1101 if ((k = SDDS_GetArrayIndex(SDDS_target, new_data.new_array[i])) < 0) {
1102 sprintf(s, "Warning: Array '%s' not defined in output.\n", new_data.new_array[i]);
1103 SDDS_SetError(s);
1104 continue;
1105 }
1106 if (SDDS_source->layout.array_definition[j].type != SDDS_target->layout.array_definition[k].type) {
1107 SDDS_SetError("Error: Cannot copy arrays of different types.");
1108 return 0;
1109 }
1110 SDDS_target->array[k].definition = SDDS_target->layout.array_definition + k;
1111 SDDS_target->array[k].elements = SDDS_source->array[j].elements;
1112 if (!(SDDS_target->array[k].dimension = (int32_t *)SDDS_Malloc(sizeof(*SDDS_target->array[k].dimension) * SDDS_target->array[k].definition->dimensions)) ||
1113 !(SDDS_target->array[k].data = SDDS_Realloc(SDDS_target->array[k].data, SDDS_type_size[SDDS_target->array[k].definition->type - 1] * SDDS_target->array[k].elements))) {
1114 SDDS_SetError("Error: Unable to copy arrays due to memory allocation failure.");
1115 return 0;
1116 }
1117 for (m = 0; m < SDDS_target->array[k].definition->dimensions; m++)
1118 SDDS_target->array[k].dimension[m] = SDDS_source->array[j].dimension[m];
1119
1120 if (SDDS_target->array[k].definition->type != SDDS_STRING)
1121 memcpy(SDDS_target->array[k].data, SDDS_source->array[j].data, SDDS_type_size[SDDS_target->array[k].definition->type - 1] * SDDS_target->array[k].elements);
1122 else if (!SDDS_CopyStringArray(SDDS_target->array[k].data, SDDS_source->array[j].data, SDDS_target->array[k].elements)) {
1123 SDDS_SetError("Error: Unable to copy string arrays.");
1124 return 0;
1125 }
1126 }
1127 return 1;
1128}
1129
1130long CopyRowToNewColumn(SDDS_DATASET *target, int64_t target_row, SDDS_DATASET *source, int64_t source_row, REFDATA new_data, long columns, char *input2) {
1131 long i, j, k, type, size;
1132 char s[1024];
1133
1134 if (!columns)
1135 return 1;
1136
1137 for (i = 0; i < columns; i++) {
1138 if ((j = SDDS_GetColumnIndex(source, new_data.orig_column[i])) < 0) {
1139 sprintf(s, "Error: Column '%s' not found in file '%s'.\n", new_data.orig_column[i], input2);
1140 SDDS_SetError(s);
1141 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1142 continue;
1143 }
1144 if ((k = SDDS_GetColumnIndex(target, new_data.new_column[i])) < 0) {
1145 sprintf(s, "Error: Column '%s' not defined in output.\n", new_data.new_column[i]);
1146 SDDS_SetError(s);
1147 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1148 continue;
1149 }
1150
1151 if ((type = SDDS_GetColumnType(target, k)) == SDDS_STRING) {
1152 if (!SDDS_CopyString(((char ***)target->data)[k] + target_row, ((char ***)source->data)[j][source_row])) {
1153 SDDS_SetError("Error: Unable to copy string data.");
1154 return 0;
1155 }
1156 } else {
1157 size = SDDS_type_size[type - 1];
1158 memcpy((char *)target->data[k] + size * target_row, (char *)source->data[j] + size * source_row, size);
1159 }
1160 }
1161 return 1;
1162}
1163
1164void free_edit_request(EDIT_NAME_REQUEST *edit_request, long edit_requests) {
1165 long i;
1166 if (edit_requests) {
1167 for (i = 0; i < edit_requests; i++) {
1168 free(edit_request[i].match_string);
1169 free(edit_request[i].edit_string);
1170 }
1171 free(edit_request);
1172 }
1173}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyRowDirect(SDDS_DATASET *SDDS_target, int64_t target_row, SDDS_DATASET *SDDS_source, int64_t source_row)
Definition SDDS_copy.c:834
int32_t SDDS_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:334
int32_t SDDS_type_size[SDDS_NUM_TYPES]
Array of sizes for each supported data type.
Definition SDDS_data.c:62
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_ClearPage(SDDS_DATASET *SDDS_dataset)
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t SDDS_SetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t row_flag_value)
Sets the acceptance flags for all rows in the current data table of a data set.
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
int64_t SDDS_MatchRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, char *label_to_match, int32_t logic)
Matches and marks rows of interest in an SDDS dataset based on label matching.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
void * SDDS_GetValue(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index, void *memory)
Retrieves the value from a specified column and selected row, optionally storing it in provided memor...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_TransferArrayDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers an array definition from a source dataset to a target dataset.
int32_t SDDS_TransferParameterDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a parameter definition from a source dataset to a target dataset.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_ZeroMemory(void *mem, int64_t n_bytes)
Sets a block of memory to zero.
int32_t SDDS_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array in the SDDS dataset.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_MatchParameters(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves parameter names from an SDDS dataset based on specified criteria.
void * SDDS_CastValue(void *data, int64_t index, int32_t data_type, int32_t desired_type, void *memory)
Casts a value from one SDDS data type to another.
int32_t SDDS_ColumnCount(SDDS_DATASET *page)
Retrieves the number of columns in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
int32_t SDDS_CopyStringArray(char **target, char **source, int64_t n_strings)
Copies an array of strings from source to target.
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetTypeSize(int32_t type)
Retrieves the size in bytes of a specified SDDS data type.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
char ** SDDS_GetArrayNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all arrays in the SDDS dataset.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
int32_t SDDS_MatchArrays(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves array names from an SDDS dataset based on specified criteria.
Header file for routines used by SDDS command-line applications.
long edit_string(char *text, char *edit)
Edits the provided text based on the specified edit commands.
Definition edit_string.c:75
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
long tokenIsNumber(char *token)
Checks if the given token represents a valid number.
Definition data_scan.c:530
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int replace_string(char *t, char *s, char *orig, char *repl)
Replace all occurrences of one string with another string.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:75
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
char * tmpname(char *s)
Supplies a unique temporary filename.
Definition tmpname.c:34
int has_wildcards(char *template)
Check if a template string contains any wildcard characters.
Definition wild_match.c:498
char * expand_ranges(char *template)
Expand range specifiers in a wildcard template into explicit character lists.
Definition wild_match.c:429
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.
Definition wild_match.c:49