Merge lp:~epics-core/epics-base/printf-record into lp:~epics-core/epics-base/3.15

Proposed by Andrew Johnson
Status: Merged
Merged at revision: 12444
Proposed branch: lp:~epics-core/epics-base/printf-record
Merge into: lp:~epics-core/epics-base/3.15
Diff against target: 2365 lines (+1922/-204)
22 files modified
src/ioc/db/Makefile (+1/-0)
src/ioc/db/dbAccess.c (+34/-35)
src/ioc/db/dbLink.c (+59/-0)
src/ioc/db/dbLink.h (+7/-0)
src/ioc/db/menuPost.dbd (+11/-0)
src/std/dev/Makefile (+6/-1)
src/std/dev/devLsiSoft.c (+42/-0)
src/std/dev/devLsoSoft.c (+26/-0)
src/std/dev/devLsoSoftCallback.c (+51/-0)
src/std/dev/devPrintfSoft.c (+26/-0)
src/std/dev/devPrintfSoftCallback.c (+51/-0)
src/std/dev/devSoStdio.c (+0/-108)
src/std/dev/devSoft.dbd (+7/-0)
src/std/dev/devStdio.c (+212/-0)
src/std/rec/Makefile (+35/-59)
src/std/rec/RULES (+1/-1)
src/std/rec/lsiRecord.c (+284/-0)
src/std/rec/lsiRecord.dbd (+88/-0)
src/std/rec/lsoRecord.c (+322/-0)
src/std/rec/lsoRecord.dbd (+112/-0)
src/std/rec/printfRecord.c (+438/-0)
src/std/rec/printfRecord.dbd (+109/-0)
To merge this branch: bzr merge lp:~epics-core/epics-base/printf-record
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+139098@code.launchpad.net

Description of the change

This branch adds three new record types and associated device support to Base:
 * printf: A string conversion record, plus device support for Soft Channel, Async Soft Channel and stdio device types.
 * lsi: A long string input record, plus device support for Soft Channel input.
 * lso: A long string output record, plus device support for Soft Channel, Async Soft Channel and stdio device types.

To post a comment you must log in.
Revision history for this message
Andrew Johnson (anj) wrote :

