55static char *optionName[N_OPTIONS] = {
65#define PARAMETER_CLASS 1
67#define CONSTANT_CLASS 3
71 "Usage: sddsderef [<inputfile>] [<outputfile>]\n"
72 " [-pipe=[input][,output]]\n"
73 " [-column=<newName>,{arraySource|columnSource}=<name>,<indexColumnName>[,...]]\n"
74 " [-parameter=<newName>,{arraySource|columnSource}=<name>,<indexParameterName>[,...]]\n"
75 " [-constant=<newName>,{arraySource|columnSource}=<name>,<indexValue>[,<indexValue>]]\n"
76 " [-outOfBounds={exit|delete}] [-majorOrder=row|column]\n\n"
78 " -pipe Use standard input and/or output instead of files.\n"
79 " -column Define a new column by dereferencing an existing array or column.\n"
80 " -parameter Define a new parameter by dereferencing an existing array or column.\n"
81 " -constant Define a new constant by dereferencing an existing array or column.\n"
82 " -outOfBounds Specify behavior for out-of-bounds indices: 'exit' or 'delete'.\n"
83 " -majorOrder Specify the major order for processing: 'row' or 'column'.\n\n"
84 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
88 char *target, *source, **indexElement;
89 long targetIndex, indexElements, targetClass, sourceClass, sourceIndex;
99void addDerefRequest(
DEREF_REQUEST **deref,
long *derefs,
char **argv,
long argc,
long class);
101#define EXIT_OUTBOUNDS 0x1U
102#define DELETE_OUTBOUNDS 0x2U
104int main(
int argc,
char **argv) {
108 char *input, *output;
109 long derefRequests, code;
110 unsigned long outOfBounds;
112 unsigned long pipeFlags, majorOrderFlag;
113 short columnMajorOrder = -1;
116 argc =
scanargs(&s_arg, argc, argv);
120 input = output = NULL;
124 outOfBounds = EXIT_OUTBOUNDS;
126 for (i_arg = 1; i_arg < argc; i_arg++) {
127 if (s_arg[i_arg].arg_type == OPTION) {
128 switch (
match_string(s_arg[i_arg].list[0], optionName, N_OPTIONS, 0)) {
129 case SET_MAJOR_ORDER:
131 s_arg[i_arg].n_items--;
132 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)))
133 SDDS_Bomb(
"invalid -majorOrder syntax/values");
134 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
135 columnMajorOrder = 1;
136 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
137 columnMajorOrder = 0;
140 if (s_arg[i_arg].n_items < 4)
142 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, COLUMN_CLASS);
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, PARAMETER_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, CONSTANT_CLASS);
155 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
158 case SET_OUTOFBOUNDS:
159 s_arg[i_arg].n_items -= 1;
161 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) {
162 SDDS_Bomb(
"invalid -outOfBounds syntax/values");
166 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", s_arg[i_arg].list[0]);
172 input = s_arg[i_arg].list[0];
173 else if (output == NULL)
174 output = s_arg[i_arg].list[0];
182 setupOutputFile(&outSet, output, &inSet, input, derefRequest, derefRequests, columnMajorOrder);
187 if (!DoDereferencing(&outSet, derefRequest, derefRequests, outOfBounds))
188 SDDS_Bomb(
"problem doing dereferencing");
206 if (columnMajorOrder != -1)
207 outSet->layout.data_mode.column_major = columnMajorOrder;
209 outSet->layout.data_mode.column_major = inSet->layout.data_mode.column_major;
210 for (i = 0; i < derefs; i++) {
211 switch (deref[i].sourceClass) {
214 fprintf(stderr,
"error (sddsderef): no array %s in input\n", deref[i].source);
220 fprintf(stderr,
"error (sddsderef): no column %s in input\n", deref[i].source);
225 SDDS_Bomb(
"invalid source class in setupOutputFile (coding error)");
228 switch (deref[i].targetClass) {
229 case PARAMETER_CLASS:
231 switch (deref[i].sourceClass) {
244 if (deref[i].targetClass == PARAMETER_CLASS) {
245 for (j = 0; j < deref[i].indexElements; j++) {
247 fprintf(stderr,
"error (sddsderef): no parameter %s in input\n", deref[i].indexElement[j]);
254 switch (deref[i].sourceClass) {
267 for (j = 0; j < deref[i].indexElements; j++) {
269 fprintf(stderr,
"error (sddsderef): no column %s in input\n", deref[i].indexElement[j]);
275 fprintf(stderr,
"error (sddsderef): invalid target data class (internal error)\n");
284void addDerefRequest(
DEREF_REQUEST **deref,
long *derefs,
char **argv,
long argc,
long class) {
287#define ARRAY_SOURCE 0x1U
288#define COLUMN_SOURCE 0x2U
290 fprintf(stderr,
"error (sddsderef): too few values for -%s\n", optionName[
class]);
293 if (!(*deref =
SDDS_Realloc(*deref,
sizeof(**deref) * (*derefs + 1))))
294 SDDS_Bomb(
"memory allocation failure (addDerefRequest)");
297 (*deref)[*derefs].targetClass =
class;
298 (*deref)[*derefs].target = argv[0];
304 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) ||
306 flags == (ARRAY_SOURCE | COLUMN_SOURCE)) {
307 fprintf(stderr,
"error (sddsderef): one of arraySource or columnSource must be given with -column or -parameter\n");
310 if (flags & ARRAY_SOURCE)
311 (*deref)[*derefs].sourceClass = ARRAY_CLASS;
313 (*deref)[*derefs].sourceClass = COLUMN_CLASS;
315 fprintf(stderr,
"error (sddsderef): too many indices for column dereference\n");
323 (*deref)[*derefs].indexElements = argc;
324 (*deref)[*derefs].indexElement = NULL;
325 (*deref)[*derefs].indexValue = NULL;
326 if (
class == CONSTANT_CLASS) {
327 if (!((*deref)[*derefs].indexValue = (
long *)malloc(
sizeof(
long) * argc))) {
328 SDDS_Bomb(
"memory allocation failure (addDerefRequest)");
330 for (i = 0; i < argc; i++) {
331 if (sscanf(argv[i],
"%ld", (*deref)[*derefs].indexValue + i) != 1)
332 SDDS_Bomb(
"constant doesn't contain scannable integer");
335 if (!((*deref)[*derefs].indexElement = (
char **)malloc(
sizeof(*(*deref)[*derefs].indexElement) * argc)))
336 SDDS_Bomb(
"memory allocation failure (addDerefRequest)");
337 for (i = 0; i < argc; i++)
338 (*deref)[*derefs].indexElement[i] = argv[i];
345 for (i = 0; i < derefs; i++) {
346 switch (deref[i].targetClass) {
347 case PARAMETER_CLASS:
349 switch (deref[i].sourceClass) {
351 if (!DereferenceArrayWithParameter(outSet, deref + i, outOfBounds))
355 if (!DereferenceColumnWithParameter(outSet, deref + i, outOfBounds))
359 SDDS_Bomb(
"invalid source class--code error (DoDereferencing)");
364 switch (deref[i].sourceClass) {
366 if (!DereferenceArrayWithColumn(outSet, deref + i, outOfBounds))
370 if (!DereferenceColumnWithColumn(outSet, deref + i, outOfBounds))
374 SDDS_Bomb(
"invalid source class--code error (DoDereferencing)");
379 SDDS_Bomb(
"invalid target class--code error (DoDereferencing)");
391 int32_t zeroValue = 0;
392 static char *blankString =
"";
394 if (!(rows = outSet->n_rows))
397 if (deref->targetClass == CONSTANT_CLASS) {
398 value = deref->indexValue[0];
403 offset = ((long)value);
404 if (offset < 0 || offset >= rows) {
405 if (outOfBounds & EXIT_OUTBOUNDS) {
407 sprintf(s,
"column index out of bounds: column %s, length %" PRId64
", offset %ld\n %s=%ld", deref->source, rows, offset, deref->indexElement[0], offset);
411 memcpy((
char *)data, (
char *)&blankString,
sizeof(blankString));
421 if (!
SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (
void *)data, -1)) {
430 long i, j, offset, size;
432 int32_t zeroValue = 0;
433 static char *blankString =
"";
440 if (deref->indexElements != array->definition->dimensions) {
441 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);
446 for (i = 0, j = deref->indexElements - 1; i < deref->indexElements; i++, j--) {
447 if (deref->targetClass == CONSTANT_CLASS) {
448 value = deref->indexValue[i];
456 offset = ((long)value) + offset * array->dimension[j];
458 if (offset < 0 || offset >= array->elements) {
459 if (outOfBounds & EXIT_OUTBOUNDS) {
461 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);
465 memcpy((
char *)data, (
char *)&blankString,
sizeof(blankString));
468 if (!
SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (
void *)data, -1)) {
472 }
else if (!
SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (
char *)array->data + offset * size, -1)) {
482 long i, offset, size, index;
486 if (!(rows = outSet->n_rows))
492 if (deref->indexElements != array->definition->dimensions) {
493 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);
499 if (!(indexData = (int32_t **)malloc(
sizeof(*indexData) * deref->indexElements)))
500 SDDS_Bomb(
"memory allocation failure while derefencing column data");
501 for (i = 0; i < deref->indexElements; i++)
506 for (row = 0; row < rows; row++) {
507 for (i = offset = 0; i < deref->indexElements; i++) {
509 index = indexData[i][row];
510 if (index < 0 || index > array->dimension[i]) {
514 offset = index + offset * array->dimension[i];
517 if (offset < 0 || offset >= array->elements) {
518 if (outOfBounds & EXIT_OUTBOUNDS) {
519 char s[1024], t[1024];
520 sprintf(s,
"array index out of bounds: array %s, length %" PRId32
", offset %ld\n", deref->source, array->elements, offset);
521 for (i = 0; i < deref->indexElements; i++) {
522 sprintf(t,
" %s=%" PRId32
" (dim=%" PRId32
")", deref->indexElement[i], indexData[i][row], array->dimension[i]);
531 }
else if (!
SDDS_SetRowValues(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, row, deref->targetIndex, (
char *)array->data + offset * size, -1)) {
536 for (i = 0; i < deref->indexElements; i++)
549 if (!(rows = outSet->n_rows)) {
558 for (row = 0; row < rows; row++) {
559 offset = indexData[row];
560 if (offset < 0 || offset >= rows) {
561 if (outOfBounds & EXIT_OUTBOUNDS) {
563 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);
571 !
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.