86 {
88 long i, i_arg;
89 SCANNED_ARG *s_arg;
90 long tmpfile_used, noWarnings;
91 char *input, *output;
92 long ascii_output, binary_output;
93 unsigned long pipeFlags;
95 long snapshot = 0;
96 double epochtime;
97
98 long readbackNameIndex = -1, controlNameIndex = -1;
99 long timeIndex = -1, valueIndex = -1, controlNameIndexIndex = -1, previousRowIndex = -1;
100 double *timeData = NULL, *valueData = NULL, *previousRowData = NULL;
101 int32_t *controlNameIndexData = NULL;
104 long page = 0;
105 int64_t row, rows, snapshotrow = 0, initRow = 0, outrow;
106 double *rowdata = NULL;
107 long *origToNewIndex = NULL;
108 double minimumInterval = -1;
109 double timeInterval, previousTime = 0;
110 int64_t totalRows = 0, currentRows = 0;
111 short filterTime = 0;
112 double startTime = 0, endTime = MAXDOUBLE;
113 int64_t startTimeRow = 0, endTimeRow = 0;
114 unsigned long flags;
115 char **ColumnName = NULL;
116 long ColumnNames;
117 char **retain_name = NULL;
118 long retain_names = 0;
119 char **delete_name = NULL;
120 long delete_names = 0;
121
123 argc =
scanargs(&s_arg, argc, argv);
124 if (argc < 3) {
125 fprintf(stderr, "%s", USAGE);
126 exit(EXIT_FAILURE);
127 }
128 input = output = NULL;
129 ascii_output = binary_output = noWarnings = 0;
130
131 tmpfile_used = 0;
132 pipeFlags = 0;
133
134 for (i_arg = 1; i_arg < argc; i_arg++) {
135 if (s_arg[i_arg].arg_type == OPTION) {
137 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
138 case SET_BINARY:
139 binary_output = 1;
140 ascii_output = 0;
141 break;
142 case SET_ASCII:
143 ascii_output = 1;
144 binary_output = 0;
145 break;
146 case SET_FLOAT:
148 break;
149 case SET_DOUBLE:
151 break;
152 case SET_SNAPSHOT:
153 if (s_arg[i_arg].n_items < 2) {
154 fprintf(stderr, "Error: Invalid syntax for -snapshot option.\n");
155 exit(EXIT_FAILURE);
156 }
157 snapshot = 1;
158 if (sscanf(s_arg[i_arg].list[1], "%lf", &epochtime) != 1) {
159 fprintf(stderr, "Error: Invalid value for -snapshot option.\n");
160 exit(EXIT_FAILURE);
161 }
162 break;
163 case SET_PIPE:
164 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
165 fprintf(stderr, "Error: Invalid syntax for -pipe option.\n");
166 exit(EXIT_FAILURE);
167 }
168 break;
169 case SET_MININTERVAL:
170 if (s_arg[i_arg].n_items < 2) {
171 fprintf(stderr, "Error: Invalid syntax for -minimumInterval option.\n");
172 exit(EXIT_FAILURE);
173 }
174 if (sscanf(s_arg[i_arg].list[1], "%lf", &minimumInterval) != 1) {
175 fprintf(stderr, "Error: Invalid value for -minimumInterval option.\n");
176 exit(EXIT_FAILURE);
177 }
178 break;
179 case SET_TIME:
180 s_arg[i_arg].n_items -= 1;
181 filterTime = 1;
182 if (!
scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
185 fprintf(stderr, "Error: Invalid syntax for -time option.\n");
186 exit(EXIT_FAILURE);
187 }
188 s_arg[i_arg].n_items += 1;
189 break;
190 case SET_RETAIN:
191 retain_name =
trealloc(retain_name,
sizeof(*retain_name) * (retain_names + s_arg[i_arg].n_items - 1));
192 for (i = 1; i < s_arg[i_arg].n_items; i++)
193 retain_name[i - 1 + retain_names] = s_arg[i_arg].list[i];
194 retain_names += s_arg[i_arg].n_items - 1;
195 break;
196 case SET_DELETE:
197 delete_name =
trealloc(delete_name,
sizeof(*delete_name) * (delete_names + s_arg[i_arg].n_items - 1));
198 for (i = 1; i < s_arg[i_arg].n_items; i++)
199 delete_name[i - 1 + delete_names] = s_arg[i_arg].list[i];
200 delete_names += s_arg[i_arg].n_items - 1;
201 break;
202 default:
203 fprintf(stderr, "Error (%s): Unknown option: %s\n", argv[0], s_arg[i_arg].list[0]);
204 exit(EXIT_FAILURE);
205 break;
206 }
207 } else {
208 if (input == NULL)
209 input = s_arg[i_arg].list[0];
210 else if (output == NULL)
211 output = s_arg[i_arg].list[0];
212 else {
213 fprintf(stderr, "Error: Too many filenames provided.\n");
214 exit(EXIT_FAILURE);
215 }
216 }
217 }
218
219 if ((snapshot == 1) && (minimumInterval >= 0)) {
220 fprintf(stderr, "Error: -snapshot and -minimumInterval options cannot be used together.\n");
221 exit(EXIT_FAILURE);
222 }
223 if ((snapshot == 1) && (filterTime == 1)) {
224 fprintf(stderr, "Error: -snapshot and -time options cannot be used together.\n");
225 exit(EXIT_FAILURE);
226 }
227
228 processFilenames(
"sddsconvertlogonchange", &input, &output, pipeFlags, noWarnings, &tmpfile_used);
229
232 exit(EXIT_FAILURE);
233 }
234
241 if ((readbackNameIndex == -1) && (controlNameIndex == -1)) {
242 fprintf(stderr, "Error: Both ReadbackName and ControlName arrays are missing from the input file.\n");
243 exit(EXIT_FAILURE);
244 }
245 if (timeIndex == -1) {
246 fprintf(stderr, "Error: Time column is missing.\n");
247 exit(EXIT_FAILURE);
248 }
249 if (valueIndex == -1) {
250 fprintf(stderr, "Error: Value column is missing.\n");
251 exit(EXIT_FAILURE);
252 }
253 if (controlNameIndexIndex == -1) {
254 fprintf(stderr, "Error: ControlNameIndex column is missing.\n");
255 exit(EXIT_FAILURE);
256 }
257
258 if (!
SDDS_InitializeOutput(&SDDS_output, ascii_output ? SDDS_ASCII : (binary_output ? SDDS_BINARY : SDDS_input.layout.data_mode.mode), 1, NULL, NULL, output)) {
260 exit(EXIT_FAILURE);
261 }
262
263 outrow = 0;
264 while (SDDS_ReadTable(&SDDS_input) > 0) {
265 page++;
266 rows = SDDS_RowCount(&SDDS_input);
267 if (page == 1) {
268 if (readbackNameIndex != -1) {
269 readbackNameArray =
SDDS_GetArray(&SDDS_input,
"ReadbackName", NULL);
270 } else {
271 readbackNameArray =
SDDS_GetArray(&SDDS_input,
"ControlName", NULL);
272 }
273 if (readbackNameArray == NULL) {
275 exit(EXIT_FAILURE);
276 }
277
278 origToNewIndex = malloc(sizeof(long) * readbackNameArray->elements);
279 for (i = 0; i < readbackNameArray->elements; i++) {
280 origToNewIndex[i] = -1;
281 }
282
283 ColumnName = process_name_options(((char **)readbackNameArray->data), readbackNameArray->elements, delete_name, delete_names, retain_name, retain_names, &ColumnNames, &origToNewIndex);
284 rowdata = malloc(sizeof(double) * ColumnNames);
285 for (i = 0; i < ColumnNames; i++) {
286 rowdata[i] = 0;
287 }
288
291 exit(EXIT_FAILURE);
292 }
295 exit(EXIT_FAILURE);
296 }
299 exit(EXIT_FAILURE);
300 }
301 if (snapshot) {
302 if (SDDS_StartTable(&SDDS_output, 1) == 0) {
304 exit(EXIT_FAILURE);
305 }
306 } else {
307 if (SDDS_StartTable(&SDDS_output, 100) == 0) {
309 exit(EXIT_FAILURE);
310 }
311 totalRows = 100;
312 }
313 } else {
314 if (readbackNameIndex != -1) {
315 readbackNameArray2 =
SDDS_GetArray(&SDDS_input,
"ReadbackName", NULL);
316 } else {
317 readbackNameArray2 =
SDDS_GetArray(&SDDS_input,
"ControlName", NULL);
318 }
319 if (readbackNameArray2 == NULL) {
321 exit(EXIT_FAILURE);
322 }
323 if (readbackNameArray->elements != readbackNameArray2->elements) {
324 fprintf(stderr, "Error: Multiple pages with differing ReadbackName and/or ControlName columns cannot be processed.\n");
325 exit(EXIT_FAILURE);
326 }
327 for (i = 0; i < readbackNameArray->elements; i++) {
328 if (strcmp((char *)((char **)readbackNameArray->data)[i], (char *)((char **)readbackNameArray2->data)[i]) != 0) {
329 fprintf(stderr, "Error: Multiple pages with differing ReadbackName and/or ControlName columns cannot be processed.\n");
330 exit(EXIT_FAILURE);
331 }
332 }
334 }
337 exit(EXIT_FAILURE);
338 }
341 exit(EXIT_FAILURE);
342 }
345 exit(EXIT_FAILURE);
346 }
347 if (snapshot) {
348 snapshotrow = 0;
349 for (row = 0; row < rows; row++) {
350 if (timeData[row] <= epochtime) {
351 snapshotrow = row;
352 } else {
353 break;
354 }
355 }
356 }
357 if (filterTime) {
358 for (row = 0; row < rows; row++) {
359 if (timeData[row] <= startTime) {
360 startTimeRow = row;
361 } else {
362 break;
363 }
364 }
365 for (row = 0; row < rows; row++) {
366 if (timeData[row] <= endTime) {
367 endTimeRow = row;
368 } else {
369 break;
370 }
371 }
372 }
373 if (previousRowIndex != -1) {
376 exit(EXIT_FAILURE);
377 }
378 for (row = rows - 1; row >= 0; row--) {
379 if (previousRowData[row] == -2) {
380 if (origToNewIndex[controlNameIndexData[row]] == -1) {
381 continue;
382 }
383 initRow = row;
384 break;
385 }
386 }
387 free(previousRowData);
388 }
389
390 if (minimumInterval > 0) {
391 previousTime = timeData[0] - minimumInterval - 1;
392 }
393 for (row = 0; row < rows; row++) {
394 if ((readbackNameArray->elements < controlNameIndexData[row]) ||
395 (controlNameIndexData[row] < 0)) {
396
397 continue;
398 }
399 if (origToNewIndex[controlNameIndexData[row]] == -1) {
400 continue;
401 }
402 rowdata[origToNewIndex[controlNameIndexData[row]]] = valueData[row];
403 if (previousRowIndex != -1) {
404 if (row < initRow) {
405 continue;
406 }
407 }
408 if (((snapshot == 0) && (filterTime == 0)) ||
409 ((snapshot == 1) && (row == snapshotrow)) ||
410 ((filterTime == 1) && (row >= startTimeRow) && (row <= endTimeRow))) {
411 if (minimumInterval > 0) {
412 timeInterval = timeData[row] - previousTime;
413 if (timeInterval <= minimumInterval) {
414 continue;
415 } else {
416 previousTime = timeData[row];
417 }
418 }
419 if ((snapshot == 0) && (totalRows == currentRows)) {
422 exit(EXIT_FAILURE);
423 }
424 totalRows += 100;
425 }
426 currentRows++;
427 if (SDDS_SetRowValuesMod(&SDDS_output, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, outrow, 0, &timeData[row], -1) == 0) {
429 exit(EXIT_FAILURE);
430 }
431 for (i = 0; i < ColumnNames; i++) {
432 if (SDDS_SetRowValuesMod(&SDDS_output, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, outrow, i + 1, &rowdata[i], -1) == 0) {
434 exit(EXIT_FAILURE);
435 }
436 }
437 if (snapshot)
438 break;
439 outrow++;
440 }
441 }
442 if (timeData)
443 free(timeData);
444 if (valueData)
445 free(valueData);
446 if (controlNameIndexData)
447 free(controlNameIndexData);
448 }
449 if (rowdata)
450 free(rowdata);
451 if (origToNewIndex)
452 free(origToNewIndex);
453
454 if (ColumnName) {
455 for (i = 0; i < ColumnNames; i++) {
456 if (ColumnName[i])
457 free(ColumnName[i]);
458 }
459 free(ColumnName);
460 }
461
463 if (SDDS_WriteTable(&SDDS_output) == 0) {
465 exit(EXIT_FAILURE);
466 }
467
470 exit(EXIT_FAILURE);
471 }
472
474 exit(EXIT_FAILURE);
475
477 return EXIT_SUCCESS;
478}
int32_t SDDS_LengthenTable(SDDS_DATASET *SDDS_dataset, int64_t n_additional_rows)
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_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_DefineSimpleColumns(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type)
Defines multiple simple data columns of the same data type within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_FreeArray(SDDS_ARRAY *array)
Frees memory allocated for an SDDS array structure.
int32_t SDDS_VerifyArrayExists(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Verifies the existence of an array in the SDDS dataset based on specified criteria.
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_VerifyColumnExists(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Verifies the existence of a column in the SDDS dataset based on specified criteria.
#define SDDS_FLOAT
Identifier for the float data type.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_DOUBLE
Identifier for the double data type.
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
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.