148 {
149 int32_t beginRange, endRange, rangeInterval, rampSteps;
150 long dryRun;
151 long PVs, j, i_arg, numerical, iramp;
152 unsigned long blunderAhead;
155 unsigned long flags, dummyFlags;
156 SCANNED_ARG *s_arg;
157 char *ptr, *rangeFormat;
158 double pendIOTime;
159 chid *channelID = NULL;
160 short deltaMode, doRamp, charArray=0;
161 double *presentValue, deltaFactor, rampPause;
162 long providerMode = 0;
163#if (EPICS_VERSION > 3)
165 double *rampDeltas = NULL;
166#endif
167
168 argc =
scanargs(&s_arg, argc, argv);
169 if (argc < 2)
171
172 PVvalue = NULL;
173 presentValue = NULL;
174 List = NULL;
175 PVs = dryRun = 0;
176 pendIOTime = 1.0;
177 deltaMode = numerical = 0;
178 deltaFactor = 1;
179 blunderAhead = 0;
180 rampSteps = 1;
181 rampPause = 0.1;
182 doRamp = 0;
183
184 for (i_arg = 1; i_arg < argc; i_arg++) {
185 if (s_arg[i_arg].arg_type == OPTION) {
187 switch (
match_string(s_arg[i_arg].list[0], commandline_option, COMMANDLINE_OPTIONS, 0)) {
188 case CLO_LIST:
189 if (s_arg[i_arg].n_items < 2)
190 SDDS_Bomb((
char *)
"invalid -list syntax (cavput)");
192 for (j = 1; j < s_arg[i_arg].n_items; j++) {
193 List[j - 1].flags = 0;
194 if ((ptr = strchr(s_arg[i_arg].list[j], '=')))
195 *ptr++ = 0;
196 List[j - 1].string = s_arg[i_arg].list[j];
197 if (ptr) {
198 List[j - 1].flags |= VALUE_GIVEN;
199 List[j - 1].value = ptr;
200 }
201 }
202 multiplyWithList(&PVvalue, &PVs, List, s_arg[i_arg].n_items - 1);
203 break;
204 case CLO_RANGE:
205 s_arg[i_arg].n_items--;
206 rangeFormat = NULL;
207 rangeInterval = 1;
208 if (!
scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
209 "begin",
SDDS_LONG, &beginRange, 1, BEGIN_GIVEN,
210 "end",
SDDS_LONG, &endRange, 1, END_GIVEN,
211 "interval",
SDDS_LONG, &rangeInterval, 1, INTERVAL_GIVEN,
212 "format",
SDDS_STRING, &rangeFormat, 1, FORMAT_GIVEN,
213 NULL) ||
214 !(flags & BEGIN_GIVEN) || !(flags & END_GIVEN) || beginRange > endRange ||
216 SDDS_Bomb((
char *)
"invalid -range syntax/values");
217 if (!rangeFormat)
218 rangeFormat = (char *)"%ld";
219 multiplyWithRange(&PVvalue, &PVs, beginRange, endRange, rangeInterval, rangeFormat);
220 s_arg[i_arg].n_items++;
221 break;
222 case CLO_PENDIOTIME:
223 if (s_arg[i_arg].n_items != 2)
224 bomb((
char *)
"wrong number of items for -pendIoTime", NULL);
225 if (sscanf(s_arg[i_arg].list[1], "%lf", &pendIOTime) != 1 ||
226 pendIOTime <= 0)
227 SDDS_Bomb((
char *)
"invalid -pendIoTime value (cavget)");
228 break;
229 case CLO_DRYRUN:
230 dryRun = 1;
231 break;
232 case CLO_EZCATIMING:
233 fprintf(stderr, "warning (cavput): -ezcaTiming option is obsolete. Use -pendIoTime\n");
234 break;
235 case CLO_NOGROUPS:
236 fprintf(stderr, "warning (cavput): -noGroups option is obsolete.\n");
237 break;
238 case CLO_DELTAMODE:
239 deltaMode = 1;
240 s_arg[i_arg].n_items--;
241 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
243 NULL))
244 SDDS_Bomb((
char *)
"invalid -deltaMode syntax/values");
245 s_arg[i_arg].n_items++;
246 break;
247 case CLO_NUMERICAL:
248 numerical = 1;
249 break;
250 case CLO_CHARARRAY:
251 charArray = 1;
252 break;
253 case CLO_BLUNDERAHEAD:
254 s_arg[i_arg].n_items--;
255 if (!
scanItemList(&blunderAhead, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
256 "silently", -1, NULL, 0, BLUNDER_SILENTLY,
257 NULL))
258 SDDS_Bomb((
char *)
"invalid -blunderAhead syntax/values");
259 blunderAhead |= DO_BLUNDERAHEAD;
260 s_arg[i_arg].n_items++;
261 break;
262 case CLO_RAMP:
263 s_arg[i_arg].n_items--;
264 rangeFormat = NULL;
265 rangeInterval = 1;
266 if (!
scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
269 (rampSteps <= 1) || (rampPause < 0))
270 SDDS_Bomb((
char *)
"invalid -ramp syntax/values");
271 doRamp = 1;
272 s_arg[i_arg].n_items++;
273 break;
274 case CLO_PROVIDER:
275 if (s_arg[i_arg].n_items != 2)
276 SDDS_Bomb((
char *)
"no value given for option -provider");
277 if ((providerMode =
match_string(s_arg[i_arg].list[1], providerOption,
278 PROVIDER_COUNT, 0)) < 0)
280 break;
281 default:
282 bomb((
char *)
"unknown option (cavput)", NULL);
283 break;
284 }
285 } else
286 bomb((
char *)
"unknown option", NULL);
287 }
288
289 for (j = 0; j < PVs; j++)
290 if (!PVvalue[j].value) {
291 fprintf(stderr, "Error: no value given for %s\n", PVvalue[j].name);
292 exit(EXIT_FAILURE);
293 }
294
295 if (dryRun) {
296 for (j = 0; j < PVs; j++) {
297 if (strncmp(PVvalue[j].name, "pva://", 6) == 0) {
298 PVvalue[j].name += 6;
299 printf("%32s %s\n", PVvalue[j].name, PVvalue[j].value);
300 PVvalue[j].name -= 6;
301 } else if (strncmp(PVvalue[j].name, "ca://", 5) == 0) {
302 PVvalue[j].name += 5;
303 printf("%32s %s\n", PVvalue[j].name, PVvalue[j].value);
304 PVvalue[j].name -= 5;
305 } else {
306 printf("%32s %s\n", PVvalue[j].name, PVvalue[j].value);
307 }
308 }
309 } else {
310#if (EPICS_VERSION > 3)
311
312 allocPVA(&pva, PVs, 0);
313
314 epics::pvData::shared_vector<std::string> names(pva.numPVs);
315 epics::pvData::shared_vector<std::string> provider(pva.numPVs);
316 for (j = 0; j < pva.numPVs; j++) {
317 if (strncmp(PVvalue[j].name, "pva://", 6) == 0) {
318 PVvalue[j].name += 6;
319 names[j] = PVvalue[j].name;
320 PVvalue[j].name -= 6;
321 provider[j] = "pva";
322 } else if (strncmp(PVvalue[j].name, "ca://", 5) == 0) {
323 PVvalue[j].name += 5;
324 names[j] = PVvalue[j].name;
325 PVvalue[j].name -= 5;
326 provider[j] = "ca";
327 } else {
328 names[j] = PVvalue[j].name;
329 if (providerMode == PROVIDER_PVA) {
330 provider[j] = "pva";
331 } else {
332 provider[j] = "ca";
333 }
334 }
335 }
336 pva.pvaChannelNames = freeze(names);
337 pva.pvaProvider = freeze(provider);
338
339 ConnectPVA(&pva, pendIOTime);
340
341 for (j = 0; j < PVs; j++) {
342 if (!pva.isConnected[j]) {
343 if (!(blunderAhead & BLUNDER_SILENTLY))
344 fprintf(stderr, "Channel not connected: %s\n", PVvalue[j].name);
345 if (!blunderAhead && (doRamp || deltaMode))
346 exit(EXIT_FAILURE);
347 continue;
348 }
349 }
350
351
352
353 if (GetPVAValues(&pva) == 1) {
354 return (EXIT_FAILURE);
355 }
356
357
358 if (doRamp || deltaMode) {
359 for (j = 0; j < PVs; j++) {
360 if (pva.isConnected[j]) {
361 if (pva.pvaData[j].fieldType != epics::pvData::scalar) {
362 fprintf(stderr, "error (cavput): %s is not a scalar type PV, delta and ramp options are only available for scalar type PVs\n", PVvalue[j].name);
363 return (EXIT_FAILURE);
364 }
365 }
366 }
367 }
368
369 if (PrepPVAPutValues(&pva, PVvalue, charArray)) {
370 return (EXIT_FAILURE);
371 }
372
373
374 if (deltaMode) {
375 for (j = 0; j < PVs; j++) {
376 if (pva.isConnected[j] && (pva.pvaData[j].fieldType == epics::pvData::scalar) && pva.pvaData[j].numeric) {
377 pva.pvaData[j].putData[0].values[0] = pva.pvaData[j].putData[0].values[0] * deltaFactor + pva.pvaData[j].getData[0].values[0];
378 }
379 }
380 }
381
382 if (doRamp) {
383 double *fValues;
384
385 rampDeltas = (double *)malloc(sizeof(double) * PVs);
386 fValues = (double *)malloc(sizeof(double) * PVs);
387 for (j = 0; j < PVs; j++) {
388 if (pva.isConnected[j] && (pva.pvaData[j].fieldType == epics::pvData::scalar) && pva.pvaData[j].numeric) {
389 fValues[j] = pva.pvaData[j].putData[0].values[0];
390 rampDeltas[j] = (pva.pvaData[j].putData[0].values[0] - pva.pvaData[j].getData[0].values[0]) / rampSteps;
391 pva.pvaData[j].putData[0].values[0] = pva.pvaData[j].getData[0].values[0];
392 }
393 }
394
395 for (iramp = 1; iramp <= rampSteps; iramp++) {
396 for (j = 0; j < PVs; j++) {
397 if (pva.isConnected[j] && (pva.pvaData[j].fieldType == epics::pvData::scalar) && pva.pvaData[j].numeric) {
398 if (iramp == rampSteps) {
399 pva.pvaData[j].putData[0].values[0] = fValues[j];
400 } else {
401 pva.pvaData[j].putData[0].values[0] = pva.pvaData[j].putData[0].values[0] + rampDeltas[j];
402 }
403 pva.pvaData[j].numPutElements = 1;
404 }
405 }
406 if (PutPVAValues(&pva) == 1) {
407 return (EXIT_FAILURE);
408 }
409 if ((rampPause > 0) && (iramp < rampSteps)) {
411 }
412 }
413 free(rampDeltas);
414 } else {
415
416 if (PutPVAValues(&pva) == 1) {
417 return (EXIT_FAILURE);
418 }
419 }
420
421 if (PVvalue) {
422 for (j = 0; j < PVs; j++) {
423 if (PVvalue[j].name)
424 free(PVvalue[j].name);
425 if (PVvalue[j].value)
426 free(PVvalue[j].value);
427 }
428 free(PVvalue);
429 }
430 freePVA(&pva);
431 if (List)
432 free(List);
434 return (EXIT_SUCCESS);
435#else
436 ca_task_initialize();
437 ca_add_exception_event(oag_ca_exception_handler, NULL);
438 if (!(channelID = (chid *)malloc(sizeof(*channelID) * PVs)))
439 bomb((
char *)
"memory allocation failure (cavput)", NULL);
440 for (j = 0; j < PVs; j++) {
441 if (ca_search(PVvalue[j].name, channelID + j) != ECA_NORMAL) {
442 fprintf(stderr, "error (cavput): problem doing search for %s\n",
443 PVvalue[j].name);
444 ca_task_exit();
445 exit(EXIT_FAILURE);
446 }
447#ifdef DEBUG
448 fprintf(stderr, "ca_search initiated for %s\n", PVvalue[j].name);
449#endif
450 }
451 ca_pend_io(pendIOTime);
452#ifdef DEBUG
453 fprintf(stderr, "ca_pend_io returned\n");
454#endif
455 if (doRamp || deltaMode) {
456 for (j = 0; j < PVs; j++) {
457 if (ca_state(channelID[j]) != cs_conn) {
458 if (!(blunderAhead & BLUNDER_SILENTLY))
459 fprintf(stderr, "error (cavput): no connection for %s\n",
460 PVvalue[j].name);
461 if (!blunderAhead) {
462 ca_task_exit();
463 exit(EXIT_FAILURE);
464 }
465 }
466 }
467 if (!(presentValue = (double *)malloc(sizeof(*presentValue) * PVs))) {
468 fprintf(stderr, "error (cavput): memory allocation failure\n");
469 ca_task_exit();
470 exit(EXIT_FAILURE);
471 }
472 for (j = 0; j < PVs; j++) {
473 presentValue[j] = DBL_MAX;
474 if (ca_state(channelID[j]) != cs_conn)
475 continue;
476 if (ca_get(DBR_DOUBLE, channelID[j], presentValue + j) != ECA_NORMAL) {
477 fprintf(stderr, "error (cavput): problem doing get for %s\n",
478 PVvalue[j].name);
479 ca_task_exit();
480 exit(EXIT_FAILURE);
481 }
482 }
483 ca_pend_io(pendIOTime);
484 for (j = 0; j < PVs; j++) {
485 if (ca_state(channelID[j]) != cs_conn)
486 continue;
487 if (presentValue[j] == DBL_MAX) {
488 fprintf(stderr, "error (cavput): no value returned in time for %s\n",
489 PVvalue[j].name);
490 ca_task_exit();
491 exit(EXIT_FAILURE);
492 }
493 if (sscanf(PVvalue[j].value, "%le", &PVvalue[j].numericalValue) != 1) {
494 fprintf(stderr, "error (cavput): value (%s) for %s is not numerical--can't use -deltaMode or -ramp\n",
495 PVvalue[j].value, PVvalue[j].name);
496 ca_task_exit();
497 exit(EXIT_FAILURE);
498 }
499 }
500 numerical = 1;
501 }
502 if (deltaMode) {
503 for (j = 0; j < PVs; j++) {
504 PVvalue[j].numericalValue = PVvalue[j].numericalValue * deltaFactor + presentValue[j];
505 }
506 }
507 if (!doRamp) {
508#ifdef DEBUG
509 fprintf(stderr, "doing non-ramped puts\n");
510#endif
511 for (j = 0; j < PVs; j++) {
512 if (ca_state(channelID[j]) != cs_conn) {
513 if (!(blunderAhead & BLUNDER_SILENTLY))
514 fprintf(stderr, "Channel not connected: %s\n", PVvalue[j].name);
515 continue;
516 }
517#ifdef DEBUG
518 fprintf(stderr, "%s is connected\n", PVvalue[j].name);
519#endif
520 if (ca_write_access(channelID[j]) == 0) {
521 fprintf(stderr, "Write access denied on : %s\n", PVvalue[j].name);
522 }
523 if (!numerical) {
524 if (ca_put(DBR_STRING, channelID[j], PVvalue[j].value) != ECA_NORMAL) {
525 if (!(blunderAhead & BLUNDER_SILENTLY))
526 fprintf(stderr, "error (cavput): problem doing put for %s\n",
527 PVvalue[j].name);
528 if (!blunderAhead) {
529 ca_task_exit();
530 exit(EXIT_FAILURE);
531 }
532 }
533#ifdef DEBUG
534 fprintf(stderr, "ca_put of %s for %s done\n", PVvalue[j].value, PVvalue[j].name);
535#endif
536 } else {
537 if (!deltaMode) {
538 if (sscanf(PVvalue[j].value, "%le", &PVvalue[j].numericalValue) != 1) {
539 fprintf(stderr,
540 "error (cavput): value (%s) for %s is not scannable as a number---can't use -numerical.\n",
541 PVvalue[j].value, PVvalue[j].name);
542 ca_task_exit();
543 exit(EXIT_FAILURE);
544 }
545 }
546 if (ca_put(DBR_DOUBLE, channelID[j], &PVvalue[j].numericalValue) != ECA_NORMAL) {
547 if (!(blunderAhead & BLUNDER_SILENTLY))
548 fprintf(stderr, "error (cavput): problem doing put for %s\n",
549 PVvalue[j].name);
550 if (!blunderAhead) {
551 ca_task_exit();
552 exit(EXIT_FAILURE);
553 }
554 }
555#ifdef DEBUG
556 fprintf(stderr, "ca_put of %f for %s done\n", PVvalue[j].numericalValue, PVvalue[j].name);
557#endif
558 }
559 }
560 } else {
561
562 for (iramp = 0; iramp < rampSteps; iramp++) {
563 for (j = 0; j < PVs; j++) {
564 rampDelta = (PVvalue[j].numericalValue - presentValue[j]) / rampSteps;
565 rampValue = presentValue[j] + (iramp + 1) * rampDelta;
566 if (ca_put(DBR_DOUBLE, channelID[j], &rampValue) != ECA_NORMAL) {
567 if (!(blunderAhead & BLUNDER_SILENTLY))
568 fprintf(stderr, "error (cavput): problem doing put for %s\n",
569 PVvalue[j].name);
570 if (!blunderAhead) {
571 ca_task_exit();
572 exit(EXIT_FAILURE);
573 }
574 }
575 }
576 if ((status = ca_pend_io(pendIOTime)) != ECA_NORMAL) {
577 fprintf(stderr, "Problem processing one or more puts (cavput):\n%s\n",
578 ca_message(status));
579 ca_task_exit();
580 exit(EXIT_FAILURE);
581 }
582 if (rampPause > 0) {
583 ca_pend_event(rampPause);
584 } else {
585 ca_poll();
586 }
587 }
588 }
589
590 if ((status = ca_pend_io(pendIOTime)) != ECA_NORMAL) {
591 fprintf(stderr, "Problem processing one or more puts (cavput):\n%s\n",
592 ca_message(status));
593 ca_task_exit();
594 exit(EXIT_FAILURE);
595 }
596 ca_pend_event(0.5);
597#ifdef DEBUG
598 fprintf(stderr, "ca_pend_io returned\n");
599#endif
600
601 ca_task_exit();
602#ifdef DEBUG
603 fprintf(stderr, "ca_task_exit returned\n");
604#endif
605
606#endif
607 }
608
609#ifdef DEBUG
610 fprintf(stderr, "starting to free memory\n");
611#endif
612
613 if (channelID)
614 free(channelID);
615#ifdef DEBUG
616 fprintf(stderr, "free'd channelID\n");
617#endif
618
619 for (j = 0; j < PVs; j++) {
620 if (PVvalue[j].name)
621 free(PVvalue[j].name);
622
623 PVvalue[j].name = PVvalue[j].value = NULL;
624 }
625 free(PVvalue);
626#ifdef DEBUG
627 fprintf(stderr, "free'd PVvalue lists\n");
628#endif
629
630 if (presentValue)
631 free(presentValue);
632
634#ifdef DEBUG
635 fprintf(stderr, "free_scanargs returned\n");
636#endif
637
638 if (List)
639 free(List);
640#ifdef DEBUG
641 fprintf(stderr, "free'd List\n");
642#endif
643
644#ifdef DEBUG
645 fprintf(stderr, "exiting main routine\n");
646#endif
647
648 return (EXIT_SUCCESS);
649}
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer 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.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
void usleepSystemIndependent(long usec)
Sleep for a given number of microseconds, system-independently.
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)
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.