176 {
177 SCANNED_ARG *s_arg;
179 char *defaultType, *outputFile;
180 unsigned long pipeFlags, dummyFlags, majorOrderFlag;
184 long parameters, columns, arrays, previousOption, i, j, i_arg, currentOption, tmpfile_used, noWarnings, maxrows = 0, outputMode;
185 char *input = "obset";
186 char *description, *contents;
187 short columnMajorOrder = 0, append = 0;
188 int64_t rowsPresent;
189 int32_t colIndex, arrayIndex, dsize, startIndex;
191
192 description = contents = NULL;
193 parameter = NULL;
194 column = NULL;
195 array = NULL;
196 parameters = columns = arrays = 0;
197 outputFile = defaultType = NULL;
198 pipeFlags = 0;
199 tmpfile_used = noWarnings = 0;
200 outputMode = SDDS_BINARY;
201
204
205 argc =
scanargs(&s_arg, argc, argv);
206 if (argc < 3) {
207 fprintf(stderr, "Error: Insufficient arguments provided.\n\n%s", USAGE);
208 exit(EXIT_FAILURE);
209 }
210 previousOption = -1;
211
212 for (i_arg = 1; i_arg < argc; i_arg++) {
213 if (s_arg[i_arg].arg_type == OPTION) {
215 currentOption =
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0);
216 if (currentOption == CLO_DATA && previousOption != CLO_PARAMETER && previousOption != CLO_COLUMN && previousOption != CLO_ARRAY) {
217 SDDS_Bomb(
"-data option must follow a -parameter, -column, or -array option.");
218 }
219 switch (currentOption) {
220 case CLO_MAJOR_ORDER:
221 majorOrderFlag = 0;
222 s_arg[i_arg].n_items -= 1;
223 if (s_arg[i_arg].n_items > 0 &&
224 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
225 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
226 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
227 SDDS_Bomb(
"Invalid -majorOrder syntax or value.");
228 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
229 columnMajorOrder = 1;
230 if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
231 columnMajorOrder = 0;
232 break;
233 case CLO_NOWARNINGS:
234 noWarnings = 1;
235 break;
236 case CLO_PARAMETER:
237 if (s_arg[i_arg].n_items < 2)
239 parameter =
SDDS_Realloc(parameter,
sizeof(*parameter) * (parameters + 1));
240 parameter[parameters] = InitializeParameteterInfo();
242 s_arg[i_arg].list += 2;
243 s_arg[i_arg].n_items -= 2;
244 if (!(parameter[parameters]->name) || !strlen(parameter[parameters]->name))
245 SDDS_Bomb(
"Invalid -parameter syntax (no name).");
246 if (s_arg[i_arg].n_items > 0 &&
247 !
scanItemList(&dummyFlags, s_arg[i_arg].list, &s_arg[i_arg].n_items, 0,
248 "type",
SDDS_STRING, &(parameter[parameters]->
typename), 1, 0,
249 "units",
SDDS_STRING, &(parameter[parameters]->unit), 1, 0,
250 "symbol",
SDDS_STRING, &(parameter[parameters]->symbol), 1, 0,
251 "description",
SDDS_STRING, &(parameter[parameters]->description), 1, 0, NULL))
253 parameters++;
254 s_arg[i_arg].list -= 2;
255 s_arg[i_arg].n_items += 2;
256 break;
257 case CLO_COLUMN:
258 if (s_arg[i_arg].n_items < 2)
260 column =
SDDS_Realloc(column,
sizeof(*column) * (columns + 1));
261 column[columns] = InitializeColumnInfo();
263 s_arg[i_arg].list += 2;
264 s_arg[i_arg].n_items -= 2;
265 if (!(column[columns]->name) || !strlen(column[columns]->name))
266 SDDS_Bomb(
"Invalid -column syntax (no name).");
267 if (s_arg[i_arg].n_items > 0 &&
268 (!
scanItemList(&dummyFlags, s_arg[i_arg].list, &s_arg[i_arg].n_items, 0,
269 "type",
SDDS_STRING, &(column[columns]->
typename), 1, 0,
270 "unit",
SDDS_STRING, &(column[columns]->unit), 1, 0,
271 "symbol",
SDDS_STRING, &(column[columns]->symbol), 1, 0,
272 "description",
SDDS_STRING, &(column[columns]->description), 1, 0, NULL)))
274 columns++;
275 s_arg[i_arg].list -= 2;
276 s_arg[i_arg].n_items += 2;
277 break;
278 case CLO_ARRAY:
279 if (s_arg[i_arg].n_items < 2)
281 array =
SDDS_Realloc(array,
sizeof(*array) * (arrays + 1));
282 array[arrays] = InitializeColumnInfo();
284 s_arg[i_arg].list += 2;
285 s_arg[i_arg].n_items -= 2;
286 if (!(array[arrays]->name) || !strlen(array[arrays]->name))
287 SDDS_Bomb(
"Invalid -array syntax (no name).");
288 if (s_arg[i_arg].n_items > 0 &&
289 (!
scanItemList(&dummyFlags, s_arg[i_arg].list, &s_arg[i_arg].n_items, 0,
290 "type",
SDDS_STRING, &(array[arrays]->
typename), 1, 0,
292 "symbol",
SDDS_STRING, &(array[arrays]->symbol), 1, 0,
293 "description",
SDDS_STRING, &(array[arrays]->description), 1, 0, NULL)))
295 arrays++;
296 s_arg[i_arg].list -= 2;
297 s_arg[i_arg].n_items += 2;
298 break;
299 case CLO_DATA:
300 if (previousOption == CLO_PARAMETER) {
301 parameter[parameters - 1]->dataString = s_arg[i_arg].list[1];
302 }
303 if (previousOption == CLO_COLUMN) {
304 if (((s_arg[i_arg].n_items - 1) == 1) &&
305 (strlen(s_arg[i_arg].list[1]) > 1) &&
306 (((column[columns - 1]->typename) && (strcmp(column[columns - 1]->typename, "character") == 0)) ||
307 ((defaultType) && (strcmp(defaultType, "character") == 0)))) {
308
309 column[columns - 1]->rows = strlen(s_arg[i_arg].list[1]);
310 column[columns - 1]->dataList = malloc(sizeof(*(column[columns - 1]->dataList)) * column[columns - 1]->rows);
311 for (j = 0; j < column[columns - 1]->rows; j++) {
312 char buffer[2] = {s_arg[i_arg].list[1][j], '\0'};
314 }
315 } else {
316 column[columns - 1]->rows = s_arg[i_arg].n_items - 1;
317 column[columns - 1]->dataList = malloc(sizeof(*(column[columns - 1]->dataList)) * column[columns - 1]->rows);
318 for (j = 0; j < column[columns - 1]->rows; j++)
319 SDDS_CopyString(&column[columns - 1]->dataList[j], s_arg[i_arg].list[j + 1]);
320 }
321 }
322 if (previousOption == CLO_ARRAY) {
323 if (((s_arg[i_arg].n_items - 1) == 1) &&
324 (strlen(s_arg[i_arg].list[1]) > 1) &&
325 (((array[arrays - 1]->typename) && (strcmp(array[arrays - 1]->typename, "character") == 0)) ||
326 ((defaultType) && (strcmp(defaultType, "character") == 0)))) {
327
328 array[arrays - 1]->rows = strlen(s_arg[i_arg].list[1]);
329 array[arrays - 1]->dataList = malloc(sizeof(*(array[arrays - 1]->dataList)) * array[arrays - 1]->rows);
330 for (j = 0; j < array[arrays - 1]->rows; j++) {
331 char buffer[2] = {s_arg[i_arg].list[1][j], '\0'};
333 }
334 } else {
335 array[arrays - 1]->rows = s_arg[i_arg].n_items - 1;
336 array[arrays - 1]->dataList = malloc(sizeof(*(array[arrays - 1]->dataList)) * array[arrays - 1]->rows);
337 for (j = 0; j < array[arrays - 1]->rows; j++)
338 SDDS_CopyString(&array[arrays - 1]->dataList[j], s_arg[i_arg].list[j + 1]);
339 }
340 }
341 break;
342 case CLO_DEFAULTTYPE:
343 if (s_arg[i_arg].n_items != 2)
344 SDDS_Bomb(
"Invalid -defaultType option.");
346 break;
347 case CLO_PIPE:
348 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
350 if (pipeFlags != USE_STDOUT)
351 SDDS_Bomb(
"Only -pipe=out syntax is valid.");
352 break;
353 case CLO_DESCRIPTION:
354 if (s_arg[i_arg].n_items != 2)
355 SDDS_Bomb(
"Invalid -description option.");
357 break;
358 case CLO_CONTENTS:
359 if (s_arg[i_arg].n_items != 2)
362 break;
363 case CLO_ASCII:
364 outputMode = SDDS_ASCII;
365 break;
366 case CLO_APPEND:
367 append = 1;
368 if (s_arg[i_arg].n_items != 1) {
369 append = 2;
370 if (s_arg[i_arg].n_items > 2 || strncmp(s_arg[i_arg].list[1], "merge", strlen(s_arg[i_arg].list[1])) != 0)
372 }
373 break;
374 default:
375 fprintf(stderr, "Error: Option %s is invalid.\n", s_arg[i_arg].list[0]);
376 exit(EXIT_FAILURE);
377 break;
378 }
379 previousOption = currentOption;
380 } else {
381 if (outputFile == NULL)
383 else {
384 fprintf(stderr, "Error: Too many filenames provided (%s).\n", s_arg[i_arg].list[0]);
385 exit(EXIT_FAILURE);
386 }
387 }
388 }
389
390 if (!outputFile && !pipeFlags) {
391 fprintf(stderr, "Error: Either an output file or -pipe=out must be specified.\n\n%s", USAGE);
392 exit(EXIT_FAILURE);
393 }
394 if (outputFile && pipeFlags) {
395 fprintf(stderr, "Error: Only one of output file and -pipe=out can be specified.\n\n%s", USAGE);
396 exit(EXIT_FAILURE);
397 }
398
399 processFilenames(
"sddsmakedataset", &input, &outputFile, pipeFlags, 1, &tmpfile_used);
400 if (!columns && !parameters && !arrays) {
401 fprintf(stderr, "Error: No data provided for writing.\n\n%s", USAGE);
402 exit(EXIT_FAILURE);
403 }
404 if (contents && !description) {
405 if (!noWarnings) {
406 fprintf(stderr, "Warning: Description text is provided for contents without a description. No description will be written.\n");
407 free(contents);
408 contents = NULL;
409 }
410 }
411 for (i = 0; i < columns; i++)
412 if (maxrows < column[i]->rows)
413 maxrows = column[i]->rows;
414 SetInfoData(parameter, parameters, column, columns, array, arrays, defaultType, noWarnings, maxrows);
415
416 if (append == 0) {
417
420 outTable.layout.data_mode.column_major = columnMajorOrder;
421 for (i = 0; i < parameters; i++) {
422 if (parameter[i]->dataString) {
423 if (
SDDS_DefineParameter(&outTable, parameter[i]->name, parameter[i]->symbol, parameter[i]->unit, parameter[i]->description, NULL, parameter[i]->type, NULL) < 0)
425 }
426 }
427
428 for (i = 0; i < columns; i++) {
429 if (column[i]->dataList) {
430 if (
SDDS_DefineColumn(&outTable, column[i]->name, column[i]->symbol, column[i]->unit, column[i]->description, NULL, column[i]->type, 0) < 0)
432 }
433 }
434 for (i = 0; i < arrays; i++) {
435 if (array[i]->dataList) {
436 if (
SDDS_DefineArray(&outTable, array[i]->name, array[i]->symbol, array[i]->unit, array[i]->description, NULL, array[i]->type, 0, 1, NULL) < 0)
438 }
439 }
442 }
443 if (append == 1) {
444
447 }
448 if (append == 2) {
449
452 }
453 if (append) {
454
455 for (i = 0; i < parameters; i++) {
456 if (parameter[i]->dataString) {
458 fprintf(stderr, "Error: Parameter '%s' does not exist in the existing file.\n", parameter[i]->name);
459 exit(EXIT_FAILURE);
460 }
461 }
462 }
464 fprintf(stderr, "Error: Parameter count does not match the existing file.\n");
465 exit(EXIT_FAILURE);
466 }
467 for (i = 0; i < columns; i++) {
468 if (column[i]->dataList) {
470 fprintf(stderr, "Error: Column '%s' does not exist in the existing file.\n", column[i]->name);
471 exit(EXIT_FAILURE);
472 }
473 }
474 }
476 fprintf(stderr, "Error: Column count does not match the existing file.\n");
477 exit(EXIT_FAILURE);
478 }
479 for (i = 0; i < arrays; i++) {
480 if (array[i]->dataList) {
482 fprintf(stderr, "Error: Array '%s' does not exist in the existing file.\n", array[i]->name);
483 exit(EXIT_FAILURE);
484 }
485 }
486 }
488 fprintf(stderr, "Error: Array count does not match the existing file.\n");
489 exit(EXIT_FAILURE);
490 }
491 }
492
493 if (append == 0 || append == 1) {
496 for (i = 0; i < parameters; i++) {
497 if (parameter[i]->data) {
498 if (!
SDDS_SetParameters(&outTable, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, parameter[i]->name, parameter[i]->data, NULL))
500 }
501 }
502 for (i = 0; i < columns; i++) {
503 if (column[i]->data) {
504 if (!
SDDS_SetColumn(&outTable, SDDS_SET_BY_NAME, column[i]->data, maxrows, column[i]->name))
506 }
507 }
508 for (i = 0; i < arrays; i++) {
509 if (array[i]->data) {
510 if (!
SDDS_SetArrayVararg(&outTable, array[i]->name, SDDS_CONTIGUOUS_DATA, array[i]->data, array[i]->rows))
512 }
513 }
514 }
515 if (append == 2) {
516 for (i = 0; i < columns; i++) {
517 if (column[i]->data) {
519 for (j = 0; j < maxrows; j++) {
520 switch (column[i]->type) {
522 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
523 colIndex, ((long double *)(column[i]->data))[j], -1) == 0)
525 break;
527 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
528 colIndex, ((double *)(column[i]->data))[j], -1) == 0)
530 break;
532 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
533 colIndex, ((float *)(column[i]->data))[j], -1) == 0)
535 break;
537 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
538 colIndex, ((int64_t *)(column[i]->data))[j], -1) == 0)
540 break;
542 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
543 colIndex, ((uint64_t *)(column[i]->data))[j], -1) == 0)
545 break;
547 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
548 colIndex, ((int32_t *)(column[i]->data))[j], -1) == 0)
550 break;
552 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
553 colIndex, ((uint32_t *)(column[i]->data))[j], -1) == 0)
555 break;
557 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
558 colIndex, ((short *)(column[i]->data))[j], -1) == 0)
560 break;
562 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
563 colIndex, ((unsigned short *)(column[i]->data))[j], -1) == 0)
565 break;
567 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
568 colIndex, ((char *)(column[i]->data))[j], -1) == 0)
570 break;
572 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
573 colIndex, ((char **)(column[i]->data))[j], -1) == 0)
575 break;
576 default:
577 SDDS_Bomb(
"Invalid data type provided.");
578 break;
579 }
580 }
581 }
582 }
583 for (i = 0; i < arrays; i++) {
584 if (array[i]->data) {
586 sdds_array = outTable.array + arrayIndex;
588 startIndex = sdds_array->elements;
589 sdds_array->elements += array[i]->rows;
590 sdds_array->data =
SDDS_Realloc(sdds_array->data, dsize * sdds_array->elements);
592 if (!
SDDS_CopyStringArray(((
char **)sdds_array->data) + startIndex, array[i]->data, array[i]->rows))
594 } else {
595 memcpy((char *)sdds_array->data + dsize * startIndex, array[i]->data, dsize * array[i]->rows);
596 }
597 }
598 }
599 }
600
601 if (append == 2) {
604 } else {
607 }
608
609
611 exit(EXIT_FAILURE);
613 FreeMemory(parameter, parameters, column, columns, array, arrays, maxrows);
614 if (defaultType)
615 free(defaultType);
616 if (outputFile)
617 free(outputFile);
618 if (description)
619 free(description);
620 if (contents)
621 free(contents);
622 return EXIT_SUCCESS;
623}
int32_t SDDS_type_size[SDDS_NUM_TYPES]
Array of sizes for each supported data type.
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetArrayVararg(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t mode, void *data_pointer,...)
Sets the values of an array variable in the SDDS dataset using variable arguments for dimensions.
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_InitializeAppend(SDDS_DATASET *SDDS_dataset, const char *filename)
Initializes the SDDS dataset for appending data by adding a new page to an existing file.
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_InitializeAppendToPage(SDDS_DATASET *SDDS_dataset, const char *filename, int64_t updateInterval, int64_t *rowsPresentReturn)
Initializes the SDDS dataset for appending data to the last page of an existing file.
int32_t SDDS_DefineArray(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, int32_t dimensions, const char *group_name)
Defines a data array within the SDDS dataset.
int32_t SDDS_UpdatePage(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Updates the current page of the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
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_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array in the SDDS dataset.
int32_t SDDS_ParameterCount(SDDS_DATASET *page)
Retrieves the number of 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_ColumnCount(SDDS_DATASET *page)
Retrieves the number of columns in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
int32_t SDDS_CopyStringArray(char **target, char **source, int64_t n_strings)
Copies an array of strings from source to target.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_ArrayCount(SDDS_DATASET *page)
Retrieves the number of arrays in the SDDS dataset.
int32_t SDDS_CheckDatasetStructureSize(int32_t size)
Verifies that the size of the SDDS_DATASET structure matches the expected size.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
#define SDDS_FLOAT
Identifier for the float data type.
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_SHORT
Identifier for the signed short integer data type.
#define SDDS_CHARACTER
Identifier for the character data type.
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
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.
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)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.