Merge remote-tracking branch 'origin/7.0' into rtems5

This commit is contained in:
Brendan Chandler
2021-03-25 18:41:15 -05:00
74 changed files with 1272 additions and 668 deletions
+164 -2
View File
@@ -11,6 +11,20 @@
#ifndef INC_errlog_H
#define INC_errlog_H
/** \file errlog.h
* \brief Functions for interacting with the errlog task
*
* This file contains functions for passing error messages with varying severity,
* registering and un-registering listeners and modifying the log buffer size and
* max message size.
*
* Some of these functions are similar to the standard C library functions printf
* and vprintf. For details on the arguments and return codes it is useful to consult
* any book that describes the standard C library such as
* `The C Programming Language ANSI C Edition` by Kernighan and Ritchie.
*
*/
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -22,8 +36,15 @@
extern "C" {
#endif
/**
* errlogListener function type.
*
* This is used when adding or removing log listeners in ::errlogAddListener
* and ::errlogRemoveListeners.
*/
typedef void (*errlogListener)(void *pPrivate, const char *message);
/** errlog severity enums */
typedef enum {
errlogInfo,
errlogMinor,
@@ -45,37 +66,171 @@ LIBCOM_API extern int errVerbose;
LIBCOM_API extern const char * errlogSevEnumString[];
#endif
/* errMessage is a macro so it can get the file and line number */
/**
* errMessage is a macro so it can get the file and line number. It prints the message,
* the status symbol and string values, and the name of the task which invoked errMessage.
* It also prints the name of the source file and the line number from which the call was issued.
*
* The status code used for the 1st argument is:
* - 0: Find latest vxWorks or Unix error (errno value).
* - -1: Dont report status.
* - Other: Use this status code and lookup the string value
*
* \param S Status code
* \param PM The message to print
*/
#define errMessage(S, PM) \
errPrintf(S, __FILE__, __LINE__, "%s", PM)
/* epicsPrintf and epicsVprintf are old names for errlog routines*/
/** epicsPrintf is an old name for errlog routines */
#define epicsPrintf errlogPrintf
/** epicsVprintf is an old name for errlog routines */
#define epicsVprintf errlogVprintf
/**
* errlogPrintf is like the printf function provided by the standard C library, except
* that the output is sent to the errlog task. Unless configured not to, the output
* will appear on the console as well.
*/
LIBCOM_API int errlogPrintf(const char *pformat, ...)
EPICS_PRINTF_STYLE(1,2);
/**
* errlogVprintf is like the vprintf function provided by the standard C library, except
* that the output is sent to the errlog task. Unless configured not to, the output
* will appear on the console as well.
*/
LIBCOM_API int errlogVprintf(const char *pformat, va_list pvar);
/**
* This function is like ::errlogPrintf except that it adds the severity to the beginning
* of the message in the form `sevr=<value>` where value is one of the enumerated
* severities in ::errlogSevEnum. Also the message is suppressed if severity is less than
* the current severity to suppress.
*
* \param severity One of the severity enums from ::errlogSevEnum
* \param pFormat The message to log or print
* \return int Consult printf documentation in C standard library
*/
LIBCOM_API int errlogSevPrintf(const errlogSevEnum severity,
const char *pformat, ...) EPICS_PRINTF_STYLE(2,3);
/**
* This function is like ::errlogVprintf except that it adds the severity to the beginning
* of the message in the form `sevr=<value>` where value is one of the enumerated
* severities in ::errlogSevEnum. Also the message is suppressed if severity is less than
* the current severity to suppress. If epicsThreadIsOkToBlock is true, which is
* true during iocInit, errlogSevVprintf does NOT send output to the
* errlog task.
*
* \param severity One of the severity enums from ::errlogSevEnum
* \param pFormat The message to log or print
* \param pvar va_list
* \return int Consult printf documentation in C standard library
*/
LIBCOM_API int errlogSevVprintf(const errlogSevEnum severity,
const char *pformat, va_list pvar);
/**
* Sends message to the errlog task.
*
* \param message The message to send
*/
LIBCOM_API int errlogMessage(const char *message);
/**
* Gets the string value of severity.
*
* \param severity The severity from ::errlogSevEnum
* \return The string value
*/
LIBCOM_API const char * errlogGetSevEnumString(errlogSevEnum severity);
/**
* Sets the severity to log
*
* \param severity The severity from ::errlogSevEnum
*/
LIBCOM_API void errlogSetSevToLog(errlogSevEnum severity);
/**
* Gets the current severity to log
*
* \return ::errlogSevEnum
*/
LIBCOM_API errlogSevEnum errlogGetSevToLog(void);
/**
* Any code can receive errlog message. This function will add a listener callback.
*
* \param listener Function pointer of type ::errlogListener
* \param pPrivate This will be passed as the first argument of listener()
*/
LIBCOM_API void errlogAddListener(errlogListener listener, void *pPrivate);
/**
* This function will remove a listener callback.
*
* \param listener Function pointer of type ::errlogListener
* \param pPrivate This will be passed as the first argument of listener()
*/
LIBCOM_API int errlogRemoveListeners(errlogListener listener,
void *pPrivate);
/**
* Normally the errlog system displays all messages on the console.
* During error message storms this function can be used to suppress console messages.
* A argument of 0 suppresses the messages, any other value lets messages go to the console.
*
* \param yesno (0=No, 1=Yes)
* \return 0
*/
LIBCOM_API int eltc(int yesno);
/**
* Sets a new stream to write the messages to
*
* \param stream Pointer to file handle
* \return 0
*/
LIBCOM_API int errlogSetConsole(FILE *stream);
/**
* Can be used to initialize the error logging system with a larger buffer. The default buffer size is 1280 bytes.
*
* \param bufsize The desired buffer size
*/
LIBCOM_API int errlogInit(int bufsize);
/**
* errlogInit2 can be used to initialize the error logging system with a larger buffer and maximum message size.
* The default buffer size is 1280 bytes, and the default maximum message size is 256.
*
* \param bufsize The desired buffer size
* \param maxMsgSize The desired max message size
*/
LIBCOM_API int errlogInit2(int bufsize, int maxMsgSize);
/** Wakes up the errlog task and then waits until all messages are flushed from the queue. */
LIBCOM_API void errlogFlush(void);
/**
* Routine errPrintf is normally called as follows:
* `errPrintf(status, __FILE__, __LINE__,"<fmt>",...); `
*
* Where status is defined as:
* - 0: Find latest vxWorks or Unix error.
* - -1: Dont report status.
* - Other: Use this status code and lookup the string value
*
* \param status See above
* \param __FILE__ As shown or NULL if the file name and line number should not be printed.
* \param __LINE__ As shown
*
* The remaining arguments are just like the arguments to the C printf routine.
* ::errVerbose determines if the filename and line number are shown.
*/
LIBCOM_API void errPrintf(long status, const char *pFileName, int lineno,
const char *pformat, ...) EPICS_PRINTF_STYLE(4,5);
@@ -83,6 +238,13 @@ LIBCOM_API int errlogPrintfNoConsole(const char *pformat, ...)
EPICS_PRINTF_STYLE(1,2);
LIBCOM_API int errlogVprintfNoConsole(const char *pformat,va_list pvar);
/**
* Lookup the status code and return the string value in pBuf
*
* \param status The status code to lookup
* \param pBuf The char buffer to write the string value into
* \param bufLength The max size of pBuf
*/
LIBCOM_API void errSymLookup(long status, char *pBuf, size_t bufLength);
#ifdef __cplusplus
+17 -4
View File
@@ -163,7 +163,12 @@ const iocshCmdDef * epicsStdCall iocshFindCommand(const char *name)
static const iocshArg varCmdArg0 = { "[variable", iocshArgString};
static const iocshArg varCmdArg1 = { "[value]]", iocshArgString};
static const iocshArg *varCmdArgs[2] = {&varCmdArg0, &varCmdArg1};
static const iocshFuncDef varFuncDef = {"var", 2, varCmdArgs};
static const iocshFuncDef varFuncDef = {"var", 2, varCmdArgs,
"Print all, print single variable or set value to single variable\n"
" (default) - print all variables and their values"
" defined in database definitions files\n"
" variable - if only parameter print value for this variable\n"
" value - set the value to variable\n"};
void epicsStdCall iocshRegisterVariable (const iocshVarDef *piocshVarDef)
{
@@ -1139,7 +1144,10 @@ static void varCallFunc(const iocshArgBuf *args)
/* iocshCmd */
static const iocshArg iocshCmdArg0 = { "command",iocshArgString};
static const iocshArg *iocshCmdArgs[1] = {&iocshCmdArg0};
static const iocshFuncDef iocshCmdFuncDef = {"iocshCmd",1,iocshCmdArgs};
static const iocshFuncDef iocshCmdFuncDef = {"iocshCmd",1,iocshCmdArgs,
"Takes a single IOC shell command and executes it\n"
" * This function is most useful to execute a single IOC shell command\n"
" from vxWorks or RTEMS startup script (or command line)\n"};
static void iocshCmdCallFunc(const iocshArgBuf *args)
{
iocshCmd(args[0].sval);
@@ -1149,7 +1157,9 @@ static void iocshCmdCallFunc(const iocshArgBuf *args)
static const iocshArg iocshLoadArg0 = { "pathname",iocshArgString};
static const iocshArg iocshLoadArg1 = { "macros", iocshArgString};
static const iocshArg *iocshLoadArgs[2] = {&iocshLoadArg0, &iocshLoadArg1};
static const iocshFuncDef iocshLoadFuncDef = {"iocshLoad",2,iocshLoadArgs};
static const iocshFuncDef iocshLoadFuncDef = {"iocshLoad",2,iocshLoadArgs,
"Execute IOC shell commands provided in file from first parameter\n"
" * (optional) replace macros within the file with provided values\n"};
static void iocshLoadCallFunc(const iocshArgBuf *args)
{
iocshLoad(args[0].sval, args[1].sval);
@@ -1159,7 +1169,10 @@ static void iocshLoadCallFunc(const iocshArgBuf *args)
static const iocshArg iocshRunArg0 = { "command",iocshArgString};
static const iocshArg iocshRunArg1 = { "macros", iocshArgString};
static const iocshArg *iocshRunArgs[2] = {&iocshRunArg0, &iocshRunArg1};
static const iocshFuncDef iocshRunFuncDef = {"iocshRun",2,iocshRunArgs};
static const iocshFuncDef iocshRunFuncDef = {"iocshRun",2,iocshRunArgs,
"Takes a single IOC shell command, replaces macros and executes it\n"
" * This function is most useful to execute a single IOC shell command\n"
" from vxWorks or RTEMS startup script (or command line)\n"};
static void iocshRunCallFunc(const iocshArgBuf *args)
{
iocshRun(args[0].sval, args[1].sval);
+73 -27
View File
@@ -46,7 +46,9 @@ void date(const char *format)
static const iocshArg dateArg0 = { "format",iocshArgString};
static const iocshArg * const dateArgs[] = {&dateArg0};
static const iocshFuncDef dateFuncDef = {"date", 1, dateArgs};
static const iocshFuncDef dateFuncDef = {"date", 1, dateArgs,
"Print current date and time\n"
" (default) - '%Y/%m/%d %H:%M:%S.%06f'\n"};
static void dateCallFunc (const iocshArgBuf *args)
{
date(args[0].sval);
@@ -64,7 +66,8 @@ IOCSH_STATIC_FUNC void echo(char* str)
static const iocshArg echoArg0 = { "string",iocshArgString};
static const iocshArg * const echoArgs[1] = {&echoArg0};
static const iocshFuncDef echoFuncDef = {"echo",1,echoArgs};
static const iocshFuncDef echoFuncDef = {"echo",1,echoArgs,
"Print string after expanding macros and environment variables\n"};
static void echoCallFunc(const iocshArgBuf *args)
{
echo(args[0].sval);
@@ -73,7 +76,8 @@ static void echoCallFunc(const iocshArgBuf *args)
/* chdir */
static const iocshArg chdirArg0 = { "directory name",iocshArgString};
static const iocshArg * const chdirArgs[1] = {&chdirArg0};
static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs};
static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs,
"Change directory to new directory provided as parameter\n"};
static void chdirCallFunc(const iocshArgBuf *args)
{
if (args[0].sval == NULL ||
@@ -83,7 +87,8 @@ static void chdirCallFunc(const iocshArgBuf *args)
}
/* print current working directory */
static const iocshFuncDef pwdFuncDef = { "pwd", 0, 0 };
static const iocshFuncDef pwdFuncDef = {"pwd", 0, 0,
"Print name of current/working directory\n"};
static void pwdCallFunc (const iocshArgBuf *args)
{
char buf[256];
@@ -97,7 +102,8 @@ static void pwdCallFunc (const iocshArgBuf *args)
static const iocshArg epicsEnvSetArg0 = { "name",iocshArgString};
static const iocshArg epicsEnvSetArg1 = { "value",iocshArgString};
static const iocshArg * const epicsEnvSetArgs[2] = {&epicsEnvSetArg0,&epicsEnvSetArg1};
static const iocshFuncDef epicsEnvSetFuncDef = {"epicsEnvSet",2,epicsEnvSetArgs};
static const iocshFuncDef epicsEnvSetFuncDef = {"epicsEnvSet",2,epicsEnvSetArgs,
"Set environment variable name to value\n"};
static void epicsEnvSetCallFunc(const iocshArgBuf *args)
{
char *name = args[0].sval;
@@ -117,7 +123,8 @@ static void epicsEnvSetCallFunc(const iocshArgBuf *args)
/* epicsEnvUnset */
static const iocshArg epicsEnvUnsetArg0 = { "name",iocshArgString};
static const iocshArg * const epicsEnvUnsetArgs[1] = {&epicsEnvUnsetArg0};
static const iocshFuncDef epicsEnvUnsetFuncDef = {"epicsEnvUnset",1,epicsEnvUnsetArgs};
static const iocshFuncDef epicsEnvUnsetFuncDef = {"epicsEnvUnset",1,epicsEnvUnsetArgs,
"Remove variable name from the environment\n"};
static void epicsEnvUnsetCallFunc(const iocshArgBuf *args)
{
char *name = args[0].sval;
@@ -135,14 +142,16 @@ IOCSH_STATIC_FUNC void epicsParamShow()
epicsPrtEnvParams ();
}
static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL};
static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL,
"Show the environment variable parameters used by iocCore\n"};
static void epicsParamShowCallFunc(const iocshArgBuf *args)
{
epicsParamShow ();
}
/* epicsPrtEnvParams */
static const iocshFuncDef epicsPrtEnvParamsFuncDef = {"epicsPrtEnvParams",0,0};
static const iocshFuncDef epicsPrtEnvParamsFuncDef = {"epicsPrtEnvParams",0,0,
"Show the environment variable parameters used by iocCore\n"};
static void epicsPrtEnvParamsCallFunc(const iocshArgBuf *args)
{
epicsPrtEnvParams ();
@@ -151,21 +160,29 @@ static void epicsPrtEnvParamsCallFunc(const iocshArgBuf *args)
/* epicsEnvShow */
static const iocshArg epicsEnvShowArg0 = { "[name]",iocshArgString};
static const iocshArg * const epicsEnvShowArgs[1] = {&epicsEnvShowArg0};
static const iocshFuncDef epicsEnvShowFuncDef = {"epicsEnvShow",1,epicsEnvShowArgs};
static const iocshFuncDef epicsEnvShowFuncDef = {"epicsEnvShow",1,epicsEnvShowArgs,
"Show environment variables on your system\n"
" (default) - show all environment variables\n"
" name - show value of specific environment variable\n"};
static void epicsEnvShowCallFunc(const iocshArgBuf *args)
{
epicsEnvShow (args[0].sval);
}
/* registryDump */
static const iocshFuncDef registryDumpFuncDef = {"registryDump",0,NULL};
static const iocshFuncDef registryDumpFuncDef = {"registryDump",0,NULL,
"Dump a hash table of EPICS registry\n"};
static void registryDumpCallFunc(const iocshArgBuf *args)
{
registryDump ();
}
/* iocLogInit */
static const iocshFuncDef iocLogInitFuncDef = {"iocLogInit",0};
static const iocshFuncDef iocLogInitFuncDef = {"iocLogInit",0,0,
"Initialize IOC logging\n"
" * EPICS environment variable 'EPICS_IOC_LOG_INET' has to be defined\n"
" * Logging controled via 'iocLogDisable' variable\n"
" see 'setIocLogDisable' command\n"};
static void iocLogInitCallFunc(const iocshArgBuf *args)
{
iocLogInit ();
@@ -179,7 +196,10 @@ IOCSH_STATIC_FUNC void setIocLogDisable(int val)
static const iocshArg iocLogDisableArg0 = {"(0,1)=>(false,true)",iocshArgInt};
static const iocshArg * const iocLogDisableArgs[1] = {&iocLogDisableArg0};
static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs};
static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs,
"Controls the 'iocLogDisable' variable\n"
" 0 - enable logging\n"
" 1 - disable logging\n"};
static void iocLogDisableCallFunc(const iocshArgBuf *args)
{
setIocLogDisable(args[0].ival);
@@ -188,7 +208,8 @@ static void iocLogDisableCallFunc(const iocshArgBuf *args)
/* iocLogShow */
static const iocshArg iocLogShowArg0 = {"level",iocshArgInt};
static const iocshArg * const iocLogShowArgs[1] = {&iocLogShowArg0};
static const iocshFuncDef iocLogShowFuncDef = {"iocLogShow",1,iocLogShowArgs};
static const iocshFuncDef iocLogShowFuncDef = {"iocLogShow",1,iocLogShowArgs,
"Determine if a IOC Log Prefix has been set\n"};
static void iocLogShowCallFunc(const iocshArgBuf *args)
{
iocLogShow (args[0].ival);
@@ -197,17 +218,22 @@ static void iocLogShowCallFunc(const iocshArgBuf *args)
/* eltc */
static const iocshArg eltcArg0 = {"(0,1)=>(false,true)",iocshArgInt};
static const iocshArg * const eltcArgs[1] = {&eltcArg0};
static const iocshFuncDef eltcFuncDef = {"eltc",1,eltcArgs};
static const iocshFuncDef eltcFuncDef = {"eltc",1,eltcArgs,
"Control display of error log messages on console\n"
" 0 - no\n"
" 1 - yes (default)\n"};
static void eltcCallFunc(const iocshArgBuf *args)
{
eltc(args[0].ival);
}
/* errlogInit */
static const iocshArg errlogInitArg0 = { "bufsize",iocshArgInt};
static const iocshArg errlogInitArg0 = { "bufSize",iocshArgInt};
static const iocshArg * const errlogInitArgs[1] = {&errlogInitArg0};
static const iocshFuncDef errlogInitFuncDef =
{"errlogInit",1,errlogInitArgs};
{"errlogInit",1,errlogInitArgs,
"Initialize error log client buffer size\n"
" bufSize - size of circular buffer (default = 1280 bytes)\n"};
static void errlogInitCallFunc(const iocshArgBuf *args)
{
errlogInit(args[0].ival);
@@ -219,7 +245,10 @@ static const iocshArg errlogInit2Arg1 = { "maxMsgSize",iocshArgInt};
static const iocshArg * const errlogInit2Args[] =
{&errlogInit2Arg0, &errlogInit2Arg1};
static const iocshFuncDef errlogInit2FuncDef =
{"errlogInit2", 2, errlogInit2Args};
{"errlogInit2", 2, errlogInit2Args,
"Initialize error log client buffer size and maximum message size\n"
" bufSize - size of circular buffer (default = 1280 bytes)\n"
" maxMsgSize - maximum size of error message (default = 256 bytes)\n"};
static void errlogInit2CallFunc(const iocshArgBuf *args)
{
errlogInit2(args[0].ival, args[1].ival);
@@ -233,7 +262,8 @@ IOCSH_STATIC_FUNC void errlog(const char *message)
static const iocshArg errlogArg0 = { "message",iocshArgString};
static const iocshArg * const errlogArgs[1] = {&errlogArg0};
static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs};
static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs,
"Send message to errlog\n"};
static void errlogCallFunc(const iocshArgBuf *args)
{
errlog(args[0].sval);
@@ -243,7 +273,8 @@ static void errlogCallFunc(const iocshArgBuf *args)
/* iocLogPrefix */
static const iocshArg iocLogPrefixArg0 = { "prefix",iocshArgString};
static const iocshArg * const iocLogPrefixArgs[1] = {&iocLogPrefixArg0};
static const iocshFuncDef iocLogPrefixFuncDef = {"iocLogPrefix",1,iocLogPrefixArgs};
static const iocshFuncDef iocLogPrefixFuncDef = {"iocLogPrefix",1,iocLogPrefixArgs,
"Create the prefix for all messages going into IOC log\n"};
static void iocLogPrefixCallFunc(const iocshArgBuf *args)
{
iocLogPrefix(args[0].sval);
@@ -253,7 +284,8 @@ static void iocLogPrefixCallFunc(const iocshArgBuf *args)
static const iocshArg epicsThreadShowAllArg0 = { "level",iocshArgInt};
static const iocshArg * const epicsThreadShowAllArgs[1] = {&epicsThreadShowAllArg0};
static const iocshFuncDef epicsThreadShowAllFuncDef =
{"epicsThreadShowAll",1,epicsThreadShowAllArgs};
{"epicsThreadShowAll",1,epicsThreadShowAllArgs,
"Display info about all threads\n"};
static void epicsThreadShowAllCallFunc(const iocshArgBuf *args)
{
epicsThreadShowAll(args[0].ival);
@@ -262,7 +294,8 @@ static void epicsThreadShowAllCallFunc(const iocshArgBuf *args)
/* epicsThreadShow */
static const iocshArg threadArg0 = { "[-level] [thread ...]", iocshArgArgv};
static const iocshArg * const threadArgs[1] = { &threadArg0 };
static const iocshFuncDef threadFuncDef = {"epicsThreadShow",1,threadArgs};
static const iocshFuncDef threadFuncDef = {"epicsThreadShow",1,threadArgs,
"Display info about the specified thread\n"};
static void threadCallFunc(const iocshArgBuf *args)
{
int i = 1;
@@ -308,7 +341,8 @@ static void threadCallFunc(const iocshArgBuf *args)
static const iocshArg taskwdShowArg0 = { "level",iocshArgInt};
static const iocshArg * const taskwdShowArgs[1] = {&taskwdShowArg0};
static const iocshFuncDef taskwdShowFuncDef =
{"taskwdShow",1,taskwdShowArgs};
{"taskwdShow",1,taskwdShowArgs,
"Show number of tasks and monitors registered\n"};
static void taskwdShowCallFunc(const iocshArgBuf *args)
{
taskwdShow(args[0].ival);
@@ -320,7 +354,10 @@ static const iocshArg epicsMutexShowAllArg1 = { "level",iocshArgInt};
static const iocshArg * const epicsMutexShowAllArgs[2] =
{&epicsMutexShowAllArg0,&epicsMutexShowAllArg1};
static const iocshFuncDef epicsMutexShowAllFuncDef =
{"epicsMutexShowAll",2,epicsMutexShowAllArgs};
{"epicsMutexShowAll",2,epicsMutexShowAllArgs,
"Display information about all epicsMutex semaphores\n"
" onlyLocked - non-zero to show only locked semaphores\n"
" level - desired information level to report\n"};
static void epicsMutexShowAllCallFunc(const iocshArgBuf *args)
{
epicsMutexShowAll(args[0].ival,args[1].ival);
@@ -330,7 +367,8 @@ static void epicsMutexShowAllCallFunc(const iocshArgBuf *args)
static const iocshArg epicsThreadSleepArg0 = { "seconds",iocshArgDouble};
static const iocshArg * const epicsThreadSleepArgs[1] = {&epicsThreadSleepArg0};
static const iocshFuncDef epicsThreadSleepFuncDef =
{"epicsThreadSleep",1,epicsThreadSleepArgs};
{"epicsThreadSleep",1,epicsThreadSleepArgs,
"Pause execution of IOC shell for <seconds> seconds\n"};
static void epicsThreadSleepCallFunc(const iocshArgBuf *args)
{
epicsThreadSleep(args[0].dval);
@@ -339,7 +377,10 @@ static void epicsThreadSleepCallFunc(const iocshArgBuf *args)
/* epicsThreadResume */
static const iocshArg epicsThreadResumeArg0 = { "[thread ...]", iocshArgArgv};
static const iocshArg * const epicsThreadResumeArgs[1] = { &epicsThreadResumeArg0 };
static const iocshFuncDef epicsThreadResumeFuncDef = {"epicsThreadResume",1,epicsThreadResumeArgs};
static const iocshFuncDef epicsThreadResumeFuncDef = {"epicsThreadResume",1,epicsThreadResumeArgs,
"Resume a suspended thread.\n"
"Only do this if you know that it is safe to "
"resume a suspended thread\n"};
static void epicsThreadResumeCallFunc(const iocshArgBuf *args)
{
int i;
@@ -381,14 +422,19 @@ static void epicsThreadResumeCallFunc(const iocshArgBuf *args)
/* generalTimeReport */
static const iocshArg generalTimeReportArg0 = { "interest_level", iocshArgArgv};
static const iocshArg * const generalTimeReportArgs[1] = { &generalTimeReportArg0 };
static const iocshFuncDef generalTimeReportFuncDef = {"generalTimeReport",1,generalTimeReportArgs};
static const iocshFuncDef generalTimeReportFuncDef = {"generalTimeReport",1,generalTimeReportArgs,
"Display time providers and their priority levels"
" for current and event times\n"};
static void generalTimeReportCallFunc(const iocshArgBuf *args)
{
generalTimeReport(args[0].ival);
}
/* installLastResortEventProvider */
static const iocshFuncDef installLastResortEventProviderFuncDef = {"installLastResortEventProvider", 0, NULL};
static const iocshFuncDef installLastResortEventProviderFuncDef = {"installLastResortEventProvider", 0, NULL,
"Installs the optional Last Resort event provider"
" at priority 999,\nwhich returns the current time"
" for every event number\n"};
static void installLastResortEventProviderCallFunc(const iocshArgBuf *args)
{
installLastResortEventProvider();
+126 -2
View File
@@ -13,6 +13,20 @@
#ifndef INC_epicsStdlib_H
#define INC_epicsStdlib_H
/**
* \file epicsStdlib.h
* \brief Functions to convert strings to primative types
*
* These routines convert a string into an integer of the indicated type and
* number base, or into a floating point type. The units pointer argument may
* be NULL, but if not it will be left pointing to the first non-whitespace
* character following the numeric string, or to the terminating zero byte.
*
* The return value from these routines is a status code, zero meaning OK.
* For the macro functions beginning with `epicsScan` the return code is 0
* or 1 (0=failure or 1=success, similar to the sscanf() function).
*/
#include <stdlib.h>
#include <limits.h>
@@ -25,57 +39,167 @@
extern "C" {
#endif
/** Return code for `No digits to convert` */
#define S_stdlib_noConversion (M_stdlib | 1) /* No digits to convert */
/** Return code for `Extraneous characters` */
#define S_stdlib_extraneous (M_stdlib | 2) /* Extraneous characters */
/** Return code for `Too small to represent` */
#define S_stdlib_underflow (M_stdlib | 3) /* Too small to represent */
/** Return code for `Too large to represent` */
#define S_stdlib_overflow (M_stdlib | 4) /* Too large to represent */
/** Return code for `Number base not supported` */
#define S_stdlib_badBase (M_stdlib | 5) /* Number base not supported */
LIBCOM_API int
/**
* \brief Convert a string to a long type
*
* \param str Pointer to a constant character array
* \param to Pointer to the specified type (this will be set during the conversion)
* \param base The number base to use
* \param units Pointer to a char * (this will be set with the units string)
* \return Status code (0=OK, see macro definitions for possible errors)
*/
LIBCOM_API int
epicsParseLong(const char *str, long *to, int base, char **units);
/**
* \brief Convert a string to a unsigned long type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseULong(const char *str, unsigned long *to, int base, char **units);
/**
* \brief Convert a string to a long long type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseLLong(const char *str, long long *to, int base, char **units);
/**
* \brief Convert a string to a unsigned long long type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseULLong(const char *str, unsigned long long *to, int base, char **units);
/**
* \brief Convert a string to a double type
*
* \param str Pointer to a constant character array
* \param to Pointer to the specified type (this will be set during the conversion)
* \param units Pointer to a char * (this will be set with the units string)
* \return Status code (0=OK, see macro definitions for possible errors)
*/
LIBCOM_API int
epicsParseDouble(const char *str, double *to, char **units);
/**
* \brief Convert a string to a float type
* \copydetails epicsParseDouble
*/
LIBCOM_API int
epicsParseFloat(const char *str, float *to, char **units);
/**
* \brief Convert a string to an epicsInt8 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseInt8(const char *str, epicsInt8 *to, int base, char **units);
/**
* \brief Convert a string to an epicsUInt8 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseUInt8(const char *str, epicsUInt8 *to, int base, char **units);
/**
* \brief Convert a string to an epicsInt16 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseInt16(const char *str, epicsInt16 *to, int base, char **units);
/**
* \brief Convert a string to an epicsUInt16 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseUInt16(const char *str, epicsUInt16 *to, int base, char **units);
/**
* \brief Convert a string to an epicsInt32 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units);
/**
* \brief Convert a string to an epicsUInt32 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units);
/**
* \brief Convert a string to an epicsInt64 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseInt64(const char *str, epicsInt64 *to, int base, char **units);
/**
* \brief Convert a string to an epicsUInt64 type
* \copydetails epicsParseLong
*/
LIBCOM_API int
epicsParseUInt64(const char *str, epicsUInt64 *to, int base, char **units);
/** Macro utilizing ::epicsParseFloat to convert */
#define epicsParseFloat32(str, to, units) epicsParseFloat(str, to, units)
/** Macro utilizing ::epicsParseDouble to convert */
#define epicsParseFloat64(str, to, units) epicsParseDouble(str, to, units)
/* These macros return 1 if successful, 0 on failure.
* This is analagous to the return value from sscanf()
*/
/**
* Macro utilizing ::epicsParseLong to convert
* \return 0=failure, 1=success
*/
#define epicsScanLong(str, to, base) (!epicsParseLong(str, to, base, NULL))
/**
* Macro utilizing ::epicsParseULong to convert
* \return 0=failure, 1=success
*/
#define epicsScanULong(str, to, base) (!epicsParseULong(str, to, base, NULL))
/**
* Macro utilizing ::epicsParseLLong to convert
* \return 0=failure, 1=success
*/
#define epicsScanLLong(str, to, base) (!epicsParseLLong(str, to, base, NULL))
/**
* Macro utilizing ::epicsParseULLong to convert
* \return 0=failure, 1=success
*/
#define epicsScanULLong(str, to, base) (!epicsParseULLong(str, to, base, NULL))
/**
* Macro utilizing ::epicsParseFloat to convert
* \return 0=failure, 1=success
*/
#define epicsScanFloat(str, to) (!epicsParseFloat(str, to, NULL))
/**
* Macro utilizing ::epicsParseDouble to convert
* \return 0=failure, 1=success
*/
#define epicsScanDouble(str, to) (!epicsParseDouble(str, to, NULL))
#ifdef __cplusplus
+1 -1
View File
@@ -48,7 +48,7 @@ LIBCOM_API unsigned int epicsMemHash(const char *str, size_t length,
* @returns 1.0 when A and B are identical, down to 0.0 when A and B are unrelated,
* or < 0.0 on error.
*
* @since UNRELEASED
* @since EPICS 7.0.5
*/
LIBCOM_API double epicsStrSimilarity(const char *A, const char *B);
+42 -22
View File
@@ -8,9 +8,11 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Jeff Hill
* Date: 5-95
/**
* \file epicsTypes.h
* \author: Jeff Hill
*
* \brief The core data types used by epics
*/
#ifndef INC_epicsTypes_H
@@ -32,9 +34,12 @@ typedef enum {
epicsTrue = 1
} epicsBoolean EPICS_DEPRECATED;
/*
/**
* \name epicsTypes
* Architecture Independent Data Types
*
* These are sufficient for all our current archs
* @{
*/
typedef char epicsInt8;
typedef unsigned char epicsUInt8;
@@ -49,25 +54,28 @@ typedef epicsUInt16 epicsEnum16;
typedef float epicsFloat32;
typedef double epicsFloat64;
typedef epicsInt32 epicsStatus;
/** @} */
#define MAX_STRING_SIZE 40
/**
* \brief !! Dont use this - it may vanish in the future !!
*/
typedef struct {
unsigned length;
char *pString;
} epicsString;
/*
* !! Dont use this - it may vanish in the future !!
/**
* \brief !! Dont use this - it may vanish in the future !!
*
* Provided only for backwards compatibility with
* db_access.h
*
*/
#define MAX_STRING_SIZE 40
typedef char epicsOldString[MAX_STRING_SIZE];
/*
* union of all types
/**
* \brief Union of all types
*
* Strings included here as pointers only so that we support
* large string types.
@@ -90,11 +98,11 @@ typedef union epics_any {
epicsString string;
} epicsAny;
/*
* Corresponding Type Codes
/**
* \brief Corresponding Type Codes
* (this enum must start at zero)
*
* !! Update epicsTypeToDBR_XXXX[] and DBR_XXXXToEpicsType
* !! Update \ref epicsTypeToDBR_XXXX[] and \ref DBR_XXXXToEpicsType
* in db_access.h if you edit this enum !!
*/
typedef enum {
@@ -116,8 +124,9 @@ typedef enum {
#define invalidEpicsType(x) ((x<firstEpicsType) || (x>lastEpicsType))
/*
* The enumeration "epicsType" is an index to this array
/**
* \brief An array providing the names for each type
* The enumeration \ref epicsType is an index to this array
* of type name strings.
*/
#ifdef epicsTypesGLOBAL
@@ -138,8 +147,9 @@ const char *epicsTypeNames [lastEpicsType+1] = {
LIBCOM_API extern const char *epicsTypeNames [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
/*
* The enumeration "epicsType" is an index to this array
/**
* \brief An array providing the names for each type code
* The enumeration \ref epicsType is an index to this array
* of type code name strings.
*/
#ifdef epicsTypesGLOBAL
@@ -160,6 +170,11 @@ const char *epicsTypeCodeNames [lastEpicsType+1] = {
LIBCOM_API extern const char *epicsTypeCodeNames [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
/**
* \brief An array providing the sizes for each type
* The enumeration \ref epicsType is an index to this array
* of type code name strings.
*/
#ifdef epicsTypesGLOBAL
const unsigned epicsTypeSizes [lastEpicsType+1] = {
sizeof (epicsInt8),
@@ -178,10 +193,6 @@ const unsigned epicsTypeSizes [lastEpicsType+1] = {
LIBCOM_API extern const unsigned epicsTypeSizes [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
/*
* The enumeration "epicsType" is an index to this array
* of type class identifiers.
*/
typedef enum {
epicsIntC,
epicsUIntC,
@@ -191,6 +202,11 @@ typedef enum {
epicsOldStringC
} epicsTypeClass;
/**
* \brief An array providing the class of each type
* The enumeration \ref epicsType is an index to this array
* of type class identifiers.
*/
#ifdef epicsTypesGLOBAL
const epicsTypeClass epicsTypeClasses [lastEpicsType+1] = {
epicsIntC,
@@ -209,7 +225,11 @@ const epicsTypeClass epicsTypeClasses [lastEpicsType+1] = {
LIBCOM_API extern const epicsTypeClass epicsTypeClasses [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
/**
* \brief An array providing the field name for each type
* The enumeration \ref epicsType is an index to this array
* of type code name strings.
*/
#ifdef epicsTypesGLOBAL
const char *epicsTypeAnyFieldName [lastEpicsType+1] = {
"int8",
+13 -5
View File
@@ -13,11 +13,6 @@
extern "C" {
#endif
/*
* epicsStrtod() for systems with broken strtod() routine
*/
LIBCOM_API double epicsStrtod(const char *str, char **endp);
/*
* Microsoft apparently added strto[u]ll() in VS2013
* Older compilers have these equivalents though
@@ -28,6 +23,19 @@ LIBCOM_API double epicsStrtod(const char *str, char **endp);
# define strtoull _strtoui64
#endif
/*
* strtod works in MSVC 1900 and mingw, use
* the OS version in those and our own otherwise
*/
#if (_MSC_VER < 1900) && !defined(_MINGW)
/*
* epicsStrtod() for systems with broken strtod() routine
*/
LIBCOM_API double epicsStrtod(const char *str, char **endp);
#else
# define epicsStrtod strtod
#endif
#ifdef __cplusplus
}
#endif
@@ -194,6 +194,7 @@ void epicsMutexOsdShow(struct epicsMutexOSD * pmutex, unsigned int level)
void epicsMutexOsdShowAll(void)
{
#if defined _POSIX_THREAD_PRIO_INHERIT
int proto = -1;
int ret = pthread_mutexattr_getprotocol(&globalAttrRecursive, &proto);
if(ret) {
@@ -201,4 +202,7 @@ void epicsMutexOsdShowAll(void)
} else {
printf("PI is%s enabled\n", proto==PTHREAD_PRIO_INHERIT ? "" : " not");
}
#else
printf("PI not supported\n");
#endif
}
+16 -7
View File
@@ -1,5 +1,5 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2021 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
@@ -8,13 +8,22 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef osdThreadh
#define osdThreadh
#ifndef INC_osdThread_H
#define INC_osdThread_H
/* VxWorks 6.9 and later can support joining threads */
#include <epicsVersion.h>
#if (_WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR < 9)
#undef EPICS_THREAD_CAN_JOIN
#ifdef _WRS_VXWORKS_MAJOR
# define VXWORKS_VERSION_INT VERSION_INT(_WRS_VXWORKS_MAJOR, \
_WRS_VXWORKS_MINOR, _WRS_VXWORKS_MAINT, _WRS_VXWORKS_SVCPK)
#else
/* Version not available at compile-time, assume... */
# define VXWORKS_VERSION_INT VERSION_INT(5, 5, 0, 0)
#endif
#endif /* osdThreadh */
#if VXWORKS_VERSION_INT < VERSION_INT(6, 9, 4, 1)
/* VxWorks 6.9.4.1 and later can support joining threads */
# undef EPICS_THREAD_CAN_JOIN
#endif
#endif /* INC_osdThread_H */
+14 -2
View File
@@ -58,14 +58,26 @@ static void ClockTimeSync(void *dummy);
/* ClockTime_Report iocsh command */
static const iocshArg ReportArg0 = { "interest_level", iocshArgArgv};
static const iocshArg * const ReportArgs[1] = { &ReportArg0 };
static const iocshFuncDef ReportFuncDef = {"ClockTime_Report", 1, ReportArgs};
static const iocshFuncDef ReportFuncDef = {"ClockTime_Report", 1, ReportArgs,
"Reports clock synchronization status:\n"
" - On vxWorks and RTEMS:\n"
" * synchronization state\n"
" * last synchronization time with provider\n"
" * synchronization interval\n"
" - On workstation (WIN,*NIX):\n"
" * minimal report\n"};
static void ReportCallFunc(const iocshArgBuf *args)
{
ClockTime_Report(args[0].ival);
}
/* ClockTime_Shutdown iocsh command */
static const iocshFuncDef ShutdownFuncDef = {"ClockTime_Shutdown", 0, NULL};
static const iocshFuncDef ShutdownFuncDef = {"ClockTime_Shutdown", 0, NULL,
"Stops the OS synchronization thread\n"
" - On vxWorks and RTEMS:\n"
" * OS clock will free run\n"
" - On workstation (WIN,*NIX):\n"
" * no change\n"};
static void ShutdownCallFunc(const iocshArgBuf *args)
{
ClockTime_Shutdown(NULL);
+9 -2
View File
@@ -64,14 +64,21 @@ static void NTPTimeSync(void *dummy);
/* NTPTime_Report iocsh command */
static const iocshArg ReportArg0 = { "interest_level", iocshArgArgv};
static const iocshArg * const ReportArgs[1] = { &ReportArg0 };
static const iocshFuncDef ReportFuncDef = {"NTPTime_Report", 1, ReportArgs};
static const iocshFuncDef ReportFuncDef = {"NTPTime_Report", 1, ReportArgs,
"Display time provider synchronization state\n"
" interest_level - with level 1 it also shows:\n"
" * synchronization interval\n"
" * time when last synchronized\n"
" * nominal and measured system tick rates\n"
" * server address (vxWorks only)\n"};
static void ReportCallFunc(const iocshArgBuf *args)
{
NTPTime_Report(args[0].ival);
}
/* NTPTime_Shutdown iocsh command */
static const iocshFuncDef ShutdownFuncDef = {"NTPTime_Shutdown", 0, NULL};
static const iocshFuncDef ShutdownFuncDef = {"NTPTime_Shutdown", 0, NULL,
"Shuts down NTP time synchronization thread\n"};
static void ShutdownCallFunc(const iocshArgBuf *args)
{
NTPTime_Shutdown(NULL);
+3 -1
View File
@@ -29,6 +29,8 @@
#include "yajl_encode.h"
#include "yajl_bytestack.h"
#include <epicsStdlib.h>
#ifndef LLONG_MAX
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
#define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1)
@@ -334,7 +336,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
yajl_buf_clear(hand->decodeBuf);
yajl_buf_append(hand->decodeBuf, buf, bufLen);
buf = yajl_buf_data(hand->decodeBuf);
d = strtod((char *) buf, NULL);
d = epicsStrtod((char *) buf, NULL);
if ((d == HUGE_VAL || d == -HUGE_VAL) &&
errno == ERANGE)
{