59static char *optionName[N_OPTIONS] = {
69#define PARAMETER_CLASS 1
71#define CONSTANT_CLASS 3
75 "sddsderef [<inputfile>] [<outputfile>]\n"
76 " [-pipe=[input][,output]]\n"
77 " [-column=<newName>,{arraySource|columnSource}=<name>,<indexColumnName>[,...]]\n"
78 " [-parameter=<newName>,{arraySource|columnSource}=<name>,<indexParameterName>[,...]]\n"
79 " [-constant=<newName>,{arraySource|columnSource}=<name>,<indexValue>[,<indexValue>]]\n"
80 " [-outOfBounds=exit|delete]\n"
81 " [-majorOrder=row|column]\n\n"
83 " -pipe Use standard input and/or output instead of files.\n"
84 " -column Define a new column by dereferencing an existing array or column.\n"
85 " -parameter Define a new parameter by dereferencing an existing array or column.\n"
86 " -constant Define a new constant by dereferencing an existing array or column.\n"
87 " -outOfBounds Specify behavior for out-of-bounds indices: 'exit' or 'delete'.\n"
88 " -majorOrder Specify the major order for processing: 'row' or 'column'.\n\n"
89 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
93 char *target, *source, **indexElement;
94 long targetIndex, indexElements, targetClass, sourceClass, sourceIndex;
104void addDerefRequest(
DEREF_REQUEST **deref,
long *derefs,
char **argv,
long argc,
long class);
106#define EXIT_OUTBOUNDS 0x1U
107#define DELETE_OUTBOUNDS 0x2U
109int main(
int argc,
char **argv) {
113 char *input, *output;
114 long derefRequests, code;
115 unsigned long outOfBounds;
117 unsigned long pipeFlags, majorOrderFlag;
118 short columnMajorOrder = -1;
121 argc =
scanargs(&s_arg, argc, argv);
125 input = output = NULL;
129 outOfBounds = EXIT_OUTBOUNDS;
131 for (i_arg = 1; i_arg < argc; i_arg++) {
132 if (s_arg[i_arg].arg_type == OPTION) {
133 switch (
match_string(s_arg[i_arg].list[0], optionName, N_OPTIONS, 0)) {
134 case SET_MAJOR_ORDER:
136 s_arg[i_arg].n_items--;
137 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)))
138 SDDS_Bomb(
"invalid -majorOrder syntax/values");
139 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
140 columnMajorOrder = 1;
141 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
142 columnMajorOrder = 0;
145 if (s_arg[i_arg].n_items < 4)
147 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, COLUMN_CLASS);
150 if (s_arg[i_arg].n_items < 4)
152 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, PARAMETER_CLASS);
155 if (s_arg[i_arg].n_items < 4)
157 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, CONSTANT_CLASS);
160 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
163 case SET_OUTOFBOUNDS:
164 s_arg[i_arg].n_items -= 1;
166 if (s_arg[i_arg].n_items != 1 || !
scanItemList(&outOfBounds, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
"exit", -1, NULL, 0, EXIT_OUTBOUNDS,
"delete", -1, NULL, 0, DELETE_OUTBOUNDS, NULL) || !outOfBounds) {
167 SDDS_Bomb(
"invalid -outOfBounds syntax/values");
171 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", s_arg[i_arg].list[0]);
177 input = s_arg[i_arg].list[0];
178 else if (output == NULL)
179 output = s_arg[i_arg].list[0];
187 setupOutputFile(&outSet, output, &inSet, input, derefRequest, derefRequests, columnMajorOrder);
192 if (!DoDereferencing(&outSet, derefRequest, derefRequests, outOfBounds))
193 SDDS_Bomb(
"problem doing dereferencing");
211 if (columnMajorOrder != -1)
212 outSet->layout.data_mode.column_major = columnMajorOrder;
214 outSet->layout.data_mode.column_major = inSet->layout.data_mode.column_major;
215 for (i = 0; i < derefs; i++) {
216 switch (deref[i].sourceClass) {
219 fprintf(stderr,
"error (sddsderef): no array %s in input\n", deref[i].source);
225 fprintf(stderr,
"error (sddsderef): no column %s in input\n", deref[i].source);
230 SDDS_Bomb(
"invalid source class in setupOutputFile (coding error)");
233 switch (deref[i].targetClass) {
234 case PARAMETER_CLASS:
236 switch (deref[i].sourceClass) {
249 if (deref[i].targetClass == PARAMETER_CLASS) {
250 for (j = 0; j < deref[i].indexElements; j++) {
252 fprintf(stderr,
"error (sddsderef): no parameter %s in input\n", deref[i].indexElement[j]);
259 switch (deref[i].sourceClass) {
272 for (j = 0; j < deref[i].indexElements; j++) {
274 fprintf(stderr,
"error (sddsderef): no column %s in input\n", deref[i].indexElement[j]);
280 fprintf(stderr,
"error (sddsderef): invalid target data class (internal error)\n");
289void addDerefRequest(
DEREF_REQUEST **deref,
long *derefs,
char **argv,
long argc,
long class) {
292#define ARRAY_SOURCE 0x1U
293#define COLUMN_SOURCE 0x2U
295 fprintf(stderr,
"error (sddsderef): too few values for -%s\n", optionName[
class]);
298 if (!(*deref =
SDDS_Realloc(*deref,
sizeof(**deref) * (*derefs + 1))))
299 SDDS_Bomb(
"memory allocation failure (addDerefRequest)");
302 (*deref)[*derefs].targetClass =
class;
303 (*deref)[*derefs].target = argv[0];
309 if (!
scanItemList(&flags, argv, &items, 0,
"arraySource",
SDDS_STRING, &(*deref)[*derefs].source, 1, ARRAY_SOURCE,
"columnSource",
SDDS_STRING, &(*deref)[*derefs].source, 1, COLUMN_SOURCE, NULL) ||
311 flags == (ARRAY_SOURCE | COLUMN_SOURCE)) {
312 fprintf(stderr,
"error (sddsderef): one of arraySource or columnSource must be given with -column or -parameter\n");
315 if (flags & ARRAY_SOURCE)
316 (*deref)[*derefs].sourceClass = ARRAY_CLASS;
318 (*deref)[*derefs].sourceClass = COLUMN_CLASS;
320 fprintf(stderr,
"error (sddsderef): too many indices for column dereference\n");
328 (*deref)[*derefs].indexElements = argc;
329 (*deref)[*derefs].indexElement = NULL;
330 (*deref)[*derefs].indexValue = NULL;
331 if (
class == CONSTANT_CLASS) {
332 if (!((*deref)[*derefs].indexValue = (
long *)malloc(
sizeof(
long) * argc))) {
333 SDDS_Bomb(
"memory allocation failure (addDerefRequest)");
335 for (i = 0; i < argc; i++) {
336 if (sscanf(argv[i],
"%ld", (*deref)[*derefs].indexValue + i) != 1)
337 SDDS_Bomb(
"constant doesn't contain scannable integer");
340 if (!((*deref)[*derefs].indexElement = (
char **)malloc(
sizeof(*(*deref)[*derefs].indexElement) * argc)))
341 SDDS_Bomb(
"memory allocation failure (addDerefRequest)");
342 for (i = 0; i < argc; i++)
343 (*deref)[*derefs].indexElement[i] = argv[i];
350 for (i = 0; i < derefs; i++) {
351 switch (deref[i].targetClass) {
352 case PARAMETER_CLASS:
354 switch (deref[i].sourceClass) {
356 if (!DereferenceArrayWithParameter(outSet, deref + i, outOfBounds))
360 if (!DereferenceColumnWithParameter(outSet, deref + i, outOfBounds))
364 SDDS_Bomb(
"invalid source class--code error (DoDereferencing)");
369 switch (deref[i].sourceClass) {
371 if (!DereferenceArrayWithColumn(outSet, deref + i, outOfBounds))
375 if (!DereferenceColumnWithColumn(outSet, deref + i, outOfBounds))
379 SDDS_Bomb(
"invalid source class--code error (DoDereferencing)");
384 SDDS_Bomb(
"invalid target class--code error (DoDereferencing)");
396 int32_t zeroValue = 0;
397 static char *blankString =
"";
399 if (!(rows = outSet->n_rows))
402 if (deref->targetClass == CONSTANT_CLASS) {
403 value = deref->indexValue[0];
408 offset = ((long)value);
409 if (offset < 0 || offset >= rows) {
410 if (outOfBounds & EXIT_OUTBOUNDS) {
412 sprintf(s,
"column index out of bounds: column %s, length %" PRId64
", offset %ld\n %s=%ld", deref->source, rows, offset, deref->indexElement[0], offset);
416 memcpy((
char *)data, (
char *)&blankString,
sizeof(blankString));
426 if (!
SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (
void *)data, -1)) {
435 long i, j, offset, size;
437 int32_t zeroValue = 0;
438 static char *blankString =
"";
445 if (deref->indexElements != array->definition->dimensions) {
446 fprintf(stderr,
"error: number of index elements (%ld) doesn't match number of array dimensions (%" PRId32
") for array %s\n", deref->indexElements, array->definition->dimensions, deref->source);
451 for (i = 0, j = deref->indexElements - 1; i < deref->indexElements; i++, j--) {
452 if (deref->targetClass == CONSTANT_CLASS) {
453 value = deref->indexValue[i];
461 offset = ((long)value) + offset * array->dimension[j];
463 if (offset < 0 || offset >= array->elements) {
464 if (outOfBounds & EXIT_OUTBOUNDS) {
466 sprintf(s,
"array index out of bounds: array %s, length %" PRId32
", offset %ld\n %s=%ld", deref->source, array->elements, offset, deref->indexElement[0], offset);
470 memcpy((
char *)data, (
char *)&blankString,
sizeof(blankString));
473 if (!
SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (
void *)data, -1)) {
477 }
else if (!
SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (
char *)array->data + offset * size, -1)) {
487 long i, offset, size, index;
491 if (!(rows = outSet->n_rows))
497 if (deref->indexElements != array->definition->dimensions) {
498 fprintf(stderr,
"error: number of index elements (%ld) doesn't match number of array dimensions (%" PRId32
") for array %s\n", deref->indexElements, array->definition->dimensions, deref->source);
504 if (!(indexData = (int32_t **)malloc(
sizeof(*indexData) * deref->indexElements)))
505 SDDS_Bomb(
"memory allocation failure while derefencing column data");
506 for (i = 0; i < deref->indexElements; i++)
511 for (row = 0; row < rows; row++) {
512 for (i = offset = 0; i < deref->indexElements; i++) {
514 index = indexData[i][row];
515 if (index < 0 || index > array->dimension[i]) {
519 offset = index + offset * array->dimension[i];
522 if (offset < 0 || offset >= array->elements) {
523 if (outOfBounds & EXIT_OUTBOUNDS) {
524 char s[1024], t[1024];
525 sprintf(s,
"array index out of bounds: array %s, length %" PRId32
", offset %ld\n", deref->source, array->elements, offset);
526 for (i = 0; i < deref->indexElements; i++) {
527 sprintf(t,
" %s=%" PRId32
" (dim=%" PRId32
")", deref->indexElement[i], indexData[i][row], array->dimension[i]);
536 }
else if (!
SDDS_SetRowValues(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, row, deref->targetIndex, (
char *)array->data + offset * size, -1)) {
541 for (i = 0; i < deref->indexElements; i++)
554 if (!(rows = outSet->n_rows)) {
563 for (row = 0; row < rows; row++) {
564 offset = indexData[row];
565 if (offset < 0 || offset >= rows) {
566 if (outOfBounds & EXIT_OUTBOUNDS) {
568 sprintf(s,
"column index out of bounds: column %s, length %" PRId64
", offset %ld\n %s=%ld\n", deref->source, rows, offset, deref->indexElement[0], offset);
576 !
SDDS_SetRowValues(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, row, deref->targetIndex, (
void *)data, -1)) {
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
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_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_DefineParameterLikeColumn(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a parameter in the target dataset based on a column definition from the source dataset.
int32_t SDDS_DefineColumnLikeArray(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a column in the target dataset based on an array definition from the source dataset.
int32_t SDDS_DefineParameterLikeArray(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a parameter in the target dataset based on an array definition from the source dataset.
void SDDS_FreeArray(SDDS_ARRAY *array)
Frees memory allocated for an SDDS array structure.
int32_t SDDS_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array 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.
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.
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_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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
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 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.