124 {
126 long i, i_arg;
127 SCANNED_ARG *s_arg;
128 long tmpfile_used, noWarnings;
129 char *input, *output;
130 long ascii_output, binary_output;
131 unsigned long pipeFlags;
133 long snapshot = 0;
134 double epochtime;
135
136 long readbackNameIndex = -1, controlNameIndex = -1;
137 long timeIndex = -1, valueIndex = -1, controlNameIndexIndex = -1, previousRowIndex = -1;
138 double *timeData = NULL, *valueData = NULL, *previousRowData = NULL;
139 int32_t *controlNameIndexData = NULL;
142 long page = 0;
143 int64_t row, rows, snapshotrow = 0, initRow = 0, outrow;
144 double *rowdata = NULL;
145 long *origToNewIndex = NULL;
146 double minimumInterval = -1;
147 double timeInterval, previousTime = 0;
148 int64_t totalRows = 0, currentRows = 0;
149 short filterTime = 0;
150 double startTime = 0, endTime = MAXDOUBLE;
151 int64_t startTimeRow = 0, endTimeRow = 0;
152 unsigned long flags;
153 char **ColumnName = NULL;
154 long ColumnNames;
155 char **retain_name = NULL;
156 long retain_names = 0;
157 char **delete_name = NULL;
158 long delete_names = 0;
159
161 argc =
scanargs(&s_arg, argc, argv);
162 if (argc < 3) {
163 fprintf(stderr, "%s", USAGE);
164 exit(EXIT_FAILURE);
165 }
166 input = output = NULL;
167 ascii_output = binary_output = noWarnings = 0;
168
169 tmpfile_used = 0;
170 pipeFlags = 0;
171
172 for (i_arg = 1; i_arg < argc; i_arg++) {
173 if (s_arg[i_arg].arg_type == OPTION) {
175 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
176 case SET_BINARY:
177 binary_output = 1;
178 ascii_output = 0;
179 break;
180 case SET_ASCII:
181 ascii_output = 1;
182 binary_output = 0;
183 break;
184 case SET_FLOAT:
186 break;
187 case SET_DOUBLE:
189 break;
190 case SET_SNAPSHOT:
191 if (s_arg[i_arg].n_items < 2) {
192 fprintf(stderr, "invalid -snapshot syntax\n");
193 exit(EXIT_FAILURE);
194 }
195 snapshot = 1;
196 if (sscanf(s_arg[i_arg].list[1], "%lf", &epochtime) != 1) {
197 fprintf(stderr, "invalid -snapshot syntax or value\n");
198 exit(EXIT_FAILURE);
199 }
200 break;
201 case SET_PIPE:
202 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
203 fprintf(stderr, "invalid -pipe syntax\n");
204 exit(EXIT_FAILURE);
205 }
206 break;
207 case SET_MININTERVAL:
208 if (s_arg[i_arg].n_items < 2) {
209 fprintf(stderr, "invalid -minimumInterval syntax\n");
210 exit(EXIT_FAILURE);
211 }
212 if (sscanf(s_arg[i_arg].list[1], "%lf", &minimumInterval) != 1) {
213 fprintf(stderr, "invalid -minimumInterval syntax or value\n");
214 exit(EXIT_FAILURE);
215 }
216 break;
217 case SET_TIME:
218 s_arg[i_arg].n_items -= 1;
219 filterTime = 1;
220 if (!
scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
223 fprintf(stderr, "invalid -time syntax\n");
224 exit(EXIT_FAILURE);
225 }
226 s_arg[i_arg].n_items += 1;
227 break;
228 case SET_RETAIN:
229 retain_name =
trealloc(retain_name,
sizeof(*retain_name) * (retain_names + s_arg[i_arg].n_items - 1));
230 for (i = 1; i < s_arg[i_arg].n_items; i++)
231 retain_name[i - 1 + retain_names] = s_arg[i_arg].list[i];
232 retain_names += s_arg[i_arg].n_items - 1;
233 break;
234 case SET_DELETE:
235 delete_name =
trealloc(delete_name,
sizeof(*delete_name) * (delete_names + s_arg[i_arg].n_items - 1));
236 for (i = 1; i < s_arg[i_arg].n_items; i++)
237 delete_name[i - 1 + delete_names] = s_arg[i_arg].list[i];
238 delete_names += s_arg[i_arg].n_items - 1;
239 break;
240 default:
241 fprintf(stderr, "Error (%s): unknown switch: %s\n", argv[0], s_arg[i_arg].list[0]);
242 exit(EXIT_FAILURE);
243 break;
244 }
245 } else {
246 if (input == NULL)
247 input = s_arg[i_arg].list[0];
248 else if (output == NULL)
249 output = s_arg[i_arg].list[0];
250 else {
251 fprintf(stderr, "too many filenames\n");
252 exit(EXIT_FAILURE);
253 }
254 }
255 }
256
257 if ((snapshot == 1) && (minimumInterval >= 0)) {
258 fprintf(stderr, "-snapshot and -minimumInterval options cannot be used together\n");
259 exit(EXIT_FAILURE);
260 }
261 if ((snapshot == 1) && (filterTime == 1)) {
262 fprintf(stderr, "-snapshot and -time options cannot be used together\n");
263 exit(EXIT_FAILURE);
264 }
265
266 processFilenames(
"sddsconvertalarmlog", &input, &output, pipeFlags, noWarnings, &tmpfile_used);
267
270 exit(EXIT_FAILURE);
271 }
272
279 if ((readbackNameIndex == -1) && (controlNameIndex == -1)) {
280 fprintf(stderr, "Error: ReadbackName and ControlName arrays are both missing from the input file.\n");
281 exit(EXIT_FAILURE);
282 }
283 if (timeIndex == -1) {
284 fprintf(stderr, "Error: Time column is missing\n");
285 exit(EXIT_FAILURE);
286 }
287 if (valueIndex == -1) {
288 fprintf(stderr, "Error: Value column is missing\n");
289 exit(EXIT_FAILURE);
290 }
291 if (controlNameIndexIndex == -1) {
292 fprintf(stderr, "Error: ControlNameIndex column is missing\n");
293 exit(EXIT_FAILURE);
294 }
295
296 if (!
SDDS_InitializeOutput(&SDDS_output, ascii_output ? SDDS_ASCII : (binary_output ? SDDS_BINARY : SDDS_input.layout.data_mode.mode), 1, NULL, NULL, output)) {
298 exit(EXIT_FAILURE);
299 }
300
301 outrow = 0;
302 while (SDDS_ReadTable(&SDDS_input) > 0) {
303 page++;
304 rows = SDDS_RowCount(&SDDS_input);
305 if (page == 1) {
306 if (readbackNameIndex != -1) {
307 readbackNameArray =
SDDS_GetArray(&SDDS_input,
"ReadbackName", NULL);
308 } else {
309 readbackNameArray =
SDDS_GetArray(&SDDS_input,
"ControlName", NULL);
310 }
311 if (readbackNameArray == NULL) {
313 exit(EXIT_FAILURE);
314 }
315
316 origToNewIndex = malloc(sizeof(long) * readbackNameArray->elements);
317 for (i = 0; i < readbackNameArray->elements; i++) {
318 origToNewIndex[i] = -1;
319 }
320
321 ColumnName = process_name_options(((char **)readbackNameArray->data), readbackNameArray->elements, delete_name, delete_names, retain_name, retain_names, &ColumnNames, &origToNewIndex);
322 rowdata = malloc(sizeof(double) * ColumnNames);
323 for (i = 0; i < ColumnNames; i++) {
324 rowdata[i] = 0;
325 }
326
329 exit(EXIT_FAILURE);
330 }
333 exit(EXIT_FAILURE);
334 }
337 exit(EXIT_FAILURE);
338 }
339 if (snapshot) {
340 if (SDDS_StartTable(&SDDS_output, 1) == 0) {
342 exit(EXIT_FAILURE);
343 }
344 } else {
345 if (SDDS_StartTable(&SDDS_output, 100) == 0) {
347 exit(EXIT_FAILURE);
348 }
349 totalRows = 100;
350 }
351 } else {
352 if (readbackNameIndex != -1) {
353 readbackNameArray2 =
SDDS_GetArray(&SDDS_input,
"ReadbackName", NULL);
354 } else {
355 readbackNameArray2 =
SDDS_GetArray(&SDDS_input,
"ControlName", NULL);
356 }
357 if (readbackNameArray2 == NULL) {
359 exit(EXIT_FAILURE);
360 }
361 if (readbackNameArray->elements != readbackNameArray2->elements) {
362 fprintf(stderr, "Error: Unable to process multiple pages with different ReadbackName and/or ControlName columns\n");
363 exit(EXIT_FAILURE);
364 }
365 for (i = 0; i < readbackNameArray->elements; i++) {
366 if (strcmp((char *)((char **)readbackNameArray->data)[i], (char *)((char **)readbackNameArray2->data)[i]) != 0) {
367 fprintf(stderr, "Error: Unable to process multiple pages with different ReadbackName and/or ControlName columns\n");
368 exit(EXIT_FAILURE);
369 }
370 }
372 }
375 exit(EXIT_FAILURE);
376 }
379 exit(EXIT_FAILURE);
380 }
383 exit(EXIT_FAILURE);
384 }
385 if (snapshot) {
386 snapshotrow = 0;
387 for (row = 0; row < rows; row++) {
388 if (timeData[row] <= epochtime) {
389 snapshotrow = row;
390 } else {
391 break;
392 }
393 }
394 }
395 if (filterTime) {
396 for (row = 0; row < rows; row++) {
397 if (timeData[row] <= startTime) {
398 startTimeRow = row;
399 } else {
400 break;
401 }
402 }
403 for (row = 0; row < rows; row++) {
404 if (timeData[row] <= endTime) {
405 endTimeRow = row;
406 } else {
407 break;
408 }
409 }
410 }
411 if (previousRowIndex != -1) {
414 exit(EXIT_FAILURE);
415 }
416 for (row = rows - 1; row >= 0; row--) {
417 if (previousRowData[row] == -2) {
418 if (origToNewIndex[controlNameIndexData[row]] == -1) {
419 continue;
420 }
421 initRow = row;
422 break;
423 }
424 }
425 free(previousRowData);
426 }
427
428 if (minimumInterval > 0) {
429 previousTime = timeData[0] - minimumInterval - 1;
430 }
431 for (row = 0; row < rows; row++) {
432 if ((readbackNameArray->elements < controlNameIndexData[row]) ||
433 (controlNameIndexData[row] < 0)) {
434
435 continue;
436 }
437 if (origToNewIndex[controlNameIndexData[row]] == -1) {
438 continue;
439 }
440 rowdata[origToNewIndex[controlNameIndexData[row]]] = valueData[row];
441 if (previousRowIndex != -1) {
442 if (row < initRow) {
443 continue;
444 }
445 }
446 if (((snapshot == 0) && (filterTime == 0)) ||
447 ((snapshot == 1) && (row == snapshotrow)) ||
448 ((filterTime == 1) && (row >= startTimeRow) && (row <= endTimeRow))) {
449 if (minimumInterval > 0) {
450 timeInterval = timeData[row] - previousTime;
451 if (timeInterval <= minimumInterval) {
452 continue;
453 } else {
454 previousTime = timeData[row];
455 }
456 }
457 if ((snapshot == 0) && (totalRows == currentRows)) {
460 exit(EXIT_FAILURE);
461 }
462 totalRows += 100;
463 }
464 currentRows++;
465 if (SDDS_SetRowValuesMod(&SDDS_output, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, outrow, 0, &timeData[row], -1) == 0) {
467 exit(EXIT_FAILURE);
468 }
469 for (i = 0; i < ColumnNames; i++) {
470 if (SDDS_SetRowValuesMod(&SDDS_output, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, outrow, i + 1, &rowdata[i], -1) == 0) {
472 exit(EXIT_FAILURE);
473 }
474 }
475 if (snapshot)
476 break;
477 outrow++;
478 }
479 }
480 if (timeData)
481 free(timeData);
482 if (valueData)
483 free(valueData);
484 if (controlNameIndexData)
485 free(controlNameIndexData);
486 }
487 if (rowdata)
488 free(rowdata);
489 if (origToNewIndex)
490 free(origToNewIndex);
491
492 if (ColumnName) {
493 for (i = 0; i < ColumnNames; i++) {
494 if (ColumnName[i])
495 free(ColumnName[i]);
496 }
497 free(ColumnName);
498 }
499
501 if (SDDS_WriteTable(&SDDS_output) == 0) {
503 exit(EXIT_FAILURE);
504 }
505
508 exit(EXIT_FAILURE);
509 }
510
512 exit(EXIT_FAILURE);
513
515 return EXIT_SUCCESS;
516}
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.