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