diff --git a/modules/libcom/src/as/asTrapWrite.h b/modules/libcom/src/as/asTrapWrite.h index b8033cb94..8f93fa1ee 100644 --- a/modules/libcom/src/as/asTrapWrite.h +++ b/modules/libcom/src/as/asTrapWrite.h @@ -6,8 +6,15 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/*asTrapWrite.h*/ -/* Author: Marty Kraimer Date: 07NOV2000 */ + +/** + * \file asTrapWrite.h + * \brief API for monitoring external put operations to an IOC. + * \author Marty Kraimer + * + * The access security subsystem provides an API asTrapWrite that makes + * put/write requests visible to any facility that registers a listener. + */ #ifndef INCasTrapWriteh #define INCasTrapWriteh @@ -18,37 +25,68 @@ extern "C" { #endif +/** + * \brief The message passed to registered listeners. + */ typedef struct asTrapWriteMessage { - const char *userid; - const char *hostid; + const char *userid; /**< \brief Userid of whoever orginated the request. */ + const char *hostid; /**< \brief Hostid of whoever orginated the request. */ + /** \brief A field for use by the server. + * + * Any listener that uses this field must know what type of + * server is forwarding the put requests. This pointer holds + * the value the server provides to asTrapWriteWithData(), which + * for RSRV is the dbChannel pointer for the target field. + */ void *serverSpecific; + /** \brief A field for use by the \ref asTrapWriteListener. + * + * When the listener is called before the write, this has the + * value 0. The listener can give it any value it desires + * and it will have the same value when the listener gets + * called again after the write. + */ void *userPvt; - int dbrType; /* Data type from ca/db_access.h, NOT dbFldTypes.h */ - int no_elements; - void *data; /* Might be NULL if no data is available */ + int dbrType; /**< \brief Data type from ca/db_access.h, NOT dbFldTypes.h */ + int no_elements; /**< \brief Array length */ + void *data; /**< \brief Might be NULL if no data is available */ } asTrapWriteMessage; - +/** + * \brief An identifier needed to unregister an listener. + */ typedef void *asTrapWriteId; + +/** + * \brief Pointer to a listener function. + * + * Each registered listener function is called twice for every put; once + * before and once after the write is performed. + * The listener may set \c userPvt in the first call and retrieve it in the + * second call. + * + * Each asTrapWriteMessage can change or may be deleted after the user's + * asTrapWriteListener returns + * + * The listener function is called by a server thread so it must not block + * or do anything that causes a delay. +*/ typedef void(*asTrapWriteListener)(asTrapWriteMessage *pmessage,int after); +/** + * \brief Register function to be called on asTrapWriteListener. + * \param func The listener function to be called. + * \return A listener identifier for unregistering this listener. + */ epicsShareFunc asTrapWriteId epicsShareAPI asTrapWriteRegisterListener( asTrapWriteListener func); +/** + * \brief Unregister asTrapWriteListener. + * \param id Listener identifier from asTrapWriteRegisterListener(). + */ epicsShareFunc void epicsShareAPI asTrapWriteUnregisterListener( asTrapWriteId id); -/* - * asTrapWriteListener is called before and after the write is performed. - * The listener can set userPvt on the before call and retrieve it after - * after = (0,1) (before,after) the put. - * - * Each asTrapWriteMessage can change or may be deleted after - * the user's asTrapWriteListener returns - * - * asTrapWriteListener delays the associated server thread so it must not - * do anything that causes to to block. -*/ - #ifdef __cplusplus } #endif diff --git a/modules/libcom/src/bucketLib/bucketLib.h b/modules/libcom/src/bucketLib/bucketLib.h index 60d73b459..0336d6e18 100644 --- a/modules/libcom/src/bucketLib/bucketLib.h +++ b/modules/libcom/src/bucketLib/bucketLib.h @@ -4,16 +4,19 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Jeffrey O. Hill - * hill@luke.lanl.gov - * (505) 665 1831 - * Date: 9-93 +/** + * \file bucketLib.h + * \author Jeffrey O. Hill + * \brief A hash table. Do not use for new code. * - * NOTES: - * .01 Storage for identifier must persist until an item is deleted + * \details + * A hash table for which keys may be unsigned integers, pointers, or + * strings. This API is used by the IOC's Channel Access Server, but + * it should not be used by other code. + * + * \note Storage for identifiers must persist until an item is deleted */ #ifndef INCbucketLibh @@ -27,10 +30,13 @@ extern "C" { #include "epicsTypes.h" #include "shareLib.h" +/** \brief Internal: bucket identifier */ typedef unsigned BUCKETID; +/** \brief Internal: bucket key type */ typedef enum {bidtUnsigned, bidtPointer, bidtString} buckTypeOfId; +/** \brief Internal: bucket item structure */ typedef struct item{ struct item *pItem; const void *pId; @@ -38,6 +44,7 @@ typedef struct item{ buckTypeOfId type; }ITEM; +/** \brief Internal: Hash table structure */ typedef struct bucket{ ITEM **pTable; void *freeListPVT; @@ -45,47 +52,147 @@ typedef struct bucket{ unsigned hashIdNBits; unsigned nInUse; }BUCKET; - -epicsShareFunc BUCKET * epicsShareAPI bucketCreate (unsigned nHashTableEntries); -epicsShareFunc int epicsShareAPI bucketFree (BUCKET *prb); -epicsShareFunc int epicsShareAPI bucketShow (BUCKET *pb); - -/* - * !! Identifier must exist (and remain constant) at the specified address until - * the item is deleted from the bucket !! +/** + * \brief Creates a new hash table + * \param nHashTableEntries Table size + * \return Pointer to the newly created hash table, or NULL. */ -epicsShareFunc int epicsShareAPI bucketAddItemUnsignedId (BUCKET *prb, +epicsShareFunc BUCKET * epicsShareAPI bucketCreate (unsigned nHashTableEntries); +/** + * \brief Release memory used by a hash table + * \param *prb Pointer to the hash table + * \return S_bucket_success + * \note All items must be deleted from the hash table before calling this. + */ +epicsShareFunc int epicsShareAPI bucketFree (BUCKET *prb); +/** + * \brief Display information about a hash table + * \param *prb Pointer to the hash table + * \return S_bucket_success + */ +epicsShareFunc int epicsShareAPI bucketShow (BUCKET *prb); + +/** + * \brief Add an item identified by an unsigned int to the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \param *pApp Pointer to the payload + * \return Status value + */ +epicsShareFunc int epicsShareAPI bucketAddItemUnsignedId (BUCKET *prb, const unsigned *pId, const void *pApp); -epicsShareFunc int epicsShareAPI bucketAddItemPointerId (BUCKET *prb, +/** + * \brief Add an item identified by a pointer to the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \param *pApp Pointer to the payload + * \return Status value + */ +epicsShareFunc int epicsShareAPI bucketAddItemPointerId (BUCKET *prb, void * const *pId, const void *pApp); -epicsShareFunc int epicsShareAPI bucketAddItemStringId (BUCKET *prb, +/** + * \brief Add an item identified by a string to the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \param *pApp Pointer to the payload + * \return Status value + */ +epicsShareFunc int epicsShareAPI bucketAddItemStringId (BUCKET *prb, const char *pId, const void *pApp); - +/** + * \brief Remove an item identified by a string from the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Status value + */ epicsShareFunc int epicsShareAPI bucketRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId); +/** + * \brief Remove an item identified by a pointer from the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Status value + */ epicsShareFunc int epicsShareAPI bucketRemoveItemPointerId (BUCKET *prb, void * const *pId); +/** + * \brief Remove an item identified by a string from the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Status value + */ epicsShareFunc int epicsShareAPI bucketRemoveItemStringId (BUCKET *prb, const char *pId); - +/** + * \brief Find an item identified by an unsigned int in the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Item's payload pointer, or NULL if not found + */ epicsShareFunc void * epicsShareAPI bucketLookupItemUnsignedId (BUCKET *prb, const unsigned *pId); +/** + * \brief Find an item identified by a pointer in the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Item's payload pointer, or NULL if not found + */ epicsShareFunc void * epicsShareAPI bucketLookupItemPointerId (BUCKET *prb, void * const *pId); +/** + * \brief Find an item identified by a string in the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Item's payload pointer, or NULL if not found + */ epicsShareFunc void * epicsShareAPI bucketLookupItemStringId (BUCKET *prb, const char *pId); +/** + * \brief Find and delete an item identified by an unsigned int from the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Item's payload pointer, or NULL if not found + */ epicsShareFunc void * epicsShareAPI bucketLookupAndRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId); +/** + * \brief Find and delete an item identified by a pointer from the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Item's payload pointer, or NULL if not found + */ epicsShareFunc void * epicsShareAPI bucketLookupAndRemoveItemPointerId (BUCKET *prb, void * const *pId); +/** + * \brief Find and delete an item identified by a string from the table + * \param *prb Pointer to the hash table + * \param *pId Pointer to the identifier + * \return Item's payload pointer, or NULL if not found + */ epicsShareFunc void * epicsShareAPI bucketLookupAndRemoveItemStringId (BUCKET *prb, const char *pId); -/* - * Status returned by bucketLib functions + /** + * \name Status values returned by some bucketLib functions + * @{ + */ +/** + * \brief A synonym for S_bucket_success */ #define BUCKET_SUCCESS S_bucket_success +/** + * \brief Success, must be 0. + */ #define S_bucket_success 0 +/** + * \brief Memory allocation failed + */ #define S_bucket_noMemory (M_bucket | 1) /*Memory allocation failed*/ +/** + * \brief Identifier already in use + */ #define S_bucket_idInUse (M_bucket | 2) /*Identifier already in use*/ +/** + * \brief Unknown identifier + */ #define S_bucket_uknId (M_bucket | 3) /*Unknown identifier*/ +/** @} */ #ifdef __cplusplus } #endif #endif /*INCbucketLibh*/ - diff --git a/modules/libcom/src/calc/postfix.h b/modules/libcom/src/calc/postfix.h index b90492012..6bdbc1ae0 100644 --- a/modules/libcom/src/calc/postfix.h +++ b/modules/libcom/src/calc/postfix.h @@ -4,11 +4,16 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* postfix.h - * Original Author: Bob Dalesio - * Date: 9-21-88 +/** + * \file postfix.h + * \author Bob Dalesio, Andrew Johnson + * + * \brief The API for the EPICS Calculation Engine + * + * Defines macros and the routines provided by the calculation engine for + * subsystems that need to evaluate mathematical expressions. */ #ifndef INCpostfixh @@ -16,69 +21,340 @@ #include "shareLib.h" +/** \brief Number of input arguments to a calc expression (A-L) */ #define CALCPERFORM_NARGS 12 +/** \brief Size of the internal partial result stack */ #define CALCPERFORM_STACK 80 -#define INFIX_TO_POSTFIX_SIZE(n) ((n)*21/6) -/* The above expression is an estimate of the maximum postfix buffer - * size needed for a given infix expression buffer (the argument must count - * the trailing nil byte in the input expression string). The actual size +/** + * \name Postfix and Infix Buffer Sizes + * @{ + */ +/** + * \brief Calculate required size of postfix buffer from infix + * + * This macro calculates the maximum size of postfix buffer needed for an + * infix expression buffer of a given size. The argument \c n must count + * the trailing nil byte in the input expression string. The actual size * needed is never larger than this value, although it is actually a * few bytes smaller for some sizes. * * The maximum expansion from infix to postfix is for the sub-expression - * .1?.1: + \code + .1?.1: +\endcode * which is 6 characters long and results in 21 bytes of postfix: - * .1 => LITERAL_DOUBLE + 8 byte value - * ? => COND_IF - * .1 => LITERAL_DOUBLE + 8 byte value - * : => COND_ELSE - * ... - * => COND_END +\code + .1 => LITERAL_DOUBLE + 8 byte value + ? => COND_IF + .1 => LITERAL_DOUBLE + 8 byte value + : => COND_ELSE + ... + => COND_END +\endcode * For other short expressions the factor 21/6 always gives a big enough * postfix buffer (proven by hand, look at '1+' and '.1+' as well). */ +#define INFIX_TO_POSTFIX_SIZE(n) ((n)*21/6) -/* These are not hard limits, just default sizes for the database */ +/** + * \brief Size of a "standard" infix string. + * + * This is not a hard limit, just the default size for the database + */ #define MAX_INFIX_SIZE 100 +/** + * \brief Size of a "standard" postfix buffer. + * + * This is not a hard limit, just the default size for the database + */ #define MAX_POSTFIX_SIZE INFIX_TO_POSTFIX_SIZE(MAX_INFIX_SIZE) +/** @} */ -/* Error numbers from postfix */ +/** \name Calc Engine Error Codes +* \note Changes in these errors must also be made in calcErrorStr(). + * @{ + */ -#define CALC_ERR_NONE 0 /* No error */ -#define CALC_ERR_TOOMANY 1 /* Too many results returned */ -#define CALC_ERR_BAD_LITERAL 2 /* Bad numeric literal */ -#define CALC_ERR_BAD_ASSIGNMENT 3 /* Bad assignment target */ -#define CALC_ERR_BAD_SEPERATOR 4 /* Comma without parentheses */ -#define CALC_ERR_PAREN_NOT_OPEN 5 /* Close parenthesis without open */ -#define CALC_ERR_PAREN_OPEN 6 /* Open parenthesis at end of expression */ -#define CALC_ERR_CONDITIONAL 7 /* Unbalanced conditional ?: operators */ -#define CALC_ERR_INCOMPLETE 8 /* Incomplete expression, operand missing */ -#define CALC_ERR_UNDERFLOW 9 /* Runtime stack would underflow */ -#define CALC_ERR_OVERFLOW 10 /* Runtime stack would overflow */ -#define CALC_ERR_SYNTAX 11 /* Syntax error */ -#define CALC_ERR_NULL_ARG 12 /* NULL or empty input argument */ -#define CALC_ERR_INTERNAL 13 /* Internal error, bad element type */ -/* Changes in the above errors must also be made in calcErrorStr() */ +/** \brief No error */ +#define CALC_ERR_NONE 0 +/** \brief Too many results returned */ +#define CALC_ERR_TOOMANY 1 +/** \brief Bad numeric literal */ +#define CALC_ERR_BAD_LITERAL 2 +/** \brief Bad assignment target */ +#define CALC_ERR_BAD_ASSIGNMENT 3 +/** \brief Comma without parentheses */ +#define CALC_ERR_BAD_SEPERATOR 4 +/** \brief Close parenthesis without open */ +#define CALC_ERR_PAREN_NOT_OPEN 5 +/** \brief Open parenthesis at end of expression */ +#define CALC_ERR_PAREN_OPEN 6 +/** \brief Unbalanced conditional ?: operators */ +#define CALC_ERR_CONDITIONAL 7 +/** \brief Incomplete expression, operand missing */ +#define CALC_ERR_INCOMPLETE 8 +/** \brief Runtime stack would underflow */ +#define CALC_ERR_UNDERFLOW 9 +/** \brief Runtime stack would overflow */ +#define CALC_ERR_OVERFLOW 10 +/** \brief Syntax error */ +#define CALC_ERR_SYNTAX 11 +/** \brief NULL or empty input argument */ +#define CALC_ERR_NULL_ARG 12 +/** \brief Internal error, bad element type */ +#define CALC_ERR_INTERNAL 13 +/** @} */ #ifdef __cplusplus extern "C" { #endif +/** \brief Compile an infix expression into postfix byte-code + * + * Converts an expression from an infix string to postfix byte-code + * + * \param pinfix Pointer to the infix string + * \param ppostfix Pointer to the postfix buffer + * \param perror Place to return an error code + * \return Non-zero value in event of error + * + * It is the callers's responsibility to ensure that \c ppostfix points + * to sufficient storage to hold the postfix expression. The macro + * INFIX_TO_POSTFIX_SIZE(n) can be used to calculate an appropriate + * postfix buffer size from the length of the infix buffer. + * + * \note "n" must count the terminating nil byte too. + * + * -# The **infix expressions** that can be used are very similar + * to the C expression syntax, but with some additions and subtle + * differences in operator meaning and precedence. The string may + * contain a series of expressions separated by a semi-colon character ';' + * any one of which may actually provide the calculation result; however + * all of the other expressions included must assign their result to + * a variable. All alphabetic elements described below are case independent, + * so upper and lower case letters may be used and mixed in the variable + * and function names as desired. Spaces may be used anywhere within an + * expression except between the characters that make up a single expression element. + * + * -# ***Numeric Literals*** + * The simplest expression element is a numeric literal, any (positive) + * number expressed using the standard floating point syntax that can be stored + * as a double precision value. This now includes the values Infinity and + * NaN (not a number). Note that negative numbers will be encoded as a + * positive literal to which the unary negate operator is applied. + * + * - Examples: + * - 1 + * - 2.718281828459 + * - Inf + * + * -# ***Constants*** + * There are three trigonometric constants available to any expression + * which return a value: + * - pi returns the value of the mathematical constant pi. + * - D2R evaluates to pi/180 which, when used as a multiplier, + * converts an angle from degrees to radians. + * - R2D evaluates to 180/pi which as a multiplier converts an angle + * from radians to degrees. + * + * -# ***Variables*** + * Variables are used to provide inputs to an expression, and are named + * using the single letters A through L inclusive or the keyword VAL which + * refers to the previous result of this calculation. The software that + * makes use of the expression evaluation code should document how the + * individual variables are given values; for the calc record type the input + * links INPA through INPL can be used to obtain these from other record fields, + * and VAL refers to the the VAL field (which can be overwritten from outside + * the record via Channel Access or a database link). + * + * -# ***Variable Assignment Operator*** + * Recently added is the ability to assign the result of a sub-expression to + * any of the single letter variables, which can then be used in another + * sub-expression. The variable assignment operator is the character pair + * := and must immediately follow the name of the variable to receive the + * expression value. Since the infix string must return exactly one value, every + * expression string must have exactly one sub-expression that is not an + * assignment, which can appear anywhere in the string. Sub-expressions within + * the string are separated by a semi-colon character. + * + * - Examples: + * - B; B:=A + * - i:=i+1; a*sin(i*D2R) + * + * -# ***Arithmetic Operators*** + * The usual binary arithmetic operators are provided: + - * and / with their + * usual relative precedence and left-to-right associativity, and - may also + * be used as a unary negate operator where it has a higher precedence and + * associates from right to left. There is no unary plus operator, so numeric + * literals cannot begin with a + sign. + * + * - Examples: + * - a*b + c + * - a/-4 - b + * + * Three other binary operators are also provided: % is the integer modulo operator, + * while the synonymous operators ** and ^ raise their left operand to the power of + * the right operand. % has the same precedence and associativity as * and /, while + * the power operators associate left-to-right and have a precedence in between * and + * unary minus. + * + * - Examples: + * - e:=a%10; + * - d:=a/10%10; + * - c:=a/100%10; + * - b:=a/1000%10; + * - b*4096+c*256+d*16+e + * - sqrt(a**2 + b**2) + * + * -# ***Algebraic Functions*** + * Various algebraic functions are available which take parameters inside + * parentheses. The parameter seperator is a comma. + * + * - Absolute value: abs(a) + * - Exponential ea: exp(a) + * - Logarithm, base 10: log(a) + * - Natural logarithm (base e): ln(a) or loge(a) + * - n parameter maximum value: max(a, b, ...) + * - n parameter minimum value: min(a, b, ...) + * - Square root: sqr(a) or sqrt(a) + * + * -# ***Trigonometric Functions*** + * Standard circular trigonometric functions, with angles expressed in radians: + * - Sine: sin(a) + * - Cosine: cos(a) + * - Tangent: tan(a) + * - Arcsine: asin(a) + * - Arccosine: acos(a) + * - Arctangent: atan(a) + * - 2 parameter arctangent: atan2(a, b) + * \note Note that these arguments are the reverse of the ANSI C function, + * so while C would return arctan(a/b) the calc expression engine returns arctan(b/a) + * + * -# ***Hyperbolic Trigonometry*** + * The basic hyperbolic functions are provided, but no inverse functions + * (which are not provided by the ANSI C math library either). + * - Hyperbolic sine: sinh(a) + * - Hyperbolic cosine: cosh(a) + * - Hyperbolic tangent: tanh(a) + * + * -# ***Numeric Functions*** + * The numeric functions perform operations related to the floating point + * numeric representation and truncation or rounding. + * - Round up to next integer: ceil(a) + * - Round down to next integer: floor(a) + * - Round to nearest integer: nint(a) + * - Test for infinite result: isinf(a) + * - Test for any non-numeric values: isnan(a, ...) + * - Test for all finite, numeric values: finite(a, ...) + * - Random number between 0 and 1: rndm + * + * -# ***Boolean Operators*** + * These operators regard their arguments as true or false, where 0.0 is + * false and any other value is true. + * + * - Boolean and: a && b + * - Boolean or: a || b + * - Boolean not: !a + * + * -# ***Bitwise Operators*** + * The bitwise operators convert their arguments to an integer (by truncation), + * perform the appropriate bitwise operation and convert back to a floating point + * value. Unlike in C though, ^ is not a bitwise exclusive-or operator. + * + * - Bitwise and: a & b or a and b + * - Bitwise or: a | b or a or b + * - Bitwise exclusive or: a xor b + * - Bitwise not (ones complement): ~a or not a + * - Bitwise left shift: a << b + * - Bitwise right shift: a >> b + * + * -# ***Relational Operators*** + * Standard numeric comparisons between two values: + * + * - Less than: a < b + * - Less than or equal to: a <= b + * - Equal to: a = b or a == b + * - Greater than or equal to: a >= b + * - Greater than: a > b + * - Not equal to: a != b or a # b + * + * -# ***Conditional Operator*** + * Expressions can use the C conditional operator, which has a lower + * precedence than all of the other operators except for the assignment operator. + * + * - condition ? true result : false result + * - Example: + * - a < 360 ? a+1 : 0 + * + * -# ***Parentheses*** + * Sub-expressions can be placed within parentheses to override operator precence rules. + * Parentheses can be nested to any depth, but the intermediate value stack used by + * the expression evaluation engine is limited to 80 results (which require an + * expression at least 321 characters long to reach). + */ epicsShareFunc long postfix(const char *pinfix, char *ppostfix, short *perror); +/** \brief Run the calculation engine + * + * Evaluates the postfix expression against a set ot input values. + * + * \param parg Pointer to an array of double values for the arguments A-L + * that can appear in the expression. Note that the argument values may be + * modified if the expression uses the assignment operator. + * \param presult Where to put the calculated result, which may be a NaN or Infinity. + * \param ppostfix The postfix expression created by postfix(). + * \return Status value 0 for OK, or non-zero if an error is discovered + * during the evaluation process. + */ epicsShareFunc long calcPerform(double *parg, double *presult, const char *ppostfix); +/** \brief Find the inputs and outputs of an expression + * + * Software using the calc subsystem may need to know what expression + * arguments are used and/or modified by a particular expression. It can + * discover this from the postfix string by calling calcArgUsage(), which + * takes two pointers \c pinputs and \c pstores to a pair of unsigned long + * bitmaps which return that information to the caller. Passing a NULL value + * for either of these pointers is legal if only the other is needed. + * + * The least signficant bit (bit 0) of the bitmap at \c *pinputs will be set + * if the expression depends on the argument A, and so on through bit 11 for + * the argument L. An argument that is not used until after a value has been + * assigned to it will not be set in the pinputs bitmap, thus the bits can + * be used to determine whether a value needs to be supplied for their + * associated argument or not for the purposes of evaluating the expression. + * + * Bit 0 of the bitmap at \c *pstores will be set if the expression assigns + * a value to the argument A, bit 1 for argument B etc. + * \param ppostfix A postfix expression created by postfix(). + * \param pinputs Bitmap pointer. + * \param pstores Bitmap pointer. + * \return The return value will be non-zero if the ppostfix expression was + * illegal, otherwise 0. + */ epicsShareFunc long calcArgUsage(const char *ppostfix, unsigned long *pinputs, unsigned long *pstores); +/** \brief Convert an error code to a string. + * + * Gives out a printable version of an individual error code. + * The error codes are macros defined here with names starting \c CALC_ERR_ + * \param error Error code + * \return A string representation of the error code + */ epicsShareFunc const char * calcErrorStr(short error); +/** \brief Disassemble a postfix expression + * + * Convert the byte-code stream to text and print to stdout. + * \param pinst postfix instructions + */ epicsShareFunc void calcExprDump(const char *pinst); diff --git a/modules/libcom/src/cppStd/epicsAlgorithm.h b/modules/libcom/src/cppStd/epicsAlgorithm.h index 20850242d..e2043cf26 100644 --- a/modules/libcom/src/cppStd/epicsAlgorithm.h +++ b/modules/libcom/src/cppStd/epicsAlgorithm.h @@ -3,71 +3,105 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ -// epicsAlgorithm.h -// Authors: Jeff Hill & Andrew Johnson +/** + * \file epicsAlgorithm.h + * \author Jeff Hill & Andrew Johnson + * + * \brief Contains a few templates out of the C++ standard header algorithm + * + * \note The templates are provided here in a much smaller file. Standard algorithm + * contains many templates for sorting and searching through C++ template containers + * which are not used in EPICS. If all you need from there is std::min(), + * std::max() and/or std::swap() your code may compile faster if you include + * epicsAlgorithm.h and use epicsMin(), epicsMax() and epicsSwap() instead. + * + * The C++ standard only requires types to be less-than comparable, so + * the epicsMin and epicsMax templates only use operator <. + */ #ifndef __EPICS_ALGORITHM_H__ #define __EPICS_ALGORITHM_H__ #include "epicsMath.h" -// The C++ standard only requires types to be less-than comparable, so -// the epicsMin and epicsMax templates only use operator < - -// epicsMin +/** + * Returns the smaller of a or b compared using a inline const T& epicsMin (const T& a, const T& b) { return (b < a) ? b : a; } -// If b is a NaN the above template returns a, but should return NaN. -// These specializations ensure that epicsMin(x,NaN) == NaN - +/** + * Returns the smaller of a or b compared using a inline const float& epicsMin (const float& a, const float& b) { return (b < a) || isnan(b) ? b : a; } +/** + * Returns the smaller of a or b compared using a inline const double& epicsMin (const double& a, const double& b) { return (b < a) || isnan(b) ? b : a; } - -// epicsMax - +/** + * Returns the larger of a or b compared using a inline const T& epicsMax (const T& a, const T& b) { return (a < b) ? b : a; } -// If b is a NaN the above template returns a, but should return NaN. -// These specializations ensure that epicsMax(x,NaN) == NaN - +/** + * Returns the larger of a or b compared using a inline const float& epicsMax (const float& a, const float& b) { return (a < b) || isnan(b) ? b : a; } +/** + * Returns the larger of a or b compared using a inline const double& epicsMax (const double& a, const double& b) { return (a < b) || isnan(b) ? b : a; } - -// epicsSwap - +/** + * Swaps the values of a and b. + * + * \note The data type must support both copy-construction and assignment. + * + */ template inline void epicsSwap(T& a, T& b) { diff --git a/modules/libcom/src/dbmf/dbmf.h b/modules/libcom/src/dbmf/dbmf.h index 2c8a28f2c..ef9787500 100644 --- a/modules/libcom/src/dbmf/dbmf.h +++ b/modules/libcom/src/dbmf/dbmf.h @@ -3,15 +3,33 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Jim Kowalkowski and Marty Kraimer - * Date: 4/97 + +/** + * \file dbmf.h + * \author Jim Kowalkowski, Marty Kraimer * - * A library to manage storage that is allocated and then freed. + * \brief A library to manage storage that is allocated and quickly freed. + * + * Database Macro/Free describes a facility that prevents memory fragmentation + * when temporary storage is being allocated and freed a short time later, at + * the same time that much longer-lived storage is also being allocated, such + * as when parsing items for the IOC database while also creating records. + * + * Routines whin iocCore like dbLoadDatabase() have the following attributes: + * - They repeatedly call malloc() followed soon afterwards by a call to + * free() the temporaryily allocated storage. + * - Between those calls to malloc() and free(), additional calls to + * malloc() are made that do NOT have an associated free(). + * + * \note In some environment, e.g. vxWorks, this behavior causes severe memory + * fragmentation. + * + * \note This facility should NOT be used by code that allocates storage and + * then keeps it for a considerable period of time before releasing. Such code + * should consider using the freeList library. */ #ifndef DBMF_H #define DBMF_H @@ -23,25 +41,71 @@ extern "C" { #endif +/** + * \brief Initialize the facility + * \param size The maximum size request from dbmfMalloc() that will be + * allocated from the dbmf pool (Size is always made a multiple of 8). + * \param chunkItems Each time malloc() must be called size*chunkItems bytes + * are allocated. + * \return 0 on success, -1 if already initialized + * + * \note If dbmfInit() is not called before one of the other routines then it + * is automatically called with size=64 and chunkItems=10 + */ epicsShareFunc int dbmfInit(size_t size, int chunkItems); +/** + * \brief Allocate memory. + * \param bytes If bytes > size then malloc() is used to allocate the memory. + * \return Pointer to the newly-allocated memory, or NULL on failure. + */ epicsShareFunc void * dbmfMalloc(size_t bytes); +/** + * \brief Duplicate a string. + * + * Create a copy of the input string. + * \param str Pointer to the null-terminated string to be copied. + * \return A pointer to the new copy, or NULL on failure. + */ epicsShareFunc char * dbmfStrdup(const char *str); +/** + * \brief Duplicate a string (up to len bytes). + * + * Copy at most len bytes of the input string into a new buffer. If no nil + * terminator is seen in the first \c len bytes a nil terminator is added. + * \param str Pointer to the null-terminated string to be copied. + * \param len Max number of bytes to copy. + * \return A pointer to the new string, or NULL on failure. + */ epicsShareFunc char * dbmfStrndup(const char *str, size_t len); +/** + * \brief Concatenate three strings. + + * Returns a pointer to a null-terminated string made by concatenating the + * three input strings. + * \param lhs Start string to which the others get concatenated to (left part). + * \param mid Next string to be concatenated to the lhs (mid part). + * \param rhs Last string to be concatenated to the lhs+mid (right part). + * \return A pointer to the new string, or NULL on failure. + */ epicsShareFunc char * dbmfStrcat3(const char *lhs, const char *mid, const char *rhs); +/** + * \brief Free the memory allocated by dbmfMalloc. + * \param bytes Pointer to memory obtained from dbmfMalloc(), dbmfStrdup(), + * dbmfStrndup() or dbmfStrcat3(). + */ epicsShareFunc void dbmfFree(void *bytes); +/** + * \brief Free all chunks that contain only free items. + */ epicsShareFunc void dbmfFreeChunks(void); +/** + * \brief Show the status of the dbmf memory pool. + * \param level Detail level. + * \return 0. + */ epicsShareFunc int dbmfShow(int level); -/* Rules: - * 1) Size is always made a multiple of 8. - * 2) if dbmfInit is not called before one of the other routines then it - * is automatically called with size=64 and chunkItems=10 - * 3) These routines should only be used to allocate storage that will - * shortly thereafter be freed. - * 4) dbmfFreeChunks can only free chunks that contain only free items -*/ - #ifdef __cplusplus } #endif diff --git a/modules/libcom/src/ellLib/ellLib.h b/modules/libcom/src/ellLib/ellLib.h index 52b58d169..8448fee2d 100644 --- a/modules/libcom/src/ellLib/ellLib.h +++ b/modules/libcom/src/ellLib/ellLib.h @@ -6,10 +6,23 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: John Winans (ANL) - * Andrew Johnson +/** + * \file ellLib.h + * \author John Winans (ANL) + * \author Andrew Johnson (ANL) + * + * \brief A doubly-linked list library + * + * This provides similar functionality to the VxWorks lstLib library. + * + * Supports the creation and maintenance of a doubly-linked list. The user + * supplies a list descriptor (type \c ELLLIST) that will contain pointers to + * the first and last nodes in the list, and a count of the number of + * nodes in the list. The nodes in the list can be any user-defined structure, + * but they must reserve space for two pointers as their first elements. + * Both the forward and backward chains are terminated with a NULL pointer. */ + #ifndef INC_ellLib_H #define INC_ellLib_H @@ -19,46 +32,182 @@ extern "C" { #endif +/** \brief List node type. + * + * A list node (an \c ELLNODE) must be embedded in the structure to be placed + * on the list, ideally as the first member of that structure. + * + * If the node is elsewhere in the structure, care must be taken to convert + * between the structure pointer and the node pointer and back every time when + * calling routines in the ellLib API. The ellFree() and ellFree2() routines + * cannot be used with such a list. + */ typedef struct ELLNODE { - struct ELLNODE *next; - struct ELLNODE *previous; + struct ELLNODE *next; /**< \brief Pointer to next node in list */ + struct ELLNODE *previous; /**< \brief Pointer to previous node in list */ } ELLNODE; +/** \brief Value of a terminal node + */ #define ELLNODE_INIT {NULL, NULL} +/** \brief List header type + */ typedef struct ELLLIST { - ELLNODE node; - int count; + ELLNODE node; /**< \brief Pointers to the first and last nodes on list */ + int count; /**< \brief Number of nodes on the list */ } ELLLIST; +/** \brief Value of an empty list + */ #define ELLLIST_INIT {ELLNODE_INIT, 0} +/** \brief Pointer to free() for use by ellFree() macro. + * + * This is required for use on Windows, where each DLL has its own free() + * function. The ellFree() macro passes the application's version of free() + * to the ellFree2() function. + */ typedef void (*FREEFUNC)(void *); +/** \brief Initialize a list type + * \param PLIST Pointer to list header to be initialized + */ #define ellInit(PLIST) {\ (PLIST)->node.next = (PLIST)->node.previous = NULL;\ (PLIST)->count = 0;\ } +/** \brief Report the number of nodes in a list + * \param PLIST Pointer to list descriptor + * \return Number of nodes in the list + */ #define ellCount(PLIST) ((PLIST)->count) +/** \brief Find the first node in list + * \param PLIST Pointer to list descriptor + * \return Pointer to first node in the list + */ #define ellFirst(PLIST) ((PLIST)->node.next) +/** \brief Find the last node in list + * \param PLIST Pointer to list descriptor + * \return Pointer to last node in the list + */ #define ellLast(PLIST) ((PLIST)->node.previous) +/** \brief Find the next node in list + * \param PNODE Pointer to node whose successor is to be found + * \return Pointer to the node following \c PNODE + */ #define ellNext(PNODE) ((PNODE)->next) +/** \brief Find the previous node in list + * \param PNODE Pointer to node whose predecessor is to be found + * \return Pointer to the node prior to \c PNODE + */ #define ellPrevious(PNODE) ((PNODE)->previous) +/** \brief Free up the list + * \param PLIST List for which to free all nodes + */ #define ellFree(PLIST) ellFree2(PLIST, free) +/** + * \brief Adds a node to the end of a list + * \param pList Pointer to list descriptor + * \param pNode Pointer to node to be added + */ epicsShareFunc void ellAdd (ELLLIST *pList, ELLNODE *pNode); +/** + * \brief Concatenates a list to the end of another list. + * The list to be added is left empty. Either list (or both) + * can be empty at the beginning of the operation. + * \param pDstList Destination list + * \param pAddList List to be added to \c pDstList + */ epicsShareFunc void ellConcat (ELLLIST *pDstList, ELLLIST *pAddList); +/** + * \brief Deletes a node from a list. + * \param pList Pointer to list descriptor + * \param pNode Pointer to node to be deleted + */ epicsShareFunc void ellDelete (ELLLIST *pList, ELLNODE *pNode); +/** + * \brief Extract a sublist from a list. + * \param pSrcList Pointer to source list + * \param pStartNode First node in \c pSrcList to be extracted + * \param pEndNode Last node in \c pSrcList to be extracted + * \param pDstList Pointer to list where to put extracted list + */ epicsShareFunc void ellExtract (ELLLIST *pSrcList, ELLNODE *pStartNode, ELLNODE *pEndNode, ELLLIST *pDstList); +/** + * \brief Deletes and returns the first node from a list + * \param pList Pointer to list from which to get node + * \return Pointer to the first node from the list, or NULL if the list is empty + */ epicsShareFunc ELLNODE * ellGet (ELLLIST *pList); +/** + * \brief Deletes and returns the last node from a list. + * \param pList Pointer to list from which to get node + * \return Pointer to the last node from the list, or NULL if the list is empty + */ epicsShareFunc ELLNODE * ellPop (ELLLIST *pList); +/** + * \brief Inserts a node into a list immediately after a specific node + * \param plist Pointer to list into which to insert node + * \param pPrev Pointer to the node after which to insert + * \param pNode Pointer to the node to be inserted + * \note If \c pPrev is NULL \c pNode will be inserted at the head of the list + */ epicsShareFunc void ellInsert (ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode); +/** + * \brief Find the Nth node in a list + * \param pList Pointer to list from which to find node + * \param nodeNum Index of the node to be found + * \return Pointer to the element at index \c nodeNum in pList, or NULL if + * there is no such node in the list. + * \note The first node has index 1. + */ epicsShareFunc ELLNODE * ellNth (ELLLIST *pList, int nodeNum); +/** + * \brief Find the list node \c nStep steps away from a specified node + * \param pNode The known node + * \param nStep How many steps to take, may be negative to step backwards + * \return Pointer to the node \c nStep nodes from \c pNode, or NULL if there + * is no such node in the list. + */ epicsShareFunc ELLNODE * ellNStep (ELLNODE *pNode, int nStep); +/** + * \brief Find the index of a specific node in a list + * \param pList Pointer to list to search + * \param pNode Pointer to node to search for + * \return The node's index, or -1 if it cannot be found on the list. + * \note The first node has index 1. + */ epicsShareFunc int ellFind (ELLLIST *pList, ELLNODE *pNode); + typedef int (*pListCmp)(const ELLNODE* A, const ELLNODE* B); -epicsShareFunc void ellSortStable(ELLLIST *pList, pListCmp); +/** + * \brief Stable (MergeSort) of a given list. + * \param pList Pointer to list to be sorted + * \param pListCmp Compare function to be used + * \note The comparison function cmp(A,B) is expected + * to return -1 for AB. + * + * \note Use of mergesort algorithm based on analysis by + * http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html + */ +epicsShareFunc void ellSortStable(ELLLIST *pList, pListCmp pListCmp); +/** + * \brief Free all the nodes in a list. + * + * This routine empties a list, calling freeFunc() for every node on it. + * \param pList List from which to free all nodes + * \param freeFunc The free() routine to be called + * \note The nodes in the list are free()'d on the assumption that the node + * structures were malloc()'d one-at-a-time and that the ELLNODE structure is + * the first member of the parent structure. + */ epicsShareFunc void ellFree2 (ELLLIST *pList, FREEFUNC freeFunc); +/** + * \brief Verifies that the list is consistent + * \param pList List to be verified + */ epicsShareFunc void ellVerify (ELLLIST *pList); #ifdef __cplusplus diff --git a/modules/libcom/src/env/envDefs.h b/modules/libcom/src/env/envDefs.h index 2490702a6..7f4859063 100644 --- a/modules/libcom/src/env/envDefs.h +++ b/modules/libcom/src/env/envDefs.h @@ -4,26 +4,27 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Roger A. Cole - * Date: 07-20-91 + +/** + * \file envDefs.h + * \author Roger A. Cole * + * \brief Routines to get and set EPICS environment parameters. + * + * This file defines environment parameters used by EPICS and the + * routines used to get and set those parameter values. + * + * The ENV_PARAM's declared here are defined in the generated file + * envData.c by the bldEnvData.pl Perl script, which parses this file + * and the build system's CONFIG_ENV and CONFIG_SITE_ENV files. + * User programs can define their own environment parameters for their + * own use--the only caveat is that such parameters aren't automatically + * setup by EPICS. + * + * \note bldEnvData.pl looks for "epicsShareExtern const ENV_PARAM ;" */ -/**************************************************************************** -* TITLE envDefs.h - definitions for environment get/set routines -* -* DESCRIPTION -* This file defines the environment parameters for EPICS. These -* ENV_PARAM's are created in envData.c by bldEnvData for -* use by EPICS programs running under UNIX and VxWorks. -* -* User programs can define their own environment parameters for their -* own use--the only caveat is that such parameters aren't automatically -* setup by EPICS. -* -*****************************************************************************/ #ifndef envDefsH #define envDefsH @@ -34,14 +35,14 @@ extern "C" { #include "shareLib.h" +/** + * \brief A structure to hold a single environment parameter + */ typedef struct envParam { - char *name; /* text name of the parameter */ - char *pdflt; + char *name; /**< \brief Name of the parameter */ + char *pdflt; /**< \brief Default value */ } ENV_PARAM; -/* - * bldEnvData.pl looks for "epicsShareExtern const ENV_PARAM ;" - */ epicsShareExtern const ENV_PARAM EPICS_CA_ADDR_LIST; epicsShareExtern const ENV_PARAM EPICS_CA_CONN_TMO; epicsShareExtern const ENV_PARAM EPICS_CA_AUTO_ADDR_LIST; @@ -57,7 +58,7 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_IGNORE_ADDR_LIST; epicsShareExtern const ENV_PARAM EPICS_CAS_AUTO_BEACON_ADDR_LIST; epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_ADDR_LIST; epicsShareExtern const ENV_PARAM EPICS_CAS_SERVER_PORT; -epicsShareExtern const ENV_PARAM EPICS_CA_BEACON_PERIOD; /* deprecated */ +epicsShareExtern const ENV_PARAM EPICS_CA_BEACON_PERIOD; /**< \brief deprecated */ epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PERIOD; epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT; epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS; @@ -74,30 +75,167 @@ epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_FILE_COMMAND; epicsShareExtern const ENV_PARAM IOCSH_PS1; epicsShareExtern const ENV_PARAM IOCSH_HISTSIZE; epicsShareExtern const ENV_PARAM IOCSH_HISTEDIT_DISABLE; - epicsShareExtern const ENV_PARAM *env_param_list[]; struct in_addr; -epicsShareFunc char * epicsShareAPI +/** + * \brief Get value of a configuration parameter + * + * Gets the value of a configuration parameter from the environment + * and copies it into the caller's buffer. If the parameter isn't + * set in the environment, the default value for the parameter is + * copied instead. If neither provides a non-empty string the buffer + * is set to '\0' and NULL is returned. + * + * \param pParam Pointer to config param structure. + * \param bufDim Dimension of parameter buffer + * \param pBuf Pointer to parameter buffer + * \return Pointer to the environment variable value string, or + * NULL if no parameter value and default value was empty. + */ +epicsShareFunc char * epicsShareAPI envGetConfigParam(const ENV_PARAM *pParam, int bufDim, char *pBuf); -epicsShareFunc const char * epicsShareAPI + +/** + * \brief Get a configuration parameter's value or default string. + * + * \param pParam Pointer to config param structure. + * \return Pointer to the environment variable value string, or to + * the default value for the parameter, or NULL if those strings + * were empty or not set. + */ +epicsShareFunc const char * epicsShareAPI envGetConfigParamPtr(const ENV_PARAM *pParam); -epicsShareFunc long epicsShareAPI + +/** + * \brief Print the value of a configuration parameter. + * + * \param pParam Pointer to config param structure. + * \return 0 + */ +epicsShareFunc long epicsShareAPI envPrtConfigParam(const ENV_PARAM *pParam); -epicsShareFunc long epicsShareAPI + +/** + * \brief Get value of an inet addr config parameter. + * + * Gets the value of a configuration parameter and copies it into + * the caller's (struct in_addr) buffer. If the configuration parameter + * isn't found in the environment, the default value for that parameter + * will be used. The resulting string is converted from a dotted-quad + * format or looked up using the DNS and copied into the inet structure. + * + * If no parameter is found and there is no default, then -1 is + * returned and the callers buffer is unmodified. + * + * \param pParam Pointer to config param structure. + * \param pAddr Pointer to struct to receive inet addr. + * \return 0, or -1 if an error is encountered + */ +epicsShareFunc long epicsShareAPI envGetInetAddrConfigParam(const ENV_PARAM *pParam, struct in_addr *pAddr); -epicsShareFunc long epicsShareAPI + +/** + * \brief Get value of a double configuration parameter. + * + * Gets the value of a configuration parameter, converts it into a + * \c double value and copies that into the caller's buffer. If the + * configuration parameter isn't found in the environment, the + * default value for the parameter is used instead. + * + * If no parameter is found and there is no default, then -1 is + * returned and the callers buffer is unmodified. + * + * \param pParam Pointer to config param structure. + * \param pDouble Pointer to place to store value. + * \return 0, or -1 if an error is encountered + */ +epicsShareFunc long epicsShareAPI envGetDoubleConfigParam(const ENV_PARAM *pParam, double *pDouble); -epicsShareFunc long epicsShareAPI + +/** + * \brief Get value of a long configuration parameter. + * + * Gets the value of a configuration parameter, converts it into a + * \c long value and copies that into the caller's buffer. If the + * configuration parameter isn't found in the environment, the + * default value for the parameter is used instead. + * + * If no parameter is found and there is no default, then -1 is + * returned and the callers buffer is unmodified. + * + * \param pParam Pointer to config param structure. + * \param pLong Pointer to place to store value. + * \return 0, or -1 if an error is encountered + */ +epicsShareFunc long epicsShareAPI envGetLongConfigParam(const ENV_PARAM *pParam, long *pLong); -epicsShareFunc unsigned short epicsShareAPI envGetInetPortConfigParam + +/** + * \brief Get value of a port number configuration parameter. + * + * Returns the value of a configuration parameter that represents + * an inet port number. If no environment variable is found the + * default parameter value is used, and if that is also unset the + * \c defaultPort argument returned instead. The integer value must + * fall between the values IPPORT_USERRESERVED and USHRT_MAX or the + * \c defaultPort argument will be substituted instead. + * + * \param pEnv Pointer to config param structure. + * \param defaultPort Port number to be used if environment settings invalid. + * \return Port number. + */ +epicsShareFunc unsigned short epicsShareAPI envGetInetPortConfigParam (const ENV_PARAM *pEnv, unsigned short defaultPort); +/** + * \brief Get value of a boolean configuration parameter. + * + * Gets the value of a configuration parameter, and puts the value + * 0 or 1 into the caller's buffer depending on the value. If the + * configuration parameter isn't found in the environment, the + * default value for the parameter is used instead. + * + * A value is treated as True (1) if it compares equal to the + * string "yes" with a case-independent string comparison. All + * other strings are treated as False (0). + * + * If no parameter is found and there is no default, then -1 is + * returned and the callers buffer is unmodified. + * + * \param pParam Pointer to config param structure. + * \param pBool Pointer to place to store value. + * \return 0, or -1 if an error is encountered + */ epicsShareFunc long epicsShareAPI envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool); + +/** + * \brief Prints all configuration parameters and their current value. + * + * \return 0 + */ epicsShareFunc long epicsShareAPI epicsPrtEnvParams(void); + +/** + * \brief Set an environment variable's value + * + * The setenv() routine is not available on all operating systems. + * This routine provides a portable alternative for all EPICS targets. + * \param name Environment variable name. + * \param value New value for environment variable. + */ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value); +/** + * \brief Clear the value of an environment variable + * \param name Environment variable name. + */ epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name); +/** + * \brief Print value of an environment variable, or all variables + * + * \param name Environment variable name, or NULL to show all. + */ epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name); #ifdef __cplusplus @@ -105,4 +243,3 @@ epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name); #endif #endif /*envDefsH*/ - diff --git a/modules/libcom/src/iocsh/iocsh.h b/modules/libcom/src/iocsh/iocsh.h index 4b87f3dd7..e69bd3c7b 100644 --- a/modules/libcom/src/iocsh/iocsh.h +++ b/modules/libcom/src/iocsh/iocsh.h @@ -85,27 +85,27 @@ epicsShareFunc const iocshVarDef * epicsShareAPI iocshFindVariable( /* This should only be called when iocsh is no longer needed*/ epicsShareFunc void epicsShareAPI iocshFree(void); -/** shorthand for @code iocshLoad(pathname, NULL) @endcode */ +/** shorthand for \code iocshLoad(pathname, NULL) \endcode */ epicsShareFunc int epicsShareAPI iocsh(const char *pathname); -/** shorthand for @code iocshRun(cmd, NULL) @endcode */ +/** shorthand for \code iocshRun(cmd, NULL) \endcode */ epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd); /** Read and evaluate IOC shell commands from the given file. - * @param pathname Path to script file - * @param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y" - * @return 0 on success, non-zero on error + * \param pathname Path to script file + * \param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y" + * \return 0 on success, non-zero on error */ epicsShareFunc int epicsShareAPI iocshLoad(const char *pathname, const char* macros); /** Evaluate a single IOC shell command - * @param cmd Command string. eg. "echo \"something or other\"" - * @param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y" - * @return 0 on success, non-zero on error + * \param cmd Command string. eg. "echo \"something or other\"" + * \param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y" + * \return 0 on success, non-zero on error */ epicsShareFunc int epicsShareAPI iocshRun(const char *cmd, const char* macros); -/** @brief Signal error from an IOC shell function. +/** \brief Signal error from an IOC shell function. * - * @param err 0 - success (no op), !=0 - error - * @return The err argument value. + * \param err 0 - success (no op), !=0 - error + * \return The err argument value. */ epicsShareFunc int iocshSetError(int err); diff --git a/modules/libcom/src/macLib/macLib.h b/modules/libcom/src/macLib/macLib.h index 14ecdaa3f..8e75d3801 100644 --- a/modules/libcom/src/macLib/macLib.h +++ b/modules/libcom/src/macLib/macLib.h @@ -4,20 +4,26 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Definitions for macro substitution library (macLib) +/** + * \file macLib.h + * \brief Text macro substitution routines + * \author William Lupton, W. M. Keck Observatory * - * William Lupton, W. M. Keck Observatory + * This general purpose macro substitution library + * is used for all macro substitutions in EPICS Base. + * + * Most routines return 0 (OK) on success, -1 (ERROR) on failure, + * or small positive values for extra info. + * The macGetValue() and macExpandString() routines depart from this + * and return information both on success / failure and on value length. + * Errors and warnings are reported using errlogPrintf(). */ #ifndef INCmacLibH #define INCmacLibH -/* - * EPICS include files needed by this file - */ #include "ellLib.h" #include "shareLib.h" @@ -25,137 +31,275 @@ extern "C" { #endif -/* - * Maximum size of macro name or value string (simpler to make fixed) +/** \brief Maximum size of a macro name or value */ #define MAC_SIZE 256 -/* - * Macro substitution context. One of these contexts is allocated each time - * macCreateHandle() is called +/** \brief Macro substitution context, for use by macLib routines only. + * + * An application may have multiple active contexts if desired. */ typedef struct { - long magic; /* magic number (used for authentication) */ - int dirty; /* values need expanding from raw values? */ - int level; /* scoping level */ - int debug; /* debugging level */ - ELLLIST list; /* macro name / value list */ - int flags; /* operating mode flags */ + long magic; /**< \brief magic number (used for authentication) */ + int dirty; /**< \brief values need expanding from raw values? */ + int level; /**< \brief scoping level */ + int debug; /**< \brief debugging level */ + ELLLIST list; /**< \brief macro name / value list */ + int flags; /**< \brief operating mode flags */ } MAC_HANDLE; -/* - * Function prototypes (core library) +/** \name Core Library + * The core library provides a minimal set of basic operations. + * @{ */ -epicsShareFunc long /* 0 = OK; <0 = ERROR */ + +/** + * \brief Creates a new macro substitution context. + * \return 0 = OK; <0 = ERROR + */ +epicsShareFunc long epicsShareAPI macCreateHandle( - MAC_HANDLE **handle, /* address of variable to receive pointer */ - /* to new macro substitution context */ + MAC_HANDLE **handle, /**< pointer to variable to receive pointer + to new macro substitution context */ - const char * pairs[] /* pointer to NULL-terminated array of */ - /* {name,value} pair strings; a NULL */ - /* value implies undefined; a NULL */ - /* argument implies no macros */ + const char * pairs[] /**< pointer to NULL-terminated array of + {name,value} pair strings. A NULL + value implies undefined; a NULL \c pairs + argument implies no macros. */ ); - +/** + * \brief Disable or enable warning messages. + * + * The macExpandString() routine prints warnings when it cant expand a macro. + * This routine can be used to silence those warnings. A non zero value will + * suppress the warning messages from subsequent library routines given the + * same \c handle. + */ epicsShareFunc void epicsShareAPI macSuppressWarning( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /**< opaque handle */ - int falseTrue /*0 means issue, 1 means suppress*/ + int falseTrue /**< 0 means issue, 1 means suppress*/ ); -epicsShareFunc long /* strlen(dest), <0 if any macros are */ - /* undefined */ -epicsShareAPI macExpandString( - MAC_HANDLE *handle, /* opaque handle */ - - const char *src, /* source string */ - - char *dest, /* destination string */ - - long capacity /* capacity of destination buffer (dest) */ -); - - -epicsShareFunc long /* strlen(value) */ -epicsShareAPI macPutValue( - MAC_HANDLE *handle, /* opaque handle */ - - const char *name, /* macro name */ - - const char *value /* macro value */ -); - -epicsShareFunc long /* strlen(value), <0 if undefined */ -epicsShareAPI macGetValue( - MAC_HANDLE *handle, /* opaque handle */ - - const char *name, /* macro name or reference */ - - char *value, /* string to receive macro value or name */ - /* argument if macro is undefined */ - - long capacity /* capacity of destination buffer (value) */ -); - -epicsShareFunc long /* 0 = OK; <0 = ERROR */ -epicsShareAPI macDeleteHandle( - MAC_HANDLE *handle /* opaque handle */ -); - -epicsShareFunc long /* 0 = OK; <0 = ERROR */ -epicsShareAPI macPushScope( - MAC_HANDLE *handle /* opaque handle */ -); - -epicsShareFunc long /* 0 = OK; <0 = ERROR */ -epicsShareAPI macPopScope( - MAC_HANDLE *handle /* opaque handle */ -); - -epicsShareFunc long /* 0 = OK; <0 = ERROR */ -epicsShareAPI macReportMacros( - MAC_HANDLE *handle /* opaque handle */ -); - -/* - * Function prototypes (utility library) +/** + * \brief Expand a string which may contain macro references. + * \return Returns the length of the expanded string, <0 if any macro are + * undefined + * + * This routine parses the \c src string looking for macro references and + * passes any it finds to macGetValue() for translation. + * + * \note The return value is similar to that of macGetValue(). Its absolute + * value is the number of characters copied to \c dest. If the return value + * is negative, at least one undefined macro was left unexpanded. */ -epicsShareFunc long /* #defns encountered; <0 = ERROR */ +epicsShareFunc long +epicsShareAPI macExpandString( + MAC_HANDLE *handle, /**< opaque handle */ + + const char *src, /**< source string */ + + char *dest, /**< destination string */ + + long capacity /**< capacity of destination buffer (dest) */ +); + +/** + * \brief Sets the value of a specific macro. + * \return Returns the length of the value string. + * \note If \c value is NULL, all instances of \c name are undefined at + * all scoping levels (the named macro doesn't have to exist in this case). + * Macros referenced in \c value need not be defined at this point. + */ +epicsShareFunc long +epicsShareAPI macPutValue( + MAC_HANDLE *handle, /**< opaque handle */ + + const char *name, /**< macro name */ + + const char *value /**< macro value */ +); + +/** + * \brief Returns the value of a macro + * \return Returns the length of the value string, <0 if undefined + * + * \c value will be zero-terminated if the length of the value is less than + * \c capacity. The return value is the number of characters copied to + * \c value (see below for behavior if the macro is undefined). If \c capacity + * is zero, no characters will be copied to \c value (which may be NULL) + * and the call can be used to check whether the macro is defined. + * + * \note Truncation of the value is not reported, applications should assume + * that truncation has occurred if the return value is equal to capacity. + * + * If the macro is undefined, the macro reference will be returned in + * the value string (if permitted by maxlen) and the function value will + * be _minus_ the number of characters copied. Note that treatment of + * \c capacity is intended to be consistent with the strncpy() routine. + * + * If the value contains macro references, these references will be + * expanded recursively. This expansion will detect a direct or indirect + * self reference. + * + * Macro references begin with a "$" immediately followed by either a + * "(" or a "{" character. The macro name comes next, and may optionally + * be succeeded by an "=" and a default value, which will be returned if + * the named macro is undefined at the moment of expansion. A reference + * is terminated by the matching ")" or "}" character. + */ +epicsShareFunc long +epicsShareAPI macGetValue( + MAC_HANDLE *handle, /**< opaque handle */ + + const char *name, /**< macro name or reference */ + + char *value, /**< string to receive macro value or name + argument if macro is undefined */ + + long capacity /**< capacity of destination buffer (value) */ +); +/** + * \brief Marks a handle invalid, and frees all storage associated with it + * \return 0 = OK; <0 = ERROR + * \note Note that this does not free any strings into which macro values have + * been returned. Macro values are always returned into strings which + * were pre-allocated by the caller. + */ +epicsShareFunc long +epicsShareAPI macDeleteHandle( + MAC_HANDLE *handle /**< opaque handle */ +); +/** + * \brief Marks the start of a new scoping level + * \return 0 = OK; <0 = ERROR + * + * Marks all macro definitions added after this call as belonging + * to another scope. These macros will be lost on a macPopScope() + * call and those at the current scope will be re-instated. + */ +epicsShareFunc long +epicsShareAPI macPushScope( + MAC_HANDLE *handle /**< opaque handle */ +); +/** + * \brief Retrieve the last pushed scope (like stack operations) + * \return 0 = OK; <0 = ERROR + * + * See macPushScope() + */ +epicsShareFunc long +epicsShareAPI macPopScope( + MAC_HANDLE *handle /**< opaque handle */ +); +/** + * \brief Reports details of current definitions + * \return 0 = OK; <0 = ERROR + * This sends details of current definitions to standard output, + * and is intended purely for debugging purposes. + */ +epicsShareFunc long +epicsShareAPI macReportMacros( + MAC_HANDLE *handle /**< opaque handle */ +); +/** @} */ + +/** \name Utility Library + * These convenience functions are intended for applications to use and + * provide a more convenient interface for some purposes. + * @{ + */ + +/** + * \brief Parse macro definitions into an array of {name, value} pairs. + * \return Number of macros found; <0 = ERROR + * + * This takes a set of macro definitions in "a=xxx,b=yyy" format and + * converts them into an array of pointers to character strings which + * are, in order, "first name", "first value", "second name", "second + * value" etc. The array is terminated with two NULL pointers and all + * storage is allocated contiguously so that it can be freed with a + * single call to free(). + * + * This routine is independent of any handle and provides a generally + * useful service which may be used elsewhere. Any macro references in + * values are not expanded at this point since the referenced macros may + * be defined or redefined before the macro actually has to be + * translated. + * + * Shell-style escapes and quotes are supported, as are things like + * "A=B,B=$(C$(A)),CA=CA,CB=CB" (sets B to "CB"). White space is + * significant within values but ignored elsewhere (i.e. surrounding "=" + * and "," characters). + * + * The function returns the number of definitions encountered, or -1 if + * the supplied string is invalid. + */ +epicsShareFunc long epicsShareAPI macParseDefns( - MAC_HANDLE *handle, /* opaque handle; can be NULL if default */ - /* special characters are to be used */ + MAC_HANDLE *handle, /**< opaque handle; may be NULL if debug + messages are not required. */ - const char *defns, /* macro definitions in "a=xxx,b=yyy" */ - /* format */ + const char *defns, /**< macro definitions in "a=xxx,b=yyy" + format */ - char **pairs[] /* address of variable to receive pointer */ - /* to NULL-terminated array of {name, */ - /* value} pair strings; all storage is */ - /* allocated contiguously */ + char **pairs[] /**< address of variable to receive pointer + to NULL-terminated array of {name, + value} pair strings; all storage is + allocated contiguously */ ); -epicsShareFunc long /* #macros defined; <0 = ERROR */ +/** + * \brief Install set of {name, value} pairs as definitions + * \return Number of macros defined; <0 = ERROR + * + * This takes an array of pairs as defined above and installs them as + * definitions by calling macPutValue(). The pairs array is terminated + * by a NULL pointer. + */ +epicsShareFunc long epicsShareAPI macInstallMacros( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /**< opaque handle */ - char *pairs[] /* pointer to NULL-terminated array of */ - /* {name,value} pair strings; a NULL */ - /* value implies undefined; a NULL */ - /* argument implies no macros */ + char *pairs[] /**< pointer to NULL-terminated array of + {name,value} pair strings; a NULL + value implies undefined; a NULL + argument implies no macros */ ); -epicsShareFunc char * /* expanded string; NULL if any undefined macros */ +/** + * \brief Expand environment variables in a string. + * \return Expanded string; NULL if any undefined macros were used. + * + * This routine expands a string which may contain macros that are + * environment variables. It parses the string looking for such + * references and passes them to macGetValue() for translation. It uses + * malloc() to allocate space for the expanded string and returns a + * pointer to this null-terminated string. It returns NULL if the source + * string contains any undefined references. + */ +epicsShareFunc char * epicsShareAPI macEnvExpand( - const char *str /* string to be expanded */ + const char *str /**< string to be expanded */ ); -epicsShareFunc char * /* expanded string; NULL if any undefined macros */ +/** + * \brief Expands macros and environment variables in a string. + * \return Expanded string; NULL if any undefined macros were used. + * + * This routine is similar to macEnvExpand() but allows an optional handle + * to be passed in that may contain additional macro definitions. + * These macros are appended to the set of macros from environment + * variables when expanding the string. + */ +epicsShareFunc char * epicsShareAPI macDefExpand( - const char *str, /* string to be expanded */ - MAC_HANDLE *macros /* opaque handle; can be NULL if default */ - /* special characters are to be used */ + const char *str, /**< string to be expanded */ + MAC_HANDLE *macros /**< opaque handle; may be NULL if only + environment variables are to be used */ ); +/** @} */ #ifdef __cplusplus } diff --git a/modules/libcom/src/misc/adjustment.h b/modules/libcom/src/misc/adjustment.h index 3f152039f..c256569f1 100644 --- a/modules/libcom/src/misc/adjustment.h +++ b/modules/libcom/src/misc/adjustment.h @@ -5,9 +5,15 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* src/libCom/adjustment.h */ + +/** + * \file adjustment.h + * \brief Declare function `adjustToWorstCaseAlignment` + * + * Declares a single function `adjustToWorstCaseAlignment`. + */ #ifndef INCadjustmenth #define INCadjustmenth @@ -17,6 +23,9 @@ extern "C" { #endif +/** returns a value larger or equal than `size`, that is an exact + multiple of the worst case alignment for the architecture on + which the routine is executed. */ epicsShareFunc size_t adjustToWorstCaseAlignment(size_t size); #ifdef __cplusplus @@ -25,4 +34,3 @@ epicsShareFunc size_t adjustToWorstCaseAlignment(size_t size); #endif /*INCadjustmenth*/ - diff --git a/modules/libcom/src/misc/alarm.h b/modules/libcom/src/misc/alarm.h index 58e2b7313..edaaf1e5f 100644 --- a/modules/libcom/src/misc/alarm.h +++ b/modules/libcom/src/misc/alarm.h @@ -4,13 +4,17 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* Alarm definitions, must match menuAlarmSevr.dbd and menuAlarmStat.dbd */ -/* - * Authors: Bob Dalesio and Marty Kraimer - * Date: 11-7-90 +/** + * \file alarm.h + * \brief Alarm severity and status/condition values + * \author Bob Dalesio and Marty Kraimer + * + * These alarm definitions must match the related + * menuAlarmSevr.dbd and menuAlarmStat.dbd files + * found in the IOC database module. */ #ifndef INC_alarm_H @@ -22,54 +26,68 @@ extern "C" { #endif - +/** + * \brief The NO_ALARM value can be used as both a severity and a status. + */ #define NO_ALARM 0 -/* ALARM SEVERITIES - must match menuAlarmSevr.dbd */ - +/** + * \brief Alarm severity values + * \note These must match the choices in menuAlarmSevr.dbd + */ typedef enum { - epicsSevNone = NO_ALARM, - epicsSevMinor, - epicsSevMajor, - epicsSevInvalid, - ALARM_NSEV + epicsSevNone = NO_ALARM, /**< No alarm */ + epicsSevMinor, /**< Minor alarm severity */ + epicsSevMajor, /**< Major alarm severity */ + epicsSevInvalid, /**< Invalid alarm severity */ + ALARM_NSEV /**< Number of alarm severities */ } epicsAlarmSeverity; +/** + * \name Original macros for alarm severity values + * @{ + */ #define firstEpicsAlarmSev epicsSevNone #define MINOR_ALARM epicsSevMinor #define MAJOR_ALARM epicsSevMajor #define INVALID_ALARM epicsSevInvalid #define lastEpicsAlarmSev epicsSevInvalid +/** @} */ - -/* ALARM STATUS - must match menuAlarmStat.dbd */ - +/** + * \brief Alarm status/condition values + * \note These must match the choices in menuAlarmStat.dbd + */ typedef enum { - epicsAlarmNone = NO_ALARM, - epicsAlarmRead, - epicsAlarmWrite, - epicsAlarmHiHi, - epicsAlarmHigh, - epicsAlarmLoLo, - epicsAlarmLow, - epicsAlarmState, - epicsAlarmCos, - epicsAlarmComm, - epicsAlarmTimeout, - epicsAlarmHwLimit, - epicsAlarmCalc, - epicsAlarmScan, - epicsAlarmLink, - epicsAlarmSoft, - epicsAlarmBadSub, - epicsAlarmUDF, - epicsAlarmDisable, - epicsAlarmSimm, - epicsAlarmReadAccess, - epicsAlarmWriteAccess, - ALARM_NSTATUS + epicsAlarmNone = NO_ALARM, /**< No alarm */ + epicsAlarmRead, /**< Read alarm (read error) */ + epicsAlarmWrite, /**< Write alarm (write error) */ + epicsAlarmHiHi, /**< High high limit alarm */ + epicsAlarmHigh, /**< High limit alarm */ + epicsAlarmLoLo, /**< Low low limit alarm */ + epicsAlarmLow, /**< Low limit alarm */ + epicsAlarmState, /**< State alarm (e.g. off/on) */ + epicsAlarmCos, /**< Change of state alarm */ + epicsAlarmComm, /**< Communication alarm */ + epicsAlarmTimeout, /**< Timeout alarm */ + epicsAlarmHwLimit, /**< Hardware limit alarm */ + epicsAlarmCalc, /**< Calculation expression error */ + epicsAlarmScan, /**< Scan alarm, e.g. record not processed (10 times) or not in desired scan list */ + epicsAlarmLink, /**< Link alarm */ + epicsAlarmSoft, /**< Soft alarm, e.g. in sub record if subroutine gives error */ + epicsAlarmBadSub, /**< Bad subroutine alarm, e.g. in sub record subroutine not defined */ + epicsAlarmUDF, /**< Undefined value alarm, e.g. record never processed */ + epicsAlarmDisable, /**< Record disabled using DISV/DISA fields */ + epicsAlarmSimm, /**< Record is in simulation mode */ + epicsAlarmReadAccess, /**< Read access permission problem */ + epicsAlarmWriteAccess, /**< Write access permission problem */ + ALARM_NSTATUS /**< Number of alarm conditions */ } epicsAlarmCondition; +/** + * \name Original macros for alarm status/condition values + * @{ + */ #define firstEpicsAlarmCond epicsAlarmNone #define READ_ALARM epicsAlarmRead #define WRITE_ALARM epicsAlarmWrite @@ -93,11 +111,15 @@ typedef enum { #define READ_ACCESS_ALARM epicsAlarmReadAccess #define WRITE_ACCESS_ALARM epicsAlarmWriteAccess #define lastEpicsAlarmCond epicsAlarmWriteAccess +/** @} */ - -/* Name string arrays */ - +/** + * \brief How to convert an alarm severity into a string + */ epicsShareExtern const char *epicsAlarmSeverityStrings [ALARM_NSEV]; +/** + * \brief How to convert an alarm condition/status into a string + */ epicsShareExtern const char *epicsAlarmConditionStrings [ALARM_NSTATUS]; diff --git a/modules/libcom/src/misc/alarmString.h b/modules/libcom/src/misc/alarmString.h index ab320f058..d2741b567 100644 --- a/modules/libcom/src/misc/alarmString.h +++ b/modules/libcom/src/misc/alarmString.h @@ -4,13 +4,16 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * This file is deprecated, use alarm.h instead. +/** + * \file alarmString.h + * \brief Deprecated, use alarm.h instead * - * Old string names for alarm status and severity values + * How to convert alarm status and severity values into a string for printing. + * + * \note This file is deprecated, use alarm.h instead. */ #ifndef INC_alarmString_H @@ -22,9 +25,13 @@ extern "C" { #endif -/* Old versions of alarmString.h defined these names: */ - +/** + * \brief An alias for epicsAlarmSeverityStrings + */ #define alarmSeverityString epicsAlarmSeverityStrings +/** + * \brief An alias for epicsAlarmConditionStrings + */ #define alarmStatusString epicsAlarmConditionStrings diff --git a/modules/libcom/src/misc/cantProceed.h b/modules/libcom/src/misc/cantProceed.h index 437f96802..5fb3ef0f8 100644 --- a/modules/libcom/src/misc/cantProceed.h +++ b/modules/libcom/src/misc/cantProceed.h @@ -4,8 +4,23 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ + +/** + * \file cantProceed.h + * \brief Routines for code that can't continue or return after an error. + * + * This is the EPICS equivalent of a Kernel Panic, except that the effect + * is to halt only the thread that detects the error. + */ + +/* callocMustSucceed() and mallocMustSucceed() can be + * used in place of calloc() and malloc(). If size or count are zero, or the + * memory allocation fails, they output a message and call cantProceed(). + */ + + #ifndef INCcantProceedh #define INCcantProceedh @@ -18,9 +33,42 @@ extern "C" { #endif -epicsShareFunc void cantProceed(const char *errorMessage, ...) EPICS_PRINTF_STYLE(1,2); -epicsShareFunc void * callocMustSucceed(size_t count, size_t size, const char *errorMessage); +/** \brief Suspend this thread, the caller cannot continue or return. + * + * The effect of calling this is to print the error message followed by + * the name of the thread that is being suspended. A stack trace will + * also be shown if supported by the OS, and the thread is suspended + * inside an infinite loop. + * \param errorMessage A printf-style error message describing the error. + * \param ... Any parameters required for the error message. + */ +epicsShareFunc void cantProceed(const char *errorMessage, ...) + EPICS_PRINTF_STYLE(1,2); + +/** \name Memory Allocation Functions + * These versions of calloc() and malloc() never fail, they suspend the + * thread if the OS is unable to allocate the requested memory at the current + * time. If the thread is resumed, they will re-try the memory allocation, + * and will only return after it succeeds. These routines should only be used + * while an IOC is starting up; code that runs after iocInit() should fail + * gracefully when memory runs out. + */ +/** @{ */ +/** \brief A calloc() that never returns NULL. + * \param count Number of objects. + * \param size Size of each object. + * \param errorMessage What this memory is needed for. + * \return Pointer to zeroed allocated memory. + */ +epicsShareFunc void * callocMustSucceed(size_t count, size_t size, + const char *errorMessage); +/** \brief A malloc() that never returns NULL. + * \param size Size of block to allocate. + * \param errorMessage What this memory is needed for. + * \return Pointer to allocated memory. + */ epicsShareFunc void * mallocMustSucceed(size_t size, const char *errorMessage); +/** @} */ #ifdef __cplusplus } diff --git a/modules/libcom/src/misc/dbDefs.h b/modules/libcom/src/misc/dbDefs.h index e1de3f200..5de0cd922 100644 --- a/modules/libcom/src/misc/dbDefs.h +++ b/modules/libcom/src/misc/dbDefs.h @@ -4,11 +4,16 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Marty Kraimer - * Date: 6-1-90 + +/** + * \file dbDefs.h + * \author Marty Kraimer + * + * \brief Miscellaneous macro definitions. + * + * This file defines several miscellaneous macros. */ #ifndef INC_dbDefs_H @@ -26,22 +31,31 @@ #endif #define FALSE 0 -/* deprecated, use static */ +/** \brief Deprecated synonym for \c static */ #ifndef LOCAL # define LOCAL static #endif -/* number of elements in an array */ +/** \brief Number of elements in array */ #ifndef NELEMENTS # define NELEMENTS(array) (sizeof (array) / sizeof ((array) [0])) #endif -/* byte offset of member in structure - deprecated, use offsetof */ +/** \brief Deprecated synonym for \c offsetof */ #ifndef OFFSET # define OFFSET(structure, member) offsetof(structure, member) #endif -/* Subtract member byte offset, returning pointer to parent object */ +/** \brief Find parent object from a member pointer + * + * Subtracts the byte offset of the member in the structure from the + * pointer to the member itself, giving a pointer to parent strucure. + * \param ptr Pointer to a member data field of a structure + * \param structure Type name of the parent structure + * \param member Field name of the data member + * \return Pointer to the parent structure + * \note Both GCC and Clang will type-check this macro. + */ #ifndef CONTAINER # ifdef __GNUC__ # define CONTAINER(ptr, structure, member) ({ \ @@ -54,15 +68,18 @@ # endif #endif -/*Process Variable Name Size */ -/* PVNAME_STRINGSZ includes the nil terminator */ +/** \brief Size of a record name including the nil terminator */ #define PVNAME_STRINGSZ 61 +/** \brief Size of a record name without the nil terminator */ #define PVNAME_SZ (PVNAME_STRINGSZ - 1) -/* Buffer size for the string representation of a DBF_*LINK field */ +/** + * \def PVLINK_STRINGSZ + * \brief Buffer size for the string representation of a DBF_*LINK field + */ #define PVLINK_STRINGSZ 1024 -/* dbAccess enums/menus can have up to this many choices */ +/** \brief dbAccess enums/menus can have up to this many choices */ #define DB_MAX_CHOICES 30 #endif /* INC_dbDefs_H */ diff --git a/modules/libcom/src/misc/epicsExit.h b/modules/libcom/src/misc/epicsExit.h index 3e961cbc1..23c40f8d1 100644 --- a/modules/libcom/src/misc/epicsExit.h +++ b/modules/libcom/src/misc/epicsExit.h @@ -7,6 +7,18 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ /*epicsExit.h*/ +/** + * \file epicsExit.h + * + * \brief Extended replacement for the Posix exit and atexit routines. + * + * This is an extended replacement for the Posix exit and atexit routines, which + * also provides a pointer argument to pass to the exit handlers. This facility + * was created because of problems on vxWorks and windows with the implementation + * of atexit, i.e. neither of these systems implement exit and atexit according + * to the POSIX standard. + */ + #ifndef epicsExith #define epicsExith #include @@ -15,15 +27,63 @@ extern "C" { #endif +/** + * \brief Pointer to a callback function that is to be called + * by the epicsExit subsystem. + */ typedef void (*epicsExitFunc)(void *arg); +/** + * \brief Calls epicsExitCallAtExits(), then the OS exit() routine. + * \param status Passed to exit() + */ epicsShareFunc void epicsExit(int status); +/** + * \brief Arrange to call epicsExit() later from a low priority thread. + * + * This delays the actual call to exit() so it doesn't run in this thread. + * \param status Passed to exit() + */ epicsShareFunc void epicsExitLater(int status); +/** + * \brief Internal routine that runs the registered exit routines. + * + * Calls each of the functions registered by prior calls to epicsAtExit + * in reverse order of their registration. + * \note Most applications will not call this routine directly. + */ epicsShareFunc void epicsExitCallAtExits(void); +/** + * \brief Register a function and an associated context parameter + * \param func Function to be called when epicsExitCallAtExits is invoked. + * \param arg Context parameter for the function. + * \param name Function name + */ epicsShareFunc int epicsAtExit3(epicsExitFunc func, void *arg, const char* name); -#define epicsAtExit(F,A) epicsAtExit3(F,A,#F) +/** + * \brief Convenience macro to register a function and context value to be + * run when the process exits. + * \param F Function to be called at process shutdown. + * \param A Context parameter for the function. + */ +#define epicsAtExit(F,A) epicsAtExit3(F,A,#F) +/** + * \brief Internal routine that runs the registered thread exit routines. + * + * Calls each of the functions that were registered in the current thread by + * calling epicsAtThreadExit(), in reverse order of their registration. + * \note This routine is called automatically when an epicsThread's main + * entry routine returns. It will not be run if the thread gets stopped by + * some other method. + */ epicsShareFunc void epicsExitCallAtThreadExits(void); +/** + * \brief Register a function and an context value to be run by this thread + * when it returns from its entry routine. + * \param func Function be called at thread completion. + * \param arg Context parameter for the function. + */ epicsShareFunc int epicsAtThreadExit(epicsExitFunc func, void *arg); diff --git a/modules/libcom/src/misc/epicsExport.h b/modules/libcom/src/misc/epicsExport.h index dea8dd67a..13b27b19e 100644 --- a/modules/libcom/src/misc/epicsExport.h +++ b/modules/libcom/src/misc/epicsExport.h @@ -1,5 +1,3 @@ -/*epicsExport.h */ - /*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. @@ -7,37 +5,122 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -#ifndef INCepicsExporth -#define INCepicsExporth + +#ifndef INC_epicsExport_H +#define INC_epicsExport_H + +/** \file epicsExport.h + * \brief Exporting IOC objects. + * + * This header is unique, as it defines epicsExportSharedSymbols and thus + * triggers a transition between importing declarations from other libraries, + * to exporting symbols from our own library. The comments in shareLib.h + * provide more information. + * + * This header should be included with a trailing comment to make it stand + * out from other includes, something like this: + \code + #include // defines epicsExportSharedSymbols + \endcode + */ + +#define epicsExportSharedSymbols +#include #ifdef __cplusplus extern "C" { #endif -#define epicsExportSharedSymbols -#include - typedef void (*REGISTRAR)(void); -#define EPICS_EXPORT_POBJ(typ,obj) pvar_ ## typ ## _ ## obj -#define EPICS_EXPORT_PFUNC(obj) pvar_func_ ## obj +/** \brief Generate a name for an export object. + * \param typ Object's data type. + * \param obj Object's name. + * \return C identifier for the export object. + */ +#define EPICS_EXPORT_POBJ(typ, obj) pvar_ ## typ ## _ ## obj -#define epicsExportAddress(typ,obj) \ -epicsShareExtern typ *EPICS_EXPORT_POBJ(typ,obj); \ -epicsShareDef typ *EPICS_EXPORT_POBJ(typ,obj) = (typ *)(char *)&obj +/** \brief Generate a name for an export function object. + * \param fun Function's name. + * \return C identifier for the export object. + */ +#define EPICS_EXPORT_PFUNC(fun) EPICS_EXPORT_POBJ(func, fun) -#define epicsExportRegistrar(func) \ -epicsShareFunc REGISTRAR EPICS_EXPORT_PFUNC(func) = (REGISTRAR)(void*)&func +/** \brief Declare an object for exporting. + * + * The epicsExportAddress() macro must be used to declare any IOC object + * that is also named in a DBD file. For example a record support source + * file must contain a statement like: + \code + epicsExportAddress(rset, myRSET); + \endcode + * + * A device support source file must contain a statement like: + \code + epicsExportAddress(dset, devMyName); + \endcode + * Note that the \p typ parameter for a device support entry table must be + * spelled \c dset even if the \p obj was actually declared as some other + * type, say using \c typed_dset . + * + * A driver support source file must contain a statement like: + \code + epicsExportAddress(drvet, drvName); + \endcode + * + * A variable named in a DBD \c variable statement must be declared with: + \code + int myDebug = 0; + epicsExportAddress(int, myDebug); + \endcode + * Only \c int and \c double are currently supported for DBD variables. + * + * \param typ Object's data type. + * \param obj Object's name. + */ +#define epicsExportAddress(typ, obj) \ + epicsShareExtern typ *EPICS_EXPORT_POBJ(typ,obj); \ + epicsShareDef typ *EPICS_EXPORT_POBJ(typ, obj) = (typ *) (char *) &obj -#define epicsRegisterFunction(func) \ -static void register_func_ ## func(void) { \ - registryFunctionAdd(#func,(REGISTRYFUNCTION)func);} \ -epicsExportRegistrar(register_func_ ## func) +/** \brief Declare a registrar function for exporting. + * + * The epicsExportRegistrar() macro must be used to declare a registrar + * function that is named in a DBD \c registrar statement. For example: + \code + static void myRegistrar(void) { + ... + } + epicsExportRegistrar(myRegistrar); + \endcode + * + * \param fun Registrar function's name. + */ +#define epicsExportRegistrar(fun) \ + epicsShareFunc REGISTRAR EPICS_EXPORT_PFUNC(fun) = (REGISTRAR) &fun + +/** \brief Declare and register a function for exporting. + * + * The epicsRegisterFunction() macro must be used to declare and register + * a function that is named in a DBD \c function statement and called by + * one or more subroutine or aSub records. For example: + \code + epicsRegisterFunction(mySubInit); + epicsRegisterFunction(mySubProcess); + \endcode +* + * \param fun Function's name + */ +#define epicsRegisterFunction(fun) \ + static void register_func_ ## fun(void) \ + { \ + registryFunctionAdd(#fun, (REGISTRYFUNCTION) fun); \ + } \ + epicsExportRegistrar(register_func_ ## fun) #ifdef __cplusplus } #endif -#endif /* epicsExporth */ +#endif /* INC_epicsExport_H */ diff --git a/modules/libcom/src/misc/epicsUnitTest.h b/modules/libcom/src/misc/epicsUnitTest.h index b0199333e..31aac6dc1 100644 --- a/modules/libcom/src/misc/epicsUnitTest.h +++ b/modules/libcom/src/misc/epicsUnitTest.h @@ -5,8 +5,142 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Andrew Johnson +/** + * \file epicsUnitTest.h + * \brief Unit test routines + * \author Andrew Johnson + * + * The unit test routines make it easy for a test program to generate output + * that is compatible with the Test Anything Protocol and can thus be used with + * Perl's automated Test::Harness as well as generating human-readable output. + * The routines detect whether they are being run automatically and print a + * summary of the results at the end if not. + + * A test program starts with a call to testPlan(), announcing how many tests + * are to be conducted. If this number is not known a value of zero can be + * used during development, but it is recommended that the correct value be + * substituted after the test program has been completed. + * + * Individual test results are reported using any of testOk(), testOk1(), + * testOkV(), testPass() or testFail(). The testOk() call takes and also + * returns a logical pass/fail result (zero means failure, any other value + * is success) and a printf-like format string and arguments which describe + * the test. The convenience macro testOk1() is provided which stringifies its + * single condition argument, reducing the effort needed when writing test + * programs. The individual testPass() and testFail() routines can be used when + * the test program takes a different path on success than on failure, but one + * or other must always be called for any particular test. The testOkV() routine + * is a varargs form of testOk() included for internal purposes which may prove + * useful in some cases. + * + * If some program condition or failure makes it impossible to run some tests, + * the testSkip() routine can be used to indicate how many tests are being omitted + * from the run, thus keeping the test counts correct; the constant string why is + * displayed as an explanation to the user (this string is not printf-like). + * + * If some tests are expected to fail because functionality in the module under + * test has not yet been fully implemented, these tests may still be executed, + * wrapped between calls to testTodoBegin() and testTodoEnd(). testTodoBegin() + * takes a constant string indicating why these tests are not expected to + * succeed. This modifies the counting of the results so the wrapped tests will not + * be recorded as failures. + * + * Additional information can be supplied using the testDiag() routine, which + * displays the relevent information as a comment in the result output. None of + * the printable strings passed to any testXxx() routine should contain a newline + * '\n' character, newlines will be added by the test routines as part of the + * Test Anything Protocol. For multiple lines of diagnostic output, call + * testDiag() as many times as necessary. + * + * If at any time the test program is unable to continue for some catastrophic + * reason, calling testAbort() with an appropriate message will ensure that the + * test harness understands this. testAbort() does not return, but calls the ANSI + * C routine abort() to cause the program to stop immediately. + * + * After all of the tests have been completed, the return value from + * testDone() can be used as the return status code from the program's main() + * routine. + * + * On vxWorks and RTEMS, an alternative test harness can be used to run a + * series of tests in order and summarize the results from them all at the end + * just like the Perl harness does. The routine testHarness() is called once at + * the beginning of the test harness program. Each test program is run by + * passing its main routine name to the runTest() macro which expands into a call + * to the runTestFunc() routine. The last test program or the harness program + * itself must finish by calling testHarnessDone() which triggers the summary + * mechanism to generate its result outputs (from an epicsAtExit() callback + * routine). + * + * ### IOC Testing + * + * Some tests require the context of an IOC to be run. This conflicts with the + * idea of running multiple tests within a test harness, as iocInit() is only + * allowed to be called once, and some parts of the full IOC (e.g. the rsrv CA + * server) can not be shut down cleanly. The function iocBuildIsolated() allows + * to start an IOC without its Channel Access parts, so that it can be shutdown + * quite cleanly using iocShutdown(). This feature is only intended to be used + * from test programs, do not use it on productional IOCs. After building the + * IOC using iocBuildIsolated() or iocBuild(), it has to be started by calling + * iocRun(). The suggested call sequence in a test program that needs to run the + * IOC without Channel Access is: +\code +#include "iocInit.h" + +MAIN(iocTest) +{ + iocBuildIsolated() || iocRun(); + + ... test code ... + + iocShutdown(); + dbFreeBase(pdbbase); + registryFree(); + pdbbase = NULL; + return testDone(); +} +\endcode + + * The part from iocBuildIsolated() to iocShutdown() can be repeated to + * execute multiple tests within one executable or harness. + * + * To make it easier to create a single test program that can be built for + * both the embedded and workstation operating system harnesses, the header file + * testMain.h provides a convenience macro MAIN() that adjusts the name of the + * test program according to the platform it is running on: main() on + * workstations and a regular function name on embedded systems. + * + * ### Example + * + * The following is a simple example of a test program using the epicsUnitTest + * routines: +\code +#include +#include "epicsUnitTest.h" +#include "testMain.h" + +MAIN(mathTest) +{ + testPlan(3); + testOk(sin(0.0) == 0.0, "Sine starts"); + testOk(cos(0.0) == 1.0, "Cosine continues"); + if (!testOk1(M_PI == 4.0*atan(1.0))) + testDiag("4 * atan(1) = %g", 4.0 * atan(1.0)); + return testDone(); +} +\endcode + + * The output from running the above program looks like this: +\code +1..3 +ok 1 - Sine starts +ok 2 - Cosine continues +ok 3 - M_PI == 4.0*atan(1.0) + + Results + ======= + Tests: 3 + Passed: 3 = 100% +\endcode */ #ifndef INC_epicsUnitTest_H @@ -21,35 +155,111 @@ extern "C" { #endif +/** \brief Declare the test plan, required. + * \param tests Number of tests to be run. May be zero if not known but the + * test harness then can't tell if the program dies prematurely. + */ epicsShareFunc void testPlan(int tests); -epicsShareFunc int testOkV(int pass, const char *fmt, va_list pvar); -epicsShareFunc int testOk(int pass, const char *fmt, ...) - EPICS_PRINTF_STYLE(2, 3); -epicsShareFunc void testPass(const char *fmt, ...) - EPICS_PRINTF_STYLE(1, 2); -epicsShareFunc void testFail(const char *fmt, ...) - EPICS_PRINTF_STYLE(1, 2); -epicsShareFunc void testSkip(int skip, const char *why); -epicsShareFunc void testTodoBegin(const char *why); -epicsShareFunc void testTodoEnd(void); -epicsShareFunc int testDiag(const char *fmt, ...) - EPICS_PRINTF_STYLE(1, 2); -epicsShareFunc void testAbort(const char *fmt, ...) - EPICS_PRINTF_STYLE(1, 2); -epicsShareFunc int testDone(void); +/** \name Announcing Test Results + * Routines that declare individual test results. + */ +/** @{ */ +/** \brief Test result with printf-style description. + * \param pass True/False value indicating result. + * \param fmt A printf-style format string describing the test. + * \param ... Any parameters required for the format string. + * \return The value of \p pass. + */ +epicsShareFunc int testOk(int pass, const char *fmt, ...) + EPICS_PRINTF_STYLE(2, 3); +/** \brief Test result using condition as description + * \param cond Condition to be evaluated and displayed. + * \return The value of \p cond. + */ #define testOk1(cond) testOk(cond, "%s", #cond) +/** \brief Test result with var-args description. + * \param pass True/False value indicating result. + * \param fmt A printf-style format string describing the test. + * \param pvar A var-args pointer to any parameters for the format string. + * \return The value of \p pass. + */ +epicsShareFunc int testOkV(int pass, const char *fmt, va_list pvar); +/** \brief Passing test result with printf-style description. + * \param fmt A printf-style format string describing the test. + * \param ... Any parameters required for the format string. + * \return The value of \p pass. + */ +epicsShareFunc void testPass(const char *fmt, ...) + EPICS_PRINTF_STYLE(1, 2); +/** \brief Failing test result with printf-style description. + * \param fmt A printf-style format string describing the test. + * \param ... Any parameters required for the format string. + */ +epicsShareFunc void testFail(const char *fmt, ...) + EPICS_PRINTF_STYLE(1, 2); +/** @} */ + +/** \name Missing or Failing Tests + * \brief Routines for handling special situations. + */ +/** @{ */ + +/** \brief Place-holders for tests that can't be run. + * \param skip How many tests are being skipped. + * \param why Reason for skipping these tests. + */ +epicsShareFunc void testSkip(int skip, const char *why); +/** \brief Mark the start of a group of tests that are expected to fail + * \param why Reason for expected failures. + */ +epicsShareFunc void testTodoBegin(const char *why); +/** \brief Mark the end of a failing test group. + */ +epicsShareFunc void testTodoEnd(void); +/** \brief Stop testing, program cannot continue. + * \param fmt A printf-style format string giving the reason for stopping. + * \param ... Any parameters required for the format string. + */ +epicsShareFunc void testAbort(const char *fmt, ...) + EPICS_PRINTF_STYLE(1, 2); +/** @} */ + +/** \brief Output additional diagnostics + * \param fmt A printf-style format string containing diagnostic information. + * \param ... Any parameters required for the format string. + */ +epicsShareFunc int testDiag(const char *fmt, ...) + EPICS_PRINTF_STYLE(1, 2); +/** \brief Mark the end of testing. + */ +epicsShareFunc int testDone(void); epicsShareFunc int testImpreciseTiming(void); +/** \name Test Harness for Embedded OSs + * These routines are used to create a test-harness that can run + * multiple test programs, collect their names and results, then + * display a summary at the end of testing. + */ +/** @{ */ + typedef int (*TESTFUNC)(void); +/** \brief Initialize test harness + */ epicsShareFunc void testHarness(void); epicsShareFunc void testHarnessExit(void *dummy); epicsShareFunc void runTestFunc(const char *name, TESTFUNC func); +/** \brief Run a test program + * \param func Name of the test program. + */ #define runTest(func) runTestFunc(#func, func) +/** \brief Declare all test programs finished + */ #define testHarnessDone() testHarnessExit(0) +/** @} */ #ifdef __cplusplus } diff --git a/modules/libcom/src/misc/shareLib.h b/modules/libcom/src/misc/shareLib.h index 0d376d64a..108069781 100644 --- a/modules/libcom/src/misc/shareLib.h +++ b/modules/libcom/src/misc/shareLib.h @@ -4,38 +4,48 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Compiler specific key words to set up external symbols and entry points +/** + * \file shareLib.h + * \brief Mark external symbols and entry points for shared libraries. + * + * This is the header file for the "decorated names" that appear in + * header files, e.g. + * + * #define epicsExportSharedSymbols + * epicsShareFunc int epicsShareAPI a_func(int arg); + * + * These are needed to properly create DLLs on MS Windows. + * + * ### USAGE * - * USAGE: * There are two distinct classes of keywords in this file: * - * 1) epicsShareAPI - specifies a multi-language calling mechanism. On windows + * -# epicsShareAPI - specifies a multi-language calling mechanism. On windows * this is the pascal calling convention which is used by visual basic and other * high level tools. This is only necessary if a C/C++ function needs to be called * from other languages or from high level tools. The epicsShareAPI keyword - * must be present between the function's returned data type and the function's - * name. All compilers targeting windows accept the __stdcall keyword in this + * must be present between the function's returned data type and the function's + * name. All compilers targeting windows accept the __stdcall keyword in this * location. Functions with variable argument lists should not use the epicsShareAPI * keyword because __stdcall (pascal) calling convention cannot support variable * length ed argument lists. * - * int epicsShareAPI myExtFunc ( int arg ); - * int epicsShareAPI myExtFunc ( int arg ) {} + * int epicsShareAPI myExtFunc ( int arg ); + * int epicsShareAPI myExtFunc ( int arg ) {} * - * ** NOTE ** The epicsShareAPI attribute is deprecated and has been removed + * \note The epicsShareAPI attribute is deprecated and has been removed * from all IOC-specific APIs. Most libCom APIs still use it, but * it may get removed from these at some point in the future. * - * 2) epicsShare{Func,Class,Extern,Def} - specifies shareable library (DLL) - * export/import related information in the source code. On windows these keywords - * allow faster dispatching of calls to DLLs because more is known at compile time. + * -# epicsShare{Func,Class,Extern,Def} - specifies shareable library (DLL) + * export/import related information in the source code. On windows these keywords + * allow faster dispatching of calls to DLLs because more is known at compile time. * It is also not necessary to maintain a linker input files specifying the DLL - * entry points. This maintenance can be more laborious with C++ decorated symbol - * names. These keywords are only necessary if the address of a function or data - * internal to a shareable library (DLL) needs to be visible outside of this shareable + * entry points. This maintenance can be more laborious with C++ decorated symbol + * names. These keywords are only necessary if the address of a function or data + * internal to a shareable library (DLL) needs to be visible outside of this shareable * library (DLL). All compilers targeting windows accept the __declspec(dllexport) * and __declspec(dllimport) keywords. For GCC version 4 and above the first three * keywords specify a visibility attribute of "default", which marks the symbol as @@ -43,23 +53,23 @@ * significantly reduce the number of symbols exported to a shared library. See the * URL below for more information. * - * In header files declare references to externally visible variables, classes and + * In header files declare references to externally visible variables, classes and * functions like this: * - * #include "shareLib.h" - * epicsShareFunc int myExtFunc ( int arg ); - * epicsShareExtern int myExtVar; - * class epicsShareClass myClass { int func ( void ); }; + * #include "shareLib.h" + * epicsShareFunc int myExtFunc ( int arg ); + * epicsShareExtern int myExtVar; + * class epicsShareClass myClass { int func ( void ); }; * * In the implementation file, however, you write: * - * #include - * #define epicsExportSharedSymbols - * #include + * #include + * #define epicsExportSharedSymbols + * #include * - * epicsShareDef int myExtVar = 4; - * int myExtFunc ( int arg ) {} - * int myClass::func ( void ) {} + * epicsShareDef int myExtVar = 4; + * int myExtFunc ( int arg ) {} + * int myClass::func ( void ) {} * * By default shareLib.h sets the DLL import / export keywords to import from * a DLL so that, for DLL consumers (users), nothing special must be done. However, @@ -67,34 +77,42 @@ * which functions are exported from the DLL and which of them are imported * from other DLLs. * - * You must first #include what you import and then define epicsExportSharedSymbols - * only right before you #include the prototypes for what you implement! You must - * include shareLib.h again each time that the state of the import/ export keywords - * changes, but this usually occurs as a side effect of including the shareable - * libraries header file(s). + * You must first \c \#include what you import and then \c \#define + * \c epicsExportSharedSymbols only right before you \c \#include the + * prototypes for what you implement! You must include shareLib.h again each + * time that the state of the import/export keywords changes, but this + * usually occurs as a side effect of including the shareable libraries header + * file(s). * - * Frequently a header file for a shareable library exported interface will - * have some preprocessor switches like this if this header file must also + * ### Deprecated Usage + * + * The construct described below is used in some EPICS header files bit is + * no longer recommended as it makes it difficult to diagnose the incorrect + * inclusion of headers that are the wrong side of an \c epicsExportSharedSymbols + * marker. + * + * Sometimes a header file for a shareable library exported interface will + * have some preprocessor switches like this if this header file must also * include header files describing interfaces to other shareable libraries. * - * #ifdef epicsExportSharedSymbols - * # define interfacePDQ_epicsExportSharedSymbols - * # undef epicsExportSharedSymbols - * #endif + * #ifdef epicsExportSharedSymbols + * # define interfacePDQ_epicsExportSharedSymbols + * # undef epicsExportSharedSymbols + * #endif * - * #include "epicsTypes.h" - * #include "epicsTime.h" + * #include "epicsTypes.h" + * #include "epicsTime.h" * - * #ifdef interfacePDQ_epicsExportSharedSymbols - * # define epicsExportSharedSymbols - * # include "shareLib.h" - * #endif + * #ifdef interfacePDQ_epicsExportSharedSymbols + * # define epicsExportSharedSymbols + * # include "shareLib.h" + * #endif * - * epicsShareFunc int myExtFunc ( int arg ); - * epicsShareExtern int myExtVar; - * class epicsShareClass myClass {}; + * epicsShareFunc int myExtFunc ( int arg ); + * epicsShareExtern int myExtVar; + * class epicsShareClass myClass {}; * - * Fortunately, the above is only the concern of library authors and will have no + * Fortunately, the above is only the concern of library authors and will have no * impact on persons using functions and or external data from a library. */ @@ -132,7 +150,7 @@ # define epicsShareFunc # endif # endif -# define epicsShareDef +# define epicsShareDef # define epicsShareAPI __stdcall /* function removes arguments */ # define READONLY const @@ -162,18 +180,18 @@ */ #elif defined(VAXC) - /* + /* * VAXC creates FORTRAN common blocks when * we use "extern int fred"/"int fred=4". Therefore, * the initialization is not loaded unless we * call a function in that object module. * * DEC CXX does not have this problem. - * We suspect (but do not know) that DEC C + * We suspect (but do not know) that DEC C * also does not have this problem. */ -# define epicsShareExtern globalref -# define epicsShareDef globaldef +# define epicsShareExtern globalref +# define epicsShareDef globaldef # define READONLY const # define epicsShareClass # define epicsShareFunc diff --git a/modules/libcom/src/misc/unixFileName.h b/modules/libcom/src/misc/unixFileName.h index 9d7af252c..0b6edb92e 100644 --- a/modules/libcom/src/misc/unixFileName.h +++ b/modules/libcom/src/misc/unixFileName.h @@ -24,13 +24,13 @@ extern "C" { #define OSI_PATH_SEPARATOR "/" /** Return the absolute path of the current executable. - @returns NULL or the path. Caller must free() + \return NULL or the path. Caller must free() */ epicsShareFunc char *epicsGetExecName(void); /** Return the absolute path of the directory containing the current executable. - @returns NULL or the path. Caller must free() + \return NULL or the path. Caller must free() */ epicsShareFunc char *epicsGetExecDir(void); diff --git a/modules/libcom/src/osi/compilerDependencies.h b/modules/libcom/src/osi/compilerDependencies.h index 0b333d74e..82c89322b 100644 --- a/modules/libcom/src/osi/compilerDependencies.h +++ b/modules/libcom/src/osi/compilerDependencies.h @@ -7,10 +7,11 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: - * Jeffrey O. Hill - * johill@lanl.gov +/** + * \file compilerDependencies.h + * \author Jeffrey O. Hill johill@lanl.gov + * \brief Compiler specific declarations + * */ #ifndef compilerDependencies_h diff --git a/modules/libcom/src/osi/devLib.h b/modules/libcom/src/osi/devLib.h index 729f9b932..0f263bd90 100644 --- a/modules/libcom/src/osi/devLib.h +++ b/modules/libcom/src/osi/devLib.h @@ -8,93 +8,125 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* devLib.h */ -/* - * Original Author: Marty Kraimer - * Author: Jeff Hill - * Date: 03-10-93 +/** + * \file devLib.h + * \brief API for accessing hardware devices, originally over VMEbus + * \author Marty Kraimer and Jeff Hill + * + * Support for allocation of common device resources */ #ifndef EPICSDEVLIB_H #define EPICSDEVLIB_H -/* - * Support macros - */ - -/* - * Normalize a digital value and convert it to type TYPE - * - * Ex: - * float f; - * int d; - * f = devNormalizeDigital(d,12) - * +/** + * \name Macros for normalizing values + * \warning Deprecated, we don't know of any code currently using these. + * @{ */ +/** \brief Create a bit mask for a given number of bits */ #define devCreateMask(NBITS) ((1<<(NBITS))-1) +/** \brief Normalize a raw integer value and convert it to type double */ #define devDigToNml(DIGITAL,NBITS) \ (((double)(DIGITAL))/devCreateMask(NBITS)) +/** \brief Convert a normalized value to a raw integer */ #define devNmlToDig(NORMAL,NBITS) \ (((long)(NORMAL)) * devCreateMask(NBITS)) + /** @} */ -/* - * - * Alignment mask - * (for use when testing to see if the proper number of least - * significant bits are zero) - * +/** + * \name Macros for pointer alignment + * \warning Deprecated, we don't know of any code currently using these. + * @{ */ +/** \brief Create an alignment mask for CTYPE */ #define devCreateAlignmentMask(CTYPE)\ (sizeof(CTYPE)>sizeof(double)?sizeof(double)-1:sizeof(CTYPE)-1) -/* - * pointer aligned test - * (returns true if the pointer is on the worst case alignemnt - * boundary for its type) +/** \brief Check Pointer alignment, returns true if the pointer \c PTR + * is suitably aligned for its data type */ #define devPtrAlignTest(PTR) (!(devCreateAlignmentMask(*PTR)&(long)(PTR))) +/** @} */ -/* - * error codes (and messages) associated with devLib.c +/** + * \name Error status values returned by devLib routines + * @{ */ #define S_dev_success 0 -#define S_dev_vectorInUse (M_devLib| 1) /*interrupt vector in use*/ -#define S_dev_vecInstlFail (M_devLib| 2) /*interrupt vector install failed*/ -#define S_dev_uknIntType (M_devLib| 3) /*Unrecognized interrupt type*/ +/** \brief Interrupt vector in use */ +#define S_dev_vectorInUse (M_devLib| 1) /*Interrupt vector in use*/ +/** \brief Interrupt vector install failed */ +#define S_dev_vecInstlFail (M_devLib| 2) /*Interrupt vector install failed*/ +/** \brief Unrecognized interrupt type */ +#define S_dev_uknIntType (M_devLib| 3) /*Unrecognized interrupt type*/ +/** \brief Interrupt vector not in use by caller */ #define S_dev_vectorNotInUse (M_devLib| 4) /*Interrupt vector not in use by caller*/ +/** \brief Invalid VME A16 address */ #define S_dev_badA16 (M_devLib| 5) /*Invalid VME A16 address*/ +/** \brief Invalid VME A24 address */ #define S_dev_badA24 (M_devLib| 6) /*Invalid VME A24 address*/ +/** \brief Invalid VME A32 address */ #define S_dev_badA32 (M_devLib| 7) /*Invalid VME A32 address*/ +/** \brief Unrecognized address space type */ #define S_dev_uknAddrType (M_devLib| 8) /*Unrecognized address space type*/ -#define S_dev_addressOverlap (M_devLib| 9) /*Specified device address overlaps another device*/ -#define S_dev_identifyOverlap (M_devLib| 10) /*This device already owns the address range*/ -#define S_dev_addrMapFail (M_devLib| 11) /*unable to map address*/ -#define S_dev_intDisconnect (M_devLib| 12) /*Interrupt at vector disconnected from an EPICS device*/ -#define S_dev_internal (M_devLib| 13) /*Internal failure*/ -#define S_dev_intEnFail (M_devLib| 14) /*unable to enable interrupt level*/ -#define S_dev_intDissFail (M_devLib| 15) /*unable to disable interrupt level*/ -#define S_dev_noMemory (M_devLib| 16) /*Memory allocation failed*/ -#define S_dev_addressNotFound (M_devLib| 17) /*Specified device address unregistered*/ +/** \brief Specified device address overlaps another device */ +#define S_dev_addressOverlap (M_devLib| 9) /*Specified device address overlaps another device*/ +/** \brief This device already owns the address range */ +#define S_dev_identifyOverlap (M_devLib| 10) /*This device already owns the address range*/ +/** \brief Unable to map address */ +#define S_dev_addrMapFail (M_devLib| 11) /*Unable to map address*/ +/** \brief Interrupt at vector disconnected from an EPICS device */ +#define S_dev_intDisconnect (M_devLib| 12) /*Interrupt at vector disconnected from an EPICS device*/ +/** \brief Internal failure */ +#define S_dev_internal (M_devLib| 13) /*Internal failure*/ +/** \brief Unable to enable interrupt level */ +#define S_dev_intEnFail (M_devLib| 14) /*Unable to enable interrupt level*/ +/** \brief Unable to disable interrupt level */ +#define S_dev_intDissFail (M_devLib| 15) /*Unable to disable interrupt level*/ +/** \brief Memory allocation failed */ +#define S_dev_noMemory (M_devLib| 16) /*Memory allocation failed*/ +/** \brief Specified device address unregistered */ +#define S_dev_addressNotFound (M_devLib| 17) /*Specified device address unregistered*/ +/** \brief No device at specified address */ #define S_dev_noDevice (M_devLib| 18) /*No device at specified address*/ +/** \brief Wrong device type found at specified address */ #define S_dev_wrongDevice (M_devLib| 19) /*Wrong device type found at specified address*/ +/** \brief Signal number (offset) to large */ #define S_dev_badSignalNumber (M_devLib| 20) /*Signal number (offset) to large*/ +/** \brief Signal count to large */ #define S_dev_badSignalCount (M_devLib| 21) /*Signal count to large*/ +/** \brief Device does not support requested operation */ #define S_dev_badRequest (M_devLib| 22) /*Device does not support requested operation*/ -#define S_dev_highValue (M_devLib| 23) /*Parameter to high*/ -#define S_dev_lowValue (M_devLib| 24) /*Parameter to low*/ +/** \brief Parameter too high */ +#define S_dev_highValue (M_devLib| 23) /*Parameter too high*/ +/** \brief Parameter too low */ +#define S_dev_lowValue (M_devLib| 24) /*Parameter too low*/ +/** \brief Specified address is ambiguous (more than one device responds) */ #define S_dev_multDevice (M_devLib| 25) /*Specified address is ambiguous (more than one device responds)*/ +/** \brief Device self test failed */ #define S_dev_badSelfTest (M_devLib| 26) /*Device self test failed*/ +/** \brief Device failed during initialization */ #define S_dev_badInit (M_devLib| 27) /*Device failed during initialization*/ +/** \brief Input exceeds Hardware Limit */ #define S_dev_hdwLimit (M_devLib| 28) /*Input exceeds Hardware Limit*/ +/** \brief Unable to locate address space for device */ #define S_dev_deviceDoesNotFit (M_devLib| 29) /*Unable to locate address space for device*/ -#define S_dev_deviceTMO (M_devLib| 30) /*device timed out*/ -#define S_dev_badFunction (M_devLib| 31) /*bad function pointer*/ -#define S_dev_badVector (M_devLib| 32) /*bad interrupt vector*/ -#define S_dev_badArgument (M_devLib| 33) /*bad function argument*/ +/** \brief Device timed out */ +#define S_dev_deviceTMO (M_devLib| 30) /*Device timed out*/ +/** \brief Bad function pointer */ +#define S_dev_badFunction (M_devLib| 31) /*Bad function pointer*/ +/** \brief Bad interrupt vector */ +#define S_dev_badVector (M_devLib| 32) /*Bad interrupt vector*/ +/** \brief Bad function argument */ +#define S_dev_badArgument (M_devLib| 33) /*Bad function argument*/ +/** \brief Invalid ISA address */ #define S_dev_badISA (M_devLib| 34) /*Invalid ISA address*/ +/** \brief Invalid VME CR/CSR address */ #define S_dev_badCRCSR (M_devLib| 35) /*Invalid VME CR/CSR address*/ +/** \brief Synonym for S_dev_intEnFail */ #define S_dev_vxWorksIntEnFail S_dev_intEnFail - +/** @} */ #endif /* EPICSDEVLIB_H */ diff --git a/modules/libcom/src/osi/devLibVME.h b/modules/libcom/src/osi/devLibVME.h index 4fb17f0c2..fbf8b399a 100644 --- a/modules/libcom/src/osi/devLibVME.h +++ b/modules/libcom/src/osi/devLibVME.h @@ -4,14 +4,23 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* devLib.h */ -/* - * Original Author: Marty Kraimer - * Author: Jeff Hill - * Date: 03-10-93 +/** + * \file devLibVME.h + * \author Marty Kraimer, Jeff Hill + * \brief API for accessing hardware devices, mosty over VMEbus. + * + * API for accessing hardware devices. The original APIs here were for + * written for use with VMEbus but additional routines were added for + * ISA-bus (but not fully implemented inside EPICS Base and may never + * have been actually used). + * + * If all VMEbus drivers register with these routines then addressing + * conflicts caused by multiple device/drivers trying to use the same + * VME addresses will be detected. This API also makes it easy for a + * single driver to be written that works on both VxWorks and RTEMS. */ #ifndef INCdevLibh @@ -27,23 +36,17 @@ extern "C" { #endif -/* - * epdevAddressType & EPICStovxWorksAddrType - * devLib.c must change in unison - */ +/** \brief The available bus address types */ typedef enum { - atVMEA16, - atVMEA24, - atVMEA32, - atISA, /* memory mapped ISA access (until now only on PC) */ - atVMECSR, /* VME-64 CR/CSR address space */ - atLast /* atLast must be the last enum in this list */ - } epicsAddressType; + atVMEA16, /**< \brief VME short I/O. */ + atVMEA24, /**< \brief VME standard I/O. */ + atVMEA32, /**< \brief VME extended I/O. */ + atISA, /**< \brief Memory mapped ISA access. */ + atVMECSR, /**< \brief VME-64 CR/CSR address space. */ + atLast /**< \brief Invalid, must be the last entry. */ +} epicsAddressType; -/* - * pointer to an array of strings for each of - * the above address types - */ +/** \brief A string representation of each of the bus address types */ epicsShareExtern const char *epicsAddressTypeName[]; #ifdef __cplusplus @@ -61,41 +64,54 @@ epicsShareExtern const char *epicsAddressTypeName[]; extern "C" { #endif -/* - * General API +/** \brief Print a map of registered bus addresses. * - * This section applies to all bus types + * Display a table of registsred bus address ranges, including the owner of + * each registered address. + * \return 0, or an error status value */ +epicsShareFunc long devAddressMap(void); -epicsShareFunc long devAddressMap(void); /* print an address map */ - -/* - * devBusToLocalAddr() +/** \brief Translate a bus address to a pointer the CPU can use. * - * OSI routine to translate bus addresses their local CPU address mapping + * Given a bus address, returns a pointer to that location in the CPU's + * memory map, or an error if direct access isn't currently possible. + * \param addrType The bus address type. + * \param busAddr Bus address to be translated. + * \param *ppLocalAddr Where to put the CPU pointer. + * \return 0, or an error status value. */ epicsShareFunc long devBusToLocalAddr ( epicsAddressType addrType, size_t busAddr, volatile void **ppLocalAddr); -/* - * devReadProbe() + +/** \brief Probe the bus for reading from a specific address. * - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present + * Performs a bus-error-safe \c wordSize atomic read from a specific + * address and returns an error if this caused a bus error. + * \param wordSize The word size to read: 1, 2, 4 or 8 bytes. + * \param ptr Pointer to the location in the CPU's memory map to read. + * \param pValueRead Where to put the value read. + * \return 0, or an error status value if the location could not be + * accessed or the read caused a bus error. */ epicsShareFunc long devReadProbe ( unsigned wordSize, volatile const void *ptr, void *pValueRead); -/* - * devNoResponseProbe() +/** \brief Read-probe a range of bus addresses, looking for empty space. * - * Verifies that no devices respond at naturally aligned words - * within the specified address range. Return success if no devices - * respond. Returns an error if a device does respond or if - * a physical address for a naturally aligned word cant be mapped. - * Checks all naturally aligned word sizes between char and long for - * the entire specified range of bytes. + * Verifies that no device responds at any naturally aligned addresses + * within the given range. Tries to read every aligned address at every + * word size between char and long over the entire range, returning + * success only if none of the reads succeed. + * \warning This routine may be slow and have a very bad effect on a busy + * VMEbus. Every read probe of an unused address will hold onto the VMEbus + * for the global bus timeout period. + * \param addrType The bus address type. + * \param base First address base to probe. + * \param size Range of bus addresses to test, in bytes. + * \return 0 if no devices respond, or an error status value. */ epicsShareFunc long devNoResponseProbe( epicsAddressType addrType, @@ -103,29 +119,71 @@ epicsShareFunc long devNoResponseProbe( size_t size ); -/* - * devWriteProbe +/** \brief Probe the bus for writing to a specific address. * - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present + * Performs a bus-error-safe \c wordSize atomic write to a specific + * address and returns an error if this caused a bus error. + * \param wordSize The word size to write: 1, 2, 4 or 8 bytes. + * \param ptr Pointer to the location in the CPU's memory map to write to. + * \param pValueWritten The value to write. + * \return 0, or an error status value if the location could not be + * accessed or the write caused a bus error. */ epicsShareFunc long devWriteProbe ( unsigned wordSize, volatile void *ptr, const void *pValueWritten); +/** \brief Register a bus address range with a name. + * + * The devLib code keeps a list of all bus address ranges registered with + * this routine and returns an error if a later call attempts to register + * any addresses that overlap with a range already registered. The call to + * registering a range also converts the given base address into a pointer + * in the CPU address space for the driver to use (see devBusToLocalAddr()). + * \param pOwnerName Name of a driver that will own this range. + * \param addrType The bus address type. + * \param logicalBaseAddress The bus start address. + * \param size Number of bytes to reserve. + * \param pPhysicalAddress Where to put the converted CPU pointer. + * \return 0, or an error status. + */ epicsShareFunc long devRegisterAddress( const char *pOwnerName, epicsAddressType addrType, size_t logicalBaseAddress, - size_t size, /* bytes */ + size_t size, volatile void **pPhysicalAddress); +/** \brief Release a bus address range previously registered. + * + * Release an address range that was previously registered by a call to + * devRegisterAddress() or devAllocAddress(). + * \param addrType The bus address type. + * \param logicalBaseAddress The bus start address. + * \param pOwnerName The name of the driver that owns this range. + * \return 0, or an error status. + */ epicsShareFunc long devUnregisterAddress( epicsAddressType addrType, size_t logicalBaseAddress, const char *pOwnerName); -/* - * allocate and register an unoccupied address block +/** \brief Allocate and register an unoccupied address block. + * + * Asks devLib to allocate an address block of a particular address type. + * This is useful for devices that appear in more than one address space + * and can program the base address of one window using registers found + * in another window. As with devRegisterAddress() this call also converts + * the new base address into a pointer in the CPU address space for the + * driver to use (see devBusToLocalAddr()). + * \note This routine calls devNoResponseProbe() to find an unoccupied + * block in the bus address space, so using it may have a bad effect on a + * busy VMEbus at allocation time; see the warning above. + * \param pOwnerName Name of a driver that will own this range. + * \param addrType The bus address type. + * \param size Number of bytes to be allocated. + * \param alignment How many low bits in the address must all be zero. + * \param pLocalAddress Where to put the CPU pointer. + * \return 0, or an error status value. */ epicsShareFunc long devAllocAddress( const char *pOwnerName, @@ -134,117 +192,185 @@ epicsShareFunc long devAllocAddress( unsigned alignment, /*n ls bits zero in addr*/ volatile void **pLocalAddress); -/* - * VME API - * - * Functions in this section apply only to the VME bus type +/** \name VME Interrupt Management + * Routines to manage VME interrupts. + * @{ */ - -/* - * connect ISR to a VME interrupt vector +/** \brief Connect an ISR up to a VME interrupt vector. + * + * Interrupt Service Routines (ISRs) are normally written in C, and get + * passed a context parameter given with them to this connection routine. + * + * There are many restrictions on the routines that an ISR may call; see + * epicsEvent.h, epicsInterrupt.h, epicsMessageQueue.h, epicsRingBytes.h, + * epicsRingPointer.h and epicsTime.h for some APIs known to be suitable. + * It is safest just to trigger a high-priority task to handle any + * complex work that must happen as a result of the interrupt. + * \param vectorNumber VME interrupt vector number. + * \param pFunction The ISR to be called. + * \param parameter Context parameter for the ISR. + * \return 0, or an error status value. */ epicsShareFunc long devConnectInterruptVME( unsigned vectorNumber, void (*pFunction)(void *), void *parameter); -/* - * disconnect ISR from a VME interrupt vector +/** \brief Disconnect an ISR from its VME interrupt vector. * - * The parameter pFunction should be set to the C function pointer that - * was connected. It is used as a key to prevent a driver from inadvertently - * removing an interrupt handler that it didn't install + * Device drivers may disconnect an ISR they connected earlier using this + * routine. In addition to taking the \c vectorNumber the ISR itself is + * required and used as a check to prevent a driver from inadvertently + * removing an interrupt handler that it didn't install. + * + * On a PowerPC target running VxWorks, this routine will always return + * with an error status. + * \param vectorNumber VME interrupt vector number. + * \param pFunction The ISR to be disconnected. + * \return 0, or an error status value. */ epicsShareFunc long devDisconnectInterruptVME( unsigned vectorNumber, void (*pFunction)(void *)); -/* - * determine if a VME interrupt vector is in use +/** \brief Determine if a VME interrupt vector is in use. * - * returns boolean + * On a PowerPC target running VxWorks this routine will always return + * false, indicating that a vector is unused. + * \param vectorNumber Interrupt vector number. + * \return True if vector has an ISR attached, otherwise false. */ epicsShareFunc int devInterruptInUseVME (unsigned vectorNumber); -/* - * enable VME interrupt level +/** \brief Enable a VME interrupt level onto the CPU. + * + * The VMEbus allows multiple CPU boards to be installed in the same + * backplane. When this is done, the differente VME interrupt levels + * must be assigned to the CPUs since they cannot be shared. This + * routine tells the VME interface that it should connect interrupts + * from the indicated interrupt level to a CPU interrupt line. + * \param level VMEbus interrupt level to enable, 1-7. + * \return 0, or an error status value. */ epicsShareFunc long devEnableInterruptLevelVME (unsigned level); -/* - * disable VME interrupt level +/** \brief Disable a VME interrupt level. + * + * This routine is the reverse of devEnableInterruptLevelVME(). + * \note This routine should not normally be used, even by a + * driver that enabled the interrupt level. Disabling a VME + * interrupt level should only be done by software that knows + * for certain that no other interrupting device is also using + * that VME interrupt level. + * \param level VMEbus interrupt level to disable, 1-7. + * \return 0, or an error status value. */ epicsShareFunc long devDisableInterruptLevelVME (unsigned level); +/** @} */ -/* - * Routines to allocate and free memory in the A24 memory region. - * +/** \name Memory for VME DMA Operations + * These routines manage memory that can be directly accessed + * from the VMEbus in the A24 address space by another bus master + * such as a DMA controller. + * @{ + */ +/** \brief malloc() for VME drivers that support DMA. + * + * Allocate memory of a given size from a region that can be + * accessed from the VMEbus in the A24 address space. + * \param size How many bytes to allocate + * \return A pointer to the memory allocated, or NULL. + */ +epicsShareFunc void *devLibA24Malloc(size_t size); + +/** \brief calloc() for VME drivers that support DMA. + * + * Allocate and zero-fill a block of memory of a given size from + * a region that can be accessed from the VMEbus in the A24 + * address space. + * \param size How many bytes to allocate and zero. + * \return A pointer to the memory allocated, or NULL. + */ +epicsShareFunc void *devLibA24Calloc(size_t size); + +/** \brief free() for VME drivers that support DMA. + * + * Free a block of memory that was allocated using either + * devLibA24Malloc() or devLibA24Calloc(). + * \param pBlock Block to be released. */ -epicsShareFunc void *devLibA24Malloc(size_t); -epicsShareFunc void *devLibA24Calloc(size_t); epicsShareFunc void devLibA24Free(void *pBlock); +/** @} */ -/* - * ISA API - * - * Functions in this section apply only to the ISA bus type +/** \name ISA Interrupt Management + * Routines to manage ISAbus interrupts. + * \note These routines may not have been used for a very long time; + * some appear to have never been implemented at all. They may vanish + * with no notice from future versions of EPICS Base. Nobody is using + * the PC's ISA-bus any more are they? + * @{ */ -/* - * connect ISR to an ISA interrupt level - * (not implemented) - * (API should be reviewed) +/** + * Connect ISR to a ISA interrupt. + * \warning Not implemented! + * \param interruptLevel Bus interrupt level to connect to. + * \param pFunction C function pointer to connect to. + * \param parameter Parameter to the called function. + * \return Returns success or error. */ epicsShareFunc long devConnectInterruptISA( unsigned interruptLevel, void (*pFunction)(void *), void *parameter); -/* - * disconnect ISR from an ISA interrupt level - * (not implemented) - * (API should be reviewed) - * - * The parameter pFunction should be set to the C function pointer that - * was connected. It is used as a key to prevent a driver from inadvertently - * removing an interrupt handler that it didn't install +/** + * Disconnect ISR from a ISA interrupt level. + * \warning Not implemented! + * \param interruptLevel Interrupt level. + * \param pFunction C function pointer that was connected. + * \return returns success or error. */ epicsShareFunc long devDisconnectInterruptISA( unsigned interruptLevel, void (*pFunction)(void *)); -/* - * determine if an ISA interrupt level is in use - * (not implemented) - * - * returns boolean +/** + * Determine if an ISA interrupt level is in use + * \warning Not implemented! + * \param interruptLevel Interrupt level. + * \return Returns True/False. */ epicsShareFunc int devInterruptLevelInUseISA (unsigned interruptLevel); -/* - * enable ISA interrupt level +/** + * Enable ISA interrupt level + * \param level Interrupt level. + * \return Returns True/False. */ epicsShareFunc long devEnableInterruptLevelISA (unsigned level); -/* - * disable ISA interrupt level +/** + * Disable ISA interrupt level + * \param level Interrupt level. + * \return Returns True/False. */ epicsShareFunc long devDisableInterruptLevelISA (unsigned level); - -/* - * Deprecated interface - */ +/** @} */ #ifndef NO_DEVLIB_OLD_INTERFACE +/** + * \name Deprecated Interfaces + * @{ + */ typedef enum {intVME, intVXI, intISA} epicsInterruptType; -/* - * NOTE: this routine has been deprecated. It exists +/** + * \note This routine has been deprecated. It exists * for backwards compatibility purposes only. - * - * Please use one of devConnectInterruptVME, devConnectInterruptPCI, - * devConnectInterruptISA etc. devConnectInterrupt will be removed + * Please use one of devConnectInterruptVME(), devConnectInterruptPCI(), + * devConnectInterruptISA() instead. devConnectInterrupt() will be removed * in a future release. */ epicsShareFunc long devConnectInterrupt( @@ -253,50 +379,48 @@ epicsShareFunc long devConnectInterrupt( void (*pFunction)(void *), void *parameter); -/* - * NOTE: this routine has been deprecated. It exists +/** + * \note This routine has been deprecated. It exists * for backwards compatibility purposes only. - * - * Please use one of devDisconnectInterruptVME, devDisconnectInterruptPCI, - * devDisconnectInterruptISA etc. devDisconnectInterrupt will be removed - * in a future release. + * Please use one of devDisconnectInterruptVME(), devDisconnectInterruptPCI(), + * devDisconnectInterruptISA() instead. devDisconnectInterrupt() will + * be removed in a future release. */ epicsShareFunc long devDisconnectInterrupt( epicsInterruptType intType, unsigned vectorNumber, void (*pFunction)(void *)); -/* - * NOTE: this routine has been deprecated. It exists +/** + * \note This routine has been deprecated. It exists * for backwards compatibility purposes only. - * - * Please use one of devEnableInterruptLevelVME, devEnableInterruptLevelPCI, - * devEnableInterruptLevelISA etc. devEnableInterruptLevel will be removed - * in a future release. + * Please use one of devEnableInterruptLevelVME(), devEnableInterruptLevelPCI(), + * devEnableInterruptLevelISA() instead. devEnableInterruptLevel() will + * be removed in a future release. */ epicsShareFunc long devEnableInterruptLevel( epicsInterruptType intType, unsigned level); -/* - * NOTE: this routine has been deprecated. It exists +/** + * \note This routine has been deprecated. It exists * for backwards compatibility purposes only. - * - * Please use one of devDisableInterruptLevelVME, devDisableInterruptLevelISA, - * devDisableInterruptLevelPCI etc. devDisableInterruptLevel will be removed - * in a future release. + * Please use one of devDisableInterruptLevelVME(), devDisableInterruptLevelISA(), + * devDisableInterruptLevelPCI() instead. devDisableInterruptLevel() will + * be removed in a future release. */ epicsShareFunc long devDisableInterruptLevel ( epicsInterruptType intType, unsigned level); -/* - * NOTE: this routine has been deprecated. It exists +/** + * \note This routine has been deprecated. It exists * for backwards compatibility purposes only. - * - * Please use devNoResponseProbe(). locationProbe() will be removed + * Please use devNoResponseProbe() instead. locationProbe() will be removed * in a future release. */ epicsShareFunc long locationProbe (epicsAddressType addrType, char *pLocation); +/** @} */ + #endif /* NO_DEVLIB_OLD_INTERFACE */ #ifdef __cplusplus diff --git a/modules/libcom/src/osi/devLibVMEImpl.h b/modules/libcom/src/osi/devLibVMEImpl.h index e479d869c..c9fea8d00 100644 --- a/modules/libcom/src/osi/devLibVMEImpl.h +++ b/modules/libcom/src/osi/devLibVMEImpl.h @@ -6,14 +6,13 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* devLibImpl.h */ -/* - * Original Author: Marty Kraimer - * Author: Jeff Hill - * Date: 03-10-93 +/** + * \file devLibVMEImpl.h + * \author Marty Kraimer, Jeff Hill + * \brief An interface from devLibVME.c to its OS-specific implementations. */ #ifndef INCdevLibImplh @@ -27,72 +26,57 @@ extern "C" { #endif -/* - * virtual OS layer for devLib.c +/** + * \brief A table of function pointers for devLibVME implementations * - * The global virtual OS table pdevLibVME controls + * The global virtual OS table \ref pdevLibVME controls * the behaviour of the functions defined in devLib.h. * All of which call into the functions found in this table * to perform system specific tasks. */ typedef struct devLibVME { - /* - * maps logical address to physical address, but does not detect - * two device drivers that are using the same address range - */ - long (*pDevMapAddr) (epicsAddressType addrType, unsigned options, - size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress); + /** \brief Map a bus address to the CPU's address space. */ + long (*pDevMapAddr) (epicsAddressType addrType, unsigned options, + size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress); - /* - * a bus error safe "wordSize" read at the specified address which returns - * unsuccessful status if the device isnt present - */ - long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr, void *pValueRead); + /** \brief Read a word, detect and protect against bus errors. */ + long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr, + void *pValueRead); + /** \brief Write a word, detect and protect against bus errors. */ + long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr, + const void *pValueWritten); - /* - * a bus error safe "wordSize" write at the specified address which returns - * unsuccessful status if the device isnt present - */ - long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr, const void *pValueWritten); + /** \brief Connect ISR to a VME interrupt vector. */ + long (*pDevConnectInterruptVME) (unsigned vectorNumber, + void (*pFunction)(void *), void *parameter); + /** \brief Disconnect ISR from a VME interrupt vector. */ + long (*pDevDisconnectInterruptVME) (unsigned vectorNumber, + void (*pFunction)(void *)); - /* - * connect ISR to a VME interrupt vector - * (required for backwards compatibility) - */ - long (*pDevConnectInterruptVME) (unsigned vectorNumber, - void (*pFunction)(void *), void *parameter); + /** \brief Enable VME interrupt level to CPU. */ + long (*pDevEnableInterruptLevelVME) (unsigned level); + /** \brief Disable VME interrupt level to CPU. */ + long (*pDevDisableInterruptLevelVME) (unsigned level); - /* - * disconnect ISR from a VME interrupt vector - * (required for backwards compatibility) - */ - long (*pDevDisconnectInterruptVME) (unsigned vectorNumber, - void (*pFunction)(void *)); + /** \brief Malloc a block accessible from the VME A24 address space. */ + void *(*pDevA24Malloc)(size_t nbytes); + /** \brief Free a block allocated for the VME A24 address space. */ + void (*pDevA24Free)(void *pBlock); - /* - * enable VME interrupt level - */ - long (*pDevEnableInterruptLevelVME) (unsigned level); + /** \brief Init devLib */ + long (*pDevInit)(void); - /* - * disable VME interrupt level - */ - long (*pDevDisableInterruptLevelVME) (unsigned level); - /* malloc/free A24 address space */ - void *(*pDevA24Malloc)(size_t nbytes); - void (*pDevA24Free)(void *pBlock); - long (*pDevInit)(void); - - /* - * test if VME interrupt has an ISR connected - */ - int (*pDevInterruptInUseVME) (unsigned vectorNumber); + /** \brief Check if interrupt vector has an ISR connected. */ + int (*pDevInterruptInUseVME)(unsigned vectorNumber); }devLibVME; +/** \brief Pointer to the entry table used by devLibVME routines. */ epicsShareExtern devLibVME *pdevLibVME; #ifndef NO_DEVLIB_COMPAT +/** \brief An alias for pdevLibVME */ # define pdevLibVirtualOS pdevLibVME +/** \brief A type definition for devLibVME */ typedef devLibVME devLibVirtualOS; #endif diff --git a/modules/libcom/src/osi/epicsAssert.h b/modules/libcom/src/osi/epicsAssert.h index 6f83d3a82..8df8a2e86 100644 --- a/modules/libcom/src/osi/epicsAssert.h +++ b/modules/libcom/src/osi/epicsAssert.h @@ -4,14 +4,39 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * EPICS assert + +/**\file epicsAssert.h + * \author Jeffery O. Hill * - * Author: Jeffrey O. Hill - * Date: 022795 - */ + * \brief An EPICS-specific replacement for ANSI C's assert. + * + * To use this version just include: + \code + #define epicsAssertAuthor "Code Author my@email.address" + #include + \endcode + * instead of + \code + #include + \endcode + * + * If an assert() fails, it calls errlog indicating the program's author, file name, and + * line number. Under each OS there are specialized instructions assisting the user to + * diagnose the problem and generate a good bug report. For instance, under vxWorks, + * there are instructions on how to generate a stack trace, and on posix there are + * instructions about saving the core file. After printing the message the calling thread + * is suspended. An author may, before the above include line, optionally define a + * preprocessor macro named epicsAssertAuthor as a string that provides their name and + * email address if they wish to be contacted when the assertion fires. + * + * This header also provides a compile-time assertion macro STATIC_ASSERT() + * which can be used to check a constant-expression at compile-time. The C or + * C++ compiler will flag an error if the expresstion evaluates to 0. The + * STATIC_ASSERT() macro can only be used where a \c typedef is syntactically + * legal. + **/ #ifndef INC_epicsAssert_H #define INC_epicsAssert_H @@ -25,6 +50,7 @@ extern "C" { #ifndef epicsAssertAuthor +/**\brief Optional string giving the author's name */ # define epicsAssertAuthor 0 #endif @@ -34,9 +60,13 @@ extern "C" { # define assert(ignore) ((void) 0) #else /* NDEBUG */ +/**@private */ epicsShareFunc void epicsAssert (const char *pFile, const unsigned line, const char *pExp, const char *pAuthorName); +/**\brief Declare that a condition should be true. + * \param exp Expression that should evaluate to True. + */ # define assert(exp) ((exp) ? (void)0 : \ epicsAssert(__FILE__, __LINE__, #exp, epicsAssertAuthor)) @@ -49,6 +79,10 @@ epicsShareFunc void epicsAssert (const char *pFile, const unsigned line, #else #define STATIC_JOIN(x, y) STATIC_JOIN2(x, y) #define STATIC_JOIN2(x, y) x ## y + +/**\brief Declare a condition that should be true at compile-time. + * \param expr A C/C++ const-expression that should evaluate to True. + */ #define STATIC_ASSERT(expr) \ typedef int STATIC_JOIN(static_assert_failed_at_line_, __LINE__) \ [ (expr) ? 1 : -1 ] EPICS_UNUSED diff --git a/modules/libcom/src/osi/epicsEvent.h b/modules/libcom/src/osi/epicsEvent.h index e77d9a5ce..c97cb4d8a 100644 --- a/modules/libcom/src/osi/epicsEvent.h +++ b/modules/libcom/src/osi/epicsEvent.h @@ -4,26 +4,62 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ + +/**\file epicsEvent.h + * + * \brief APIs for the epicsEvent binary semaphore. + * + * Defines the C++ and C API's for a simple binary semaphore. If multiple threads are + * waiting on the same event, only one of them will be woken when the event is signalled. + * + * The primary use of an event semaphore is for thread synchronization. An example of using an + * event semaphore is a consumer thread that processes requests from one or more producer threads. + * For example: + * + * When creating the consumer thread also create an epicsEvent. + \code + epicsEvent *pevent = new epicsEvent; + \endcode + * The consumer thread has code containing: + \code + while(1) { + pevent->wait(); + while( {more work} ) { + {process work} + } + } + \endcode + * Producers create requests and issue the statement: + \code + pevent->trigger(); + \endcode + **/ + #ifndef epicsEventh #define epicsEventh #include "shareLib.h" +/** \brief An identifier for an epicsEvent for use with the C API */ typedef struct epicsEventOSD *epicsEventId; +/** \brief Return status from several C API routines. */ typedef enum { epicsEventOK = 0, epicsEventWaitTimeout, epicsEventError } epicsEventStatus; -/* Backwards compatibility */ +/** \brief Old name provided for backwards compatibility */ #define epicsEventWaitStatus epicsEventStatus +/** \brief Old name provided for backwards compatibility */ #define epicsEventWaitOK epicsEventOK +/** \brief Old name provided for backwards compatibility */ #define epicsEventWaitError epicsEventError +/** \brief Possible initial states of a new epicsEvent */ typedef enum { epicsEventEmpty, epicsEventFull @@ -31,15 +67,50 @@ typedef enum { #ifdef __cplusplus +/**\brief A binary semaphore. + * + * An epicsEvent is a binary semaphore that can be empty or full. + * When empty, a wait() issued before the next call to trigger() will block. + * When full, the next call to wait() will empty the event and return + * immediately. Multiple calls to trigger() may occur between wait() calls + * but will have the same effect as a single trigger(), filling the event. + **/ class epicsShareClass epicsEvent { public: + /**\brief Constructor. + * \param initial State when created, empty (the default) or full. + **/ epicsEvent ( epicsEventInitialState initial = epicsEventEmpty ); + /**\brief Destroy the epicsEvent and any resources it holds. No calls to + * wait() can be active when this call is made. + **/ ~epicsEvent (); + /**\brief Trigger the event i.e. ensures the next or current call to wait + * completes. This method may be called from a vxWorks or RTEMS interrupt + * handler. + **/ void trigger (); + /**\brief Signal is a synonym for trigger(). + **/ void signal () { this->trigger(); } - void wait (); /* blocks until full */ - bool wait ( double timeOut ); /* false if still empty at time out */ - bool tryWait (); /* false if empty */ + /**\brief Wait for the event. + * \note Blocks until full. + **/ + void wait (); + /**\brief Wait for the event or until the specified timeout. + * \param timeOut The timeout delay in seconds. + * \return True if the event was triggered, False if it timed out. + **/ + bool wait ( double timeOut ); + /**\brief Similar to wait() except that if the event is currenly empty the + * call will return immediately. + * \return True if the event was full (triggered), False if empty. + **/ + bool tryWait (); + /**\brief Display information about the semaphore. + * \note The information displayed is architecture dependant. + * \param level An unsigned int for the level of information to be displayed. + **/ void show ( unsigned level ) const; class invalidSemaphore; /* exception payload */ @@ -52,22 +123,91 @@ private: extern "C" { #endif /*__cplusplus */ +/**\brief Create an epicsEvent for use from C code, or return NULL. + * + * \param initialState Starting state, \c epicsEventEmpty or \c epicsEventFull. + * \return An identifier for the new event, or NULL if one not be created. + **/ epicsShareFunc epicsEventId epicsEventCreate( epicsEventInitialState initialState); + +/**\brief Create an epicsEvent for use from C code. + * + * This routine does not return if the object could not be created. + * \param initialState Starting state, \c epicsEventEmpty or \c epicsEventFull. + * \return An identifier for the new event. + **/ epicsShareFunc epicsEventId epicsEventMustCreate ( epicsEventInitialState initialState); + +/**\brief Destroy an epicsEvent and any resources it holds. + * + * No calls to any epicsEventWait routines can be active when this call is made. + * \param id The event identifier. + **/ epicsShareFunc void epicsEventDestroy(epicsEventId id); + +/**\brief Trigger an event i.e. ensures the next or current call to wait + * completes. + * + * \note This method may be called from a VxWorks or RTEMS interrupt + * handler. + * \param id The event identifier. + * \return Status indicator. + **/ epicsShareFunc epicsEventStatus epicsEventTrigger( epicsEventId id); + +/**\brief Trigger an event. + * + * This routine does not return if the identifier is invalid. + * \param id The event identifier. + */ epicsShareFunc void epicsEventMustTrigger(epicsEventId id); + +/**\brief A synonym for epicsEventTrigger(). + * \param ID The event identifier. + * \return Status indicator. + **/ #define epicsEventSignal(ID) epicsEventMustTrigger(ID) + +/**\brief Wait for an event. + * \note Blocks until full. + * \param id The event identifier. + * \return Status indicator. + **/ epicsShareFunc epicsEventStatus epicsEventWait( epicsEventId id); + +/**\brief Wait for an event (see epicsEventWait()). + * + * This routine does not return if the identifier is invalid. + * \param id The event identifier. + */ epicsShareFunc void epicsEventMustWait(epicsEventId id); + +/**\brief Wait an the event or until the specified timeout period is over. + * \note Blocks until full or timeout. + * \param id The event identifier. + * \param timeOut The timeout delay in seconds. + * \return Status indicator. + **/ epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout( epicsEventId id, double timeOut); + +/**\brief Similar to wait() except that if the event is currenly empty the + * call will return immediately with status \c epicsEventWaitTimeout. + * \param id The event identifier. + * \return Status indicator, \c epicsEventWaitTimeout when the event is empty. + **/ epicsShareFunc epicsEventStatus epicsEventTryWait( epicsEventId id); + +/**\brief Display information about the semaphore. + * \note The information displayed is architecture dependant. + * \param id The event identifier. + * \param level An unsigned int for the level of information to be displayed. + **/ epicsShareFunc void epicsEventShow( epicsEventId id, unsigned int level); diff --git a/modules/libcom/src/osi/epicsGeneralTime.h b/modules/libcom/src/osi/epicsGeneralTime.h index 6bbb0b21b..8f494b376 100644 --- a/modules/libcom/src/osi/epicsGeneralTime.h +++ b/modules/libcom/src/osi/epicsGeneralTime.h @@ -7,6 +7,32 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ +/**\file epicsGeneralTime.h + * + * \brief The generalTime framework provides a mechanism for several time providers to be + * present within the system. + * + * There are two types of time provider, one type provides the current wall-clock + * time, the other provides Event System times. Each time provider is registered with + * a priority, and installed providers are queried in priority order whenever a time + * is requested, until one returns successfully. Thus there is a fallback from higher + * priority providers (smaller value of priority) to lower priority providers (larger + * value of priority) if the highest priority ones fail. Each architecture has a "last + * resort" provider, installed at priority 999, usually based on the system clock, which + * is used in the absence of any other provider. + * + * Targets running VxWorks and RTEMS have an NTP provider installed at priority 100. + * + * Registered providers may also add an interrupt-safe routine that will be called from + * the epicsTimeGetCurrentInt() or epicsTimeGetEventInt() API routines. These interfaces + * cannot check the priority queue, so will only succeed if the last-used provider has + * registered a suitable routine. + * + * \note There are two interfaces to this framework, epicsGeneralTime.h for consumers + * to obtain a time and query the framework, and generalTimeSup.h for providers + * that can supply timestamps. + **/ + #ifndef INC_epicsGeneralTime_H #define INC_epicsGeneralTime_H @@ -16,28 +42,109 @@ extern "C" { #endif +/**\def NUM_TIME_EVENTS + * \brief The number of time events that are validated. + * + * Time Events numbered 0 through (NUM_TIME_EVENTS-1) are validated by code in + * epicsGeneralTime.c that tests for advancing timestamps and enforces that + * restriction. + * + * \note Event numbers greater than or equal to NUM_TIME_EVENTS are now allowed + * if supported by a custom time provider which should provide its own advancing + * timestamp validation. + **/ #define NUM_TIME_EVENTS 256 -/* Time Events numbered 0 through (NUM_TIME_EVENTS-1) are validated by */ -/* code in epicsGeneralTime.c that tests for advancing timestamps and */ -/* enforces that restriction. Event numbers greater than or equal to */ -/* NUM_TIME_EVENTS are now allowed if supported by a custom time provider */ -/* which should provide its own advancing timestamp validation. */ +/**\brief Initialise the framework. + * + * This routine is called automatically by any function that requires the + * framework. It does not need to be called explicitly. + **/ epicsShareFunc void generalTime_Init(void); +/**\brief Install a Time Event time provider that returns the current time for any + * Time event number. + * + * \note This is optional as it is site policy whether the last resort for a Time + * Event time in the absence of any working provider should be a failure, or the + * current time. + **/ epicsShareFunc int installLastResortEventProvider(void); +/**\brief Reset the internal counter of the number of times the time returned was + * earlier than when previously requested. + * + * Used by device support for binary out record + * with: + \code + DTYP = "General Time" + OUT = "@RSTERRCNT" + \endcode + **/ epicsShareFunc void generalTimeResetErrorCounts(void); + +/**\brief Return the internal counter of the number of times the time returned was + * earlier than when previously requested. + * + * Used by device support for longin record + * with: + \code + DTYP = "General Time" + INP = "@GETERRCNT" + \endcode + * + * \return Reset error counts + **/ epicsShareFunc int generalTimeGetErrorCounts(void); +/**\brief Return the nume of the provider that last returned a valid current time, or + * NULL if none. + * + * Used by stringin device support with: + \code + DTYP = "General Time" + INP = "@BESTTCP" + \endcode + * + * \return Provider name + **/ epicsShareFunc const char * generalTimeCurrentProviderName(void); + +/**\brief Return the name of the provider that last returned a valid Time Event time, or + * NULL of none. + * + * Used by stringin device support with: + \code + DTYP = "General Time" + INP = "@BESTTEP" + \endcode + * + * \return Provider name + **/ epicsShareFunc const char * generalTimeEventProviderName(void); + +/**\brief Return the name of the registered current time provider that has the highest + * priority. + * + * Used by stringin device support with: + \code + DTYP = "General Time" + INP = "@TOPTCP" + \endcode + * + * \return Provider name + **/ epicsShareFunc const char * generalTimeHighestCurrentName(void); -/* Original names, for compatibility */ +/** \brief Old name provided for backwards compatibility */ #define generalTimeCurrentTpName generalTimeCurrentProviderName +/** \brief Old name provided for backwards compatibility */ #define generalTimeEventTpName generalTimeEventProviderName +/**\brief Provide information about the installed providers and their current best times. + * + * \param interest Desired interest level to report + **/ epicsShareFunc long generalTimeReport(int interest); #ifdef __cplusplus diff --git a/modules/libcom/src/osi/epicsMessageQueue.h b/modules/libcom/src/osi/epicsMessageQueue.h index c6a98fd47..7150eab44 100644 --- a/modules/libcom/src/osi/epicsMessageQueue.h +++ b/modules/libcom/src/osi/epicsMessageQueue.h @@ -5,17 +5,18 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author W. Eric Norum - * norume@aps.anl.gov - * 630 252 4793 + +/** + * \file epicsMessageQueue.h + * \author W. Eric Norum + * + * \brief A C++ and a C facility for communication between threads. + * + * Each C function corresponds to one of the C++ methods. */ -/* - * Interthread message passing - */ #ifndef epicsMessageQueueh #define epicsMessageQueueh @@ -26,22 +27,135 @@ typedef struct epicsMessageQueueOSD *epicsMessageQueueId; #ifdef __cplusplus +/** Provides methods for sending messages between threads on a first in, + * first out basis. It is designed so that a single message queue can + * be used with multiple writer and reader threads. + * + * A C++ epicsMessageQueue cannot be assigned to, copy-constructed, or + * constructed without giving the capacity and max-imumMessageSize + * arguments. + * + * The C++ compiler will object to some of the statements below: + * \code{.cpp} + * epicsMessageQueue mq0(); // Error: default constructor is private + * epicsMessageQueue mq1(10, 20); // OK + * epicsMessageQueue mq2(t1); // Error: copy constructor is private + * epicsMessageQueue*pmq; // OK, pointer + * *pmq = mq1; // Error: assignment operator is private + * pmq = &mq1; // OK, pointer assignment and address-of + * \endcode + **/ class epicsShareClass epicsMessageQueue { public: + + /** + * \brief Constructor. + * \param capacity Maximum number of messages to queue + * \param maximumMessageSize Number of bytes of the largest + * message that may be queued + **/ epicsMessageQueue ( unsigned int capacity, unsigned int maximumMessageSize ); + + /** + * \brief Destructor. + **/ ~epicsMessageQueue (); + + /** + * \brief Try to send a message. + * \note On VxWorks and RTEMS this method may be called from + * an interrupt handler. + * \returns 0 if the message was sent to a receiver or queued for + * future delivery. + * \returns -1 if no more messages can be queued or if the message + * is larger than the queue's maximum message size. + **/ int trySend ( void *message, unsigned int messageSize ); - int send ( void *message, unsigned int messageSize); + + /** + * \brief Send a message. + * \returns 0 if the message was sent to a receiver or queued for + * future delivery. + * \returns -1 if the message is larger than the queue's maximum + * message size. + **/ + int send ( void *message, unsigned int messageSize ); + + /** + * \brief Send a message or timeout. + * \returns 0 if the message was sent to a receiver or queued for + * future delivery. + * \returns -1 if the timeout was reached before the + * message could be sent or queued, or if the message is larger + * than the queue's maximum message size. + **/ int send ( void *message, unsigned int messageSize, double timeout ); + + /** + * \brief Try to receive a message. + * If the queue holds at least one message, + * the first message on the queue is moved to the specified location + * and the length of that message is returned. + * + * If the received message is larger than the specified message size + * the implementation may either return -1, or truncate the + * message. It is most efficient if the messageBufferSize is equal + * to the maximumMessageSize with which the message queue was + * created. + * \returns Number of bytes in the message. + * \returns -1 if the message queue is empty, or the buffer too small. + **/ int tryReceive ( void *message, unsigned int size ); + + /** + * \brief Fetch the next message on the queue. + * Wait for a message to be sent if the queue is empty, then move + * the first message queued to the specified location. + * + * If the received message is larger than the specified message size + * the implementation may either return -1, or truncate the + * message. It is most efficient if the messageBufferSize is equal + * to the maximumMessageSize with which the message queue was + * created. + * \returns Number of bytes in the message. + * \returns -1 if the buffer is too small for the message. + **/ int receive ( void *message, unsigned int size ); + + /** + * \brief Wait for a message to be queued. + * Wait up to \p timeout seconds for a message to be sent if the queue + * is empty, then move the first message to the specified location. + * + * If the received message is larger than the specified + * messageBufferSize it may either return -1, or truncate the + * message. It is most efficient if the messageBufferSize is equal + * to the maximumMessageSize with which the message queue was + * created. + * \returns Number of bytes in the message. + * \returns -1 if a message is not received within the timeout + * interval. + **/ int receive ( void *message, unsigned int size, double timeout ); + + /** + * \brief Displays some information about the message queue. + * \param level Controls the amount of information displayed. + **/ void show ( unsigned int level = 0 ); + + /** + * \brief How many messages are queued. + * \returns The number of messages presently in the queue. + **/ unsigned int pending (); -private: /* Prevent compiler-generated member functions */ - /* default constructor, copy constructor, assignment operator */ +private: + /** + * Prevent compiler-generated member functions default constructor, + * copy constructor, assignment operator. + **/ epicsMessageQueue(); epicsMessageQueue(const epicsMessageQueue &); epicsMessageQueue& operator=(const epicsMessageQueue &); @@ -52,39 +166,136 @@ private: /* Prevent compiler-generated member functions */ extern "C" { #endif /*__cplusplus */ +/** + * \brief Create a message queue. + * \param capacity Maximum number of messages to queue + * \param maximumMessageSize Number of bytes of the largest + * message that may be queued + * \return An identifier for the new queue, or 0. + **/ epicsShareFunc epicsMessageQueueId epicsShareAPI epicsMessageQueueCreate( unsigned int capacity, unsigned int maximumMessageSize); + +/** + * \brief Destroy a message queue, release all its memory. + **/ epicsShareFunc void epicsShareAPI epicsMessageQueueDestroy( epicsMessageQueueId id); + +/** + * \brief Try to send a message. + * \note On VxWorks and RTEMS this routine may be called from + * an interrupt handler. + * \returns 0 if the message was sent to a receiver or queued for + * future delivery. + * \returns -1 if no more messages can be queued or if the message + * is larger than the queue's maximum message size. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueueTrySend( epicsMessageQueueId id, void *message, unsigned int messageSize); + +/** + * \brief Send a message. + * \returns 0 if the message was sent to a receiver or queued for + * future delivery. + * \returns -1 if the message is larger than the queue's maximum + * message size. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueueSend( epicsMessageQueueId id, void *message, unsigned int messageSize); + +/** + * \brief Send a message or timeout. + * \returns 0 if the message was sent to a receiver or queued for + * future delivery. + * \returns -1 if the timeout was reached before the + * message could be sent or queued, or if the message is larger + * than the queue's maximum message size. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueueSendWithTimeout( epicsMessageQueueId id, void *message, unsigned int messageSize, double timeout); + +/** + * \brief Try to receive a message. + * + * If the queue holds at least one message, + * the first message on the queue is moved to the specified location + * and the length of that message is returned. + * + * If the received message is larger than the specified message size + * the implementation may either return -1, or truncate the + * message. It is most efficient if the messageBufferSize is equal + * to the maximumMessageSize with which the message queue was + * created. + * \returns Number of bytes in the message. + * \returns -1 if the message queue is empty, or the buffer too small. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueueTryReceive( epicsMessageQueueId id, void *message, unsigned int size); + +/** + * \brief Fetch the next message on the queue. + * + * Wait for a message to be sent if the queue is empty, then move the + * first message queued to the specified location. + * + * If the received message is larger than the specified message size + * the implementation may either return -1, or truncate the + * message. It is most efficient if the messageBufferSize is equal + * to the maximumMessageSize with which the message queue was + * created. + * \returns Number of bytes in the message. + * \returns -1 if the buffer is too small for the message. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueueReceive( epicsMessageQueueId id, void *message, unsigned int size); + +/** + * \brief Wait for a message to be queued. + * + * Wait up to \p timeout seconds for a message to be sent if the queue + * is empty, then move the first message to the specified location. + * + * If the received message is larger than the specified message buffer + * size the implementation may either return -1, or truncate the + * message. It is most efficient if the messageBufferSize is equal + * to the maximumMessageSize with which the message queue was + * created. + * \returns Number of bytes in the message. + * \returns -1 if a message is not received within the timeout + * interval. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueueReceiveWithTimeout( epicsMessageQueueId id, void *message, unsigned int size, double timeout); + +/** + * \brief How many messages are queued. + * \param id Message queue identifier. + * \returns The number of messages presently in the queue. + **/ epicsShareFunc int epicsShareAPI epicsMessageQueuePending( epicsMessageQueueId id); + +/** + * \brief Displays some information about the message queue. + * \param id Message queue identifier. + * \param level Controls the amount of information displayed. + **/ epicsShareFunc void epicsShareAPI epicsMessageQueueShow( epicsMessageQueueId id, int level); diff --git a/modules/libcom/src/osi/epicsMutex.h b/modules/libcom/src/osi/epicsMutex.h index 070efd0e4..89a3410f9 100644 --- a/modules/libcom/src/osi/epicsMutex.h +++ b/modules/libcom/src/osi/epicsMutex.h @@ -3,10 +3,34 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ + +/**\file epicsMutex.h + * + * \brief APIs for the epicsMutex mutual exclusion semaphore + * + * Mutual exclusion semaphores are for situations requiring exclusive access to + * resources. An epicsMutex may be claimed recursively, i.e. taken more than + * once by a thread, which must release it as many times as it was taken. + * Recursive usage is common for a set of routines that call each other while + * working on an exclusive resource. + * + * The typical C++ use of a mutual exclusion semaphore is: + \code + epicsMutex *plock = new epicsMutex; + ... + ... + plock->lock(); + // process resources + plock->unlock(); + \endcode + * + * \note The implementation: + * - MUST implement recursive locking + * - SHOULD implement priority inheritance and deletion safety if possible. + **/ #ifndef epicsMutexh #define epicsMutexh @@ -14,9 +38,14 @@ #include "shareLib.h" +/**\brief An identifier for an epicsMutex for use with the C API */ typedef struct epicsMutexParm *epicsMutexId; + +/** Return status from some C API routines. */ typedef enum { - epicsMutexLockOK,epicsMutexLockTimeout,epicsMutexLockError + epicsMutexLockOK = 0, + epicsMutexLockTimeout, + epicsMutexLockError } epicsMutexLockStatus; #ifdef __cplusplus @@ -24,31 +53,82 @@ typedef enum { #include "compilerDependencies.h" #include "epicsGuard.h" +/**\brief Create a C++ epicsMutex with current filename and line number + */ #define newEpicsMutex new epicsMutex(__FILE__,__LINE__) +/**\brief The C++ API for an epicsMutex. + */ class epicsShareClass epicsMutex { public: typedef epicsGuard guard_t; typedef epicsGuard release_t; class mutexCreateFailed; /* exception payload */ class invalidMutex; /* exception payload */ + #if !defined(__GNUC__) || __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<8) + /**\brief Create a mutual exclusion semaphore. + **/ epicsMutex (); + + /**\brief Create a mutual exclusion semaphore with source location. + * + * \note The newEpicsMutex macro simplifies using this constructor. + * \param *pFileName Source file name. + * \param lineno Source line number + **/ epicsMutex ( const char *pFileName, int lineno ); #else + /**\brief Create a mutual exclusion semaphore. + * \param *pFileName Source file name. + * \param lineno Source line number + **/ epicsMutex ( const char *pFileName = __builtin_FILE(), int lineno = __builtin_LINE() ); #endif + + /**\brief Delete the semaphore and its resources. + **/ ~epicsMutex (); + + /**\brief Display information about the semaphore. + * + * \note Results are architecture dependant. + * + * \param level Desired information level to report + **/ void show ( unsigned level ) const; - void lock (); /* blocks until success */ + + /**\brief Claim the semaphore, waiting until it's free if currently owned + * owned by a different thread. + * + * This call blocks until the calling thread can get exclusive access to + * the semaphore. + * \note After a successful lock(), additional recursive locks may be + * issued by the same thread, but each must have an associated unlock(). + **/ + void lock (); + + /**\brief Release the semaphore. + * + * \note If a thread issues recursive locks, it must call unlock() as many + * times as it calls lock(). + **/ void unlock (); - bool tryLock (); /* true if successful */ + + /**\brief Similar to lock() except that the call returns immediately if the + * semaphore is currently owned by another thread, giving the value false. + * + * \return True if the resource is now owned by the caller. + * \return False if some other thread already owns the resource. + **/ + bool tryLock (); private: epicsMutexId id; epicsMutex ( const epicsMutex & ); epicsMutex & operator = ( const epicsMutex & ); }; +/**\brief A semaphore for locating deadlocks in C++ code. */ class epicsShareClass epicsDeadlockDetectMutex { public: typedef epicsGuard guard_t; @@ -74,36 +154,96 @@ private: extern "C" { #endif /*__cplusplus*/ +/**\brief Create an epicsMutex semaphore for use from C code. + * + * This macro stores the source location of the creation call in the mutex. + * \return An identifier for the mutex, or NULL if one could not be created. + **/ #define epicsMutexCreate() epicsMutexOsiCreate(__FILE__,__LINE__) +/**\brief Internal API, used by epicsMutexCreate(). */ epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiCreate( const char *pFileName,int lineno); + +/**\brief Create an epicsMutex semaphore for use from C code. + * + * This macro stores the source location of the creation call in the mutex. + * The routine does not return if the object could not be created. + * \return An identifier for the mutex. + **/ #define epicsMutexMustCreate() epicsMutexOsiMustCreate(__FILE__,__LINE__) +/**\brief Internal API, used by epicsMutexMustCreate(). */ epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiMustCreate( const char *pFileName,int lineno); + +/**\brief Destroy an epicsMutex semaphore. + * \param id The mutex identifier. + **/ epicsShareFunc void epicsShareAPI epicsMutexDestroy(epicsMutexId id); + +/**\brief Release the semaphore. + * \param id The mutex identifier. + * \note If a thread issues recursive locks, it must call epicsMutexUnlock() + * as many times as it calls epicsMutexLock() or equivalents. + **/ epicsShareFunc void epicsShareAPI epicsMutexUnlock(epicsMutexId id); + +/**\brief Claim the semaphore, waiting until it's free if currently owned + * owned by a different thread. + * + * This call blocks until the calling thread can get exclusive access to + * the semaphore. + * \note After a successful lock(), additional recursive locks may be + * issued by the same thread, but each must have an associated unlock(). + * \param id The mutex identifier. + * \return Status indicator. + **/ epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLock( epicsMutexId id); + +/**\brief Claim a semaphore (see epicsMutexLock()). + * + * This routine does not return if the identifier is invalid. + * \param ID The mutex identifier. + **/ #define epicsMutexMustLock(ID) { \ epicsMutexLockStatus status = epicsMutexLock(ID); \ assert(status == epicsMutexLockOK); \ } + +/**\brief Similar to epicsMutexLock() except that the call returns immediately, + * with the return status indicating if the semaphore is currently owned by + * this thread or another thread. + * + * \return \c epicsMutexLockOK if the resource is now owned by the caller. + * \return \c epicsMutexLockTimeout if some other thread owns the resource. + **/ epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexTryLock( epicsMutexId id); + +/**\brief Display information about the semaphore. + * + * \note Results are architecture dependant. + * + * \param id The mutex identifier. + * \param level Desired information level to report + **/ epicsShareFunc void epicsShareAPI epicsMutexShow( epicsMutexId id,unsigned int level); + +/**\brief Display information about all epicsMutex semaphores. + * + * \note Results are architecture dependant. + * + * \param onlyLocked Non-zero to show only locked semaphores. + * \param level Desired information level to report + **/ epicsShareFunc void epicsShareAPI epicsMutexShowAll( int onlyLocked,unsigned int level); -/*NOTES: - epicsMutex MUST implement recursive locking - epicsMutex should implement priority inheritance and deletion safe -*/ - -/* - * The following is the interface to the OS dependent - * implementation and should NOT be called directly by - * user code +/**@privatesection + * The following are interfaces to the OS dependent + * implementation and should NOT be called directly by + * user code. */ struct epicsMutexOSD * epicsMutexOsdCreate(void); void epicsMutexOsdDestroy(struct epicsMutexOSD *); diff --git a/modules/libcom/src/osi/epicsReadline.h b/modules/libcom/src/osi/epicsReadline.h index 1d0e8b761..78c233119 100644 --- a/modules/libcom/src/osi/epicsReadline.h +++ b/modules/libcom/src/osi/epicsReadline.h @@ -6,6 +6,16 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ + +/** + * \file epicsReadline.h + * \brief Command-line editing functions + * \author Eric Norum + * + * Provides a generalized API for command line history and line-editing. + * The implementation of this API can call GNU Readline, libtecla, and on + * VxWorks the ledLib routines, according to the EPICS build configuration. + */ #ifndef INC_epicsReadline_H #define INC_epicsReadline_H @@ -15,9 +25,23 @@ extern "C" { #include #include - +/** + * \brief Create a command-line context + * \param in Filehandle to read from + * \return Command-line context + */ epicsShareFunc void * epicsShareAPI epicsReadlineBegin (FILE *in); +/** + * \brief Read a line of input + * \param prompt Prompt string + * \param context To read from + * \return Line read + */ epicsShareFunc char * epicsShareAPI epicsReadline (const char *prompt, void *context); +/** + * \brief Destroy a command-line context + * \param context Command-line context to destroy + */ epicsShareFunc void epicsShareAPI epicsReadlineEnd (void *context); #ifdef __cplusplus diff --git a/modules/libcom/src/osi/epicsSignal.h b/modules/libcom/src/osi/epicsSignal.h index 79adf71d1..f976ee040 100644 --- a/modules/libcom/src/osi/epicsSignal.h +++ b/modules/libcom/src/osi/epicsSignal.h @@ -16,30 +16,33 @@ extern "C" { #include "shareLib.h" -/* +/** \file epicsSignal.h + * \brief OS-independent routines for ignoring Posix signals + * * The requests in this interface are typically ignored on OS that do not implement * POSIX signals. */ struct epicsThreadOSD; -/* +/** Ignore the SIGHUP signal. * Required to avoid problems with soft IOCs getting SIGHUPs when a * Channel Access client disconnects */ epicsShareFunc void epicsShareAPI epicsSignalInstallSigHupIgnore ( void ); -/* +/** Ignore the SIGPIPE signal. * Required to avoid terminating a process which is blocking in a * socket send() call when the SIGPIPE signal is generated by the OS. */ epicsShareFunc void epicsShareAPI epicsSignalInstallSigPipeIgnore ( void ); -/* - * required only if shutdown() and close() do not interrupt a thread blocking in +/** Ignore the SIGALRM signal. + * Required only if shutdown() and close() do not interrupt a thread blocking in * a socket system call */ epicsShareFunc void epicsShareAPI epicsSignalInstallSigAlarmIgnore ( void ); +/** Raise a SIGALRM signal to a specific epicsThread */ epicsShareFunc void epicsShareAPI epicsSignalRaiseSigAlarm ( struct epicsThreadOSD * ); #ifdef __cplusplus diff --git a/modules/libcom/src/osi/epicsTempFile.h b/modules/libcom/src/osi/epicsTempFile.h index e20879d04..210e69740 100644 --- a/modules/libcom/src/osi/epicsTempFile.h +++ b/modules/libcom/src/osi/epicsTempFile.h @@ -4,10 +4,13 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* epicsTempFile.h */ +/** + * \file epicsTempFile.h + * \brief OS-independent way to create temporary files. + **/ #ifndef INC_epicsTempFile_H #define INC_epicsTempFile_H @@ -20,6 +23,10 @@ extern "C" { #endif +/** + * \brief Create and open a temporary file. + * \return NULL or a FILE pointer to a temporary file. + **/ epicsShareFunc FILE * epicsShareAPI epicsTempFile(void); #ifdef __cplusplus diff --git a/modules/libcom/src/osi/epicsThread.h b/modules/libcom/src/osi/epicsThread.h index da16a0b25..b25c3cd7c 100644 --- a/modules/libcom/src/osi/epicsThread.h +++ b/modules/libcom/src/osi/epicsThread.h @@ -5,8 +5,53 @@ * Operator of Los Alamos National Laboratory. * Copyright (c) 2013 ITER Organization. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ + +/** + * \file epicsThread.h + * + * \brief C++ and C descriptions for a thread. + * + * The epicsThread API is meant as a somewhat minimal interface for + * multithreaded applications. It can be implementedon a wide variety of + * systems with the restriction that the system MUST support a + * multithreaded environment. + * A POSIX pthreads version is provided. + * + * The interface provides the following thread facilities, + * with restrictions as noted: + * - Life cycle: a thread starts life as a result of a call to + * epicsThreadCreate. It terminates when the thread function returns. + * It should not return until it has released all resources it uses. + * If a thread is expected to terminate as a natural part of its life + * cycle then the thread function must return. + * - epicsThreadOnce: this provides the ability to have an + * initialization function that is guaranteed to be called exactly + * once. + * - main: if a main routine finishes its work but wants to leave other + * threads running it can call epicsThreadExitMain, which should be + * the last statement in main. + * - Priorities: ranges between 0 and 99 with a higher number meaning + * higher priority. A number of constants are defined for iocCore + * specific threads. The underlying implementation may collapse the + * range 0 to 99 into a smaller range; even a single priority. User + * code should never rely on the existence of multiple thread + * priorities to guarantee correct behavior. + * - Stack Size: epicsThreadCreate accepts a stack size parameter. Three + * generic sizes are available: small, medium,and large. Portable code + * should always use one of the generic sizes. Some implementation may + * ignore the stack size request and use a system default instead. + * Virtual memory systems providing generous stack sizes can be + * expected to use the system default. + * - epicsThreadId: every epicsThread has an Id which gets returned by + * epicsThreadCreate and is valid as long as that thread still exists. + * A value of 0 always means no thread. If a threadId is used after + * the thread has terminated,the results are not defined (but will + * normally lead to bad things happening). Thus code that looks after + * other threads MUST be aware of threads terminating. + */ + #ifndef epicsThreadh #define epicsThreadh @@ -20,6 +65,9 @@ extern "C" { typedef void (*EPICSTHREADFUNC)(void *parm); +/** @name Some Named Thread Priorities + * @{ + */ #define epicsThreadPriorityMax 99 #define epicsThreadPriorityMin 0 @@ -35,8 +83,9 @@ typedef void (*EPICSTHREADFUNC)(void *parm); #define epicsThreadPriorityScanHigh 70 #define epicsThreadPriorityIocsh 91 #define epicsThreadPriorityBaseMax 91 +/** @} */ -/* stack sizes for each stackSizeClass are implementation and CPU dependent */ +/** Stack sizes for each stackSizeClass are implementation and CPU dependent. */ typedef enum { epicsThreadStackSmall, epicsThreadStackMedium, epicsThreadStackBig } epicsThreadStackSizeClass; @@ -45,11 +94,15 @@ typedef enum { epicsThreadBooleanStatusFail, epicsThreadBooleanStatusSuccess } epicsThreadBooleanStatus; -/** Lookup target specific default stack size */ +/** + * Get a stack size value that can be given to epicsThreadCreate(). + * \param size one of the values epicsThreadStackSmall, + * epicsThreadStackMedium or epicsThreadStackBig. + **/ epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize( epicsThreadStackSizeClass size); -/* (epicsThreadId)0 is guaranteed to be an invalid thread id */ +/** (epicsThreadId)0 is guaranteed to be an invalid thread id */ typedef struct epicsThreadOSD *epicsThreadId; typedef epicsThreadId epicsThreadOnceId; @@ -57,27 +110,38 @@ typedef epicsThreadId epicsThreadOnceId; /** Perform one-time initialization. * - * Run the provided function if it has not run, and is not running. + * Run the provided function if it has not run, and is not running in + * some other thread. * - * @post The provided function has been run. + * For each unique epicsThreadOnceId, epicsThreadOnce guarantees that + * -# myInitFunc will only be called only once. + * -# myInitFunc will have returned before any other epicsThreadOnce + * call using the same epicsThreadOnceId returns. * - * @code + * \code * static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT; * static void myInitFunc(void *arg) { ... } * static void some Function(void) { * epicsThreadOnce(&onceId, &myInitFunc, NULL); * } - * @endcode + * \endcode */ epicsShareFunc void epicsShareAPI epicsThreadOnce( epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg); -/* When real-time scheduling is active, attempt any post-init operations +/** + * When real-time scheduling is active, attempt any post-init operations * that preserve real-time performance. For POSIX targets this locks the * process into RAM, preventing swap-related VM faults. - */ + **/ epicsShareFunc void epicsThreadRealtimeLock(void); +/** + * If the main routine is done but wants to let other threads run it can + * call this routine. This should be the last call in main, except the + * final return. On most systems epicsThreadExitMain never returns.This + * must only be called by the main thread. + **/ epicsShareFunc void epicsShareAPI epicsThreadExitMain(void); /** For use with epicsThreadCreateOpt() */ @@ -103,12 +167,12 @@ typedef struct epicsThreadOpts { #define EPICS_THREAD_OPTS_INIT { \ epicsThreadPriorityLow, epicsThreadStackMedium, 0} -/** @brief Allocate and start a new OS thread. - * @param name A name describing this thread. Appears in various log and error message. - * @param funptr The thread main function. - * @param parm Passed to thread main function. - * @param opts Modifiers for the new thread, or NULL to use target specific defaults. - * @return NULL on error +/** \brief Allocate and start a new OS thread. + * \param name A name describing this thread. Appears in various log and error message. + * \param funptr The thread main function. + * \param parm Passed to thread main function. + * \param opts Modifiers for the new thread, or NULL to use target specific defaults. + * \return NULL on error */ epicsShareFunc epicsThreadId epicsThreadCreateOpt ( const char * name, @@ -156,16 +220,20 @@ epicsShareFunc epicsThreadBooleanStatus epicsShareAPI /** Test if two thread IDs actually refer to the same OS thread */ epicsShareFunc int epicsShareAPI epicsThreadIsEqual( epicsThreadId id1, epicsThreadId id2); -/** Test if thread has been suspended with epicsThreadSuspendSelf() */ +/** How and why a thread can be suspended is implementation dependent. A + * thread calling epicsThreadSuspendSelf() should result in this routine + * returning true for that thread, but a thread may also be suspended + * for other reasons. + **/ epicsShareFunc int epicsShareAPI epicsThreadIsSuspended(epicsThreadId id); -/** @brief Block the calling thread for at least the specified time. - * @param seconds Time to wait in seconds. Values <=0 blocks for the shortest possible time. +/** \brief Block the calling thread for at least the specified time. + * \param seconds Time to wait in seconds. Values <=0 blocks for the shortest possible time. */ epicsShareFunc void epicsShareAPI epicsThreadSleep(double seconds); -/** @brief Query a value approximating the OS timer/scheduler resolution. - * @return A value in seconds >=0 +/** \brief Query a value approximating the OS timer/scheduler resolution. + * \return A value in seconds >=0 * - * @warning On targets other than vxWorks and RTEMS, the quantum value often isn't + * \warning On targets other than vxWorks and RTEMS, the quantum value often isn't * meaningful. Use of this function is discouraged in portable code. */ epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum(void); @@ -174,23 +242,23 @@ epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum(void); */ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf(void); /** Attempt to find the first instance of a thread by name. - * @return An epicsThreadId, or NULL if no such thread is currently running. + * \return An epicsThreadId, or NULL if no such thread is currently running. * Note that a non-NULL ID may still be invalid if this call races * with thread exit. * - * @warning Safe use of this function requires external knowledge that this + * \warning Safe use of this function requires external knowledge that this * thread will not return. */ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetId(const char *name); /** Return a value approximating the number of threads which this target * can run in parallel. This value is advisory. - * @return >=1 + * \return >=1 */ epicsShareFunc int epicsThreadGetCPUs(void); /** Return the name of the current thread. * - * @return Never NULL. Storage lifetime tied to epicsThreadId. + * \return Never NULL. Storage lifetime tied to epicsThreadId. * * This is either a copy of the string passed to epicsThread*Create*(), * or an arbitrary unique string for non-EPICS threads. @@ -206,22 +274,54 @@ epicsShareFunc const char * epicsShareAPI epicsThreadGetNameSelf(void); epicsShareFunc void epicsShareAPI epicsThreadGetName( epicsThreadId id, char *name, size_t size); +/** + * Is it OK for a thread to block? This can be called by support code + * that does not know if it is called in a thread that should not block. + * For example the errlog system calls this to decide when messages + * should be displayed on the console. + **/ epicsShareFunc int epicsShareAPI epicsThreadIsOkToBlock(void); +/** + * When a thread is started the default is that it is not allowed to + * block. This method can be called to change the state. For example + * iocsh calls this to specify that it is OK to block. + **/ epicsShareFunc void epicsShareAPI epicsThreadSetOkToBlock(int isOkToBlock); /** Print to stdout information about all running EPICS threads. - * @param level 0 prints minimal output. Higher values print more details. + * \param level 0 prints minimal output. Higher values print more details. */ epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level); /** Print info about a single EPICS thread. */ epicsShareFunc void epicsShareAPI epicsThreadShow( epicsThreadId id,unsigned int level); -/* Hooks called when a thread starts, map function called once for every thread */ +/** + * Hooks called when a thread starts, map function called once for every thread. + **/ typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id); + +/** + * Register a routine to be called by every new thread before the thread + * function gets run. Hook routines will often register a thread exit + * routine with epicsAtThreadExit() to release thread-specific resources + * they have allocated. + */ epicsShareFunc int epicsThreadHookAdd(EPICS_THREAD_HOOK_ROUTINE hook); + +/** + * Remove routine from the list of hooks run at thread creation time. + **/ epicsShareFunc int epicsThreadHookDelete(EPICS_THREAD_HOOK_ROUTINE hook); + +/** + * Print the current list of hook function pointers. + **/ epicsShareFunc void epicsThreadHooksShow(void); + +/** + * Call func once for every known thread. + **/ epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func); /** Thread local storage */ @@ -260,18 +360,18 @@ public: extern "C" void epicsThreadCallEntryPoint ( void * ); -/** @brief An OS thread +/** \brief An OS thread * * A wrapper around the epicsThread* C API. * - * @note Threads must be start() ed. + * \note Threads must be start() ed. */ class epicsShareClass epicsThread { public: /** Create a new thread with the provided information. * * cf. epicsThreadOpts - * @note Threads must be start() ed. + * \note Threads must be start() ed. * @throws epicsThread::unableToCreateThread on error. */ epicsThread ( epicsThreadRunable &,const char *name, unsigned int stackSize, @@ -282,11 +382,11 @@ public: //! Wait for the thread epicsRunnable::run() to return. void exitWait () throw (); //! Wait for the thread epicsRunnable::run() to return. - //! @param delay Wait up to this many seconds. - //! @returns true if run() returned. false on timeout. + //! \param delay Wait up to this many seconds. + //! \return true if run() returned. false on timeout. bool exitWait ( const double delay ) throw (); //! @throws A special exitException which will be caught and ignored. - //! @note This exitException doesn't not derive from std::exception + //! \note This exitException doesn't not derive from std::exception static void exit (); //! cf. epicsThreadResume() void resume () throw (); @@ -300,7 +400,7 @@ public: void setPriority ( unsigned int ) throw (); bool priorityIsEqual ( const epicsThread & ) const throw (); bool isSuspended () const throw (); - //! @return true if call through this thread's epicsRunnable::run() + //! \return true if call through this thread's epicsRunnable::run() bool isCurrentThread () const throw (); bool operator == ( const epicsThread & ) const throw (); //! Say something interesting about this thread to stdout. @@ -331,7 +431,7 @@ private: epicsThread ( const epicsThread & ); epicsThread & operator = ( const epicsThread & ); friend void epicsThreadCallEntryPoint ( void * ); - void printLastChanceExceptionMessage ( + void printLastChanceExceptionMessage ( const char * pExceptionTypeName, const char * pExceptionContext ); /* exceptions */ @@ -346,7 +446,7 @@ protected: }; template < class T > -class epicsThreadPrivate : +class epicsThreadPrivate : private epicsThreadPrivateBase { public: epicsThreadPrivate (); diff --git a/modules/libcom/src/osi/epicsTime.h b/modules/libcom/src/osi/epicsTime.h index e9ec71aaf..579d08adc 100644 --- a/modules/libcom/src/osi/epicsTime.h +++ b/modules/libcom/src/osi/epicsTime.h @@ -4,10 +4,13 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* epicsTime.h */ -/* Author Jeffrey O. Hill */ +/** \file epicsTime.h + * \brief EPICS time-stamps (epicsTimeStamp), epicsTime C++ class + * and C functions for handling wall-clock times. + * \author Jeffrey O. Hill + */ #ifndef epicsTimehInclude #define epicsTimehInclude @@ -19,139 +22,294 @@ #include "osdTime.h" #include "errMdef.h" -/* The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC */ +/** \brief The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC */ #define POSIX_TIME_AT_EPICS_EPOCH 631152000u -/* epics time stamp for C interface*/ +/** \brief EPICS time stamp, for use from C code. + * + * Because it uses an unsigned 32-bit integer to hold the seconds count, an + * epicsTimeStamp can safely represent time stamps until the year 2106. + */ typedef struct epicsTimeStamp { - epicsUInt32 secPastEpoch; /* seconds since 0000 Jan 1, 1990 */ - epicsUInt32 nsec; /* nanoseconds within second */ + epicsUInt32 secPastEpoch; /**< \brief seconds since 0000 Jan 1, 1990 */ + epicsUInt32 nsec; /**< \brief nanoseconds within second */ } epicsTimeStamp; -/*TS_STAMP is deprecated */ +/** \brief Old time-stamp data type, deprecated. + * \deprecated TS_STAMP was provided for compatibility with Base-3.13 code. + * It will be removed in some future release of EPICS 7. + */ #define TS_STAMP epicsTimeStamp +/** \struct timespec + * \brief Defined by POSIX Real Time + * + * This is defined by POSIX Real Time. It requires two mandatory fields: + * \li time_t tv_sec - Number of seconds since 1970 (The POSIX epoch) + * \li long tv_nsec - nanoseconds within a second + */ struct timespec; /* POSIX real time */ + +/** \struct timeval + * \brief BSD and SRV5 Unix timestamp + * + * BSD and SRV5 Unix timestamp. It has two fields: + * \li time_t tv_sec - Number of seconds since 1970 (The POSIX epoch) + * \li time_t tv_nsec - nanoseconds within a second + */ struct timeval; /* BSD */ + +/** \struct l_fp + * \brief Network Time Protocol timestamp + * + * Network Time Protocol timestamp. The fields are: + * \li \c lui - Number of seconds since 1900 (The NTP epoch) + * \li \c luf - Fraction of a second. For example 0x800000000 represents 1/2 second. + */ struct l_fp; /* NTP timestamp */ #ifdef __cplusplus -/* - * extend ANSI C RTL "struct tm" to include nano seconds within a second - * and a struct tm that is adjusted for the local timezone +/** \brief C++ only ANSI C struct tm with nanoseconds, local timezone + * + * Extend ANSI C "struct tm" to include nano seconds within a second + * and a struct tm that is adjusted for the local timezone. */ struct local_tm_nano_sec { - struct tm ansi_tm; /* ANSI C time details */ - unsigned long nSec; /* nano seconds extension */ + struct tm ansi_tm; /**< \brief ANSI C time details */ + unsigned long nSec; /**< \brief nanoseconds extension */ }; -/* - * extend ANSI C RTL "struct tm" to includes nano seconds within a second - * and a struct tm that is adjusted for GMT (UTC) +/** \brief C++ only ANSI C sruct tm with nanoseconds, UTC + * + * Extend ANSI C "struct tm" to include nanoseconds within a second + * and a struct tm that is adjusted for GMT (UTC). */ struct gm_tm_nano_sec { - struct tm ansi_tm; /* ANSI C time details */ - unsigned long nSec; /* nano seconds extension */ + struct tm ansi_tm; /**< \brief ANSI C time details */ + unsigned long nSec; /**< \brief nanoseconds extension */ }; -/* - * wrapping this in a struct allows conversion to and - * from ANSI time_t but does not allow unexpected - * conversions to occur +/** \brief C++ only ANSI C time_t + * + * This is for converting to/from the ANSI C \c time_t. Since \c time_t + * is usually an elementary type providing a conversion operator from + * \c time_t to/from epicsTime could cause undesirable implicit + * conversions. Providing a conversion operator to/from the + * \c time_t_wrapper instead prevents implicit conversions. */ struct time_t_wrapper { time_t ts; }; +/** \brief C++ Event number wrapper class + * + * Stores an event number for use by the epicsTime::getEvent() static + * class method. + */ class epicsShareClass epicsTimeEvent { public: - epicsTimeEvent (const int &number); - operator int () const; + epicsTimeEvent (const int &number); /**< \brief Constructor */ + operator int () const; /**< \brief Extractor */ private: int eventNumber; }; - + +/** \brief C++ time stamp object + * + * Holds an EPICS time stamp, and provides conversion functions for both + * input and output from/to other types. + * + * \note Time conversions: The epicsTime implementation will properly + * convert between the various formats from the beginning of the EPICS + * epoch until at least 2038. Unless the underlying architecture support + * has defective POSIX, BSD/SRV5, or standard C time support the EPICS + * implementation should be valid until 2106. + */ class epicsShareClass epicsTime { public: - /* exceptions */ + /// \brief Exception: Time provider problem class unableToFetchCurrentTime {}; + /// \brief Exception: Bad field(s) in struct tm class formatProblemWithStructTM {}; + /** \brief The default constructor sets the time to the EPICS epoch. */ epicsTime (); + /** \brief Get time of event system event. + * + * Returns an epicsTime indicating when the associated event system + * event last occurred. + */ static epicsTime getEvent ( const epicsTimeEvent & ); + /** \brief Get current clock time + * + * Returns an epicsTime containing the current time. For example: + * \code{.cpp} + * epicsTime now = epicsTime::getCurrent(); + * \endcode + */ static epicsTime getCurrent (); + /** \brief Get current monotonic time + * + * Returns an epicsTime containing the current monotonic time, a + * high-resolution OS clock that counts at a steady rate, never + * going backwards or jumping forwards. This time is only useful + * for measuring time differences. + */ static epicsTime getMonotonic (); - /* convert to and from EPICS epicsTimeStamp format */ + /** \name epicsTimeStamp conversions + * Convert to and from EPICS epicsTimeStamp format + * @{ */ + /** \brief Convert to epicsTimeStamp */ operator epicsTimeStamp () const; + /** \brief Construct from epicsTimeStamp */ epicsTime ( const epicsTimeStamp & ts ); + /** \brief Assign from epicsTimeStamp */ epicsTime & operator = ( const epicsTimeStamp & ); + /** @} */ - /* convert to and from ANSI time_t */ + /** \name ANSI C time_t conversions + * Convert to and from ANSI C \c time_t wrapper . + * @{ */ + /** \brief Convert to ANSI C \c time_t */ operator time_t_wrapper () const; + /** \brief Construct from ANSI C \c time_t */ epicsTime ( const time_t_wrapper & ); + /** \brief Assign from ANSI C \c time_t */ epicsTime & operator = ( const time_t_wrapper & ); + /** @} */ - /* - * convert to and from ANSI Cs "struct tm" (with nano seconds) - * adjusted for the local time zone - */ + /** \name ANSI C struct tm local-time conversions + * Convert to and from ANSI Cs struct tm (with nano seconds), + * adjusted for the local time zone. + * @{ */ + /** \brief Convert to struct tm in local time zone */ operator local_tm_nano_sec () const; + /** \brief Construct from struct tm in local time zone */ epicsTime ( const local_tm_nano_sec & ); + /** \brief Assign from struct tm in local time zone */ epicsTime & operator = ( const local_tm_nano_sec & ); + /** @} */ - /* - * convert to and from ANSI Cs "struct tm" (with nano seconds) - * adjusted for GM time (UTC) - */ + /** \name ANSI C struct tm UTC conversions + * Convert to and from ANSI Cs struct tm (with nano seconds), + * adjusted for Greenwich Mean Time (UTC). + * @{ */ + /** \brief Convert to struct tm in UTC/GMT */ operator gm_tm_nano_sec () const; + /** \brief Construct from struct tm in UTC/GMT */ epicsTime ( const gm_tm_nano_sec & ); + /** \brief Assign from struct tm in UTC */ epicsTime & operator = ( const gm_tm_nano_sec & ); + /** @} */ - /* convert to and from POSIX RTs "struct timespec" */ + /** \name POSIX RT struct timespec conversions + * Convert to and from the POSIX RealTime struct timespec + * format. + * @{ */ + /** \brief Convert to struct timespec */ operator struct timespec () const; + /** \brief Construct from struct timespec */ epicsTime ( const struct timespec & ); + /** \brief Assign from struct timespec */ epicsTime & operator = ( const struct timespec & ); + /** @} */ - /* convert to and from BSDs "struct timeval" */ + /** \name BSD's struct timeval conversions + * Convert to and from the BSD struct timeval format. + * @{ */ + /** \brief Convert to struct timeval */ operator struct timeval () const; + /** \brief Construct from struct timeval */ epicsTime ( const struct timeval & ); + /** \brief Assign from struct timeval */ epicsTime & operator = ( const struct timeval & ); + /** @} */ - /* convert to and from NTP timestamp format */ + /** \name NTP timestamp conversions + * Convert to and from the NTP timestamp structure \c l_fp + * @{ */ + /** \brief Convert to NTP format */ operator l_fp () const; + /** \brief Construct from NTP format */ epicsTime ( const l_fp & ); + /** \brief Assign from NTP format */ epicsTime & operator = ( const l_fp & ); + /** @} */ - /* convert to and from WIN32s FILETIME (implemented only on WIN32) */ + /** \name WIN32 FILETIME conversions + * Convert to and from WIN32s _FILETIME + * \note These are only implemented on Windows targets. + * @{ */ + /** \brief Convert to Windows struct _FILETIME */ operator struct _FILETIME () const; + /** \brief Constuct from Windows struct _FILETIME */ epicsTime ( const struct _FILETIME & ); + /** \brief Assign from Windows struct _FILETIME */ epicsTime & operator = ( const struct _FILETIME & ); + /** @} */ - /* arithmetic operators */ - double operator- ( const epicsTime & ) const; /* returns seconds */ - epicsTime operator+ ( const double & ) const; /* add rhs seconds */ - epicsTime operator- ( const double & ) const; /* subtract rhs seconds */ - epicsTime operator+= ( const double & ); /* add rhs seconds */ - epicsTime operator-= ( const double & ); /* subtract rhs seconds */ + /** \name Arithmetic operators + * Standard operators involving epicsTime objects and time differences + * which are always expressed as a \c double in seconds. + * @{ */ + /// \brief \p lhs minus \p rhs, in seconds + double operator- ( const epicsTime & ) const; + /// \brief \p lhs plus rhs seconds + epicsTime operator+ ( const double & ) const; + /// \brief \p lhs minus rhs seconds + epicsTime operator- ( const double & ) const; + /// \brief add rhs seconds to \p lhs + epicsTime operator+= ( const double & ); + /// \brief subtract rhs seconds from \p lhs + epicsTime operator-= ( const double & ); + /** @} */ - /* comparison operators */ - bool operator == ( const epicsTime & ) const; - bool operator != ( const epicsTime & ) const; - bool operator <= ( const epicsTime & ) const; - bool operator < ( const epicsTime & ) const; - bool operator >= ( const epicsTime & ) const; - bool operator > ( const epicsTime & ) const; + /** \name Comparison operators + * Standard comparisons between epicsTime objects. + * @{ */ + /// \brief \p lhs equals \p rhs + bool operator == ( const epicsTime & ) const; + /// \brief \p lhs not equal to \p rhs + bool operator != ( const epicsTime & ) const; + /// \brief \p rhs no later than \p lhs + bool operator <= ( const epicsTime & ) const; + /// \brief \p lhs was before \p rhs + bool operator < ( const epicsTime & ) const; + /// \brief \p rhs not before \p lhs + bool operator >= ( const epicsTime & ) const; + /// \brief \p lhs was after \p rhs + bool operator > ( const epicsTime & ) const; + /** @} */ - /* convert current state to user-specified string */ + /** \brief Convert to string in user-specified format + * + * This method extends the standard C library routine strftime(). + * See your OS documentation for details about the standard routine. + * The epicsTime method adds support for printing the fractional + * portion of the time. It searches the format string for the + * sequence %0nf where \a n is the desired precision, + * and uses this format to convert the fractional seconds with the + * requested precision. For example: + * \code{.cpp} + * epicsTime time = epicsTime::getCurrent(); + * char buf[30]; + * time.strftime(buf, 30, "%Y-%m-%d %H:%M:%S.%06f"); + * printf("%s\n", buf); + * \endcode + * This will print the current time in the format: + * \code + * 2001-01-26 20:50:29.813505 + * \endcode + */ size_t strftime ( char * pBuff, size_t bufLength, const char * pFormat ) const; - /* dump current state to standard out */ + /** \brief Dump current state to standard out */ void show ( unsigned interestLevel ) const; private: @@ -173,98 +331,179 @@ private: extern "C" { #endif /* __cplusplus */ -/* epicsTime routines return S_time_ error status values */ +/** \name Return status values + * epicsTime routines return \c S_time_ error status values: + * @{ + */ +/** \brief Success */ #define epicsTimeOK 0 +/** \brief No time provider */ #define S_time_noProvider (M_time| 1) /*No time provider*/ +/** \brief Bad event number */ #define S_time_badEvent (M_time| 2) /*Bad event number*/ +/** \brief Invalid arguments */ #define S_time_badArgs (M_time| 3) /*Invalid arguments*/ +/** \brief Out of memory */ #define S_time_noMemory (M_time| 4) /*Out of memory*/ +/** \brief Provider not synchronized */ #define S_time_unsynchronized (M_time| 5) /*Provider not synchronized*/ -#define S_time_timezone (M_time| 6) /*Invalid timeone*/ +/** \brief Invalid timezone */ +#define S_time_timezone (M_time| 6) /*Invalid timezone*/ +/** \brief Time conversion error */ #define S_time_conversion (M_time| 7) /*Time conversion error*/ +/** @} */ -/*Some special values for eventNumber*/ +/** \name epicsTimeEvent numbers + * Some special values for eventNumber: + * @{ + */ #define epicsTimeEventCurrentTime 0 #define epicsTimeEventBestTime -1 #define epicsTimeEventDeviceTime -2 +/** @} */ -/* These are implemented in the "generalTime" framework */ +/** \name generalTime functions + * These are implemented in the "generalTime" framework: + * @{ + */ +/** \brief Get current time into \p *pDest */ epicsShareFunc int epicsShareAPI epicsTimeGetCurrent ( epicsTimeStamp * pDest ); +/** \brief Get time of event \p eventNumber into \p *pDest */ epicsShareFunc int epicsShareAPI epicsTimeGetEvent ( epicsTimeStamp *pDest, int eventNumber); +/** \brief Get monotonic time into \p *pDest */ epicsShareFunc int epicsTimeGetMonotonic ( epicsTimeStamp * pDest ); +/** @} */ -/* These are callable from an Interrupt Service Routine */ +/** \name ISR-callable + * These routines may be called from an Interrupt Service Routine, and + * will return a value from the last current time or event time provider + * that sucessfully returned a result from the equivalent non-ISR routine. + * @{ + */ +/** \brief Get current time into \p *pDest (ISR-safe) */ epicsShareFunc int epicsTimeGetCurrentInt(epicsTimeStamp *pDest); +/** \brief Get time of event \p eventNumber into \p *pDest (ISR-safe) */ epicsShareFunc int epicsTimeGetEventInt(epicsTimeStamp *pDest, int eventNumber); +/** @} */ -/* convert to and from ANSI C's "time_t" */ +/** \name ANSI C time_t conversions + * Convert to and from ANSI C \c time_t + * @{ + */ +/** \brief Convert epicsTimeStamp to ANSI C \c time_t */ epicsShareFunc int epicsShareAPI epicsTimeToTime_t ( time_t * pDest, const epicsTimeStamp * pSrc ); +/** \brief Convert ANSI C \c time_t to epicsTimeStamp */ epicsShareFunc int epicsShareAPI epicsTimeFromTime_t ( epicsTimeStamp * pDest, time_t src ); +/** @} */ -/* convert to and from ANSI C's "struct tm" with nano seconds */ +/** \name ANSI C struct tm conversions + * Convert to and from ANSI C's struct tm with nanoseconds + * @{ + */ +/** \brief Convert epicsTimeStamp to struct tm in local time zone */ epicsShareFunc int epicsShareAPI epicsTimeToTM ( struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc ); +/** \brief Convert epicsTimeStamp to struct tm in UTC/GMT */ epicsShareFunc int epicsShareAPI epicsTimeToGMTM ( struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc ); +/** \brief Set epicsTimeStamp from struct tm in local time zone */ epicsShareFunc int epicsShareAPI epicsTimeFromTM ( epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc ); +/** \brief Set epicsTimeStamp from struct tm in UTC/GMT */ epicsShareFunc int epicsShareAPI epicsTimeFromGMTM ( epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc ); +/** @} */ -/* convert to and from POSIX RT's "struct timespec" */ +/** \name POSIX RT struct timespec conversions + * Convert to and from the POSIX RealTime struct timespec + * format. + * @{ */ +/** \brief Convert epicsTimeStamp to struct timespec */ epicsShareFunc int epicsShareAPI epicsTimeToTimespec ( struct timespec * pDest, const epicsTimeStamp * pSrc ); +/** \brief Set epicsTimeStamp from struct timespec */ epicsShareFunc int epicsShareAPI epicsTimeFromTimespec ( epicsTimeStamp * pDest, const struct timespec * pSrc ); +/** @} */ -/* convert to and from BSD's "struct timeval" */ +/** \name BSD's struct timeval conversions + * Convert to and from the BSD struct timeval format. + * @{ */ +/** \brief Convert epicsTimeStamp to struct timeval */ epicsShareFunc int epicsShareAPI epicsTimeToTimeval ( struct timeval * pDest, const epicsTimeStamp * pSrc ); +/** \brief Set epicsTimeStamp from struct timeval */ epicsShareFunc int epicsShareAPI epicsTimeFromTimeval ( epicsTimeStamp * pDest, const struct timeval * pSrc ); +/** @} */ -/*arithmetic operations */ +/** \name Arithmetic operations + * Arithmetic operations on epicsTimeStamp objects and time differences + * which are always expressed as a \c double in seconds. + * @{ */ +/** \brief Time difference between \p left and \p right in seconds. */ epicsShareFunc double epicsShareAPI epicsTimeDiffInSeconds ( const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight );/* left - right */ +/** \brief Add some number of seconds to \p dest */ epicsShareFunc void epicsShareAPI epicsTimeAddSeconds ( epicsTimeStamp * pDest, double secondsToAdd ); /* adds seconds to *pDest */ +/** @} */ -/*comparison operations: returns (0,1) if (false,true) */ +/** \name Comparison operators + * Comparisons between epicsTimeStamp objects, returning 0=false, 1=true. + * @{ */ +/** \brief \p left equals \p right */ epicsShareFunc int epicsShareAPI epicsTimeEqual ( const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); +/** \brief \p left not equal to \p right */ epicsShareFunc int epicsShareAPI epicsTimeNotEqual ( const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); +/** \brief \p left was before \p right */ epicsShareFunc int epicsShareAPI epicsTimeLessThan ( - const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left < right */ + const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); +/** \brief \p right was no later than \p left */ epicsShareFunc int epicsShareAPI epicsTimeLessThanEqual ( - const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left <= right) */ + const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); +/** \brief \p left was after \p right */ epicsShareFunc int epicsShareAPI epicsTimeGreaterThan ( - const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left > right */ + const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); +/** \brief \p right was not before \p left */ epicsShareFunc int epicsShareAPI epicsTimeGreaterThanEqual ( - const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left >= right */ + const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); +/** @} */ -/*convert to ASCII string */ +/** \brief Convert epicsTimeStamp to string. See epicsTime::strftime() */ epicsShareFunc size_t epicsShareAPI epicsTimeToStrftime ( char * pBuff, size_t bufLength, const char * pFormat, const epicsTimeStamp * pTS ); -/* dump current state to standard out */ +/** \brief Dump current state to stdout */ epicsShareFunc void epicsShareAPI epicsTimeShow ( const epicsTimeStamp *, unsigned interestLevel ); -/* OS dependent reentrant versions of the ANSI C interface because */ -/* vxWorks gmtime_r interface does not match POSIX standards */ +/** \name Reentrant time_t to struct tm conversions + * OS-specific reentrant versions of the ANSI C interface because the + * vxWorks \c gmtime_r interface does not match POSIX standards + * @{ */ +/** \brief Break down a \c time_t into a struct tm in the local timezone */ epicsShareFunc int epicsShareAPI epicsTime_localtime ( const time_t * clock, struct tm * result ); +/** \brief Break down a \c time_t into a struct tm in the UTC timezone */ epicsShareFunc int epicsShareAPI epicsTime_gmtime ( const time_t * clock, struct tm * result ); +/** @} */ -/* Advertised monotonic counter resolution (may not be accurate). - * Minimum non-zero difference between two calls to epicsMonotonicGet() +/** \name Monotonic time routines +* @{ */ +/** \brief Monotonic time resolution, may not be accurate. Returns the + * minimum non-zero time difference between two calls to epicsMonotonicGet() + * in units of nanoseconds. */ epicsShareFunc epicsUInt64 epicsMonotonicResolution(void); -/* Fetch monotonic counter, return is nano-seconds since an unspecified time */ +/** \brief Fetch monotonic counter, returns the number of nanoseconds since + * some unspecified time. */ epicsShareFunc epicsUInt64 epicsMonotonicGet(void); +/** @} */ #ifdef EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE epicsShareFunc void osdMonotonicInit(void); @@ -366,4 +605,3 @@ inline epicsTime & epicsTime::operator = ( const time_t_wrapper & rhs ) #endif /* __cplusplus */ #endif /* epicsTimehInclude */ - diff --git a/modules/libcom/src/osi/os/WIN32/osiFileName.h b/modules/libcom/src/osi/os/WIN32/osiFileName.h index ced745f71..bba2d55c1 100644 --- a/modules/libcom/src/osi/os/WIN32/osiFileName.h +++ b/modules/libcom/src/osi/os/WIN32/osiFileName.h @@ -25,13 +25,13 @@ extern "C" { #define OSI_PATH_SEPARATOR "\\" /** Return the absolute path of the current executable. - @returns NULL or the path. Caller must free() + * \return NULL or the path. Caller must free() */ epicsShareFunc char *epicsGetExecName(void); /** Return the absolute path of the directory containing the current executable. - @returns NULL or the path. Caller must free() + * \return NULL or the path. Caller must free() */ epicsShareFunc char *epicsGetExecDir(void); diff --git a/modules/libcom/src/osi/os/cygwin32/osiFileName.h b/modules/libcom/src/osi/os/cygwin32/osiFileName.h index 1e7799098..76562f3e4 100644 --- a/modules/libcom/src/osi/os/cygwin32/osiFileName.h +++ b/modules/libcom/src/osi/os/cygwin32/osiFileName.h @@ -24,13 +24,13 @@ extern "C" { #define OSI_PATH_SEPARATOR "\\" /** Return the absolute path of the current executable. - @returns NULL or the path. Caller must free() + \return NULL or the path. Caller must free() */ epicsShareFunc char *epicsGetExecName(void); /** Return the absolute path of the directory containing the current executable. - @returns NULL or the path. Caller must free() + \return NULL or the path. Caller must free() */ epicsShareFunc char *epicsGetExecDir(void); diff --git a/modules/libcom/src/osi/os/default/epicsMMIODef.h b/modules/libcom/src/osi/os/default/epicsMMIODef.h index dc4bb4cb7..114a67c6e 100644 --- a/modules/libcom/src/osi/os/default/epicsMMIODef.h +++ b/modules/libcom/src/osi/os/default/epicsMMIODef.h @@ -4,8 +4,14 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Michael Davidsaver +/** + * \file epicsMMIODef.h + * \brief Memory Mapped I/O + * + * Definitions related to Memory Mapped I/O + * + * \author Michael Davidsaver + * @ingroup mmio */ #ifndef EPICSMMIODEF_H @@ -26,7 +32,7 @@ *@{ */ -/** @brief Read a single byte. +/** \brief Read a single byte. */ static EPICS_ALWAYS_INLINE epicsUInt8 @@ -35,7 +41,7 @@ ioread8(volatile void* addr) return *(volatile epicsUInt8*)(addr); } -/** @brief Write a single byte. +/** \brief Write a single byte. */ static EPICS_ALWAYS_INLINE void @@ -44,7 +50,7 @@ iowrite8(volatile void* addr, epicsUInt8 val) *(volatile epicsUInt8*)(addr) = val; } -/** @brief Read two bytes in host order. +/** \brief Read two bytes in host order. * Not byte swapping */ static EPICS_ALWAYS_INLINE @@ -54,7 +60,7 @@ nat_ioread16(volatile void* addr) return *(volatile epicsUInt16*)(addr); } -/** @brief Write two byte in host order. +/** \brief Write two byte in host order. * Not byte swapping */ static EPICS_ALWAYS_INLINE @@ -64,7 +70,7 @@ nat_iowrite16(volatile void* addr, epicsUInt16 val) *(volatile epicsUInt16*)(addr) = val; } -/** @brief Read four bytes in host order. +/** \brief Read four bytes in host order. * Not byte swapping */ static EPICS_ALWAYS_INLINE @@ -74,7 +80,7 @@ nat_ioread32(volatile void* addr) return *(volatile epicsUInt32*)(addr); } -/** @brief Write four byte in host order. +/** \brief Write four byte in host order. * Not byte swapping */ static EPICS_ALWAYS_INLINE @@ -151,50 +157,50 @@ bswap32(epicsUInt32 value) # error Unable to determine native byte order #endif -/** @def bswap16 - * @brief Unconditional two byte swap +/** \def bswap16 + * \brief Unconditional two byte swap */ -/** @def bswap32 - * @brief Unconditional four byte swap +/** \def bswap32 + * \brief Unconditional four byte swap */ -/** @def be_ioread16 - * @brief Read two byte in big endian order. +/** \def be_ioread16 + * \brief Read two byte in big endian order. */ -/** @def be_iowrite16 - * @brief Write two byte in big endian order. +/** \def be_iowrite16 + * \brief Write two byte in big endian order. */ -/** @def be_ioread32 - * @brief Read four byte in big endian order. +/** \def be_ioread32 + * \brief Read four byte in big endian order. */ -/** @def be_iowrite32 - * @brief Write four byte in big endian order. +/** \def be_iowrite32 + * \brief Write four byte in big endian order. */ -/** @def le_ioread16 - * @brief Read two byte in little endian order. +/** \def le_ioread16 + * \brief Read two byte in little endian order. */ -/** @def le_iowrite16 - * @brief Write two byte in little endian order. +/** \def le_iowrite16 + * \brief Write two byte in little endian order. */ -/** @def le_ioread32 - * @brief Read four byte in little endian order. +/** \def le_ioread32 + * \brief Read four byte in little endian order. */ -/** @def le_iowrite32 - * @brief Write four byte in little endian order. +/** \def le_iowrite32 + * \brief Write four byte in little endian order. */ /** @ingroup mmio *@{ */ -/** @brief Explicit read memory barrier +/** \brief Explicit read memory barrier * Prevents reordering of reads around it. */ #define rbarr() do{}while(0) -/** @brief Explicit write memory barrier +/** \brief Explicit write memory barrier * Prevents reordering of writes around it. */ #define wbarr() do{}while(0) -/** @brief Explicit read/write memory barrier +/** \brief Explicit read/write memory barrier * Prevents reordering of reads or writes around it. */ #define rwbarr() do{}while(0) @@ -233,30 +239,30 @@ bswap32(epicsUInt32 value) * *@b PCI * - @code + \code be_iowrite16(base+off, 14); var = be_ioread16(base+off); - @endcode + \endcode * *@b VME * - @code + \code nat_iowrite16(base+off, 14); var = nat_ioread16(base+off); - @endcode + \endcode * *@subsection mmioexle Little endian device * *@b PCI - @code + \code le_iowrite16(base+off, 14); var = le_ioread16(base+off); - @endcode + \endcode *@b VME - @code + \code nat_iowrite16(base+off, bswap16(14)); var = bswap16(nat_iowrite16(base+off)); - @endcode + \endcode *This difference arises because VME bridges implement hardware byte *swapping on little endian systems, while PCI bridges do not. *Software accessing PCI devices must know if byte swapping is required. @@ -268,7 +274,9 @@ bswap32(epicsUInt32 value) * *Software accessing VME must @b not do conditional swapping. * - *@note All read and write operations have an implicit read or write barrier. + *\note All read and write operations have an implicit read or write barrier. */ + /** @} */ + #endif /* EPICSMMIODEF_H */ diff --git a/modules/libcom/src/osi/osiPoolStatus.h b/modules/libcom/src/osi/osiPoolStatus.h index b0207f185..197d5fc96 100644 --- a/modules/libcom/src/osi/osiPoolStatus.h +++ b/modules/libcom/src/osi/osiPoolStatus.h @@ -7,16 +7,15 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ +/**\file osiPoolStatus.h + * \author Jeff Hill + * \brief Functions to check the state of the system memory pool. + * + **/ + #ifndef INC_osiPoolStatus_H #define INC_osiPoolStatus_H -/* - * Author: Jeff Hill - * - * Functions which interrogate the state of the system wide pool - * - */ - #include #include "shareLib.h" @@ -24,12 +23,17 @@ extern "C" { #endif -/* - * tests to see if there is sufficent space for a block of the requested size - * along with whatever additional free space is necessary to keep the system running - * reliably +/**\brief Checks if a memory block of a specific size can be safely allocated. * - * this routine is called quite frequently so an efficent implementation is important + * The meaning of "safely allocated" is target-specific, some additional free + * space is usually necessary to keep the system running reliably. + * On vxWorks this returns True if at least 100000 bytes is free. + * + * \note This routine is called quite frequently by the IOC so an efficent + * implementation is important. + * + * \param contiguousBlockSize Block size to check. + * \return True if the requested memory should be available. */ epicsShareFunc int epicsShareAPI osiSufficentSpaceInPool ( size_t contiguousBlockSize ); diff --git a/modules/libcom/src/ring/epicsRingBytes.h b/modules/libcom/src/ring/epicsRingBytes.h index 3dc0081ad..870d44093 100644 --- a/modules/libcom/src/ring/epicsRingBytes.h +++ b/modules/libcom/src/ring/epicsRingBytes.h @@ -7,11 +7,21 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ - -/* - * Author: Marty Kraimer Date: 15JUL99 - * Eric Norum - * Ralph Lange +/** + * \file epicsRingBytes.h + * \author Marty Kraimer, Eric Norum, Ralph Lange + * \brief A circular buffer to store bytes + * + * \details + * EpicsRingBytes provides a C API for creating and using ring buffers + * (first in first out circular buffers) that store bytes. The unlocked + * variant is designed so that one writer thread and one reader thread + * can access the ring simultaneously without requiring mutual exclusion. + * The locked variant uses an epicsSpinLock, and works with any numbers of + * writer and reader threads. + * \note If there is only one writer it is not necessary to lock for puts. + * If there is a single reader it is not necessary to lock for gets. + * epicsRingBytesLocked uses a spinlock. */ #ifndef INCepicsRingBytesh @@ -23,35 +33,103 @@ extern "C" { #include "shareLib.h" +/** \brief An identifier for a ring buffer */ typedef void *epicsRingBytesId; typedef void const *epicsRingBytesIdConst; +/** + * \brief Create a new ring buffer + * \param nbytes Size of ring buffer to create + * \return Ring buffer Id or NULL on failure + */ epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesCreate(int nbytes); -/* Same, but secured by a spinlock */ +/** + * \brief Create a new ring buffer, secured by a spinlock + * \param nbytes Size of ring buffer to create + * \return Ring buffer Id or NULL on failure + */ epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesLockedCreate(int nbytes); +/** + * \brief Delete the ring buffer and free any associated memory + * \param id RingbufferID returned by epicsRingBytesCreate() + */ epicsShareFunc void epicsShareAPI epicsRingBytesDelete(epicsRingBytesId id); +/** + * \brief Read data out of the ring buffer + * \param id RingbufferID returned by epicsRingBytesCreate() + * \param value Where to put the data fetched from the buffer + * \param nbytes Maximum number of bytes to get + * \return The number of bytes actually fetched + */ epicsShareFunc int epicsShareAPI epicsRingBytesGet( epicsRingBytesId id, char *value,int nbytes); +/** + * \brief Write data into the ring buffer + * \param id RingbufferID returned by epicsRingBytesCreate() + * \param value Source of the data to be put into the buffer + * \param nbytes How many bytes to put + * \return The number of bytes actually stored, zero if not enough space + */ epicsShareFunc int epicsShareAPI epicsRingBytesPut( epicsRingBytesId id, char *value,int nbytes); +/** + * \brief Make the ring buffer empty + * \param id RingbufferID returned by epicsRingBytesCreate() + * \note Should only be used when both gets and puts are locked out. + */ epicsShareFunc void epicsShareAPI epicsRingBytesFlush(epicsRingBytesId id); +/** + * \brief Return the number of free bytes in the ring buffer + * \param id RingbufferID returned by epicsRingBytesCreate() + * \return The number of free bytes in the ring buffer + */ epicsShareFunc int epicsShareAPI epicsRingBytesFreeBytes(epicsRingBytesId id); +/** + * \brief Return the number of bytes currently stored in the ring buffer + * \param id RingbufferID returned by epicsRingBytesCreate() + * \return The number of bytes currently stored in the ring buffer + */ epicsShareFunc int epicsShareAPI epicsRingBytesUsedBytes(epicsRingBytesId id); +/** + * \brief Return the size of the ring buffer + * \param id RingbufferID returned by epicsRingBytesCreate() + * \return Return the size of the ring buffer, i.e., nbytes specified in + * the call to epicsRingBytesCreate(). + */ epicsShareFunc int epicsShareAPI epicsRingBytesSize(epicsRingBytesId id); +/** + * \brief Test if the ring buffer is currently empty. + * \param id RingbufferID returned by epicsRingBytesCreate() + * \return 1 if the buffer is empty, otherwise 0 + */ epicsShareFunc int epicsShareAPI epicsRingBytesIsEmpty(epicsRingBytesId id); +/** + * \brief Test if the ring buffer is currently full. + * \param id RingbufferID returned by epicsRingBytesCreate() + * \return 1 if the buffer is full, otherwise 0 + */ epicsShareFunc int epicsShareAPI epicsRingBytesIsFull(epicsRingBytesId id); +/** + * \brief See how full a ring buffer has been since it was last checked. + * + * Returns the maximum amount of data the ring buffer has held in bytes + * since the water mark was last reset. A new ring buffer starts with a + * water mark of 0. + * \param id RingbufferID returned by epicsRingBytesCreate() + * \return Actual Highwater mark + */ epicsShareFunc int epicsShareAPI epicsRingBytesHighWaterMark(epicsRingBytesIdConst id); +/** + * \brief Reset the Highwater mark of the ring buffer. + * + * The Highwater mark will be set to the current usage + * \param id RingbufferID returned by epicsRingBytesCreate() + */ epicsShareFunc void epicsShareAPI epicsRingBytesResetHighWaterMark(epicsRingBytesId id); #ifdef __cplusplus } #endif -/* NOTES - If there is only one writer it is not necessary to lock for put - If there is a single reader it is not necessary to lock for puts - - epicsRingBytesLocked uses a spinlock. -*/ #endif /* INCepicsRingBytesh */ diff --git a/modules/libcom/src/ring/epicsRingPointer.h b/modules/libcom/src/ring/epicsRingPointer.h index 68bf8f5a6..8ecdcec81 100644 --- a/modules/libcom/src/ring/epicsRingPointer.h +++ b/modules/libcom/src/ring/epicsRingPointer.h @@ -7,40 +7,92 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ - -/* - * Author: Marty Kraimer Date: 15JUL99 - * Ralph Lange +/** + * \file epicsRingPointer.h + * \brief A circular buffer to store pointers + * \author Marty Kraimer, Ralph Lange + * + * \details + * epicsRingPointer.h provides both C and C++ APIs for creating and using ring + * buffers (first in first out circular buffers) that store pointers. The + * unlocked kind is designed so that one writer thread and one reader thread + * can access the ring simultaneously without requiring mutual exclusion. The + * locked variant uses an epicsSpinLock, and works with any numbers of writer + * and reader threads. + * \note If there is only one writer it is not necessary to lock pushes. + * If there is a single reader it is not necessary to lock pops. + * epicsRingPointerLocked uses a spinlock. */ #ifndef INCepicsRingPointerh #define INCepicsRingPointerh -/* NOTES - * If there is only one writer it is not necessary to lock push - * If there is a single reader it is not necessary to lock pop - * - * epicsRingPointerLocked uses a spinlock. - */ #include "epicsSpin.h" #include "shareLib.h" #ifdef __cplusplus +/** + * \brief A C++ template class providing methods for creating and using a ring + * buffer (a first in, first out circular buffer) that stores pointers to + * objects of the template type. + */ template class epicsRingPointer { public: /* Functions */ + /**\brief Constructor + * \param size Maximum number of elements (pointers) that can be stored + * \param locked If true, the spin lock secured variant is created + */ epicsRingPointer(int size, bool locked); + /**\brief Destructor + */ ~epicsRingPointer(); + /**\brief Push a new entry on the ring + * \return True on success, False if the buffer was full + */ bool push(T *p); + /**\brief Take an element off the ring + * \return The element, or NULL if the ring was empty + */ T* pop(); + /**\brief Remove all elements from the ring. + * \note If this operation is performed on a ring buffer of the + * unsecured kind, all access to the ring should be locked. + */ void flush(); + /**\brief Get how much free space remains in the ring + * \return The number of additional elements the ring could hold. + */ int getFree() const; + /**\brief Get how many elements are stored on the ring + * \return The number of elements currently stored. + */ int getUsed() const; + /**\brief Get the size of the ring + * \return The \c size specified when the ring was created. + */ int getSize() const; + /**\brief Test if the ring is currently empty + * \return True if the ring is empty, otherwise false. + */ bool isEmpty() const; + /**\brief Test if the ring is currently full + * \return True if the ring is full, otherwise false. + */ bool isFull() const; + /**\brief See how full the ring has got since it was last checked. + * + * Returns the maximum number of elements the ring + * buffer has held since the water mark was last reset. + * A new ring buffer starts with a water mark of 0. + * \return Actual highwater mark + */ int getHighWaterMark() const; + /**\brief Reset high water mark + * + * High water mark will be set to the current usage + */ void resetHighWaterMark(); private: /* Prevent compiler-generated member functions */ @@ -62,24 +114,93 @@ private: /* Data */ extern "C" { #endif /*__cplusplus */ +/** \brief An identifier for the C API to a ring buffer storing pointers */ typedef void *epicsRingPointerId; typedef void const *epicsRingPointerIdConst; - +/** + * \brief Create a new ring buffer + * \param size Size of ring buffer to create + * \return Ring buffer identifier or NULL on failure + */ epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size); -/* Same, but secured by a spinlock */ +/** + * \brief Create a new ring buffer, secured by a spinlock + * \param size Size of ring buffer to create + * \return Ring buffer identifier or NULL on failure + */ epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerLockedCreate(int size); +/** + * \brief Delete the ring buffer and free any associated memory + * \param id Ring buffer identifier + */ epicsShareFunc void epicsShareAPI epicsRingPointerDelete(epicsRingPointerId id); -/*ringPointerPush returns (0,1) if p (was not, was) put on ring*/ +/** + * \brief Push pointer into the ring buffer + * \param id Ring buffer identifier + * \param p Pointer to be pushed to the ring + * \return 1 if the pointer was successfully pushed, 0 if the buffer was full + */ epicsShareFunc int epicsShareAPI epicsRingPointerPush(epicsRingPointerId id,void *p); -/*ringPointerPop returns 0 if ring is empty*/ +/** + * \brief Take an element off the ring + * \param id Ring buffer identifier + * \return The pointer from the buffer, or NULL if the ring was empty + */ epicsShareFunc void* epicsShareAPI epicsRingPointerPop(epicsRingPointerId id) ; +/** + * \brief Remove all elements from the ring + * \param id Ring buffer identifier + * \note If this operation is performed on a ring buffer of the unsecured + * kind, all access to the ring should be locked. + */ epicsShareFunc void epicsShareAPI epicsRingPointerFlush(epicsRingPointerId id); +/** + * \brief Return the amount of empty space in the ring buffer + * \param id Ring buffer identifier + * \return The number of additional elements it could hold. + */ epicsShareFunc int epicsShareAPI epicsRingPointerGetFree(epicsRingPointerId id); +/** + * \brief Return the number of elements stored in the ring buffer + * \param id Ring buffer identifier + * \return The number of elements stored in the ring buffer + */ epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id); +/** + * \brief Return the size of the ring + * \param id Ring buffer identifier + * \return The size of the ring buffer, i.e. the value of \c size + * given when the ring was created. + */ epicsShareFunc int epicsShareAPI epicsRingPointerGetSize(epicsRingPointerId id); +/** + * \brief Check if the ring buffer is currently empty + * \param id Ring buffer identifier + * \return 1 if the ring is empty, otherwise 0 + */ epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id); +/** + * \brief Check if the ring buffer is currently full + * \param id Ring buffer identifier + * \return 1 if the ring buffer is full, otherwise 0 + */ epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id); +/** + * \brief Get the Highwater mark of the ring buffer + * + * Returns the largest number of elements the ring buffer has held since + * the water mark was last reset. A new ring buffer starts with a + * water mark of 0. + * \param id Ring buffer identifier + * \return Actual Highwater mark + */ epicsShareFunc int epicsShareAPI epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id); +/** + * \brief Reset the Highwater mark of the ring buffer + * + * The Highwater mark will be set to the current usage + * \param id Ring buffer identifier + */ epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPointerId id); /* This routine was incorrectly named in previous releases */ @@ -92,12 +213,6 @@ epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPo /* INLINE FUNCTIONS */ -/* Algorithm note - * Space is allocated for one additional element. - * A put request is rejected if the it would cause nextPush to equal nextPop - * The algorithm does not require locking puts for a single writer - * or locking of gets for a single reader - */ #ifdef __cplusplus template diff --git a/modules/libcom/src/yajl/yajl_alloc.h b/modules/libcom/src/yajl/yajl_alloc.h index 433b16c9d..406310ac0 100644 --- a/modules/libcom/src/yajl/yajl_alloc.h +++ b/modules/libcom/src/yajl/yajl_alloc.h @@ -16,8 +16,12 @@ /** * \file yajl_alloc.h - * default memory allocation routines for yajl which use malloc/realloc and - * free + * \brief Memory allocation macros for yajl + * \author Lloyd Hilaiel + * + * These macros are used inside YAJL instead of directly calling + * malloc(), realloc() or free(). They call the equivalent method + * in their \ref yajl_alloc_funcs parameter \a afs. */ #ifndef __YAJL_ALLOC_H__ diff --git a/modules/libcom/src/yajl/yajl_common.h b/modules/libcom/src/yajl/yajl_common.h index 8bf0b44c6..9fbf8e283 100644 --- a/modules/libcom/src/yajl/yajl_common.h +++ b/modules/libcom/src/yajl/yajl_common.h @@ -26,47 +26,54 @@ extern "C" { #endif +/** \file yajl_common.h + * \brief Common routines and macros used by other YAJL APIs. + * \author Lloyd Hilaiel + */ + /** YAJL API history in brief * - * Originally macro not defined - * YAJL 1.0.12 - * Bundled with EPICS Base 3.15.0.1 + * This macro was not defined in the + * YAJL 1.0.12 version that was + * bundled with EPICS Base 3.15.0.1 * * YAJL 2.1.0 - * Changes argument type for yajl_integer() from 'int' to 'long long' - * Changes argument type for yajl_string() and yajl_map_key() from 'unsigned' to 'size_t' - * Replacement of struct yajl_parser_config with yajl_config() - * Replacement of yajl_parse_complete() with yajl_complete_parse() + * \li Changes argument type for yajl_integer() from \c int to \c long \c long + * \li Changes argument type for yajl_string() and yajl_map_key() from \c unsigned to \c size_t + * \li Replacement of struct yajl_parser_config with yajl_config() + * \li Replacement of yajl_parse_complete() with yajl_complete_parse() */ #define EPICS_YAJL_VERSION VERSION_INT(2,1,0,0) +/** Maximum generation depth for YAJL's JSON generation routines */ #define YAJL_MAX_DEPTH 128 +/** Symbol decoration for Microsoft builds */ #define YAJL_API LIBCOM_API -/** pointer to a malloc function, supporting client overriding memory +/** Pointer to a malloc() function, supporting client overriding memory * allocation routines */ typedef void * (*yajl_malloc_func)(void *ctx, size_t sz); -/** pointer to a free function, supporting client overriding memory +/** Pointer to a free() function, supporting client overriding memory * allocation routines */ typedef void (*yajl_free_func)(void *ctx, void * ptr); -/** pointer to a realloc function which can resize an allocation. */ +/** Pointer to a realloc() function which can resize an allocation. */ typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz); /** A structure which can be passed to yajl_*_alloc routines to allow the * client to specify memory allocation functions to be used. */ typedef struct { - /** pointer to a function that can allocate uninitialized memory */ + /** Pointer to a function that can allocate uninitialized memory */ yajl_malloc_func malloc; - /** pointer to a function that can resize memory allocations */ + /** Pointer to a function that can resize memory allocations */ yajl_realloc_func realloc; - /** pointer to a function that can free memory allocated using + /** Pointer to a function that can free memory allocated using * reallocFunction or mallocFunction */ yajl_free_func free; - /** a context pointer that will be passed to above allocation routines */ + /** A context pointer that will be passed to above allocation routines */ void * ctx; } yajl_alloc_funcs; diff --git a/modules/libcom/src/yajl/yajl_gen.h b/modules/libcom/src/yajl/yajl_gen.h index 3ea05e555..233f7d141 100644 --- a/modules/libcom/src/yajl/yajl_gen.h +++ b/modules/libcom/src/yajl/yajl_gen.h @@ -16,7 +16,8 @@ /** * \file yajl_gen.h - * Interface to YAJL's JSON generation facilities. + * \brief Interface to YAJL's JSON generation facilities. + * \author Lloyd Hilaiel */ #ifndef __YAJL_GEN_H__ @@ -27,49 +28,49 @@ #ifdef __cplusplus extern "C" { #endif - /** generator status codes */ + /** Generator status codes */ typedef enum { - /** no error */ + /** No error */ yajl_gen_status_ok = 0, - /** at a point where a map key is generated, a function other than - * yajl_gen_string was called */ + /** At a point where a map key is generated, a function other than + * yajl_gen_string() was called */ yajl_gen_keys_must_be_strings, /** YAJL's maximum generation depth was exceeded. see - * YAJL_MAX_DEPTH */ + * \ref YAJL_MAX_DEPTH */ yajl_max_depth_exceeded, /** A generator function (yajl_gen_XXX) was called while in an error * state */ yajl_gen_in_error_state, /** A complete JSON document has been generated */ yajl_gen_generation_complete, - /** yajl_gen_double was passed an invalid floating point value + /** yajl_gen_double() was passed an invalid floating point value * (infinity or NaN). */ yajl_gen_invalid_number, /** A print callback was passed in, so there is no internal * buffer to get from */ yajl_gen_no_buf, - /** returned from yajl_gen_string() when the yajl_gen_validate_utf8 + /** Returned from yajl_gen_string() when the yajl_gen_validate_utf8() * option is enabled and an invalid was passed by client code. */ yajl_gen_invalid_string } yajl_gen_status; - /** an opaque handle to a generator */ + /** An opaque handle to a generator */ typedef struct yajl_gen_t * yajl_gen; - /** a callback used for "printing" the results. */ + /** A callback used for "printing" the results. */ typedef void (*yajl_print_t)(void * ctx, const char * str, size_t len); - /** configuration parameters for the parser, these may be passed to + /** Configuration parameters for the parser, these may be passed to * yajl_gen_config() along with option specific argument(s). In general, * all configuration parameters default to *off*. */ typedef enum { - /** generate indented (beautiful) output */ + /** Generate indented (beautiful) output */ yajl_gen_beautify = 0x01, /** - * Set an indent string which is used when yajl_gen_beautify + * Set an indent string which is used when yajl_gen_beautify() * is enabled. Maybe something like \\t or some number of * spaces. The default is four spaces ' '. */ @@ -77,11 +78,12 @@ extern "C" { /** * Set a function and context argument that should be used to * output generated json. the function should conform to the - * yajl_print_t prototype while the context argument is a + * yajl_print_t() prototype while the context argument is a * void * of your choosing. * - * example: + * Example: \code{.cpp} * yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr); + * \endcode */ yajl_gen_print_callback = 0x04, /** @@ -91,7 +93,7 @@ extern "C" { */ yajl_gen_validate_utf8 = 0x08, /** - * the forward solidus (slash or '/' in human) is not required to be + * The forward solidus (slash or '/' in human) is not required to be * escaped in json text. By default, YAJL will not escape it in the * iterest of saving bytes. Setting this flag will cause YAJL to * always escape '/' in generated JSON strings. @@ -99,51 +101,62 @@ extern "C" { yajl_gen_escape_solidus = 0x10 } yajl_gen_option; - /** allow the modification of generator options subsequent to handle - * allocation (via yajl_alloc) + /** Allow the modification of generator options subsequent to handle + * allocation (via yajl_alloc()) * \returns zero in case of errors, non-zero otherwise */ YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...); - /** allocate a generator handle - * \param allocFuncs an optional pointer to a structure which allows + /** Allocate a generator handle + * \param allocFuncs An optional pointer to a structure which allows * the client to overide the memory allocation * used by yajl. May be NULL, in which case - * malloc/free/realloc will be used. + * malloc(), free() and realloc() will be used. * * \returns an allocated handle on success, NULL on failure (bad params) */ YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs); - /** free a generator handle */ + /** Free a generator handle */ YAJL_API void yajl_gen_free(yajl_gen handle); + /** Generate an integer number. */ YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number); - /** generate a floating point number. number may not be infinity or + /** Generate a floating point number. \p number may not be infinity or * NaN, as these have no representation in JSON. In these cases the - * generator will return 'yajl_gen_invalid_number' */ + * generator will return \ref yajl_gen_invalid_number */ YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number); + /** Generate a number from the string given in \p num. */ YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand, const char * num, size_t len); + /** Generate a string value or map key from \p str. */ YAJL_API yajl_gen_status yajl_gen_string(yajl_gen hand, const unsigned char * str, size_t len); + /** Generate a \c null value. */ YAJL_API yajl_gen_status yajl_gen_null(yajl_gen hand); + /** Generate a \c true or \c false value from \p boolean. */ YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean); + /** Start generating a JSON map. This should be followed by calls to + * yajl_gen_string() to provide a key and another yajl_gen routine + * to provide the value associated with that key. */ YAJL_API yajl_gen_status yajl_gen_map_open(yajl_gen hand); + /** Finish generating a JSON map. */ YAJL_API yajl_gen_status yajl_gen_map_close(yajl_gen hand); + /** Start generating a JSON array. */ YAJL_API yajl_gen_status yajl_gen_array_open(yajl_gen hand); + /** Finish generating a JSON array. */ YAJL_API yajl_gen_status yajl_gen_array_close(yajl_gen hand); - /** access the null terminated generator buffer. If incrementally - * outputing JSON, one should call yajl_gen_clear to clear the + /** Access the null terminated generator buffer. If incrementally + * outputing JSON, one should call yajl_gen_clear() to clear the * buffer. This allows stream generation. */ YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand, const unsigned char ** buf, size_t * len); - /** clear yajl's output buffer, but maintain all internal generation + /** Clear yajl's output buffer, but maintain all internal generation * state. This function will not "reset" the generator state, and is * intended to enable incremental JSON outputing. */ YAJL_API void yajl_gen_clear(yajl_gen hand); diff --git a/modules/libcom/src/yajl/yajl_parse.h b/modules/libcom/src/yajl/yajl_parse.h index f113c7cf4..663a3a864 100644 --- a/modules/libcom/src/yajl/yajl_parse.h +++ b/modules/libcom/src/yajl/yajl_parse.h @@ -16,7 +16,8 @@ /** * \file yajl_parse.h - * Interface to YAJL's JSON stream parsing facilities. + * \brief Interface to YAJL's JSON stream parsing facilities. + * \author Lloyd Hilaiel */ #ifndef __YAJL_PARSE_H__ @@ -27,47 +28,45 @@ #ifdef __cplusplus extern "C" { #endif - /** error codes returned from this interface */ + /** Error codes returned from this interface */ typedef enum { - /** no error was encountered */ + /** No error was encountered */ yajl_status_ok, - /** a client callback returned zero, stopping the parse */ + /** A client callback returned zero, stopping the parse */ yajl_status_client_canceled, - /** An error occured during the parse. Call yajl_get_error for + /** An error occured during the parse. Call yajl_get_error() for * more information about the encountered error */ yajl_status_error } yajl_status; - /** attain a human readable, english, string for an error */ + /** Attain a human readable, english, string for an error */ YAJL_API const char * yajl_status_to_string(yajl_status code); - /** an opaque handle to a parser */ + /** An opaque handle to a parser */ typedef struct yajl_handle_t * yajl_handle; - /** yajl is an event driven parser. this means as json elements are + /** YAJL is an event driven parser. This means as json elements are * parsed, you are called back to do something with the data. The * functions in this table indicate the various events for which * you will be called back. Each callback accepts a "context" - * pointer, this is a void * that is passed into the yajl_parse + * pointer, this is a void * that is passed into the yajl_parse() * function which the client code may use to pass around context. * * All callbacks return an integer. If non-zero, the parse will * continue. If zero, the parse will be canceled and - * yajl_status_client_canceled will be returned from the parse. + * yajl_status_client_canceled() will be returned from the parse. * - * \attention { + * \attention * A note about the handling of numbers: - * * yajl will only convert numbers that can be represented in a * double or a 64 bit (long long) int. All other numbers will - * be passed to the client in string form using the yajl_number - * callback. Furthermore, if yajl_number is not NULL, it will - * always be used to return numbers, that is yajl_integer and - * yajl_double will be ignored. If yajl_number is NULL but one - * of yajl_integer or yajl_double are defined, parsing of a + * be passed to the client in string form using the yajl_number() + * callback. Furthermore, if yajl_number() is not NULL, it will + * always be used to return numbers, that is yajl_integer() and + * yajl_double() will be ignored. If yajl_number() is NULL but one + * of yajl_integer() or yajl_double() are defined, parsing of a * number larger than is representable in a double or 64 bit * integer will result in a parse error. - * } */ typedef struct { int (* yajl_null)(void * ctx); @@ -79,7 +78,7 @@ extern "C" { int (* yajl_number)(void * ctx, const char * numberVal, size_t numberLen); - /** strings are returned as pointers into the JSON text when, + /** Strings are returned as pointers into the JSON text when, * possible, as a result, they are _not_ null padded */ int (* yajl_string)(void * ctx, const unsigned char * stringVal, size_t stringLen); @@ -93,8 +92,8 @@ extern "C" { int (* yajl_end_array)(void * ctx); } yajl_callbacks; - /** allocate a parser handle - * \param callbacks a yajl callbacks structure specifying the + /** Allocate a parser handle + * \param callbacks A yajl callbacks structure specifying the * functions to call when different JSON entities * are encountered in the input text. May be NULL, * which is only useful for validation. @@ -107,7 +106,7 @@ extern "C" { void * ctx); - /** configuration parameters for the parser, these may be passed to + /** Configuration parameters for the parser, these may be passed to * yajl_config() along with option specific argument(s). In general, * all configuration parameters default to *off*. */ typedef enum { @@ -115,8 +114,9 @@ extern "C" { * JSON input. Non-standard, but rather fun * arguments: toggled off with integer zero, on otherwise. * - * example: + * Example: \code{.cpp} * yajl_config(h, yajl_allow_comments, 1); // turn comment support on + * \endcode */ yajl_allow_comments = 0x01, /** @@ -125,8 +125,9 @@ extern "C" { * this option makes parsing slightly more expensive (~7% depending * on processor and compiler in use) * - * example: + * Example: \code{.cpp} * yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking + * \endcode */ yajl_dont_validate_strings = 0x02, /** @@ -157,17 +158,17 @@ extern "C" { yajl_allow_partial_values = 0x10 } yajl_option; - /** allow the modification of parser options subsequent to handle - * allocation (via yajl_alloc) + /** Allow the modification of parser options subsequent to handle + * allocation (via yajl_alloc()) * \returns zero in case of errors, non-zero otherwise */ YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...); - /** free a parser handle */ + /** Free a parser handle */ YAJL_API void yajl_free(yajl_handle handle); /** Parse some json! - * \param hand - a handle to the json parser allocated with yajl_alloc + * \param hand - a handle to the json parser allocated with yajl_alloc() * \param jsonText - a pointer to the UTF8 json text to be parsed * \param jsonTextLength - the length, in bytes, of input text */ @@ -182,11 +183,11 @@ extern "C" { * yajl can't know whether another digit is next or some character * that would terminate the integer token. * - * \param hand - a handle to the json parser allocated with yajl_alloc + * \param hand - a handle to the json parser allocated with yajl_alloc() */ YAJL_API yajl_status yajl_complete_parse(yajl_handle hand); - /** get an error string describing the state of the + /** Get an error string describing the state of the * parse. * * If verbose is non-zero, the message will include the JSON @@ -194,14 +195,14 @@ extern "C" { * the specific char. * * \returns A dynamically allocated string will be returned which should - * be freed with yajl_free_error + * be freed with yajl_free_error() */ YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose, const unsigned char * jsonText, size_t jsonTextLength); /** - * get the amount of data consumed from the last chunk passed to YAJL. + * Get the amount of data consumed from the last chunk passed to YAJL. * * In the case of a successful parse this can help you understand if * the entire buffer was consumed (which will allow you to handle @@ -214,7 +215,7 @@ extern "C" { */ YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand); - /** free an error returned from yajl_get_error */ + /** Free an error returned from yajl_get_error() */ YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str); #ifdef __cplusplus