98 {
100 long i, i_arg;
101 SCANNED_ARG *s_arg;
102 long tmpfile_used, noWarnings;
103 char *input, *output;
104 long ascii_output, binary_output;
105 unsigned long pipeFlags;
107 long snapshot = 0;
108 double epochtime;
109
110 long readbackNameIndex = -1, controlNameIndex = -1;
111 long timeIndex = -1, valueIndex = -1, controlNameIndexIndex = -1, previousRowIndex = -1;
112 double *timeData = NULL, *valueData = NULL, *previousRowData = NULL;
113 int32_t *controlNameIndexData = NULL;
116 long page = 0;
117 int64_t row, rows, snapshotrow = 0, initRow = 0, outrow;
118 double *rowdata = NULL;
119 long *origToNewIndex = NULL;
120 double minimumInterval = -1;
121 double timeInterval, previousTime = 0;
122 int64_t totalRows = 0, currentRows = 0;
123 short filterTime = 0;
124 double startTime = 0, endTime = MAXDOUBLE;
125 int64_t startTimeRow = 0, endTimeRow = 0;
126 unsigned long flags;
127 char **ColumnName = NULL;
128 long ColumnNames;
129 char **retain_name = NULL;
130 long retain_names = 0;
131 char **delete_name = NULL;
132 long delete_names = 0;
133
135 argc =
scanargs(&s_arg, argc, argv);
136 if (argc < 3) {
137 fprintf(stderr, "%s", USAGE);
138 exit(EXIT_FAILURE);
139 }
140 input = output = NULL;
141 ascii_output = binary_output = noWarnings = 0;
142
143 tmpfile_used = 0;
144 pipeFlags = 0;
145
146 for (i_arg = 1; i_arg < argc; i_arg++) {
147 if (s_arg[i_arg].arg_type == OPTION) {
149 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
150 case SET_BINARY:
151 binary_output = 1;
152 ascii_output = 0;
153 break;
154 case SET_ASCII:
155 ascii_output = 1;
156 binary_output = 0;
157 break;
158 case SET_FLOAT:
160 break;
161 case SET_DOUBLE:
163 break;
164 case SET_SNAPSHOT:
165 if (s_arg[i_arg].n_items < 2) {
166 fprintf(stderr, "invalid -snapshot syntax\n");
167 exit(EXIT_FAILURE);
168 }
169 snapshot = 1;
170 if (sscanf(s_arg[i_arg].list[1], "%lf", &epochtime) != 1) {
171 fprintf(stderr, "invalid -snapshot syntax or value\n");
172 exit(EXIT_FAILURE);
173 }
174 break;
175 case SET_PIPE:
176 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
177 fprintf(stderr, "invalid -pipe syntax\n");
178 exit(EXIT_FAILURE);
179 }
180 break;
181 case SET_MININTERVAL:
182 if (s_arg[i_arg].n_items < 2) {
183 fprintf(stderr, "invalid -minimumInterval syntax\n");
184 exit(EXIT_FAILURE);
185 }
186 if (sscanf(s_arg[i_arg].list[1], "%lf", &minimumInterval) != 1) {
187 fprintf(stderr, "invalid -minimumInterval syntax or value\n");
188 exit(EXIT_FAILURE);
189 }
190 break;
191 case SET_TIME:
192 s_arg[i_arg].n_items -= 1;
193 filterTime = 1;
194 if (!
scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
197 fprintf(stderr, "invalid -time syntax\n");
198 exit(EXIT_FAILURE);
199 }
200 s_arg[i_arg].n_items += 1;
201 break;
202 case SET_RETAIN:
203 retain_name =
trealloc(retain_name,
sizeof(*retain_name) * (retain_names + s_arg[i_arg].n_items - 1));
204 for (i = 1; i < s_arg[i_arg].n_items; i++)
205 retain_name[i - 1 + retain_names] = s_arg[i_arg].list[i];
206 retain_names += s_arg[i_arg].n_items - 1;
207 break;
208 case SET_DELETE:
209 delete_name =
trealloc(delete_name,
sizeof(*delete_name) * (delete_names + s_arg[i_arg].n_items - 1));
210 for (i = 1; i < s_arg[i_arg].n_items; i++)
211 delete_name[i - 1 + delete_names] = s_arg[i_arg].list[i];
212 delete_names += s_arg[i_arg].n_items - 1;
213 break;
214 default:
215 fprintf(stderr, "Error (%s): unknown switch: %s\n", argv[0], s_arg[i_arg].list[0]);
216 exit(EXIT_FAILURE);
217 break;
218 }
219 } else {
220 if (input == NULL)
221 input = s_arg[i_arg].list[0];
222 else if (output == NULL)
223 output = s_arg[i_arg].list[0];
224 else {
225 fprintf(stderr, "too many filenames\n");
226 exit(EXIT_FAILURE);
227 }
228 }
229 }
230
231 if ((snapshot == 1) && (minimumInterval >= 0)) {
232 fprintf(stderr, "-snapshot and -minimumInterval options cannot be used together\n");
233 exit(EXIT_FAILURE);
234 }
235 if ((snapshot == 1) && (filterTime == 1)) {
236 fprintf(stderr, "-snapshot and -time options cannot be used together\n");
237 exit(EXIT_FAILURE);
238 }
239
240 processFilenames(
"sddsconvertalarmlog", &input, &output, pipeFlags, noWarnings, &tmpfile_used);
241
244 exit(EXIT_FAILURE);
245 }
246
253 if ((readbackNameIndex == -1) && (controlNameIndex == -1)) {
254 fprintf(stderr, "Error: ReadbackName and ControlName arrays are both missing from the input file.\n");
255 exit(EXIT_FAILURE);
256 }
257 if (timeIndex == -1) {
258 fprintf(stderr, "Error: Time column is missing\n");
259 exit(EXIT_FAILURE);
260 }
261 if (valueIndex == -1) {
262 fprintf(stderr, "Error: Value column is missing\n");
263 exit(EXIT_FAILURE);
264 }
265 if (controlNameIndexIndex == -1) {
266 fprintf(stderr, "Error: ControlNameIndex column is missing\n");
267 exit(EXIT_FAILURE);
268 }
269
270 if (!
SDDS_InitializeOutput(&SDDS_output, ascii_output ? SDDS_ASCII : (binary_output ? SDDS_BINARY : SDDS_input.layout.data_mode.mode), 1, NULL, NULL, output)) {
272 exit(EXIT_FAILURE);
273 }
274
275 outrow = 0;
276 while (SDDS_ReadTable(&SDDS_input) > 0) {
277 page++;
278 rows = SDDS_RowCount(&SDDS_input);
279 if (page == 1) {
280 if (readbackNameIndex != -1) {
281 readbackNameArray =
SDDS_GetArray(&SDDS_input,
"ReadbackName", NULL);
282 } else {
283 readbackNameArray =
SDDS_GetArray(&SDDS_input,
"ControlName", NULL);
284 }
285 if (readbackNameArray == NULL) {
287 exit(EXIT_FAILURE);
288 }
289
290 origToNewIndex = malloc(sizeof(long) * readbackNameArray->elements);
291 for (i = 0; i < readbackNameArray->elements; i++) {
292 origToNewIndex[i] = -1;
293 }
294
295 ColumnName = process_name_options(((char **)readbackNameArray->data), readbackNameArray->elements, delete_name, delete_names, retain_name, retain_names, &ColumnNames, &origToNewIndex);
296 rowdata = malloc(sizeof(double) * ColumnNames);
297 for (i = 0; i < ColumnNames; i++) {
298 rowdata[i] = 0;
299 }
300
303 exit(EXIT_FAILURE);
304 }
307 exit(EXIT_FAILURE);
308 }
311 exit(EXIT_FAILURE);
312 }
313 if (snapshot) {
314 if (SDDS_StartTable(&SDDS_output, 1) == 0) {
316 exit(EXIT_FAILURE);
317 }
318 } else {
319 if (SDDS_StartTable(&SDDS_output, 100) == 0) {
321 exit(EXIT_FAILURE);
322 }
323 totalRows = 100;
324 }
325 } else {
326 if (readbackNameIndex != -1) {
327 readbackNameArray2 =
SDDS_GetArray(&SDDS_input,
"ReadbackName", NULL);
328 } else {
329 readbackNameArray2 =
SDDS_GetArray(&SDDS_input,
"ControlName", NULL);
330 }
331 if (readbackNameArray2 == NULL) {
333 exit(EXIT_FAILURE);
334 }
335 if (readbackNameArray->elements != readbackNameArray2->elements) {
336 fprintf(stderr, "Error: Unable to process multiple pages with different ReadbackName and/or ControlName columns\n");
337 exit(EXIT_FAILURE);
338 }
339 for (i = 0; i < readbackNameArray->elements; i++) {
340 if (strcmp((char *)((char **)readbackNameArray->data)[i], (char *)((char **)readbackNameArray2->data)[i]) != 0) {
341 fprintf(stderr, "Error: Unable to process multiple pages with different ReadbackName and/or ControlName columns\n");
342 exit(EXIT_FAILURE);
343 }
344 }
346 }
349 exit(EXIT_FAILURE);
350 }
353 exit(EXIT_FAILURE);
354 }
357 exit(EXIT_FAILURE);
358 }
359 if (snapshot) {
360 snapshotrow = 0;
361 for (row = 0; row < rows; row++) {
362 if (timeData[row] <= epochtime) {
363 snapshotrow = row;
364 } else {
365 break;
366 }
367 }
368 }
369 if (filterTime) {
370 for (row = 0; row < rows; row++) {
371 if (timeData[row] <= startTime) {
372 startTimeRow = row;
373 } else {
374 break;
375 }
376 }
377 for (row = 0; row < rows; row++) {
378 if (timeData[row] <= endTime) {
379 endTimeRow = row;
380 } else {
381 break;
382 }
383 }
384 }
385 if (previousRowIndex != -1) {
388 exit(EXIT_FAILURE);
389 }
390 for (row = rows - 1; row >= 0; row--) {
391 if (previousRowData[row] == -2) {
392 if (origToNewIndex[controlNameIndexData[row]] == -1) {
393 continue;
394 }
395 initRow = row;
396 break;
397 }
398 }
399 free(previousRowData);
400 }
401
402 if (minimumInterval > 0) {
403 previousTime = timeData[0] - minimumInterval - 1;
404 }
405 for (row = 0; row < rows; row++) {
406 if ((readbackNameArray->elements < controlNameIndexData[row]) ||
407 (controlNameIndexData[row] < 0)) {
408
409 continue;
410 }
411 if (origToNewIndex[controlNameIndexData[row]] == -1) {
412 continue;
413 }
414 rowdata[origToNewIndex[controlNameIndexData[row]]] = valueData[row];
415 if (previousRowIndex != -1) {
416 if (row < initRow) {
417 continue;
418 }
419 }
420 if (((snapshot == 0) && (filterTime == 0)) ||
421 ((snapshot == 1) && (row == snapshotrow)) ||
422 ((filterTime == 1) && (row >= startTimeRow) && (row <= endTimeRow))) {
423 if (minimumInterval > 0) {
424 timeInterval = timeData[row] - previousTime;
425 if (timeInterval <= minimumInterval) {
426 continue;
427 } else {
428 previousTime = timeData[row];
429 }
430 }
431 if ((snapshot == 0) && (totalRows == currentRows)) {
434 exit(EXIT_FAILURE);
435 }
436 totalRows += 100;
437 }
438 currentRows++;
439 if (SDDS_SetRowValuesMod(&SDDS_output, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, outrow, 0, &timeData[row], -1) == 0) {
441 exit(EXIT_FAILURE);
442 }
443 for (i = 0; i < ColumnNames; i++) {
444 if (SDDS_SetRowValuesMod(&SDDS_output, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, outrow, i + 1, &rowdata[i], -1) == 0) {
446 exit(EXIT_FAILURE);
447 }
448 }
449 if (snapshot)
450 break;
451 outrow++;
452 }
453 }
454 if (timeData)
455 free(timeData);
456 if (valueData)
457 free(valueData);
458 if (controlNameIndexData)
459 free(controlNameIndexData);
460 }
461 if (rowdata)
462 free(rowdata);
463 if (origToNewIndex)
464 free(origToNewIndex);
465
466 if (ColumnName) {
467 for (i = 0; i < ColumnNames; i++) {
468 if (ColumnName[i])
469 free(ColumnName[i]);
470 }
471 free(ColumnName);
472 }
473
475 if (SDDS_WriteTable(&SDDS_output) == 0) {
477 exit(EXIT_FAILURE);
478 }
479
482 exit(EXIT_FAILURE);
483 }
484
486 exit(EXIT_FAILURE);
487
489 return EXIT_SUCCESS;
490}
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.