summaryrefslogtreecommitdiffstats
path: root/include/asn1c/asn_internal.h
blob: 580c2e769f226160a43b311cc4ec6f1b14d967c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*-
 * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin <vlm@lionet.info>.
 * All rights reserved.
 * Redistribution and modifications are permitted subject to BSD license.
 */
/*
 * Declarations internally useful for the ASN.1 support code.
 */
#ifndef	_ASN_INTERNAL_H_
#define	_ASN_INTERNAL_H_

#include "asn_application.h"	/* Application-visible API */

#ifndef	__NO_ASSERT_H__		/* Include assert.h only for internal use. */
#include <assert.h>		/* for assert() macro */
#endif

#include <talloc.h>

#ifdef	__cplusplus
extern "C" {
#endif

/* Environment version might be used to avoid running with the old library */
#define	ASN1C_ENVIRONMENT_VERSION	924	/* Compile-time version */
int get_asn1c_environment_version(void);	/* Run-time version */

extern void *talloc_asn1_ctx;

#define	CALLOC(nmemb, size)	talloc_zero_size(talloc_asn1_ctx, (nmemb) * (size))
#define	MALLOC(size)		talloc_size(talloc_asn1_ctx, size)
#define	REALLOC(oldptr, size)	talloc_realloc_size(talloc_asn1_ctx, oldptr, size)
#define	FREEMEM(ptr)		talloc_free(ptr)

#define	asn_debug_indent	0
#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)

/*
 * A macro for debugging the ASN.1 internals.
 * You may enable or override it.
 */
#ifndef	ASN_DEBUG	/* If debugging code is not defined elsewhere... */
#if	EMIT_ASN_DEBUG == 1	/* And it was asked to emit this code... */
#ifdef	__GNUC__
#ifdef	ASN_THREAD_SAFE
/* Thread safety requires sacrifice in output indentation:
 * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
#else	/* !ASN_THREAD_SAFE */
#undef  ASN_DEBUG_INDENT_ADD
#undef  asn_debug_indent
int asn_debug_indent;
#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
#endif	/* ASN_THREAD_SAFE */
extern int asn_debug; /* Allow option on execution */
#define	ASN_DEBUG(fmt, args...) \
if (asn_debug) {    \
    do {			\
		int adi = asn_debug_indent;		\
		while(adi--) fprintf(stderr, " ");	\
		fprintf(stderr, fmt, ##args);		\
		fprintf(stderr, " (%s:%d)\n",		\
			__FILE__, __LINE__);		\
	} while(0);  \
}
#else	/* !__GNUC__ */
void ASN_DEBUG_f(const char *fmt, ...);
#define	ASN_DEBUG	ASN_DEBUG_f
#endif	/* __GNUC__ */
#else	/* EMIT_ASN_DEBUG != 1 */
static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
#endif	/* EMIT_ASN_DEBUG */
#endif	/* ASN_DEBUG */

/*
 * Invoke the application-supplied callback and fail, if something is wrong.
 */
#define	__ASN_E_cbc(buf, size)	(cb((buf), (size), app_key) < 0)
#define	_ASN_E_CALLBACK(foo)	do {					\
		if(foo)	goto cb_failed;					\
	} while(0)
#define	_ASN_CALLBACK(buf, size)					\
	_ASN_E_CALLBACK(__ASN_E_cbc(buf, size))
#define	_ASN_CALLBACK2(buf1, size1, buf2, size2)			\
	_ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) || __ASN_E_cbc(buf2, size2))
#define	_ASN_CALLBACK3(buf1, size1, buf2, size2, buf3, size3)		\
	_ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1)			\
		|| __ASN_E_cbc(buf2, size2)				\
		|| __ASN_E_cbc(buf3, size3))

#define	_i_ASN_TEXT_INDENT(nl, level) do {				\
	int __level = (level);						\
	int __nl = ((nl) != 0);						\
	int __i;							\
	if(__nl) _ASN_CALLBACK("\n", 1);				\
	if(__level < 0) __level = 0;					\
	for(__i = 0; __i < __level; __i++)				\
		_ASN_CALLBACK("    ", 4);				\
	er.encoded += __nl + 4 * __level;				\
} while(0)

#define	_i_INDENT(nl)	do {						\
	int __i;							\
	if((nl) && cb("\n", 1, app_key) < 0) return -1;			\
	for(__i = 0; __i < ilevel; __i++)				\
		if(cb("    ", 4, app_key) < 0) return -1;		\
} while(0)

/*
 * Check stack against overflow, if limit is set.
 */
#define	_ASN_DEFAULT_STACK_MAX	(30000)
static inline int
_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
	if(ctx && ctx->max_stack_size) {

		/* ctx MUST be allocated on the stack */
		ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx);
		if(usedstack > 0) usedstack = -usedstack; /* grows up! */

		/* double negative required to avoid int wrap-around */
		if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
			ASN_DEBUG("Stack limit %ld reached",
				(long)ctx->max_stack_size);
			return -1;
		}
	}
	return 0;
}

#ifdef	__cplusplus
}
#endif

#endif	/* _ASN_INTERNAL_H_ */