109 {
110 SCANNED_ARG *s_arg;
112
113 char *inputfile, *outputfile;
114 char **inputColumnName, **inputStringColumnName, **inputDoubleColumnName;
115 char **outputStringColumnName, **outputDoubleColumnName, **matchColumn = NULL;
116 long inputDoubleColumns, inputStringColumns, indexColumn = 0, noOldColumnNamesColumn = 0;
117 int64_t inputRows;
118 int32_t matchColumns = 0;
119 long outputRows, outputDoubleColumns, outputStringColumns;
120 char **inputParameterName;
121 int32_t inputParameters;
122 int32_t inputColumns;
123 char *inputDescription, *inputContents;
124 char *outputDescription;
125 long i, i_arg, col;
126 char *buffer;
127 char **columnOfStrings;
128 long buffer_size;
129#define BUFFER_SIZE_INCREMENT 16384
130 MATRIX *R, *RInv;
131 long OldStringColumnsDefined;
132 char *inputStringRows, *outputStringRows;
133 char **stringArray, *stringParameter;
134 long token_length;
135 long verbose;
136 char format[32];
137 long digits;
138 char *Symbol, *Root;
139 void *parameterPointer;
140 long ascii;
141 unsigned long pipeFlags, majorOrderFlag;
142 long tmpfile_used, noWarnings;
143 long ipage = 0, columnType;
144 char *oldColumnNames, *newColumnNamesColumn;
145 short columnMajorOrder = -1;
146
147 inputColumnName = outputStringColumnName = outputDoubleColumnName = inputParameterName = NULL;
148 outputRows = outputDoubleColumns = outputStringColumns = OldStringColumnsDefined = 0;
149
151
152 argc =
scanargs(&s_arg, argc, argv);
153 if (argc == 1)
155
156 inputfile = outputfile = NULL;
157 verbose = 0;
158 Symbol = Root = NULL;
159 ascii = 0;
160 digits = 3;
161 pipeFlags = 0;
162 tmpfile_used = 0;
163 noWarnings = 0;
164 oldColumnNames = NULL;
165 newColumnNamesColumn = NULL;
166
167 for (i_arg = 1; i_arg < argc; i_arg++) {
168 if (s_arg[i_arg].arg_type == OPTION) {
169 switch (
match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
170 case CLO_MAJOR_ORDER:
171 majorOrderFlag = 0;
172 s_arg[i_arg].n_items--;
173 if (s_arg[i_arg].n_items > 0 &&
174 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
175 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
176 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
177 SDDS_Bomb(
"invalid -majorOrder syntax/values");
178 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
179 columnMajorOrder = 1;
180 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
181 columnMajorOrder = 0;
182 break;
183 case CLO_MATCH_COLUMN:
184 matchColumns = s_arg[i_arg].n_items - 1;
185 matchColumn = s_arg[i_arg].list + 1;
186 break;
187 case CLO_INDEX_COLUMN:
188 indexColumn = 1;
189 break;
190 case CLO_NO_OLDCOLUMNNAMES:
191 noOldColumnNamesColumn = 1;
192 break;
193 case CLO_VERBOSE:
194 verbose = 1;
195 break;
196 case CLO_ASCII:
197 ascii = 1;
198 break;
199 case CLO_DIGITS:
200 if (!(
get_long(&digits, s_arg[i_arg].list[1])))
201 bomb(
"No integer provided for option -digits", USAGE);
202 break;
203 case CLO_COLUMNROOT:
204 if (!(Root = s_arg[i_arg].list[1]))
205 SDDS_Bomb(
"No root string provided with -root option");
206 break;
207 case CLO_SYMBOL:
208 if (!(Symbol = s_arg[i_arg].list[1]))
209 SDDS_Bomb(
"No symbol string provided with -symbol option");
210 break;
211 case CLO_PIPE:
212 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
214 break;
215 case CLO_OLDCOLUMNNAMES:
216 if (!(oldColumnNames = s_arg[i_arg].list[1]))
217 SDDS_Bomb(
"No string provided for -oldColumnNames option");
218 break;
219 case CLO_NEWCOLUMNNAMES:
220 if (s_arg[i_arg].n_items != 2 ||
SDDS_StringIsBlank(newColumnNamesColumn = s_arg[i_arg].list[1]))
221 SDDS_Bomb(
"Invalid syntax or value for -newColumnNames option");
222 break;
223 default:
224 bomb(
"Unrecognized option provided", USAGE);
225 }
226 } else {
227 if (!inputfile)
228 inputfile = s_arg[i_arg].list[0];
229 else if (!outputfile)
230 outputfile = s_arg[i_arg].list[0];
231 else
232 bomb(
"Too many filenames provided", USAGE);
233 }
234 }
235
236 processFilenames(
"sddstranspose", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
237 if (newColumnNamesColumn && Root)
238 SDDS_Bomb(
"-root and -newColumnNames options are incompatible");
239
244
245 if (matchColumns)
246 inputColumnName =
getMatchingSDDSNames(&inputPage, matchColumn, matchColumns, &inputColumns, SDDS_MATCH_COLUMN);
247 else {
250 }
251
252 inputDoubleColumns = 0;
253 inputStringColumns = 0;
254 inputDoubleColumnName = (char **)malloc(inputColumns * sizeof(char *));
255 inputStringColumnName = (char **)malloc(inputColumns * sizeof(char *));
256 inputRows = 0;
257
258
259
260
261 while (0 < SDDS_ReadTable(&inputPage)) {
262 ipage++;
263#if defined(DEBUG)
264 fprintf(stderr, "Working on page %ld\n", ipage);
265#endif
266 if (ipage == 1) {
269
270
271 for (i = 0; i < inputColumns; i++) {
273 inputDoubleColumnName[inputDoubleColumns] = inputColumnName[i];
274 inputDoubleColumns++;
275 }
276 }
277 for (i = 0; i < inputPage.layout.n_columns; i++) {
278 if (inputPage.layout.column_definition[i].type ==
SDDS_STRING) {
279 inputStringColumnName[inputStringColumns] = inputPage.layout.column_definition[i].name;
280 inputStringColumns++;
281 }
282 }
285 } else {
286
288 SDDS_Bomb(
"Datasets have differing number of rows. Processing stopped before reaching end of input file.");
289 }
290 }
291
292 if (inputRows > INT32_MAX) {
294 }
295
296#if defined(DEBUG)
297 fprintf(stderr, "Row flags set\n");
298#endif
299 if (inputDoubleColumns == 0)
300 SDDS_Bomb(
"No numerical columns in file.");
301
302 if ((ipage == 1) && verbose) {
303 fprintf(stderr, "Number of numerical columns: %ld.\n", inputDoubleColumns);
304 fprintf(stderr, "Number of string columns: %ld.\n", inputStringColumns);
305 fprintf(stderr, "Number of rows: %" PRId64 ".\n", inputRows);
306 }
307
308
309
310
311 if (inputDoubleColumns) {
312 if (ipage == 1) {
313 m_alloc(&RInv, inputRows, inputDoubleColumns);
314 m_alloc(&R, inputDoubleColumns, inputRows);
315 }
316 for (col = 0; col < inputDoubleColumns; col++) {
319 }
320 }
321 if (verbose) {
322 m_show(R, "%9.6le ", "Transpose of input matrix:\n", stdout);
323 }
324 m_trans(RInv, R);
325 }
326
327
328
329
330
331 if (ipage == 1) {
332 OldStringColumnsDefined = 0;
334 case SDDS_CHECK_OKAY:
335 OldStringColumnsDefined = 1;
336 break;
337 case SDDS_CHECK_NONEXISTENT:
338 break;
339 case SDDS_CHECK_WRONGTYPE:
340 case SDDS_CHECK_WRONGUNITS:
341 fprintf(stderr, "Error: Parameter OldStringColumns has incorrect type or units.\n");
342 exit(EXIT_FAILURE);
343 break;
344 }
345
346 if (OldStringColumnsDefined) {
347
350
351 if (verbose) {
352 fprintf(stderr, "Parameter OldStringColumns: %s.\n", inputStringRows);
353 }
354
355 outputStringColumnName = (char **)malloc(sizeof(char *));
356 outputStringColumns = 0;
357 buffer_size = BUFFER_SIZE_INCREMENT;
358 buffer = (char *)malloc(sizeof(char) * buffer_size);
359 while (0 <= (token_length =
SDDS_GetToken(inputStringRows, buffer, BUFFER_SIZE_INCREMENT))) {
360 if (!token_length)
361 SDDS_Bomb(
"A null string was detected in parameter OldStringColumns.");
362
363 if (!
SDDS_CopyString(&outputStringColumnName[outputStringColumns], buffer))
365
366 if (verbose) {
367 fprintf(stderr, "Output string column: %s\n", outputStringColumnName[outputStringColumns]);
368 }
369 outputStringColumns++;
370 }
371 }
372 }
373
374
375
376
377 if (ipage == 1) {
378 outputRows = inputDoubleColumns;
379 outputDoubleColumns = inputRows;
380
381 if (inputDescription) {
382 outputDescription = (char *)malloc(sizeof(char) * (strlen("Transpose of ") + strlen(inputDescription) + 1));
383 strcpy(outputDescription, "Transpose of ");
384 strcat(outputDescription, inputDescription);
385 if (!
SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, outputDescription, inputContents, outputfile))
387 free(outputDescription);
388 } else {
389 if (!
SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, outputfile))
391 }
392
394
395 if (columnMajorOrder != -1)
396 outputPage.layout.data_mode.column_major = columnMajorOrder;
397 else
398 outputPage.layout.data_mode.column_major = inputPage.layout.data_mode.column_major;
399
400
401
402
403 if (!Root && inputStringColumns) {
404
405 if (!newColumnNamesColumn)
406
407 outputDoubleColumnName = (
char **)
SDDS_GetColumn(&inputPage, inputStringColumnName[0]);
408 else {
409
411 SDDS_Bomb(
"Column specified with -newColumnNames does not exist in input file.");
412 outputDoubleColumnName = (
char **)
SDDS_GetColumn(&inputPage, newColumnNamesColumn);
413 }
414
415 for (i = 1; i < inputRows; i++) {
416 if (
match_string(outputDoubleColumnName[i - 1], outputDoubleColumnName + i, inputRows - i, EXACT_MATCH) >= 0) {
417 fprintf(stderr, "Error: Duplicate column name '%s' found in input file string column '%s'. Cannot be used as output column names.\n",
418 outputDoubleColumnName[i - 1], newColumnNamesColumn ? newColumnNamesColumn : inputStringColumnName[0]);
419 exit(EXIT_FAILURE);
420 }
421 }
422 } else {
423
424 outputDoubleColumnName = (char **)malloc(outputDoubleColumns * sizeof(char *));
425 digits = MAX(digits, (long)(log10(inputRows) + 1));
426 if (!Root) {
427 Root = (char *)malloc(sizeof(char) * (strlen("Column") + 1));
428 strcpy(Root, "Column");
429 }
430 if (outputDoubleColumns != 1) {
431 for (i = 0; i < outputDoubleColumns; i++) {
432 outputDoubleColumnName[i] = (char *)malloc(sizeof(char) * (strlen(Root) + digits + 1));
433 sprintf(format, "%s%%0%ldld", Root, digits);
434 sprintf(outputDoubleColumnName[i], format, i);
435 }
436 } else {
437 outputDoubleColumnName[0] = (char *)malloc(sizeof(char) * (strlen(Root) + 1));
438 strcpy(outputDoubleColumnName[0], Root);
439 }
440 }
441
442
443
444
445 if (OldStringColumnsDefined) {
448 } else {
449
450 if (!noOldColumnNamesColumn) {
451 outputStringColumns = 1;
452 outputStringColumnName = (char **)malloc(sizeof(char *));
453 if (oldColumnNames) {
454
455 outputStringColumnName[0] = oldColumnNames;
456 } else {
457 outputStringColumnName[0] = (char *)malloc(sizeof(char) * (strlen("OldColumnNames") + 1));
458 strcpy(outputStringColumnName[0], "OldColumnNames");
459 }
462 }
463 }
464
467
468
469
470
471 for (i = 0; i < outputDoubleColumns; i++) {
472 if (Symbol) {
475 } else {
478 }
479 }
480
481
482
483
484
485 if (inputStringColumns > 1) {
488 for (i = 0; i < inputStringColumns; i++) {
491 }
492 }
493
494
495
496
497 if (inputParameters) {
498 for (i = 0; i < inputParameters; i++) {
499 if ((0 >
match_string(inputParameterName[i], outputStringColumnName, outputStringColumns, 0) &&
500 strcasecmp(inputParameterName[i], OLD_STRING_COLUMN_NAMES))) {
503 }
504 }
505 }
506
507
508
509
511
512
514 case SDDS_CHECK_NONEXISTENT:
517 break;
518 default:
519 break;
520 }
521
524 }
525
526#if defined(DEBUG)
527 fprintf(stderr, "Table layout defined\n");
528#endif
529
530 if (!SDDS_StartTable(&outputPage, outputRows))
532 if (ipage == 1) {
533 if (!
SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
"InputFile", inputfile ? inputfile :
"pipe", NULL))
535 }
536
537
538
539
540
541 if (inputStringColumns > 1) {
542 for (i = 0; i < inputStringColumns; i++) {
543 columnOfStrings = (
char **)
SDDS_GetColumn(&inputPage, inputStringColumnName[i]);
544 stringParameter = JoinStrings(columnOfStrings, inputRows, BUFFER_SIZE_INCREMENT);
545 if (!
SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, inputStringColumnName[i], stringParameter, NULL))
547 free(columnOfStrings);
548 free(stringParameter);
549 }
550 outputStringRows = JoinStrings(inputStringColumnName, inputStringColumns, BUFFER_SIZE_INCREMENT);
551 if (!
SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, OLD_STRING_COLUMN_NAMES, outputStringRows, NULL))
553 }
554
555#if defined(DEBUG)
556 fprintf(stderr, "String parameters assigned\n");
557#endif
558
559 if (inputParameters) {
560 for (i = 0; i < inputParameters; i++) {
561 if ((0 >
match_string(inputParameterName[i], outputStringColumnName, outputStringColumns, 0) &&
562 strcasecmp(inputParameterName[i], OLD_STRING_COLUMN_NAMES))) {
563 parameterPointer = (
void *)
SDDS_GetParameter(&inputPage, inputParameterName[i], NULL);
564 if (!
SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, inputParameterName[i], parameterPointer, NULL))
566 free(parameterPointer);
567 }
568 }
569 }
570
571#if defined(DEBUG)
572 fprintf(stderr, "Input parameters assigned\n");
573#endif
574
575
576
577
578
579 if (outputRows) {
580
581
582
583 if (OldStringColumnsDefined) {
584 for (i = 0; i < outputStringColumns; i++) {
587 stringArray = TokenizeString(stringParameter, outputRows);
588 if (!
SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, stringArray, outputRows, outputStringColumnName[i]))
590 free(stringArray);
591 }
592 } else {
593 if (!noOldColumnNamesColumn &&
594 !
SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, inputDoubleColumnName, outputRows, outputStringColumnName[0]))
596 }
597
598#if defined(DEBUG)
599 fprintf(stderr, "String data columns assigned\n");
600#endif
601
602
603
604
605 for (i = 0; i < outputDoubleColumns; i++)
606 if (!
SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, RInv->a[i], outputRows, outputDoubleColumnName[i]))
608
609 if (indexColumn) {
610 for (i = 0; i < outputRows; i++)
611 if (!
SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, i,
"Index", i, NULL))
613 }
614
615#if defined(DEBUG)
616 fprintf(stderr, "Numerical data columns assigned\n");
617#endif
618 }
619
620#if defined(DEBUG)
621 fprintf(stderr, "Data assigned\n");
622#endif
623
624 if (!SDDS_WriteTable(&outputPage))
626
627#if defined(DEBUG)
628 fprintf(stderr, "Data written out\n");
629#endif
630 }
631
632 if (inputDoubleColumns) {
633 m_free(&RInv);
634 m_free(&R);
635 }
636 if (inputColumnName) {
638 free(inputColumnName);
639 }
640 if (inputStringColumns)
641 free(inputStringColumnName);
642 if (inputDescription)
643 free(inputDescription);
644 if (inputParameterName) {
646 free(inputParameterName);
647 }
648 if (outputDoubleColumns) {
650 free(outputDoubleColumnName);
651 }
652
655 if (ipage > 0) {
658 }
660 exit(EXIT_FAILURE);
661
662 return EXIT_SUCCESS;
663}
void SDDS_DeferSavingLayout(SDDS_DATASET *SDDS_dataset, int32_t mode)
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_DefineSimpleColumns(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type)
Defines multiple simple data columns of the same data type within the SDDS dataset.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
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.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
char ** getMatchingSDDSNames(SDDS_DATASET *dataset, char **matchName, int32_t matches, int32_t *names, short type)
Retrieves an array of matching SDDS entity names based on specified criteria.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_GetToken(char *s, char *buffer, int32_t buflen)
Extracts the next token from a string, handling quoted substrings and escape characters.
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.
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
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.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
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.