166 lines
4.8 KiB
C
166 lines
4.8 KiB
C
/* qlib.h - run-time library */
|
|
|
|
/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */
|
|
|
|
|
|
#ifndef QLIB_H
|
|
#define QLIB_H
|
|
|
|
#ifdef DUMP_MODE
|
|
#define PREFIX(x) qd_##x
|
|
#else
|
|
#define PREFIX(x) q_##x
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Severity codes used by the run-time library. Surprisingly, they happen to
|
|
* have the same numerical values as their corresponding atmsigd counterparts.
|
|
*/
|
|
|
|
#define Q_DEBUG 3
|
|
#define Q_ERROR 0
|
|
#define Q_FATAL -1
|
|
|
|
|
|
extern int q_dump;
|
|
extern void q_report(int severity,const char *msg,...);
|
|
|
|
#ifdef DUMP_MODE
|
|
#ifndef STANDALONE
|
|
extern void qd_dump(const char *fmt,...);
|
|
#endif
|
|
extern void qd_report(int severity,const char *msg,...);
|
|
#endif
|
|
|
|
|
|
typedef enum {
|
|
qet_catch_zero,
|
|
qet_space, /* length of message area exceeds length of surroundings */
|
|
qet_case, /* case value not found */
|
|
qet_abort, /* user abort */
|
|
qet_init /* fatal initialization error. DO NOT PROCEED ! */
|
|
} Q_ERR_TYPE;
|
|
|
|
typedef struct _q_err_dsc {
|
|
Q_ERR_TYPE type; /* error type code */
|
|
int pc; /* PC when error was discovered */
|
|
int offset; /* offset into message when error was discovered */
|
|
int value; /* additional value (optional) */
|
|
int id; /* user-assigned id */
|
|
int start; /* recovery area */
|
|
int length;
|
|
int group; /* group that failed (for fixups) */
|
|
struct _q_err_dsc *next;
|
|
} Q_ERR_DSC;
|
|
|
|
typedef struct {
|
|
unsigned char *data;
|
|
unsigned char *required;
|
|
unsigned char *field_present;
|
|
unsigned long *group_present;
|
|
int *length;
|
|
int *field_map;
|
|
int *group_map; /* @@@ useless overhead until we allow nested structures */
|
|
void *buffer;
|
|
int buf_size;
|
|
int error;
|
|
Q_ERR_DSC *errors;
|
|
} Q_DSC;
|
|
|
|
|
|
/*
|
|
* *_START intializes global data structures and needs to be invoked before any
|
|
* other function of qlib.
|
|
*/
|
|
|
|
void PREFIX(start)(void);
|
|
|
|
/*
|
|
* *_OPEN opens an existing Q.2931 message (pointed to be BUF and of size
|
|
* SIZE), parses its contents, and initializes the descriptor for further use
|
|
* by Q_PRESENT, etc. *_OPEN returns zero on success, -1 if any problem has
|
|
* been discovered with the message. In the latter case, the error list on
|
|
* DSC.errors should be examined. Note that parts of the message may still be
|
|
* valid and can be accessed with the usual functions. (Actually, because
|
|
* invalid or unrecognized fields will simply be treated as absent, code that
|
|
* tests for presence of mandatory elements does not need to examine the
|
|
* error list. Not that, however, an error report of type QET_INIT carries
|
|
* incomplete information and must not be examined beyond the TYPE element.
|
|
* Also, _all_ calls to Q_PRESENT will return zero in this case.) The
|
|
* descriptor must be closed with *_CLOSE even if *_OPEN fails.
|
|
*/
|
|
|
|
int PREFIX(open)(Q_DSC *dsc,void *buf,int size);
|
|
|
|
/*
|
|
* Q_CREATE initializes the descriptor DSC points to. It also registers the
|
|
* message area (to be used by Q_CLOSE) starting at BUF and of size SIZE in the
|
|
* descriptor. Q_CREATE returns zero on success, -1 on failure. *_CLOSE does
|
|
* not need to be called if Q_CREATE fails.
|
|
*/
|
|
|
|
int q_create(Q_DSC *dsc,void *buf,int size);
|
|
|
|
/*
|
|
* Deallocates resources from the specified descriptor. If the descriptor was
|
|
* initialized by Q_CREATE and if no error occurred, the message is composed
|
|
* and *_CLOSE returns its size in bytes. In all other cases, *_CLOSE returns
|
|
* zero on success, -1 on failure. Note that *_CLOSE also clears the error
|
|
* list.
|
|
*/
|
|
|
|
int PREFIX(close)(Q_DSC *dsc);
|
|
|
|
/*
|
|
* Q_ASSIGN sets the specified field to VALUE. Q_ASSIGN can only be used with
|
|
* fixed-length fields of a size less than sizeof(unsigned long)*8 bits. Note
|
|
* that the values of fields with associated groups can't be changed.
|
|
*/
|
|
|
|
void q_assign(Q_DSC *dsc,int field,unsigned long value);
|
|
|
|
/*
|
|
* Like Q_ASSIGN, but for all fields (without associated groups) whose size is
|
|
* a multiple of one byte.
|
|
*/
|
|
|
|
void q_write(Q_DSC *dsc,int field,const void *buf,int size);
|
|
|
|
/*
|
|
* Checks the presence of the specified field (QF_*) or group (QG_*). Returns
|
|
* one if the field or group is present, zero otherwise.
|
|
*/
|
|
|
|
int q_present(const Q_DSC *dsc,int field);
|
|
|
|
/*
|
|
* Returns the value of the specified fields. Be warned that Q_FETCH does not
|
|
* check if the fields is present or if its content fits in an unsigned long.
|
|
*/
|
|
|
|
unsigned long q_fetch(const Q_DSC *dsc,int field);
|
|
|
|
/*
|
|
* Like Q_FETCH, but for byte-aligned fields of arbitrary size (as long as it's
|
|
* a multiple of one byte). BUF points to a buffer and SIZE is its size. Q_READ
|
|
* returns how many bytes were written to that buffer.
|
|
*/
|
|
|
|
int q_read(Q_DSC *dsc,int field,void *buf,int size);
|
|
|
|
/*
|
|
* Returns the size (in bytes) of the specified variable-length field.
|
|
*/
|
|
|
|
int q_length(const Q_DSC *dsc,int field);
|
|
|
|
/*
|
|
* Enables all instances which are controlled by the specified group.
|
|
* It is an error to use a group that controls no instances.
|
|
*/
|
|
|
|
void q_instance(Q_DSC *dsc,int group);
|
|
|
|
#endif
|