Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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