Commit 87cafc5e authored by David Lawrence's avatar David Lawrence

Megacommit of many files.

Mostly, several functions that take pointers as arguments, almost
always char * pointers, had those pointers qualified with "const".
Those that returned pointers to previously const-qualified arguments
had their return values qualified as const.  Some structure members
were qualified as const to retain that attribute from the variables
from which they were assigned.

The macro DE_CONST was added to isc/util.h to deal with a handful of very
special places where something is qualified as const but really needs to have
its const qualifier removed.

Also cleaned up a few places where variable names clashed with reserved
identifiers.  (Which mostly works fine, but strictly speaking is undefined
by the standard.)

Minor other ISC style cleanups.
parent fd6de7af
......@@ -26,7 +26,8 @@
* Forward.
*/
static void default_callback(char *, int, isc_assertiontype_t, char *);
static void
default_callback(const char *, int, isc_assertiontype_t, const char *);
/*
* Public.
......@@ -42,9 +43,9 @@ isc_assertion_setcallback(isc_assertioncallback_t cb) {
isc_assertion_failed = cb;
}
char *
const char *
isc_assertion_typetotext(isc_assertiontype_t type) {
char *result;
const char *result;
switch (type) {
case isc_assertiontype_require:
......@@ -70,7 +71,9 @@ isc_assertion_typetotext(isc_assertiontype_t type) {
*/
static void
default_callback(char *file, int line, isc_assertiontype_t type, char *cond) {
default_callback(const char *file, int line, isc_assertiontype_t type,
const char *cond)
{
fprintf(stderr, "%s:%d: %s(%s) failed.\n",
file, line, isc_assertion_typetotext(type), cond);
fflush(stderr);
......
......@@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: base64.c,v 1.13 2000/05/16 05:19:46 tale Exp $ */
/* $Id: base64.c,v 1.14 2000/06/01 17:20:18 tale Exp $ */
#include <config.h>
......@@ -36,18 +36,22 @@
* These static functions are also present in lib/dns/rdata.c. I'm not
* sure where they should go. -- bwelling
*/
static isc_result_t str_totext(char *source, isc_buffer_t *target);
static isc_result_t gettoken(isc_lex_t *lexer, isc_token_t *token,
isc_tokentype_t expect, isc_boolean_t eol);
static isc_result_t mem_tobuffer(isc_buffer_t *target, void *base,
unsigned int length);
static isc_result_t
str_totext(const char *source, isc_buffer_t *target);
static isc_result_t
gettoken(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect,
isc_boolean_t eol);
static isc_result_t
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
static const char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
isc_result_t
isc_base64_totext(isc_region_t *source, int wordlength,
char *wordbreak, isc_buffer_t *target)
const char *wordbreak, isc_buffer_t *target)
{
char buf[5];
unsigned int loops = 0;
......@@ -157,7 +161,7 @@ isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
}
static isc_result_t
str_totext(char *source, isc_buffer_t *target) {
str_totext(const char *source, isc_buffer_t *target) {
unsigned int l;
isc_region_t region;
......
......@@ -24,9 +24,10 @@
#include <isc/util.h>
void
isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length) {
isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) {
/*
* Make 'b' refer to the 'length'-byte region starting at base.
* Make 'b' refer to the 'length'-byte region starting at 'base'.
* XXXDCL see the comment in buffer.h about base being const.
*/
REQUIRE(b != NULL);
......@@ -214,8 +215,8 @@ isc_buffer_compact(isc_buffer_t *b) {
REQUIRE(ISC_BUFFER_VALID(b));
src = (unsigned char *)b->base + b->current;
length = b->used - b->current;
src = isc_buffer_current(b);
length = isc_buffer_remaininglength(b);
(void)memmove(b->base, src, (size_t)length);
if (b->active > b->current)
......@@ -238,17 +239,15 @@ isc_buffer_getuint8(isc_buffer_t *b) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used - b->current >= 1);
cp = b->base;
cp += b->current;
cp = isc_buffer_current(b);
b->current += 1;
result = ((unsigned int)(cp[0]));
result = ((isc_uint8_t)(cp[0]));
return (result);
}
void
isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val)
{
isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used + 1 <= b->length);
......@@ -268,8 +267,7 @@ isc_buffer_getuint16(isc_buffer_t *b) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used - b->current >= 2);
cp = b->base;
cp += b->current;
cp = isc_buffer_current(b);
b->current += 2;
result = ((unsigned int)(cp[0])) << 8;
result |= ((unsigned int)(cp[1]));
......@@ -278,8 +276,7 @@ isc_buffer_getuint16(isc_buffer_t *b) {
}
void
isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val)
{
isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used + 2 <= b->length);
......@@ -299,8 +296,7 @@ isc_buffer_getuint32(isc_buffer_t *b) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used - b->current >= 4);
cp = b->base;
cp += b->current;
cp = isc_buffer_current(b);
b->current += 4;
result = ((unsigned int)(cp[0])) << 24;
result |= ((unsigned int)(cp[1])) << 16;
......@@ -311,8 +307,7 @@ isc_buffer_getuint32(isc_buffer_t *b) {
}
void
isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val)
{
isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used + 4 <= b->length);
......@@ -320,21 +315,26 @@ isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val)
}
void
isc__buffer_putmem(isc_buffer_t *b, unsigned char *base, unsigned int length) {
isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
unsigned int length)
{
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(b->used + length <= b->length);
ISC__BUFFER_PUTMEM(b, base, length);
}
}
void
isc_buffer_putstr(isc_buffer_t *b, const char *source) {
isc__buffer_putstr(isc_buffer_t *b, const char *source) {
unsigned int l;
unsigned char *cp;
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(source != NULL);
/*
* Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
*/
l = strlen(source);
REQUIRE(l <= isc_buffer_availablelength(b));
......@@ -352,8 +352,11 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r) {
REQUIRE(ISC_BUFFER_VALID(b));
REQUIRE(r != NULL);
base = (unsigned char *)b->base + b->used;
available = b->length - b->used;
/*
* XXXDCL
*/
base = isc_buffer_used(b);
available = isc_buffer_availablelength(b);
if (r->length > available)
return (ISC_R_NOSPACE);
memcpy(base, r->base, r->length);
......@@ -385,8 +388,7 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
}
void
isc_buffer_free(isc_buffer_t **dynbuffer)
{
isc_buffer_free(isc_buffer_t **dynbuffer) {
unsigned int real_length;
isc_buffer_t *dbuf;
isc_mem_t *mctx;
......
......@@ -48,7 +48,7 @@
* SUCH DAMAGE.
*/
/* $Id: commandline.c,v 1.6 2000/05/08 14:37:20 tale Exp $ */
/* $Id: commandline.c,v 1.7 2000/06/01 17:20:20 tale Exp $ */
/*
* This file was adapted from the NetBSD project's source tree, RCS ID:
......@@ -80,9 +80,11 @@ char *isc_commandline_progname; /* For printing error messages. */
isc_boolean_t isc_commandline_errprint = ISC_TRUE; /* Print error messages. */
isc_boolean_t isc_commandline_reset = ISC_TRUE; /* Reset processing. */
static char endopt = '\0';
#define BADOPT '?'
#define BADARG ':'
#define ENDOPT ""
#define ENDOPT &endopt
/*
* getopt --
......
......@@ -23,10 +23,10 @@
#include <isc/error.h>
static void
default_unexpected_callback(char *, int, char *, va_list);
default_unexpected_callback(const char *, int, const char *, va_list);
static void
default_fatal_callback(char *, int, char *, va_list);
default_fatal_callback(const char *, int, const char *, va_list);
static isc_errorcallback_t unexpected_callback = default_unexpected_callback;
static isc_errorcallback_t fatal_callback = default_fatal_callback;
......@@ -48,7 +48,7 @@ isc_error_setfatal(isc_errorcallback_t cb) {
}
void
isc_error_unexpected(char *file, int line, char *format, ...) {
isc_error_unexpected(const char *file, int line, const char *format, ...) {
va_list args;
va_start(args, format);
......@@ -57,7 +57,7 @@ isc_error_unexpected(char *file, int line, char *format, ...) {
}
void
isc_error_fatal(char *file, int line, char *format, ...) {
isc_error_fatal(const char *file, int line, const char *format, ...) {
va_list args;
va_start(args, format);
......@@ -67,12 +67,14 @@ isc_error_fatal(char *file, int line, char *format, ...) {
}
void
isc_error_runtimecheck(char *file, int line, char *expression) {
isc_error_runtimecheck(const char *file, int line, const char *expression) {
isc_error_fatal(file, line, "RUNTIME_CHECK(%s) failed", expression);
}
static void
default_unexpected_callback(char *file, int line, char *format, va_list args) {
default_unexpected_callback(const char *file, int line, const char *format,
va_list args)
{
fprintf(stderr, "%s:%d: ", file, line);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
......@@ -80,7 +82,9 @@ default_unexpected_callback(char *file, int line, char *format, va_list args) {
}
static void
default_fatal_callback(char *file, int line, char *format, va_list args) {
default_fatal_callback(const char *file, int line, const char *format,
va_list args)
{
fprintf(stderr, "%s:%d: fatal error: ", file, line);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
......
......@@ -38,9 +38,10 @@ destroy(isc_event_t *event) {
isc_event_t *
isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
isc_taskaction_t action, void *arg, size_t size)
isc_taskaction_t action, const void *arg, size_t size)
{
isc_event_t *event;
void *deconst_arg;
if (size < sizeof (struct isc_event))
return (NULL);
......@@ -50,8 +51,23 @@ isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
event = isc_mem_get(mctx, size);
if (event == NULL)
return (NULL);
ISC_EVENT_INIT(event, size, 0, NULL, type, action, arg, sender,
destroy, mctx);
/*
* Removing the const attribute from "arg" is the best of two
* evils here. If the event->ev_arg member is made const, then
* it affects a great many users of the task/event subsystem
* which are not passing in an "arg" which starts its life as
* const. Changing isc_event_allocate() and isc_task_onshutdown()
* to not have "arg" prototyped as const (which is quite legitimate,
* because neither of those functions modify arg) can cause
* compiler whining anytime someone does want to use a const
* arg that they themselves never modify, such as with
* gcc -Wwrite-strings and using a string "arg".
*/
DE_CONST(arg, deconst_arg);
ISC_EVENT_INIT(event, size, 0, NULL, type, action, deconst_arg,
sender, destroy, mctx);
return (event);
}
......
......@@ -16,7 +16,7 @@
*/
/*
* $Id: assertions.h,v 1.9 2000/04/28 16:54:53 tale Exp $
* $Id: assertions.h,v 1.10 2000/06/01 17:20:34 tale Exp $
*/
#ifndef ISC_ASSERTIONS_H
......@@ -33,13 +33,16 @@ typedef enum {
isc_assertiontype_invariant
} isc_assertiontype_t;
typedef void (*isc_assertioncallback_t)(char *, int, isc_assertiontype_t,
char *);
typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t,
const char *);
extern isc_assertioncallback_t isc_assertion_failed;
void isc_assertion_setcallback(isc_assertioncallback_t);
char *isc_assertion_typetotext(isc_assertiontype_t type);
void
isc_assertion_setcallback(isc_assertioncallback_t);
const char *
isc_assertion_typetotext(isc_assertiontype_t type);
#ifdef ISC_CHECK_ALL
#define ISC_CHECK_REQUIRE 1
......
......@@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: base64.h,v 1.6 2000/04/10 21:52:31 gson Exp $ */
/* $Id: base64.h,v 1.7 2000/06/01 17:20:35 tale Exp $ */
#ifndef ISC_BASE64_H
#define ISC_BASE64_H 1
......@@ -50,7 +50,7 @@ ISC_LANG_BEGINDECLS
*/
isc_result_t
isc_base64_totext(isc_region_t *source, int wordlength,
char *wordbreak, isc_buffer_t *target);
const char *wordbreak, isc_buffer_t *target);
/* Convert base64 encoded text into data.
*
......
......@@ -62,7 +62,7 @@
* d == used pointer.
* e == length of buffer.
*
* a-e == entire (length) of buffer.
* a-e == entire length of buffer.
* a-d == used region.
* a-b == consumed region.
* b-d == remaining region.
......@@ -132,11 +132,14 @@ ISC_LANG_BEGINDECLS
/*
* Fundamental buffer elements. (A through E in the introductory comment.)
*/
#define isc_buffer_base(b) ((unsigned char *)(b)->base) /*a*/
#define isc_buffer_current(b) ((unsigned char *)(b)->base + (b)->current) /*b*/
#define isc_buffer_active(b) ((unsigned char *)(b)->base + (b)->active) /*c*/
#define isc_buffer_used(b) ((unsigned char *)(b)->base + (b)->used) /*d*/
#define isc_buffer_length(b) ((b)->length) /*e*/
#define isc_buffer_base(b) ((void *)(b)->base) /*a*/
#define isc_buffer_current(b) \
((void *)((unsigned char *)(b)->base + (b)->current)) /*b*/
#define isc_buffer_active(b) \
((void *)((unsigned char *)(b)->base + (b)->active)) /*c*/
#define isc_buffer_used(b) \
((void *)((unsigned char *)(b)->base + (b)->used)) /*d*/
#define isc_buffer_length(b) ((b)->length) /*e*/
/*
* Derived lengths. (Described in the introductory comment.)
......@@ -208,7 +211,7 @@ isc_buffer_free(isc_buffer_t **dynbuffer);
*/
void
isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length);
isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length);
/*
* Make 'b' refer to the 'length'-byte region starting at base.
*
......@@ -525,14 +528,9 @@ isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val);
* The used pointer in 'b' is advanced by 4.
*/
#define ISC__BUFFER_PUTMEM(_b, _base, _length) \
do { \
memcpy((unsigned char *)(_b)->base + (_b)->used, \
(_base), (_length)); \
(_b)->used += (_length); \
} while (0)
void
isc__buffer_putmem(isc_buffer_t *b, unsigned char *base, unsigned int length);
isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
unsigned int length);
/*
* Copy 'length' bytes of memory at 'base' into 'b'.
*
......@@ -544,7 +542,7 @@ isc__buffer_putmem(isc_buffer_t *b, unsigned char *base, unsigned int length);
*/
void
isc_buffer_putstr(isc_buffer_t *b, const char *source);
isc__buffer_putstr(isc_buffer_t *b, const char *source);
/*
* Copy 'source' into 'b', not including terminating NUL.
*
......@@ -573,6 +571,8 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
* big enough.
*/
ISC_LANG_ENDDECLS
/*
* Inline macro versions of the functions. These should never be called
* directly by an application, but will be used by the functions within
......@@ -580,16 +580,38 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
* ones beginning with "isc__"
*/
/*
* XXXDCL Something more could be done with initializing buffers that
* point to const data. For example, a new function, isc_buffer_initconst,
* could be used, and a new boolean flag in the buffer structure could
* indicate whether the buffer was initialized with that function.
* (isc_bufer_init itself would be reprototyped to *not* have its "base"
* parameter be const.) Then if the boolean were true, the isc_buffer_put*
* functions could assert a contractual requirement for a non-const buffer.
* One drawback is that the isc_buffer_* functions (macros) that return
* pointers would still need to return non-const pointers to avoid compiler
* warnings, so it would be up to code that uses them to have to deal
* with the possibility that the buffer was initialized as const --
* a problem that they *already* have to deal with but have absolutely
* no ability to. With a new isc_buffer_isconst() function returning
* true/false, they could at least assert a contractual requirement for
* non-const buffers when needed.
*/
#define ISC__BUFFER_INIT(_b, _base, _length) \
do { \
(_b)->magic = ISC_BUFFER_MAGIC; \
(_b)->base = (_base); \
union { \
const void * konst; \
void * var; \
} _u; \
_u.konst = (_base); \
(_b)->base = _u.var; \
(_b)->length = (_length); \
(_b)->used = 0; \
(_b)->current = 0; \
(_b)->active = 0; \
(_b)->mctx = NULL; \
ISC_LINK_INIT(b, link); \
(_b)->magic = ISC_BUFFER_MAGIC; \
} while (0)
#define ISC__BUFFER_INVALIDATE(_b) \
......@@ -616,8 +638,8 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \
do { \
(_r)->base = ((unsigned char *)(_b)->base) + (_b)->used; \
(_r)->length = (_b)->length - (_b)->used; \
(_r)->base = isc_buffer_used(_b); \
(_r)->length = isc_buffer_availablelength(_b); \
} while (0)
#define ISC__BUFFER_ADD(_b, _n) \
......@@ -649,16 +671,15 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
#define ISC__BUFFER_REMAININGREGION(_b, _r) \
do { \
(_r)->base = ((unsigned char *)(_b)->base) + (_b)->current; \
(_r)->length = (_b)->used - (_b)->current; \
(_r)->base = isc_buffer_current(_b); \
(_r)->length = isc_buffer_remaininglength(_b); \
} while (0)
#define ISC__BUFFER_ACTIVEREGION(_b, _r) \
do { \
if ((_b)->current < (_b)->active) { \
(_r)->base = (unsigned char *)(_b)->base \
+ (_b)->current; \
(_r)->length = (_b)->active - (_b)->current; \
(_r)->base = isc_buffer_current(_b); \
(_r)->length = isc_buffer_activelength(_b); \
} else { \
(_r)->base = NULL; \
(_r)->length = 0; \
......@@ -685,12 +706,27 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
(_b)->current -= (_n); \
} while (0)
#define ISC__BUFFER_PUTMEM(_b, _base, _length) \
do { \
memcpy(isc_buffer_used(_b), (_base), (_length)); \
(_b)->used += (_length); \
} while (0)
#define ISC__BUFFER_PUTSTR(_b, _source) \
do { \
unsigned int _length; \
unsigned char *_cp; \
_length = strlen(_source); \
_cp = isc_buffer_used(_b); \
memcpy(_cp, (_source), _length); \
(_b)->used += (_length); \
} while (0)
#define ISC__BUFFER_PUTUINT8(_b, _val) \
do { \
unsigned char *_cp; \
isc_uint8_t _val2 = (_val); \
_cp = (_b)->base; \
_cp += (_b)->used; \
_cp = isc_buffer_used(_b); \
(_b)->used++; \
_cp[0] = (_val2 & 0x00ff); \
} while (0)
......@@ -699,8 +735,7 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
do { \
unsigned char *_cp; \
isc_uint16_t _val2 = (_val); \
_cp = (_b)->base; \
_cp += (_b)->used; \
_cp = isc_buffer_used(_b); \
(_b)->used += 2; \
_cp[0] = (_val2 & 0xff00U) >> 8; \
_cp[1] = (_val2 & 0x00ffU); \
......@@ -710,8 +745,7 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
do { \
unsigned char *_cp; \
isc_uint32_t _val2 = (_val); \
_cp = (_b)->base; \
_cp += (_b)->used; \
_cp = isc_buffer_used(_b); \
(_b)->used += 4; \
_cp[0] = (_val2 & 0xff000000) >> 24; \
_cp[1] = (_val2 & 0x00ff0000) >> 16; \
......@@ -735,10 +769,11 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
#define isc_buffer_first ISC__BUFFER_FIRST
#define isc_buffer_forward ISC__BUFFER_FORWARD
#define isc_buffer_back ISC__BUFFER_BACK
#define isc_buffer_putmem ISC__BUFFER_PUTMEM
#define isc_buffer_putstr ISC__BUFFER_PUTSTR
#define isc_buffer_putuint8 ISC__BUFFER_PUTUINT8
#define isc_buffer_putuint16 ISC__BUFFER_PUTUINT16
#define isc_buffer_putuint32 ISC__BUFFER_PUTUINT32
#define isc_buffer_putmem ISC__BUFFER_PUTMEM
#else
#define isc_buffer_init isc__buffer_init
#define isc_buffer_invalidate isc__buffer_invalidate
......@@ -755,12 +790,11 @@ isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r);
#define isc_buffer_first isc__buffer_first
#define isc_buffer_forward isc__buffer_forward
#define isc_buffer_back isc__buffer_back
#define isc_buffer_putmem isc__buffer_putmem
#define isc_buffer_putstr isc__buffer_putstr
#define isc_buffer_putuint8 isc__buffer_putuint8
#define isc_buffer_putuint16 isc__buffer_putuint16
#define isc_buffer_putuint32 isc__buffer_putuint32
#define isc_buffer_putmem isc__buffer_putmem
#endif
ISC_LANG_ENDDECLS
#endif /* ISC_BUFFER_H */
......@@ -24,13 +24,18 @@
ISC_LANG_BEGINDECLS
typedef void (*isc_errorcallback_t)(char *, int, char *, va_list);
void isc_error_setunexpected(isc_errorcallback_t);
void isc_error_setfatal(isc_errorcallback_t);
void isc_error_unexpected(char *, int, char *, ...);
void isc_error_fatal(char *, int, char *, ...);
void isc_error_runtimecheck(char *, int, char *);
typedef void (*isc_errorcallback_t)(const char *, int, const char *, va_list);
void
isc_error_setunexpected(isc_errorcallback_t);
void
isc_error_setfatal(isc_errorcallback_t);
void
isc_error_unexpected(const char *, int, const char *, ...);
void
isc_error_fatal(const char *, int, const char *, ...);
void
isc_error_runtimecheck(const char *, int, const char *);
#define ISC_ERROR_RUNTIMECHECK(cond) \
((void) ((cond) || \
......
......@@ -84,7 +84,7 @@ ISC_LANG_BEGINDECLS