Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#if FS_STDARG
63
#include <stdarg.h>
64
#else
65
#include <varargs.h>
66
#endif
67
#include "c_types.h"
68
#include "error.h"
69
#include "buffer.h"
70
#include "ustring.h"
71
#include "xalloc.h"
72
 
73
 
74
/*
75
    FREE A BUFFER
76
 
77
    This routine frees the contents of the buffer bf.
78
*/
79
 
6 7u83 80
void
81
free_buffer(BUFFER *bf)
2 7u83 82
{
6 7u83 83
	xfree_nof(bf->start);
84
	bf->start = NULL;
85
	bf->posn = NULL;
86
	bf->end = NULL;
87
	return;
2 7u83 88
}
89
 
90
 
91
/*
92
    CLEAR A BUFFER
93
 
94
    This routine sets the current position of the buffer bf to the start
95
    of the buffer and sets the buffer file to f.  It returns bf.
96
*/
97
 
6 7u83 98
BUFFER *
99
clear_buffer(BUFFER *bf, FILE *f)
2 7u83 100
{
6 7u83 101
	bf->posn = bf->start;
102
	bf->file = f;
103
	return (bf);
2 7u83 104
}
105
 
106
 
107
/*
108
    OUTPUT THE CONTENTS OF A BUFFER
109
 
110
    This routine outputs the content of the buffer bf to the associated
111
    file and resets the position to the start of the buffer.  If fl is
112
    true then the file is flushed.
113
*/
114
 
6 7u83 115
void
116
output_buffer(BUFFER *bf, int fl)
2 7u83 117
{
6 7u83 118
	FILE *f = bf->file;
119
	if (f) {
120
		string s = bf->start;
121
		size_t n = (size_t)(bf->posn - s);
122
		if (n) {
123
			IGNORE fwrite((gen_ptr)s, sizeof(character), n, f);
124
			if (fl) {
125
				IGNORE fflush_v(f);
126
			}
127
			bf->posn = s;
128
		}
2 7u83 129
	}
6 7u83 130
	return;
2 7u83 131
}
132
 
133
 
134
/*
135
    EXTEND A BUFFER
136
 
137
    This routine extends the buffer bf.  s gives a pointer into the buffer,
138
    the corresponding position in the extended buffer is returned.
139
*/
140
 
6 7u83 141
string
142
extend_buffer(BUFFER *bf, string s)
2 7u83 143
{
6 7u83 144
	string p = bf->start;
145
	gen_size m = (gen_size)(s - p);
146
	gen_size n = (gen_size)(bf->end - p) + 500;
147
	p = xrealloc_nof(p, character, n + 12);
148
	bf->start = p;
149
	bf->end = p + n;
150
	return (p + m);
2 7u83 151
}
152
 
153
 
154
/*
155
    MAKE SPACE IN A BUFFER
156
 
157
    This routine makes space for at least m + 1 characters in the buffer
158
    bf following the position s.  It returns the corresponding position
159
    in the extended buffer.
160
*/
161
 
6 7u83 162
string
163
stretch_buffer(BUFFER *bf, string s, gen_size m)
2 7u83 164
{
6 7u83 165
	gen_size n = (gen_size)(bf->end - s);
166
	while (m >= n) {
167
		s = extend_buffer(bf, s);
168
		n = (gen_size)(bf->end - s);
169
	}
170
	return (s);
2 7u83 171
}
172
 
173
 
174
/*
175
    ADD A CHARACTER TO A BUFFER
176
 
177
    This routine adds the character c to the buffer bf.  Note that bf will
178
    not necessarily be null terminated after this routine.
179
*/
180
 
6 7u83 181
void
182
bfputc(BUFFER *bf, int c)
2 7u83 183
{
6 7u83 184
	string p = bf->posn;
185
	if (p == bf->end)p = extend_buffer(bf, p);
186
	*p = (character)c;
187
	bf->posn = p + 1;
188
	return;
2 7u83 189
}
190
 
191
 
192
/*
193
    ADD A STRING TO A BUFFER
194
 
195
    This routine adds the string s to the buffer bf.  Note that this
196
    guarantees that bf will be null terminated.
197
*/
198
 
6 7u83 199
void
200
bfputs(BUFFER *bf, string s)
2 7u83 201
{
6 7u83 202
	gen_size m = (gen_size)ustrlen(s);
203
	string p = stretch_buffer(bf, bf->posn, m);
204
	ustrcpy_v(p, s);
205
	bf->posn = p + m;
206
	return;
2 7u83 207
}
208
 
