140 {
141 SCANNED_ARG *s_arg;
143 char *defaultType, *outputFile;
144 unsigned long pipeFlags, dummyFlags, majorOrderFlag;
148 long parameters, columns, arrays, previousOption, i, j, i_arg, currentOption, tmpfile_used, noWarnings, maxrows = 0, outputMode;
149 char *input = "obset";
150 char *description, *contents;
151 short columnMajorOrder = 0, append = 0;
152 int64_t rowsPresent;
153 int32_t colIndex, arrayIndex, dsize, startIndex;
155
156 description = contents = NULL;
157 parameter = NULL;
158 column = NULL;
159 array = NULL;
160 parameters = columns = arrays = 0;
161 outputFile = defaultType = NULL;
162 pipeFlags = 0;
163 tmpfile_used = noWarnings = 0;
164 outputMode = SDDS_BINARY;
165
168
169 argc =
scanargs(&s_arg, argc, argv);
170 if (argc < 3) {
171 fprintf(stderr, "Error: Insufficient arguments provided.\n\n%s", USAGE);
172 exit(EXIT_FAILURE);
173 }
174 previousOption = -1;
175
176 for (i_arg = 1; i_arg < argc; i_arg++) {
177 if (s_arg[i_arg].arg_type == OPTION) {
179 currentOption =
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0);
180 if (currentOption == CLO_DATA && previousOption != CLO_PARAMETER && previousOption != CLO_COLUMN && previousOption != CLO_ARRAY) {
181 SDDS_Bomb(
"-data option must follow a -parameter, -column, or -array option.");
182 }
183 switch (currentOption) {
184 case CLO_MAJOR_ORDER:
185 majorOrderFlag = 0;
186 s_arg[i_arg].n_items -= 1;
187 if (s_arg[i_arg].n_items > 0 &&
188 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
189 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
190 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
191 SDDS_Bomb(
"Invalid -majorOrder syntax or value.");
192 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
193 columnMajorOrder = 1;
194 if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
195 columnMajorOrder = 0;
196 break;
197 case CLO_NOWARNINGS:
198 noWarnings = 1;
199 break;
200 case CLO_PARAMETER:
201 if (s_arg[i_arg].n_items < 2)
203 parameter =
SDDS_Realloc(parameter,
sizeof(*parameter) * (parameters + 1));
204 parameter[parameters] = InitializeParameteterInfo();
206 s_arg[i_arg].list += 2;
207 s_arg[i_arg].n_items -= 2;
208 if (!(parameter[parameters]->name) || !strlen(parameter[parameters]->name))
209 SDDS_Bomb(
"Invalid -parameter syntax (no name).");
210 if (s_arg[i_arg].n_items > 0 &&
211 !
scanItemList(&dummyFlags, s_arg[i_arg].list, &s_arg[i_arg].n_items, 0,
212 "type",
SDDS_STRING, &(parameter[parameters]->
typename), 1, 0,
213 "units",
SDDS_STRING, &(parameter[parameters]->unit), 1, 0,
214 "symbol",
SDDS_STRING, &(parameter[parameters]->symbol), 1, 0,
215 "description",
SDDS_STRING, &(parameter[parameters]->description), 1, 0, NULL))
217 parameters++;
218 s_arg[i_arg].list -= 2;
219 s_arg[i_arg].n_items += 2;
220 break;
221 case CLO_COLUMN:
222 if (s_arg[i_arg].n_items < 2)
224 column =
SDDS_Realloc(column,
sizeof(*column) * (columns + 1));
225 column[columns] = InitializeColumnInfo();
227 s_arg[i_arg].list += 2;
228 s_arg[i_arg].n_items -= 2;
229 if (!(column[columns]->name) || !strlen(column[columns]->name))
230 SDDS_Bomb(
"Invalid -column syntax (no name).");
231 if (s_arg[i_arg].n_items > 0 &&
232 (!
scanItemList(&dummyFlags, s_arg[i_arg].list, &s_arg[i_arg].n_items, 0,
233 "type",
SDDS_STRING, &(column[columns]->
typename), 1, 0,
234 "unit",
SDDS_STRING, &(column[columns]->unit), 1, 0,
235 "symbol",
SDDS_STRING, &(column[columns]->symbol), 1, 0,
236 "description",
SDDS_STRING, &(column[columns]->description), 1, 0, NULL)))
238 columns++;
239 s_arg[i_arg].list -= 2;
240 s_arg[i_arg].n_items += 2;
241 break;
242 case CLO_ARRAY:
243 if (s_arg[i_arg].n_items < 2)
245 array =
SDDS_Realloc(array,
sizeof(*array) * (arrays + 1));
246 array[arrays] = InitializeColumnInfo();
248 s_arg[i_arg].list += 2;
249 s_arg[i_arg].n_items -= 2;
250 if (!(array[arrays]->name) || !strlen(array[arrays]->name))
251 SDDS_Bomb(
"Invalid -array syntax (no name).");
252 if (s_arg[i_arg].n_items > 0 &&
253 (!
scanItemList(&dummyFlags, s_arg[i_arg].list, &s_arg[i_arg].n_items, 0,
254 "type",
SDDS_STRING, &(array[arrays]->
typename), 1, 0,
256 "symbol",
SDDS_STRING, &(array[arrays]->symbol), 1, 0,
257 "description",
SDDS_STRING, &(array[arrays]->description), 1, 0, NULL)))
259 arrays++;
260 s_arg[i_arg].list -= 2;
261 s_arg[i_arg].n_items += 2;
262 break;
263 case CLO_DATA:
264 if (previousOption == CLO_PARAMETER) {
265 parameter[parameters - 1]->dataString = s_arg[i_arg].list[1];
266 }
267 if (previousOption == CLO_COLUMN) {
268 if (((s_arg[i_arg].n_items - 1) == 1) &&
269 (strlen(s_arg[i_arg].list[1]) > 1) &&
270 (((column[columns - 1]->typename) && (strcmp(column[columns - 1]->typename, "character") == 0)) ||
271 ((defaultType) && (strcmp(defaultType, "character") == 0)))) {
272
273 column[columns - 1]->rows = strlen(s_arg[i_arg].list[1]);
274 column[columns - 1]->dataList = malloc(sizeof(*(column[columns - 1]->dataList)) * column[columns - 1]->rows);
275 for (j = 0; j < column[columns - 1]->rows; j++) {
276 char buffer[2] = {s_arg[i_arg].list[1][j], '\0'};
278 }
279 } else {
280 column[columns - 1]->rows = s_arg[i_arg].n_items - 1;
281 column[columns - 1]->dataList = malloc(sizeof(*(column[columns - 1]->dataList)) * column[columns - 1]->rows);
282 for (j = 0; j < column[columns - 1]->rows; j++)
283 SDDS_CopyString(&column[columns - 1]->dataList[j], s_arg[i_arg].list[j + 1]);
284 }
285 }
286 if (previousOption == CLO_ARRAY) {
287 if (((s_arg[i_arg].n_items - 1) == 1) &&
288 (strlen(s_arg[i_arg].list[1]) > 1) &&
289 (((array[arrays - 1]->typename) && (strcmp(array[arrays - 1]->typename, "character") == 0)) ||
290 ((defaultType) && (strcmp(defaultType, "character") == 0)))) {
291
292 array[arrays - 1]->rows = strlen(s_arg[i_arg].list[1]);
293 array[arrays - 1]->dataList = malloc(sizeof(*(array[arrays - 1]->dataList)) * array[arrays - 1]->rows);
294 for (j = 0; j < array[arrays - 1]->rows; j++) {
295 char buffer[2] = {s_arg[i_arg].list[1][j], '\0'};
297 }
298 } else {
299 array[arrays - 1]->rows = s_arg[i_arg].n_items - 1;
300 array[arrays - 1]->dataList = malloc(sizeof(*(array[arrays - 1]->dataList)) * array[arrays - 1]->rows);
301 for (j = 0; j < array[arrays - 1]->rows; j++)
302 SDDS_CopyString(&array[arrays - 1]->dataList[j], s_arg[i_arg].list[j + 1]);
303 }
304 }
305 break;
306 case CLO_DEFAULTTYPE:
307 if (s_arg[i_arg].n_items != 2)
308 SDDS_Bomb(
"Invalid -defaultType option.");
310 break;
311 case CLO_PIPE:
312 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
314 if (pipeFlags != USE_STDOUT)
315 SDDS_Bomb(
"Only -pipe=out syntax is valid.");
316 break;
317 case CLO_DESCRIPTION:
318 if (s_arg[i_arg].n_items != 2)
319 SDDS_Bomb(
"Invalid -description option.");
321 break;
322 case CLO_CONTENTS:
323 if (s_arg[i_arg].n_items != 2)
326 break;
327 case CLO_ASCII:
328 outputMode = SDDS_ASCII;
329 break;
330 case CLO_APPEND:
331 append = 1;
332 if (s_arg[i_arg].n_items != 1) {
333 append = 2;
334 if (s_arg[i_arg].n_items > 2 || strncmp(s_arg[i_arg].list[1], "merge", strlen(s_arg[i_arg].list[1])) != 0)
336 }
337 break;
338 default:
339 fprintf(stderr, "Error: Option %s is invalid.\n", s_arg[i_arg].list[0]);
340 exit(EXIT_FAILURE);
341 break;
342 }
343 previousOption = currentOption;
344 } else {
345 if (outputFile == NULL)
347 else {
348 fprintf(stderr, "Error: Too many filenames provided (%s).\n", s_arg[i_arg].list[0]);
349 exit(EXIT_FAILURE);
350 }
351 }
352 }
353
354 if (!outputFile && !pipeFlags) {
355 fprintf(stderr, "Error: Either an output file or -pipe=out must be specified.\n\n%s", USAGE);
356 exit(EXIT_FAILURE);
357 }
358 if (outputFile && pipeFlags) {
359 fprintf(stderr, "Error: Only one of output file and -pipe=out can be specified.\n\n%s", USAGE);
360 exit(EXIT_FAILURE);
361 }
362
363 processFilenames(
"sddsmakedataset", &input, &outputFile, pipeFlags, 1, &tmpfile_used);
364 if (!columns && !parameters && !arrays) {
365 fprintf(stderr, "Error: No data provided for writing.\n\n%s", USAGE);
366 exit(EXIT_FAILURE);
367 }
368 if (contents && !description) {
369 if (!noWarnings) {
370 fprintf(stderr, "Warning: Description text is provided for contents without a description. No description will be written.\n");
371 free(contents);
372 contents = NULL;
373 }
374 }
375 for (i = 0; i < columns; i++)
376 if (maxrows < column[i]->rows)
377 maxrows = column[i]->rows;
378 SetInfoData(parameter, parameters, column, columns, array, arrays, defaultType, noWarnings, maxrows);
379
380 if (append == 0) {
381
384 outTable.layout.data_mode.column_major = columnMajorOrder;
385 for (i = 0; i < parameters; i++) {
386 if (parameter[i]->dataString) {
387 if (
SDDS_DefineParameter(&outTable, parameter[i]->name, parameter[i]->symbol, parameter[i]->unit, parameter[i]->description, NULL, parameter[i]->type, NULL) < 0)
389 }
390 }
391
392 for (i = 0; i < columns; i++) {
393 if (column[i]->dataList) {
394 if (
SDDS_DefineColumn(&outTable, column[i]->name, column[i]->symbol, column[i]->unit, column[i]->description, NULL, column[i]->type, 0) < 0)
396 }
397 }
398 for (i = 0; i < arrays; i++) {
399 if (array[i]->dataList) {
400 if (
SDDS_DefineArray(&outTable, array[i]->name, array[i]->symbol, array[i]->unit, array[i]->description, NULL, array[i]->type, 0, 1, NULL) < 0)
402 }
403 }
406 }
407 if (append == 1) {
408
411 }
412 if (append == 2) {
413
416 }
417 if (append) {
418
419 for (i = 0; i < parameters; i++) {
420 if (parameter[i]->dataString) {
422 fprintf(stderr, "Error: Parameter '%s' does not exist in the existing file.\n", parameter[i]->name);
423 exit(EXIT_FAILURE);
424 }
425 }
426 }
428 fprintf(stderr, "Error: Parameter count does not match the existing file.\n");
429 exit(EXIT_FAILURE);
430 }
431 for (i = 0; i < columns; i++) {
432 if (column[i]->dataList) {
434 fprintf(stderr, "Error: Column '%s' does not exist in the existing file.\n", column[i]->name);
435 exit(EXIT_FAILURE);
436 }
437 }
438 }
440 fprintf(stderr, "Error: Column count does not match the existing file.\n");
441 exit(EXIT_FAILURE);
442 }
443 for (i = 0; i < arrays; i++) {
444 if (array[i]->dataList) {
446 fprintf(stderr, "Error: Array '%s' does not exist in the existing file.\n", array[i]->name);
447 exit(EXIT_FAILURE);
448 }
449 }
450 }
452 fprintf(stderr, "Error: Array count does not match the existing file.\n");
453 exit(EXIT_FAILURE);
454 }
455 }
456
457 if (append == 0 || append == 1) {
460 for (i = 0; i < parameters; i++) {
461 if (parameter[i]->data) {
462 if (!
SDDS_SetParameters(&outTable, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, parameter[i]->name, parameter[i]->data, NULL))
464 }
465 }
466 for (i = 0; i < columns; i++) {
467 if (column[i]->data) {
468 if (!
SDDS_SetColumn(&outTable, SDDS_SET_BY_NAME, column[i]->data, maxrows, column[i]->name))
470 }
471 }
472 for (i = 0; i < arrays; i++) {
473 if (array[i]->data) {
474 if (!
SDDS_SetArrayVararg(&outTable, array[i]->name, SDDS_CONTIGUOUS_DATA, array[i]->data, array[i]->rows))
476 }
477 }
478 }
479 if (append == 2) {
480 for (i = 0; i < columns; i++) {
481 if (column[i]->data) {
483 for (j = 0; j < maxrows; j++) {
484 switch (column[i]->type) {
486 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
487 colIndex, ((long double *)(column[i]->data))[j], -1) == 0)
489 break;
491 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
492 colIndex, ((double *)(column[i]->data))[j], -1) == 0)
494 break;
496 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
497 colIndex, ((float *)(column[i]->data))[j], -1) == 0)
499 break;
501 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
502 colIndex, ((int64_t *)(column[i]->data))[j], -1) == 0)
504 break;
506 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
507 colIndex, ((uint64_t *)(column[i]->data))[j], -1) == 0)
509 break;
511 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
512 colIndex, ((int32_t *)(column[i]->data))[j], -1) == 0)
514 break;
516 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
517 colIndex, ((uint32_t *)(column[i]->data))[j], -1) == 0)
519 break;
521 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
522 colIndex, ((short *)(column[i]->data))[j], -1) == 0)
524 break;
526 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
527 colIndex, ((unsigned short *)(column[i]->data))[j], -1) == 0)
529 break;
531 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
532 colIndex, ((char *)(column[i]->data))[j], -1) == 0)
534 break;
536 if (
SDDS_SetRowValues(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rowsPresent + j,
537 colIndex, ((char **)(column[i]->data))[j], -1) == 0)
539 break;
540 default:
541 SDDS_Bomb(
"Invalid data type provided.");
542 break;
543 }
544 }
545 }
546 }
547 for (i = 0; i < arrays; i++) {
548 if (array[i]->data) {
550 sdds_array = outTable.array + arrayIndex;
552 startIndex = sdds_array->elements;
553 sdds_array->elements += array[i]->rows;
554 sdds_array->data =
SDDS_Realloc(sdds_array->data, dsize * sdds_array->elements);
556 if (!
SDDS_CopyStringArray(((
char **)sdds_array->data) + startIndex, array[i]->data, array[i]->rows))
558 } else {
559 memcpy((char *)sdds_array->data + dsize * startIndex, array[i]->data, dsize * array[i]->rows);
560 }
561 }
562 }
563 }
564
565 if (append == 2) {
568 } else {
571 }
572
573
575 exit(EXIT_FAILURE);
577 FreeMemory(parameter, parameters, column, columns, array, arrays, maxrows);
578 if (defaultType)
579 free(defaultType);
580 if (outputFile)
581 free(outputFile);
582 if (description)
583 free(description);
584 if (contents)
585 free(contents);
586 return EXIT_SUCCESS;
587}
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.