-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathstralloc.h
145 lines (124 loc) · 4.64 KB
/
stralloc.h
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
135
136
137
138
139
140
141
142
143
144
145
#ifndef _STRALLOC_H_
#define _STRALLOC_H_
/* ref-count debugging code */
#undef NOISY_DEBUG
#define NOISY_STRING "workroom"
/* implementation */
#ifdef NOISY_DEBUG
void bp PROT((void));
# ifdef NOISY_STRING
# define NDBG(x) if (strcmp(STRING(x), NOISY_STRING)==0) \
debug_message("%s - %d\n", STRING(x), REFS(x)), bp()
# else
# define NDBG(x) debug_message("%s - %d\n", STRING(x), REFS(x)), bp()
# endif
#else
# define NDBG(x)
#endif
#if defined(DEBUGMALLOC_EXTENSIONS) && defined(STRING_STATS)
/* Uncomment for very complete string ref checking, but be warned it runs
_very_ slowly. A conditional definition like:
(current_prog && strcmp(current_prog->name, "foo") == 0 ? check_string_stats(0) : 0)
is usually best.
*/
#define CHECK_STRING_STATS /* check_string_stats(0) */
#else
#define CHECK_STRING_STATS
#endif
#ifdef STRING_STATS
#define ADD_NEW_STRING(len, overhead) num_distinct_strings++; bytes_distinct_strings += len + 1; overhead_bytes += overhead
#define SUB_NEW_STRING(len, overhead) num_distinct_strings--; bytes_distinct_strings -= len + 1; overhead_bytes -= overhead
#define ADD_STRING(len) allocd_strings++; allocd_bytes += len + 1; CHECK_STRING_STATS
#define ADD_STRING_SIZE(len) allocd_bytes += len; bytes_distinct_strings += len
#define SUB_STRING(len) allocd_strings--; allocd_bytes -= len + 1; CHECK_STRING_STATS
#else
/* Blazing fast macros :) */
#define ADD_NEW_STRING(x, y)
#define SUB_NEW_STRING(x, y)
#define ADD_STRING(x)
#define ADD_STRING_SIZE(x)
#define SUB_STRING(x)
#endif
typedef struct malloc_block_s {
#ifdef DEBUGMALLOC_EXTENSIONS
int extra_ref;
#endif
unsigned short size;
unsigned short ref;
} malloc_block_t;
#define MSTR_BLOCK(x) (((malloc_block_t *)(x)) - 1)
#define MSTR_EXTRA_REF(x) (MSTR_BLOCK(x)->extra_ref)
#define MSTR_REF(x) (MSTR_BLOCK(x)->ref)
#define MSTR_SIZE(x) (MSTR_BLOCK(x)->size)
#define MSTR_UPDATE_SIZE(x, y) SAFE(\
ADD_STRING_SIZE(y - MSTR_SIZE(x));\
MSTR_BLOCK(x)->size = \
(y > USHRT_MAX ? USHRT_MAX : y);\
)
#define FREE_MSTR(x) SAFE(\
DEBUG_CHECK(MSTR_REF(x) != 1, "FREE_MSTR used on a multiply referenced string\n");\
svalue_strlen_size = MSTR_SIZE(x);\
SUB_NEW_STRING(svalue_strlen_size, \
sizeof(malloc_block_t));\
FREE(MSTR_BLOCK(x));\
SUB_STRING(svalue_strlen_size);\
)
/* This counts on some rather crucial alignment between malloc_block_t and
* block_t. COUNTED_STRLEN(x) is the same as strlen(sv->u.string) when
* sv->subtype is STRING_MALLOC or STRING_SHARED, and runs significantly
* faster.
*/
#define COUNTED_STRLEN(x) ((svalue_strlen_size = MSTR_SIZE(x)), svalue_strlen_size != USHRT_MAX ? svalue_strlen_size : strlen((x)+USHRT_MAX)+USHRT_MAX)
/* return the number of references to a STRING_MALLOC or STRING_SHARED
string */
#define COUNTED_REF(x) MSTR_REF(x)
/* ref == 0 means the string has been referenced USHRT_MAX times and is
immortal */
#define INC_COUNTED_REF(x) if (MSTR_REF(x)) MSTR_REF(x)++;
/* This is a conditional expression that evaluates to zero if the block
should be deallocated */
#define DEC_COUNTED_REF(x) (!(MSTR_REF(x) == 0 || --MSTR_REF(x) > 0))
typedef struct block_s {
struct block_s *next; /* next block in the hash chain */
#if defined(DEBUGMALLOC_EXTENSIONS) || (SIZEOF_PTR == 8)
int extra_ref;
#endif
/* these two must be last */
unsigned short size; /* length of the string */
unsigned short refs; /* reference count */
} block_t;
#define NEXT(x) (x)->next
#define REFS(x) (x)->refs
#define EXTRA_REF(x) (x)->extra_ref
#define SIZE(x) (x)->size
#define BLOCK(x) (((block_t *)(x)) - 1) /* pointer arithmetic */
#define STRING(x) ((char *)(x + 1))
#define SHARED_STRLEN(x) COUNTED_STRLEN(x)
#define SVALUE_STRLEN(x) (((x)->subtype & STRING_COUNTED) ? \
COUNTED_STRLEN((x)->u.string) : \
strlen((x)->u.string))
/* For quick checks. Avoid strlen(), etc. This is */
#define SVALUE_STRLEN_DIFFERS(x, y) ((((x)->subtype & STRING_COUNTED) && \
((y)->subtype & STRING_COUNTED)) ? \
MSTR_SIZE((x)->u.string) != \
MSTR_SIZE((y)->u.string) : 0)
/*
* stralloc.c
*/
void init_strings PROT((void));
char *findstring PROT((char *));
char *make_shared_string PROT((char *));
char *ref_string PROT((char *));
void free_string PROT((char *));
void deallocate_string PROT((char *));
int add_string_status PROT((outbuffer_t *, int));
char *extend_string PROT((char *, int));
extern int svalue_strlen_size;
#ifdef STRING_STATS
extern int num_distinct_strings;
extern int bytes_distinct_strings;
extern int allocd_strings;
extern int allocd_bytes;
extern int overhead_bytes;
#endif
#endif