Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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