209
 
210
/*
211
    ADD A FORMATTED STRING TO A BUFFER
212
 
213
    This routine adds the string s to the buffer bf, using printf-like
214
    format characters to print the extra arguments.  Note that this
215
    guarantees that bf will be null terminated.
216
*/
217
 
6 7u83 218
void
219
bfprintf(BUFFER *bf, CONST char *s, ...) /* VARARGS */
2 7u83 220
{
6 7u83 221
	char c;
222
	string p;
223
	gen_size m;
224
	va_list args;
2 7u83 225
#if FS_STDARG
6 7u83 226
	va_start(args, s);
2 7u83 227
#else
6 7u83 228
	BUFFER *bf;
229
	CONST char *s;
230
	va_start(args);
231
	bf = va_arg(args, BUFFER *);
232
	s = va_arg(args, CONST char *);
2 7u83 233
#endif
6 7u83 234
	m = (gen_size)strlen(s);
235
	p = stretch_buffer(bf, bf->posn, m);
2 7u83 236
 
6 7u83 237
	/* Scan through format string */
238
	while (c = *(s++), c != 0) {
239
		if (c == '%') {
240
			int ext = 0;
241
			c = *(s++);
242
			if (c == 'l') {
243
				c = *(s++);
244
				ext = 1;
245
			}
246
			switch (c) {
247
			case 'c': {
248
				/* '%c' -> character (passed as int) */
249
				int ac = va_arg(args, int);
250
				*(p++) = (character)ac;
251
				break;
252
			}
253
			case 'd': {
254
				p = stretch_buffer(bf, p,(gen_size)50);
255
				if (ext) {
256
					/* '%ld' -> long */
257
					long al = va_arg(args, long);
258
					sprintf_v(strlit(p), "%ld", al);
259
				} else {
260
					/* '%d' -> int */
261
					int ad = va_arg(args, int);
262
					sprintf_v(strlit(p), "%d", ad);
263
				}
264
				p = p + ustrlen(p);
265
				break;
266
			}
267
			case 's': {
268
				/* '%s' -> string */
269
				string as = va_arg(args, string);
270
				if (as) {
271
					m = (gen_size)ustrlen(as);
272
					p = stretch_buffer(bf, p, m);
273
					ustrcpy_v(p, as);
274
					p += m;
275
				}
276
				break;
277
			}
278
			case 'u': {
279
				p = stretch_buffer(bf, p,(gen_size)50);
280
				if (ext) {
281
					/* '%lu' -> unsigned long */
282
					unsigned long al =
283
					    va_arg(args, unsigned long);
284
					sprintf_v(strlit(p), "%lu", al);
285
				} else {
286
					/* '%u' -> unsigned */
287
					unsigned au = va_arg(args, unsigned);
288
					sprintf_v(strlit(p), "%u", au);
289
				}
290
				p = p + ustrlen(p);
291
				break;
292
			}
293
			case 'x': {
294
				/* '%x' -> char * */
295
				char *ax = va_arg(args, char *);
296
				if (ax) {
297
					m = (gen_size)strlen(ax);
298
					p = stretch_buffer(bf, p, m);
299
					ustrcpy_v(p, ustrlit(ax));
300
					p += m;
301
				}
302
				break;
303
			}
304
			case '%': {
305
				/* '%%' -> percent */
306
				*(p++) = (character)c;
307
				break;
308
			}
309
			default : {
310
				/* Other characters */
311
				FAIL(Unknown format character);
312
				s = "<ERROR>";
313
				break;
314
			}
315
			}
316
		} else {
317
			*(p++) = (character)c;
2 7u83 318
		}
319
	}
6 7u83 320
	*p = 0;
321
	bf->posn = p;
322
	va_end(args);
323
	return;
2 7u83 324
}
325
 
326
 
327
/*
328
    READ A STRING FROM A BUFFER
329
 
330
    This routine reads at most n characters from the buffer bf into the
331
    string s.  It returns the number of characters read.
332
*/
333
 
6 7u83 334
gen_size
335
bfread(BUFFER *bf, string s, gen_size n)
2 7u83 336
{
6 7u83 337
	string p = bf->posn;
338
	gen_size m = (gen_size)(bf->end - p);
339
	if (m > n)m = n;
340
	if (m) {
341
		xumemcpy(s, p, m);
342
		bf->posn = p + m;
343
	}
344
	return (m);
2 7u83 345
}