68char *option[N_OPTIONS] = {
79 "Usage: sddssequence [<outputfile>] \\\n"
80 " [-pipe=<output>] \\\n"
81 " -define=<columnName>[,<definitionEntries>] \\\n"
82 " [-repeat=<number>] \\\n"
84 " -sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] \\\n"
85 " [-sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] ...] \\\n"
86 " [-majorOrder=row|column]\n\n"
87 "Generates an SDDS file with a single page and several columns of data.\n"
89 " <outputfile> Specify the output SDDS file. If omitted, standard output is used.\n"
90 " -pipe=<output> Define pipe output options.\n"
91 " -define=<columnName>,<entries> Define a column with the given name and entries.\n"
92 " -repeat=<number> Repeat the sequence the specified number of times.\n"
93 " -break Insert a page break between repeats.\n"
94 " -sequence=begin=<val>,number=<n>,end=<val>,delta=<val>,interval=<n>\n"
95 " Define a sequence with specified parameters. Multiple -sequence options can be used.\n"
96 " -majorOrder=row|column Set the major order of data storage.\n\n"
98 " - The default data type is double. To specify a different type, use type=<typeName> in -define.\n"
99 " - Each column is specified with a -define option followed by any number of -sequence options.\n"
100 " - The default value of delta is 1.\n"
101 " - The default beginning value is the ending value of the last sequence plus the delta of the last sequence.\n\n"
102 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
104#define SEQ_END_GIVEN 0x0001
105#define SEQ_BEGIN_GIVEN 0x0002
106#define SEQ_NUMBER_GIVEN 0x0004
107#define SEQ_DELTA_GIVEN 0x0008
108#define SEQ_INTERVAL_GIVEN 0x0010
111#define SEQ_ENDplusDELTA (SEQ_END_GIVEN + SEQ_DELTA_GIVEN)
112#define SEQ_ENDplusNUMBER (SEQ_END_GIVEN + SEQ_NUMBER_GIVEN)
113#define SEQ_DELTAplusNUMBER (SEQ_DELTA_GIVEN + SEQ_NUMBER_GIVEN)
117 double begin, end, delta;
118 int64_t number, interval;
132void addSequence(
char **item,
long items,
DEFINITION *definition);
133void addDefinition(
char **item,
long items,
DEFINITION **definition,
long *definitions);
135void setupOutputFile(
SDDS_DATASET *outputTable,
char *output,
DEFINITION *definition,
long definitions,
short columnMajorOrder);
138int main(
int argc,
char **argv) {
143 long definitions = 0;
147 unsigned long pipeFlags = 0, majorOrderFlag;
148 short columnMajorOrder = 0;
151 argc =
scanargs(&s_arg, argc, argv);
156 for (i_arg = 1; i_arg < argc; i_arg++) {
157 if (s_arg[i_arg].arg_type == OPTION) {
158 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
159 case SET_MAJOR_ORDER:
161 s_arg[i_arg].n_items--;
162 if (s_arg[i_arg].n_items > 0 &&
163 !
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
164 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
165 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
166 SDDS_Bomb(
"invalid -majorOrder syntax/values");
168 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER) {
169 columnMajorOrder = 1;
170 }
else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER) {
171 columnMajorOrder = 0;
176 addDefinition(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &definition, &definitions);
180 if (definitions == 0) {
181 SDDS_Bomb(
"can't give a repeat specifier prior to a definition");
183 if (s_arg[i_arg].n_items != 2 ||
184 sscanf(s_arg[i_arg].list[1],
"%ld", &definition[definitions - 1].repeats) != 1 ||
185 definition[definitions - 1].repeats <= 0) {
186 SDDS_Bomb(
"invalid -repeat syntax/value");
195 if (definitions == 0) {
196 SDDS_Bomb(
"can't create a sequence prior to defining the variable");
198 addSequence(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, definition + definitions - 1);
202 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
208 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", s_arg[i_arg].list[0]);
213 if (output == NULL) {
214 output = s_arg[i_arg].list[0];
221 if (output == NULL && !(pipeFlags & USE_STDOUT)) {
229 setupOutputFile(&outputTable, output, definition, definitions, columnMajorOrder);
230 generateOutput(&outputTable, definition, definitions, doBreak);
237 for (i = 0; i < definitions; i++) {
238 free(definition[i].sequence);
239 free(definition[i].data);
247void addDefinition(
char **item,
long items,
DEFINITION **definition,
long *definitions) {
249 SDDS_Bomb(
"unable to add definition--supply column name");
251 *definition =
SDDS_Realloc(*definition,
sizeof(**definition) * (*definitions + 1));
252 if (!(*definition)) {
253 SDDS_Bomb(
"unable to add definition---allocation failure");
256 (*definition)[*definitions].columnName = item[0];
257 (*definition)[*definitions].item = item + 1;
258 (*definition)[*definitions].items = items - 1;
259 (*definition)[*definitions].sequence = NULL;
260 (*definition)[*definitions].sequences = 0;
261 (*definition)[*definitions].rows = 0;
262 (*definition)[*definitions].data = NULL;
263 (*definition)[*definitions].repeats = 1;
267void addSequence(
char **item,
long items,
DEFINITION *definition) {
271 definition->sequence =
SDDS_Realloc(definition->sequence,
sizeof(*definition->sequence) * (definition->sequences + 1));
272 if (!definition->sequence) {
273 SDDS_Bomb(
"unable to add sequence--memory allocation failure");
276 sequence = &definition->sequence[definition->sequences];
277 sequence->interval = 1;
280 "begin",
SDDS_DOUBLE, &sequence->begin, 1, SEQ_BEGIN_GIVEN,
281 "end",
SDDS_DOUBLE, &sequence->end, 1, SEQ_END_GIVEN,
282 "number",
SDDS_LONG64, &sequence->number, 1, SEQ_NUMBER_GIVEN,
283 "delta",
SDDS_DOUBLE, &sequence->delta, 1, SEQ_DELTA_GIVEN,
284 "interval",
SDDS_LONG64, &sequence->interval, 1, SEQ_INTERVAL_GIVEN,
289 if ((sequence->flags & SEQ_NUMBER_GIVEN) && sequence->number <= 0) {
290 SDDS_Bomb(
"number <= 0 is not valid for -sequence");
293 if ((sequence->flags & SEQ_DELTA_GIVEN) && sequence->delta == 0) {
294 SDDS_Bomb(
"delta == 0 is not valid for -sequence");
297 if (!(sequence->flags & SEQ_BEGIN_GIVEN)) {
298 if (definition->sequences == 0) {
299 SDDS_Bomb(
"you must give begin point for the first sequence of a definition");
301 if (!(sequence->flags & SEQ_DELTA_GIVEN)) {
302 SDDS_Bomb(
"you must give delta with implied begin point");
304 sequence->begin = definition->sequence[definition->sequences - 1].end + sequence->delta;
307 if ((sequence->flags & SEQ_INTERVAL_GIVEN) && sequence->interval <= 0) {
308 SDDS_Bomb(
"interval for sequence must be > 0");
311 if ((sequence->flags & SEQ_ENDplusDELTA) == SEQ_ENDplusDELTA) {
312 sequence->number = ((long)((sequence->end - sequence->begin) / sequence->delta + 1.5)) * sequence->interval;
313 if (sequence->number <= 0) {
314 SDDS_Bomb(
"given (start, end, delta) implies number of points <= 0");
316 }
else if ((sequence->flags & SEQ_ENDplusNUMBER) == SEQ_ENDplusNUMBER) {
317 if (sequence->number == 1) {
320 sequence->delta = (sequence->end - sequence->begin) / (sequence->number - 1) * sequence->interval;
322 }
else if ((sequence->flags & SEQ_DELTAplusNUMBER) == SEQ_DELTAplusNUMBER) {
323 sequence->end = (sequence->delta / sequence->interval) * (sequence->number - 1) + sequence->begin;
325 SDDS_Bomb(
"you must supply (end, delta), (end, number), or (delta, number)");
328 definition->data =
SDDS_Realloc(definition->data,
sizeof(*definition->data) * (definition->rows + sequence->number));
329 if (!definition->data) {
330 SDDS_Bomb(
"unable to generate sequence data--allocation failure");
333 for (i = 0; i < sequence->number; i++) {
334 definition->data[definition->rows + i] = sequence->begin + (i / sequence->interval) * sequence->delta;
337 definition->rows += sequence->number;
338 definition->sequences++;
342 long idef, row, rows = 0, totalRows = 0;
345 for (idef = 0; idef < definitions; idef++) {
346 totalRows = definition[idef].rows * definition[idef].repeats;
347 if (idef && totalRows != rows) {
348 fputs(
"warning: sequences are of different length (sddssequence)\n", stderr);
350 if (totalRows > rows) {
356 SDDS_Bomb(
"total number of points in sequence is zero");
363 for (idef = 0; idef < definitions; idef++) {
364 if (definition[idef].rows != totalRows) {
366 definition[idef].data =
SDDS_Realloc(definition[idef].data,
sizeof(*definition[idef].data) * rows);
367 if (!definition[idef].data) {
368 SDDS_Bomb(
"unable to generate output--allocation failure");
370 for (row = definition[idef].rows; row < rows; row++) {
371 definition[idef].data[row] = definition[idef].data[row % definition[idef].rows];
384 rows = definition[0].rows;
386 SDDS_Bomb(
"number of points in sequence is zero");
388 for (idef = 1; idef < definitions; idef++) {
389 if (rows != definition[idef].rows) {
390 fputs(
"warning: sequences are of different length (sddssequence)\n", stderr);
393 for (irep = 0; irep < definition[0].repeats; irep++) {
397 for (idef = 0; idef < definitions; idef++) {
409void setupOutputFile(
SDDS_DATASET *outputTable,
char *output,
DEFINITION *definition,
long definitions,
short columnMajorOrder) {
416 for (i = 0; i < definitions; i++) {
417 createColumn(outputTable, &definition[i]);
420 outputTable->layout.data_mode.column_major = columnMajorOrder;
427 char s[SDDS_MAXLINE];
431 if (!definition->columnName) {
435 SDDS_Bomb(
"column name already exists (sddssequence)");
439 snprintf(s,
sizeof(s),
"&column name=%s, ", definition->columnName);
441 for (i = 0; i < definition->items; i++) {
442 ptr = strchr(definition->item[i],
'=');
444 fprintf(stderr,
"error: invalid definition-entry: %s\n", definition->item[i]);
448 strcat(s, definition->item[i]);
455 if (!strstr(s,
", type=")) {
456 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.