Merge ~anj/epics-base/+git/base-7.0:loadable-err-syms into ~epics-core/epics-base/+git/epics-base:7.0
- Git
- lp:~anj/epics-base/+git/base-7.0
- loadable-err-syms
- Merge into 7.0
Status: | Rejected |
---|---|
Rejected by: | Andrew Johnson |
Proposed branch: | ~anj/epics-base/+git/base-7.0:loadable-err-syms |
Merge into: | ~epics-core/epics-base/+git/epics-base:7.0 |
Diff against target: |
1562 lines (+606/-297) 28 files modified
configure/CONFIG (+4/-4) configure/RULES_BUILD (+1/-24) configure/RULES_FILE_TYPE (+11/-9) documentation/RELEASE_NOTES.html (+30/-1) modules/database/src/ioc/Makefile (+5/-0) modules/database/src/ioc/db/Makefile (+2/-1) modules/database/src/ioc/db/dbIocRegister.c (+6/-1) modules/database/src/ioc/dbStatic/Makefile (+6/-1) modules/libcom/configure/CONFIG_LIBCOM_MODULE (+4/-0) modules/libcom/configure/Makefile (+1/-0) modules/libcom/configure/RULES_LIBCOM (+38/-0) modules/libcom/src/Makefile (+8/-1) modules/libcom/src/as/Makefile (+3/-1) modules/libcom/src/env/Makefile (+0/-2) modules/libcom/src/error/Makefile (+4/-12) modules/libcom/src/error/RULES (+1/-4) modules/libcom/src/error/errMdef.h (+4/-6) modules/libcom/src/error/errSymLib.c (+189/-167) modules/libcom/src/error/errSymTbl.h (+14/-14) modules/libcom/src/error/errlog.c (+1/-3) modules/libcom/src/error/makeStatTbl.pl (+151/-39) modules/libcom/src/iocsh/libComRegister.c (+18/-3) modules/libcom/src/misc/Makefile (+3/-1) modules/libcom/src/osi/Makefile (+4/-1) modules/libcom/src/pool/Makefile (+3/-2) modules/libcom/test/Makefile (+5/-0) modules/libcom/test/epicsRunLibComTests.c (+2/-0) modules/libcom/test/errSymTest.c (+88/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Disapprove | ||
mdavidsaver | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change
This branch changes the error symbol registration code in libCom so additional error symbols can be registered by modules and applications as necessary. It also restores the error symbols defined by the IOC subsystems which were lost when we split off the database module, calling the newly-generated registration routine from the same code that registers iocsh commands.
Macros are provided so external code can easily detect whether their libCom version supports this.
Still to do:
* Write release notes.
* Instrument an external module to make use of this (ipac)
* No self-tests yet...
Questions:
There is no unregistration (never has been), but re-registering an existing symbol is (intended to be) silent. Is this acceptable?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Johnson (anj) wrote : | # |
- 91b098c... by Andrew Johnson
-
To avoid linking issues on Windows, make errSymsAdd() static
The generated errSyms.c file must now be #included by the source
file that calls the now static errSymsAdd() routine.
This also requires a dependency rule to ensure the .c file gets
generated early enough in the build. - 6ae8c62... by Andrew Johnson
-
Release notes and conversion instructions
- 960c9e7... by Andrew Johnson
-
Added unit tests in errSymTest.c
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Johnson (anj) wrote : | # |
Added basic unit tests for symbol registration and lookup functionality.
I think this is done for now.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
mdavidsaver (mdavidsaver) wrote : | # |
So I have to ask. As this is effectively new functionality as far as external modules are concerned. Do we want to expose another code generator just for error message strings?
As the error code are already hard-coded in headers, why not just add
> void errSymAdd(long status, const char *message);
Which would be called in registrar functions.
Please understand, I'm not saying "no" to this approach. I'd just like to have the design discussion.
Also, the diff shows some seemingly unrelated makefile changes (antelope/flex rules).
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ralph Lange (ralph-lange) wrote : | # |
Thanks a lot, Andrew, for jumping in.
I know this was on my list, I had started to work on it, and obviously lost that working copy at some point. (Definitely when my laptop was replaced a month ago.)
IMHO Michael's questions are valid, though.
From a module author perspective, I would start wishing for a code generator as soon as I have to register more than ~5-10 symbols manually in my registrar. How many modules define more? Close to none, I guess.
Also, if we seriously export this mechanism to external modules, I think the module itself should first register with its name and get a module code in return that it uses for registering symbols (to avoid the unavoidable clashes in the hardcoded module numbers).
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Johnson (anj) wrote : | # |
So the trigger behind this was a question from a colleague here who has been maintaining the epvxi (EPICS VXI) code that we still use here. The epvxi module was originally written by Jeff Hill and was part of Base back in 3.13 days, and as such it has its own series of error status values (34 of them), which were included in the generated errSymTbl.c file. The epvxi code calls the errPrintf() routine to display its errors, which takes a status value and shows the associated message. When we updated our VXI systems from 3.13 to 3.14 they lost the ability to display the epvxi error messages properly.
He asked me more recently how to fix this in 3.14.12.x, and I suggested he try the routine
int errSymbolAdd(long errNum, const char *name);
which was declared in errMdef.h (although we moved it to errSymTbl.h in 7.0.2). Unfortunately this routine only adds the symbol to an internal linked list and not to the hash table that actually gets used for symbol lookups, so it doesn't do what we'd want it to and there's no way to fix that externally. That prompted me to work on this when I had some time over Christmas.
So my requirement was to be able to support existing header files with error symbol definitions and just require calling a registration routine to add them to the errSym hash-table. I wanted to impose minimal work on the module maintainer without breaking a build against older Base releases that don't have the new APIs. I regarded this more as restoring capabilities that we lost when we unbundled the hardware-specific modules (and again when we split Base into modules) than as adding new functionality.
So why didn't I just fix the above errSymbolAdd() routine? Well nobody can be relying on that API at the moment, since it doesn't actually work, so that gives us license to change the prototype. I also wanted to add a separate string to hold the "S_<module>
Finally I wanted to try to ensure that all the strings would be stored in the program text and not have to be needlessly copied into RAM at registration time. I decided it would be simpler and faster to use an API that takes a const ERRSYMBOL pointer with all of the information included in that one object (this structure already existed in the old API, I just extended it) and to store that pointer.
I wouldn't object to adding an API for registering an error symbol that would take the 3 arguments separately, but in practice I don't see a great deal of difference:
static const ERRSYMBOL es_one = {S_x_one, "S_x_one", "Error one"};
errSymAdd(
vs
errSymAdd(
There's no way to mark that we store the string pointers and force the user to not generate those strings (or the ERRSYMBOL object) in a reusable buffer. I see that as a bit less likely when they have to pass in an object pointer, but I admit that's not guaranteed there either. In most cases you'll be registering multiple symbols so you'd usually call the other API to pass in an ERRSYMTAB which has an array...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ralph Lange (ralph-lange) wrote : | # |
Re: module number clashes
I think a run time test for clashes would be good and useful for the existing modules (that blindly claim a number).
We might still want to add a call to get a unique module number, so that new developments (or fixes for discovered clashes) have the chance to handle this issue smarter.
Also, the dump could use module names for those that did register.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ralph Lange (ralph-lange) wrote : | # |
Having every IOC use a different number for the same error would be a debugging nightmare.
Modules should try to register their claimed number, and get a different one back if it is taken. (Maybe on a different "page", e.g. claimed+200 or similar.)
- 4522666... by Andrew Johnson
-
errSymAdd: Add duplicate value check, return error on rejection
Also switches to calloc() instead of callocMustSucceed()
- 6e48e78... by Andrew Johnson
-
Register M_<module> symbols too
Adds errMDef.h to the headers parsed.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Johnson (anj) wrote : | # |
More commits. I am now checking for duplicate module numbers by registering the M_xxx symbols and their status values too. I added code to errSymAdd() that rejects the re-registration of a status value if the symbol names (i.e. the S_xxx_yyyy identifiers) are different. I assume the message texts for the same symbol name should be interchangeable even it they aren't identical.
I haven't added an API for handing out module numbers, I'm hoping that error messages at registration time will be enough to handle the case of clashing module numbers, e.g:
errSymAdd: Status value (1234,1) is S_test_bug "Test Bug"
so can't be registered as S_check_bug "Check bug"
Should the generated registration code abort/suspend if it gets a rejection, preventing IOC startup? It doesn't yet.
If we don't add an API fixing a rejection will require manual intervention (and rebuilding at least one module), but this should be very rare. There aren't many modules that create their own status codes anyway. Maybe we should have an EPICS Module Numbering Authority (like IANA)?
I'm concerned that making module numbers dynamic by changing the M_<module> constants into a read of an extern long might trigger symbol decoration problems on Windows. I don't want to have to fix more of those kinds of problems in other people's downstream code...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ralph Lange (ralph-lange) wrote : | # |
As a lightweight alternative to creating an international institution:
Would adding a column in the EPICS Module database (on epics-controls.org) be a start?
- d4ea352... by Andrew Johnson
-
Cosmetic touches
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
mdavidsaver (mdavidsaver) wrote : | # |
So I wondered, who all is using errSymLookup() outside of Base?
The newer errSymMsg() doesn't yet have any outside users.
A github search shows:
https:/
https:/
https:/
https:/
https:/
also ca-gateway
So, mostly me.
A google search doesn't turn up anything more.
https:/
Of course this isn't going to find code which isn't public.
I would expect a similar ratio there though.
I see this as a commentary on the utility of these error message strings.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Johnson (anj) wrote : | # |
The main entry points used by older drivers were errMessage() and errPrintf() both of which take a status value argument and display/log the associated string. By having a central registry of message strings a module can display the strings from the modules it calls or pass on the error status values without having to identify them specifically. In C++ code an exception class provides a very similar use-case.
For example in Asyn the ni1014Config() routine (a startup script command for a VME GPIB card) has 3 calls to errMessage(
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
mdavidsaver (mdavidsaver) wrote : | # |
I don't like the idea of having to adjudicate error code conflicts between two modules which would otherwise not need to be aware of each other. At minimum, this API needs a redesign to avoid conflicts. Either by choosing codes at runtime (a la. asynPortDriver), or otherwise ensuring uniqueness. (Maybe by using/abusing a pointer address as a code?)
Maybe a reasonable comparison is with the errno codes and perror()/strerror() API. Which looks quite similar. There is no standard way to add custom codes.
I recall reading that some Linux dev. were thinking about ways to provide more info than errno can reasonably contain. This might be worth checking to see if anything came of this.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrew Johnson (anj) wrote : | # |
So I discovered that external code built against 3.14 *can* add error symbols at runtime, it just has to do so by calling errSymbolAdd() for each symbol before errlogInit() first gets run, which may be from an explicit call in the startup script, at iocInit, or whenever some code calls one of the errlogPrintf() functions. A C++ static constructor should be fine for registering symbols.
We are now using that approach for the epvxi module, so I am withdrawing this merge proposal.
Unmerged commits
- d4ea352... by Andrew Johnson
-
Cosmetic touches
- 6e48e78... by Andrew Johnson
-
Register M_<module> symbols too
Adds errMDef.h to the headers parsed.
- 4522666... by Andrew Johnson
-
errSymAdd: Add duplicate value check, return error on rejection
Also switches to calloc() instead of callocMustSucceed()
- 960c9e7... by Andrew Johnson
-
Added unit tests in errSymTest.c
- 6ae8c62... by Andrew Johnson
-
Release notes and conversion instructions
- 91b098c... by Andrew Johnson
-
To avoid linking issues on Windows, make errSymsAdd() static
The generated errSyms.c file must now be #included by the source
file that calls the now static errSymsAdd() routine.
This also requires a dependency rule to ensure the .c file gets
generated early enough in the build. - dd2350f... by Andrew Johnson
-
Define FEATURE_
LOADABLE_ ERR_SYMS so apps can build conditionally This both is a macro defined in errMdef.h and a Makefile variable.
- 9747f48... by Andrew Johnson
-
Register "errSymDump" as an iocsh command
- c381445... by Andrew Johnson
-
Add error symbol registration for the database module
- bf088cd... by Andrew Johnson
-
Name headers containing error symbols in their Makefile fragment
Preview Diff
1 | diff --git a/configure/CONFIG b/configure/CONFIG |
2 | index e40d3f5..48acebc 100644 |
3 | --- a/configure/CONFIG |
4 | +++ b/configure/CONFIG |
5 | @@ -93,11 +93,13 @@ endif # ifdef T_A |
6 | |
7 | # Include <top>/cfg/CONFIG* definitions from tops defined in RELEASE* files |
8 | # |
9 | +TOP_CFG_CONFIGS = $(wildcard $(INSTALL_CFG)/CONFIG*) |
10 | ifneq ($(CONFIG),$(TOP)/configure) |
11 | RELEASE_TOPS_REVERSE := $(shell \ |
12 | $(PERL) -e '$$,=" ";print reverse @ARGV' $(RELEASE_TOPS)) |
13 | - RELEASE_CFG_CONFIGS = $(foreach top, $(RELEASE_TOPS_REVERSE), \ |
14 | - $(wildcard $($(top))/cfg/CONFIG*)) |
15 | + RELEASE_CFG_CONFIGS = $(filter-out $(TOP_CFG_CONFIGS), \ |
16 | + $(foreach top, $(RELEASE_TOPS_REVERSE), \ |
17 | + $(wildcard $($(top))/cfg/CONFIG*))) |
18 | ifneq ($(RELEASE_CFG_CONFIGS),) |
19 | include $(RELEASE_CFG_CONFIGS) |
20 | endif |
21 | @@ -105,7 +107,6 @@ endif |
22 | |
23 | # Include $(INSTALL_CFG)/CONFIG* definitions |
24 | # |
25 | -TOP_CFG_CONFIGS = $(wildcard $(INSTALL_CFG)/CONFIG*) |
26 | ifneq ($(TOP_CFG_CONFIGS),) |
27 | include $(TOP_CFG_CONFIGS) |
28 | endif |
29 | @@ -118,4 +119,3 @@ ifdef T_A |
30 | -include $(HOME)/configure/CONFIG_USER.Common.$(T_A) |
31 | -include $(HOME)/configure/CONFIG_USER.$(EPICS_HOST_ARCH).$(T_A) |
32 | endif |
33 | - |
34 | diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD |
35 | index 2dc9dd5..344862d 100644 |
36 | --- a/configure/RULES_BUILD |
37 | +++ b/configure/RULES_BUILD |
38 | @@ -23,9 +23,6 @@ vpath %.rc $(USR_VPATH) $(ALL_SRC_DIRS) |
39 | vpath %.h $(USR_VPATH) $(ALL_SRC_DIRS) |
40 | vpath %.hpp $(USR_VPATH) $(ALL_SRC_DIRS) |
41 | vpath %.html $(USR_VPATH) $(ALL_SRC_DIRS) |
42 | -vpath %.skel.static $(USR_VPATH) $(ALL_SRC_DIRS) |
43 | -vpath %.y $(USR_VPATH) $(ALL_SRC_DIRS) |
44 | -vpath %.l $(USR_VPATH) $(ALL_SRC_DIRS) |
45 | |
46 | #--------------------------------------------------------------- |
47 | |
48 | @@ -75,7 +72,7 @@ HTMLS_DIR ?= . |
49 | # First target |
50 | |
51 | all: install |
52 | -ifeq ($(EPICS_HOST_ARCH),$T_A) |
53 | +ifeq ($(EPICS_HOST_ARCH),$(T_A)) |
54 | host: install |
55 | else |
56 | # Do nothing |
57 | @@ -247,26 +244,6 @@ $(TESTPRODNAME) $(PRODNAME): %$(EXE): |
58 | @$(RM) $@ |
59 | $(RCCMD) |
60 | |
61 | -YACCOPT ?= $($*_YACCOPT) |
62 | -# |
63 | -# rename the y.tab.h file only if we |
64 | -# are creating it |
65 | -# |
66 | -%.c: %.y |
67 | - @$(RM) $*.tab.c |
68 | - @$(RM) $*.tab.h |
69 | - $(YACC) -b$* $(YACCOPT) $< |
70 | - $(MV) $*.tab.c $*.c |
71 | - $(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,) |
72 | - |
73 | -# must be a separate rule since when not using '-d' the |
74 | -# prefix for .h will be different then .c |
75 | -%.h : %.c %.y |
76 | - |
77 | -%.c: %.l |
78 | - @$(RM) $@ |
79 | - $(LEX) $(LEXOPT) -o$@ $< |
80 | - |
81 | #--------------------------------------------------------------- |
82 | # Libraries, shared/DLL and stubs |
83 | |
84 | diff --git a/configure/RULES_FILE_TYPE b/configure/RULES_FILE_TYPE |
85 | index 5936fd5..bdec938 100644 |
86 | --- a/configure/RULES_FILE_TYPE |
87 | +++ b/configure/RULES_FILE_TYPE |
88 | @@ -17,10 +17,13 @@ ifneq ($(RELEASE_RULES_BUILDS),) |
89 | include $(RELEASE_RULES_BUILDS) |
90 | endif |
91 | |
92 | -# Include <top>/cfg/RULES* files from tops defined in RELEASE* files |
93 | +# Include <top>/cfg/RULES* files from tops defined in RELEASE* files, |
94 | +# excluding files in our own INSTALL_LOCATION |
95 | # |
96 | -RELEASE_CFG_RULES = $(foreach top, $(RELEASE_TOPS), \ |
97 | - $(wildcard $($(top))/cfg/RULES*)) |
98 | +TOP_CFG_RULES = $(wildcard $(INSTALL_CFG)/RULES*) |
99 | +RELEASE_CFG_RULES = $(filter-out $(TOP_CFG_RULES), \ |
100 | + $(foreach top, $(RELEASE_TOPS) INSTALL_LOCATION, \ |
101 | + $(wildcard $($(top))/cfg/RULES*))) |
102 | ifneq ($(RELEASE_CFG_RULES),) |
103 | include $(RELEASE_CFG_RULES) |
104 | endif |
105 | @@ -28,15 +31,14 @@ endif |
106 | # If this is not BASE then include <top>/configure/RULES_BUILD |
107 | # |
108 | ifeq ($(wildcard $(TOP)/configure/CONFIG_BASE_VERSION),) |
109 | -TOP_RULES_BUILDS = $(wildcard $(TOP)/configure/RULES_BUILD) |
110 | -ifneq ($(TOP_RULES_BUILDS),) |
111 | - include $(TOP_RULES_BUILDS) |
112 | -endif |
113 | + TOP_RULES_BUILDS = $(wildcard $(TOP)/configure/RULES_BUILD) |
114 | + ifneq ($(TOP_RULES_BUILDS),) |
115 | + include $(TOP_RULES_BUILDS) |
116 | + endif |
117 | endif |
118 | |
119 | -# Include our own $(INSTALL_CFG)/RULES* files |
120 | +# Now include our own $(INSTALL_CFG)/RULES* files |
121 | # |
122 | -TOP_CFG_RULES = $(wildcard $(INSTALL_CFG)/RULES*) |
123 | ifneq ($(TOP_CFG_RULES),) |
124 | include $(TOP_CFG_RULES) |
125 | endif |
126 | diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html |
127 | index 004f67b..43ad6aa 100644 |
128 | --- a/documentation/RELEASE_NOTES.html |
129 | +++ b/documentation/RELEASE_NOTES.html |
130 | @@ -21,7 +21,7 @@ which should also be read to understand what has changed since an earlier |
131 | release.</p> |
132 | |
133 | |
134 | -<h1 align="center">EPICS Release 7.0.2</h1> |
135 | +<h1 align="center">EPICS Release 7.0.3</h1> |
136 | |
137 | <!-- Insert new items immediately below this template ... |
138 | |
139 | @@ -31,6 +31,35 @@ release.</p> |
140 | |
141 | --> |
142 | |
143 | +<h3>Loadable Error Symbols</h3> |
144 | + |
145 | +<p>The error symbol registry code in libCom has been updated to allow symbols to |
146 | +be added after initialization time, and the Perl parser that generated symbol |
147 | +tables from header files included in EPICS Base has been converted into a |
148 | +generic tool that can be used by other modules to capture their error symbols |
149 | +and register them with the symbol registry. This change also permits error |
150 | +symbols defined by IOC code to be registered again (they had to be removed when |
151 | +Base was split into separate modules for the EPICS 7.0.1 release). A new iocsh |
152 | +command is also provided to display the contents of the symbol table.</p> |
153 | + |
154 | +<p>External modules that define their own error symbols (including modules that |
155 | +were unbundled from Base for the 3.14 release) can now register their own error |
156 | +symbols at initialization time. The recommended approach is for symbols to be |
157 | +defined in one or more header files and parsed by the <tt>makeStatTbl.pl</tt> |
158 | +script, which generates a C source file containing the data structures used for |
159 | +registering those symbols. This file also defines a static routine that must be |
160 | +called to perform the registration.</p> |
161 | + |
162 | +<p>Detailed information on how to add symbol registration to an external module |
163 | +can be obtained by giving the option <tt>-H</tt> to the <tt>makeStatTbl.pl</tt> |
164 | +Perl script found in the Base/bin/<i>host-arch</i> directory. The required |
165 | +changes can be made conditional on a macro that is only defined in EPICS |
166 | +releases that contain the new functionality, so the module will still build and |
167 | +run against older versions of EPICS Base.</p> |
168 | + |
169 | + |
170 | +<h1 align="center">EPICS Release 7.0.2</h1> |
171 | + |
172 | <h3>Launchpad Bugs</h3> |
173 | |
174 | <p>The list of tracked bugs fixed in this release can be found on the |
175 | diff --git a/modules/database/src/ioc/Makefile b/modules/database/src/ioc/Makefile |
176 | index 3258728..94a3202 100644 |
177 | --- a/modules/database/src/ioc/Makefile |
178 | +++ b/modules/database/src/ioc/Makefile |
179 | @@ -25,6 +25,9 @@ INC += databaseVersionNum.h |
180 | |
181 | PROD_LIBS = Com |
182 | |
183 | +STAT_TBL = dbIocErrSyms.c |
184 | +CLEANS += $(STAT_TBL) |
185 | + |
186 | include $(IOCDIR)/as/Makefile |
187 | include $(IOCDIR)/bpt/Makefile |
188 | include $(IOCDIR)/db/Makefile |
189 | @@ -53,3 +56,5 @@ include $(IOCDIR)/dbtemplate/RULES |
190 | ../O.Common/databaseVersionNum.h: ../databaseVersionNum.h@ |
191 | $(MKDIR) $(COMMON_DIR) |
192 | $(EXPAND_TOOL) $(EXPANDFLAGS) $($@_EXPANDFLAGS) $< $@ |
193 | + |
194 | +dbIocRegister$(DEP): $(STAT_TBL) |
195 | diff --git a/modules/database/src/ioc/db/Makefile b/modules/database/src/ioc/db/Makefile |
196 | index 2dc4fec..67e5264 100644 |
197 | --- a/modules/database/src/ioc/db/Makefile |
198 | +++ b/modules/database/src/ioc/db/Makefile |
199 | @@ -4,7 +4,7 @@ |
200 | # Copyright (c) 2002 The Regents of the University of California, as |
201 | # Operator of Los Alamos National Laboratory. |
202 | # EPICS BASE is distributed subject to a Software License Agreement found |
203 | -# in file LICENSE that is included with this distribution. |
204 | +# in file LICENSE that is included with this distribution. |
205 | #************************************************************************* |
206 | |
207 | # This is a Makefile fragment, see src/ioc/Makefile. |
208 | @@ -97,3 +97,4 @@ dbCore_SRCS += dbState.c |
209 | dbCore_SRCS += dbUnitTest.c |
210 | dbCore_SRCS += dbServer.c |
211 | |
212 | +ERR_S_FILES += $(IOCDIR)/db/dbAccessDefs.h |
213 | diff --git a/modules/database/src/ioc/db/dbIocRegister.c b/modules/database/src/ioc/db/dbIocRegister.c |
214 | index c40af92..e5053ea 100644 |
215 | --- a/modules/database/src/ioc/db/dbIocRegister.c |
216 | +++ b/modules/database/src/ioc/db/dbIocRegister.c |
217 | @@ -4,10 +4,11 @@ |
218 | * Copyright (c) 2002 The Regents of the University of California, as |
219 | * Operator of Los Alamos National Laboratory. |
220 | * EPICS BASE is distributed subject to a Software License Agreement found |
221 | -* in file LICENSE that is included with this distribution. |
222 | +* in file LICENSE that is included with this distribution. |
223 | \*************************************************************************/ |
224 | |
225 | #include "iocsh.h" |
226 | +#include "errSymTbl.h" |
227 | |
228 | #define epicsExportSharedSymbols |
229 | #include "callback.h" |
230 | @@ -421,8 +422,12 @@ static void dbStateShowAllCallFunc (const iocshArgBuf *args) |
231 | dbStateShowAll(args[0].ival); |
232 | } |
233 | |
234 | +#include "dbIocErrSyms.c" |
235 | + |
236 | void dbIocRegister(void) |
237 | { |
238 | + dbIocErrSymsAdd(); |
239 | + |
240 | iocshRegister(&dbbFuncDef,dbbCallFunc); |
241 | iocshRegister(&dbdFuncDef,dbdCallFunc); |
242 | iocshRegister(&dbcFuncDef,dbcCallFunc); |
243 | diff --git a/modules/database/src/ioc/dbStatic/Makefile b/modules/database/src/ioc/dbStatic/Makefile |
244 | index c962501..edbb749 100644 |
245 | --- a/modules/database/src/ioc/dbStatic/Makefile |
246 | +++ b/modules/database/src/ioc/dbStatic/Makefile |
247 | @@ -4,7 +4,7 @@ |
248 | # Copyright (c) 2002 The Regents of the University of California, as |
249 | # Operator of Los Alamos National Laboratory. |
250 | # EPICS BASE is distributed subject to a Software License Agreement found |
251 | -# in file LICENSE that is included with this distribution. |
252 | +# in file LICENSE that is included with this distribution. |
253 | #************************************************************************* |
254 | |
255 | # This is a Makefile fragment, see src/ioc/Makefile. |
256 | @@ -29,4 +29,9 @@ dbCore_SRCS += dbPvdLib.c |
257 | dbCore_SRCS += dbStaticRun.c |
258 | dbCore_SRCS += dbStaticIocRegister.c |
259 | |
260 | +ERR_S_FILES += $(IOCDIR)/dbStatic/dbStaticLib.h |
261 | +ERR_S_FILES += $(IOCDIR)/dbStatic/devSup.h |
262 | +ERR_S_FILES += $(IOCDIR)/dbStatic/drvSup.h |
263 | +ERR_S_FILES += $(IOCDIR)/dbStatic/recSup.h |
264 | + |
265 | CLEANS += dbLex.c dbYacc.c |
266 | diff --git a/modules/libcom/configure/CONFIG_LIBCOM_MODULE b/modules/libcom/configure/CONFIG_LIBCOM_MODULE |
267 | index 175606c..1267b2f 100644 |
268 | --- a/modules/libcom/configure/CONFIG_LIBCOM_MODULE |
269 | +++ b/modules/libcom/configure/CONFIG_LIBCOM_MODULE |
270 | @@ -17,9 +17,13 @@ endif |
271 | YACC = $(abspath $(EPICS_LIBCOM_HOST_BIN))/antelope$(HOSTEXE) |
272 | LEX = $(abspath $(EPICS_LIBCOM_HOST_BIN))/e_flex$(HOSTEXE) \ |
273 | -S$(EPICS_LIBCOM)/include/flex.skel.static |
274 | +MAKE_STAT_TBL = $(abspath $(EPICS_LIBCOM_HOST_BIN))/makeStatTbl.pl |
275 | |
276 | # Default stack size for osiThread |
277 | OSITHREAD_USE_DEFAULT_STACK = NO |
278 | OSITHREAD_DEFAULT_STACK_FLAGS_YES = -DOSITHREAD_USE_DEFAULT_STACK |
279 | |
280 | BASE_CPPFLAGS += $(OSITHREAD_DEFAULT_STACK_FLAGS_$(OSITHREAD_USE_DEFAULT_STACK)) |
281 | + |
282 | +# Features available |
283 | +FEATURE_LOADABLE_ERR_SYMS = 1 |
284 | diff --git a/modules/libcom/configure/Makefile b/modules/libcom/configure/Makefile |
285 | index 85a7b58..1fc9889 100644 |
286 | --- a/modules/libcom/configure/Makefile |
287 | +++ b/modules/libcom/configure/Makefile |
288 | @@ -11,5 +11,6 @@ CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) |
289 | |
290 | CFG += CONFIG_LIBCOM_MODULE |
291 | CFG += CONFIG_LIBCOM_VERSION |
292 | +CFG += RULES_LIBCOM |
293 | |
294 | include $(TOP)/configure/RULES |
295 | diff --git a/modules/libcom/configure/RULES_LIBCOM b/modules/libcom/configure/RULES_LIBCOM |
296 | new file mode 100644 |
297 | index 0000000..4f870bf |
298 | --- /dev/null |
299 | +++ b/modules/libcom/configure/RULES_LIBCOM |
300 | @@ -0,0 +1,38 @@ |
301 | +#************************************************************************* |
302 | +# EPICS BASE is distributed subject to a Software License Agreement found |
303 | +# in file LICENSE that is included with this distribution. |
304 | +#************************************************************************* |
305 | + |
306 | +vpath %.skel.static $(USR_VPATH) $(ALL_SRC_DIRS) |
307 | +vpath %.y $(USR_VPATH) $(ALL_SRC_DIRS) |
308 | +vpath %.l $(USR_VPATH) $(ALL_SRC_DIRS) |
309 | + |
310 | +# YACC = antelope |
311 | +# |
312 | +YACCOPT ?= $($*_YACCOPT) |
313 | +# |
314 | +# rename the y.tab.h file only if we |
315 | +# are creating it |
316 | +# |
317 | +%.c: %.y |
318 | + @$(RM) $*.tab.c |
319 | + @$(RM) $*.tab.h |
320 | + $(YACC) -b$* $(YACCOPT) $< |
321 | + $(MV) $*.tab.c $*.c |
322 | + $(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,) |
323 | + |
324 | +# must be a separate rule since when not using '-d' the |
325 | +# prefix for .h will be different then .c |
326 | +%.h : %.c %.y |
327 | + |
328 | +# LEX = e_flex |
329 | +# |
330 | +%.c: %.l |
331 | + @$(RM) $@ |
332 | + $(LEX) $(LEXOPT) -o$@ $< |
333 | + |
334 | +# MAKE_STAT_TBL = makeStatTbl.pl |
335 | +# |
336 | +$(STAT_TBL): $(ERR_S_FILES) $(MAKE_STAT_TBL) |
337 | + @$(RM) $@ |
338 | + $(PERL) $(MAKE_STAT_TBL) -o $@ $(STAT_TBL_OPTS) $(ERR_S_FILES) |
339 | diff --git a/modules/libcom/src/Makefile b/modules/libcom/src/Makefile |
340 | index d61b268..12ed3c4 100644 |
341 | --- a/modules/libcom/src/Makefile |
342 | +++ b/modules/libcom/src/Makefile |
343 | @@ -20,6 +20,9 @@ INC += valgrind/valgrind.h |
344 | INC += libComVersion.h |
345 | INC += libComVersionNum.h |
346 | |
347 | +STAT_TBL = libComErrSyms.c |
348 | +CLEANS += $(STAT_TBL) |
349 | + |
350 | include $(LIBCOM)/as/Makefile |
351 | include $(LIBCOM)/bucketLib/Makefile |
352 | include $(LIBCOM)/calc/Makefile |
353 | @@ -46,6 +49,9 @@ include $(LIBCOM)/timer/Makefile |
354 | include $(LIBCOM)/yacc/Makefile |
355 | include $(LIBCOM)/yajl/Makefile |
356 | |
357 | +# Find Perl scripts in source subdirectories |
358 | +vpath %.pl $(USR_VPATH) $(SRC_DIRS) |
359 | + |
360 | # Library to build: |
361 | LIBRARY=Com |
362 | |
363 | @@ -72,7 +78,6 @@ include $(TOP)/configure/RULES |
364 | |
365 | include $(LIBCOM)/as/RULES |
366 | include $(LIBCOM)/env/RULES |
367 | -include $(LIBCOM)/error/RULES |
368 | include $(LIBCOM)/flex/RULES |
369 | include $(LIBCOM)/misc/RULES |
370 | include $(LIBCOM)/osi/RULES |
371 | @@ -82,3 +87,5 @@ include $(LIBCOM)/yajl/RULES |
372 | # in O.Common, but EXPAND emits rules for O.$(T_A) |
373 | ../O.Common/libComVersionNum.h: ../libComVersionNum.h@ |
374 | $(EXPAND_TOOL) $(EXPANDFLAGS) $($@_EXPANDFLAGS) $< $@ |
375 | + |
376 | +libComRegister$(DEP): $(STAT_TBL) |
377 | diff --git a/modules/libcom/src/as/Makefile b/modules/libcom/src/as/Makefile |
378 | index 65f7520..bb76a4e 100644 |
379 | --- a/modules/libcom/src/as/Makefile |
380 | +++ b/modules/libcom/src/as/Makefile |
381 | @@ -6,7 +6,7 @@ |
382 | # Copyright (c) 2002 The Regents of the University of California, as |
383 | # Operator of Los Alamos National Laboratory. |
384 | # EPICS BASE is distributed subject to a Software License Agreement found |
385 | -# in file LICENSE that is included with this distribution. |
386 | +# in file LICENSE that is included with this distribution. |
387 | #************************************************************************ |
388 | |
389 | # This is a Makefile fragment, see src/libCom/Makefile. |
390 | @@ -16,6 +16,8 @@ SRC_DIRS += $(LIBCOM)/as |
391 | INC += asLib.h |
392 | INC += asTrapWrite.h |
393 | |
394 | +ERR_S_FILES += $(LIBCOM)/as/asLib.h |
395 | + |
396 | Com_SRCS += asLib.c |
397 | Com_SRCS += asTrapWrite.c |
398 | |
399 | diff --git a/modules/libcom/src/env/Makefile b/modules/libcom/src/env/Makefile |
400 | index 804426b..bd23581 100644 |
401 | --- a/modules/libcom/src/env/Makefile |
402 | +++ b/modules/libcom/src/env/Makefile |
403 | @@ -9,8 +9,6 @@ |
404 | |
405 | SRC_DIRS += $(LIBCOM)/env |
406 | |
407 | -vpath %.pl $(USR_VPATH) $(SRC_DIRS) |
408 | - |
409 | PERL_SCRIPTS += bldEnvData.pl |
410 | PERL_SCRIPTS += libcomModuleDirs.pm |
411 | |
412 | diff --git a/modules/libcom/src/error/Makefile b/modules/libcom/src/error/Makefile |
413 | index c79752c..c56fa33 100644 |
414 | --- a/modules/libcom/src/error/Makefile |
415 | +++ b/modules/libcom/src/error/Makefile |
416 | @@ -9,22 +9,14 @@ |
417 | |
418 | SRC_DIRS += $(LIBCOM)/error |
419 | |
420 | +PERL_SCRIPTS += makeStatTbl.pl |
421 | + |
422 | INC += epicsPrint.h |
423 | INC += errMdef.h |
424 | INC += errSymTbl.h |
425 | INC += errlog.h |
426 | |
427 | -Com_SRCS += errlog.c |
428 | -Com_SRCS += errSymLib.c |
429 | -Com_SRCS += errSymTbl.c |
430 | - |
431 | -# For bldErrSymTbl |
432 | -# |
433 | -ERR_S_FILES += $(LIBCOM)/osi/devLib.h |
434 | -ERR_S_FILES += $(LIBCOM)/osi/epicsTime.h |
435 | -ERR_S_FILES += $(LIBCOM)/as/asLib.h |
436 | -ERR_S_FILES += $(LIBCOM)/misc/epicsStdlib.h |
437 | -ERR_S_FILES += $(LIBCOM)/pool/epicsThreadPool.h |
438 | ERR_S_FILES += $(LIBCOM)/error/errMdef.h |
439 | |
440 | -CLEANS += errSymTbl.c |
441 | +Com_SRCS += errlog.c |
442 | +Com_SRCS += errSymLib.c |
443 | diff --git a/modules/libcom/src/error/RULES b/modules/libcom/src/error/RULES |
444 | index dc2926f..0b9318a 100644 |
445 | --- a/modules/libcom/src/error/RULES |
446 | +++ b/modules/libcom/src/error/RULES |
447 | @@ -2,10 +2,7 @@ |
448 | # Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne |
449 | # National Laboratory. |
450 | # EPICS BASE is distributed subject to a Software License Agreement found |
451 | -# in file LICENSE that is included with this distribution. |
452 | +# in file LICENSE that is included with this distribution. |
453 | #************************************************************************* |
454 | |
455 | # This is a Makefile fragment, see src/libCom/Makefile. |
456 | - |
457 | -errSymTbl.c: $(ERR_S_FILES) $(LIBCOM)/error/makeStatTbl.pl |
458 | - $(PERL) $(LIBCOM)/error/makeStatTbl.pl $(ERR_S_FILES) |
459 | diff --git a/modules/libcom/src/error/errMdef.h b/modules/libcom/src/error/errMdef.h |
460 | index 4f68f76..21c67c0 100644 |
461 | --- a/modules/libcom/src/error/errMdef.h |
462 | +++ b/modules/libcom/src/error/errMdef.h |
463 | @@ -17,12 +17,10 @@ |
464 | |
465 | #define RTN_SUCCESS(STATUS) ((STATUS)==0) |
466 | |
467 | -/* Module numbers start above 500 for compatibility with vxWorks errnoLib */ |
468 | +/* Feature detection for applications */ |
469 | +#define FEATURE_LOADABLE_ERR_SYMS |
470 | |
471 | -/* FIXME: M_xxx values could be declared as integer variables and set |
472 | - * at runtime from registration routines; the S_xxx definitions would |
473 | - * still work with that change, with careful initialization. |
474 | - */ |
475 | +/* Module numbers start above 500 for compatibility with vxWorks errnoLib */ |
476 | |
477 | /* libCom */ |
478 | #define M_asLib (501 << 16) /* Access Security */ |
479 | @@ -44,4 +42,4 @@ |
480 | #define M_gddFuncTbl (522 << 16) /* gdd jump table */ |
481 | #define M_casApp (523 << 16) /* CA server application */ |
482 | |
483 | -#endif /*INC_errMdef_H*/ |
484 | +#endif /* INC_errMdef_H */ |
485 | diff --git a/modules/libcom/src/error/errSymLib.c b/modules/libcom/src/error/errSymLib.c |
486 | index b220f2b..5e849a8 100644 |
487 | --- a/modules/libcom/src/error/errSymLib.c |
488 | +++ b/modules/libcom/src/error/errSymLib.c |
489 | @@ -1,5 +1,5 @@ |
490 | /*************************************************************************\ |
491 | -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
492 | +* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne |
493 | * National Laboratory. |
494 | * Copyright (c) 2002 The Regents of the University of California, as |
495 | * Operator of Los Alamos National Laboratory. |
496 | @@ -8,8 +8,6 @@ |
497 | \*************************************************************************/ |
498 | /* |
499 | * errSymLib.c |
500 | - * Author: Marty Kraimer |
501 | - * Date: 6-1-90 |
502 | */ |
503 | |
504 | #include <string.h> |
505 | @@ -21,8 +19,9 @@ |
506 | |
507 | #define epicsExportSharedSymbols |
508 | #include "cantProceed.h" |
509 | -#include "epicsAssert.h" |
510 | +#include "epicsMutex.h" |
511 | #include "epicsStdio.h" |
512 | +#include "epicsThread.h" |
513 | #include "errMdef.h" |
514 | #include "errSymTbl.h" |
515 | #include "ellLib.h" |
516 | @@ -30,159 +29,180 @@ |
517 | |
518 | #define NHASH 256 |
519 | |
520 | -static epicsUInt16 errhash(long errNum); |
521 | - |
522 | typedef struct errnumnode { |
523 | - ELLNODE node; |
524 | - long errNum; |
525 | - struct errnumnode *hashnode; |
526 | - const char *message; |
527 | - long pad; |
528 | + struct errnumnode *next; |
529 | + const ERRSYMBOL *p; |
530 | } ERRNUMNODE; |
531 | |
532 | -static ELLLIST errnumlist = ELLLIST_INIT; |
533 | -static ERRNUMNODE **hashtable; |
534 | -static int initialized = 0; |
535 | -extern ERRSYMTAB_ID errSymTbl; |
536 | +static epicsMutexId hashLock; /* protects hashTable */ |
537 | +static ERRNUMNODE **hashTable; |
538 | +static int hashEntries; |
539 | + |
540 | +/*************************************************************** |
541 | + * errSymInit |
542 | + ***************************************************************/ |
543 | + |
544 | +static |
545 | +void errSymOnce(void * dummy) |
546 | +{ |
547 | + hashTable = (ERRNUMNODE **)callocMustSucceed |
548 | + (NHASH, sizeof(ERRNUMNODE *), "errSymOnce"); |
549 | + hashLock = epicsMutexMustCreate(); |
550 | + hashEntries = 0; |
551 | +} |
552 | + |
553 | +static |
554 | +int errSymInit(void) |
555 | +{ |
556 | + static epicsThreadOnceId once = EPICS_THREAD_ONCE_INIT; |
557 | + |
558 | + epicsThreadOnce(&once, errSymOnce, NULL); |
559 | + return hashEntries; |
560 | +} |
561 | |
562 | /**************************************************************** |
563 | - * ERRSYMBLD |
564 | - * |
565 | - * Create the normal ell LIST of sorted error messages nodes |
566 | - * Followed by linked hash lists - that link together those |
567 | - * ell nodes that have a common hash number. |
568 | - * |
569 | + * errSymTabAdd |
570 | + * adds a list of symbols to hash table |
571 | ***************************************************************/ |
572 | -int errSymBld(void) |
573 | +int errSymTabAdd(ERRSYMTAB *errtab) |
574 | { |
575 | - ERRSYMBOL *errArray = errSymTbl->symbols; |
576 | - ERRNUMNODE *perrNumNode = NULL; |
577 | - ERRNUMNODE *pNextNode = NULL; |
578 | - ERRNUMNODE **phashnode = NULL; |
579 | - int i; |
580 | - int modnum; |
581 | - |
582 | - if (initialized) |
583 | - return(0); |
584 | - |
585 | - hashtable = (ERRNUMNODE**)callocMustSucceed |
586 | - (NHASH, sizeof(ERRNUMNODE*),"errSymBld"); |
587 | - for (i = 0; i < errSymTbl->nsymbols; i++, errArray++) { |
588 | - modnum = errArray->errNum >> 16; |
589 | + const ERRSYMBOL *symbol = errtab->symbols; |
590 | + int i; |
591 | + |
592 | + errSymInit(); |
593 | + |
594 | + for (i = 0; i < errtab->nsymbols; i++, symbol++) { |
595 | + epicsUInt16 modnum = (symbol->status >> 16) & 0xffff; |
596 | + |
597 | if (modnum < 501) { |
598 | - fprintf(stderr, "errSymBld: ERROR - Module number in errSymTbl < 501 was Module=%lx Name=%s\n", |
599 | - errArray->errNum, errArray->name); |
600 | - continue; |
601 | - } |
602 | - if ((errSymbolAdd(errArray->errNum, errArray->name)) < 0) { |
603 | - fprintf(stderr, "errSymBld: ERROR - errSymbolAdd() failed \n"); |
604 | + epicsUInt16 errnum = symbol->status & 0xffff; |
605 | + fprintf(stderr, "errSymTabAdd: Bad module number for\n" |
606 | + " %-25s = (%3u,%2u) \"%s\"\n", |
607 | + symbol->sym, modnum, errnum, symbol->msg); |
608 | continue; |
609 | } |
610 | + errSymAdd(symbol); |
611 | } |
612 | - perrNumNode = (ERRNUMNODE *) ellFirst(&errnumlist); |
613 | - while (perrNumNode) { |
614 | - /* hash each perrNumNode->errNum */ |
615 | - epicsUInt16 hashInd = errhash(perrNumNode->errNum); |
616 | - |
617 | - phashnode = (ERRNUMNODE**)&hashtable[hashInd]; |
618 | - pNextNode = (ERRNUMNODE*) *phashnode; |
619 | - /* search for last node (NULL) of hashnode linked list */ |
620 | - while (pNextNode) { |
621 | - phashnode = &pNextNode->hashnode; |
622 | - pNextNode = *phashnode; |
623 | - } |
624 | - *phashnode = perrNumNode; |
625 | - perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode); |
626 | - } |
627 | - initialized = 1; |
628 | - return(0); |
629 | + return 0; |
630 | } |
631 | |
632 | /**************************************************************** |
633 | - * HASH |
634 | - * returns the hash index of errNum |
635 | + * errHash |
636 | + * returns the hash index of status |
637 | ****************************************************************/ |
638 | -static epicsUInt16 errhash(long errNum) |
639 | +static |
640 | +epicsUInt16 errHash(long status) |
641 | { |
642 | - epicsUInt16 modnum; |
643 | - epicsUInt16 errnum; |
644 | + epicsUInt16 modnum = (status >> 16) & 0xffff; |
645 | + epicsUInt16 errnum = status & 0xffff; |
646 | |
647 | - modnum = (unsigned short) (errNum >> 16); |
648 | - errnum = (unsigned short) (errNum & 0xffff); |
649 | - return (((modnum - 500) * 20) + errnum) % NHASH; |
650 | + return ((modnum - 500) * 20 + errnum) % NHASH; |
651 | } |
652 | |
653 | /**************************************************************** |
654 | - * ERRSYMBOLADD |
655 | - * adds symbols to the master errnumlist as compiled from errSymTbl.c |
656 | + * errSymAdd |
657 | + * adds one symbol to hash table |
658 | ***************************************************************/ |
659 | -int errSymbolAdd(long errNum, const char *name) |
660 | +int errSymAdd(const ERRSYMBOL *errsym) |
661 | { |
662 | - ERRNUMNODE *pNew = (ERRNUMNODE*) callocMustSucceed(1, |
663 | - sizeof(ERRNUMNODE), "errSymbolAdd"); |
664 | + epicsUInt16 bucket = errHash(errsym->status); |
665 | + ERRNUMNODE **ppNode = &hashTable[bucket]; |
666 | + ERRNUMNODE *pNode, *pNew = (ERRNUMNODE *) calloc(1, sizeof(ERRNUMNODE)); |
667 | + int result = 0; |
668 | + |
669 | + if (!pNew) { |
670 | + fprintf(stderr, "errSymAdd: Out of memory\n"); |
671 | + return -1; |
672 | + } |
673 | + pNew->p = errsym; |
674 | + |
675 | + /* Scan the bucket list */ |
676 | + epicsMutexMustLock(hashLock); |
677 | + while ((pNode = *ppNode)) { |
678 | + if (pNode->p->status == errsym->status) { |
679 | + /* We've seen this status value before */ |
680 | + free(pNew); |
681 | + if (pNode->p != errsym && |
682 | + strcmp(pNode->p->sym, errsym->sym)) { |
683 | + epicsUInt16 modnum = (errsym->status >> 16) & 0xffff; |
684 | + epicsUInt16 errnum = errsym->status & 0xffff; |
685 | + |
686 | + /* Same value, different symbol names */ |
687 | + fprintf(stderr, "errSymAdd: Status value (%u,%u) is %s \"%s\"\n" |
688 | + " so can't be registered as %s \"%s\"\n" , |
689 | + modnum, errnum, pNode->p->sym, pNode->p->msg, |
690 | + errsym->sym, errsym->msg); |
691 | + result = -1; |
692 | + } |
693 | + goto done; |
694 | + } |
695 | + ppNode = &pNode->next; |
696 | + } |
697 | |
698 | - pNew->errNum = errNum; |
699 | - pNew->message = name; |
700 | - ellAdd(&errnumlist, (ELLNODE*)pNew); |
701 | - return 0; |
702 | + /* Append new node to the list */ |
703 | + *ppNode = pNew; |
704 | + hashEntries++; |
705 | +done: |
706 | + epicsMutexUnlock(hashLock); |
707 | + return result; |
708 | } |
709 | |
710 | -/**************************************************************** |
711 | - * errRawCopy |
712 | +/*************************************************************** |
713 | + * errSymLookupNode |
714 | ***************************************************************/ |
715 | -static void errRawCopy(long statusToDecode, char *pBuf, size_t bufLength) |
716 | +static |
717 | +const ERRNUMNODE * errSymLookupNode(long status) |
718 | { |
719 | - epicsUInt16 modnum = (statusToDecode >>= 16) & 0xffff; |
720 | - epicsUInt16 errnum = statusToDecode & 0xffff; |
721 | + unsigned bucket = errHash(status); |
722 | + ERRNUMNODE *pNode, **ppNode; |
723 | |
724 | - assert(bufLength > 20); |
725 | + if (errSymInit() == 0) |
726 | + return NULL; |
727 | |
728 | - if (modnum == 0) { |
729 | - epicsSnprintf(pBuf, bufLength, "Error #%u", errnum); |
730 | - } |
731 | - else { |
732 | - epicsSnprintf(pBuf, bufLength, "Error (%u,%u)", modnum, errnum); |
733 | + ppNode = &hashTable[bucket]; |
734 | + |
735 | + epicsMutexMustLock(hashLock); |
736 | + pNode = *ppNode; |
737 | + while (pNode) { |
738 | + if (pNode->p->status == status) { |
739 | + epicsMutexUnlock(hashLock); |
740 | + return pNode; |
741 | + } |
742 | + ppNode = &pNode->next; |
743 | + pNode = *ppNode; |
744 | } |
745 | + epicsMutexUnlock(hashLock); |
746 | + return NULL; |
747 | } |
748 | |
749 | +/*************************************************************** |
750 | + * errSymLookupMessage |
751 | + ***************************************************************/ |
752 | static |
753 | -const char* errSymLookupInternal(long status) |
754 | +const char* errSymLookupMessage(long status) |
755 | { |
756 | - unsigned modNum; |
757 | - ERRNUMNODE *pNextNode; |
758 | - ERRNUMNODE **phashnode = NULL; |
759 | - |
760 | - if (!initialized) |
761 | - errSymBld(); |
762 | - |
763 | - modNum = (unsigned) status; |
764 | - modNum >>= 16; |
765 | - modNum &= 0xffff; |
766 | - if (modNum <= 500) { |
767 | - const char * pStr = strerror ((int) status); |
768 | - if (pStr) { |
769 | - return pStr; |
770 | - } |
771 | + epicsUInt16 modnum = (status >> 16) & 0xffff; |
772 | + |
773 | + if (modnum <= 500) { |
774 | + return strerror((int) status); |
775 | } |
776 | else { |
777 | - unsigned hashInd = errhash(status); |
778 | - phashnode = (ERRNUMNODE**)&hashtable[hashInd]; |
779 | - pNextNode = *phashnode; |
780 | - while (pNextNode) { |
781 | - if (pNextNode->errNum==status){ |
782 | - return pNextNode->message; |
783 | - } |
784 | - phashnode = &pNextNode->hashnode; |
785 | - pNextNode = *phashnode; |
786 | + const ERRNUMNODE *ppNode = errSymLookupNode(status); |
787 | + if (ppNode) { |
788 | + return ppNode->p->msg; |
789 | } |
790 | } |
791 | return NULL; |
792 | } |
793 | |
794 | -const char* errSymMsg(long status) |
795 | +/**************************************************************** |
796 | + * errSymMsg |
797 | + ***************************************************************/ |
798 | +const char * errSymMsg(long status) |
799 | { |
800 | - const char* msg = errSymLookupInternal(status); |
801 | - return msg ? msg : "<Unknown code>"; |
802 | + const char *msg = errSymLookupMessage(status); |
803 | + |
804 | + return msg ? msg : "<Unknown status>"; |
805 | } |
806 | |
807 | /**************************************************************** |
808 | @@ -190,93 +210,95 @@ const char* errSymMsg(long status) |
809 | ***************************************************************/ |
810 | void errSymLookup(long status, char * pBuf, size_t bufLength) |
811 | { |
812 | - const char* msg = errSymLookupInternal(status); |
813 | - if(msg) { |
814 | + const char *msg = errSymLookupMessage(status); |
815 | + |
816 | + if (msg) { |
817 | strncpy(pBuf, msg, bufLength); |
818 | pBuf[bufLength-1] = '\0'; |
819 | - return; |
820 | } |
821 | - errRawCopy(status, pBuf, bufLength); |
822 | + else { |
823 | + epicsUInt16 modnum = (status >> 16) & 0xffff; |
824 | + epicsUInt16 errnum = status & 0xffff; |
825 | + |
826 | + if (modnum == 0) { |
827 | + epicsSnprintf(pBuf, bufLength, "Error #%u", errnum); |
828 | + } |
829 | + else { |
830 | + epicsSnprintf(pBuf, bufLength, "Error (%u,%u) <unknown>", |
831 | + modnum, errnum); |
832 | + } |
833 | + } |
834 | } |
835 | |
836 | /**************************************************************** |
837 | * errSymDump |
838 | ***************************************************************/ |
839 | -void errSymDump(void) |
840 | +void errSymDump(int level) |
841 | { |
842 | int i; |
843 | int msgcount = 0; |
844 | |
845 | - if (!initialized) errSymBld(); |
846 | + if (errSymInit() == 0) { |
847 | + puts("Error symbol table empty\n"); |
848 | + return; |
849 | + } |
850 | + |
851 | + epicsMutexMustLock(hashLock); |
852 | + if (level > 0) |
853 | + printf("errSymDump: %d buckets, added %d symbols\n", NHASH, hashEntries); |
854 | |
855 | - msgcount = 0; |
856 | - printf("errSymDump: number of hash slots = %d\n", NHASH); |
857 | for (i = 0; i < NHASH; i++) { |
858 | - ERRNUMNODE **phashnode = &hashtable[i]; |
859 | - ERRNUMNODE *pNextNode = *phashnode; |
860 | + ERRNUMNODE **ppNode = &hashTable[i]; |
861 | + ERRNUMNODE *pNode = *ppNode; |
862 | int count = 0; |
863 | |
864 | - while (pNextNode) { |
865 | - int modnum = pNextNode->errNum >> 16; |
866 | - int errnum = pNextNode->errNum & 0xffff; |
867 | + while (pNode) { |
868 | + long status = pNode->p->status; |
869 | + epicsUInt16 modnum = (status >> 16) & 0xffff; |
870 | + epicsUInt16 errnum = status & 0xffff; |
871 | |
872 | - if (!count++) { |
873 | - printf("HASHNODE = %d\n", i); |
874 | + if (!count++ && level > 0) { |
875 | + printf("Bucket %d:\n", i); |
876 | } |
877 | - printf("\tmod %d num %d \"%s\"\n", |
878 | - modnum , errnum , pNextNode->message); |
879 | - phashnode = &pNextNode->hashnode; |
880 | - pNextNode = *phashnode; |
881 | + printf(" %-25s = (%3u,%2u) \"%s\"\n", |
882 | + pNode->p->sym, modnum, errnum, pNode->p->msg); |
883 | + ppNode = &pNode->next; |
884 | + pNode = *ppNode; |
885 | } |
886 | msgcount += count; |
887 | } |
888 | - printf("\nerrSymDump: total number of error messages = %d\n", msgcount); |
889 | + epicsMutexUnlock(hashLock); |
890 | + printf("Counted %d error symbols\n", msgcount); |
891 | } |
892 | |
893 | - |
894 | |
895 | /**************************************************************** |
896 | * errSymTestPrint |
897 | ***************************************************************/ |
898 | -void errSymTestPrint(long errNum) |
899 | +void errSymTestPrint(long status) |
900 | { |
901 | - char message[256]; |
902 | - epicsUInt16 modnum; |
903 | - epicsUInt16 errnum; |
904 | - |
905 | - if (!initialized) errSymBld(); |
906 | + epicsUInt16 modnum = (status >> 16) & 0xffff; |
907 | + epicsUInt16 errnum = status & 0xffff; |
908 | + const ERRNUMNODE *pNode = errSymLookupNode(status); |
909 | |
910 | - message[0] = '\0'; |
911 | - modnum = (epicsUInt16) (errNum >> 16); |
912 | - errnum = (epicsUInt16) (errNum & 0xffff); |
913 | - if (modnum < 501) { |
914 | - fprintf(stderr, "Usage: errSymTestPrint(long errNum) \n"); |
915 | - fprintf(stderr, "errSymTestPrint: module number < 501 \n"); |
916 | - return; |
917 | - } |
918 | - errSymLookup(errNum, message, sizeof(message)); |
919 | - if ( message[0] == '\0' ) return; |
920 | - printf("module %hu number %hu message=\"%s\"\n", |
921 | - modnum, errnum, message); |
922 | - return; |
923 | + if (pNode) |
924 | + printf(" %-25s = (%3u,%2u) \"%s\"\n", |
925 | + pNode->p->sym, modnum, errnum, pNode->p->msg); |
926 | } |
927 | - |
928 | |
929 | + |
930 | /**************************************************************** |
931 | - * ERRSYMTEST |
932 | + * errSymTest |
933 | ****************************************************************/ |
934 | -void errSymTest(epicsUInt16 modnum, epicsUInt16 begErrNum, |
935 | - epicsUInt16 endErrNum) |
936 | +void errSymTest(epicsUInt16 modnum, epicsUInt16 first, epicsUInt16 last) |
937 | { |
938 | - long errNum; |
939 | - epicsUInt16 errnum; |
940 | + epicsUInt16 errnum; |
941 | |
942 | - if (!initialized) errSymBld(); |
943 | - if (modnum < 501) |
944 | + if ((modnum < 501) || (first > last)) |
945 | return; |
946 | |
947 | /* print range of error messages */ |
948 | - for (errnum = begErrNum; errnum <= endErrNum; errnum++) { |
949 | - errNum = modnum << 16; |
950 | - errNum |= (errnum & 0xffff); |
951 | - errSymTestPrint(errNum); |
952 | + for (errnum = first; errnum <= last; errnum++) { |
953 | + long status = (modnum << 16) | errnum; |
954 | + |
955 | + errSymTestPrint(status); |
956 | } |
957 | } |
958 | diff --git a/modules/libcom/src/error/errSymTbl.h b/modules/libcom/src/error/errSymTbl.h |
959 | index 7fc25f7..c58133d 100644 |
960 | --- a/modules/libcom/src/error/errSymTbl.h |
961 | +++ b/modules/libcom/src/error/errSymTbl.h |
962 | @@ -1,10 +1,10 @@ |
963 | /*************************************************************************\ |
964 | -* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne |
965 | +* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne |
966 | * National Laboratory. |
967 | * Copyright (c) 2002 The Regents of the University of California, as |
968 | * Operator of Los Alamos National Laboratory. |
969 | * EPICS BASE is distributed subject to a Software License Agreement found |
970 | -* in file LICENSE that is included with this distribution. |
971 | +* in file LICENSE that is included with this distribution. |
972 | \*************************************************************************/ |
973 | |
974 | #ifndef INC_errSymTbl_H |
975 | @@ -14,34 +14,34 @@ |
976 | |
977 | #include "shareLib.h" |
978 | #include "epicsTypes.h" |
979 | +#include "dbDefs.h" /* for the generated errSyms.c file */ |
980 | |
981 | /* ERRSYMBOL - entry in symbol table */ |
982 | typedef struct { |
983 | - long errNum; /* errMessage symbol number */ |
984 | - const char *name; /* pointer to symbol name */ |
985 | + long status; /* error status code */ |
986 | + const char *sym; /* symbol name */ |
987 | + const char *msg; /* error message text */ |
988 | } ERRSYMBOL; |
989 | |
990 | /* ERRSYMTAB - symbol table */ |
991 | typedef struct { |
992 | int nsymbols; /* current number of symbols in table */ |
993 | - ERRSYMBOL *symbols; /* ptr to array of symbol entries */ |
994 | + const ERRSYMBOL *symbols; /* ptr to array of symbol entries */ |
995 | } ERRSYMTAB; |
996 | |
997 | -typedef ERRSYMTAB *ERRSYMTAB_ID; |
998 | - |
999 | |
1000 | #ifdef __cplusplus |
1001 | extern "C" { |
1002 | #endif |
1003 | |
1004 | epicsShareFunc void errSymLookup(long status, char *pBuf, size_t bufLength); |
1005 | -epicsShareFunc const char* errSymMsg(long status); |
1006 | -epicsShareFunc void errSymTest(epicsUInt16 modnum, epicsUInt16 begErrNum, |
1007 | - epicsUInt16 endErrNum); |
1008 | -epicsShareFunc void errSymTestPrint(long errNum); |
1009 | -epicsShareFunc int errSymBld(void); |
1010 | -epicsShareFunc int errSymbolAdd(long errNum, const char *name); |
1011 | -epicsShareFunc void errSymDump(void); |
1012 | +epicsShareFunc const char * errSymMsg(long status); |
1013 | +epicsShareFunc void errSymTest(epicsUInt16 modnum, epicsUInt16 first, |
1014 | + epicsUInt16 last); |
1015 | +epicsShareFunc void errSymTestPrint(long status); |
1016 | +epicsShareFunc int errSymTabAdd(ERRSYMTAB *errtab); |
1017 | +epicsShareFunc int errSymAdd(const ERRSYMBOL *errsym); |
1018 | +epicsShareFunc void errSymDump(int level); |
1019 | |
1020 | #ifdef __cplusplus |
1021 | } |
1022 | diff --git a/modules/libcom/src/error/errlog.c b/modules/libcom/src/error/errlog.c |
1023 | index 8445a5a..9ed2ba6 100644 |
1024 | --- a/modules/libcom/src/error/errlog.c |
1025 | +++ b/modules/libcom/src/error/errlog.c |
1026 | @@ -4,7 +4,7 @@ |
1027 | * Copyright (c) 2002 The Regents of the University of California, as |
1028 | * Operator of Los Alamos National Laboratory. |
1029 | * EPICS BASE is distributed subject to a Software License Agreement found |
1030 | -* in file LICENSE that is included with this distribution. |
1031 | +* in file LICENSE that is included with this distribution. |
1032 | \*************************************************************************/ |
1033 | /* |
1034 | * Original Author: Marty Kraimer |
1035 | @@ -487,8 +487,6 @@ static void errlogInitPvt(void *arg) |
1036 | pvtData.pbuffer = callocMustSucceed(1, pvtData.buffersize, |
1037 | "errlogInitPvt"); |
1038 | |
1039 | - errSymBld(); /* Better not to do this lazily... */ |
1040 | - |
1041 | tid = epicsThreadCreate("errlog", epicsThreadPriorityLow, |
1042 | epicsThreadGetStackSize(epicsThreadStackSmall), |
1043 | (EPICSTHREADFUNC)errlogThread, 0); |
1044 | diff --git a/modules/libcom/src/error/makeStatTbl.pl b/modules/libcom/src/error/makeStatTbl.pl |
1045 | index e9ca10e..ed9b2ae 100644 |
1046 | --- a/modules/libcom/src/error/makeStatTbl.pl |
1047 | +++ b/modules/libcom/src/error/makeStatTbl.pl |
1048 | @@ -1,50 +1,85 @@ |
1049 | #!/usr/bin/env perl |
1050 | |
1051 | #************************************************************************* |
1052 | -# Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
1053 | +# Copyright (c) 2018 The University of Chicago, as Operator of Argonne |
1054 | # National Laboratory. |
1055 | # Copyright (c) 2014 The Regents of the University of California, as |
1056 | # Operator of Los Alamos National Laboratory. |
1057 | # EPICS BASE is distributed subject to a Software License Agreement found |
1058 | -# in file LICENSE that is included with this distribution. |
1059 | +# in file LICENSE that is included with this distribution. |
1060 | #************************************************************************* |
1061 | # |
1062 | -# makeStatTbl.pl - Create Error Symbol Table |
1063 | +# makeStatTbl.pl - Register Error Symbols |
1064 | # |
1065 | # Original Author: Kay-Uwe Kasemir, 1-31-97 |
1066 | -# |
1067 | -# SYNOPSIS |
1068 | -# perl makeStatTbl.pl files.h... |
1069 | -# |
1070 | -# DESCRIPTION |
1071 | -# This tool creates a symbol table (ERRSYMTAB) structure which contains the |
1072 | -# names and values of all the status codes defined in the .h files named in |
1073 | -# its input arguments. The status codes must be prefixed with "S_" |
1074 | -# in order to be included in this table. |
1075 | -# Module numbers definitions prefixed with "M_" are also read from the input |
1076 | -# files and included in the output. |
1077 | -# |
1078 | -# This tool's primary use is for creating an error status table used |
1079 | -# by errPrint, and errSymLookup. |
1080 | -# |
1081 | -# FILES |
1082 | -# errMdef.h Module number file for each h directory |
1083 | -# errSymTbl.c Source file generated by tool in the cwd |
1084 | -# |
1085 | -# SEE ALSO: errnoLib(1), symLib(1) |
1086 | |
1087 | use strict; |
1088 | use Getopt::Std; |
1089 | +use Pod::Usage; |
1090 | + |
1091 | +=head1 NAME |
1092 | + |
1093 | +makeStatTbl.pl - Generate code to register error symbols |
1094 | + |
1095 | +=head1 SYNOPSIS |
1096 | + |
1097 | +B<makeStatTbl.pl> [B<-r> errSymsAdd] [B<-o> errSyms.c] file.h ... |
1098 | + |
1099 | +=head1 DESCRIPTION |
1100 | + |
1101 | +This tool parses one or more C header files and extracts any definitions that |
1102 | +match the following formats: |
1103 | + |
1104 | + #define M_xxx (1234 << 16) /* Module name */ |
1105 | + #define S_xxx_error (M_xxx | 1) /* Error description */ |
1106 | + |
1107 | +These definitions are converted into a series of C structures with code that |
1108 | +registers all of the C<S_> symbol values as error status values with the given |
1109 | +descriptions. |
1110 | + |
1111 | +=head1 OPTIONS |
1112 | + |
1113 | +B<makeStatTbl.pl> understands the following options: |
1114 | + |
1115 | +=over 4 |
1116 | + |
1117 | +=item B<-h> |
1118 | + |
1119 | +Help, display usage information. |
1120 | + |
1121 | +=item B<-H> |
1122 | + |
1123 | +Conversion help, display detailed information about converting a module to |
1124 | +register its error symbols. |
1125 | + |
1126 | +=item B<-r> errSymsAdd |
1127 | + |
1128 | +Name of the C registration routine to be created in the output file. |
1129 | + |
1130 | +=item B<-o> errSyms.c |
1131 | + |
1132 | +Name of the output file to be created. |
1133 | + |
1134 | +=back |
1135 | + |
1136 | +If no output filename is set, the file created will be named C<errSyms.c>. If no |
1137 | +registration routine name is set, the routine will be named after the output |
1138 | +file with the trailing C<.c> replaced with C<Add>. |
1139 | + |
1140 | +=cut |
1141 | |
1142 | my $tool = 'makeStatTbl.pl'; |
1143 | |
1144 | -our ($opt_h); |
1145 | -our $opt_o = 'errSymTbl.c'; |
1146 | +our ($opt_h, $opt_H, $opt_r); |
1147 | +our $opt_o = 'errSyms.c'; |
1148 | + |
1149 | +pod2usage(2) unless getopts('hHo:r:'); |
1150 | |
1151 | -$Getopt::Std::OUTPUT_HELP_VERSION = 1; |
1152 | +($opt_r = $opt_o) =~ s/\.c$/Add/ unless defined $opt_r; |
1153 | |
1154 | -&HELP_MESSAGE unless getopts('ho:') && @ARGV; |
1155 | -&HELP_MESSAGE if $opt_h; |
1156 | +pod2usage(-verbose => 2) if $opt_H; |
1157 | +pod2usage(1) if $opt_h; |
1158 | +pod2usage("$tool: No input files given.\n") if !@ARGV; |
1159 | |
1160 | my (@syms, %vals, %msgs); |
1161 | |
1162 | @@ -62,11 +97,12 @@ open my $out, '>', $opt_o or |
1163 | die "Can't create $opt_o: $!\n"; |
1164 | |
1165 | print $out <<"END"; |
1166 | -/* Generated file $opt_o */ |
1167 | +/* Generated file $opt_o |
1168 | + * |
1169 | + * The source file that includes this must also include errSymTbl.h |
1170 | + */ |
1171 | |
1172 | #include "errMdef.h" |
1173 | -#include "errSymTbl.h" |
1174 | -#include "dbDefs.h" |
1175 | |
1176 | END |
1177 | |
1178 | @@ -86,11 +122,16 @@ print $out |
1179 | "\n", |
1180 | "static ERRSYMBOL symbols[] = {\n"; |
1181 | |
1182 | +foreach my $mod (@mods) { |
1183 | + my $msg = escape($msgs{$mod}); |
1184 | + print $out |
1185 | + " { $mod, \"$mod\", \"$msg\"},\n"; |
1186 | +} |
1187 | foreach my $err (@errs) { |
1188 | my $msg = escape($msgs{$err}); |
1189 | my $val = $vals{$err}; |
1190 | print $out |
1191 | - " { $val, \"$msg\"},\n"; |
1192 | + " { $val, \"$err\", \"$msg\"},\n"; |
1193 | } |
1194 | |
1195 | print $out <<"END"; |
1196 | @@ -100,17 +141,88 @@ static ERRSYMTAB symTbl = { |
1197 | NELEMENTS(symbols), symbols |
1198 | }; |
1199 | |
1200 | -ERRSYMTAB_ID errSymTbl = &symTbl; |
1201 | - |
1202 | -END |
1203 | - |
1204 | -sub HELP_MESSAGE { |
1205 | - print STDERR "Usage: $tool [-o file.c] files.h ...\n"; |
1206 | - exit 2; |
1207 | +static void ${opt_r}(void) |
1208 | +{ |
1209 | + errSymTabAdd(&symTbl); |
1210 | } |
1211 | +END |
1212 | |
1213 | sub escape { |
1214 | $_ = shift; |
1215 | s/"/\\"/g; |
1216 | return $_; |
1217 | } |
1218 | + |
1219 | +=pod |
1220 | + |
1221 | +=head1 Registering Error Symbols |
1222 | + |
1223 | +Small changes are needed to the module's build instructions, and to a module |
1224 | +initialization routine. The examples here show the changes that were required to |
1225 | +the IndustryPack Driver module. |
1226 | + |
1227 | +=head2 Makefile Changes |
1228 | + |
1229 | +In the main part of the C<Makefile> that compiles the module from source, add |
1230 | +all the header files that contain error symbol definitions to the variable |
1231 | +C<ERR_S_FILES> like this: |
1232 | + |
1233 | + ERR_S_FILES += ../drvIpac.h |
1234 | + |
1235 | +The leading C<../> is required for files that appear in the regular source |
1236 | +directory; all filenames must be specified relative to the target's C<O.arch> |
1237 | +build directory. |
1238 | + |
1239 | +Also in this section of the C<Makefile>, set the variable C<STAT_TBL> to the |
1240 | +name of the file to be generated containing the symbol information: |
1241 | + |
1242 | + STAT_TBL = ipacErrSyms.c |
1243 | + |
1244 | +Optionally also add this to the C<CLEANS> variable to cause the generated file |
1245 | +to be deleted by a C<make clean> command: |
1246 | + |
1247 | + CLEANS += $(STAT_TBL) |
1248 | + |
1249 | +Finally in the build rules section of the C<Makefile> (i.e. after the include |
1250 | +line for C<$(TOP)/configure/RULES>) add a dependency rule to ensure the new file |
1251 | +gets generated when it is needed. The file named before the colon is the C |
1252 | +source file that contains the initialization routine that will be edited below, |
1253 | +with its C<.c> filename extension replaced by C<$(DEP)>: |
1254 | + |
1255 | + drvIpac$(DEP): $(STAT_TBL) |
1256 | + |
1257 | +=head2 Initialization Routine Changes |
1258 | + |
1259 | +Find a suitable routine in the module that gets called to initialize it, |
1260 | +preferably one that is normally only used once, although multiple calls |
1261 | +shouldn't be a problem. A routine that registers commands with the IOC shell |
1262 | +would be ideal. |
1263 | + |
1264 | +The header section of the source file containing this routine must contain the |
1265 | +following include statements exactly as shown: |
1266 | + |
1267 | + #include <errMdef.h> |
1268 | + #ifdef FEATURE_LOADABLE_ERR_SYMS |
1269 | + #include <errSymTbl.h> |
1270 | + #endif |
1271 | + |
1272 | +To ensure compatibility with Microsoft Windows builds of the module, make sure |
1273 | +these lines appear above the inclusion of C<epicsExport.h> or of any definition |
1274 | +of the macro C<epicsExportSharedSymbols>. |
1275 | + |
1276 | +Just above the initialization routine, add the following code to include the new |
1277 | +file or declare a dummy macro when building older versions of Base (replace the |
1278 | +text C<ipacErrSyms> with your own equivalent in both indented lines): |
1279 | + |
1280 | + #ifdef FEATURE_LOADABLE_ERR_SYMS |
1281 | + #include "ipacErrSyms.c" |
1282 | + #else |
1283 | + #define ipacErrSymsAdd() (void) 0 |
1284 | + #endif |
1285 | + |
1286 | +Finally, inside the routine itself, add a call to the symbol registration |
1287 | +routine: |
1288 | + |
1289 | + ipacErrSymsAdd(); |
1290 | + |
1291 | +=cut |
1292 | diff --git a/modules/libcom/src/iocsh/libComRegister.c b/modules/libcom/src/iocsh/libComRegister.c |
1293 | index 737d7e9..851c2ba 100644 |
1294 | --- a/modules/libcom/src/iocsh/libComRegister.c |
1295 | +++ b/modules/libcom/src/iocsh/libComRegister.c |
1296 | @@ -5,7 +5,7 @@ |
1297 | * Copyright (c) 2002 The Regents of the University of California, as |
1298 | * Operator of Los Alamos National Laboratory. |
1299 | * EPICS BASE is distributed subject to a Software License Agreement found |
1300 | -* in file LICENSE that is included with this distribution. |
1301 | +* in file LICENSE that is included with this distribution. |
1302 | \*************************************************************************/ |
1303 | |
1304 | #include <stdlib.h> |
1305 | @@ -21,6 +21,7 @@ |
1306 | #include "osiUnistd.h" |
1307 | #include "logClient.h" |
1308 | #include "errlog.h" |
1309 | +#include "errSymTbl.h" |
1310 | #include "taskwd.h" |
1311 | #include "registry.h" |
1312 | #include "epicsGeneralTime.h" |
1313 | @@ -163,6 +164,15 @@ static void registryDumpCallFunc(const iocshArgBuf *args) |
1314 | registryDump (); |
1315 | } |
1316 | |
1317 | +/* errSymDump */ |
1318 | +static const iocshArg errSymDumpArg0 = { "level",iocshArgInt}; |
1319 | +static const iocshArg * const errSymDumpArgs[1] = {&errSymDumpArg0}; |
1320 | +static const iocshFuncDef errSymDumpFuncDef = {"errSymDump",1,errSymDumpArgs}; |
1321 | +static void errSymDumpCallFunc(const iocshArgBuf *args) |
1322 | +{ |
1323 | + errSymDump(args[0].ival); |
1324 | +} |
1325 | + |
1326 | /* iocLogInit */ |
1327 | static const iocshFuncDef iocLogInitFuncDef = {"iocLogInit",0}; |
1328 | static void iocLogInitCallFunc(const iocshArgBuf *args) |
1329 | @@ -215,7 +225,7 @@ static void errlogInitCallFunc(const iocshArgBuf *args) |
1330 | /* errlogInit2 */ |
1331 | static const iocshArg errlogInit2Arg0 = { "bufSize",iocshArgInt}; |
1332 | static const iocshArg errlogInit2Arg1 = { "maxMsgSize",iocshArgInt}; |
1333 | -static const iocshArg * const errlogInit2Args[] = |
1334 | +static const iocshArg * const errlogInit2Args[] = |
1335 | {&errlogInit2Arg0, &errlogInit2Arg1}; |
1336 | static const iocshFuncDef errlogInit2FuncDef = |
1337 | {"errlogInit2", 2, errlogInit2Args}; |
1338 | @@ -393,8 +403,12 @@ static void installLastResortEventProviderCallFunc(const iocshArgBuf *args) |
1339 | installLastResortEventProvider(); |
1340 | } |
1341 | |
1342 | +#include "libComErrSyms.c" |
1343 | + |
1344 | void epicsShareAPI libComRegister(void) |
1345 | { |
1346 | + libComErrSymsAdd(); |
1347 | + |
1348 | iocshRegister(&dateFuncDef, dateCallFunc); |
1349 | iocshRegister(&echoFuncDef, echoCallFunc); |
1350 | iocshRegister(&chdirFuncDef, chdirCallFunc); |
1351 | @@ -407,6 +421,7 @@ void epicsShareAPI libComRegister(void) |
1352 | iocshRegister(&epicsEnvShowFuncDef, epicsEnvShowCallFunc); |
1353 | iocshRegister(®istryDumpFuncDef, registryDumpCallFunc); |
1354 | |
1355 | + iocshRegister(&errSymDumpFuncDef, errSymDumpCallFunc); |
1356 | iocshRegister(&iocLogInitFuncDef, iocLogInitCallFunc); |
1357 | iocshRegister(&iocLogDisableFuncDef, iocLogDisableCallFunc); |
1358 | iocshRegister(&iocLogShowFuncDef, iocLogShowCallFunc); |
1359 | @@ -422,7 +437,7 @@ void epicsShareAPI libComRegister(void) |
1360 | iocshRegister(&epicsMutexShowAllFuncDef,epicsMutexShowAllCallFunc); |
1361 | iocshRegister(&epicsThreadSleepFuncDef,epicsThreadSleepCallFunc); |
1362 | iocshRegister(&epicsThreadResumeFuncDef,epicsThreadResumeCallFunc); |
1363 | - |
1364 | + |
1365 | iocshRegister(&generalTimeReportFuncDef,generalTimeReportCallFunc); |
1366 | iocshRegister(&installLastResortEventProviderFuncDef, installLastResortEventProviderCallFunc); |
1367 | } |
1368 | diff --git a/modules/libcom/src/misc/Makefile b/modules/libcom/src/misc/Makefile |
1369 | index 3d5412d..6a4fe11 100644 |
1370 | --- a/modules/libcom/src/misc/Makefile |
1371 | +++ b/modules/libcom/src/misc/Makefile |
1372 | @@ -2,7 +2,7 @@ |
1373 | # Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne |
1374 | # National Laboratory. |
1375 | # EPICS BASE is distributed subject to a Software License Agreement found |
1376 | -# in file LICENSE that is included with this distribution. |
1377 | +# in file LICENSE that is included with this distribution. |
1378 | #************************************************************************* |
1379 | |
1380 | # This is a Makefile fragment, see src/libCom/Makefile. |
1381 | @@ -31,6 +31,8 @@ INC += testMain.h |
1382 | # epicsVersion.h is created by this Makefile |
1383 | INC += epicsVersion.h |
1384 | |
1385 | +ERR_S_FILES += $(LIBCOM)/misc/epicsStdlib.h |
1386 | + |
1387 | Com_SRCS += alarmString.c |
1388 | Com_SRCS += aToIPAddr.c |
1389 | Com_SRCS += adjustment.c |
1390 | diff --git a/modules/libcom/src/osi/Makefile b/modules/libcom/src/osi/Makefile |
1391 | index ecbf4c2..53167f0 100644 |
1392 | --- a/modules/libcom/src/osi/Makefile |
1393 | +++ b/modules/libcom/src/osi/Makefile |
1394 | @@ -2,7 +2,7 @@ |
1395 | # Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne |
1396 | # National Laboratory. |
1397 | # EPICS BASE is distributed subject to a Software License Agreement found |
1398 | -# in file LICENSE that is included with this distribution. |
1399 | +# in file LICENSE that is included with this distribution. |
1400 | #************************************************************************* |
1401 | |
1402 | # This is a Makefile fragment, see src/libCom/Makefile. |
1403 | @@ -65,6 +65,9 @@ INC += osdVME.h |
1404 | INC += epicsMMIO.h |
1405 | INC += epicsMMIODef.h |
1406 | |
1407 | +ERR_S_FILES += $(LIBCOM)/osi/devLib.h |
1408 | +ERR_S_FILES += $(LIBCOM)/osi/epicsTime.h |
1409 | + |
1410 | Com_SRCS += epicsThread.cpp |
1411 | Com_SRCS += epicsMutex.cpp |
1412 | Com_SRCS += epicsEvent.cpp |
1413 | diff --git a/modules/libcom/src/pool/Makefile b/modules/libcom/src/pool/Makefile |
1414 | index efaf667..8f33320 100644 |
1415 | --- a/modules/libcom/src/pool/Makefile |
1416 | +++ b/modules/libcom/src/pool/Makefile |
1417 | @@ -2,7 +2,7 @@ |
1418 | # Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne |
1419 | # National Laboratory. |
1420 | # EPICS BASE is distributed subject to a Software License Agreement found |
1421 | -# in file LICENSE that is included with this distribution. |
1422 | +# in file LICENSE that is included with this distribution. |
1423 | #************************************************************************* |
1424 | |
1425 | # This is a Makefile fragment, see src/libCom/Makefile. |
1426 | @@ -11,6 +11,7 @@ SRC_DIRS += $(LIBCOM)/pool |
1427 | |
1428 | INC += epicsThreadPool.h |
1429 | |
1430 | +ERR_S_FILES += $(LIBCOM)/pool/epicsThreadPool.h |
1431 | + |
1432 | Com_SRCS += poolJob.c |
1433 | Com_SRCS += threadPool.c |
1434 | - |
1435 | diff --git a/modules/libcom/test/Makefile b/modules/libcom/test/Makefile |
1436 | index 1c26c44..7cd1a01 100755 |
1437 | --- a/modules/libcom/test/Makefile |
1438 | +++ b/modules/libcom/test/Makefile |
1439 | @@ -79,6 +79,11 @@ epicsErrlogTest_SRCS += epicsErrlogTest.c |
1440 | testHarness_SRCS += epicsErrlogTest.c |
1441 | TESTS += epicsErrlogTest |
1442 | |
1443 | +TESTPROD_HOST += errSymTest |
1444 | +errSymTest_SRCS += errSymTest.c |
1445 | +testHarness_SRCS += errSymTest.c |
1446 | +TESTS += errSymTest |
1447 | + |
1448 | TESTPROD_HOST += epicsStdioTest |
1449 | epicsStdioTest_SRCS += epicsStdioTest.c |
1450 | testHarness_SRCS += epicsStdioTest.c |
1451 | diff --git a/modules/libcom/test/epicsRunLibComTests.c b/modules/libcom/test/epicsRunLibComTests.c |
1452 | index 94fe3d7..a51d684 100644 |
1453 | --- a/modules/libcom/test/epicsRunLibComTests.c |
1454 | +++ b/modules/libcom/test/epicsRunLibComTests.c |
1455 | @@ -24,6 +24,7 @@ int epicsCalcTest(void); |
1456 | int epicsEllTest(void); |
1457 | int epicsEnvTest(void); |
1458 | int epicsErrlogTest(void); |
1459 | +int errSymLibTest(void); |
1460 | int epicsEventTest(void); |
1461 | int epicsExitTest(void); |
1462 | int epicsMathTest(void); |
1463 | @@ -82,6 +83,7 @@ void epicsRunLibComTests(void) |
1464 | runTest(epicsEllTest); |
1465 | runTest(epicsEnvTest); |
1466 | runTest(epicsErrlogTest); |
1467 | + runTest(errSymLibTest); |
1468 | runTest(epicsEventTest); |
1469 | runTest(epicsInlineTest); |
1470 | runTest(epicsMathTest); |
1471 | diff --git a/modules/libcom/test/errSymTest.c b/modules/libcom/test/errSymTest.c |
1472 | new file mode 100644 |
1473 | index 0000000..1efbe0a |
1474 | --- /dev/null |
1475 | +++ b/modules/libcom/test/errSymTest.c |
1476 | @@ -0,0 +1,88 @@ |
1477 | +/*************************************************************************\ |
1478 | +* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne |
1479 | +* National Laboratory. |
1480 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1481 | +* in file LICENSE that is included with this distribution. |
1482 | +\*************************************************************************/ |
1483 | +/* errSymTest.c |
1484 | + * |
1485 | + * Check functionality of the errSym routines |
1486 | + */ |
1487 | + |
1488 | +#include <string.h> |
1489 | + |
1490 | +#include "epicsUnitTest.h" |
1491 | +#include "errSymTbl.h" |
1492 | +#include "testMain.h" |
1493 | + |
1494 | +#define M_test (0x1234 << 16) |
1495 | +#define S_1 M_test | 1 |
1496 | +#define S_2 M_test | 2 |
1497 | +#define S_3 M_test | 3 |
1498 | + |
1499 | +static ERRSYMBOL sym0 = {M_test, "M_test", "Okay"}; |
1500 | +static ERRSYMBOL sym1 = {M_test, "M_test", "OK"}; |
1501 | +static ERRSYMBOL sym2 = {M_test, "M_err", "Not okay"}; |
1502 | + |
1503 | +static ERRSYMBOL syms1[] = { |
1504 | + { S_1, "S_1", "One"}, |
1505 | +}; |
1506 | +static ERRSYMTAB tab1 = { |
1507 | + NELEMENTS(syms1), syms1 |
1508 | +}; |
1509 | + |
1510 | +static ERRSYMBOL syms2[] = { |
1511 | + { S_2, "S_2", "Two"}, |
1512 | + { S_3, "S_3", "Three"}, |
1513 | +}; |
1514 | +static ERRSYMTAB tab2 = { |
1515 | + NELEMENTS(syms2), syms2 |
1516 | +}; |
1517 | + |
1518 | +MAIN(errSymLibTest) |
1519 | +{ |
1520 | + const char *unknown = errSymMsg(M_test); |
1521 | + const char *msg; |
1522 | + char buf[40]; |
1523 | + |
1524 | + testPlan(14); |
1525 | + |
1526 | + testOk(!strcmp(unknown, "<Unknown status>"), |
1527 | + "Got expected 'Unknown status' message"); |
1528 | + |
1529 | + testOk(!errSymAdd(&sym0), "Added symbol M_test"); |
1530 | + |
1531 | + msg = errSymMsg(M_test); |
1532 | + testOk(msg == sym0.msg, "errSymMsg(M_test) => '%s'", msg); |
1533 | + |
1534 | + testOk(!errSymTabAdd(&tab1), "Added tab1 symbols"); |
1535 | + |
1536 | + msg = errSymMsg(S_1); |
1537 | + testOk(msg == syms1[0].msg, "errSymMsg(S_1) => '%s'", msg); |
1538 | + |
1539 | + msg = errSymMsg(S_2); |
1540 | + testOk(msg == unknown, "errSymMsg(S_2) => '%s'", msg); |
1541 | + |
1542 | + testOk(!errSymTabAdd(&tab2), "Added tab2 symbols"); |
1543 | + |
1544 | + msg = errSymMsg(S_2); |
1545 | + testOk(msg == syms2[0].msg, "errSymMsg(S_2) => '%s'", msg); |
1546 | + |
1547 | + testOk(!errSymAdd(&sym0), "Added symbol M_test again"); |
1548 | + testOk(!errSymAdd(&sym1), "Added a different M_test"); |
1549 | + testOk( errSymAdd(&sym2), "Added incompatible M_test"); |
1550 | + msg = errSymMsg(M_test); |
1551 | + testOk(msg == sym0.msg, "errSymMsg(M_test) => '%s'", msg); |
1552 | + |
1553 | + buf[0] = 0; |
1554 | + errSymLookup(M_test, buf, sizeof(buf)); |
1555 | + testOk(buf[0] && !strcmp(buf, sym0.msg), |
1556 | + "errSymLookup(M_test) => '%s'", buf); |
1557 | + |
1558 | + buf[0] = 0; |
1559 | + errSymLookup(1024<<16, buf, sizeof(buf)); |
1560 | + testOk(buf[0] && !strcmp(buf, "Error (1024,0) <unknown>"), |
1561 | + "errSymLookup(1024<<16) => '%s'", buf); |
1562 | + |
1563 | + return testDone(); |
1564 | +} |
Modifications needed for drvIpac to register its own symbols were mostly as expected, wrapped in LOADABLE_ ERR_SYMS
ifdef FEATURE_
for backwards compatibility. Had to add comments to my #define M_xxx symbol definitions to ensure they matched what the script was looking for; could make comments optional for M_xxx symbols to avoid having to do that.