Merge lp:~epics-core/epics-base/printf-record into lp:~epics-core/epics-base/3.15
- printf-record
- Merge into 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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Approve | ||
Review via email: mp+139098@code.launchpad.net |
Commit message
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.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/ioc/db/Makefile' | |||
2 | --- src/ioc/db/Makefile 2012-06-21 20:27:32 +0000 | |||
3 | +++ src/ioc/db/Makefile 2012-12-10 21:21:25 +0000 | |||
4 | @@ -47,6 +47,7 @@ | |||
5 | 47 | menuGlobal_DBD += menuIvoa.dbd | 47 | menuGlobal_DBD += menuIvoa.dbd |
6 | 48 | menuGlobal_DBD += menuOmsl.dbd | 48 | menuGlobal_DBD += menuOmsl.dbd |
7 | 49 | menuGlobal_DBD += menuPini.dbd | 49 | menuGlobal_DBD += menuPini.dbd |
8 | 50 | menuGlobal_DBD += menuPost.dbd | ||
9 | 50 | menuGlobal_DBD += menuPriority.dbd | 51 | menuGlobal_DBD += menuPriority.dbd |
10 | 51 | menuGlobal_DBD += menuScan.dbd | 52 | menuGlobal_DBD += menuScan.dbd |
11 | 52 | menuGlobal_DBD += menuYesNo.dbd | 53 | menuGlobal_DBD += menuYesNo.dbd |
12 | 53 | 54 | ||
13 | === modified file 'src/ioc/db/dbAccess.c' | |||
14 | --- src/ioc/db/dbAccess.c 2012-10-29 06:20:56 +0000 | |||
15 | +++ src/ioc/db/dbAccess.c 2012-12-10 21:21:25 +0000 | |||
16 | @@ -583,10 +583,8 @@ | |||
17 | 583 | { | 583 | { |
18 | 584 | DBENTRY dbEntry; | 584 | DBENTRY dbEntry; |
19 | 585 | dbFldDes *pflddes; | 585 | dbFldDes *pflddes; |
20 | 586 | struct rset *prset; | ||
21 | 587 | long status = 0; | 586 | long status = 0; |
24 | 588 | long no_elements = 1; | 587 | short dbfType; |
23 | 589 | short dbfType, dbrType, field_size; | ||
25 | 590 | 588 | ||
26 | 591 | if (!pname || !*pname || !pdbbase) | 589 | if (!pname || !*pname || !pdbbase) |
27 | 592 | return S_db_notFound; | 590 | return S_db_notFound; |
28 | @@ -601,48 +599,49 @@ | |||
29 | 601 | status = dbGetAttributePart(&dbEntry, &pname); | 599 | status = dbGetAttributePart(&dbEntry, &pname); |
30 | 602 | if (status) goto finish; | 600 | if (status) goto finish; |
31 | 603 | 601 | ||
32 | 602 | pflddes = dbEntry.pflddes; | ||
33 | 603 | dbfType = pflddes->field_type; | ||
34 | 604 | |||
35 | 604 | paddr->precord = dbEntry.precnode->precord; | 605 | paddr->precord = dbEntry.precnode->precord; |
36 | 605 | paddr->pfield = dbEntry.pfield; | 606 | paddr->pfield = dbEntry.pfield; |
43 | 606 | pflddes = dbEntry.pflddes; | 607 | paddr->pfldDes = pflddes; |
44 | 607 | 608 | paddr->no_elements = 1; | |
45 | 608 | dbfType = pflddes->field_type; | 609 | paddr->field_type = dbfType; |
46 | 609 | dbrType = mapDBFToDBR[dbfType]; | 610 | paddr->field_size = pflddes->size; |
47 | 610 | field_size = pflddes->size; | 611 | paddr->special = pflddes->special; |
48 | 611 | 612 | paddr->dbr_field_type = mapDBFToDBR[dbfType]; | |
49 | 613 | |||
50 | 614 | if (paddr->special == SPC_DBADDR) { | ||
51 | 615 | struct rset *prset = dbGetRset(paddr); | ||
52 | 616 | |||
53 | 617 | /* Let record type modify paddr */ | ||
54 | 618 | if (prset && prset->cvt_dbaddr) { | ||
55 | 619 | status = prset->cvt_dbaddr(paddr); | ||
56 | 620 | if (status) | ||
57 | 621 | goto finish; | ||
58 | 622 | dbfType = paddr->field_type; | ||
59 | 623 | } | ||
60 | 624 | } | ||
61 | 625 | |||
62 | 626 | /* Handle field modifiers */ | ||
63 | 612 | if (*pname++ == '$') { | 627 | if (*pname++ == '$') { |
64 | 613 | /* Some field types can be accessed as char arrays */ | 628 | /* Some field types can be accessed as char arrays */ |
65 | 614 | if (dbfType == DBF_STRING) { | 629 | if (dbfType == DBF_STRING) { |
70 | 615 | dbfType = DBF_CHAR; | 630 | paddr->no_elements = paddr->field_size; |
71 | 616 | dbrType = DBR_CHAR; | 631 | paddr->field_type = DBF_CHAR; |
72 | 617 | no_elements = field_size; | 632 | paddr->field_size = 1; |
73 | 618 | field_size = 1; | 633 | paddr->dbr_field_type = DBR_CHAR; |
74 | 619 | } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { | 634 | } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { |
75 | 620 | /* Clients see a char array, but keep original dbfType */ | 635 | /* Clients see a char array, but keep original dbfType */ |
79 | 621 | dbrType = DBR_CHAR; | 636 | paddr->no_elements = PVNAME_STRINGSZ + 12; |
80 | 622 | no_elements = PVNAME_STRINGSZ + 12; | 637 | paddr->field_size = 1; |
81 | 623 | field_size = 1; | 638 | paddr->dbr_field_type = DBR_CHAR; |
82 | 624 | } else { | 639 | } else { |
83 | 625 | status = S_dbLib_fieldNotFound; | 640 | status = S_dbLib_fieldNotFound; |
84 | 626 | goto finish; | 641 | goto finish; |
85 | 627 | } | 642 | } |
86 | 628 | } | 643 | } |
87 | 629 | 644 | ||
88 | 630 | paddr->pfldDes = pflddes; | ||
89 | 631 | paddr->field_type = dbfType; | ||
90 | 632 | paddr->dbr_field_type = dbrType; | ||
91 | 633 | paddr->field_size = field_size; | ||
92 | 634 | paddr->special = pflddes->special; | ||
93 | 635 | paddr->no_elements = no_elements; | ||
94 | 636 | |||
95 | 637 | if ((paddr->special == SPC_DBADDR) && | ||
96 | 638 | (prset = dbGetRset(paddr)) && | ||
97 | 639 | prset->cvt_dbaddr) | ||
98 | 640 | /* cvt_dbaddr routine may change any of these elements of paddr: | ||
99 | 641 | * pfield, no_elements, element_offset, field_type, | ||
100 | 642 | * dbr_field_type, field_size, and/or special. | ||
101 | 643 | */ | ||
102 | 644 | status = prset->cvt_dbaddr(paddr); | ||
103 | 645 | |||
104 | 646 | finish: | 645 | finish: |
105 | 647 | dbFinishEntry(&dbEntry); | 646 | dbFinishEntry(&dbEntry); |
106 | 648 | return status; | 647 | return status; |
107 | @@ -817,7 +816,7 @@ | |||
108 | 817 | 816 | ||
109 | 818 | /* check for array */ | 817 | /* check for array */ |
110 | 819 | if ((!pfl || pfl->type == dbfl_type_rec) && | 818 | if ((!pfl || pfl->type == dbfl_type_rec) && |
112 | 820 | paddr->special == SPC_DBADDR && | 819 | paddr->pfldDes->special == SPC_DBADDR && |
113 | 821 | no_elements > 1 && | 820 | no_elements > 1 && |
114 | 822 | (prset = dbGetRset(paddr)) && | 821 | (prset = dbGetRset(paddr)) && |
115 | 823 | prset->get_array_info) { | 822 | prset->get_array_info) { |
116 | @@ -1171,7 +1170,7 @@ | |||
117 | 1171 | struct rset *prset = dbGetRset(paddr); | 1170 | struct rset *prset = dbGetRset(paddr); |
118 | 1172 | long offset = 0; | 1171 | long offset = 0; |
119 | 1173 | 1172 | ||
121 | 1174 | if (paddr->special == SPC_DBADDR && | 1173 | if (paddr->pfldDes->special == SPC_DBADDR && |
122 | 1175 | prset && prset->get_array_info) { | 1174 | prset && prset->get_array_info) { |
123 | 1176 | long dummy; | 1175 | long dummy; |
124 | 1177 | 1176 | ||
125 | @@ -1184,7 +1183,7 @@ | |||
126 | 1184 | 1183 | ||
127 | 1185 | /* update array info */ | 1184 | /* update array info */ |
128 | 1186 | if (!status && | 1185 | if (!status && |
130 | 1187 | paddr->special == SPC_DBADDR && | 1186 | paddr->pfldDes->special == SPC_DBADDR && |
131 | 1188 | prset && prset->put_array_info) { | 1187 | prset && prset->put_array_info) { |
132 | 1189 | status = prset->put_array_info(paddr, nRequest); | 1188 | status = prset->put_array_info(paddr, nRequest); |
133 | 1190 | } | 1189 | } |
134 | 1191 | 1190 | ||
135 | === modified file 'src/ioc/db/dbLink.c' | |||
136 | --- src/ioc/db/dbLink.c 2012-07-07 20:54:31 +0000 | |||
137 | +++ src/ioc/db/dbLink.c 2012-12-10 21:21:25 +0000 | |||
138 | @@ -649,3 +649,62 @@ | |||
139 | 649 | } | 649 | } |
140 | 650 | } | 650 | } |
141 | 651 | 651 | ||
142 | 652 | /* Helper functions for long string support */ | ||
143 | 653 | |||
144 | 654 | long dbLoadLinkLS(struct link *plink, char *pbuffer, epicsUInt32 size, | ||
145 | 655 | epicsUInt32 *plen) | ||
146 | 656 | { | ||
147 | 657 | if (plink->type == CONSTANT && | ||
148 | 658 | plink->value.constantStr) { | ||
149 | 659 | strncpy(pbuffer, plink->value.constantStr, --size); | ||
150 | 660 | pbuffer[size] = 0; | ||
151 | 661 | *plen = strlen(pbuffer) + 1; | ||
152 | 662 | return 0; | ||
153 | 663 | } | ||
154 | 664 | |||
155 | 665 | return S_db_notFound; | ||
156 | 666 | } | ||
157 | 667 | |||
158 | 668 | long dbGetLinkLS(struct link *plink, char *pbuffer, epicsUInt32 size, | ||
159 | 669 | epicsUInt32 *plen) | ||
160 | 670 | { | ||
161 | 671 | int dtyp = dbGetLinkDBFtype(plink); | ||
162 | 672 | long len = size; | ||
163 | 673 | long status; | ||
164 | 674 | |||
165 | 675 | if (dtyp < 0) /* Not connected */ | ||
166 | 676 | return 0; | ||
167 | 677 | |||
168 | 678 | if (dtyp == DBR_CHAR || dtyp == DBF_UCHAR) { | ||
169 | 679 | status = dbGetLink(plink, dtyp, pbuffer, 0, &len); | ||
170 | 680 | } | ||
171 | 681 | else if (size >= MAX_STRING_SIZE) | ||
172 | 682 | status = dbGetLink(plink, DBR_STRING, pbuffer, 0, 0); | ||
173 | 683 | else { | ||
174 | 684 | /* pbuffer is too small to fetch using DBR_STRING */ | ||
175 | 685 | char tmp[MAX_STRING_SIZE]; | ||
176 | 686 | |||
177 | 687 | status = dbGetLink(plink, DBR_STRING, tmp, 0, 0); | ||
178 | 688 | if (!status) | ||
179 | 689 | strncpy(pbuffer, tmp, len - 1); | ||
180 | 690 | } | ||
181 | 691 | if (!status) { | ||
182 | 692 | pbuffer[--len] = 0; | ||
183 | 693 | *plen = strlen(pbuffer) + 1; | ||
184 | 694 | } | ||
185 | 695 | return status; | ||
186 | 696 | } | ||
187 | 697 | |||
188 | 698 | long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len) | ||
189 | 699 | { | ||
190 | 700 | int dtyp = dbGetLinkDBFtype(plink); | ||
191 | 701 | |||
192 | 702 | if (dtyp < 0) | ||
193 | 703 | return 0; /* Not connected */ | ||
194 | 704 | |||
195 | 705 | if (dtyp == DBR_CHAR || dtyp == DBF_UCHAR) | ||
196 | 706 | return dbPutLink(plink, dtyp, pbuffer, len); | ||
197 | 707 | |||
198 | 708 | return dbPutLink(plink, DBR_STRING, pbuffer, 1); | ||
199 | 709 | } | ||
200 | 710 | |||
201 | 652 | 711 | ||
202 | === modified file 'src/ioc/db/dbLink.h' | |||
203 | --- src/ioc/db/dbLink.h 2012-08-08 18:38:21 +0000 | |||
204 | +++ src/ioc/db/dbLink.h 2012-12-10 21:21:25 +0000 | |||
205 | @@ -81,6 +81,13 @@ | |||
206 | 81 | const void *pbuffer, long nRequest); | 81 | const void *pbuffer, long nRequest); |
207 | 82 | epicsShareFunc void dbScanFwdLink(struct link *plink); | 82 | epicsShareFunc void dbScanFwdLink(struct link *plink); |
208 | 83 | 83 | ||
209 | 84 | epicsShareFunc long dbLoadLinkLS(struct link *plink, char *pbuffer, | ||
210 | 85 | epicsUInt32 size, epicsUInt32 *plen); | ||
211 | 86 | epicsShareFunc long dbGetLinkLS(struct link *plink, char *pbuffer, | ||
212 | 87 | epicsUInt32 buffer_size, epicsUInt32 *plen); | ||
213 | 88 | epicsShareFunc long dbPutLinkLS(struct link *plink, char *pbuffer, | ||
214 | 89 | epicsUInt32 len); | ||
215 | 90 | |||
216 | 84 | #ifdef __cplusplus | 91 | #ifdef __cplusplus |
217 | 85 | } | 92 | } |
218 | 86 | #endif | 93 | #endif |
219 | 87 | 94 | ||
220 | === added file 'src/ioc/db/menuPost.dbd' | |||
221 | --- src/ioc/db/menuPost.dbd 1970-01-01 00:00:00 +0000 | |||
222 | +++ src/ioc/db/menuPost.dbd 2012-12-10 21:21:25 +0000 | |||
223 | @@ -0,0 +1,11 @@ | |||
224 | 1 | #************************************************************************* | ||
225 | 2 | # Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
226 | 3 | # National Laboratory. | ||
227 | 4 | # EPICS BASE is distributed subject to a Software License Agreement found | ||
228 | 5 | # in file LICENSE that is included with this distribution. | ||
229 | 6 | #************************************************************************* | ||
230 | 7 | |||
231 | 8 | menu(menuPost) { | ||
232 | 9 | choice(menuPost_OnChange, "On Change") | ||
233 | 10 | choice(menuPost_Always, "Always") | ||
234 | 11 | } | ||
235 | 0 | 12 | ||
236 | === modified file 'src/std/dev/Makefile' | |||
237 | --- src/std/dev/Makefile 2012-07-11 23:07:23 +0000 | |||
238 | +++ src/std/dev/Makefile 2012-12-10 21:21:25 +0000 | |||
239 | @@ -30,6 +30,8 @@ | |||
240 | 30 | dbRecStd_SRCS += devHistogramSoft.c | 30 | dbRecStd_SRCS += devHistogramSoft.c |
241 | 31 | dbRecStd_SRCS += devLiSoft.c | 31 | dbRecStd_SRCS += devLiSoft.c |
242 | 32 | dbRecStd_SRCS += devLoSoft.c | 32 | dbRecStd_SRCS += devLoSoft.c |
243 | 33 | dbRecStd_SRCS += devLsiSoft.c | ||
244 | 34 | dbRecStd_SRCS += devLsoSoft.c | ||
245 | 33 | dbRecStd_SRCS += devMbbiDirectSoft.c | 35 | dbRecStd_SRCS += devMbbiDirectSoft.c |
246 | 34 | dbRecStd_SRCS += devMbbiDirectSoftRaw.c | 36 | dbRecStd_SRCS += devMbbiDirectSoftRaw.c |
247 | 35 | dbRecStd_SRCS += devMbbiSoft.c | 37 | dbRecStd_SRCS += devMbbiSoft.c |
248 | @@ -38,6 +40,7 @@ | |||
249 | 38 | dbRecStd_SRCS += devMbboDirectSoftRaw.c | 40 | dbRecStd_SRCS += devMbboDirectSoftRaw.c |
250 | 39 | dbRecStd_SRCS += devMbboSoft.c | 41 | dbRecStd_SRCS += devMbboSoft.c |
251 | 40 | dbRecStd_SRCS += devMbboSoftRaw.c | 42 | dbRecStd_SRCS += devMbboSoftRaw.c |
252 | 43 | dbRecStd_SRCS += devPrintfSoft.c | ||
253 | 41 | dbRecStd_SRCS += devSASoft.c | 44 | dbRecStd_SRCS += devSASoft.c |
254 | 42 | dbRecStd_SRCS += devSiSoft.c | 45 | dbRecStd_SRCS += devSiSoft.c |
255 | 43 | dbRecStd_SRCS += devSoSoft.c | 46 | dbRecStd_SRCS += devSoSoft.c |
256 | @@ -55,12 +58,14 @@ | |||
257 | 55 | dbRecStd_SRCS += devBoSoftCallback.c | 58 | dbRecStd_SRCS += devBoSoftCallback.c |
258 | 56 | dbRecStd_SRCS += devCalcoutSoftCallback.c | 59 | dbRecStd_SRCS += devCalcoutSoftCallback.c |
259 | 57 | dbRecStd_SRCS += devLoSoftCallback.c | 60 | dbRecStd_SRCS += devLoSoftCallback.c |
260 | 61 | dbRecStd_SRCS += devLsoSoftCallback.c | ||
261 | 58 | dbRecStd_SRCS += devMbboSoftCallback.c | 62 | dbRecStd_SRCS += devMbboSoftCallback.c |
262 | 59 | dbRecStd_SRCS += devMbboDirectSoftCallback.c | 63 | dbRecStd_SRCS += devMbboDirectSoftCallback.c |
263 | 64 | dbRecStd_SRCS += devPrintfSoftCallback.c | ||
264 | 60 | dbRecStd_SRCS += devSoSoftCallback.c | 65 | dbRecStd_SRCS += devSoSoftCallback.c |
265 | 61 | 66 | ||
266 | 62 | dbRecStd_SRCS += devTimestamp.c | 67 | dbRecStd_SRCS += devTimestamp.c |
268 | 63 | dbRecStd_SRCS += devSoStdio.c | 68 | dbRecStd_SRCS += devStdio.c |
269 | 64 | 69 | ||
270 | 65 | dbRecStd_SRCS += asSubRecordFunctions.c | 70 | dbRecStd_SRCS += asSubRecordFunctions.c |
271 | 66 | 71 | ||
272 | 67 | 72 | ||
273 | === added file 'src/std/dev/devLsiSoft.c' | |||
274 | --- src/std/dev/devLsiSoft.c 1970-01-01 00:00:00 +0000 | |||
275 | +++ src/std/dev/devLsiSoft.c 2012-12-10 21:21:25 +0000 | |||
276 | @@ -0,0 +1,42 @@ | |||
277 | 1 | /*************************************************************************\ | ||
278 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
279 | 3 | * National Laboratory. | ||
280 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
281 | 5 | * in file LICENSE that is included with this distribution. | ||
282 | 6 | \*************************************************************************/ | ||
283 | 7 | |||
284 | 8 | /* Long String Input soft device support | ||
285 | 9 | * | ||
286 | 10 | * Author: Andrew Johnson | ||
287 | 11 | * Date: 2012-11-28 | ||
288 | 12 | */ | ||
289 | 13 | |||
290 | 14 | #include "dbAccess.h" | ||
291 | 15 | #include "epicsTime.h" | ||
292 | 16 | #include "link.h" | ||
293 | 17 | #include "lsiRecord.h" | ||
294 | 18 | #include "epicsExport.h" | ||
295 | 19 | |||
296 | 20 | static long init_record(lsiRecord *prec) | ||
297 | 21 | { | ||
298 | 22 | dbLoadLinkLS(&prec->inp, prec->val, prec->sizv, &prec->len); | ||
299 | 23 | |||
300 | 24 | return 0; | ||
301 | 25 | } | ||
302 | 26 | |||
303 | 27 | static long read_string(lsiRecord *prec) | ||
304 | 28 | { | ||
305 | 29 | long status = dbGetLinkLS(&prec->inp, prec->val, prec->sizv, &prec->len); | ||
306 | 30 | |||
307 | 31 | if (!status && | ||
308 | 32 | prec->tsel.type == CONSTANT && | ||
309 | 33 | prec->tse == epicsTimeEventDeviceTime) | ||
310 | 34 | dbGetTimeStamp(&prec->inp, &prec->time); | ||
311 | 35 | |||
312 | 36 | return status; | ||
313 | 37 | } | ||
314 | 38 | |||
315 | 39 | lsidset devLsiSoft = { | ||
316 | 40 | 5, NULL, NULL, init_record, NULL, read_string | ||
317 | 41 | }; | ||
318 | 42 | epicsExportAddress(dset, devLsiSoft); | ||
319 | 0 | 43 | ||
320 | === added file 'src/std/dev/devLsoSoft.c' | |||
321 | --- src/std/dev/devLsoSoft.c 1970-01-01 00:00:00 +0000 | |||
322 | +++ src/std/dev/devLsoSoft.c 2012-12-10 21:21:25 +0000 | |||
323 | @@ -0,0 +1,26 @@ | |||
324 | 1 | /*************************************************************************\ | ||
325 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
326 | 3 | * National Laboratory. | ||
327 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
328 | 5 | * in file LICENSE that is included with this distribution. | ||
329 | 6 | \*************************************************************************/ | ||
330 | 7 | |||
331 | 8 | /* Long String Output soft device support | ||
332 | 9 | * | ||
333 | 10 | * Author: Andrew Johnson | ||
334 | 11 | * Date: 2012-11-29 | ||
335 | 12 | */ | ||
336 | 13 | |||
337 | 14 | #include "dbAccess.h" | ||
338 | 15 | #include "lsoRecord.h" | ||
339 | 16 | #include "epicsExport.h" | ||
340 | 17 | |||
341 | 18 | static long write_string(lsoRecord *prec) | ||
342 | 19 | { | ||
343 | 20 | return dbPutLinkLS(&prec->out, prec->val, prec->len); | ||
344 | 21 | } | ||
345 | 22 | |||
346 | 23 | lsodset devLsoSoft = { | ||
347 | 24 | 5, NULL, NULL, NULL, NULL, write_string | ||
348 | 25 | }; | ||
349 | 26 | epicsExportAddress(dset, devLsoSoft); | ||
350 | 0 | 27 | ||
351 | === added file 'src/std/dev/devLsoSoftCallback.c' | |||
352 | --- src/std/dev/devLsoSoftCallback.c 1970-01-01 00:00:00 +0000 | |||
353 | +++ src/std/dev/devLsoSoftCallback.c 2012-12-10 21:21:25 +0000 | |||
354 | @@ -0,0 +1,51 @@ | |||
355 | 1 | /*************************************************************************\ | ||
356 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
357 | 3 | * National Laboratory. | ||
358 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
359 | 5 | * in file LICENSE that is included with this distribution. | ||
360 | 6 | \*************************************************************************/ | ||
361 | 7 | /* $Revision-Id$ */ | ||
362 | 8 | /* | ||
363 | 9 | * Author: Andrew Johnson | ||
364 | 10 | * Date: 30 Nov 2012 | ||
365 | 11 | */ | ||
366 | 12 | |||
367 | 13 | #include "alarm.h" | ||
368 | 14 | #include "dbAccess.h" | ||
369 | 15 | #include "recGbl.h" | ||
370 | 16 | #include "lsoRecord.h" | ||
371 | 17 | #include "epicsExport.h" | ||
372 | 18 | |||
373 | 19 | static long write_string(lsoRecord *prec) | ||
374 | 20 | { | ||
375 | 21 | struct link *plink = &prec->out; | ||
376 | 22 | int dtyp = dbGetLinkDBFtype(plink); | ||
377 | 23 | long len = prec->len; | ||
378 | 24 | long status; | ||
379 | 25 | |||
380 | 26 | if (prec->pact || dtyp < 0) | ||
381 | 27 | return 0; | ||
382 | 28 | |||
383 | 29 | if (dtyp != DBR_CHAR && dtyp != DBF_UCHAR) { | ||
384 | 30 | dtyp = DBR_STRING; | ||
385 | 31 | len = 1; | ||
386 | 32 | } | ||
387 | 33 | |||
388 | 34 | if (plink->type != CA_LINK) | ||
389 | 35 | return dbPutLink(plink, dtyp, prec->val, len); | ||
390 | 36 | |||
391 | 37 | status = dbCaPutLinkCallback(plink, dtyp, prec->val, len, | ||
392 | 38 | dbCaCallbackProcess, plink); | ||
393 | 39 | if (status) { | ||
394 | 40 | recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM); | ||
395 | 41 | return status; | ||
396 | 42 | } | ||
397 | 43 | |||
398 | 44 | prec->pact = TRUE; | ||
399 | 45 | return 0; | ||
400 | 46 | } | ||
401 | 47 | |||
402 | 48 | lsodset devLsoSoftCallback = { | ||
403 | 49 | 5, NULL, NULL, NULL, NULL, write_string | ||
404 | 50 | }; | ||
405 | 51 | epicsExportAddress(dset, devLsoSoftCallback); | ||
406 | 0 | 52 | ||
407 | === added file 'src/std/dev/devPrintfSoft.c' | |||
408 | --- src/std/dev/devPrintfSoft.c 1970-01-01 00:00:00 +0000 | |||
409 | +++ src/std/dev/devPrintfSoft.c 2012-12-10 21:21:25 +0000 | |||
410 | @@ -0,0 +1,26 @@ | |||
411 | 1 | /*************************************************************************\ | ||
412 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
413 | 3 | * National Laboratory. | ||
414 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
415 | 5 | * in file LICENSE that is included with this distribution. | ||
416 | 6 | \*************************************************************************/ | ||
417 | 7 | /* $Revision-Id$ */ | ||
418 | 8 | /* | ||
419 | 9 | * Author: Andrew Johnson | ||
420 | 10 | * Date: 28 Sept 2012 | ||
421 | 11 | */ | ||
422 | 12 | |||
423 | 13 | #include "dbAccess.h" | ||
424 | 14 | #include "printfRecord.h" | ||
425 | 15 | #include "epicsExport.h" | ||
426 | 16 | |||
427 | 17 | static long write_string(printfRecord *prec) | ||
428 | 18 | { | ||
429 | 19 | return dbPutLinkLS(&prec->out, prec->val, prec->len); | ||
430 | 20 | } | ||
431 | 21 | |||
432 | 22 | printfdset devPrintfSoft = { | ||
433 | 23 | 5, NULL, NULL, NULL, NULL, write_string | ||
434 | 24 | }; | ||
435 | 25 | epicsExportAddress(dset, devPrintfSoft); | ||
436 | 26 | |||
437 | 0 | 27 | ||
438 | === added file 'src/std/dev/devPrintfSoftCallback.c' | |||
439 | --- src/std/dev/devPrintfSoftCallback.c 1970-01-01 00:00:00 +0000 | |||
440 | +++ src/std/dev/devPrintfSoftCallback.c 2012-12-10 21:21:25 +0000 | |||
441 | @@ -0,0 +1,51 @@ | |||
442 | 1 | /*************************************************************************\ | ||
443 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
444 | 3 | * National Laboratory. | ||
445 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
446 | 5 | * in file LICENSE that is included with this distribution. | ||
447 | 6 | \*************************************************************************/ | ||
448 | 7 | /* $Revision-Id$ */ | ||
449 | 8 | /* | ||
450 | 9 | * Author: Andrew Johnson | ||
451 | 10 | * Date: 28 Sept 2012 | ||
452 | 11 | */ | ||
453 | 12 | |||
454 | 13 | #include "alarm.h" | ||
455 | 14 | #include "dbAccess.h" | ||
456 | 15 | #include "recGbl.h" | ||
457 | 16 | #include "printfRecord.h" | ||
458 | 17 | #include "epicsExport.h" | ||
459 | 18 | |||
460 | 19 | static long write_string(printfRecord *prec) | ||
461 | 20 | { | ||
462 | 21 | struct link *plink = &prec->out; | ||
463 | 22 | int dtyp = dbGetLinkDBFtype(plink); | ||
464 | 23 | long len = prec->len; | ||
465 | 24 | long status; | ||
466 | 25 | |||
467 | 26 | if (prec->pact || dtyp < 0) | ||
468 | 27 | return 0; | ||
469 | 28 | |||
470 | 29 | if (dtyp != DBR_CHAR && dtyp != DBF_UCHAR) { | ||
471 | 30 | dtyp = DBR_STRING; | ||
472 | 31 | len = 1; | ||
473 | 32 | } | ||
474 | 33 | |||
475 | 34 | if (plink->type != CA_LINK) | ||
476 | 35 | return dbPutLink(plink, dtyp, prec->val, len); | ||
477 | 36 | |||
478 | 37 | status = dbCaPutLinkCallback(plink, dtyp, prec->val, len, | ||
479 | 38 | dbCaCallbackProcess, plink); | ||
480 | 39 | if (status) { | ||
481 | 40 | recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM); | ||
482 | 41 | return status; | ||
483 | 42 | } | ||
484 | 43 | |||
485 | 44 | prec->pact = TRUE; | ||
486 | 45 | return 0; | ||
487 | 46 | } | ||
488 | 47 | |||
489 | 48 | printfdset devPrintfSoftCallback = { | ||
490 | 49 | 5, NULL, NULL, NULL, NULL, write_string | ||
491 | 50 | }; | ||
492 | 51 | epicsExportAddress(dset, devPrintfSoftCallback); | ||
493 | 0 | 52 | ||
494 | === removed file 'src/std/dev/devSoStdio.c' | |||
495 | --- src/std/dev/devSoStdio.c 2012-07-18 21:45:23 +0000 | |||
496 | +++ src/std/dev/devSoStdio.c 1970-01-01 00:00:00 +0000 | |||
497 | @@ -1,108 +0,0 @@ | |||
498 | 1 | /*************************************************************************\ | ||
499 | 2 | * Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne | ||
500 | 3 | * National Laboratory. | ||
501 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
502 | 5 | * in file LICENSE that is included with this distribution. | ||
503 | 6 | \*************************************************************************/ | ||
504 | 7 | |||
505 | 8 | /* $Revision-Id$ */ | ||
506 | 9 | |||
507 | 10 | #include <stdio.h> | ||
508 | 11 | #include <string.h> | ||
509 | 12 | |||
510 | 13 | #include "dbCommon.h" | ||
511 | 14 | #include "devSup.h" | ||
512 | 15 | #include "errlog.h" | ||
513 | 16 | #include "recGbl.h" | ||
514 | 17 | #include "recSup.h" | ||
515 | 18 | #include "stringoutRecord.h" | ||
516 | 19 | #include "epicsExport.h" | ||
517 | 20 | |||
518 | 21 | typedef int (*PRINTFFUNC)(const char *fmt, ...); | ||
519 | 22 | |||
520 | 23 | static int stderrPrintf(const char *fmt, ...); | ||
521 | 24 | static int logPrintf(const char *fmt, ...); | ||
522 | 25 | |||
523 | 26 | |||
524 | 27 | static struct outStream { | ||
525 | 28 | const char *name; | ||
526 | 29 | PRINTFFUNC print; | ||
527 | 30 | } outStreams[] = { | ||
528 | 31 | {"stdout", printf}, | ||
529 | 32 | {"stderr", stderrPrintf}, | ||
530 | 33 | {"errlog", logPrintf}, | ||
531 | 34 | {NULL, NULL} | ||
532 | 35 | }; | ||
533 | 36 | |||
534 | 37 | static int stderrPrintf(const char *fmt, ...) { | ||
535 | 38 | va_list pvar; | ||
536 | 39 | int retval; | ||
537 | 40 | |||
538 | 41 | va_start(pvar, fmt); | ||
539 | 42 | retval = vfprintf(stderr, fmt, pvar); | ||
540 | 43 | va_end (pvar); | ||
541 | 44 | |||
542 | 45 | return retval; | ||
543 | 46 | } | ||
544 | 47 | |||
545 | 48 | static int logPrintf(const char *fmt, ...) { | ||
546 | 49 | va_list pvar; | ||
547 | 50 | int retval; | ||
548 | 51 | |||
549 | 52 | va_start(pvar, fmt); | ||
550 | 53 | retval = errlogVprintf(fmt, pvar); | ||
551 | 54 | va_end (pvar); | ||
552 | 55 | |||
553 | 56 | return retval; | ||
554 | 57 | } | ||
555 | 58 | |||
556 | 59 | static long add(dbCommon *pcommon) { | ||
557 | 60 | stringoutRecord *prec = (stringoutRecord *) pcommon; | ||
558 | 61 | struct outStream *pstream; | ||
559 | 62 | |||
560 | 63 | if (prec->out.type != INST_IO) | ||
561 | 64 | return S_dev_badOutType; | ||
562 | 65 | |||
563 | 66 | for (pstream = outStreams; pstream->name; ++pstream) { | ||
564 | 67 | if (strcmp(prec->out.value.instio.string, pstream->name) == 0) { | ||
565 | 68 | prec->dpvt = pstream; | ||
566 | 69 | return 0; | ||
567 | 70 | } | ||
568 | 71 | } | ||
569 | 72 | prec->dpvt = NULL; | ||
570 | 73 | return -1; | ||
571 | 74 | } | ||
572 | 75 | |||
573 | 76 | static long del(dbCommon *pcommon) { | ||
574 | 77 | stringoutRecord *prec = (stringoutRecord *) pcommon; | ||
575 | 78 | |||
576 | 79 | prec->dpvt = NULL; | ||
577 | 80 | return 0; | ||
578 | 81 | } | ||
579 | 82 | |||
580 | 83 | static struct dsxt dsxtSoStdio = { | ||
581 | 84 | add, del | ||
582 | 85 | }; | ||
583 | 86 | |||
584 | 87 | static long init(int pass) | ||
585 | 88 | { | ||
586 | 89 | if (pass == 0) devExtend(&dsxtSoStdio); | ||
587 | 90 | return 0; | ||
588 | 91 | } | ||
589 | 92 | |||
590 | 93 | static long write_string(stringoutRecord *prec) | ||
591 | 94 | { | ||
592 | 95 | struct outStream *pstream = (struct outStream *)prec->dpvt; | ||
593 | 96 | if (pstream) | ||
594 | 97 | pstream->print("%s\n", prec->val); | ||
595 | 98 | return 0; | ||
596 | 99 | } | ||
597 | 100 | |||
598 | 101 | /* Create the dset for devSoStdio */ | ||
599 | 102 | static struct { | ||
600 | 103 | dset common; | ||
601 | 104 | DEVSUPFUN write; | ||
602 | 105 | } devSoStdio = { | ||
603 | 106 | {5, NULL, init, NULL, NULL}, write_string | ||
604 | 107 | }; | ||
605 | 108 | epicsExportAddress(dset, devSoStdio); | ||
606 | 109 | 0 | ||
607 | === modified file 'src/std/dev/devSoft.dbd' | |||
608 | --- src/std/dev/devSoft.dbd 2012-07-11 23:07:23 +0000 | |||
609 | +++ src/std/dev/devSoft.dbd 2012-12-10 21:21:25 +0000 | |||
610 | @@ -9,10 +9,13 @@ | |||
611 | 9 | device(histogram,CONSTANT,devHistogramSoft,"Soft Channel") | 9 | device(histogram,CONSTANT,devHistogramSoft,"Soft Channel") |
612 | 10 | device(longin,CONSTANT,devLiSoft,"Soft Channel") | 10 | device(longin,CONSTANT,devLiSoft,"Soft Channel") |
613 | 11 | device(longout,CONSTANT,devLoSoft,"Soft Channel") | 11 | device(longout,CONSTANT,devLoSoft,"Soft Channel") |
614 | 12 | device(lsi,CONSTANT,devLsiSoft,"Soft Channel") | ||
615 | 13 | device(lso,CONSTANT,devLsoSoft,"Soft Channel") | ||
616 | 12 | device(mbbi,CONSTANT,devMbbiSoft,"Soft Channel") | 14 | device(mbbi,CONSTANT,devMbbiSoft,"Soft Channel") |
617 | 13 | device(mbbiDirect,CONSTANT,devMbbiDirectSoft,"Soft Channel") | 15 | device(mbbiDirect,CONSTANT,devMbbiDirectSoft,"Soft Channel") |
618 | 14 | device(mbbo,CONSTANT,devMbboSoft,"Soft Channel") | 16 | device(mbbo,CONSTANT,devMbboSoft,"Soft Channel") |
619 | 15 | device(mbboDirect,CONSTANT,devMbboDirectSoft,"Soft Channel") | 17 | device(mbboDirect,CONSTANT,devMbboDirectSoft,"Soft Channel") |
620 | 18 | device(printf,CONSTANT,devPrintfSoft,"Soft Channel") | ||
621 | 16 | device(stringin,CONSTANT,devSiSoft,"Soft Channel") | 19 | device(stringin,CONSTANT,devSiSoft,"Soft Channel") |
622 | 17 | device(stringout,CONSTANT,devSoSoft,"Soft Channel") | 20 | device(stringout,CONSTANT,devSoSoft,"Soft Channel") |
623 | 18 | device(subArray,CONSTANT,devSASoft,"Soft Channel") | 21 | device(subArray,CONSTANT,devSASoft,"Soft Channel") |
624 | @@ -34,10 +37,12 @@ | |||
625 | 34 | device(calcout,CONSTANT,devCalcoutSoftCallback,"Async Soft Channel") | 37 | device(calcout,CONSTANT,devCalcoutSoftCallback,"Async Soft Channel") |
626 | 35 | device(longin,CONSTANT,devLiSoftCallback,"Async Soft Channel") | 38 | device(longin,CONSTANT,devLiSoftCallback,"Async Soft Channel") |
627 | 36 | device(longout,CONSTANT,devLoSoftCallback,"Async Soft Channel") | 39 | device(longout,CONSTANT,devLoSoftCallback,"Async Soft Channel") |
628 | 40 | device(lso,CONSTANT,devLsoSoftCallback,"Async Soft Channel") | ||
629 | 37 | device(mbbi,CONSTANT,devMbbiSoftCallback,"Async Soft Channel") | 41 | device(mbbi,CONSTANT,devMbbiSoftCallback,"Async Soft Channel") |
630 | 38 | device(mbbiDirect,CONSTANT,devMbbiDirectSoftCallback,"Async Soft Channel") | 42 | device(mbbiDirect,CONSTANT,devMbbiDirectSoftCallback,"Async Soft Channel") |
631 | 39 | device(mbbo,CONSTANT,devMbboSoftCallback,"Async Soft Channel") | 43 | device(mbbo,CONSTANT,devMbboSoftCallback,"Async Soft Channel") |
632 | 40 | device(mbboDirect,CONSTANT,devMbboDirectSoftCallback,"Async Soft Channel") | 44 | device(mbboDirect,CONSTANT,devMbboDirectSoftCallback,"Async Soft Channel") |
633 | 45 | device(printf,CONSTANT,devPrintfSoftCallback,"Async Soft Channel") | ||
634 | 41 | device(stringin,CONSTANT,devSiSoftCallback,"Async Soft Channel") | 46 | device(stringin,CONSTANT,devSiSoftCallback,"Async Soft Channel") |
635 | 42 | device(stringout,CONSTANT,devSoSoftCallback,"Async Soft Channel") | 47 | device(stringout,CONSTANT,devSoSoftCallback,"Async Soft Channel") |
636 | 43 | 48 | ||
637 | @@ -49,6 +54,8 @@ | |||
638 | 49 | device(longin, INST_IO,devLiGeneralTime,"General Time") | 54 | device(longin, INST_IO,devLiGeneralTime,"General Time") |
639 | 50 | device(stringin,INST_IO,devSiGeneralTime,"General Time") | 55 | device(stringin,INST_IO,devSiGeneralTime,"General Time") |
640 | 51 | 56 | ||
641 | 57 | device(lso,INST_IO,devLsoStdio,"stdio") | ||
642 | 58 | device(printf,INST_IO,devPrintfStdio,"stdio") | ||
643 | 52 | device(stringout,INST_IO,devSoStdio,"stdio") | 59 | device(stringout,INST_IO,devSoStdio,"stdio") |
644 | 53 | 60 | ||
645 | 54 | device(bi, INST_IO, devBiDbState, "Db State") | 61 | device(bi, INST_IO, devBiDbState, "Db State") |
646 | 55 | 62 | ||
647 | === added file 'src/std/dev/devStdio.c' | |||
648 | --- src/std/dev/devStdio.c 1970-01-01 00:00:00 +0000 | |||
649 | +++ src/std/dev/devStdio.c 2012-12-10 21:21:25 +0000 | |||
650 | @@ -0,0 +1,212 @@ | |||
651 | 1 | /*************************************************************************\ | ||
652 | 2 | * Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne | ||
653 | 3 | * National Laboratory. | ||
654 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
655 | 5 | * in file LICENSE that is included with this distribution. | ||
656 | 6 | \*************************************************************************/ | ||
657 | 7 | |||
658 | 8 | /* $Revision-Id$ */ | ||
659 | 9 | |||
660 | 10 | #include <stdio.h> | ||
661 | 11 | #include <string.h> | ||
662 | 12 | |||
663 | 13 | #include "dbCommon.h" | ||
664 | 14 | #include "devSup.h" | ||
665 | 15 | #include "errlog.h" | ||
666 | 16 | #include "recGbl.h" | ||
667 | 17 | #include "recSup.h" | ||
668 | 18 | #include "lsoRecord.h" | ||
669 | 19 | #include "printfRecord.h" | ||
670 | 20 | #include "stringoutRecord.h" | ||
671 | 21 | #include "epicsExport.h" | ||
672 | 22 | |||
673 | 23 | typedef int (*PRINTFFUNC)(const char *fmt, ...); | ||
674 | 24 | |||
675 | 25 | static int stderrPrintf(const char *fmt, ...); | ||
676 | 26 | static int logPrintf(const char *fmt, ...); | ||
677 | 27 | |||
678 | 28 | |||
679 | 29 | static struct outStream { | ||
680 | 30 | const char *name; | ||
681 | 31 | PRINTFFUNC print; | ||
682 | 32 | } outStreams[] = { | ||
683 | 33 | {"stdout", printf}, | ||
684 | 34 | {"stderr", stderrPrintf}, | ||
685 | 35 | {"errlog", logPrintf}, | ||
686 | 36 | {NULL, NULL} | ||
687 | 37 | }; | ||
688 | 38 | |||
689 | 39 | static int stderrPrintf(const char *fmt, ...) { | ||
690 | 40 | va_list pvar; | ||
691 | 41 | int retval; | ||
692 | 42 | |||
693 | 43 | va_start(pvar, fmt); | ||
694 | 44 | retval = vfprintf(stderr, fmt, pvar); | ||
695 | 45 | va_end (pvar); | ||
696 | 46 | |||
697 | 47 | return retval; | ||
698 | 48 | } | ||
699 | 49 | |||
700 | 50 | static int logPrintf(const char *fmt, ...) { | ||
701 | 51 | va_list pvar; | ||
702 | 52 | int retval; | ||
703 | 53 | |||
704 | 54 | va_start(pvar, fmt); | ||
705 | 55 | retval = errlogVprintf(fmt, pvar); | ||
706 | 56 | va_end (pvar); | ||
707 | 57 | |||
708 | 58 | return retval; | ||
709 | 59 | } | ||
710 | 60 | |||
711 | 61 | |||
712 | 62 | /* lso device support */ | ||
713 | 63 | |||
714 | 64 | static long add_lso(dbCommon *pcommon) { | ||
715 | 65 | lsoRecord *prec = (lsoRecord *) pcommon; | ||
716 | 66 | struct outStream *pstream; | ||
717 | 67 | |||
718 | 68 | if (prec->out.type != INST_IO) | ||
719 | 69 | return S_dev_badOutType; | ||
720 | 70 | |||
721 | 71 | for (pstream = outStreams; pstream->name; ++pstream) { | ||
722 | 72 | if (strcmp(prec->out.value.instio.string, pstream->name) == 0) { | ||
723 | 73 | prec->dpvt = pstream; | ||
724 | 74 | return 0; | ||
725 | 75 | } | ||
726 | 76 | } | ||
727 | 77 | prec->dpvt = NULL; | ||
728 | 78 | return -1; | ||
729 | 79 | } | ||
730 | 80 | |||
731 | 81 | static long del_lso(dbCommon *pcommon) { | ||
732 | 82 | lsoRecord *prec = (lsoRecord *) pcommon; | ||
733 | 83 | |||
734 | 84 | prec->dpvt = NULL; | ||
735 | 85 | return 0; | ||
736 | 86 | } | ||
737 | 87 | |||
738 | 88 | static struct dsxt dsxtLsoStdio = { | ||
739 | 89 | add_lso, del_lso | ||
740 | 90 | }; | ||
741 | 91 | |||
742 | 92 | static long init_lso(int pass) | ||
743 | 93 | { | ||
744 | 94 | if (pass == 0) devExtend(&dsxtLsoStdio); | ||
745 | 95 | return 0; | ||
746 | 96 | } | ||
747 | 97 | |||
748 | 98 | static long write_lso(lsoRecord *prec) | ||
749 | 99 | { | ||
750 | 100 | struct outStream *pstream = (struct outStream *)prec->dpvt; | ||
751 | 101 | if (pstream) | ||
752 | 102 | pstream->print("%s\n", prec->val); | ||
753 | 103 | return 0; | ||
754 | 104 | } | ||
755 | 105 | |||
756 | 106 | lsodset devLsoStdio = { | ||
757 | 107 | 5, NULL, init_lso, NULL, NULL, write_lso | ||
758 | 108 | }; | ||
759 | 109 | epicsExportAddress(dset, devLsoStdio); | ||
760 | 110 | |||
761 | 111 | |||
762 | 112 | /* printf device support */ | ||
763 | 113 | |||
764 | 114 | static long add_printf(dbCommon *pcommon) { | ||
765 | 115 | printfRecord *prec = (printfRecord *) pcommon; | ||
766 | 116 | struct outStream *pstream; | ||
767 | 117 | |||
768 | 118 | if (prec->out.type != INST_IO) | ||
769 | 119 | return S_dev_badOutType; | ||
770 | 120 | |||
771 | 121 | for (pstream = outStreams; pstream->name; ++pstream) { | ||
772 | 122 | if (strcmp(prec->out.value.instio.string, pstream->name) == 0) { | ||
773 | 123 | prec->dpvt = pstream; | ||
774 | 124 | return 0; | ||
775 | 125 | } | ||
776 | 126 | } | ||
777 | 127 | prec->dpvt = NULL; | ||
778 | 128 | return -1; | ||
779 | 129 | } | ||
780 | 130 | |||
781 | 131 | static long del_printf(dbCommon *pcommon) { | ||
782 | 132 | printfRecord *prec = (printfRecord *) pcommon; | ||
783 | 133 | |||
784 | 134 | prec->dpvt = NULL; | ||
785 | 135 | return 0; | ||
786 | 136 | } | ||
787 | 137 | |||
788 | 138 | static struct dsxt dsxtPrintfStdio = { | ||
789 | 139 | add_printf, del_printf | ||
790 | 140 | }; | ||
791 | 141 | |||
792 | 142 | static long init_printf(int pass) | ||
793 | 143 | { | ||
794 | 144 | if (pass == 0) devExtend(&dsxtPrintfStdio); | ||
795 | 145 | return 0; | ||
796 | 146 | } | ||
797 | 147 | |||
798 | 148 | static long write_printf(printfRecord *prec) | ||
799 | 149 | { | ||
800 | 150 | struct outStream *pstream = (struct outStream *)prec->dpvt; | ||
801 | 151 | if (pstream) | ||
802 | 152 | pstream->print("%s\n", prec->val); | ||
803 | 153 | return 0; | ||
804 | 154 | } | ||
805 | 155 | |||
806 | 156 | printfdset devPrintfStdio = { | ||
807 | 157 | 5, NULL, init_printf, NULL, NULL, write_printf | ||
808 | 158 | }; | ||
809 | 159 | epicsExportAddress(dset, devPrintfStdio); | ||
810 | 160 | |||
811 | 161 | |||
812 | 162 | /* stringout device support */ | ||
813 | 163 | |||
814 | 164 | static long add_stringout(dbCommon *pcommon) { | ||
815 | 165 | stringoutRecord *prec = (stringoutRecord *) pcommon; | ||
816 | 166 | struct outStream *pstream; | ||
817 | 167 | |||
818 | 168 | if (prec->out.type != INST_IO) | ||
819 | 169 | return S_dev_badOutType; | ||
820 | 170 | |||
821 | 171 | for (pstream = outStreams; pstream->name; ++pstream) { | ||
822 | 172 | if (strcmp(prec->out.value.instio.string, pstream->name) == 0) { | ||
823 | 173 | prec->dpvt = pstream; | ||
824 | 174 | return 0; | ||
825 | 175 | } | ||
826 | 176 | } | ||
827 | 177 | prec->dpvt = NULL; | ||
828 | 178 | return -1; | ||
829 | 179 | } | ||
830 | 180 | |||
831 | 181 | static long del_stringout(dbCommon *pcommon) { | ||
832 | 182 | stringoutRecord *prec = (stringoutRecord *) pcommon; | ||
833 | 183 | |||
834 | 184 | prec->dpvt = NULL; | ||
835 | 185 | return 0; | ||
836 | 186 | } | ||
837 | 187 | |||
838 | 188 | static struct dsxt dsxtSoStdio = { | ||
839 | 189 | add_stringout, del_stringout | ||
840 | 190 | }; | ||
841 | 191 | |||
842 | 192 | static long init_stringout(int pass) | ||
843 | 193 | { | ||
844 | 194 | if (pass == 0) devExtend(&dsxtSoStdio); | ||
845 | 195 | return 0; | ||
846 | 196 | } | ||
847 | 197 | |||
848 | 198 | static long write_stringout(stringoutRecord *prec) | ||
849 | 199 | { | ||
850 | 200 | struct outStream *pstream = (struct outStream *)prec->dpvt; | ||
851 | 201 | if (pstream) | ||
852 | 202 | pstream->print("%s\n", prec->val); | ||
853 | 203 | return 0; | ||
854 | 204 | } | ||
855 | 205 | |||
856 | 206 | static struct { | ||
857 | 207 | dset common; | ||
858 | 208 | DEVSUPFUN write; | ||
859 | 209 | } devSoStdio = { | ||
860 | 210 | {5, NULL, init_stringout, NULL, NULL}, write_stringout | ||
861 | 211 | }; | ||
862 | 212 | epicsExportAddress(dset, devSoStdio); | ||
863 | 0 | 213 | ||
864 | === modified file 'src/std/rec/Makefile' | |||
865 | --- src/std/rec/Makefile 2011-11-14 23:42:50 +0000 | |||
866 | +++ src/std/rec/Makefile 2012-12-10 21:21:25 +0000 | |||
867 | @@ -11,67 +11,43 @@ | |||
868 | 11 | 11 | ||
869 | 12 | SRC_DIRS += $(STDDIR)/rec | 12 | SRC_DIRS += $(STDDIR)/rec |
870 | 13 | 13 | ||
900 | 14 | DBDINC += aaiRecord | 14 | stdRecords += aaiRecord |
901 | 15 | DBDINC += aaoRecord | 15 | stdRecords += aaoRecord |
902 | 16 | DBDINC += aiRecord | 16 | stdRecords += aiRecord |
903 | 17 | DBDINC += aoRecord | 17 | stdRecords += aoRecord |
904 | 18 | DBDINC += aSubRecord | 18 | stdRecords += aSubRecord |
905 | 19 | DBDINC += biRecord | 19 | stdRecords += biRecord |
906 | 20 | DBDINC += boRecord | 20 | stdRecords += boRecord |
907 | 21 | DBDINC += calcRecord | 21 | stdRecords += calcRecord |
908 | 22 | DBDINC += calcoutRecord | 22 | stdRecords += calcoutRecord |
909 | 23 | DBDINC += compressRecord | 23 | stdRecords += compressRecord |
910 | 24 | DBDINC += dfanoutRecord | 24 | stdRecords += dfanoutRecord |
911 | 25 | DBDINC += eventRecord | 25 | stdRecords += eventRecord |
912 | 26 | DBDINC += fanoutRecord | 26 | stdRecords += fanoutRecord |
913 | 27 | DBDINC += histogramRecord | 27 | stdRecords += histogramRecord |
914 | 28 | DBDINC += longinRecord | 28 | stdRecords += longinRecord |
915 | 29 | DBDINC += longoutRecord | 29 | stdRecords += longoutRecord |
916 | 30 | DBDINC += mbbiRecord | 30 | stdRecords += lsiRecord |
917 | 31 | DBDINC += mbbiDirectRecord | 31 | stdRecords += lsoRecord |
918 | 32 | DBDINC += mbboRecord | 32 | stdRecords += mbbiRecord |
919 | 33 | DBDINC += mbboDirectRecord | 33 | stdRecords += mbbiDirectRecord |
920 | 34 | DBDINC += permissiveRecord | 34 | stdRecords += mbboRecord |
921 | 35 | DBDINC += selRecord | 35 | stdRecords += mbboDirectRecord |
922 | 36 | DBDINC += seqRecord | 36 | stdRecords += permissiveRecord |
923 | 37 | DBDINC += stateRecord | 37 | stdRecords += printfRecord |
924 | 38 | DBDINC += stringinRecord | 38 | stdRecords += selRecord |
925 | 39 | DBDINC += stringoutRecord | 39 | stdRecords += seqRecord |
926 | 40 | DBDINC += subRecord | 40 | stdRecords += stateRecord |
927 | 41 | DBDINC += subArrayRecord | 41 | stdRecords += stringinRecord |
928 | 42 | DBDINC += waveformRecord | 42 | stdRecords += stringoutRecord |
929 | 43 | stdRecords += subRecord | ||
930 | 44 | stdRecords += subArrayRecord | ||
931 | 45 | stdRecords += waveformRecord | ||
932 | 43 | 46 | ||
933 | 47 | DBDINC += $(stdRecords) | ||
934 | 44 | DBD += stdRecords.dbd | 48 | DBD += stdRecords.dbd |
935 | 45 | 49 | ||
937 | 46 | stdRecords_DBD = $(patsubst %,%.dbd,$(DBDINC)) | 50 | stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords)) |
938 | 47 | 51 | ||
968 | 48 | dbRecStd_SRCS += aaiRecord.c | 52 | dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords)) |
940 | 49 | dbRecStd_SRCS += aaoRecord.c | ||
941 | 50 | dbRecStd_SRCS += aiRecord.c | ||
942 | 51 | dbRecStd_SRCS += aoRecord.c | ||
943 | 52 | dbRecStd_SRCS += aSubRecord.c | ||
944 | 53 | dbRecStd_SRCS += biRecord.c | ||
945 | 54 | dbRecStd_SRCS += boRecord.c | ||
946 | 55 | dbRecStd_SRCS += calcRecord.c | ||
947 | 56 | dbRecStd_SRCS += calcoutRecord.c | ||
948 | 57 | dbRecStd_SRCS += compressRecord.c | ||
949 | 58 | dbRecStd_SRCS += dfanoutRecord.c | ||
950 | 59 | dbRecStd_SRCS += eventRecord.c | ||
951 | 60 | dbRecStd_SRCS += fanoutRecord.c | ||
952 | 61 | dbRecStd_SRCS += histogramRecord.c | ||
953 | 62 | dbRecStd_SRCS += longinRecord.c | ||
954 | 63 | dbRecStd_SRCS += longoutRecord.c | ||
955 | 64 | dbRecStd_SRCS += mbbiRecord.c | ||
956 | 65 | dbRecStd_SRCS += mbbiDirectRecord.c | ||
957 | 66 | dbRecStd_SRCS += mbboRecord.c | ||
958 | 67 | dbRecStd_SRCS += mbboDirectRecord.c | ||
959 | 68 | dbRecStd_SRCS += permissiveRecord.c | ||
960 | 69 | dbRecStd_SRCS += selRecord.c | ||
961 | 70 | dbRecStd_SRCS += seqRecord.c | ||
962 | 71 | dbRecStd_SRCS += stateRecord.c | ||
963 | 72 | dbRecStd_SRCS += stringinRecord.c | ||
964 | 73 | dbRecStd_SRCS += stringoutRecord.c | ||
965 | 74 | dbRecStd_SRCS += subRecord.c | ||
966 | 75 | dbRecStd_SRCS += subArrayRecord.c | ||
967 | 76 | dbRecStd_SRCS += waveformRecord.c | ||
969 | 77 | 53 | ||
970 | 78 | 54 | ||
971 | === modified file 'src/std/rec/RULES' | |||
972 | --- src/std/rec/RULES 2011-02-27 00:24:51 +0000 | |||
973 | +++ src/std/rec/RULES 2012-12-10 21:21:25 +0000 | |||
974 | @@ -9,7 +9,7 @@ | |||
975 | 9 | 9 | ||
976 | 10 | # This is a Makefile fragment, see src/std/Makefile. | 10 | # This is a Makefile fragment, see src/std/Makefile. |
977 | 11 | 11 | ||
979 | 12 | $(COMMON_DIR)/stdRecords.dbd: | 12 | $(COMMON_DIR)/stdRecords.dbd: ../rec/Makefile |
980 | 13 | $(RM) $@ | 13 | $(RM) $@ |
981 | 14 | $(PERL) $(TOOLS)/makeIncludeDbd.pl $(stdRecords_DBD) $@ | 14 | $(PERL) $(TOOLS)/makeIncludeDbd.pl $(stdRecords_DBD) $@ |
982 | 15 | 15 | ||
983 | 16 | 16 | ||
984 | === added file 'src/std/rec/lsiRecord.c' | |||
985 | --- src/std/rec/lsiRecord.c 1970-01-01 00:00:00 +0000 | |||
986 | +++ src/std/rec/lsiRecord.c 2012-12-10 21:21:25 +0000 | |||
987 | @@ -0,0 +1,284 @@ | |||
988 | 1 | /*************************************************************************\ | ||
989 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
990 | 3 | * National Laboratory. | ||
991 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
992 | 5 | * in file LICENSE that is included with this distribution. | ||
993 | 6 | \*************************************************************************/ | ||
994 | 7 | |||
995 | 8 | /* Long String Input record type */ | ||
996 | 9 | /* | ||
997 | 10 | * Author: Andrew Johnson | ||
998 | 11 | * Date: 2012-11-27 | ||
999 | 12 | */ | ||
1000 | 13 | |||
1001 | 14 | #include <stddef.h> | ||
1002 | 15 | #include <stdio.h> | ||
1003 | 16 | #include <string.h> | ||
1004 | 17 | |||
1005 | 18 | #include "dbDefs.h" | ||
1006 | 19 | #include "errlog.h" | ||
1007 | 20 | #include "alarm.h" | ||
1008 | 21 | #include "cantProceed.h" | ||
1009 | 22 | #include "dbAccess.h" | ||
1010 | 23 | #include "dbEvent.h" | ||
1011 | 24 | #include "dbFldTypes.h" | ||
1012 | 25 | #include "errMdef.h" | ||
1013 | 26 | #include "menuPost.h" | ||
1014 | 27 | #include "menuYesNo.h" | ||
1015 | 28 | #include "recSup.h" | ||
1016 | 29 | #include "recGbl.h" | ||
1017 | 30 | #include "special.h" | ||
1018 | 31 | #define GEN_SIZE_OFFSET | ||
1019 | 32 | #include "lsiRecord.h" | ||
1020 | 33 | #undef GEN_SIZE_OFFSET | ||
1021 | 34 | #include "epicsExport.h" | ||
1022 | 35 | |||
1023 | 36 | static void monitor(lsiRecord *); | ||
1024 | 37 | static long readValue(lsiRecord *); | ||
1025 | 38 | |||
1026 | 39 | static long init_record(lsiRecord *prec, int pass) | ||
1027 | 40 | { | ||
1028 | 41 | lsidset *pdset; | ||
1029 | 42 | |||
1030 | 43 | if (pass == 0) { | ||
1031 | 44 | size_t sizv = prec->sizv; | ||
1032 | 45 | |||
1033 | 46 | if (sizv < 16) { | ||
1034 | 47 | sizv = 16; /* Enforce a minimum size for the VAL field */ | ||
1035 | 48 | prec->sizv = sizv; | ||
1036 | 49 | } | ||
1037 | 50 | |||
1038 | 51 | prec->val = callocMustSucceed(1, sizv, "lsi::init_record"); | ||
1039 | 52 | prec->len = 0; | ||
1040 | 53 | prec->oval = callocMustSucceed(1, sizv, "lsi::init_record"); | ||
1041 | 54 | prec->olen = 0; | ||
1042 | 55 | return 0; | ||
1043 | 56 | } | ||
1044 | 57 | |||
1045 | 58 | dbLoadLink(&prec->siml, DBF_USHORT, &prec->simm); | ||
1046 | 59 | |||
1047 | 60 | pdset = (lsidset *) prec->dset; | ||
1048 | 61 | if (!pdset) { | ||
1049 | 62 | recGblRecordError(S_dev_noDSET, prec, "lsi: init_record"); | ||
1050 | 63 | return S_dev_noDSET; | ||
1051 | 64 | } | ||
1052 | 65 | |||
1053 | 66 | /* must have a read_string function */ | ||
1054 | 67 | if (pdset->number < 5 || !pdset->read_string) { | ||
1055 | 68 | recGblRecordError(S_dev_missingSup, prec, "lsi: init_record"); | ||
1056 | 69 | return S_dev_missingSup; | ||
1057 | 70 | } | ||
1058 | 71 | |||
1059 | 72 | if (pdset->init_record) { | ||
1060 | 73 | long status = pdset->init_record(prec); | ||
1061 | 74 | |||
1062 | 75 | if (status) | ||
1063 | 76 | return status; | ||
1064 | 77 | } | ||
1065 | 78 | |||
1066 | 79 | if (prec->len) { | ||
1067 | 80 | strcpy(prec->oval, prec->val); | ||
1068 | 81 | prec->olen = prec->len; | ||
1069 | 82 | prec->udf = FALSE; | ||
1070 | 83 | } | ||
1071 | 84 | |||
1072 | 85 | return 0; | ||
1073 | 86 | } | ||
1074 | 87 | |||
1075 | 88 | static long process(lsiRecord *prec) | ||
1076 | 89 | { | ||
1077 | 90 | int pact = prec->pact; | ||
1078 | 91 | lsidset *pdset = (lsidset *) prec->dset; | ||
1079 | 92 | long status = 0; | ||
1080 | 93 | |||
1081 | 94 | if (!pdset || !pdset->read_string) { | ||
1082 | 95 | prec->pact = TRUE; | ||
1083 | 96 | recGblRecordError(S_dev_missingSup, prec, "lsi: read_string"); | ||
1084 | 97 | return S_dev_missingSup; | ||
1085 | 98 | } | ||
1086 | 99 | |||
1087 | 100 | status = readValue(prec); /* read the new value */ | ||
1088 | 101 | if (!pact && prec->pact) | ||
1089 | 102 | return 0; | ||
1090 | 103 | |||
1091 | 104 | prec->pact = TRUE; | ||
1092 | 105 | recGblGetTimeStamp(prec); | ||
1093 | 106 | |||
1094 | 107 | monitor(prec); | ||
1095 | 108 | |||
1096 | 109 | /* Wrap up */ | ||
1097 | 110 | recGblFwdLink(prec); | ||
1098 | 111 | prec->pact = FALSE; | ||
1099 | 112 | return status; | ||
1100 | 113 | } | ||
1101 | 114 | |||
1102 | 115 | static long cvt_dbaddr(DBADDR *paddr) | ||
1103 | 116 | { | ||
1104 | 117 | lsiRecord *prec = (lsiRecord *) paddr->precord; | ||
1105 | 118 | int fieldIndex = dbGetFieldIndex(paddr); | ||
1106 | 119 | |||
1107 | 120 | if (fieldIndex == lsiRecordVAL) { | ||
1108 | 121 | paddr->pfield = prec->val; | ||
1109 | 122 | paddr->special = SPC_MOD; | ||
1110 | 123 | } | ||
1111 | 124 | else if (fieldIndex == lsiRecordOVAL) { | ||
1112 | 125 | paddr->pfield = prec->oval; | ||
1113 | 126 | paddr->special = SPC_NOMOD; | ||
1114 | 127 | } | ||
1115 | 128 | else { | ||
1116 | 129 | errlogPrintf("lsiRecord::cvt_dbaddr called for %s.%s\n", | ||
1117 | 130 | prec->name, paddr->pfldDes->name); | ||
1118 | 131 | return -1; | ||
1119 | 132 | } | ||
1120 | 133 | |||
1121 | 134 | paddr->no_elements = 1; | ||
1122 | 135 | paddr->field_type = DBF_STRING; | ||
1123 | 136 | paddr->dbr_field_type = DBF_STRING; | ||
1124 | 137 | paddr->field_size = prec->sizv; | ||
1125 | 138 | return 0; | ||
1126 | 139 | } | ||
1127 | 140 | |||
1128 | 141 | static long get_array_info(DBADDR *paddr, long *no_elements, long *offset) | ||
1129 | 142 | { | ||
1130 | 143 | lsiRecord *prec = (lsiRecord *) paddr->precord; | ||
1131 | 144 | int fieldIndex = dbGetFieldIndex(paddr); | ||
1132 | 145 | |||
1133 | 146 | if (fieldIndex == lsiRecordVAL) | ||
1134 | 147 | *no_elements = prec->len; | ||
1135 | 148 | else if (fieldIndex == lsiRecordOVAL) | ||
1136 | 149 | *no_elements = prec->olen; | ||
1137 | 150 | else | ||
1138 | 151 | return -1; | ||
1139 | 152 | |||
1140 | 153 | *offset = 0; | ||
1141 | 154 | return 0; | ||
1142 | 155 | } | ||
1143 | 156 | |||
1144 | 157 | static long put_array_info(DBADDR *paddr, long nNew) | ||
1145 | 158 | { | ||
1146 | 159 | lsiRecord *prec = (lsiRecord *) paddr->precord; | ||
1147 | 160 | |||
1148 | 161 | if (nNew == prec->sizv) | ||
1149 | 162 | --nNew; /* truncated string */ | ||
1150 | 163 | prec->val[nNew] = 0; /* ensure data is terminated */ | ||
1151 | 164 | |||
1152 | 165 | return 0; | ||
1153 | 166 | } | ||
1154 | 167 | |||
1155 | 168 | static long special(DBADDR *paddr, int after) | ||
1156 | 169 | { | ||
1157 | 170 | lsiRecord *prec = (lsiRecord *) paddr->precord; | ||
1158 | 171 | |||
1159 | 172 | if (!after) | ||
1160 | 173 | return 0; | ||
1161 | 174 | |||
1162 | 175 | /* We set prec->len here and not in put_array_info() | ||
1163 | 176 | * because that does not get called if the put was | ||
1164 | 177 | * done using a DBR_STRING type. | ||
1165 | 178 | */ | ||
1166 | 179 | prec->len = strlen(prec->val) + 1; | ||
1167 | 180 | db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG); | ||
1168 | 181 | |||
1169 | 182 | return 0; | ||
1170 | 183 | } | ||
1171 | 184 | |||
1172 | 185 | static void monitor(lsiRecord *prec) | ||
1173 | 186 | { | ||
1174 | 187 | epicsUInt16 events = recGblResetAlarms(prec); | ||
1175 | 188 | |||
1176 | 189 | if (prec->len != prec->olen || | ||
1177 | 190 | memcmp(prec->oval, prec->val, prec->len)) { | ||
1178 | 191 | events |= DBE_VALUE | DBE_LOG; | ||
1179 | 192 | memcpy(prec->oval, prec->val, prec->len); | ||
1180 | 193 | } | ||
1181 | 194 | |||
1182 | 195 | if (prec->len != prec->olen) { | ||
1183 | 196 | prec->olen = prec->len; | ||
1184 | 197 | db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG); | ||
1185 | 198 | } | ||
1186 | 199 | |||
1187 | 200 | if (prec->mpst == menuPost_Always) | ||
1188 | 201 | events |= DBE_VALUE; | ||
1189 | 202 | if (prec->apst == menuPost_Always) | ||
1190 | 203 | events |= DBE_LOG; | ||
1191 | 204 | |||
1192 | 205 | if (events) | ||
1193 | 206 | db_post_events(prec, prec->val, events); | ||
1194 | 207 | } | ||
1195 | 208 | |||
1196 | 209 | static long readValue(lsiRecord *prec) | ||
1197 | 210 | { | ||
1198 | 211 | long status; | ||
1199 | 212 | lsidset *pdset = (lsidset *) prec->dset; | ||
1200 | 213 | |||
1201 | 214 | if (prec->pact) | ||
1202 | 215 | goto read; | ||
1203 | 216 | |||
1204 | 217 | status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0); | ||
1205 | 218 | if (status) | ||
1206 | 219 | return status; | ||
1207 | 220 | |||
1208 | 221 | switch (prec->simm) { | ||
1209 | 222 | case menuYesNoNO: | ||
1210 | 223 | read: | ||
1211 | 224 | status = pdset->read_string(prec); | ||
1212 | 225 | break; | ||
1213 | 226 | |||
1214 | 227 | case menuYesNoYES: | ||
1215 | 228 | recGblSetSevr(prec, SIMM_ALARM, prec->sims); | ||
1216 | 229 | status = dbGetLinkLS(&prec->siol, prec->val, prec->sizv, &prec->len); | ||
1217 | 230 | break; | ||
1218 | 231 | |||
1219 | 232 | default: | ||
1220 | 233 | recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); | ||
1221 | 234 | status = -1; | ||
1222 | 235 | } | ||
1223 | 236 | |||
1224 | 237 | if (!status) | ||
1225 | 238 | prec->udf = FALSE; | ||
1226 | 239 | |||
1227 | 240 | return status; | ||
1228 | 241 | } | ||
1229 | 242 | |||
1230 | 243 | |||
1231 | 244 | /* Create Record Support Entry Table*/ | ||
1232 | 245 | |||
1233 | 246 | #define report NULL | ||
1234 | 247 | #define initialize NULL | ||
1235 | 248 | /* init_record */ | ||
1236 | 249 | /* process */ | ||
1237 | 250 | /* special */ | ||
1238 | 251 | #define get_value NULL | ||
1239 | 252 | /* cvt_dbaddr */ | ||
1240 | 253 | /* get_array_info */ | ||
1241 | 254 | /* put_array_info */ | ||
1242 | 255 | #define get_units NULL | ||
1243 | 256 | #define get_precision NULL | ||
1244 | 257 | #define get_enum_str NULL | ||
1245 | 258 | #define get_enum_strs NULL | ||
1246 | 259 | #define put_enum_str NULL | ||
1247 | 260 | #define get_graphic_double NULL | ||
1248 | 261 | #define get_control_double NULL | ||
1249 | 262 | #define get_alarm_double NULL | ||
1250 | 263 | |||
1251 | 264 | rset lsiRSET = { | ||
1252 | 265 | RSETNUMBER, | ||
1253 | 266 | report, | ||
1254 | 267 | initialize, | ||
1255 | 268 | init_record, | ||
1256 | 269 | process, | ||
1257 | 270 | special, | ||
1258 | 271 | get_value, | ||
1259 | 272 | cvt_dbaddr, | ||
1260 | 273 | get_array_info, | ||
1261 | 274 | put_array_info, | ||
1262 | 275 | get_units, | ||
1263 | 276 | get_precision, | ||
1264 | 277 | get_enum_str, | ||
1265 | 278 | get_enum_strs, | ||
1266 | 279 | put_enum_str, | ||
1267 | 280 | get_graphic_double, | ||
1268 | 281 | get_control_double, | ||
1269 | 282 | get_alarm_double | ||
1270 | 283 | }; | ||
1271 | 284 | epicsExportAddress(rset, lsiRSET); | ||
1272 | 0 | 285 | ||
1273 | === added file 'src/std/rec/lsiRecord.dbd' | |||
1274 | --- src/std/rec/lsiRecord.dbd 1970-01-01 00:00:00 +0000 | |||
1275 | +++ src/std/rec/lsiRecord.dbd 2012-12-10 21:21:25 +0000 | |||
1276 | @@ -0,0 +1,88 @@ | |||
1277 | 1 | #************************************************************************* | ||
1278 | 2 | # Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
1279 | 3 | # National Laboratory. | ||
1280 | 4 | # EPICS BASE is distributed subject to a Software License Agreement found | ||
1281 | 5 | # in file LICENSE that is included with this distribution. | ||
1282 | 6 | #************************************************************************* | ||
1283 | 7 | |||
1284 | 8 | recordtype(lsi) { | ||
1285 | 9 | include "dbCommon.dbd" | ||
1286 | 10 | %#include "devSup.h" | ||
1287 | 11 | % | ||
1288 | 12 | %/* Declare Device Support Entry Table */ | ||
1289 | 13 | %typedef struct lsidset { | ||
1290 | 14 | % long number; | ||
1291 | 15 | % DEVSUPFUN report; | ||
1292 | 16 | % DEVSUPFUN init; | ||
1293 | 17 | % DEVSUPFUN init_record; | ||
1294 | 18 | % DEVSUPFUN get_ioint_info; | ||
1295 | 19 | % DEVSUPFUN read_string; | ||
1296 | 20 | %} lsidset; | ||
1297 | 21 | % | ||
1298 | 22 | field(VAL,DBF_NOACCESS) { | ||
1299 | 23 | prompt("Current Value") | ||
1300 | 24 | asl(ASL0) | ||
1301 | 25 | pp(TRUE) | ||
1302 | 26 | special(SPC_DBADDR) | ||
1303 | 27 | extra("char *val") | ||
1304 | 28 | } | ||
1305 | 29 | field(OVAL,DBF_NOACCESS) { | ||
1306 | 30 | prompt("Old Value") | ||
1307 | 31 | special(SPC_DBADDR) | ||
1308 | 32 | interest(3) | ||
1309 | 33 | extra("char *oval") | ||
1310 | 34 | } | ||
1311 | 35 | field(SIZV,DBF_USHORT) { | ||
1312 | 36 | prompt("Size of buffers") | ||
1313 | 37 | promptgroup(GUI_OUTPUT) | ||
1314 | 38 | special(SPC_NOMOD) | ||
1315 | 39 | interest(1) | ||
1316 | 40 | initial("41") | ||
1317 | 41 | } | ||
1318 | 42 | field(LEN,DBF_ULONG) { | ||
1319 | 43 | prompt("Length of VAL") | ||
1320 | 44 | special(SPC_NOMOD) | ||
1321 | 45 | } | ||
1322 | 46 | field(OLEN,DBF_ULONG) { | ||
1323 | 47 | prompt("Length of OVAL") | ||
1324 | 48 | special(SPC_NOMOD) | ||
1325 | 49 | } | ||
1326 | 50 | field(INP,DBF_INLINK) { | ||
1327 | 51 | prompt("Input Specification") | ||
1328 | 52 | promptgroup(GUI_INPUTS) | ||
1329 | 53 | interest(1) | ||
1330 | 54 | } | ||
1331 | 55 | field(MPST,DBF_MENU) { | ||
1332 | 56 | prompt("Post Value Monitors") | ||
1333 | 57 | promptgroup(GUI_DISPLAY) | ||
1334 | 58 | interest(1) | ||
1335 | 59 | menu(menuPost) | ||
1336 | 60 | } | ||
1337 | 61 | field(APST,DBF_MENU) { | ||
1338 | 62 | prompt("Post Archive Monitors") | ||
1339 | 63 | promptgroup(GUI_DISPLAY) | ||
1340 | 64 | interest(1) | ||
1341 | 65 | menu(menuPost) | ||
1342 | 66 | } | ||
1343 | 67 | field(SIML,DBF_INLINK) { | ||
1344 | 68 | prompt("Simulation Mode Link") | ||
1345 | 69 | promptgroup(GUI_INPUTS) | ||
1346 | 70 | interest(2) | ||
1347 | 71 | } | ||
1348 | 72 | field(SIMM,DBF_MENU) { | ||
1349 | 73 | prompt("Simulation Mode") | ||
1350 | 74 | interest(2) | ||
1351 | 75 | menu(menuYesNo) | ||
1352 | 76 | } | ||
1353 | 77 | field(SIMS,DBF_MENU) { | ||
1354 | 78 | prompt("Simulation Mode Severity") | ||
1355 | 79 | promptgroup(GUI_INPUTS) | ||
1356 | 80 | interest(2) | ||
1357 | 81 | menu(menuAlarmSevr) | ||
1358 | 82 | } | ||
1359 | 83 | field(SIOL,DBF_INLINK) { | ||
1360 | 84 | prompt("Sim Input Specifctn") | ||
1361 | 85 | promptgroup(GUI_INPUTS) | ||
1362 | 86 | interest(2) | ||
1363 | 87 | } | ||
1364 | 88 | } | ||
1365 | 0 | 89 | ||
1366 | === added file 'src/std/rec/lsoRecord.c' | |||
1367 | --- src/std/rec/lsoRecord.c 1970-01-01 00:00:00 +0000 | |||
1368 | +++ src/std/rec/lsoRecord.c 2012-12-10 21:21:25 +0000 | |||
1369 | @@ -0,0 +1,322 @@ | |||
1370 | 1 | /*************************************************************************\ | ||
1371 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
1372 | 3 | * National Laboratory. | ||
1373 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
1374 | 5 | * in file LICENSE that is included with this distribution. | ||
1375 | 6 | \*************************************************************************/ | ||
1376 | 7 | |||
1377 | 8 | /* Long String Output record type */ | ||
1378 | 9 | /* | ||
1379 | 10 | * Author: Andrew Johnson | ||
1380 | 11 | * Date: 2012-11-28 | ||
1381 | 12 | */ | ||
1382 | 13 | |||
1383 | 14 | |||
1384 | 15 | #include <stddef.h> | ||
1385 | 16 | #include <stdio.h> | ||
1386 | 17 | #include <string.h> | ||
1387 | 18 | |||
1388 | 19 | #include "dbDefs.h" | ||
1389 | 20 | #include "errlog.h" | ||
1390 | 21 | #include "alarm.h" | ||
1391 | 22 | #include "cantProceed.h" | ||
1392 | 23 | #include "dbAccess.h" | ||
1393 | 24 | #include "dbEvent.h" | ||
1394 | 25 | #include "dbFldTypes.h" | ||
1395 | 26 | #include "devSup.h" | ||
1396 | 27 | #include "errMdef.h" | ||
1397 | 28 | #include "menuIvoa.h" | ||
1398 | 29 | #include "menuOmsl.h" | ||
1399 | 30 | #include "menuPost.h" | ||
1400 | 31 | #include "menuYesNo.h" | ||
1401 | 32 | #include "recSup.h" | ||
1402 | 33 | #include "recGbl.h" | ||
1403 | 34 | #include "special.h" | ||
1404 | 35 | #define GEN_SIZE_OFFSET | ||
1405 | 36 | #include "lsoRecord.h" | ||
1406 | 37 | #undef GEN_SIZE_OFFSET | ||
1407 | 38 | #include "epicsExport.h" | ||
1408 | 39 | |||
1409 | 40 | static void monitor(lsoRecord *); | ||
1410 | 41 | static long writeValue(lsoRecord *); | ||
1411 | 42 | |||
1412 | 43 | static long init_record(lsoRecord *prec, int pass) | ||
1413 | 44 | { | ||
1414 | 45 | lsodset *pdset; | ||
1415 | 46 | |||
1416 | 47 | if (pass == 0) { | ||
1417 | 48 | size_t sizv = prec->sizv; | ||
1418 | 49 | |||
1419 | 50 | if (sizv < 16) { | ||
1420 | 51 | sizv = 16; /* Enforce a minimum size for the VAL field */ | ||
1421 | 52 | prec->sizv = sizv; | ||
1422 | 53 | } | ||
1423 | 54 | |||
1424 | 55 | prec->val = callocMustSucceed(1, sizv, "lso::init_record"); | ||
1425 | 56 | prec->len = 0; | ||
1426 | 57 | prec->oval = callocMustSucceed(1, sizv, "lso::init_record"); | ||
1427 | 58 | prec->olen = 0; | ||
1428 | 59 | return 0; | ||
1429 | 60 | } | ||
1430 | 61 | |||
1431 | 62 | dbLoadLink(&prec->siml, DBF_USHORT, &prec->simm); | ||
1432 | 63 | |||
1433 | 64 | pdset = (lsodset *) prec->dset; | ||
1434 | 65 | if (!pdset) { | ||
1435 | 66 | recGblRecordError(S_dev_noDSET, prec, "lso: init_record"); | ||
1436 | 67 | return S_dev_noDSET; | ||
1437 | 68 | } | ||
1438 | 69 | |||
1439 | 70 | /* must have a write_string function defined */ | ||
1440 | 71 | if (pdset->number < 5 || !pdset->write_string) { | ||
1441 | 72 | recGblRecordError(S_dev_missingSup, prec, "lso: init_record"); | ||
1442 | 73 | return S_dev_missingSup; | ||
1443 | 74 | } | ||
1444 | 75 | |||
1445 | 76 | dbLoadLinkLS(&prec->dol, prec->val, prec->sizv, &prec->len); | ||
1446 | 77 | |||
1447 | 78 | if (pdset->init_record) { | ||
1448 | 79 | long status = pdset->init_record(prec); | ||
1449 | 80 | |||
1450 | 81 | if (status) | ||
1451 | 82 | return status; | ||
1452 | 83 | } | ||
1453 | 84 | |||
1454 | 85 | if (prec->len) { | ||
1455 | 86 | strcpy(prec->oval, prec->val); | ||
1456 | 87 | prec->olen = prec->len; | ||
1457 | 88 | prec->udf = FALSE; | ||
1458 | 89 | } | ||
1459 | 90 | |||
1460 | 91 | return 0; | ||
1461 | 92 | } | ||
1462 | 93 | |||
1463 | 94 | static long process(lsoRecord *prec) | ||
1464 | 95 | { | ||
1465 | 96 | int pact = prec->pact; | ||
1466 | 97 | lsodset *pdset = (lsodset *) prec->dset; | ||
1467 | 98 | long status = 0; | ||
1468 | 99 | |||
1469 | 100 | if (!pdset || !pdset->write_string) { | ||
1470 | 101 | prec->pact = TRUE; | ||
1471 | 102 | recGblRecordError(S_dev_missingSup, prec, "lso: write_string"); | ||
1472 | 103 | return S_dev_missingSup; | ||
1473 | 104 | } | ||
1474 | 105 | |||
1475 | 106 | if (!pact && prec->omsl == menuOmslclosed_loop) | ||
1476 | 107 | if (!dbGetLinkLS(&prec->dol, prec->val, prec->sizv, &prec->len)) | ||
1477 | 108 | prec->udf = FALSE; | ||
1478 | 109 | |||
1479 | 110 | if (prec->udf) | ||
1480 | 111 | recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM); | ||
1481 | 112 | |||
1482 | 113 | if (prec->nsev < INVALID_ALARM ) | ||
1483 | 114 | status = writeValue(prec); /* write the new value */ | ||
1484 | 115 | else { | ||
1485 | 116 | switch (prec->ivoa) { | ||
1486 | 117 | case menuIvoaContinue_normally: | ||
1487 | 118 | status = writeValue(prec); /* write the new value */ | ||
1488 | 119 | break; | ||
1489 | 120 | |||
1490 | 121 | case menuIvoaDon_t_drive_outputs: | ||
1491 | 122 | break; | ||
1492 | 123 | |||
1493 | 124 | case menuIvoaSet_output_to_IVOV: | ||
1494 | 125 | if (!prec->pact) { | ||
1495 | 126 | size_t size = prec->sizv - 1; | ||
1496 | 127 | |||
1497 | 128 | strncpy(prec->val, prec->ivov, size); | ||
1498 | 129 | prec->val[size] = 0; | ||
1499 | 130 | prec->len = strlen(prec->val) + 1; | ||
1500 | 131 | } | ||
1501 | 132 | status = writeValue(prec); /* write the new value */ | ||
1502 | 133 | break; | ||
1503 | 134 | |||
1504 | 135 | default: | ||
1505 | 136 | status = -1; | ||
1506 | 137 | recGblRecordError(S_db_badField, prec, | ||
1507 | 138 | "lso:process Bad IVOA choice"); | ||
1508 | 139 | } | ||
1509 | 140 | } | ||
1510 | 141 | |||
1511 | 142 | /* Asynchronous if device support set pact */ | ||
1512 | 143 | if (!pact && prec->pact) | ||
1513 | 144 | return status; | ||
1514 | 145 | |||
1515 | 146 | prec->pact = TRUE; | ||
1516 | 147 | recGblGetTimeStamp(prec); | ||
1517 | 148 | |||
1518 | 149 | monitor(prec); | ||
1519 | 150 | |||
1520 | 151 | /* Wrap up */ | ||
1521 | 152 | recGblFwdLink(prec); | ||
1522 | 153 | prec->pact = FALSE; | ||
1523 | 154 | return status; | ||
1524 | 155 | } | ||
1525 | 156 | |||
1526 | 157 | static long cvt_dbaddr(DBADDR *paddr) | ||
1527 | 158 | { | ||
1528 | 159 | lsoRecord *prec = (lsoRecord *) paddr->precord; | ||
1529 | 160 | int fieldIndex = dbGetFieldIndex(paddr); | ||
1530 | 161 | |||
1531 | 162 | if (fieldIndex == lsoRecordVAL) { | ||
1532 | 163 | paddr->pfield = prec->val; | ||
1533 | 164 | paddr->special = SPC_MOD; | ||
1534 | 165 | } | ||
1535 | 166 | else if (fieldIndex == lsoRecordOVAL) { | ||
1536 | 167 | paddr->pfield = prec->oval; | ||
1537 | 168 | paddr->special = SPC_NOMOD; | ||
1538 | 169 | } | ||
1539 | 170 | else { | ||
1540 | 171 | errlogPrintf("lsoRecord::cvt_dbaddr called for %s.%s\n", | ||
1541 | 172 | prec->name, paddr->pfldDes->name); | ||
1542 | 173 | return -1; | ||
1543 | 174 | } | ||
1544 | 175 | |||
1545 | 176 | paddr->no_elements = 1; | ||
1546 | 177 | paddr->field_type = DBF_STRING; | ||
1547 | 178 | paddr->dbr_field_type = DBF_STRING; | ||
1548 | 179 | paddr->field_size = prec->sizv; | ||
1549 | 180 | return 0; | ||
1550 | 181 | } | ||
1551 | 182 | |||
1552 | 183 | static long get_array_info(DBADDR *paddr, long *no_elements, long *offset) | ||
1553 | 184 | { | ||
1554 | 185 | lsoRecord *prec = (lsoRecord *) paddr->precord; | ||
1555 | 186 | int fieldIndex = dbGetFieldIndex(paddr); | ||
1556 | 187 | |||
1557 | 188 | if (fieldIndex == lsoRecordVAL) | ||
1558 | 189 | *no_elements = prec->len; | ||
1559 | 190 | else if (fieldIndex == lsoRecordOVAL) | ||
1560 | 191 | *no_elements = prec->olen; | ||
1561 | 192 | else | ||
1562 | 193 | return -1; | ||
1563 | 194 | |||
1564 | 195 | *offset = 0; | ||
1565 | 196 | return 0; | ||
1566 | 197 | } | ||
1567 | 198 | |||
1568 | 199 | static long put_array_info(DBADDR *paddr, long nNew) | ||
1569 | 200 | { | ||
1570 | 201 | lsoRecord *prec = (lsoRecord *) paddr->precord; | ||
1571 | 202 | |||
1572 | 203 | if (nNew == prec->sizv) | ||
1573 | 204 | --nNew; /* truncated string */ | ||
1574 | 205 | prec->val[nNew] = 0; /* ensure data is terminated */ | ||
1575 | 206 | |||
1576 | 207 | return 0; | ||
1577 | 208 | } | ||
1578 | 209 | |||
1579 | 210 | static long special(DBADDR *paddr, int after) | ||
1580 | 211 | { | ||
1581 | 212 | lsoRecord *prec = (lsoRecord *) paddr->precord; | ||
1582 | 213 | |||
1583 | 214 | if (!after) | ||
1584 | 215 | return 0; | ||
1585 | 216 | |||
1586 | 217 | /* We set prec->len here and not in put_array_info() | ||
1587 | 218 | * because that does not get called if the put was | ||
1588 | 219 | * done using a DBR_STRING type. | ||
1589 | 220 | */ | ||
1590 | 221 | prec->len = strlen(prec->val) + 1; | ||
1591 | 222 | db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG); | ||
1592 | 223 | |||
1593 | 224 | return 0; | ||
1594 | 225 | } | ||
1595 | 226 | |||
1596 | 227 | static void monitor(lsoRecord *prec) | ||
1597 | 228 | { | ||
1598 | 229 | epicsUInt16 events = recGblResetAlarms(prec); | ||
1599 | 230 | |||
1600 | 231 | if (prec->len != prec->olen || | ||
1601 | 232 | memcmp(prec->oval, prec->val, prec->len)) { | ||
1602 | 233 | events |= DBE_VALUE | DBE_LOG; | ||
1603 | 234 | memcpy(prec->oval, prec->val, prec->len); | ||
1604 | 235 | } | ||
1605 | 236 | |||
1606 | 237 | if (prec->len != prec->olen) { | ||
1607 | 238 | prec->olen = prec->len; | ||
1608 | 239 | db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG); | ||
1609 | 240 | } | ||
1610 | 241 | |||
1611 | 242 | if (prec->mpst == menuPost_Always) | ||
1612 | 243 | events |= DBE_VALUE; | ||
1613 | 244 | if (prec->apst == menuPost_Always) | ||
1614 | 245 | events |= DBE_LOG; | ||
1615 | 246 | |||
1616 | 247 | if (events) | ||
1617 | 248 | db_post_events(prec, prec->val, events); | ||
1618 | 249 | } | ||
1619 | 250 | |||
1620 | 251 | static long writeValue(lsoRecord *prec) | ||
1621 | 252 | { | ||
1622 | 253 | long status; | ||
1623 | 254 | lsodset *pdset = (lsodset *) prec->dset; | ||
1624 | 255 | |||
1625 | 256 | if (prec->pact) | ||
1626 | 257 | goto write; | ||
1627 | 258 | |||
1628 | 259 | status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0); | ||
1629 | 260 | if (status) | ||
1630 | 261 | return(status); | ||
1631 | 262 | |||
1632 | 263 | switch (prec->simm) { | ||
1633 | 264 | case menuYesNoNO: | ||
1634 | 265 | write: | ||
1635 | 266 | status = pdset->write_string(prec); | ||
1636 | 267 | break; | ||
1637 | 268 | |||
1638 | 269 | case menuYesNoYES: | ||
1639 | 270 | recGblSetSevr(prec, SIMM_ALARM, prec->sims); | ||
1640 | 271 | status = dbPutLink(&prec->siol,DBR_STRING, prec->val,1); | ||
1641 | 272 | break; | ||
1642 | 273 | |||
1643 | 274 | default: | ||
1644 | 275 | recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); | ||
1645 | 276 | status = -1; | ||
1646 | 277 | } | ||
1647 | 278 | |||
1648 | 279 | return status; | ||
1649 | 280 | } | ||
1650 | 281 | |||
1651 | 282 | /* Create Record Support Entry Table*/ | ||
1652 | 283 | |||
1653 | 284 | #define report NULL | ||
1654 | 285 | #define initialize NULL | ||
1655 | 286 | /* init_record */ | ||
1656 | 287 | /* process */ | ||
1657 | 288 | /* special */ | ||
1658 | 289 | #define get_value NULL | ||
1659 | 290 | /* cvt_dbaddr */ | ||
1660 | 291 | /* get_array_info */ | ||
1661 | 292 | /* put_array_info */ | ||
1662 | 293 | #define get_units NULL | ||
1663 | 294 | #define get_precision NULL | ||
1664 | 295 | #define get_enum_str NULL | ||
1665 | 296 | #define get_enum_strs NULL | ||
1666 | 297 | #define put_enum_str NULL | ||
1667 | 298 | #define get_graphic_double NULL | ||
1668 | 299 | #define get_control_double NULL | ||
1669 | 300 | #define get_alarm_double NULL | ||
1670 | 301 | |||
1671 | 302 | rset lsoRSET = { | ||
1672 | 303 | RSETNUMBER, | ||
1673 | 304 | report, | ||
1674 | 305 | initialize, | ||
1675 | 306 | init_record, | ||
1676 | 307 | process, | ||
1677 | 308 | special, | ||
1678 | 309 | get_value, | ||
1679 | 310 | cvt_dbaddr, | ||
1680 | 311 | get_array_info, | ||
1681 | 312 | put_array_info, | ||
1682 | 313 | get_units, | ||
1683 | 314 | get_precision, | ||
1684 | 315 | get_enum_str, | ||
1685 | 316 | get_enum_strs, | ||
1686 | 317 | put_enum_str, | ||
1687 | 318 | get_graphic_double, | ||
1688 | 319 | get_control_double, | ||
1689 | 320 | get_alarm_double | ||
1690 | 321 | }; | ||
1691 | 322 | epicsExportAddress(rset, lsoRSET); | ||
1692 | 0 | 323 | ||
1693 | === added file 'src/std/rec/lsoRecord.dbd' | |||
1694 | --- src/std/rec/lsoRecord.dbd 1970-01-01 00:00:00 +0000 | |||
1695 | +++ src/std/rec/lsoRecord.dbd 2012-12-10 21:21:25 +0000 | |||
1696 | @@ -0,0 +1,112 @@ | |||
1697 | 1 | #************************************************************************* | ||
1698 | 2 | # Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
1699 | 3 | # National Laboratory. | ||
1700 | 4 | # EPICS BASE is distributed subject to a Software License Agreement found | ||
1701 | 5 | # in file LICENSE that is included with this distribution. | ||
1702 | 6 | #************************************************************************* | ||
1703 | 7 | |||
1704 | 8 | recordtype(lso) { | ||
1705 | 9 | include "dbCommon.dbd" | ||
1706 | 10 | %#include "devSup.h" | ||
1707 | 11 | % | ||
1708 | 12 | %/* Declare Device Support Entry Table */ | ||
1709 | 13 | %typedef struct lsodset { | ||
1710 | 14 | % long number; | ||
1711 | 15 | % DEVSUPFUN report; | ||
1712 | 16 | % DEVSUPFUN init; | ||
1713 | 17 | % DEVSUPFUN init_record; | ||
1714 | 18 | % DEVSUPFUN get_ioint_info; | ||
1715 | 19 | % DEVSUPFUN write_string; | ||
1716 | 20 | %} lsodset; | ||
1717 | 21 | % | ||
1718 | 22 | field(VAL,DBF_NOACCESS) { | ||
1719 | 23 | prompt("Current Value") | ||
1720 | 24 | asl(ASL0) | ||
1721 | 25 | pp(TRUE) | ||
1722 | 26 | special(SPC_DBADDR) | ||
1723 | 27 | extra("char *val") | ||
1724 | 28 | } | ||
1725 | 29 | field(OVAL,DBF_NOACCESS) { | ||
1726 | 30 | prompt("Previous Value") | ||
1727 | 31 | special(SPC_DBADDR) | ||
1728 | 32 | interest(3) | ||
1729 | 33 | extra("char *oval") | ||
1730 | 34 | } | ||
1731 | 35 | field(SIZV,DBF_USHORT) { | ||
1732 | 36 | prompt("Size of buffers") | ||
1733 | 37 | promptgroup(GUI_OUTPUT) | ||
1734 | 38 | special(SPC_NOMOD) | ||
1735 | 39 | interest(1) | ||
1736 | 40 | initial("41") | ||
1737 | 41 | } | ||
1738 | 42 | field(LEN,DBF_ULONG) { | ||
1739 | 43 | prompt("Length of VAL") | ||
1740 | 44 | special(SPC_NOMOD) | ||
1741 | 45 | } | ||
1742 | 46 | field(OLEN,DBF_ULONG) { | ||
1743 | 47 | prompt("Length of OVAL") | ||
1744 | 48 | special(SPC_NOMOD) | ||
1745 | 49 | interest(3) | ||
1746 | 50 | } | ||
1747 | 51 | field(DOL,DBF_INLINK) { | ||
1748 | 52 | prompt("Desired Output Link") | ||
1749 | 53 | promptgroup(GUI_OUTPUT) | ||
1750 | 54 | interest(1) | ||
1751 | 55 | } | ||
1752 | 56 | field(IVOA,DBF_MENU) { | ||
1753 | 57 | prompt("INVALID Output Action") | ||
1754 | 58 | promptgroup(GUI_OUTPUT) | ||
1755 | 59 | interest(2) | ||
1756 | 60 | menu(menuIvoa) | ||
1757 | 61 | } | ||
1758 | 62 | field(IVOV,DBF_STRING) { | ||
1759 | 63 | prompt("INVALID Output Value") | ||
1760 | 64 | promptgroup(GUI_OUTPUT) | ||
1761 | 65 | interest(2) | ||
1762 | 66 | size(40) | ||
1763 | 67 | } | ||
1764 | 68 | field(OMSL,DBF_MENU) { | ||
1765 | 69 | prompt("Output Mode Select") | ||
1766 | 70 | promptgroup(GUI_OUTPUT) | ||
1767 | 71 | interest(1) | ||
1768 | 72 | menu(menuOmsl) | ||
1769 | 73 | } | ||
1770 | 74 | field(OUT,DBF_OUTLINK) { | ||
1771 | 75 | prompt("Output Specification") | ||
1772 | 76 | promptgroup(GUI_OUTPUT) | ||
1773 | 77 | interest(1) | ||
1774 | 78 | } | ||
1775 | 79 | field(MPST,DBF_MENU) { | ||
1776 | 80 | prompt("Post Value Monitors") | ||
1777 | 81 | promptgroup(GUI_DISPLAY) | ||
1778 | 82 | interest(1) | ||
1779 | 83 | menu(menuPost) | ||
1780 | 84 | } | ||
1781 | 85 | field(APST,DBF_MENU) { | ||
1782 | 86 | prompt("Post Archive Monitors") | ||
1783 | 87 | promptgroup(GUI_DISPLAY) | ||
1784 | 88 | interest(1) | ||
1785 | 89 | menu(menuPost) | ||
1786 | 90 | } | ||
1787 | 91 | field(SIML,DBF_INLINK) { | ||
1788 | 92 | prompt("Sim Mode link") | ||
1789 | 93 | promptgroup(GUI_INPUTS) | ||
1790 | 94 | interest(1) | ||
1791 | 95 | } | ||
1792 | 96 | field(SIMM,DBF_MENU) { | ||
1793 | 97 | prompt("Simulation Mode") | ||
1794 | 98 | interest(1) | ||
1795 | 99 | menu(menuYesNo) | ||
1796 | 100 | } | ||
1797 | 101 | field(SIMS,DBF_MENU) { | ||
1798 | 102 | prompt("Sim mode Alarm Svrty") | ||
1799 | 103 | promptgroup(GUI_INPUTS) | ||
1800 | 104 | interest(2) | ||
1801 | 105 | menu(menuAlarmSevr) | ||
1802 | 106 | } | ||
1803 | 107 | field(SIOL,DBF_OUTLINK) { | ||
1804 | 108 | prompt("Sim Output Specifctn") | ||
1805 | 109 | promptgroup(GUI_INPUTS) | ||
1806 | 110 | interest(1) | ||
1807 | 111 | } | ||
1808 | 112 | } | ||
1809 | 0 | 113 | ||
1810 | === added file 'src/std/rec/printfRecord.c' | |||
1811 | --- src/std/rec/printfRecord.c 1970-01-01 00:00:00 +0000 | |||
1812 | +++ src/std/rec/printfRecord.c 2012-12-10 21:21:25 +0000 | |||
1813 | @@ -0,0 +1,438 @@ | |||
1814 | 1 | /*************************************************************************\ | ||
1815 | 2 | * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
1816 | 3 | * National Laboratory. | ||
1817 | 4 | * EPICS BASE is distributed subject to a Software License Agreement found | ||
1818 | 5 | * in file LICENSE that is included with this distribution. | ||
1819 | 6 | \*************************************************************************/ | ||
1820 | 7 | |||
1821 | 8 | /* Printf record type */ | ||
1822 | 9 | /* | ||
1823 | 10 | * Author: Andrew Johnson | ||
1824 | 11 | * Date: 2012-09-18 | ||
1825 | 12 | */ | ||
1826 | 13 | |||
1827 | 14 | #include <stddef.h> | ||
1828 | 15 | #include <string.h> | ||
1829 | 16 | |||
1830 | 17 | #include "dbDefs.h" | ||
1831 | 18 | #include "errlog.h" | ||
1832 | 19 | #include "alarm.h" | ||
1833 | 20 | #include "cantProceed.h" | ||
1834 | 21 | #include "dbAccess.h" | ||
1835 | 22 | #include "dbEvent.h" | ||
1836 | 23 | #include "dbFldTypes.h" | ||
1837 | 24 | #include "epicsMath.h" | ||
1838 | 25 | #include "epicsStdio.h" | ||
1839 | 26 | #include "errMdef.h" | ||
1840 | 27 | #include "recSup.h" | ||
1841 | 28 | #include "recGbl.h" | ||
1842 | 29 | #include "special.h" | ||
1843 | 30 | #define GEN_SIZE_OFFSET | ||
1844 | 31 | #include "printfRecord.h" | ||
1845 | 32 | #undef GEN_SIZE_OFFSET | ||
1846 | 33 | #include "epicsExport.h" | ||
1847 | 34 | |||
1848 | 35 | |||
1849 | 36 | /* Flag bits */ | ||
1850 | 37 | #define F_CHAR 1 | ||
1851 | 38 | #define F_SHORT 2 | ||
1852 | 39 | #define F_LONG 4 | ||
1853 | 40 | #define F_LEFT 8 | ||
1854 | 41 | #define F_BADFMT 0x10 | ||
1855 | 42 | #define F_BADLNK 0x20 | ||
1856 | 43 | #define F_BAD (F_BADFMT | F_BADLNK) | ||
1857 | 44 | |||
1858 | 45 | #define GET_PRINT(VALTYPE, DBRTYPE) \ | ||
1859 | 46 | VALTYPE val; \ | ||
1860 | 47 | int ok; \ | ||
1861 | 48 | \ | ||
1862 | 49 | if (plink->type == CONSTANT) \ | ||
1863 | 50 | ok = recGblInitConstantLink(plink++, DBRTYPE, &val); \ | ||
1864 | 51 | else \ | ||
1865 | 52 | ok = ! dbGetLink(plink++, DBRTYPE, &val, 0, 0); \ | ||
1866 | 53 | if (ok) \ | ||
1867 | 54 | added = epicsSnprintf(pval, vspace + 1, format, val); \ | ||
1868 | 55 | else \ | ||
1869 | 56 | flags |= F_BADLNK | ||
1870 | 57 | |||
1871 | 58 | static void doPrintf(printfRecord *prec) | ||
1872 | 59 | { | ||
1873 | 60 | const char *pfmt = prec->fmt; | ||
1874 | 61 | DBLINK *plink = &prec->inp0; | ||
1875 | 62 | int linkn = 0; | ||
1876 | 63 | char *pval = prec->val; | ||
1877 | 64 | int vspace = prec->sizv - 1; | ||
1878 | 65 | int ch; | ||
1879 | 66 | |||
1880 | 67 | while (vspace > 0 && (ch = *pfmt++)) { | ||
1881 | 68 | if (ch != '%') { | ||
1882 | 69 | /* Copy literal strings directly into prec->val */ | ||
1883 | 70 | *pval++ = ch; | ||
1884 | 71 | --vspace; | ||
1885 | 72 | } | ||
1886 | 73 | else { | ||
1887 | 74 | char format[20]; | ||
1888 | 75 | char *pformat = format; | ||
1889 | 76 | int width = 0; | ||
1890 | 77 | int precision = 0; | ||
1891 | 78 | int *pnum = &width; | ||
1892 | 79 | int flags = 0; | ||
1893 | 80 | int added = 0; | ||
1894 | 81 | int cont = 1; | ||
1895 | 82 | |||
1896 | 83 | /* The format directive parsing here is not comprehensive, | ||
1897 | 84 | * in most cases we just copy each directive into format[] | ||
1898 | 85 | * and get epicsSnprintf() do all the work. We do replace | ||
1899 | 86 | * all variable-length field width or precision '*' chars | ||
1900 | 87 | * with an integer read from the next input link, and we | ||
1901 | 88 | * also convert %ls (long string) directives ourself, so | ||
1902 | 89 | * we need to know the width, precision and justification. | ||
1903 | 90 | */ | ||
1904 | 91 | |||
1905 | 92 | *pformat++ = ch; /* '%' */ | ||
1906 | 93 | while (cont && (ch = *pfmt++)) { | ||
1907 | 94 | *pformat++ = ch; | ||
1908 | 95 | switch (ch) { | ||
1909 | 96 | case '+': case ' ': case '#': | ||
1910 | 97 | break; | ||
1911 | 98 | case '-': | ||
1912 | 99 | flags |= F_LEFT; | ||
1913 | 100 | break; | ||
1914 | 101 | case '.': | ||
1915 | 102 | pnum = &precision; | ||
1916 | 103 | break; | ||
1917 | 104 | case '0': case '1': case '2': case '3': case '4': | ||
1918 | 105 | case '5': case '6': case '7': case '8': case '9': | ||
1919 | 106 | *pnum = *pnum * 10 + ch - '0'; | ||
1920 | 107 | break; | ||
1921 | 108 | case '*': | ||
1922 | 109 | if (*pnum) { | ||
1923 | 110 | flags |= F_BADFMT; | ||
1924 | 111 | } | ||
1925 | 112 | else if (linkn++ < PRINTF_NLINKS) { | ||
1926 | 113 | epicsInt16 i; | ||
1927 | 114 | int ok; | ||
1928 | 115 | |||
1929 | 116 | if (plink->type == CONSTANT) | ||
1930 | 117 | ok = recGblInitConstantLink(plink++, DBR_SHORT, &i); | ||
1931 | 118 | else | ||
1932 | 119 | ok = ! dbGetLink(plink++, DBR_SHORT, &i, 0, 0); | ||
1933 | 120 | if (ok) { | ||
1934 | 121 | *pnum = i; | ||
1935 | 122 | added = epicsSnprintf(--pformat, 6, "%d", i); | ||
1936 | 123 | pformat += added; | ||
1937 | 124 | } | ||
1938 | 125 | else /* No more LNKn fields */ | ||
1939 | 126 | flags |= F_BADLNK; | ||
1940 | 127 | } | ||
1941 | 128 | else | ||
1942 | 129 | flags |= F_BADLNK; | ||
1943 | 130 | break; | ||
1944 | 131 | case 'h': | ||
1945 | 132 | if (flags & F_SHORT) | ||
1946 | 133 | flags = (flags & ~F_SHORT) | F_CHAR; | ||
1947 | 134 | else | ||
1948 | 135 | flags |= F_SHORT; | ||
1949 | 136 | break; | ||
1950 | 137 | case 'l': | ||
1951 | 138 | flags |= F_LONG; | ||
1952 | 139 | break; | ||
1953 | 140 | default: | ||
1954 | 141 | if (strchr("diouxXeEfFgGcs%", ch) == NULL) | ||
1955 | 142 | flags |= F_BADFMT; | ||
1956 | 143 | cont = 0; | ||
1957 | 144 | break; | ||
1958 | 145 | } | ||
1959 | 146 | } | ||
1960 | 147 | if (!ch) /* End of format string */ | ||
1961 | 148 | break; | ||
1962 | 149 | |||
1963 | 150 | if (flags & F_BAD) | ||
1964 | 151 | goto bad_format; | ||
1965 | 152 | |||
1966 | 153 | *pformat = 0; /* Terminate our format string */ | ||
1967 | 154 | |||
1968 | 155 | if (width < 0) { | ||
1969 | 156 | width = -width; | ||
1970 | 157 | flags |= F_LEFT; | ||
1971 | 158 | } | ||
1972 | 159 | if (precision < 0) | ||
1973 | 160 | precision = 0; | ||
1974 | 161 | |||
1975 | 162 | if (ch == '%') { | ||
1976 | 163 | added = epicsSnprintf(pval, vspace + 1, format); | ||
1977 | 164 | } | ||
1978 | 165 | else if (linkn++ >= PRINTF_NLINKS) { | ||
1979 | 166 | /* No more LNKn fields */ | ||
1980 | 167 | flags |= F_BADLNK; | ||
1981 | 168 | } | ||
1982 | 169 | else | ||
1983 | 170 | switch (ch) { /* Conversion character */ | ||
1984 | 171 | case 'c': case 'd': case 'i': | ||
1985 | 172 | if (ch == 'c' || flags & F_CHAR) { | ||
1986 | 173 | GET_PRINT(epicsInt8, DBR_CHAR); | ||
1987 | 174 | } | ||
1988 | 175 | else if (flags & F_SHORT) { | ||
1989 | 176 | GET_PRINT(epicsInt16, DBR_SHORT); | ||
1990 | 177 | } | ||
1991 | 178 | else { /* F_LONG has no real effect */ | ||
1992 | 179 | GET_PRINT(epicsInt32, DBR_LONG); | ||
1993 | 180 | } | ||
1994 | 181 | break; | ||
1995 | 182 | |||
1996 | 183 | case 'o': case 'x': case 'X': case 'u': | ||
1997 | 184 | if (flags & F_CHAR) { | ||
1998 | 185 | GET_PRINT(epicsUInt8, DBR_UCHAR); | ||
1999 | 186 | } | ||
2000 | 187 | else if (flags & F_SHORT) { | ||
2001 | 188 | GET_PRINT(epicsUInt16, DBR_USHORT); | ||
2002 | 189 | } | ||
2003 | 190 | else { /* F_LONG has no real effect */ | ||
2004 | 191 | GET_PRINT(epicsUInt32, DBR_ULONG); | ||
2005 | 192 | } | ||
2006 | 193 | break; | ||
2007 | 194 | |||
2008 | 195 | case 'e': case 'E': | ||
2009 | 196 | case 'f': case 'F': | ||
2010 | 197 | case 'g': case 'G': | ||
2011 | 198 | if (flags & F_SHORT) { | ||
2012 | 199 | GET_PRINT(epicsFloat32, DBR_FLOAT); | ||
2013 | 200 | } | ||
2014 | 201 | else { | ||
2015 | 202 | GET_PRINT(epicsFloat64, DBR_DOUBLE); | ||
2016 | 203 | } | ||
2017 | 204 | break; | ||
2018 | 205 | |||
2019 | 206 | case 's': | ||
2020 | 207 | if (flags & F_LONG && plink->type != CONSTANT) { | ||
2021 | 208 | long n = vspace + 1; | ||
2022 | 209 | |||
2023 | 210 | if (precision && n > precision) | ||
2024 | 211 | n = precision + 1; | ||
2025 | 212 | /* If set, precision is the maximum number of | ||
2026 | 213 | * characters to be printed from the string. | ||
2027 | 214 | * It does not limit the field width however. | ||
2028 | 215 | */ | ||
2029 | 216 | if (dbGetLink(plink++, DBR_CHAR, pval, 0, &n)) | ||
2030 | 217 | flags |= F_BADLNK; | ||
2031 | 218 | else { | ||
2032 | 219 | int padding; | ||
2033 | 220 | |||
2034 | 221 | /* Terminate string and measure its length */ | ||
2035 | 222 | pval[n] = 0; | ||
2036 | 223 | added = strlen(pval); | ||
2037 | 224 | padding = width - added; | ||
2038 | 225 | |||
2039 | 226 | if (padding > 0) { | ||
2040 | 227 | if (flags & F_LEFT) { | ||
2041 | 228 | /* add spaces on RHS */ | ||
2042 | 229 | if (width > vspace) | ||
2043 | 230 | padding = vspace - added; | ||
2044 | 231 | memset(pval + added, ' ', padding); | ||
2045 | 232 | } | ||
2046 | 233 | else { | ||
2047 | 234 | /* insert spaces on LHS */ | ||
2048 | 235 | int trunc = width - vspace; | ||
2049 | 236 | |||
2050 | 237 | if (trunc < added) { | ||
2051 | 238 | added -= trunc; | ||
2052 | 239 | memmove(pval + padding, pval, added); | ||
2053 | 240 | } | ||
2054 | 241 | else { | ||
2055 | 242 | padding = vspace; | ||
2056 | 243 | added = 0; | ||
2057 | 244 | } | ||
2058 | 245 | memset(pval, ' ', padding); | ||
2059 | 246 | } | ||
2060 | 247 | added += padding; | ||
2061 | 248 | } | ||
2062 | 249 | } | ||
2063 | 250 | } | ||
2064 | 251 | else { | ||
2065 | 252 | char val[MAX_STRING_SIZE]; | ||
2066 | 253 | int ok; | ||
2067 | 254 | |||
2068 | 255 | if (plink->type == CONSTANT) | ||
2069 | 256 | ok = recGblInitConstantLink(plink++, DBR_STRING, val); | ||
2070 | 257 | else | ||
2071 | 258 | ok = ! dbGetLink(plink++, DBR_STRING, val, 0, 0); | ||
2072 | 259 | if (ok) | ||
2073 | 260 | added = epicsSnprintf(pval, vspace + 1, format, val); | ||
2074 | 261 | else | ||
2075 | 262 | flags |= F_BADLNK; | ||
2076 | 263 | } | ||
2077 | 264 | break; | ||
2078 | 265 | |||
2079 | 266 | default: | ||
2080 | 267 | errlogPrintf("printfRecord: Unexpected conversion '%s'\n", | ||
2081 | 268 | format); | ||
2082 | 269 | flags |= F_BADFMT; | ||
2083 | 270 | break; | ||
2084 | 271 | } | ||
2085 | 272 | |||
2086 | 273 | if (flags & F_BAD) { | ||
2087 | 274 | bad_format: | ||
2088 | 275 | added = epicsSnprintf(pval, vspace + 1, "%s", | ||
2089 | 276 | flags & F_BADLNK ? prec->ivls : format); | ||
2090 | 277 | } | ||
2091 | 278 | |||
2092 | 279 | if (added <= vspace) { | ||
2093 | 280 | pval += added; | ||
2094 | 281 | vspace -= added; | ||
2095 | 282 | } | ||
2096 | 283 | else { | ||
2097 | 284 | /* Output was truncated */ | ||
2098 | 285 | pval += vspace; | ||
2099 | 286 | vspace = 0; | ||
2100 | 287 | } | ||
2101 | 288 | } | ||
2102 | 289 | } | ||
2103 | 290 | *pval++ = 0; /* Terminate the VAL string */ | ||
2104 | 291 | prec->len = pval - prec->val; | ||
2105 | 292 | } | ||
2106 | 293 | |||
2107 | 294 | |||
2108 | 295 | static long init_record(printfRecord *prec, int pass) | ||
2109 | 296 | { | ||
2110 | 297 | printfdset *pdset; | ||
2111 | 298 | |||
2112 | 299 | if (pass == 0) { | ||
2113 | 300 | size_t sizv = prec->sizv; | ||
2114 | 301 | |||
2115 | 302 | if (sizv < 16) { | ||
2116 | 303 | sizv = 16; /* Enforce a minimum size for the VAL field */ | ||
2117 | 304 | prec->sizv = sizv; | ||
2118 | 305 | } | ||
2119 | 306 | |||
2120 | 307 | prec->val = callocMustSucceed(1, sizv, "printf::init_record"); | ||
2121 | 308 | prec->len = 0; | ||
2122 | 309 | return 0; | ||
2123 | 310 | } | ||
2124 | 311 | |||
2125 | 312 | pdset = (printfdset *) prec->dset; | ||
2126 | 313 | if (!pdset) | ||
2127 | 314 | return 0; /* Device support is optional */ | ||
2128 | 315 | |||
2129 | 316 | if (pdset->number < 5) { | ||
2130 | 317 | recGblRecordError(S_dev_missingSup, prec, "printf::init_record"); | ||
2131 | 318 | return S_dev_missingSup; | ||
2132 | 319 | } | ||
2133 | 320 | |||
2134 | 321 | if (pdset->init_record) { | ||
2135 | 322 | long status = pdset->init_record(prec); | ||
2136 | 323 | if (status) | ||
2137 | 324 | return status; | ||
2138 | 325 | } | ||
2139 | 326 | |||
2140 | 327 | return 0; | ||
2141 | 328 | } | ||
2142 | 329 | |||
2143 | 330 | static long process(printfRecord *prec) | ||
2144 | 331 | { | ||
2145 | 332 | int pact = prec->pact; | ||
2146 | 333 | printfdset *pdset; | ||
2147 | 334 | long status = 0; | ||
2148 | 335 | epicsUInt16 events; | ||
2149 | 336 | |||
2150 | 337 | if (!pact) { | ||
2151 | 338 | doPrintf(prec); | ||
2152 | 339 | |||
2153 | 340 | prec->udf = FALSE; | ||
2154 | 341 | recGblGetTimeStamp(prec); | ||
2155 | 342 | } | ||
2156 | 343 | |||
2157 | 344 | /* Call device support */ | ||
2158 | 345 | pdset = (printfdset *) prec->dset; | ||
2159 | 346 | if (pdset && | ||
2160 | 347 | pdset->number >= 5 && | ||
2161 | 348 | pdset->write_string) { | ||
2162 | 349 | status = pdset->write_string(prec); | ||
2163 | 350 | |||
2164 | 351 | /* Asynchronous if device support set pact */ | ||
2165 | 352 | if (!pact && prec->pact) | ||
2166 | 353 | return status; | ||
2167 | 354 | } | ||
2168 | 355 | |||
2169 | 356 | prec->pact = TRUE; | ||
2170 | 357 | |||
2171 | 358 | /* Post monitor */ | ||
2172 | 359 | events = recGblResetAlarms(prec); | ||
2173 | 360 | db_post_events(prec, prec->val, events | DBE_VALUE | DBE_LOG); | ||
2174 | 361 | db_post_events(prec, &prec->len, events | DBE_VALUE | DBE_LOG); | ||
2175 | 362 | |||
2176 | 363 | /* Wrap up */ | ||
2177 | 364 | recGblFwdLink(prec); | ||
2178 | 365 | prec->pact = FALSE; | ||
2179 | 366 | return status; | ||
2180 | 367 | } | ||
2181 | 368 | |||
2182 | 369 | static long cvt_dbaddr(DBADDR *paddr) | ||
2183 | 370 | { | ||
2184 | 371 | printfRecord *prec = (printfRecord *)paddr->precord; | ||
2185 | 372 | int fieldIndex = dbGetFieldIndex(paddr); | ||
2186 | 373 | |||
2187 | 374 | if (fieldIndex == printfRecordVAL) { | ||
2188 | 375 | paddr->pfield = prec->val; | ||
2189 | 376 | paddr->no_elements = 1; | ||
2190 | 377 | paddr->field_type = DBF_STRING; | ||
2191 | 378 | paddr->dbr_field_type = DBF_STRING; | ||
2192 | 379 | paddr->field_size = prec->sizv; | ||
2193 | 380 | } | ||
2194 | 381 | else | ||
2195 | 382 | errlogPrintf("printfRecord::cvt_dbaddr called for %s.%s\n", | ||
2196 | 383 | prec->name, paddr->pfldDes->name); | ||
2197 | 384 | return 0; | ||
2198 | 385 | } | ||
2199 | 386 | |||
2200 | 387 | static long get_array_info(DBADDR *paddr, long *no_elements, long *offset) | ||
2201 | 388 | { | ||
2202 | 389 | printfRecord *prec = (printfRecord *) paddr->precord; | ||
2203 | 390 | |||
2204 | 391 | *no_elements = prec->len; | ||
2205 | 392 | *offset = 0; | ||
2206 | 393 | return 0; | ||
2207 | 394 | } | ||
2208 | 395 | |||
2209 | 396 | |||
2210 | 397 | /* Create Record Support Entry Table */ | ||
2211 | 398 | |||
2212 | 399 | #define report NULL | ||
2213 | 400 | #define initialize NULL | ||
2214 | 401 | /* init_record */ | ||
2215 | 402 | /* process */ | ||
2216 | 403 | #define special NULL | ||
2217 | 404 | #define get_value NULL | ||
2218 | 405 | /* cvt_dbaddr */ | ||
2219 | 406 | /* get_array_info */ | ||
2220 | 407 | #define put_array_info NULL | ||
2221 | 408 | #define get_units NULL | ||
2222 | 409 | #define get_precision NULL | ||
2223 | 410 | #define get_enum_str NULL | ||
2224 | 411 | #define get_enum_strs NULL | ||
2225 | 412 | #define put_enum_str NULL | ||
2226 | 413 | #define get_graphic_double NULL | ||
2227 | 414 | #define get_control_double NULL | ||
2228 | 415 | #define get_alarm_double NULL | ||
2229 | 416 | |||
2230 | 417 | rset printfRSET = { | ||
2231 | 418 | RSETNUMBER, | ||
2232 | 419 | report, | ||
2233 | 420 | initialize, | ||
2234 | 421 | init_record, | ||
2235 | 422 | process, | ||
2236 | 423 | special, | ||
2237 | 424 | get_value, | ||
2238 | 425 | cvt_dbaddr, | ||
2239 | 426 | get_array_info, | ||
2240 | 427 | put_array_info, | ||
2241 | 428 | get_units, | ||
2242 | 429 | get_precision, | ||
2243 | 430 | get_enum_str, | ||
2244 | 431 | get_enum_strs, | ||
2245 | 432 | put_enum_str, | ||
2246 | 433 | get_graphic_double, | ||
2247 | 434 | get_control_double, | ||
2248 | 435 | get_alarm_double | ||
2249 | 436 | }; | ||
2250 | 437 | epicsExportAddress(rset, printfRSET); | ||
2251 | 438 | |||
2252 | 0 | 439 | ||
2253 | === added file 'src/std/rec/printfRecord.dbd' | |||
2254 | --- src/std/rec/printfRecord.dbd 1970-01-01 00:00:00 +0000 | |||
2255 | +++ src/std/rec/printfRecord.dbd 2012-12-10 21:21:25 +0000 | |||
2256 | @@ -0,0 +1,109 @@ | |||
2257 | 1 | #************************************************************************* | ||
2258 | 2 | # Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne | ||
2259 | 3 | # National Laboratory. | ||
2260 | 4 | # EPICS BASE is distributed subject to a Software License Agreement found | ||
2261 | 5 | # in file LICENSE that is included with this distribution. | ||
2262 | 6 | #************************************************************************* | ||
2263 | 7 | |||
2264 | 8 | recordtype(printf) { | ||
2265 | 9 | include "dbCommon.dbd" | ||
2266 | 10 | %#include "devSup.h" | ||
2267 | 11 | % | ||
2268 | 12 | %/* Declare Device Support Entry Table */ | ||
2269 | 13 | %typedef struct printfdset { | ||
2270 | 14 | % long number; | ||
2271 | 15 | % DEVSUPFUN report; | ||
2272 | 16 | % DEVSUPFUN init; | ||
2273 | 17 | % DEVSUPFUN init_record; | ||
2274 | 18 | % DEVSUPFUN get_ioint_info; | ||
2275 | 19 | % DEVSUPFUN write_string; | ||
2276 | 20 | %} printfdset; | ||
2277 | 21 | % | ||
2278 | 22 | field(VAL,DBF_NOACCESS) { | ||
2279 | 23 | prompt("Result") | ||
2280 | 24 | asl(ASL0) | ||
2281 | 25 | pp(TRUE) | ||
2282 | 26 | special(SPC_DBADDR) | ||
2283 | 27 | extra("char *val") | ||
2284 | 28 | } | ||
2285 | 29 | field(SIZV,DBF_USHORT) { | ||
2286 | 30 | prompt("Size of VAL buffer") | ||
2287 | 31 | promptgroup(GUI_OUTPUT) | ||
2288 | 32 | special(SPC_NOMOD) | ||
2289 | 33 | interest(1) | ||
2290 | 34 | initial("41") | ||
2291 | 35 | } | ||
2292 | 36 | field(LEN,DBF_ULONG) { | ||
2293 | 37 | prompt("Length of VAL") | ||
2294 | 38 | special(SPC_NOMOD) | ||
2295 | 39 | } | ||
2296 | 40 | field(OUT,DBF_OUTLINK) { | ||
2297 | 41 | prompt("Output Specification") | ||
2298 | 42 | promptgroup(GUI_OUTPUT) | ||
2299 | 43 | interest(1) | ||
2300 | 44 | } | ||
2301 | 45 | field(FMT,DBF_STRING) { | ||
2302 | 46 | prompt("Format String") | ||
2303 | 47 | promptgroup(GUI_CALC) | ||
2304 | 48 | pp(TRUE) | ||
2305 | 49 | size(81) | ||
2306 | 50 | } | ||
2307 | 51 | field(IVLS,DBF_STRING) { | ||
2308 | 52 | prompt("Invalid Link String") | ||
2309 | 53 | promptgroup(GUI_CALC) | ||
2310 | 54 | size(16) | ||
2311 | 55 | initial("LNK") | ||
2312 | 56 | } | ||
2313 | 57 | field(INP0,DBF_INLINK) { | ||
2314 | 58 | prompt("Input 0") | ||
2315 | 59 | promptgroup(GUI_INPUTS) | ||
2316 | 60 | interest(1) | ||
2317 | 61 | } | ||
2318 | 62 | field(INP1,DBF_INLINK) { | ||
2319 | 63 | prompt("Input 1") | ||
2320 | 64 | promptgroup(GUI_INPUTS) | ||
2321 | 65 | interest(1) | ||
2322 | 66 | } | ||
2323 | 67 | field(INP2,DBF_INLINK) { | ||
2324 | 68 | prompt("Input 2") | ||
2325 | 69 | promptgroup(GUI_INPUTS) | ||
2326 | 70 | interest(1) | ||
2327 | 71 | } | ||
2328 | 72 | field(INP3,DBF_INLINK) { | ||
2329 | 73 | prompt("Input 3") | ||
2330 | 74 | promptgroup(GUI_INPUTS) | ||
2331 | 75 | interest(1) | ||
2332 | 76 | } | ||
2333 | 77 | field(INP4,DBF_INLINK) { | ||
2334 | 78 | prompt("Input 4") | ||
2335 | 79 | promptgroup(GUI_INPUTS) | ||
2336 | 80 | interest(1) | ||
2337 | 81 | } | ||
2338 | 82 | field(INP5,DBF_INLINK) { | ||
2339 | 83 | prompt("Input 5") | ||
2340 | 84 | promptgroup(GUI_INPUTS) | ||
2341 | 85 | interest(1) | ||
2342 | 86 | } | ||
2343 | 87 | field(INP6,DBF_INLINK) { | ||
2344 | 88 | prompt("Input 6") | ||
2345 | 89 | promptgroup(GUI_INPUTS) | ||
2346 | 90 | interest(1) | ||
2347 | 91 | } | ||
2348 | 92 | field(INP7,DBF_INLINK) { | ||
2349 | 93 | prompt("Input 7") | ||
2350 | 94 | promptgroup(GUI_INPUTS) | ||
2351 | 95 | interest(1) | ||
2352 | 96 | } | ||
2353 | 97 | field(INP8,DBF_INLINK) { | ||
2354 | 98 | prompt("Input 8") | ||
2355 | 99 | promptgroup(GUI_INPUTS) | ||
2356 | 100 | interest(1) | ||
2357 | 101 | } | ||
2358 | 102 | field(INP9,DBF_INLINK) { | ||
2359 | 103 | prompt("Input 9") | ||
2360 | 104 | promptgroup(GUI_INPUTS) | ||
2361 | 105 | interest(1) | ||
2362 | 106 | } | ||
2363 | 107 | %/* Number of INPx fields defined */ | ||
2364 | 108 | %#define PRINTF_NLINKS 10 | ||
2365 | 109 | } |
Nobody seems to care, so I'm merging this.