|
1 /* |
|
2 Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. |
|
3 This program is free software; you can redistribute it and/or modify it |
|
4 under the terms of version 2 of the GNU General Public License as |
|
5 published by the Free Software Foundation. |
|
6 |
|
7 This program is distributed in the hope that it would be useful, but |
|
8 WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
10 |
|
11 Further, this software is distributed without any warranty that it is |
|
12 free of the rightful claim of any third person regarding infringement |
|
13 or the like. Any license provided herein, whether implied or |
|
14 otherwise, applies only to this software file. Patent licenses, if |
|
15 any, provided herein do not apply to combinations of this program with |
|
16 other software, or any other product whatsoever. |
|
17 |
|
18 You should have received a copy of the GNU General Public License along |
|
19 with this program; if not, write the Free Software Foundation, Inc., 51 |
|
20 Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. |
|
21 |
|
22 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, |
|
23 Mountain View, CA 94043, or: |
|
24 |
|
25 http://www.sgi.com |
|
26 |
|
27 For further information regarding this notice, see: |
|
28 |
|
29 http://oss.sgi.com/projects/GenInfo/NoticeExplan |
|
30 |
|
31 |
|
32 $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/esb.c,v 1.1 2005/08/04 05:09:37 davea Exp $ */ |
|
33 |
|
34 /* esb.c |
|
35 extensible string buffer. |
|
36 |
|
37 A simple means (vaguely like a C++ class) that |
|
38 enables safely saving strings of arbitrary length built up |
|
39 in small pieces. |
|
40 |
|
41 */ |
|
42 |
|
43 #include "globals.h" |
|
44 #include "esb.h" |
|
45 |
|
46 #define INITIAL_ALLOC 1024 |
|
47 static size_t alloc_size = INITIAL_ALLOC; |
|
48 |
|
49 |
|
50 static void |
|
51 init_esb_string(struct esb_s *data, size_t min_len) |
|
52 { |
|
53 string d; |
|
54 |
|
55 if (data->esb_allocated_size > 0) { |
|
56 return; |
|
57 } |
|
58 if (min_len < alloc_size) { |
|
59 min_len = alloc_size; |
|
60 } |
|
61 d = malloc(min_len); |
|
62 if (!d) { |
|
63 fprintf(stderr, |
|
64 "dwarfdump is out of memory allocating %lu bytes\n", |
|
65 (unsigned long) min_len); |
|
66 exit(5); |
|
67 } |
|
68 data->esb_string = d; |
|
69 data->esb_allocated_size = min_len; |
|
70 data->esb_string[0] = 0; |
|
71 data->esb_used_bytes = 0; |
|
72 } |
|
73 |
|
74 /* Make more room. Leaving contents unchanged, effectively. |
|
75 */ |
|
76 static void |
|
77 allocate_more(struct esb_s *data, size_t len) |
|
78 { |
|
79 size_t new_size = data->esb_allocated_size + len; |
|
80 string newd = 0; |
|
81 |
|
82 if (new_size < alloc_size) |
|
83 new_size = alloc_size; |
|
84 newd = realloc(data->esb_string, new_size); |
|
85 if (!newd) { |
|
86 fprintf(stderr, "dwarfdump is out of memory re-allocating " |
|
87 "%lu bytes\n", (unsigned long) new_size); |
|
88 exit(5); |
|
89 } |
|
90 data->esb_string = newd; |
|
91 data->esb_allocated_size = new_size; |
|
92 } |
|
93 |
|
94 static void |
|
95 esb_appendn_internal(struct esb_s *data, string in_string, size_t len); |
|
96 |
|
97 void |
|
98 esb_appendn(struct esb_s *data, string in_string, size_t len) |
|
99 { |
|
100 size_t full_len = strlen(in_string); |
|
101 |
|
102 if (full_len < len) { |
|
103 fprintf(stderr, "dwarfdump internal error, bad string length " |
|
104 " %lu < %lu \n", |
|
105 (unsigned long) full_len, (unsigned long) len); |
|
106 len = full_len; |
|
107 } |
|
108 |
|
109 esb_appendn_internal(data, in_string, len); |
|
110 } |
|
111 |
|
112 /* The length is gotten from the in_string itself. */ |
|
113 void |
|
114 esb_append(struct esb_s *data, string in_string) |
|
115 { |
|
116 size_t len = strlen(in_string); |
|
117 |
|
118 esb_appendn_internal(data, in_string, len); |
|
119 } |
|
120 |
|
121 /* The 'len' is believed. Do not pass in strings < len bytes long. */ |
|
122 static void |
|
123 esb_appendn_internal(struct esb_s *data, string in_string, size_t len) |
|
124 { |
|
125 size_t remaining = 0; |
|
126 size_t needed = len + 1; |
|
127 |
|
128 if (data->esb_allocated_size == 0) { |
|
129 size_t maxlen = (len > alloc_size) ? len : alloc_size; |
|
130 |
|
131 init_esb_string(data, maxlen); |
|
132 } |
|
133 remaining = data->esb_allocated_size - data->esb_used_bytes; |
|
134 if (remaining < needed) { |
|
135 allocate_more(data, needed); |
|
136 } |
|
137 strncpy(&data->esb_string[data->esb_used_bytes], in_string, len); |
|
138 data->esb_used_bytes += len; |
|
139 /* Insist on explicit NUL terminator */ |
|
140 data->esb_string[data->esb_used_bytes] = 0; |
|
141 } |
|
142 |
|
143 /* Always returns an empty string or a non-empty string. Never 0. */ |
|
144 string |
|
145 esb_get_string(struct esb_s *data) |
|
146 { |
|
147 if (data->esb_allocated_size == 0) { |
|
148 init_esb_string(data, alloc_size); |
|
149 } |
|
150 return data->esb_string; |
|
151 } |
|
152 |
|
153 |
|
154 /* Sets esb_used_bytes to zero. The string is not freed and |
|
155 esb_allocated_size is unchanged. */ |
|
156 void |
|
157 esb_empty_string(struct esb_s *data) |
|
158 { |
|
159 if (data->esb_allocated_size == 0) { |
|
160 init_esb_string(data, alloc_size); |
|
161 } |
|
162 data->esb_used_bytes = 0; |
|
163 data->esb_string[0] = 0; |
|
164 |
|
165 } |
|
166 |
|
167 |
|
168 /* Return esb_used_bytes. */ |
|
169 size_t |
|
170 esb_string_len(struct esb_s *data) |
|
171 { |
|
172 return data->esb_used_bytes; |
|
173 } |
|
174 |
|
175 |
|
176 /* The following are for testing esb, not use by dwarfdump. */ |
|
177 |
|
178 /* *data is presumed to contain garbage, not values, and |
|
179 is properly initialized. */ |
|
180 void |
|
181 esb_constructor(struct esb_s *data) |
|
182 { |
|
183 memset(data, 0, sizeof(*data)); |
|
184 } |
|
185 |
|
186 /* The string is freed, contents of *data set to zeroes. */ |
|
187 void |
|
188 esb_destructor(struct esb_s *data) |
|
189 { |
|
190 if (data->esb_string) { |
|
191 free(data->esb_string); |
|
192 } |
|
193 esb_constructor(data); |
|
194 } |
|
195 |
|
196 |
|
197 /* To get all paths in the code tested, this sets the |
|
198 allocation/reallocation to the given value, which can be quite small |
|
199 but must not be zero. */ |
|
200 void |
|
201 esb_alloc_size(size_t size) |
|
202 { |
|
203 alloc_size = size; |
|
204 } |
|
205 |
|
206 size_t |
|
207 esb_get_allocated_size(struct esb_s *data) |
|
208 { |
|
209 return data->esb_allocated_size; |
|
210 } |