72char *option[N_OPTIONS] = {
83 "sddssequence [<outputfile>] \\\n"
84 " [-pipe=<output>] \\\n"
85 " -define=<columnName>[,<definitionEntries>] \\\n"
86 " [-repeat=<number>] \\\n"
88 " -sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] \\\n"
89 " [-sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] ...] \\\n"
90 " [-majorOrder=row|column]\n"
91 "Generates an SDDS file with a single page and several columns of data.\n"
93 " <outputfile> Specify the output SDDS file. If omitted, standard output is used.\n"
94 " -pipe=<output> Define pipe output options.\n"
95 " -define=<columnName>,<entries> Define a column with the given name and entries.\n"
96 " -repeat=<number> Repeat the sequence the specified number of times.\n"
97 " -break Insert a page break between repeats.\n"
98 " -sequence=begin=<val>,number=<n>,end=<val>,delta=<val>,interval=<n>\n"
99 " Define a sequence with specified parameters. Multiple -sequence options can be used.\n"
100 " -majorOrder=row|column Set the major order of data storage.\n\n"
102 " - The default data type is double. To specify a different type, use type=<typeName> in -define.\n"
103 " - Each column is specified with a -define option followed by any number of -sequence options.\n"
104 " - The default value of delta is 1.\n"
105 " - The default beginning value is the ending value of the last sequence plus the delta of the last sequence.\n\n"
106 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
108#define SEQ_END_GIVEN 0x0001
109#define SEQ_BEGIN_GIVEN 0x0002
110#define SEQ_NUMBER_GIVEN 0x0004
111#define SEQ_DELTA_GIVEN 0x0008
112#define SEQ_INTERVAL_GIVEN 0x0010
115#define SEQ_ENDplusDELTA (SEQ_END_GIVEN + SEQ_DELTA_GIVEN)
116#define SEQ_ENDplusNUMBER (SEQ_END_GIVEN + SEQ_NUMBER_GIVEN)
117#define SEQ_DELTAplusNUMBER (SEQ_DELTA_GIVEN + SEQ_NUMBER_GIVEN)
121 double begin, end, delta;
122 int64_t number, interval;
136void addSequence(
char **item,
long items,
DEFINITION *definition);
137void addDefinition(
char **item,
long items,
DEFINITION **definition,
long *definitions);
139void setupOutputFile(
SDDS_DATASET *outputTable,
char *output,
DEFINITION *definition,
long definitions,
short columnMajorOrder);
142int main(
int argc,
char **argv) {
147 long definitions = 0;
151 unsigned long pipeFlags = 0, majorOrderFlag;
152 short columnMajorOrder = 0;
155 argc =
scanargs(&s_arg, argc, argv);
160 for (i_arg = 1; i_arg < argc; i_arg++) {
161 if (s_arg[i_arg].arg_type == OPTION) {
162 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
163 case SET_MAJOR_ORDER:
165 s_arg[i_arg].n_items--;
166 if (s_arg[i_arg].n_items > 0 &&
167 !
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
168 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
169 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
170 SDDS_Bomb(
"invalid -majorOrder syntax/values");
172 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER) {
173 columnMajorOrder = 1;
174 }
else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER) {
175 columnMajorOrder = 0;
180 addDefinition(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &definition, &definitions);
184 if (definitions == 0) {
185 SDDS_Bomb(
"can't give a repeat specifier prior to a definition");
187 if (s_arg[i_arg].n_items != 2 ||
188 sscanf(s_arg[i_arg].list[1],
"%ld", &definition[definitions - 1].repeats) != 1 ||
189 definition[definitions - 1].repeats <= 0) {
190 SDDS_Bomb(
"invalid -repeat syntax/value");
199 if (definitions == 0) {
200 SDDS_Bomb(
"can't create a sequence prior to defining the variable");
202 addSequence(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, definition + definitions - 1);
206 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
212 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", s_arg[i_arg].list[0]);
217 if (output == NULL) {
218 output = s_arg[i_arg].list[0];
225 if (output == NULL && !(pipeFlags & USE_STDOUT)) {
233 setupOutputFile(&outputTable, output, definition, definitions, columnMajorOrder);
234 generateOutput(&outputTable, definition, definitions, doBreak);
241 for (i = 0; i < definitions; i++) {
242 free(definition[i].sequence);
243 free(definition[i].data);
251void addDefinition(
char **item,
long items,
DEFINITION **definition,
long *definitions) {
253 SDDS_Bomb(
"unable to add definition--supply column name");
255 *definition =
SDDS_Realloc(*definition,
sizeof(**definition) * (*definitions + 1));
256 if (!(*definition)) {
257 SDDS_Bomb(
"unable to add definition---allocation failure");
260 (*definition)[*definitions].columnName = item[0];
261 (*definition)[*definitions].item = item + 1;
262 (*definition)[*definitions].items = items - 1;
263 (*definition)[*definitions].sequence = NULL;
264 (*definition)[*definitions].sequences = 0;
265 (*definition)[*definitions].rows = 0;
266 (*definition)[*definitions].data = NULL;
267 (*definition)[*definitions].repeats = 1;
271void addSequence(
char **item,
long items,
DEFINITION *definition) {
275 definition->sequence =
SDDS_Realloc(definition->sequence,
sizeof(*definition->sequence) * (definition->sequences + 1));
276 if (!definition->sequence) {
277 SDDS_Bomb(
"unable to add sequence--memory allocation failure");
280 sequence = &definition->sequence[definition->sequences];
281 sequence->interval = 1;
284 "begin",
SDDS_DOUBLE, &sequence->begin, 1, SEQ_BEGIN_GIVEN,
285 "end",
SDDS_DOUBLE, &sequence->end, 1, SEQ_END_GIVEN,
286 "number",
SDDS_LONG64, &sequence->number, 1, SEQ_NUMBER_GIVEN,
287 "delta",
SDDS_DOUBLE, &sequence->delta, 1, SEQ_DELTA_GIVEN,
288 "interval",
SDDS_LONG64, &sequence->interval, 1, SEQ_INTERVAL_GIVEN,
293 if ((sequence->flags & SEQ_NUMBER_GIVEN) && sequence->number <= 0) {
294 SDDS_Bomb(
"number <= 0 is not valid for -sequence");
297 if ((sequence->flags & SEQ_DELTA_GIVEN) && sequence->delta == 0) {
298 SDDS_Bomb(
"delta == 0 is not valid for -sequence");
301 if (!(sequence->flags & SEQ_BEGIN_GIVEN)) {
302 if (definition->sequences == 0) {
303 SDDS_Bomb(
"you must give begin point for the first sequence of a definition");
305 if (!(sequence->flags & SEQ_DELTA_GIVEN)) {
306 SDDS_Bomb(
"you must give delta with implied begin point");
308 sequence->begin = definition->sequence[definition->sequences - 1].end + sequence->delta;
311 if ((sequence->flags & SEQ_INTERVAL_GIVEN) && sequence->interval <= 0) {
312 SDDS_Bomb(
"interval for sequence must be > 0");
315 if ((sequence->flags & SEQ_ENDplusDELTA) == SEQ_ENDplusDELTA) {
316 sequence->number = ((long)((sequence->end - sequence->begin) / sequence->delta + 1.5)) * sequence->interval;
317 if (sequence->number <= 0) {
318 SDDS_Bomb(
"given (start, end, delta) implies number of points <= 0");
320 }
else if ((sequence->flags & SEQ_ENDplusNUMBER) == SEQ_ENDplusNUMBER) {
321 if (sequence->number == 1) {
324 sequence->delta = (sequence->end - sequence->begin) / (sequence->number - 1) * sequence->interval;
326 }
else if ((sequence->flags & SEQ_DELTAplusNUMBER) == SEQ_DELTAplusNUMBER) {
327 sequence->end = (sequence->delta / sequence->interval) * (sequence->number - 1) + sequence->begin;
329 SDDS_Bomb(
"you must supply (end, delta), (end, number), or (delta, number)");
332 definition->data =
SDDS_Realloc(definition->data,
sizeof(*definition->data) * (definition->rows + sequence->number));
333 if (!definition->data) {
334 SDDS_Bomb(
"unable to generate sequence data--allocation failure");
337 for (i = 0; i < sequence->number; i++) {
338 definition->data[definition->rows + i] = sequence->begin + (i / sequence->interval) * sequence->delta;
341 definition->rows += sequence->number;
342 definition->sequences++;
346 long idef, row, rows = 0, totalRows = 0;
349 for (idef = 0; idef < definitions; idef++) {
350 totalRows = definition[idef].rows * definition[idef].repeats;
351 if (idef && totalRows != rows) {
352 fputs(
"warning: sequences are of different length (sddssequence)\n", stderr);
354 if (totalRows > rows) {
360 SDDS_Bomb(
"total number of points in sequence is zero");
367 for (idef = 0; idef < definitions; idef++) {
368 if (definition[idef].rows != totalRows) {
370 definition[idef].data =
SDDS_Realloc(definition[idef].data,
sizeof(*definition[idef].data) * rows);
371 if (!definition[idef].data) {
372 SDDS_Bomb(
"unable to generate output--allocation failure");
374 for (row = definition[idef].rows; row < rows; row++) {
375 definition[idef].data[row] = definition[idef].data[row % definition[idef].rows];
388 rows = definition[0].rows;
390 SDDS_Bomb(
"number of points in sequence is zero");
392 for (idef = 1; idef < definitions; idef++) {
393 if (rows != definition[idef].rows) {
394 fputs(
"warning: sequences are of different length (sddssequence)\n", stderr);
397 for (irep = 0; irep < definition[0].repeats; irep++) {
401 for (idef = 0; idef < definitions; idef++) {
413void setupOutputFile(
SDDS_DATASET *outputTable,
char *output,
DEFINITION *definition,
long definitions,
short columnMajorOrder) {
420 for (i = 0; i < definitions; i++) {
421 createColumn(outputTable, &definition[i]);
424 outputTable->layout.data_mode.column_major = columnMajorOrder;
431 char s[SDDS_MAXLINE];
435 if (!definition->columnName) {
439 SDDS_Bomb(
"column name already exists (sddssequence)");
443 snprintf(s,
sizeof(s),
"&column name=%s, ", definition->columnName);
445 for (i = 0; i < definition->items; i++) {
446 ptr = strchr(definition->item[i],
'=');
448 fprintf(stderr,
"error: invalid definition-entry: %s\n", definition->item[i]);
452 strcat(s, definition->item[i]);
459 if (!strstr(s,
", type=")) {
460 strcat(s,
" type=\"double\", ");
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
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_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_ProcessColumnString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode)
Process a column definition string.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column 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.
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_DOUBLE
Identifier for the double data type.
#define SDDS_LONG64
Identifier for the signed 64-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 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.