Error Library : Error List Management Facilities
Contents:
=========
1. History
2. Description
3. How to link/include the Error library (liberr.a)
- Include files.
- Code location.
4. Structures
4.1: dsErrCode
4.2: dsErrType
4.3: dsErrMsgType
4.4: dsErrSeverity
4.5: dsErrBool
4.6: dsErrInstance
4.7: dsErrList
4.8: dsErrGroup
5. Functions
5.1: Initialization, Creation, Close
5.1.1: dsErrInitLib()
5.1.2: dsErrCreateInstance()
5.1.3: dsErrResetInstance()
5.1.4: dsErrCreateList()
5.1.5: dsErrCloseLib()
5.1.6: dsErrDirectOutput()
5.2: Adding/Setting Errors
5.2.1: dsErrAdd()
5.2.2: dsErrSetInstance()
5.2.3: dsErrAddToEnd()
5.3: Searching for Errors in an Error List
5.3.1: dsErrLook()
5.3.2: dsErrLookN()
5.3.3: dsErrLookCode()
5.3.4: dsErrLookCodeExcl()
5.3.5: dsErrLookSev()
5.3.6: dsErrLookAllSev()
5.3.7: dsErrLookAllCode()
5.3.8: dsErrLookAllCodeExcl()
5.3.9: dsErrGetNumOccur()
5.3.10: dsErrPeek()
5.3.11: dsErrPeekN()
5.3.12: dsErrPeekCode()
5.3.13: dsErrPeekCodeExcl()
5.3.14: dsErrPeekSev()
5.4: Removing Errors from Error Lists
5.4.1: dsErrRemove()
5.4.2: dsErrRemoveN()
5.4.3: dsErrRemoveCode()
5.4.4: dsErrRemoveSev()
5.4.5: dsErrRemoveAll()
5.4.6: dsErrRemoveAllSev()
5.4.7: dsErrRemoveAllCode()
5.5: Processing Error Instances and Error Lists
5.5.1: dsErrPrintList()
5.5.2: dsErrPrintInstance()
5.5.3: dsErrReturnInstance()
5.5.4: dsErrExitInstance()
5.5.5: dsErrQuitInstance()
5.5.6: dsErrDumpInstance()
5.6: Accessor Functions for Error Instances and Error Lists
5.6.1: dsErrGetErrorCt()
5.6.2: dsErrGetFatalCt()
5.6.3: dsErrGetWarningCt()
5.6.4: dsErrGetInstCt()
5.6.5: dsErrGetInstCode()
5.6.6: dsErrGetInstSev()
5.6.7: dsErrGetInstMsg()
5.7: Signal Handling
6. How to Add Errors to the Library
6.1 The Error Elements
6.1.1 The error number:
6.1.2 The error severity:
6.1.3 The generic error message:
6.2 Location of the Error
6.3 Modifying the code to place the error in the hash map
7. Debug and Function Tracing
7.1 Function Tracing
7.2 Routines for Function Tracing
7.2.1 init_function_stack()
7.2.2 check_in()
7.2.3 check_out()
7.2.4 exit_upon_error()
7.2.5 print_function_stack()
8. Synopsis of Defined Errors
===========
Date Comment
----------------------------------
5/18/98 DLM - initial release.
7/23/98 DLM - Many updates: more errors, custom error messaging expanded,
API in HTML format.
1/27/99 DLM - added ability to redirect output to a logfile.
7/05/00 NRAW - added the debug and function tracing
===============
Concepts:
A group of new functions has been added to the already
existent ASCDS error library. They have been added with the following
requirements in mind:
- Provide ability to store a large number of errors.
- Provide ability to store multiple instances of a given error.
- Provide standard set of error messages, to give common feel
to error reporting.
- Provide ability to customize error messages.
- Provide various functionality to search through stored messages
and retrieve or remove the error data, either singly, or
multiply.
- Provide ability to directly process errors stored.
- Do not alter/break/remove current functionality of the error library
The errors will range from -32000 to -1 with 0 as a NO_ERROR
value. The space of errors (32000 values) is divided between the
various groups - General, DB, UI, Integ, Pipe/Tools, MTA + V&V, and
any others. As some of those groups should perhaps be divided up
further, the division may not be equal - the Pipe/Tools group may have
a lot of subdivision, and need a larger part of the error space.
Currently there are errors defined for General and Pipe/Tools, but the
Fitting Engine will also get it's own area.
Errors can be stored by either pushing them onto a list of
errors, or putting them into an error instance structure. Errors can
be retrieved from the lists via a number of search criteria. The
searches can also return the first instance of a matching error, or
all matching errors. The same search criteria can be used to remove
errors from a list. Note that searching for an error, will not remove
it if the error is found. Errors must be explicitly removed. In
addition, errors may be specified as individual, or as accumulations.
Any accumulation errors will be stored once, with their count being
incremented each time another such accumulation is added.
Memory Allocation/Deallocation. Provided that the user
creates and populates the list and instance structures via the functions
provided, they will not need to be concerned about managing the memory
for the error library. This includes the memory for the error
messages that will be stored with each instance of an error. These
messages are dynamically sized. This introduces a chance for memory
allocation errors to occur in a number of places within the error
library code. The routines that may experience this return an error
code, which in general will either be dsNOERR, or dsALLOCERR. There
are some cases where a third return value may be possible. It has
been decided that in the case of an allocation error within the error
library, a message will be sent to standard error, notifying the user
of this.
================================================
There are no special concerns or dependencies of the error
library. Simply include it in your link line.
cc main.c -lerr ...
The only include file you will need in your code is liberr.h,
although it does depend on other header files which must be in the
include path:
dserror_database.h
dserror_funcs.h
dserror_general.h
dserror_ptdmtools.h
dserror_ptinstrument.h
dserror_ptanalysis.h
dserror_ptnonsi.h
dserror_signal_handler.h
dserror_structs.h
dserror_trace_fct.h
The code is located in <developement area>/lib/dserror/.
Example code can be found in the dserror_test.c file.
=============
There are some structures and types that the user will need to know
about in order to utilize the added functionality of the error library.
This is a long, with values ranging from -32000
to 0, with 0 as the no error value. This is the type that is
returned by error library functions, and that identifies an
error when it is being added to a list. See the error header
files for the errors that have been defined to date.
dserror_general.h - generic errors
dserror_ptdmtools.h - data model tools errors
dserror_ptinstrument.h - pipe/tools group instrument
tool errors
dserror_ptanalysis.h - pipe/tools group analysis tool
errors
dserror_ptnonsi.h - pipe/tools group non-si tool errors
This identifies a given instance of an error (see
below) as either an individual error, or an accumulation.
Individual errors are useful when you want the same error with
slightly different variations (a file i/o error, that occurs
for more than one file). Accumulations are useful when you
want to note how often a given error occurs, without storing
each instance (such as a coordinate error which could occur
thousands of times within a program).
Values: Accumulation, Individual, Both
This identifies what type of error message is
to be stored in the error instance. This structure is only
used when specifying an error as it is added to a list or when
a dsErrInstance is to be populated, but it tells the function
in question whether to use the generic message, and fill in
the elements with values the user provides, or to expect a
format string from the user, which will be filled with values
the user provides.
Values: Custom, Generic
This defines the severity of the error in
question. Errors are either fatal or warnings, at present,
with the exception of dsNOERR, which has a severity of NONE.
The severity of an error is predefined, but an error list can
be searched on the basis of severity.
Values: None, Warning, Fatal
This is a boolean. False is zero, true is one.
Values: dsErrFalse, dsErrTrue
This is a specific instance of an error.
While a generic error message is defined for each error code,
that message may have elements that need to be filled in (such
as a filename for i/o errors). A dsErrInstance will store the
dsErrCode, it's severity, and a version of the generic message
with any elements filled in. It will also store a count (a long)
of the number of times that error has occurred, if it was an
accumulation error. The count is zero if the Instance has not
been populated.
Elements: dsErr{ dsErrCode;
dsErrSeverity;
dsErrMsg;
}
count (a long, 1 if Individual, 1+ if Accumulation)
error_type_e (indicates Individual/Accumulation)
This is a linked list that holds instances of
errors. New errors can be added to the list, errors can be
searched for, errors can be removed. In general new errors
are added to the end of the list. The exception is
accumulations. When you "add" an accumulation error, and
there is another such accumulation error (same dsErrCode),
then the count of the existent one is incremented. There are
a few elements of a dsErrList that the user may find useful, in
addition to the errors themselves.
Elements: size(long, number of errors total)
contains_fatal(long, number of fatal errors)
contains_warning(long, number of warning errors)
This is a bit mask that defines which group's errors
will be used within the library, when it is initialized. The
generic errors are always used, this bit mask defines which
groups in addition will be utilized.
Values: dsPTGRPERR, dsPTDMGRPERR, dsPTNONSIGRPERR, dsPTINSTRGRPERR,
dsPTANALGRPERR, dsASCFITERR, dsDBGRPERR
dsPTGRPERR is comprised of the 4 other dsPT*GRPERR bit masks.
============
The examples are drawn in part from the dserror_test.c code,
for those who are interested in seeing a working example.
The ASCDS Error library does attempt to take care of memory
management for the user, but with certain caveats. The following
functions must be used to initialize the library, and to create
various structures the user will need, and then to close the library.
In addition, the error lists won't operate correctly if dsErrCreateList
is not used. No guarantees about memory leaks or proper operation of
functions is given if the user starts manipulating the structures directly.
dsErrCode dsErrInitLib(dsErrGroup error_groups_t,
char *tool_name_a)
where
error_groups_t - Input, bit mask that specifies which groups
of errors to use in the error library environment.
tool_name_a - Input, character array, containing the name of
the tool, used by the old initialization routine.
dsErrInitLib() is a wrapper around init_error_lib(), the
previous error library initialization routine(which may still
be used). dsErrInitLib() sets up a hash map which allows it
to associate a dsErrCode with its severity and standard
message. In addition, structures for internal memory
management are initialized.
The following groups are defined:
dsPTGRPERR, dsASCFITERR, dsDBGRPERR
Ex.
dsErrGroup groups_to_add_t = dsDBGRPERR;
dsErrCode local_errstat_t = dsNOERR;
char func_name_a[] = {"this functions name"};
groups_to_add_t |= dsPTGRPERR;
local_errstat_t = dsErrInitLib(groups_to_add_t, func_name);
Return Codes: dsNOERR, dsALLOCERR, dsINITLIBERR
dsErrCode dsErrCreateInstance(dsErrInstance **error_instance_p)
where
error_instance_p - Update, this is the dsErrInstance structure to be
allocated and initialized.
dsErrCreateInstance() takes in a double dsErrInstance pointer,
allocates memory for a dsErrInstance, and assigns it to the
(dereferenced)input pointer. The dsErrInstance elements are
initialized, and the address of the dsErrInstance is added to a
list of dsErrInstances, to handle memory allocation.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
local_errstat_t = dsErrCreateInstance(&holder_p);
Return Codes: dsNOERR, dsALLOCERR
void dsErrResetInstance(dsErrInstance *error_instance_p)
where
error_instance_p - Update, this is the dsErrInstance structure to be
re-initialized.
dsErrResetInstance() frees any memory allocated for the error
message within the instance, and then reinitializes the
elements of the instance.
Ex.
- Initialize library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
local_errstat_t = dsErrCreateInstance(&holder_p);
- populate instance (see dsErrSetInstance(), below)
- print instance (see dsErrPrintInstance(), below)
dsErrResetInstance(holder_p);
dsErrCode dsErrCreateList(dsErrList **error_list_p)
where
error_list_p - Update, pointer to a pointer to a list of dsErrInstances
dsErrCreateList() takes in a double dsErrList pointer,
allocates memory for a dsErrList, and assigns it to the
(dereferenced)input pointer. The dsErrList elements are
initialized, and the address of the dsErrList is added to a
list of dsErrLists, to handle memory allocation.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
local_errstat_t = dsErrCreateList(&base_list_p);
Return Codes: dsNOERR, dsALLOCERR
void dsErrCloseLib()
dsErrCloseLib() frees memory for any dsErrInstances created
via dsErrCreateInstance(), as well as the memory for their
error messages. It also frees any nodes in dsErrLists that
were created via dsErrCreateList(), including the memory
for the error message in each node. The lists are then freed.
Some other cleaning up is also performed.
Ex.
- Initialize error library
- Utilize error library, and when done...
dsErrCloseLib();
void dsErrDirectOutput(FILE *output_p)
where
output_p - Input, file pointer to send output to
dsErrDirectOutput allows the user to send the error messages to
a FILE *, including stderr or stdout. The default is stderr, and
will be set when the library is initialized. There is nothing to
prevent the user from resetting this multiple times in given tool.
Ex.
- Initialize error library
FILE * err_log_p = NULL;
err_log_p = fopen("logfile", "w");
if(err_log_p != NULL)
{
dsErrDirectOutput(err_log_p);
}
The user can either add errors to a dsErrList, or populate
an isolated dsErrInstance. In either case, they must specify the
dsErrCode, what type of message they want to use (the default, or a
custom one), and the type of message. Any additional arguments are
used to fill out the error message (in the case of default), or are
interpreted as the error message (in the case of custom). If the
proper types of arguments are not passed, the error message will end
up with garbage in it.
dsErrCode dsErrAdd(dsErrList *error_list_p,
dsErrCode error_code_t,
dsErrType error_type_e,
dsErrMsgType msg_type_e,
...)
where
error_list_p - Input, error list to add to
error_code_t - Input, error code to add to the list
error_type_e - Input, error type of the error to add: Individual
or Accumulation
msg_type_e - Input, message type of the error to add: Custom
or Generic
... - Input, elements to fill in in generic message,
or the custom error message string and any
elements it requires
dsErrAdd() adds an error to a list. If the error is an individual
error, or the first instance of an accumulation of that error code,
the error is added to the end of the list. Otherwise increment
the counter in the instance of the accumulation found in
the list. The user must specify whether the error is to be an
individual one, or an accumulation, and whether the generic
message will be used, or a custom message provided by the user.
If the former, the ... arguments must fill out the required
elements in the generic message. If the message is to be a
custom one, ... should have a character string as its' first
element. That string may either be the entire custom message,
or a formatting string, of the type used in printf, with
consecutive arguments of the elipsis(...) filling out the
elements in the formatting string. There are some rules about
what types of values are allowed in the messages.
Generic Message Parsing:
The following types of values are allowed:
char (c)
string (s)
short integer (hd)
integer (d)
long integer (ld)
double (e|f|g)
long double (L)(e|f|g)
There is no provision currently for special formating of the
elements. Only the strings in the parenthesis are allowed in
the generic error messages.
Ex.
- initialize library
dsErrList *base_list_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
local_errstat_t = dsErrCreateList(&base_list_p);
local_errstat_t = dsErrAdd(base_list_p, dsALLOCERR, Individual,
Custom,
"This is a custom memory allocation error message\n");
or
local_errstat_t = dsErrAdd(base_list_p, dsEVENTCOORDSERR,
Accumulation, Generic, NULL);
and so on, varying the arguments for dsErrType and dsErrMsgType.
Return Codes: dsNOERR, dsALLOCERR, dsUNDEFERR(an undefined
value, positive for example, was passed in for the error code)
dsErrCode dsErrSetInstance(dsErrCode error_code_t,
dsErrType error_type_e,
dsErrMsgType msg_type_e,
dsErrInstance *error_instance_p,
...)
where
error_code_t - Input, error code to add to the list
error_type_e - Input, error type of the error to add: Individual
or Accumulation
msg_type_e - Input, message type of the error to add: Custom
or Generic
error_instance_p - Output, error instance to populate.
... - Input, elements to fill in generic message
dsErrSetInstance() follows the same rules as dsErrAdd() except
that instead of adding a new node, error_instance_p is
repopulated. In the case that an accumulation is set, if
error_instance_p is already populated by an accumulation of the
same dsErrCode, the count will be incremented.
Ex.
- initialize library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
local_errstat_t = dsErrCreateInstance(&holder_p);
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual, Generic, holder_p,
"foo", "not-a-file", "double") == dsNOERR)
Return Codes: dsNOERR, dsALLOCERR, dsUNDEFERR(an undefined
value, positive for example, was passed in for the error code)
dsErrCode dsErrAddToEnd(dsErrList *error_list_p,
dsErrInstance *error_to_add_p)
where
error_list_p - Input, list to add the error to
error_to_add_p - Input, error instance to add
dsErrAddToEnd() takes a pointer to a dsErrInstance that has already
been populated, and adds it to the input error list, at the end.
No effort is made to handle situations in which the error is
an instance of an accumulation that already exists in the list.
Ex.
- Initialize library
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
local_errstat_t = dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double");
if(local_errstat_t == dsNOERR)
dsErrAddToEnd(base_list_p, holder_p);
}
Return Codes: dsNOERR, dsALLOCERR
The user can search a list of errors in a number of ways.
They can search by location, search for a specific error code, or
search for a given severity. They can also search for only the first
match, or they can search for all matches. In the first case they
must provide a dsErrInstance to populate, in the second they must
provide a dsErrList. Searches can be done in an exclusive manner, rather
than inclusive. In addition there are a number of functions that mimic
the functionality of the "Look" functions, but rather than copying the
data, they return a dsErrInstance pointer to the errors found. These
are the "Peek" functions (there are no PeekAll functions, for obvious
reasons).
dsErrCode dsErrLook(dsErrList *error_list_p,
dsErrInstance *out_instance_p)
where
error_list_p - Input, error list to look in
out_instance_p - Output, error instance structure to populate with
results of search
dsErrLook() copies the first error in error_list_p to out_instance_p.
If there are no errors in the list, dsERRNOTFOUNDERR is returned.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if(dsErrLook(base_list_p, holder_p) == dsNOERR)
.
.
.
Return Codes: dsNOERR, dsALLOCERR, dsERRNOTFOUNDERR
dsErrCode dsErrLookN(dsErrList *error_list_p,
long N,
dsErrInstance *out_instance_p)
where
error_list_p - Input, error list to look in
N - Input, element in the list to find
out_instance_p - Output, error instance structure to populate with
results of search
dsErrLookN() finds the Nth error in the error list and copies
it into out_instance_p. If N is larger than the number of
elements in the list, or if N is less than 1, dsERRNOTFOUNDERR
is returned. N starts counting at 1.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if(dsErrLookN(base_list_p, 1, holder_p) == dsNOERR)
.
.
.
Return Codes: dsNOERR, dsALLOCERR, dsERRNOTFOUNDERR
dsErrCode dsErrLookCode(dsErrList *error_list_p,
dsErrCode error_code_t,
dsErrType error_type_e,
dsErrInstance *out_instance_p)
where
error_list_p - Input, error list to look in
error_code_t - Input, error code to search for
error_type_e - Input, error type to search for
out_instance_p - Output, error instance structure to populate with
results of search
dsErrLookCode() searches error_list_p for the first instance
of an error whose code matches error_code_t, and whose type
matches error_type_e. If error_type_e is Both, then either
Individual or Accumulations will be matched. If a match is
found, it is copied to out_instance_p, otherwise dsERRNOTFOUNDERR
is returned.
Ex.
- Initialize error library,
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if(dsErrLookCode(base_list_p, dsEVENTCOORDSERR, Both, holder_p)
== dsNOERR)
.
.
.
or
if(dsErrLookCode(base_list_p, dsEVENTCOORDSERR, Accumulation,
holder_p) == dsNOERR)
.
.
.
and so forth.
Return Codes: dsNOERR, dsALLOCERR, dsERRNOTFOUNDERR
dsErrCode dsErrLookCodeExcl(dsErrList *error_list_p,
dsErrCode error_code_t,
dsErrType error_type_e,
dsErrInstance *out_instance_p)
where
error_list_p - Input, error list to look in
error_code_t - Input, error code to exclude
error_type_e - Input, error type to exclude
out_instance_p - Output, error instance structure to populate with
results of search
dsErrLookCodeExcl() operates in the same manner as dsErrLookCode(), except
that it searches for the first instance that does not match the input code
and type.
Return Codes: dsNOERR, dsALLOCERR
dsErrCode dsErrLookSev(dsErrList *error_list_p,
dsErrSeverity err_severity_e,
dsErrInstance *out_instance_p)
where
error_list_p - Input, error list to look in
error_severity_t - Input, error severity to search for
out_instance_p - Output, error instance structure to populate with
results of search
dsErrLookSev() searches error_list_p for the first error that
matches the input severity type. If a match is found, it is
copied to out_instance_p, else dsERRNOTFOUNDERR is returned.
Ex.
- Initialize error library,
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if(dsErrLookSev(base_list_p, Fatal, holder_p) == dsNOERR)
.
.
.
Return Codes: dsNOERR, dsALLOCERR, dsERRNOTFOUNDERR
dsErrCode dsErrLookAllSev(dsErrList *in_list_p,
dsErrSeverity err_severity_e,
dsErrList *out_list_p)
where
in_list_p - Input, error list to look in
error_severity_t - Input, error severity to search for
out_list_p - Output, error list to populate with results of
search
dsErrLookAllSev() searches in_list_p for all errors with the
input severity, and copies them to out_list_p, in the order
they were found.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
dsErrList *new_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR &&
dsErrCreateList(&new_list_p) == dsNOERR)
{
- populate base_list_p
if(dsErrLookAllSev(base_list_p, Fatal, new_list_p) == dsNOERR)
.
.
.
Return Codes: dsNOERR, dsALLOCERR
dsErrCode dsErrLookAllCode(dsErrList *in_list_p,
dsErrCode error_code_t,
dsErrType error_type_e,
dsErrList *out_list_p)
where
in_list_p - Input, error list to look in
error_code_t - Input, error code to search for
error_type_e - Input, error type to search for
out_list_p - Output, error list to populate with results of search
dsErrLookAllCode() searches in_list_p for all errors whose code
matches error_code_t, and whose type matches error_type_e. If
error_type_e is Both, then either Individual or Accumulations
will be matched. All matches are copied into out_list_p in
the order they were found.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrList *base_list_p = NULL;
dsErrList *new_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR &&
dsErrCreateList(&new_list_p) == dsNOERR)
{
- populate base_list_p
if(dsErrLookAllCode(base_list_p, dsEVENTCOORDSERR, Individual,
new_list_p) == dsNOERR)
.
.
.
and so forth.
Return Codes: dsNOERR, dsALLOCERR
dsErrCode dsErrLookAllCodeExcl(dsErrList *in_list_p,
dsErrCode error_code_t,
dsErrType error_type_e,
dsErrList *out_list_p)
where
in_list_p - Input, error list to look in
error_code_t - Input, error code to exclude
error_type_e - Input, error type to exclude
out_list_p - Output, error list to populate with results of search
dsErrLookAllCodeExcl() operates as dsErrLookAllCode() does, except it
searches for all errors that do not match the input code and type.
Return Codes: dsNOERR, dsALLOCERR
long dsErrGetNumOccur(dsErrList *error_list_p,
dsErrCode error_code_t,
dsErrType error_type_e)
where
error_list_p - Input, the error list to look in
error_code_t - Input, error code to search for
error_type_e - Input, error type to search for
dsErrGetNumOccur() searches error_list_p for all errors whose code
matches error_code_t, and whose type matches error_type_e. If
error_type_e is Both, then either Individual or Accumulations
will be matched. If an error is matched, then the count of that error
is added to the value that will be returned. This is not to be
confused with returning the number of nodes in the list that
match the conditions. Accumulations can have a count well above one,
and the returned value will represent that.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
long error_count = dsErrGetNumOccur(base_list_p, dsEVENTCOORDSERR,
Individual);
printf("The number of dsEVENTCOORDSERRs is: %ld\n", error_count);
}
dsErrInstance *dsErrPeek(dsErrList *error_list_p)
where
error_list_p - Input, error list to look in
dsErrPeek() returns a pointer to the first error in error_list_p.
If there are no errors in the list, NULL is returned.
Ex.
- Initialize error library
dsErrInstance *pointer_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if((pointer_p = dsErrPeek(base_list_p)) != NULL)
.
.
.
Return Values: NULL or valid address
dsErrInstance *dsErrPeekN(dsErrList *error_list_p,
long N)
where
error_list_p - Input, error list to look in
N - Input, element in the list to find
dsErrPeekN() finds the Nth error in the error list and returns its'
address. If N is larger than the number of elements in the list,
or if N is less than 1, NULL is returned. N starts counting at 1.
Ex.
- Initialize error library
dsErrInstance *pointer_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if((pointer_p = dsErrPeekN(base_list_p, 1)) != NULL)
.
.
.
Return Values: NULL or valid address
dsErrInstance *dsErrPeekCode(dsErrList *error_list_p,
dsErrCode error_code_t,
dsErrType error_type_e)
where
error_list_p - Input, error list to look in
error_code_t - Input, error code to search for
error_type_e - Input, error type to search for
dsErrPeekCode() searches error_list_p for the first instance
of an error whose code matches error_code_t, and whose type
matches error_type_e. If error_type_e is Both, then either
Individual or Accumulations will be matched. If a match is
found, its address is returned, otherwise NULL is returned.
Ex.
- Initialize error library,
dsErrInstance *pointer_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if((pointer_p = dsErrPeekCode(base_list_p, dsEVENTCOORDSERR, Both))
!= NULL)
.
.
.
or
if(dsErrLookCode(base_list_p, dsEVENTCOORDSERR, Accumulation,
holder_p) == dsNOERR)
.
.
.
and so forth.
Return Values: NULL or valid address
dsErrInstance *dsErrPeekCodeExcl(dsErrList *error_list_p,
dsErrCode error_code_t,
dsErrType error_type_e)
where
error_list_p - Input, error list to look in
error_code_t - Input, error code to exclude
error_type_e - Input, error type to exclude
dsErrPeekCodeExcl() operates in the same manner as dsErrPeekCode(), except
that it searches for the first instance that does not match the input code
and type.
Return Values: NULL or valid address
dsErrInstance *dsErrPeekSev(dsErrList *error_list_p,
dsErrSeverity err_severity_e)
where
error_list_p - Input, error list to look in
error_severity_t - Input, error severity to search for
dsErrPeekSev() searches error_list_p for the first error that
matches the input severity type. If a match is found, its
address is returned, else NULL is returned.
Ex.
- Initialize error library,
dsErrInstance *pointer_p = NULL;
dsErrList *base_list_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR &&
dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate error list
if((pointer_p = dsErrPeekSev(base_list_p, Fatal)) != NULL)
.
.
.
Return Values: NULL or valid address
In all the remove functions, memory that was allocated for the
error that is removed, and the node, is freed in the function.
dsErrBool dsErrRemove(dsErrList *error_list_p)
where
error_list_p - Input, error list to Remove in
dsErrRemove() removes the first error in error_list_p.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemove(base_list_p);
.
.
.
Return Codes: dsErrTrue, dsErrFalse
dsErrBool dsErrRemoveN(dsErrList *error_list_p,
long N)
where
error_list_p - Input, error list to Remove in
N - Input, element in the list to find
dsErrRemoveN() finds the Nth error in the error list and removes
it. If N is larger than the number of elements in the list,
or if N is less than 1, dsErrFalse is returned. N starts
counting at 1.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
long element_to_remove = 2;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemoveN(base_list_p, element_to_remove);
.
.
.
Return Codes: dsErrTrue, dsErrFalse
dsErrBool dsErrRemoveCode(dsErrList *error_list_p,
dsErrBool error_code_t,
dsErrType error_type_e)
where
error_list_p - Input, error list to Remove in
error_code_t - Input, error code to search for
error_type_e - Input, error type to search for
dsErrRemoveCode() searches error_list_p for the first instance
of an error whose code matches error_code_t, and whose type
matches error_type_e. If error_type_e is Both, then either
Individual or Accumulations will be matched. If a match is
found, it is removed, otherwise dsErrFalse is returned.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemoveCode(base_list_p, dsALLOCERR, Individual);
or
dsErrRemoveCode(base_list_p, dsEVENTCOORDSERR, Accumulation);
and so forth
.
.
.
Return Codes: dsErrTrue, dsErrFalse
dsErrBool dsErrRemoveSev(dsErrList *error_list_p,
dsErrSeverity err_severity_e)
where
error_list_p - Input, error list to Remove in
error_severity_t - Input, error severity to search for
dsErrRemoveSev() searches error_list_p for the first error that
matches the input severity type. If a match is found, it is
removed, else dsErrFalse is returned.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemoveSev(base_list_p, Fatal);
.
.
.
Return Codes: dsErrTrue, dsErrFalse
dsErrBool dsErrRemoveAll(dsErrList *error_list_p)
where
error_list_p - Input, error list to Remove errors from
dsErrRemoveAll() removes all the errors from a list. It
returns dsErrFalse only if there were no errors to remove.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemoveAll(base_list_p);
.
.
.
Return Codes: dsErrTrue, dsErrFalse
dsErrBool dsErrRemoveAllSev(dsErrList *in_list_p,
dsErrSeverity err_severity_e)
where
in_list_p - Input, error list to Remove in
error_severity_t - Input, error severity to search for
dsErrRemoveAllSev() searches in_list_p for all errors with the
input severity, and removes them.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemoveAllSev(base_list_p, Fatal);
.
.
.
Return Codes: dsErrTrue, dsErrFalse
dsErrBool dsErrRemoveAllCode(dsErrList *in_list_p,
dsErrBool error_code_t,
dsErrType error_type_e)
where
in_list_p - Input, error list to Remove in
error_code_t - Input, error code to search for
error_type_e - Input, error type to search for
dsErrRemoveAllCode() searches in_list_p for all errors whose code
matches error_code_t, and whose type matches error_type_e. If
error_type_e is Both, then either Individual or Accumulations
will be matched. All matches are removed.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
dsErrRemoveAllCode(base_list_p, dsALLOCERR, Individual);
or
dsErrRemoveAllCode(base_list_p, dsEVENTCOORDSERR, Accumulation);
and so forth
.
.
.
Return Codes: dsErrTrue, dsErrFalse
These functions are all wrappers around the existent error
processing routines in the error library; err_msg, err_exit, err_quit,
err_ret, and err_dump. See the other error lib document for more
information on what these tasks do.
There is only one function that will process an entire list,
dsErrPrintList(). This is a wrapper around err_msg(), which is the
only one of the above five functions that does not return or exit the
program.
All of the processing functions take an argument specifying
whether or not they should print out the number of times an
accumulation error occurs. If the user says yes, then the following
string will be prepended to the dsErrInstance error message:
"The following error occurred %d times:\n\t%s"
where %d is filled in with the number of times the error
occurred, and %s is the actual error message. The user will not
need to supply these, it is done internally to the functions.
void dsErrPrintList(dsErrList *error_list_p,
dsErrBool print_accum_e)
where
error_list_p - Input, list to print
print_accum_e - Input, flag indicating whether or not to print
the count of an accumulation error.
dsErrPrintList() is a wrapper around the existent error
library function err_msg(). It will print the dsErrInstance's
error message to stderr for each node in the list.
Ex.
- Initialize error library
dsErrList *base_list_p = NULL;
if(dsErrCreateList(&base_list_p) == dsNOERR)
{
- populate base_list_p
.
.
.
}
dsErrPrintList(base_list_p, dsErrTrue);
void dsErrPrintInstance(dsErrInstance *error_instance_p,
dsErrBool print_accum_e)
where
error_instance_p - Input, instance to print
print_accum_e - Input, flag indicating whether or not to print
the count of an accumulation error.
dsErrPrintInstance() is a wrapper around err_msg(). It prints
the dsErrInstance's error message to stderr.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrPrintInstance(holder_p, dsErrTrue);
}
}
void dsErrReturnInstance(dsErrInstance *error_instance_p,
dsErrBool print_accum_e)
where
error_instance_p - Input, instance to print
print_accum_e - Input, flag indicating whether or not to print
the count of an accumulation error.
dsErrReturnInstance() is a wrapper around err_ret(). It prints
the dsErrInstance's error message to stderr, and returns.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrReturnInstance(holder_p, dsErrTrue);
}
}
void dsErrExitInstance(dsErrInstance *error_instance_p,
dsErrBool print_accum_e)
where
error_instance_p - Input, instance to print
print_accum_e - Input, flag indicating whether or not to print
the count of an accumulation error.
dsErrExitInstance() is a wrapper around err_exit(). It prints
the dsErrInstance's error message to stderr, and terminates.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrExitInstance(holder_p, dsErrTrue);
}
}
void dsErrQuitInstance(dsErrInstance *error_instance_p,
dsErrBool print_accum_e)
where
error_instance_p - Input, instance to print
print_accum_e - Input, flag indicating whether or not to print
the count of an accumulation error.
dsErrQuitInstance() is a wrapper around err_quit(). It prints
the dsErrInstance's error message to stderr, and terminates.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrQuitInstance(holder_p, dsErrTrue);
}
}
void dsErrDumpInstance(dsErrInstance *error_instance_p,
dsErrBool print_accum_e)
where
error_instance_p - Input, instance to print
print_accum_e - Input, flag indicating whether or not to print
the count of an accumulation error.
dsErrDumpInstance() is a wrapper around err_dump(). It prints
the dsErrInstance's error message to stderr, dumps core, and
terminates.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
dsErrCode local_errstat_t = dsNOERR;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrDumpInstance(holder_p, dsErrTrue);
}
}
===========================================================
The following are a series of simple accessor functions that return
various data members of the dsErrLists and dsErrInstances.
long dsErrGetErrorCt(dsErrList *error_list_p)
where
error_list_p - Input, error list to get the number of nodes of
dsErrGetErrorCt() returns the number of dsErrInstances (essentially
the number of nodes) in the input error list.
Ex.
- Initialize error library
dsErrList *list_p = NULL;
if(dsErrCreateList(&list_p) == dsNOERR)
{
- populate the list...
long list_size = dsErrGetErrorCt(list_p);
printf("The number of errors in the list is %ld.\n", list_size);
}
long dsErrGetFatalCt(dsErrList *error_list_p)
where
error_list_p - Input, error list to get the number of fatal errors of
dsErrGetFatalCt() returns the number of dsErrInstances (essentially
the number of nodes) in the input error list with a severity of
Fatal.
Ex.
- Initialize error library
dsErrList *list_p = NULL;
if(dsErrCreateList(&list_p) == dsNOERR)
{
- populate the list...
long list_size = dsErrGetFatalCt(list_p);
printf("The number of fatal errors in the list is %ld.\n", list_size);
}
long dsErrGetWarningCt(dsErrList *error_list_p)
where
error_list_p - Input, error list to get the number of warnings of
dsErrGetWarningCt() returns the number of dsErrInstances (essentially
the number of nodes) in the input error list with a severity of
Warning.
Ex.
- Initialize error library
dsErrList *list_p = NULL;
if(dsErrCreateList(&list_p) == dsNOERR)
{
- populate the list...
long list_size = dsErrGetWarningCt(list_p);
printf("The number of warnings in the list is %ld.\n", list_size);
}
long dsErrGetInstCt(dsErrInstance *error_instance_p)
where
error_instance_p - Input, error instance to return the value of the
count accumulator of.
dsErrGetInstCt() returns the value of the count element of the data
structure, which for an Individual error will be one, and for
Accumulations may be greater than one.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
long instance_count = dsErrGetInstCt(holder_p);
printf("The number of times the dsCOLUMNTYPEERR occurred is:");
printf(" %ld\n", instance_count);
}
}
dsErrCode dsErrGetInstCode(dsErrInstance *error_instance_p)
where
error_instance_p - Input, error instance to return the value of the
dsErrCode.
dsErrGetInstCode() returns the dsErrCode of the error stored within the
dsErrInstance, which is essentially a long.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrCode instance_code = dsErrGetInstCode(holder_p);
printf("The error code of dsCOLUMNTYPEERR is:");
printf(" %ld\n", instance_code);
}
}
dsErrSeverity dsErrGetInstSev(dsErrInstance *error_instance_p)
where
error_instance_p - Input, error instance to return the value of the
dsErrSeverity.
dsErrGetInstCode() returns the dsErrSeverity of the error stored within
the dsErrInstance.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
dsErrSeverity instance_sev = dsErrGetInstSev(holder_p);
printf("The error severity of dsCOLUMNTYPEERR is:");
printf(" %s\n", ((instance_sev == Fatal) ? "Fatal" : "Warning"));
}
}
dsErrMsg dsErrGetInstMsg(dsErrInstance *error_instance_p)
where
error_instance_p - Input, error instance to return the value of the
dsErrMsg.
dsErrGetInstCode() returns the dsErrMsg of the error stored within
the dsErrInstance, which is essentially a char *.
Ex.
- Initialize error library
dsErrInstance *holder_p = NULL;
if(dsErrCreateInstance(&holder_p) == dsNOERR)
{
if(dsErrSetInstance(dsCOLUMNTYPEERR, Individual,
Generic, holder_p, "foo",
"not-a-file", "double") == dsNOERR)
{
printf("The error message of dsCOLUMNTYPEERR is:");
printf(" %s\n", dsErrGetInstMsg(holder_p));
}
}
The error library has a singal handler for three signals:
SIGSEGV (segmentation violation), SIGFPE (floating point error),
and SIGILL (illegal instruction). The user is strongly suggested to
add the following line to their main before initializing the error library:
setjmp(dserr_jmpbuf);
This will allow the error library to have a location to junp to in the
case of catching one of these signals.
===================================
An error in the DS error library is defined by three elements:
an Error Code, a Severity, and a Standard Message. The following
serve as examples:
#define dsNOERR dsGENERALERROFFSET
#define dsNOERRSEV dsERRSEVNONE
#define dsNOERRSTDMSG ""
and
#define dsGENERICERR (dsGENERALERROFFSET - 1)
#define dsGENERICSEV dsERRSEVWARNING
#define dsGENERICSTDMSG "WARNING: An unspecified error has occurred.\n"
These are the first two errors defined in the error library.
In general the format is:
#define dsERR (ds - )
#define dsSEV dsERRSEVWARNING/dsERRSEVFATAL
#define dsSTDMSG ""
#define dsERR (ds - )
The error number is usually defined relative to an offset.
There are two sorts of offsets, one for groups, and one for subgroups.
The group offsets tend to be larger, and are defined on the basis of
teams or large projects. So far the group offsets are:
dsGENERALERROFFSET 0
dsPTDMTOOLERROFFSET -2000
dsPTINSTRUMENTERROFFSET -3000
dsPTANALYSISERROFFSET -4000
dsPTNONSIERROFFSET -5000
dsDATABASEERROFFSET -8000
There will also be one for the ASC Fitting Engine, and most
likely a separate offset for the Pixlib, although both of those are
maintained by the Pipe/Tools team.
The subgroups are currently only used within the general
errors group, as this is the one most likely to have new errors
inserted, rather than merely appended. They are defined as follows:
dsGENCOLKEYOFFSET (dsGENERALERROFFSET - 25)
dsGENFIOOFFSET (dsGENCOLKEYOFFSET - 25)
dsGENDMOFFSET (dsGENFIOOFFSET - 25)
dsGENPARAMOFFSET (dsGENDMOFFSET - 50)
dsGENASCFITOFFSET (dsGENPARAMOFFSET - 25)
dsGENTIMEOFFSET (dsGENASCFITOFFSET - 25)
dsGENSTACKOFFSET (dsGENTIMEOFFSET - 25)
As can be seen, they are defined in a chain like manner, and
set the starting point for various smaller groups of errors. It is
important to note, that if a sub group grows beyond 25 errors, then
these numbers will need to be modified, i.e., if the parameter errors
(governed by the dsGENPARAMOFFSET) grow to 27 errors, then they will
overlap with the ASCFit errors (governed by dsGENASCFITOFFSET). In
that case dsGENASCFITOFFSET should be redefined to dsGENPARAMOFFSET - 50.
#define dsSEV dsERRSEVWARNING/dsERRSEVFATAL
There are only two options for this, dsERRSEVWARNING or dsERRSEVFATAL.
#define dsSTDMSG ""
This can be whatever is desired, and may contain % type
elements, like the formating strings used in printf and so forth, with
the restrictions outlined in section 5.2.1 about parsing. The string
must start with either ERROR or WARNING, depending on the severity,
and should end in a newline.
The errors are defined in a group of header files, which are
defined by the groups in the ASCDS. Currently there is a header file
for the Pipe Tools team, and the Database team. If you are a member
of one of those teams, then your error should go into one of those
headers, with the exception of generic errors. The generic error
header file contains errors that anyone in the ASCDS or even within a
group, is likely to run into. They are errors that have to do with
interfaces to libraries (stack, param, ASCFit, Data Model),
allocation errors, file I/O and so forth. The following are the
existent error header files:
dserror_general.h ----> generic errors
dserror_database.h ---> errors for the database team
dserror_pt{var}.h ----> various headers that include errors
for the pipe/tools teams, grouped by
broad categories
If the error that is being added does not belong in one of
these headers (i.e, it is not generic, and is a new group), then the
maintainer of the error library needs to be contacted in order to add
a new header file to the library. Otherwise, the individual will be
able to add the error to the library on their own.
In order to do this, the three elements of the new error are
added to the header file. If the new error is inserted into the
header file, rather than appended to the end, then the error number
value of all consecutive errors must be adjusted - the errors should
be define in numerical order in the header file. In either case, in
each header file there is a macro that defines the number of errors in
that header file. This has to be updated to reflect the addition of
the new error(s).
Please NOTE: If you are adding a series of errors, that
pertain to a tool/library, to a group initialization function, please
precede them with a comment indicating the tool/library that they
pertain to. This way groupings can be easier to discern. Likewise
for a series of generic errors that have a common thread.
Provided that the new error(s) have been added to a header
file that already exists, the last thing the user needs to do is to
modify one of a number of initialization helper functions. In the C
file dserror_init.c there are a number of functions that help the
dsErrInitLib() function. They are dsErrInitGeneralErr(),
dsErrInitPTErr(), and dsErrInitDBErr(), and they correspond to one of
each of the header files. Each of them calls
dsErrInitHashMapElement() a number of times. In order to add a new
error, add another call to the appropriate init function, substituting
the macros that you defined for the error. It is very important that
the errors in the library be initialized in numerical order. To that
end it is best to define them in the header file in numerical order,
and then have the dsErrInitHashMapElement() calls occur in the same
order the errors were defined in. Thus, if an error is INSERTED into
the header file, it will need to be inserted into the function call in
the initialization routine, in the same location. If an error is
merely added to the end of a header file, then add the function call
to the end of the initialization routine.
That is what is required to add an error to the library.
Please NOTE: If you are adding to a groups initialization
function a series of errors that pertain to a tool/library,
please precede them with a comment indicating the tool/library
that they pertain to. This way groupings can be easier to
discern. Likewise for a series of generic errors that have a
common thread.
===================================
In code development, it is sometimes difficult to determine
which function an error is occurring in. To help following the function
calls made, the error library supplies some functions to trace the
function calls. The functions called are tracked by means of a
heap/stack. All function tracing routines are described in detail
below.
The user must begin by calling the function init_function_stack().
After entering a function, the user must call check_in("function
name"). This will add the "function name" onto the heap of functions
that have been called. Before exiting a function, the user must call
check_out() to clear the function stack of this function. The internal
data structure used is a stack given its first-in-last-out (filo)
model.
Below are the public routines for function tracing
void init_function_stack(char * name,
int print_it,
int num_fct_to_print)
where
name - Input, name of the program, preferably argv[0]
print_it - Input, print messages upon entry and exit
of a function
num_fct_to_print - Input, if positive, only the requested
number of function names will be printed,
otherwise, all of the function names will
be printed.
init_function_stack() sets the output options for using the
function tracing. The stack is set to NULL in this function.
Ex.
- Initialize the function stack
init_function_stack("my_code",1,-1);
will use "my_code" as the main program name and will print
out messages for all functions
void check_in(char * name)
where
name - Input, function name to be added to the
stack
check_in() will added the name to the stack. If print_it was
set, a message will be printed here.
Ex
int my_function(void)
{
int print_flag=1;
check_in("my_function"); /* checks in the function */
if (print_flag)
printf("Hello World!\n");
check_out(); /*check out the function */
}
void check_out()
check_out() will remove the top function name on the stack.
If print_it was set, a message will be printed here.
Ex
int my_function(void)
{
int print_flag=1;
check_in("my_function"); /* checks in the function */
if (print_flag)
printf("Hello World!\n");
check_out(); /*check out the function */
}
int exit_upon_error(long exit_code,
char * format,
...)
where
exit_code - Input, exit value to test. If non-zero,
this routine will force the program to
exit with this value.
format - Input, format string including the
standard C format codes.
... - Input, any arguments to the format
string
exit_upon_error() will check if the exit_code is non-zero. If
it is, then the format string and any extra variables are
printed via vfprintf. It is the user's responsibility to supply
all arguments needed. A segmentation violation may occur if a
variable substitution is to occur and the variable is not supplied.
Ex.
foo=my_function();
exit_upon_error(foo,"my_function failed with error code %d\n",foo);
NOTE:
It is bad practice for the user to use this function for
anything, but debugging purposes. To exit within a function
will prevent other libraries from properly closing down and may
prevent other error messages from being reported.
void print_function_stack(FILE * fp)
where
fp - Input, function stack is printed to
this file stream
print_function_stack() will print the current function stack
when called.
Ex.
foo=my_function();
print_function_stack(stderr); /* print the function stack */
NOTE:
In general, this should only be used for debugging purposes.
=============================
Errors in the dserror_general.h file:
Various Misc: allocation, divide by zero, null ptr received, etc.
Column and Keyword Errors.
File I/O Errors.
*Data Model Errors.
*Parameter Library Errors.
*ASC Fitting Engine Errors.
Timing Errors.
*Stack Library Errors.
* These aren't errors that occur within the named library, but occur
in utilizing it within a tool, i.e., a library function failed, etc.
Errors in the dserror_ptdmtools.h file:
dmhedit
dmsort
dmwritefef
dmextract
dmregrid
Errors in the dserror_ptinstrument.h file:
acis_process_events
acis_format_events
acis_collate_events
acis_build_chip_gti
acis_merge_gti
hrc_process_events
hrc_calc_dead_time
hrc_build_badpix
hrc_merge_times
tg_resolve_events
tg_create_mask
Errors in the dserror_ptnonsi.h file:
mtl_build_table
mtl_build_gti
asp_calc_offsets
asphist
ephem_calc_vg_angles
tel_data_clean
sim_data_select
sim_compute_stf_pos
obi_merge_times
obi_sim_look
obi_eng_look
obi_asp_look
obi_check_tol
calc_mean_pointing
obi_acishk_look
obi_hrchk_look
obspar_upd
Errors in the dserror_ptanalysis.h file:
wrecon
wtransform
celldetect
bkgd_calc_global_count_rate
tcd specific
csmooth
rmfcalc
lightcurve