Nobody seems to care, so I'm merging this.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/ioc/db/Makefile'
--- src/ioc/db/Makefile 2012-06-21 20:27:32 +0000
+++ src/ioc/db/Makefile 2012-12-10 21:21:25 +0000
@@ -47,6 +47,7 @@
47menuGlobal_DBD += menuIvoa.dbd47menuGlobal_DBD += menuIvoa.dbd
48menuGlobal_DBD += menuOmsl.dbd48menuGlobal_DBD += menuOmsl.dbd
49menuGlobal_DBD += menuPini.dbd49menuGlobal_DBD += menuPini.dbd
50menuGlobal_DBD += menuPost.dbd
50menuGlobal_DBD += menuPriority.dbd51menuGlobal_DBD += menuPriority.dbd
51menuGlobal_DBD += menuScan.dbd52menuGlobal_DBD += menuScan.dbd
52menuGlobal_DBD += menuYesNo.dbd53menuGlobal_DBD += menuYesNo.dbd
5354
=== modified file 'src/ioc/db/dbAccess.c'
--- src/ioc/db/dbAccess.c 2012-10-29 06:20:56 +0000
+++ src/ioc/db/dbAccess.c 2012-12-10 21:21:25 +0000
@@ -583,10 +583,8 @@
583{583{
584 DBENTRY dbEntry;584 DBENTRY dbEntry;
585 dbFldDes *pflddes;585 dbFldDes *pflddes;
586 struct rset *prset;
587 long status = 0;586 long status = 0;
588 long no_elements = 1;587 short dbfType;
589 short dbfType, dbrType, field_size;
590588
591 if (!pname || !*pname || !pdbbase)589 if (!pname || !*pname || !pdbbase)
592 return S_db_notFound;590 return S_db_notFound;
@@ -601,48 +599,49 @@
601 status = dbGetAttributePart(&dbEntry, &pname);599 status = dbGetAttributePart(&dbEntry, &pname);
602 if (status) goto finish;600 if (status) goto finish;
603601
602 pflddes = dbEntry.pflddes;
603 dbfType = pflddes->field_type;
604
604 paddr->precord = dbEntry.precnode->precord;605 paddr->precord = dbEntry.precnode->precord;
605 paddr->pfield = dbEntry.pfield;606 paddr->pfield = dbEntry.pfield;
606 pflddes = dbEntry.pflddes;607 paddr->pfldDes = pflddes;
607608 paddr->no_elements = 1;
608 dbfType = pflddes->field_type;609 paddr->field_type = dbfType;
609 dbrType = mapDBFToDBR[dbfType];610 paddr->field_size = pflddes->size;
610 field_size = pflddes->size;611 paddr->special = pflddes->special;
611612 paddr->dbr_field_type = mapDBFToDBR[dbfType];
613
614 if (paddr->special == SPC_DBADDR) {
615 struct rset *prset = dbGetRset(paddr);
616
617 /* Let record type modify paddr */
618 if (prset && prset->cvt_dbaddr) {
619 status = prset->cvt_dbaddr(paddr);
620 if (status)
621 goto finish;
622 dbfType = paddr->field_type;
623 }
624 }
625
626 /* Handle field modifiers */
612 if (*pname++ == '$') {627 if (*pname++ == '$') {
613 /* Some field types can be accessed as char arrays */628 /* Some field types can be accessed as char arrays */
614 if (dbfType == DBF_STRING) {629 if (dbfType == DBF_STRING) {
615 dbfType = DBF_CHAR;630 paddr->no_elements = paddr->field_size;
616 dbrType = DBR_CHAR;631 paddr->field_type = DBF_CHAR;
617 no_elements = field_size;632 paddr->field_size = 1;
618 field_size = 1;633 paddr->dbr_field_type = DBR_CHAR;
619 } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {634 } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
620 /* Clients see a char array, but keep original dbfType */635 /* Clients see a char array, but keep original dbfType */
621 dbrType = DBR_CHAR;636 paddr->no_elements = PVNAME_STRINGSZ + 12;
622 no_elements = PVNAME_STRINGSZ + 12;637 paddr->field_size = 1;
623 field_size = 1;638 paddr->dbr_field_type = DBR_CHAR;
624 } else {639 } else {
625 status = S_dbLib_fieldNotFound;640 status = S_dbLib_fieldNotFound;
626 goto finish;641 goto finish;
627 }642 }
628 }643 }
629644
630 paddr->pfldDes = pflddes;
631 paddr->field_type = dbfType;
632 paddr->dbr_field_type = dbrType;
633 paddr->field_size = field_size;
634 paddr->special = pflddes->special;
635 paddr->no_elements = no_elements;
636
637 if ((paddr->special == SPC_DBADDR) &&
638 (prset = dbGetRset(paddr)) &&
639 prset->cvt_dbaddr)
640 /* cvt_dbaddr routine may change any of these elements of paddr:
641 * pfield, no_elements, element_offset, field_type,
642 * dbr_field_type, field_size, and/or special.
643 */
644 status = prset->cvt_dbaddr(paddr);
645
646finish:645finish:
647 dbFinishEntry(&dbEntry);646 dbFinishEntry(&dbEntry);
648 return status;647 return status;
@@ -817,7 +816,7 @@
817816
818 /* check for array */817 /* check for array */
819 if ((!pfl || pfl->type == dbfl_type_rec) &&818 if ((!pfl || pfl->type == dbfl_type_rec) &&
820 paddr->special == SPC_DBADDR &&819 paddr->pfldDes->special == SPC_DBADDR &&
821 no_elements > 1 &&820 no_elements > 1 &&
822 (prset = dbGetRset(paddr)) &&821 (prset = dbGetRset(paddr)) &&
823 prset->get_array_info) {822 prset->get_array_info) {
@@ -1171,7 +1170,7 @@
1171 struct rset *prset = dbGetRset(paddr);1170 struct rset *prset = dbGetRset(paddr);
1172 long offset = 0;1171 long offset = 0;
11731172
1174 if (paddr->special == SPC_DBADDR &&1173 if (paddr->pfldDes->special == SPC_DBADDR &&
1175 prset && prset->get_array_info) {1174 prset && prset->get_array_info) {
1176 long dummy;1175 long dummy;
11771176
@@ -1184,7 +1183,7 @@
11841183
1185 /* update array info */1184 /* update array info */
1186 if (!status &&1185 if (!status &&
1187 paddr->special == SPC_DBADDR &&1186 paddr->pfldDes->special == SPC_DBADDR &&
1188 prset && prset->put_array_info) {1187 prset && prset->put_array_info) {
1189 status = prset->put_array_info(paddr, nRequest);1188 status = prset->put_array_info(paddr, nRequest);
1190 }1189 }
11911190
=== modified file 'src/ioc/db/dbLink.c'
--- src/ioc/db/dbLink.c 2012-07-07 20:54:31 +0000
+++ src/ioc/db/dbLink.c 2012-12-10 21:21:25 +0000
@@ -649,3 +649,62 @@
649 }649 }
650}650}
651651
652/* Helper functions for long string support */
653
654long dbLoadLinkLS(struct link *plink, char *pbuffer, epicsUInt32 size,
655 epicsUInt32 *plen)
656{
657 if (plink->type == CONSTANT &&
658 plink->value.constantStr) {
659 strncpy(pbuffer, plink->value.constantStr, --size);
660 pbuffer[size] = 0;
661 *plen = strlen(pbuffer) + 1;
662 return 0;
663 }
664
665 return S_db_notFound;
666}
667
668long dbGetLinkLS(struct link *plink, char *pbuffer, epicsUInt32 size,
669 epicsUInt32 *plen)
670{
671 int dtyp = dbGetLinkDBFtype(plink);
672 long len = size;
673 long status;
674
675 if (dtyp < 0) /* Not connected */
676 return 0;
677
678 if (dtyp == DBR_CHAR || dtyp == DBF_UCHAR) {
679 status = dbGetLink(plink, dtyp, pbuffer, 0, &len);
680 }
681 else if (size >= MAX_STRING_SIZE)
682 status = dbGetLink(plink, DBR_STRING, pbuffer, 0, 0);
683 else {
684 /* pbuffer is too small to fetch using DBR_STRING */
685 char tmp[MAX_STRING_SIZE];
686
687 status = dbGetLink(plink, DBR_STRING, tmp, 0, 0);
688 if (!status)
689 strncpy(pbuffer, tmp, len - 1);
690 }
691 if (!status) {
692 pbuffer[--len] = 0;
693 *plen = strlen(pbuffer) + 1;
694 }
695 return status;
696}
697
698long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len)
699{
700 int dtyp = dbGetLinkDBFtype(plink);
701
702 if (dtyp < 0)
703 return 0; /* Not connected */
704
705 if (dtyp == DBR_CHAR || dtyp == DBF_UCHAR)
706 return dbPutLink(plink, dtyp, pbuffer, len);
707
708 return dbPutLink(plink, DBR_STRING, pbuffer, 1);
709}
710
652711
=== modified file 'src/ioc/db/dbLink.h'
--- src/ioc/db/dbLink.h 2012-08-08 18:38:21 +0000
+++ src/ioc/db/dbLink.h 2012-12-10 21:21:25 +0000
@@ -81,6 +81,13 @@
81 const void *pbuffer, long nRequest);81 const void *pbuffer, long nRequest);
82epicsShareFunc void dbScanFwdLink(struct link *plink);82epicsShareFunc void dbScanFwdLink(struct link *plink);
8383
84epicsShareFunc long dbLoadLinkLS(struct link *plink, char *pbuffer,
85 epicsUInt32 size, epicsUInt32 *plen);
86epicsShareFunc long dbGetLinkLS(struct link *plink, char *pbuffer,
87 epicsUInt32 buffer_size, epicsUInt32 *plen);
88epicsShareFunc long dbPutLinkLS(struct link *plink, char *pbuffer,
89 epicsUInt32 len);
90
84#ifdef __cplusplus91#ifdef __cplusplus
85}92}
86#endif93#endif
8794
=== added file 'src/ioc/db/menuPost.dbd'
--- src/ioc/db/menuPost.dbd 1970-01-01 00:00:00 +0000
+++ src/ioc/db/menuPost.dbd 2012-12-10 21:21:25 +0000
@@ -0,0 +1,11 @@
1#*************************************************************************
2# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3# National Laboratory.
4# EPICS BASE is distributed subject to a Software License Agreement found
5# in file LICENSE that is included with this distribution.
6#*************************************************************************
7
8menu(menuPost) {
9 choice(menuPost_OnChange, "On Change")
10 choice(menuPost_Always, "Always")
11}
012
=== modified file 'src/std/dev/Makefile'
--- src/std/dev/Makefile 2012-07-11 23:07:23 +0000
+++ src/std/dev/Makefile 2012-12-10 21:21:25 +0000
@@ -30,6 +30,8 @@
30dbRecStd_SRCS += devHistogramSoft.c30dbRecStd_SRCS += devHistogramSoft.c
31dbRecStd_SRCS += devLiSoft.c31dbRecStd_SRCS += devLiSoft.c
32dbRecStd_SRCS += devLoSoft.c32dbRecStd_SRCS += devLoSoft.c
33dbRecStd_SRCS += devLsiSoft.c
34dbRecStd_SRCS += devLsoSoft.c
33dbRecStd_SRCS += devMbbiDirectSoft.c35dbRecStd_SRCS += devMbbiDirectSoft.c
34dbRecStd_SRCS += devMbbiDirectSoftRaw.c36dbRecStd_SRCS += devMbbiDirectSoftRaw.c
35dbRecStd_SRCS += devMbbiSoft.c37dbRecStd_SRCS += devMbbiSoft.c
@@ -38,6 +40,7 @@
38dbRecStd_SRCS += devMbboDirectSoftRaw.c40dbRecStd_SRCS += devMbboDirectSoftRaw.c
39dbRecStd_SRCS += devMbboSoft.c41dbRecStd_SRCS += devMbboSoft.c
40dbRecStd_SRCS += devMbboSoftRaw.c42dbRecStd_SRCS += devMbboSoftRaw.c
43dbRecStd_SRCS += devPrintfSoft.c
41dbRecStd_SRCS += devSASoft.c44dbRecStd_SRCS += devSASoft.c
42dbRecStd_SRCS += devSiSoft.c45dbRecStd_SRCS += devSiSoft.c
43dbRecStd_SRCS += devSoSoft.c46dbRecStd_SRCS += devSoSoft.c
@@ -55,12 +58,14 @@
55dbRecStd_SRCS += devBoSoftCallback.c58dbRecStd_SRCS += devBoSoftCallback.c
56dbRecStd_SRCS += devCalcoutSoftCallback.c59dbRecStd_SRCS += devCalcoutSoftCallback.c
57dbRecStd_SRCS += devLoSoftCallback.c60dbRecStd_SRCS += devLoSoftCallback.c
61dbRecStd_SRCS += devLsoSoftCallback.c
58dbRecStd_SRCS += devMbboSoftCallback.c62dbRecStd_SRCS += devMbboSoftCallback.c
59dbRecStd_SRCS += devMbboDirectSoftCallback.c63dbRecStd_SRCS += devMbboDirectSoftCallback.c
64dbRecStd_SRCS += devPrintfSoftCallback.c
60dbRecStd_SRCS += devSoSoftCallback.c65dbRecStd_SRCS += devSoSoftCallback.c
6166
62dbRecStd_SRCS += devTimestamp.c67dbRecStd_SRCS += devTimestamp.c
63dbRecStd_SRCS += devSoStdio.c68dbRecStd_SRCS += devStdio.c
6469
65dbRecStd_SRCS += asSubRecordFunctions.c70dbRecStd_SRCS += asSubRecordFunctions.c
6671
6772
=== added file 'src/std/dev/devLsiSoft.c'
--- src/std/dev/devLsiSoft.c 1970-01-01 00:00:00 +0000
+++ src/std/dev/devLsiSoft.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,42 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* Long String Input soft device support
9 *
10 * Author: Andrew Johnson
11 * Date: 2012-11-28
12 */
13
14#include "dbAccess.h"
15#include "epicsTime.h"
16#include "link.h"
17#include "lsiRecord.h"
18#include "epicsExport.h"
19
20static long init_record(lsiRecord *prec)
21{
22 dbLoadLinkLS(&prec->inp, prec->val, prec->sizv, &prec->len);
23
24 return 0;
25}
26
27static long read_string(lsiRecord *prec)
28{
29 long status = dbGetLinkLS(&prec->inp, prec->val, prec->sizv, &prec->len);
30
31 if (!status &&
32 prec->tsel.type == CONSTANT &&
33 prec->tse == epicsTimeEventDeviceTime)
34 dbGetTimeStamp(&prec->inp, &prec->time);
35
36 return status;
37}
38
39lsidset devLsiSoft = {
40 5, NULL, NULL, init_record, NULL, read_string
41};
42epicsExportAddress(dset, devLsiSoft);
043
=== added file 'src/std/dev/devLsoSoft.c'
--- src/std/dev/devLsoSoft.c 1970-01-01 00:00:00 +0000
+++ src/std/dev/devLsoSoft.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,26 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* Long String Output soft device support
9 *
10 * Author: Andrew Johnson
11 * Date: 2012-11-29
12 */
13
14#include "dbAccess.h"
15#include "lsoRecord.h"
16#include "epicsExport.h"
17
18static long write_string(lsoRecord *prec)
19{
20 return dbPutLinkLS(&prec->out, prec->val, prec->len);
21}
22
23lsodset devLsoSoft = {
24 5, NULL, NULL, NULL, NULL, write_string
25};
26epicsExportAddress(dset, devLsoSoft);
027
=== added file 'src/std/dev/devLsoSoftCallback.c'
--- src/std/dev/devLsoSoftCallback.c 1970-01-01 00:00:00 +0000
+++ src/std/dev/devLsoSoftCallback.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,51 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7/* $Revision-Id$ */
8/*
9 * Author: Andrew Johnson
10 * Date: 30 Nov 2012
11 */
12
13#include "alarm.h"
14#include "dbAccess.h"
15#include "recGbl.h"
16#include "lsoRecord.h"
17#include "epicsExport.h"
18
19static long write_string(lsoRecord *prec)
20{
21 struct link *plink = &prec->out;
22 int dtyp = dbGetLinkDBFtype(plink);
23 long len = prec->len;
24 long status;
25
26 if (prec->pact || dtyp < 0)
27 return 0;
28
29 if (dtyp != DBR_CHAR && dtyp != DBF_UCHAR) {
30 dtyp = DBR_STRING;
31 len = 1;
32 }
33
34 if (plink->type != CA_LINK)
35 return dbPutLink(plink, dtyp, prec->val, len);
36
37 status = dbCaPutLinkCallback(plink, dtyp, prec->val, len,
38 dbCaCallbackProcess, plink);
39 if (status) {
40 recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
41 return status;
42 }
43
44 prec->pact = TRUE;
45 return 0;
46}
47
48lsodset devLsoSoftCallback = {
49 5, NULL, NULL, NULL, NULL, write_string
50};
51epicsExportAddress(dset, devLsoSoftCallback);
052
=== added file 'src/std/dev/devPrintfSoft.c'
--- src/std/dev/devPrintfSoft.c 1970-01-01 00:00:00 +0000
+++ src/std/dev/devPrintfSoft.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,26 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7/* $Revision-Id$ */
8/*
9 * Author: Andrew Johnson
10 * Date: 28 Sept 2012
11 */
12
13#include "dbAccess.h"
14#include "printfRecord.h"
15#include "epicsExport.h"
16
17static long write_string(printfRecord *prec)
18{
19 return dbPutLinkLS(&prec->out, prec->val, prec->len);
20}
21
22printfdset devPrintfSoft = {
23 5, NULL, NULL, NULL, NULL, write_string
24};
25epicsExportAddress(dset, devPrintfSoft);
26
027
=== added file 'src/std/dev/devPrintfSoftCallback.c'
--- src/std/dev/devPrintfSoftCallback.c 1970-01-01 00:00:00 +0000
+++ src/std/dev/devPrintfSoftCallback.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,51 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7/* $Revision-Id$ */
8/*
9 * Author: Andrew Johnson
10 * Date: 28 Sept 2012
11 */
12
13#include "alarm.h"
14#include "dbAccess.h"
15#include "recGbl.h"
16#include "printfRecord.h"
17#include "epicsExport.h"
18
19static long write_string(printfRecord *prec)
20{
21 struct link *plink = &prec->out;
22 int dtyp = dbGetLinkDBFtype(plink);
23 long len = prec->len;
24 long status;
25
26 if (prec->pact || dtyp < 0)
27 return 0;
28
29 if (dtyp != DBR_CHAR && dtyp != DBF_UCHAR) {
30 dtyp = DBR_STRING;
31 len = 1;
32 }
33
34 if (plink->type != CA_LINK)
35 return dbPutLink(plink, dtyp, prec->val, len);
36
37 status = dbCaPutLinkCallback(plink, dtyp, prec->val, len,
38 dbCaCallbackProcess, plink);
39 if (status) {
40 recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
41 return status;
42 }
43
44 prec->pact = TRUE;
45 return 0;
46}
47
48printfdset devPrintfSoftCallback = {
49 5, NULL, NULL, NULL, NULL, write_string
50};
51epicsExportAddress(dset, devPrintfSoftCallback);
052
=== removed file 'src/std/dev/devSoStdio.c'
--- src/std/dev/devSoStdio.c 2012-07-18 21:45:23 +0000
+++ src/std/dev/devSoStdio.c 1970-01-01 00:00:00 +0000
@@ -1,108 +0,0 @@
1/*************************************************************************\
2* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* $Revision-Id$ */
9
10#include <stdio.h>
11#include <string.h>
12
13#include "dbCommon.h"
14#include "devSup.h"
15#include "errlog.h"
16#include "recGbl.h"
17#include "recSup.h"
18#include "stringoutRecord.h"
19#include "epicsExport.h"
20
21typedef int (*PRINTFFUNC)(const char *fmt, ...);
22
23static int stderrPrintf(const char *fmt, ...);
24static int logPrintf(const char *fmt, ...);
25
26
27static struct outStream {
28 const char *name;
29 PRINTFFUNC print;
30} outStreams[] = {
31 {"stdout", printf},
32 {"stderr", stderrPrintf},
33 {"errlog", logPrintf},
34 {NULL, NULL}
35};
36
37static int stderrPrintf(const char *fmt, ...) {
38 va_list pvar;
39 int retval;
40
41 va_start(pvar, fmt);
42 retval = vfprintf(stderr, fmt, pvar);
43 va_end (pvar);
44
45 return retval;
46}
47
48static int logPrintf(const char *fmt, ...) {
49 va_list pvar;
50 int retval;
51
52 va_start(pvar, fmt);
53 retval = errlogVprintf(fmt, pvar);
54 va_end (pvar);
55
56 return retval;
57}
58
59static long add(dbCommon *pcommon) {
60 stringoutRecord *prec = (stringoutRecord *) pcommon;
61 struct outStream *pstream;
62
63 if (prec->out.type != INST_IO)
64 return S_dev_badOutType;
65
66 for (pstream = outStreams; pstream->name; ++pstream) {
67 if (strcmp(prec->out.value.instio.string, pstream->name) == 0) {
68 prec->dpvt = pstream;
69 return 0;
70 }
71 }
72 prec->dpvt = NULL;
73 return -1;
74}
75
76static long del(dbCommon *pcommon) {
77 stringoutRecord *prec = (stringoutRecord *) pcommon;
78
79 prec->dpvt = NULL;
80 return 0;
81}
82
83static struct dsxt dsxtSoStdio = {
84 add, del
85};
86
87static long init(int pass)
88{
89 if (pass == 0) devExtend(&dsxtSoStdio);
90 return 0;
91}
92
93static long write_string(stringoutRecord *prec)
94{
95 struct outStream *pstream = (struct outStream *)prec->dpvt;
96 if (pstream)
97 pstream->print("%s\n", prec->val);
98 return 0;
99}
100
101/* Create the dset for devSoStdio */
102static struct {
103 dset common;
104 DEVSUPFUN write;
105} devSoStdio = {
106 {5, NULL, init, NULL, NULL}, write_string
107};
108epicsExportAddress(dset, devSoStdio);
1090
=== modified file 'src/std/dev/devSoft.dbd'
--- src/std/dev/devSoft.dbd 2012-07-11 23:07:23 +0000
+++ src/std/dev/devSoft.dbd 2012-12-10 21:21:25 +0000
@@ -9,10 +9,13 @@
9device(histogram,CONSTANT,devHistogramSoft,"Soft Channel")9device(histogram,CONSTANT,devHistogramSoft,"Soft Channel")
10device(longin,CONSTANT,devLiSoft,"Soft Channel")10device(longin,CONSTANT,devLiSoft,"Soft Channel")
11device(longout,CONSTANT,devLoSoft,"Soft Channel")11device(longout,CONSTANT,devLoSoft,"Soft Channel")
12device(lsi,CONSTANT,devLsiSoft,"Soft Channel")
13device(lso,CONSTANT,devLsoSoft,"Soft Channel")
12device(mbbi,CONSTANT,devMbbiSoft,"Soft Channel")14device(mbbi,CONSTANT,devMbbiSoft,"Soft Channel")
13device(mbbiDirect,CONSTANT,devMbbiDirectSoft,"Soft Channel")15device(mbbiDirect,CONSTANT,devMbbiDirectSoft,"Soft Channel")
14device(mbbo,CONSTANT,devMbboSoft,"Soft Channel")16device(mbbo,CONSTANT,devMbboSoft,"Soft Channel")
15device(mbboDirect,CONSTANT,devMbboDirectSoft,"Soft Channel")17device(mbboDirect,CONSTANT,devMbboDirectSoft,"Soft Channel")
18device(printf,CONSTANT,devPrintfSoft,"Soft Channel")
16device(stringin,CONSTANT,devSiSoft,"Soft Channel")19device(stringin,CONSTANT,devSiSoft,"Soft Channel")
17device(stringout,CONSTANT,devSoSoft,"Soft Channel")20device(stringout,CONSTANT,devSoSoft,"Soft Channel")
18device(subArray,CONSTANT,devSASoft,"Soft Channel")21device(subArray,CONSTANT,devSASoft,"Soft Channel")
@@ -34,10 +37,12 @@
34device(calcout,CONSTANT,devCalcoutSoftCallback,"Async Soft Channel")37device(calcout,CONSTANT,devCalcoutSoftCallback,"Async Soft Channel")
35device(longin,CONSTANT,devLiSoftCallback,"Async Soft Channel")38device(longin,CONSTANT,devLiSoftCallback,"Async Soft Channel")
36device(longout,CONSTANT,devLoSoftCallback,"Async Soft Channel")39device(longout,CONSTANT,devLoSoftCallback,"Async Soft Channel")
40device(lso,CONSTANT,devLsoSoftCallback,"Async Soft Channel")
37device(mbbi,CONSTANT,devMbbiSoftCallback,"Async Soft Channel")41device(mbbi,CONSTANT,devMbbiSoftCallback,"Async Soft Channel")
38device(mbbiDirect,CONSTANT,devMbbiDirectSoftCallback,"Async Soft Channel")42device(mbbiDirect,CONSTANT,devMbbiDirectSoftCallback,"Async Soft Channel")
39device(mbbo,CONSTANT,devMbboSoftCallback,"Async Soft Channel")43device(mbbo,CONSTANT,devMbboSoftCallback,"Async Soft Channel")
40device(mbboDirect,CONSTANT,devMbboDirectSoftCallback,"Async Soft Channel")44device(mbboDirect,CONSTANT,devMbboDirectSoftCallback,"Async Soft Channel")
45device(printf,CONSTANT,devPrintfSoftCallback,"Async Soft Channel")
41device(stringin,CONSTANT,devSiSoftCallback,"Async Soft Channel")46device(stringin,CONSTANT,devSiSoftCallback,"Async Soft Channel")
42device(stringout,CONSTANT,devSoSoftCallback,"Async Soft Channel")47device(stringout,CONSTANT,devSoSoftCallback,"Async Soft Channel")
4348
@@ -49,6 +54,8 @@
49device(longin, INST_IO,devLiGeneralTime,"General Time")54device(longin, INST_IO,devLiGeneralTime,"General Time")
50device(stringin,INST_IO,devSiGeneralTime,"General Time")55device(stringin,INST_IO,devSiGeneralTime,"General Time")
5156
57device(lso,INST_IO,devLsoStdio,"stdio")
58device(printf,INST_IO,devPrintfStdio,"stdio")
52device(stringout,INST_IO,devSoStdio,"stdio")59device(stringout,INST_IO,devSoStdio,"stdio")
5360
54device(bi, INST_IO, devBiDbState, "Db State")61device(bi, INST_IO, devBiDbState, "Db State")
5562
=== added file 'src/std/dev/devStdio.c'
--- src/std/dev/devStdio.c 1970-01-01 00:00:00 +0000
+++ src/std/dev/devStdio.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,212 @@
1/*************************************************************************\
2* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* $Revision-Id$ */
9
10#include <stdio.h>
11#include <string.h>
12
13#include "dbCommon.h"
14#include "devSup.h"
15#include "errlog.h"
16#include "recGbl.h"
17#include "recSup.h"
18#include "lsoRecord.h"
19#include "printfRecord.h"
20#include "stringoutRecord.h"
21#include "epicsExport.h"
22
23typedef int (*PRINTFFUNC)(const char *fmt, ...);
24
25static int stderrPrintf(const char *fmt, ...);
26static int logPrintf(const char *fmt, ...);
27
28
29static struct outStream {
30 const char *name;
31 PRINTFFUNC print;
32} outStreams[] = {
33 {"stdout", printf},
34 {"stderr", stderrPrintf},
35 {"errlog", logPrintf},
36 {NULL, NULL}
37};
38
39static int stderrPrintf(const char *fmt, ...) {
40 va_list pvar;
41 int retval;
42
43 va_start(pvar, fmt);
44 retval = vfprintf(stderr, fmt, pvar);
45 va_end (pvar);
46
47 return retval;
48}
49
50static int logPrintf(const char *fmt, ...) {
51 va_list pvar;
52 int retval;
53
54 va_start(pvar, fmt);
55 retval = errlogVprintf(fmt, pvar);
56 va_end (pvar);
57
58 return retval;
59}
60
61
62/* lso device support */
63
64static long add_lso(dbCommon *pcommon) {
65 lsoRecord *prec = (lsoRecord *) pcommon;
66 struct outStream *pstream;
67
68 if (prec->out.type != INST_IO)
69 return S_dev_badOutType;
70
71 for (pstream = outStreams; pstream->name; ++pstream) {
72 if (strcmp(prec->out.value.instio.string, pstream->name) == 0) {
73 prec->dpvt = pstream;
74 return 0;
75 }
76 }
77 prec->dpvt = NULL;
78 return -1;
79}
80
81static long del_lso(dbCommon *pcommon) {
82 lsoRecord *prec = (lsoRecord *) pcommon;
83
84 prec->dpvt = NULL;
85 return 0;
86}
87
88static struct dsxt dsxtLsoStdio = {
89 add_lso, del_lso
90};
91
92static long init_lso(int pass)
93{
94 if (pass == 0) devExtend(&dsxtLsoStdio);
95 return 0;
96}
97
98static long write_lso(lsoRecord *prec)
99{
100 struct outStream *pstream = (struct outStream *)prec->dpvt;
101 if (pstream)
102 pstream->print("%s\n", prec->val);
103 return 0;
104}
105
106lsodset devLsoStdio = {
107 5, NULL, init_lso, NULL, NULL, write_lso
108};
109epicsExportAddress(dset, devLsoStdio);
110
111
112/* printf device support */
113
114static long add_printf(dbCommon *pcommon) {
115 printfRecord *prec = (printfRecord *) pcommon;
116 struct outStream *pstream;
117
118 if (prec->out.type != INST_IO)
119 return S_dev_badOutType;
120
121 for (pstream = outStreams; pstream->name; ++pstream) {
122 if (strcmp(prec->out.value.instio.string, pstream->name) == 0) {
123 prec->dpvt = pstream;
124 return 0;
125 }
126 }
127 prec->dpvt = NULL;
128 return -1;
129}
130
131static long del_printf(dbCommon *pcommon) {
132 printfRecord *prec = (printfRecord *) pcommon;
133
134 prec->dpvt = NULL;
135 return 0;
136}
137
138static struct dsxt dsxtPrintfStdio = {
139 add_printf, del_printf
140};
141
142static long init_printf(int pass)
143{
144 if (pass == 0) devExtend(&dsxtPrintfStdio);
145 return 0;
146}
147
148static long write_printf(printfRecord *prec)
149{
150 struct outStream *pstream = (struct outStream *)prec->dpvt;
151 if (pstream)
152 pstream->print("%s\n", prec->val);
153 return 0;
154}
155
156printfdset devPrintfStdio = {
157 5, NULL, init_printf, NULL, NULL, write_printf
158};
159epicsExportAddress(dset, devPrintfStdio);
160
161
162/* stringout device support */
163
164static long add_stringout(dbCommon *pcommon) {
165 stringoutRecord *prec = (stringoutRecord *) pcommon;
166 struct outStream *pstream;
167
168 if (prec->out.type != INST_IO)
169 return S_dev_badOutType;
170
171 for (pstream = outStreams; pstream->name; ++pstream) {
172 if (strcmp(prec->out.value.instio.string, pstream->name) == 0) {
173 prec->dpvt = pstream;
174 return 0;
175 }
176 }
177 prec->dpvt = NULL;
178 return -1;
179}
180
181static long del_stringout(dbCommon *pcommon) {
182 stringoutRecord *prec = (stringoutRecord *) pcommon;
183
184 prec->dpvt = NULL;
185 return 0;
186}
187
188static struct dsxt dsxtSoStdio = {
189 add_stringout, del_stringout
190};
191
192static long init_stringout(int pass)
193{
194 if (pass == 0) devExtend(&dsxtSoStdio);
195 return 0;
196}
197
198static long write_stringout(stringoutRecord *prec)
199{
200 struct outStream *pstream = (struct outStream *)prec->dpvt;
201 if (pstream)
202 pstream->print("%s\n", prec->val);
203 return 0;
204}
205
206static struct {
207 dset common;
208 DEVSUPFUN write;
209} devSoStdio = {
210 {5, NULL, init_stringout, NULL, NULL}, write_stringout
211};
212epicsExportAddress(dset, devSoStdio);
0213
=== modified file 'src/std/rec/Makefile'
--- src/std/rec/Makefile 2011-11-14 23:42:50 +0000
+++ src/std/rec/Makefile 2012-12-10 21:21:25 +0000
@@ -11,67 +11,43 @@
1111
12SRC_DIRS += $(STDDIR)/rec12SRC_DIRS += $(STDDIR)/rec
1313
14DBDINC += aaiRecord14stdRecords += aaiRecord
15DBDINC += aaoRecord15stdRecords += aaoRecord
16DBDINC += aiRecord16stdRecords += aiRecord
17DBDINC += aoRecord17stdRecords += aoRecord
18DBDINC += aSubRecord18stdRecords += aSubRecord
19DBDINC += biRecord19stdRecords += biRecord
20DBDINC += boRecord20stdRecords += boRecord
21DBDINC += calcRecord21stdRecords += calcRecord
22DBDINC += calcoutRecord22stdRecords += calcoutRecord
23DBDINC += compressRecord23stdRecords += compressRecord
24DBDINC += dfanoutRecord24stdRecords += dfanoutRecord
25DBDINC += eventRecord25stdRecords += eventRecord
26DBDINC += fanoutRecord26stdRecords += fanoutRecord
27DBDINC += histogramRecord27stdRecords += histogramRecord
28DBDINC += longinRecord28stdRecords += longinRecord
29DBDINC += longoutRecord29stdRecords += longoutRecord
30DBDINC += mbbiRecord30stdRecords += lsiRecord
31DBDINC += mbbiDirectRecord31stdRecords += lsoRecord
32DBDINC += mbboRecord32stdRecords += mbbiRecord
33DBDINC += mbboDirectRecord33stdRecords += mbbiDirectRecord
34DBDINC += permissiveRecord34stdRecords += mbboRecord
35DBDINC += selRecord35stdRecords += mbboDirectRecord
36DBDINC += seqRecord36stdRecords += permissiveRecord
37DBDINC += stateRecord37stdRecords += printfRecord
38DBDINC += stringinRecord38stdRecords += selRecord
39DBDINC += stringoutRecord39stdRecords += seqRecord
40DBDINC += subRecord40stdRecords += stateRecord
41DBDINC += subArrayRecord41stdRecords += stringinRecord
42DBDINC += waveformRecord42stdRecords += stringoutRecord
43stdRecords += subRecord
44stdRecords += subArrayRecord
45stdRecords += waveformRecord
4346
47DBDINC += $(stdRecords)
44DBD += stdRecords.dbd48DBD += stdRecords.dbd
4549
46stdRecords_DBD = $(patsubst %,%.dbd,$(DBDINC))50stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords))
4751
48dbRecStd_SRCS += aaiRecord.c52dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords))
49dbRecStd_SRCS += aaoRecord.c
50dbRecStd_SRCS += aiRecord.c
51dbRecStd_SRCS += aoRecord.c
52dbRecStd_SRCS += aSubRecord.c
53dbRecStd_SRCS += biRecord.c
54dbRecStd_SRCS += boRecord.c
55dbRecStd_SRCS += calcRecord.c
56dbRecStd_SRCS += calcoutRecord.c
57dbRecStd_SRCS += compressRecord.c
58dbRecStd_SRCS += dfanoutRecord.c
59dbRecStd_SRCS += eventRecord.c
60dbRecStd_SRCS += fanoutRecord.c
61dbRecStd_SRCS += histogramRecord.c
62dbRecStd_SRCS += longinRecord.c
63dbRecStd_SRCS += longoutRecord.c
64dbRecStd_SRCS += mbbiRecord.c
65dbRecStd_SRCS += mbbiDirectRecord.c
66dbRecStd_SRCS += mbboRecord.c
67dbRecStd_SRCS += mbboDirectRecord.c
68dbRecStd_SRCS += permissiveRecord.c
69dbRecStd_SRCS += selRecord.c
70dbRecStd_SRCS += seqRecord.c
71dbRecStd_SRCS += stateRecord.c
72dbRecStd_SRCS += stringinRecord.c
73dbRecStd_SRCS += stringoutRecord.c
74dbRecStd_SRCS += subRecord.c
75dbRecStd_SRCS += subArrayRecord.c
76dbRecStd_SRCS += waveformRecord.c
7753
7854
=== modified file 'src/std/rec/RULES'
--- src/std/rec/RULES 2011-02-27 00:24:51 +0000
+++ src/std/rec/RULES 2012-12-10 21:21:25 +0000
@@ -9,7 +9,7 @@
99
10# This is a Makefile fragment, see src/std/Makefile.10# This is a Makefile fragment, see src/std/Makefile.
1111
12$(COMMON_DIR)/stdRecords.dbd:12$(COMMON_DIR)/stdRecords.dbd: ../rec/Makefile
13 $(RM) $@13 $(RM) $@
14 $(PERL) $(TOOLS)/makeIncludeDbd.pl $(stdRecords_DBD) $@14 $(PERL) $(TOOLS)/makeIncludeDbd.pl $(stdRecords_DBD) $@
1515
1616
=== added file 'src/std/rec/lsiRecord.c'
--- src/std/rec/lsiRecord.c 1970-01-01 00:00:00 +0000
+++ src/std/rec/lsiRecord.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,284 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* Long String Input record type */
9/*
10 * Author: Andrew Johnson
11 * Date: 2012-11-27
12 */
13
14#include <stddef.h>
15#include <stdio.h>
16#include <string.h>
17
18#include "dbDefs.h"
19#include "errlog.h"
20#include "alarm.h"
21#include "cantProceed.h"
22#include "dbAccess.h"
23#include "dbEvent.h"
24#include "dbFldTypes.h"
25#include "errMdef.h"
26#include "menuPost.h"
27#include "menuYesNo.h"
28#include "recSup.h"
29#include "recGbl.h"
30#include "special.h"
31#define GEN_SIZE_OFFSET
32#include "lsiRecord.h"
33#undef GEN_SIZE_OFFSET
34#include "epicsExport.h"
35
36static void monitor(lsiRecord *);
37static long readValue(lsiRecord *);
38
39static long init_record(lsiRecord *prec, int pass)
40{
41 lsidset *pdset;
42
43 if (pass == 0) {
44 size_t sizv = prec->sizv;
45
46 if (sizv < 16) {
47 sizv = 16; /* Enforce a minimum size for the VAL field */
48 prec->sizv = sizv;
49 }
50
51 prec->val = callocMustSucceed(1, sizv, "lsi::init_record");
52 prec->len = 0;
53 prec->oval = callocMustSucceed(1, sizv, "lsi::init_record");
54 prec->olen = 0;
55 return 0;
56 }
57
58 dbLoadLink(&prec->siml, DBF_USHORT, &prec->simm);
59
60 pdset = (lsidset *) prec->dset;
61 if (!pdset) {
62 recGblRecordError(S_dev_noDSET, prec, "lsi: init_record");
63 return S_dev_noDSET;
64 }
65
66 /* must have a read_string function */
67 if (pdset->number < 5 || !pdset->read_string) {
68 recGblRecordError(S_dev_missingSup, prec, "lsi: init_record");
69 return S_dev_missingSup;
70 }
71
72 if (pdset->init_record) {
73 long status = pdset->init_record(prec);
74
75 if (status)
76 return status;
77 }
78
79 if (prec->len) {
80 strcpy(prec->oval, prec->val);
81 prec->olen = prec->len;
82 prec->udf = FALSE;
83 }
84
85 return 0;
86}
87
88static long process(lsiRecord *prec)
89{
90 int pact = prec->pact;
91 lsidset *pdset = (lsidset *) prec->dset;
92 long status = 0;
93
94 if (!pdset || !pdset->read_string) {
95 prec->pact = TRUE;
96 recGblRecordError(S_dev_missingSup, prec, "lsi: read_string");
97 return S_dev_missingSup;
98 }
99
100 status = readValue(prec); /* read the new value */
101 if (!pact && prec->pact)
102 return 0;
103
104 prec->pact = TRUE;
105 recGblGetTimeStamp(prec);
106
107 monitor(prec);
108
109 /* Wrap up */
110 recGblFwdLink(prec);
111 prec->pact = FALSE;
112 return status;
113}
114
115static long cvt_dbaddr(DBADDR *paddr)
116{
117 lsiRecord *prec = (lsiRecord *) paddr->precord;
118 int fieldIndex = dbGetFieldIndex(paddr);
119
120 if (fieldIndex == lsiRecordVAL) {
121 paddr->pfield = prec->val;
122 paddr->special = SPC_MOD;
123 }
124 else if (fieldIndex == lsiRecordOVAL) {
125 paddr->pfield = prec->oval;
126 paddr->special = SPC_NOMOD;
127 }
128 else {
129 errlogPrintf("lsiRecord::cvt_dbaddr called for %s.%s\n",
130 prec->name, paddr->pfldDes->name);
131 return -1;
132 }
133
134 paddr->no_elements = 1;
135 paddr->field_type = DBF_STRING;
136 paddr->dbr_field_type = DBF_STRING;
137 paddr->field_size = prec->sizv;
138 return 0;
139}
140
141static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
142{
143 lsiRecord *prec = (lsiRecord *) paddr->precord;
144 int fieldIndex = dbGetFieldIndex(paddr);
145
146 if (fieldIndex == lsiRecordVAL)
147 *no_elements = prec->len;
148 else if (fieldIndex == lsiRecordOVAL)
149 *no_elements = prec->olen;
150 else
151 return -1;
152
153 *offset = 0;
154 return 0;
155}
156
157static long put_array_info(DBADDR *paddr, long nNew)
158{
159 lsiRecord *prec = (lsiRecord *) paddr->precord;
160
161 if (nNew == prec->sizv)
162 --nNew; /* truncated string */
163 prec->val[nNew] = 0; /* ensure data is terminated */
164
165 return 0;
166}
167
168static long special(DBADDR *paddr, int after)
169{
170 lsiRecord *prec = (lsiRecord *) paddr->precord;
171
172 if (!after)
173 return 0;
174
175 /* We set prec->len here and not in put_array_info()
176 * because that does not get called if the put was
177 * done using a DBR_STRING type.
178 */
179 prec->len = strlen(prec->val) + 1;
180 db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG);
181
182 return 0;
183}
184
185static void monitor(lsiRecord *prec)
186{
187 epicsUInt16 events = recGblResetAlarms(prec);
188
189 if (prec->len != prec->olen ||
190 memcmp(prec->oval, prec->val, prec->len)) {
191 events |= DBE_VALUE | DBE_LOG;
192 memcpy(prec->oval, prec->val, prec->len);
193 }
194
195 if (prec->len != prec->olen) {
196 prec->olen = prec->len;
197 db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG);
198 }
199
200 if (prec->mpst == menuPost_Always)
201 events |= DBE_VALUE;
202 if (prec->apst == menuPost_Always)
203 events |= DBE_LOG;
204
205 if (events)
206 db_post_events(prec, prec->val, events);
207}
208
209static long readValue(lsiRecord *prec)
210{
211 long status;
212 lsidset *pdset = (lsidset *) prec->dset;
213
214 if (prec->pact)
215 goto read;
216
217 status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0);
218 if (status)
219 return status;
220
221 switch (prec->simm) {
222 case menuYesNoNO:
223read:
224 status = pdset->read_string(prec);
225 break;
226
227 case menuYesNoYES:
228 recGblSetSevr(prec, SIMM_ALARM, prec->sims);
229 status = dbGetLinkLS(&prec->siol, prec->val, prec->sizv, &prec->len);
230 break;
231
232 default:
233 recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
234 status = -1;
235 }
236
237 if (!status)
238 prec->udf = FALSE;
239
240 return status;
241}
242
243
244/* Create Record Support Entry Table*/
245
246#define report NULL
247#define initialize NULL
248/* init_record */
249/* process */
250/* special */
251#define get_value NULL
252/* cvt_dbaddr */
253/* get_array_info */
254/* put_array_info */
255#define get_units NULL
256#define get_precision NULL
257#define get_enum_str NULL
258#define get_enum_strs NULL
259#define put_enum_str NULL
260#define get_graphic_double NULL
261#define get_control_double NULL
262#define get_alarm_double NULL
263
264rset lsiRSET = {
265 RSETNUMBER,
266 report,
267 initialize,
268 init_record,
269 process,
270 special,
271 get_value,
272 cvt_dbaddr,
273 get_array_info,
274 put_array_info,
275 get_units,
276 get_precision,
277 get_enum_str,
278 get_enum_strs,
279 put_enum_str,
280 get_graphic_double,
281 get_control_double,
282 get_alarm_double
283};
284epicsExportAddress(rset, lsiRSET);
0285
=== added file 'src/std/rec/lsiRecord.dbd'
--- src/std/rec/lsiRecord.dbd 1970-01-01 00:00:00 +0000
+++ src/std/rec/lsiRecord.dbd 2012-12-10 21:21:25 +0000
@@ -0,0 +1,88 @@
1#*************************************************************************
2# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3# National Laboratory.
4# EPICS BASE is distributed subject to a Software License Agreement found
5# in file LICENSE that is included with this distribution.
6#*************************************************************************
7
8recordtype(lsi) {
9 include "dbCommon.dbd"
10 %#include "devSup.h"
11 %
12 %/* Declare Device Support Entry Table */
13 %typedef struct lsidset {
14 % long number;
15 % DEVSUPFUN report;
16 % DEVSUPFUN init;
17 % DEVSUPFUN init_record;
18 % DEVSUPFUN get_ioint_info;
19 % DEVSUPFUN read_string;
20 %} lsidset;
21 %
22 field(VAL,DBF_NOACCESS) {
23 prompt("Current Value")
24 asl(ASL0)
25 pp(TRUE)
26 special(SPC_DBADDR)
27 extra("char *val")
28 }
29 field(OVAL,DBF_NOACCESS) {
30 prompt("Old Value")
31 special(SPC_DBADDR)
32 interest(3)
33 extra("char *oval")
34 }
35 field(SIZV,DBF_USHORT) {
36 prompt("Size of buffers")
37 promptgroup(GUI_OUTPUT)
38 special(SPC_NOMOD)
39 interest(1)
40 initial("41")
41 }
42 field(LEN,DBF_ULONG) {
43 prompt("Length of VAL")
44 special(SPC_NOMOD)
45 }
46 field(OLEN,DBF_ULONG) {
47 prompt("Length of OVAL")
48 special(SPC_NOMOD)
49 }
50 field(INP,DBF_INLINK) {
51 prompt("Input Specification")
52 promptgroup(GUI_INPUTS)
53 interest(1)
54 }
55 field(MPST,DBF_MENU) {
56 prompt("Post Value Monitors")
57 promptgroup(GUI_DISPLAY)
58 interest(1)
59 menu(menuPost)
60 }
61 field(APST,DBF_MENU) {
62 prompt("Post Archive Monitors")
63 promptgroup(GUI_DISPLAY)
64 interest(1)
65 menu(menuPost)
66 }
67 field(SIML,DBF_INLINK) {
68 prompt("Simulation Mode Link")
69 promptgroup(GUI_INPUTS)
70 interest(2)
71 }
72 field(SIMM,DBF_MENU) {
73 prompt("Simulation Mode")
74 interest(2)
75 menu(menuYesNo)
76 }
77 field(SIMS,DBF_MENU) {
78 prompt("Simulation Mode Severity")
79 promptgroup(GUI_INPUTS)
80 interest(2)
81 menu(menuAlarmSevr)
82 }
83 field(SIOL,DBF_INLINK) {
84 prompt("Sim Input Specifctn")
85 promptgroup(GUI_INPUTS)
86 interest(2)
87 }
88}
089
=== added file 'src/std/rec/lsoRecord.c'
--- src/std/rec/lsoRecord.c 1970-01-01 00:00:00 +0000
+++ src/std/rec/lsoRecord.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,322 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* Long String Output record type */
9/*
10 * Author: Andrew Johnson
11 * Date: 2012-11-28
12 */
13
14
15#include <stddef.h>
16#include <stdio.h>
17#include <string.h>
18
19#include "dbDefs.h"
20#include "errlog.h"
21#include "alarm.h"
22#include "cantProceed.h"
23#include "dbAccess.h"
24#include "dbEvent.h"
25#include "dbFldTypes.h"
26#include "devSup.h"
27#include "errMdef.h"
28#include "menuIvoa.h"
29#include "menuOmsl.h"
30#include "menuPost.h"
31#include "menuYesNo.h"
32#include "recSup.h"
33#include "recGbl.h"
34#include "special.h"
35#define GEN_SIZE_OFFSET
36#include "lsoRecord.h"
37#undef GEN_SIZE_OFFSET
38#include "epicsExport.h"
39
40static void monitor(lsoRecord *);
41static long writeValue(lsoRecord *);
42
43static long init_record(lsoRecord *prec, int pass)
44{
45 lsodset *pdset;
46
47 if (pass == 0) {
48 size_t sizv = prec->sizv;
49
50 if (sizv < 16) {
51 sizv = 16; /* Enforce a minimum size for the VAL field */
52 prec->sizv = sizv;
53 }
54
55 prec->val = callocMustSucceed(1, sizv, "lso::init_record");
56 prec->len = 0;
57 prec->oval = callocMustSucceed(1, sizv, "lso::init_record");
58 prec->olen = 0;
59 return 0;
60 }
61
62 dbLoadLink(&prec->siml, DBF_USHORT, &prec->simm);
63
64 pdset = (lsodset *) prec->dset;
65 if (!pdset) {
66 recGblRecordError(S_dev_noDSET, prec, "lso: init_record");
67 return S_dev_noDSET;
68 }
69
70 /* must have a write_string function defined */
71 if (pdset->number < 5 || !pdset->write_string) {
72 recGblRecordError(S_dev_missingSup, prec, "lso: init_record");
73 return S_dev_missingSup;
74 }
75
76 dbLoadLinkLS(&prec->dol, prec->val, prec->sizv, &prec->len);
77
78 if (pdset->init_record) {
79 long status = pdset->init_record(prec);
80
81 if (status)
82 return status;
83 }
84
85 if (prec->len) {
86 strcpy(prec->oval, prec->val);
87 prec->olen = prec->len;
88 prec->udf = FALSE;
89 }
90
91 return 0;
92}
93
94static long process(lsoRecord *prec)
95{
96 int pact = prec->pact;
97 lsodset *pdset = (lsodset *) prec->dset;
98 long status = 0;
99
100 if (!pdset || !pdset->write_string) {
101 prec->pact = TRUE;
102 recGblRecordError(S_dev_missingSup, prec, "lso: write_string");
103 return S_dev_missingSup;
104 }
105
106 if (!pact && prec->omsl == menuOmslclosed_loop)
107 if (!dbGetLinkLS(&prec->dol, prec->val, prec->sizv, &prec->len))
108 prec->udf = FALSE;
109
110 if (prec->udf)
111 recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
112
113 if (prec->nsev < INVALID_ALARM )
114 status = writeValue(prec); /* write the new value */
115 else {
116 switch (prec->ivoa) {
117 case menuIvoaContinue_normally:
118 status = writeValue(prec); /* write the new value */
119 break;
120
121 case menuIvoaDon_t_drive_outputs:
122 break;
123
124 case menuIvoaSet_output_to_IVOV:
125 if (!prec->pact) {
126 size_t size = prec->sizv - 1;
127
128 strncpy(prec->val, prec->ivov, size);
129 prec->val[size] = 0;
130 prec->len = strlen(prec->val) + 1;
131 }
132 status = writeValue(prec); /* write the new value */
133 break;
134
135 default:
136 status = -1;
137 recGblRecordError(S_db_badField, prec,
138 "lso:process Bad IVOA choice");
139 }
140 }
141
142 /* Asynchronous if device support set pact */
143 if (!pact && prec->pact)
144 return status;
145
146 prec->pact = TRUE;
147 recGblGetTimeStamp(prec);
148
149 monitor(prec);
150
151 /* Wrap up */
152 recGblFwdLink(prec);
153 prec->pact = FALSE;
154 return status;
155}
156
157static long cvt_dbaddr(DBADDR *paddr)
158{
159 lsoRecord *prec = (lsoRecord *) paddr->precord;
160 int fieldIndex = dbGetFieldIndex(paddr);
161
162 if (fieldIndex == lsoRecordVAL) {
163 paddr->pfield = prec->val;
164 paddr->special = SPC_MOD;
165 }
166 else if (fieldIndex == lsoRecordOVAL) {
167 paddr->pfield = prec->oval;
168 paddr->special = SPC_NOMOD;
169 }
170 else {
171 errlogPrintf("lsoRecord::cvt_dbaddr called for %s.%s\n",
172 prec->name, paddr->pfldDes->name);
173 return -1;
174 }
175
176 paddr->no_elements = 1;
177 paddr->field_type = DBF_STRING;
178 paddr->dbr_field_type = DBF_STRING;
179 paddr->field_size = prec->sizv;
180 return 0;
181}
182
183static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
184{
185 lsoRecord *prec = (lsoRecord *) paddr->precord;
186 int fieldIndex = dbGetFieldIndex(paddr);
187
188 if (fieldIndex == lsoRecordVAL)
189 *no_elements = prec->len;
190 else if (fieldIndex == lsoRecordOVAL)
191 *no_elements = prec->olen;
192 else
193 return -1;
194
195 *offset = 0;
196 return 0;
197}
198
199static long put_array_info(DBADDR *paddr, long nNew)
200{
201 lsoRecord *prec = (lsoRecord *) paddr->precord;
202
203 if (nNew == prec->sizv)
204 --nNew; /* truncated string */
205 prec->val[nNew] = 0; /* ensure data is terminated */
206
207 return 0;
208}
209
210static long special(DBADDR *paddr, int after)
211{
212 lsoRecord *prec = (lsoRecord *) paddr->precord;
213
214 if (!after)
215 return 0;
216
217 /* We set prec->len here and not in put_array_info()
218 * because that does not get called if the put was
219 * done using a DBR_STRING type.
220 */
221 prec->len = strlen(prec->val) + 1;
222 db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG);
223
224 return 0;
225}
226
227static void monitor(lsoRecord *prec)
228{
229 epicsUInt16 events = recGblResetAlarms(prec);
230
231 if (prec->len != prec->olen ||
232 memcmp(prec->oval, prec->val, prec->len)) {
233 events |= DBE_VALUE | DBE_LOG;
234 memcpy(prec->oval, prec->val, prec->len);
235 }
236
237 if (prec->len != prec->olen) {
238 prec->olen = prec->len;
239 db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG);
240 }
241
242 if (prec->mpst == menuPost_Always)
243 events |= DBE_VALUE;
244 if (prec->apst == menuPost_Always)
245 events |= DBE_LOG;
246
247 if (events)
248 db_post_events(prec, prec->val, events);
249}
250
251static long writeValue(lsoRecord *prec)
252{
253 long status;
254 lsodset *pdset = (lsodset *) prec->dset;
255
256 if (prec->pact)
257 goto write;
258
259 status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0);
260 if (status)
261 return(status);
262
263 switch (prec->simm) {
264 case menuYesNoNO:
265write:
266 status = pdset->write_string(prec);
267 break;
268
269 case menuYesNoYES:
270 recGblSetSevr(prec, SIMM_ALARM, prec->sims);
271 status = dbPutLink(&prec->siol,DBR_STRING, prec->val,1);
272 break;
273
274 default:
275 recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
276 status = -1;
277 }
278
279 return status;
280}
281
282/* Create Record Support Entry Table*/
283
284#define report NULL
285#define initialize NULL
286/* init_record */
287/* process */
288/* special */
289#define get_value NULL
290/* cvt_dbaddr */
291/* get_array_info */
292/* put_array_info */
293#define get_units NULL
294#define get_precision NULL
295#define get_enum_str NULL
296#define get_enum_strs NULL
297#define put_enum_str NULL
298#define get_graphic_double NULL
299#define get_control_double NULL
300#define get_alarm_double NULL
301
302rset lsoRSET = {
303 RSETNUMBER,
304 report,
305 initialize,
306 init_record,
307 process,
308 special,
309 get_value,
310 cvt_dbaddr,
311 get_array_info,
312 put_array_info,
313 get_units,
314 get_precision,
315 get_enum_str,
316 get_enum_strs,
317 put_enum_str,
318 get_graphic_double,
319 get_control_double,
320 get_alarm_double
321};
322epicsExportAddress(rset, lsoRSET);
0323
=== added file 'src/std/rec/lsoRecord.dbd'
--- src/std/rec/lsoRecord.dbd 1970-01-01 00:00:00 +0000
+++ src/std/rec/lsoRecord.dbd 2012-12-10 21:21:25 +0000
@@ -0,0 +1,112 @@
1#*************************************************************************
2# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3# National Laboratory.
4# EPICS BASE is distributed subject to a Software License Agreement found
5# in file LICENSE that is included with this distribution.
6#*************************************************************************
7
8recordtype(lso) {
9 include "dbCommon.dbd"
10 %#include "devSup.h"
11 %
12 %/* Declare Device Support Entry Table */
13 %typedef struct lsodset {
14 % long number;
15 % DEVSUPFUN report;
16 % DEVSUPFUN init;
17 % DEVSUPFUN init_record;
18 % DEVSUPFUN get_ioint_info;
19 % DEVSUPFUN write_string;
20 %} lsodset;
21 %
22 field(VAL,DBF_NOACCESS) {
23 prompt("Current Value")
24 asl(ASL0)
25 pp(TRUE)
26 special(SPC_DBADDR)
27 extra("char *val")
28 }
29 field(OVAL,DBF_NOACCESS) {
30 prompt("Previous Value")
31 special(SPC_DBADDR)
32 interest(3)
33 extra("char *oval")
34 }
35 field(SIZV,DBF_USHORT) {
36 prompt("Size of buffers")
37 promptgroup(GUI_OUTPUT)
38 special(SPC_NOMOD)
39 interest(1)
40 initial("41")
41 }
42 field(LEN,DBF_ULONG) {
43 prompt("Length of VAL")
44 special(SPC_NOMOD)
45 }
46 field(OLEN,DBF_ULONG) {
47 prompt("Length of OVAL")
48 special(SPC_NOMOD)
49 interest(3)
50 }
51 field(DOL,DBF_INLINK) {
52 prompt("Desired Output Link")
53 promptgroup(GUI_OUTPUT)
54 interest(1)
55 }
56 field(IVOA,DBF_MENU) {
57 prompt("INVALID Output Action")
58 promptgroup(GUI_OUTPUT)
59 interest(2)
60 menu(menuIvoa)
61 }
62 field(IVOV,DBF_STRING) {
63 prompt("INVALID Output Value")
64 promptgroup(GUI_OUTPUT)
65 interest(2)
66 size(40)
67 }
68 field(OMSL,DBF_MENU) {
69 prompt("Output Mode Select")
70 promptgroup(GUI_OUTPUT)
71 interest(1)
72 menu(menuOmsl)
73 }
74 field(OUT,DBF_OUTLINK) {
75 prompt("Output Specification")
76 promptgroup(GUI_OUTPUT)
77 interest(1)
78 }
79 field(MPST,DBF_MENU) {
80 prompt("Post Value Monitors")
81 promptgroup(GUI_DISPLAY)
82 interest(1)
83 menu(menuPost)
84 }
85 field(APST,DBF_MENU) {
86 prompt("Post Archive Monitors")
87 promptgroup(GUI_DISPLAY)
88 interest(1)
89 menu(menuPost)
90 }
91 field(SIML,DBF_INLINK) {
92 prompt("Sim Mode link")
93 promptgroup(GUI_INPUTS)
94 interest(1)
95 }
96 field(SIMM,DBF_MENU) {
97 prompt("Simulation Mode")
98 interest(1)
99 menu(menuYesNo)
100 }
101 field(SIMS,DBF_MENU) {
102 prompt("Sim mode Alarm Svrty")
103 promptgroup(GUI_INPUTS)
104 interest(2)
105 menu(menuAlarmSevr)
106 }
107 field(SIOL,DBF_OUTLINK) {
108 prompt("Sim Output Specifctn")
109 promptgroup(GUI_INPUTS)
110 interest(1)
111 }
112}
0113
=== added file 'src/std/rec/printfRecord.c'
--- src/std/rec/printfRecord.c 1970-01-01 00:00:00 +0000
+++ src/std/rec/printfRecord.c 2012-12-10 21:21:25 +0000
@@ -0,0 +1,438 @@
1/*************************************************************************\
2* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* EPICS BASE is distributed subject to a Software License Agreement found
5* in file LICENSE that is included with this distribution.
6\*************************************************************************/
7
8/* Printf record type */
9/*
10 * Author: Andrew Johnson
11 * Date: 2012-09-18
12 */
13
14#include <stddef.h>
15#include <string.h>
16
17#include "dbDefs.h"
18#include "errlog.h"
19#include "alarm.h"
20#include "cantProceed.h"
21#include "dbAccess.h"
22#include "dbEvent.h"
23#include "dbFldTypes.h"
24#include "epicsMath.h"
25#include "epicsStdio.h"
26#include "errMdef.h"
27#include "recSup.h"
28#include "recGbl.h"
29#include "special.h"
30#define GEN_SIZE_OFFSET
31#include "printfRecord.h"
32#undef GEN_SIZE_OFFSET
33#include "epicsExport.h"
34
35
36/* Flag bits */
37#define F_CHAR 1
38#define F_SHORT 2
39#define F_LONG 4
40#define F_LEFT 8
41#define F_BADFMT 0x10
42#define F_BADLNK 0x20
43#define F_BAD (F_BADFMT | F_BADLNK)
44
45#define GET_PRINT(VALTYPE, DBRTYPE) \
46 VALTYPE val; \
47 int ok; \
48\
49 if (plink->type == CONSTANT) \
50 ok = recGblInitConstantLink(plink++, DBRTYPE, &val); \
51 else \
52 ok = ! dbGetLink(plink++, DBRTYPE, &val, 0, 0); \
53 if (ok) \
54 added = epicsSnprintf(pval, vspace + 1, format, val); \
55 else \
56 flags |= F_BADLNK
57
58static void doPrintf(printfRecord *prec)
59{
60 const char *pfmt = prec->fmt;
61 DBLINK *plink = &prec->inp0;
62 int linkn = 0;
63 char *pval = prec->val;
64 int vspace = prec->sizv - 1;
65 int ch;
66
67 while (vspace > 0 && (ch = *pfmt++)) {
68 if (ch != '%') {
69 /* Copy literal strings directly into prec->val */
70 *pval++ = ch;
71 --vspace;
72 }
73 else {
74 char format[20];
75 char *pformat = format;
76 int width = 0;
77 int precision = 0;
78 int *pnum = &width;
79 int flags = 0;
80 int added = 0;
81 int cont = 1;
82
83 /* The format directive parsing here is not comprehensive,
84 * in most cases we just copy each directive into format[]
85 * and get epicsSnprintf() do all the work. We do replace
86 * all variable-length field width or precision '*' chars
87 * with an integer read from the next input link, and we
88 * also convert %ls (long string) directives ourself, so
89 * we need to know the width, precision and justification.
90 */
91
92 *pformat++ = ch; /* '%' */
93 while (cont && (ch = *pfmt++)) {
94 *pformat++ = ch;
95 switch (ch) {
96 case '+': case ' ': case '#':
97 break;
98 case '-':
99 flags |= F_LEFT;
100 break;
101 case '.':
102 pnum = &precision;
103 break;
104 case '0': case '1': case '2': case '3': case '4':
105 case '5': case '6': case '7': case '8': case '9':
106 *pnum = *pnum * 10 + ch - '0';
107 break;
108 case '*':
109 if (*pnum) {
110 flags |= F_BADFMT;
111 }
112 else if (linkn++ < PRINTF_NLINKS) {
113 epicsInt16 i;
114 int ok;
115
116 if (plink->type == CONSTANT)
117 ok = recGblInitConstantLink(plink++, DBR_SHORT, &i);
118 else
119 ok = ! dbGetLink(plink++, DBR_SHORT, &i, 0, 0);
120 if (ok) {
121 *pnum = i;
122 added = epicsSnprintf(--pformat, 6, "%d", i);
123 pformat += added;
124 }
125 else /* No more LNKn fields */
126 flags |= F_BADLNK;
127 }
128 else
129 flags |= F_BADLNK;
130 break;
131 case 'h':
132 if (flags & F_SHORT)
133 flags = (flags & ~F_SHORT) | F_CHAR;
134 else
135 flags |= F_SHORT;
136 break;
137 case 'l':
138 flags |= F_LONG;
139 break;
140 default:
141 if (strchr("diouxXeEfFgGcs%", ch) == NULL)
142 flags |= F_BADFMT;
143 cont = 0;
144 break;
145 }
146 }
147 if (!ch) /* End of format string */
148 break;
149
150 if (flags & F_BAD)
151 goto bad_format;
152
153 *pformat = 0; /* Terminate our format string */
154
155 if (width < 0) {
156 width = -width;
157 flags |= F_LEFT;
158 }
159 if (precision < 0)
160 precision = 0;
161
162 if (ch == '%') {
163 added = epicsSnprintf(pval, vspace + 1, format);
164 }
165 else if (linkn++ >= PRINTF_NLINKS) {
166 /* No more LNKn fields */
167 flags |= F_BADLNK;
168 }
169 else
170 switch (ch) { /* Conversion character */
171 case 'c': case 'd': case 'i':
172 if (ch == 'c' || flags & F_CHAR) {
173 GET_PRINT(epicsInt8, DBR_CHAR);
174 }
175 else if (flags & F_SHORT) {
176 GET_PRINT(epicsInt16, DBR_SHORT);
177 }
178 else { /* F_LONG has no real effect */
179 GET_PRINT(epicsInt32, DBR_LONG);
180 }
181 break;
182
183 case 'o': case 'x': case 'X': case 'u':
184 if (flags & F_CHAR) {
185 GET_PRINT(epicsUInt8, DBR_UCHAR);
186 }
187 else if (flags & F_SHORT) {
188 GET_PRINT(epicsUInt16, DBR_USHORT);
189 }
190 else { /* F_LONG has no real effect */
191 GET_PRINT(epicsUInt32, DBR_ULONG);
192 }
193 break;
194
195 case 'e': case 'E':
196 case 'f': case 'F':
197 case 'g': case 'G':
198 if (flags & F_SHORT) {
199 GET_PRINT(epicsFloat32, DBR_FLOAT);
200 }
201 else {
202 GET_PRINT(epicsFloat64, DBR_DOUBLE);
203 }
204 break;
205
206 case 's':
207 if (flags & F_LONG && plink->type != CONSTANT) {
208 long n = vspace + 1;
209
210 if (precision && n > precision)
211 n = precision + 1;
212 /* If set, precision is the maximum number of
213 * characters to be printed from the string.
214 * It does not limit the field width however.
215 */
216 if (dbGetLink(plink++, DBR_CHAR, pval, 0, &n))
217 flags |= F_BADLNK;
218 else {
219 int padding;
220
221 /* Terminate string and measure its length */
222 pval[n] = 0;
223 added = strlen(pval);
224 padding = width - added;
225
226 if (padding > 0) {
227 if (flags & F_LEFT) {
228 /* add spaces on RHS */
229 if (width > vspace)
230 padding = vspace - added;
231 memset(pval + added, ' ', padding);
232 }
233 else {
234 /* insert spaces on LHS */
235 int trunc = width - vspace;
236
237 if (trunc < added) {
238 added -= trunc;
239 memmove(pval + padding, pval, added);
240 }
241 else {
242 padding = vspace;
243 added = 0;
244 }
245 memset(pval, ' ', padding);
246 }
247 added += padding;
248 }
249 }
250 }
251 else {
252 char val[MAX_STRING_SIZE];
253 int ok;
254
255 if (plink->type == CONSTANT)
256 ok = recGblInitConstantLink(plink++, DBR_STRING, val);
257 else
258 ok = ! dbGetLink(plink++, DBR_STRING, val, 0, 0);
259 if (ok)
260 added = epicsSnprintf(pval, vspace + 1, format, val);
261 else
262 flags |= F_BADLNK;
263 }
264 break;
265
266 default:
267 errlogPrintf("printfRecord: Unexpected conversion '%s'\n",
268 format);
269 flags |= F_BADFMT;
270 break;
271 }
272
273 if (flags & F_BAD) {
274 bad_format:
275 added = epicsSnprintf(pval, vspace + 1, "%s",
276 flags & F_BADLNK ? prec->ivls : format);
277 }
278
279 if (added <= vspace) {
280 pval += added;
281 vspace -= added;
282 }
283 else {
284 /* Output was truncated */
285 pval += vspace;
286 vspace = 0;
287 }
288 }
289 }
290 *pval++ = 0; /* Terminate the VAL string */
291 prec->len = pval - prec->val;
292}
293
294
295static long init_record(printfRecord *prec, int pass)
296{
297 printfdset *pdset;
298
299 if (pass == 0) {
300 size_t sizv = prec->sizv;
301
302 if (sizv < 16) {
303 sizv = 16; /* Enforce a minimum size for the VAL field */
304 prec->sizv = sizv;
305 }
306
307 prec->val = callocMustSucceed(1, sizv, "printf::init_record");
308 prec->len = 0;
309 return 0;
310 }
311
312 pdset = (printfdset *) prec->dset;
313 if (!pdset)
314 return 0; /* Device support is optional */
315
316 if (pdset->number < 5) {
317 recGblRecordError(S_dev_missingSup, prec, "printf::init_record");
318 return S_dev_missingSup;
319 }
320
321 if (pdset->init_record) {
322 long status = pdset->init_record(prec);
323 if (status)
324 return status;
325 }
326
327 return 0;
328}
329
330static long process(printfRecord *prec)
331{
332 int pact = prec->pact;
333 printfdset *pdset;
334 long status = 0;
335 epicsUInt16 events;
336
337 if (!pact) {
338 doPrintf(prec);
339
340 prec->udf = FALSE;
341 recGblGetTimeStamp(prec);
342 }
343
344 /* Call device support */
345 pdset = (printfdset *) prec->dset;
346 if (pdset &&
347 pdset->number >= 5 &&
348 pdset->write_string) {
349 status = pdset->write_string(prec);
350
351 /* Asynchronous if device support set pact */
352 if (!pact && prec->pact)
353 return status;
354 }
355
356 prec->pact = TRUE;
357
358 /* Post monitor */
359 events = recGblResetAlarms(prec);
360 db_post_events(prec, prec->val, events | DBE_VALUE | DBE_LOG);
361 db_post_events(prec, &prec->len, events | DBE_VALUE | DBE_LOG);
362
363 /* Wrap up */
364 recGblFwdLink(prec);
365 prec->pact = FALSE;
366 return status;
367}
368
369static long cvt_dbaddr(DBADDR *paddr)
370{
371 printfRecord *prec = (printfRecord *)paddr->precord;
372 int fieldIndex = dbGetFieldIndex(paddr);
373
374 if (fieldIndex == printfRecordVAL) {
375 paddr->pfield = prec->val;
376 paddr->no_elements = 1;
377 paddr->field_type = DBF_STRING;
378 paddr->dbr_field_type = DBF_STRING;
379 paddr->field_size = prec->sizv;
380 }
381 else
382 errlogPrintf("printfRecord::cvt_dbaddr called for %s.%s\n",
383 prec->name, paddr->pfldDes->name);
384 return 0;
385}
386
387static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
388{
389 printfRecord *prec = (printfRecord *) paddr->precord;
390
391 *no_elements = prec->len;
392 *offset = 0;
393 return 0;
394}
395
396
397/* Create Record Support Entry Table */
398
399#define report NULL
400#define initialize NULL
401/* init_record */
402/* process */
403#define special NULL
404#define get_value NULL
405/* cvt_dbaddr */
406/* get_array_info */
407#define put_array_info NULL
408#define get_units NULL
409#define get_precision NULL
410#define get_enum_str NULL
411#define get_enum_strs NULL
412#define put_enum_str NULL
413#define get_graphic_double NULL
414#define get_control_double NULL
415#define get_alarm_double NULL
416
417rset printfRSET = {
418 RSETNUMBER,
419 report,
420 initialize,
421 init_record,
422 process,
423 special,
424 get_value,
425 cvt_dbaddr,
426 get_array_info,
427 put_array_info,
428 get_units,
429 get_precision,
430 get_enum_str,
431 get_enum_strs,
432 put_enum_str,
433 get_graphic_double,
434 get_control_double,
435 get_alarm_double
436};
437epicsExportAddress(rset, printfRSET);
438
0439
=== added file 'src/std/rec/printfRecord.dbd'
--- src/std/rec/printfRecord.dbd 1970-01-01 00:00:00 +0000
+++ src/std/rec/printfRecord.dbd 2012-12-10 21:21:25 +0000
@@ -0,0 +1,109 @@
1#*************************************************************************
2# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
3# National Laboratory.
4# EPICS BASE is distributed subject to a Software License Agreement found
5# in file LICENSE that is included with this distribution.
6#*************************************************************************
7
8recordtype(printf) {
9 include "dbCommon.dbd"
10 %#include "devSup.h"
11 %
12 %/* Declare Device Support Entry Table */
13 %typedef struct printfdset {
14 % long number;
15 % DEVSUPFUN report;
16 % DEVSUPFUN init;
17 % DEVSUPFUN init_record;
18 % DEVSUPFUN get_ioint_info;
19 % DEVSUPFUN write_string;
20 %} printfdset;
21 %
22 field(VAL,DBF_NOACCESS) {
23 prompt("Result")
24 asl(ASL0)
25 pp(TRUE)
26 special(SPC_DBADDR)
27 extra("char *val")
28 }
29 field(SIZV,DBF_USHORT) {
30 prompt("Size of VAL buffer")
31 promptgroup(GUI_OUTPUT)
32 special(SPC_NOMOD)
33 interest(1)
34 initial("41")
35 }
36 field(LEN,DBF_ULONG) {
37 prompt("Length of VAL")
38 special(SPC_NOMOD)
39 }
40 field(OUT,DBF_OUTLINK) {
41 prompt("Output Specification")
42 promptgroup(GUI_OUTPUT)
43 interest(1)
44 }
45 field(FMT,DBF_STRING) {
46 prompt("Format String")
47 promptgroup(GUI_CALC)
48 pp(TRUE)
49 size(81)
50 }
51 field(IVLS,DBF_STRING) {
52 prompt("Invalid Link String")
53 promptgroup(GUI_CALC)
54 size(16)
55 initial("LNK")
56 }
57 field(INP0,DBF_INLINK) {
58 prompt("Input 0")
59 promptgroup(GUI_INPUTS)
60 interest(1)
61 }
62 field(INP1,DBF_INLINK) {
63 prompt("Input 1")
64 promptgroup(GUI_INPUTS)
65 interest(1)
66 }
67 field(INP2,DBF_INLINK) {
68 prompt("Input 2")
69 promptgroup(GUI_INPUTS)
70 interest(1)
71 }
72 field(INP3,DBF_INLINK) {
73 prompt("Input 3")
74 promptgroup(GUI_INPUTS)
75 interest(1)
76 }
77 field(INP4,DBF_INLINK) {
78 prompt("Input 4")
79 promptgroup(GUI_INPUTS)
80 interest(1)
81 }
82 field(INP5,DBF_INLINK) {
83 prompt("Input 5")
84 promptgroup(GUI_INPUTS)
85 interest(1)
86 }
87 field(INP6,DBF_INLINK) {
88 prompt("Input 6")
89 promptgroup(GUI_INPUTS)
90 interest(1)
91 }
92 field(INP7,DBF_INLINK) {
93 prompt("Input 7")
94 promptgroup(GUI_INPUTS)
95 interest(1)
96 }
97 field(INP8,DBF_INLINK) {
98 prompt("Input 8")
99 promptgroup(GUI_INPUTS)
100 interest(1)
101 }
102 field(INP9,DBF_INLINK) {
103 prompt("Input 9")
104 promptgroup(GUI_INPUTS)
105 interest(1)
106 }
107 %/* Number of INPx fields defined */
108 %#define PRINTF_NLINKS 10
109}

Subscribers

People subscribed via source and target branches

to all changes: