buf.c revision 94587
1/*
2 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
3 * Copyright (c) 1988, 1989 by Adam de Boor
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)buf.c	8.1 (Berkeley) 6/6/93
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 94587 2002-04-13 10:17:18Z obrien $");
43
44/*-
45 * buf.c --
46 *	Functions for automatically-expanded buffers.
47 */
48
49#include    "sprite.h"
50#include    "make.h"
51#include    "buf.h"
52
53#ifndef max
54#define max(a,b)  ((a) > (b) ? (a) : (b))
55#endif
56
57/*
58 * BufExpand --
59 * 	Expand the given buffer to hold the given number of additional
60 *	bytes.
61 *	Makes sure there's room for an extra NULL byte at the end of the
62 *	buffer in case it holds a string.
63 */
64#define BufExpand(bp,nb) \
65 	if (bp->left < (nb)+1) {\
66	    int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
67	    Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
68	    \
69	    (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
70	    (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
71	    (bp)->buffer = newBuf;\
72	    (bp)->size = newSize;\
73	    (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
74	}
75
76#define BUF_DEF_SIZE	256 	/* Default buffer size */
77#define BUF_ADD_INC	256 	/* Expansion increment when Adding */
78#define BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
79
80/*-
81 *-----------------------------------------------------------------------
82 * Buf_OvAddByte --
83 *	Add a single byte to the buffer.  left is zero or negative.
84 *
85 * Results:
86 *	None.
87 *
88 * Side Effects:
89 *	The buffer may be expanded.
90 *
91 *-----------------------------------------------------------------------
92 */
93void
94Buf_OvAddByte (bp, byte)
95    Buffer bp;
96    int    byte;
97{
98    int nbytes = 1;
99    bp->left = 0;
100    BufExpand (bp, nbytes);
101
102    *bp->inPtr++ = byte;
103    bp->left--;
104
105    /*
106     * Null-terminate
107     */
108    *bp->inPtr = 0;
109}
110
111/*-
112 *-----------------------------------------------------------------------
113 * Buf_AddBytes --
114 *	Add a number of bytes to the buffer.
115 *
116 * Results:
117 *	None.
118 *
119 * Side Effects:
120 *	Guess what?
121 *
122 *-----------------------------------------------------------------------
123 */
124void
125Buf_AddBytes (bp, numBytes, bytesPtr)
126    Buffer bp;
127    int	     numBytes;
128    const Byte *bytesPtr;
129{
130
131    BufExpand (bp, numBytes);
132
133    memcpy (bp->inPtr, bytesPtr, numBytes);
134    bp->inPtr += numBytes;
135    bp->left -= numBytes;
136
137    /*
138     * Null-terminate
139     */
140    *bp->inPtr = 0;
141}
142
143/*-
144 *-----------------------------------------------------------------------
145 * Buf_UngetByte --
146 *	Place the byte back at the beginning of the buffer.
147 *
148 * Results:
149 *	SUCCESS if the byte was added ok. FAILURE if not.
150 *
151 * Side Effects:
152 *	The byte is stuffed in the buffer and outPtr is decremented.
153 *
154 *-----------------------------------------------------------------------
155 */
156void
157Buf_UngetByte (bp, byte)
158    Buffer bp;
159    int    byte;
160{
161
162    if (bp->outPtr != bp->buffer) {
163	bp->outPtr--;
164	*bp->outPtr = byte;
165    } else if (bp->outPtr == bp->inPtr) {
166	*bp->inPtr = byte;
167	bp->inPtr++;
168	bp->left--;
169	*bp->inPtr = 0;
170    } else {
171	/*
172	 * Yech. have to expand the buffer to stuff this thing in.
173	 * We use a different expansion constant because people don't
174	 * usually push back many bytes when they're doing it a byte at
175	 * a time...
176	 */
177	int 	  numBytes = bp->inPtr - bp->outPtr;
178	Byte	  *newBuf;
179
180	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
181	memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
182	bp->outPtr = newBuf + BUF_UNGET_INC;
183	bp->inPtr = bp->outPtr + numBytes;
184	free ((char *)bp->buffer);
185	bp->buffer = newBuf;
186	bp->size += BUF_UNGET_INC;
187	bp->left = bp->size - (bp->inPtr - bp->buffer);
188	bp->outPtr -= 1;
189	*bp->outPtr = byte;
190    }
191}
192
193/*-
194 *-----------------------------------------------------------------------
195 * Buf_UngetBytes --
196 *	Push back a series of bytes at the beginning of the buffer.
197 *
198 * Results:
199 *	None.
200 *
201 * Side Effects:
202 *	outPtr is decremented and the bytes copied into the buffer.
203 *
204 *-----------------------------------------------------------------------
205 */
206void
207Buf_UngetBytes (bp, numBytes, bytesPtr)
208    Buffer  bp;
209    int	    numBytes;
210    Byte    *bytesPtr;
211{
212
213    if (bp->outPtr - bp->buffer >= numBytes) {
214	bp->outPtr -= numBytes;
215	memcpy (bp->outPtr, bytesPtr, numBytes);
216    } else if (bp->outPtr == bp->inPtr) {
217	Buf_AddBytes (bp, numBytes, bytesPtr);
218    } else {
219	int 	  curNumBytes = bp->inPtr - bp->outPtr;
220	Byte	  *newBuf;
221	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
222
223	newBuf = (Byte *)emalloc (bp->size + newBytes);
224	memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
225	bp->outPtr = newBuf + newBytes;
226	bp->inPtr = bp->outPtr + curNumBytes;
227	free ((char *)bp->buffer);
228	bp->buffer = newBuf;
229	bp->size += newBytes;
230	bp->left = bp->size - (bp->inPtr - bp->buffer);
231	bp->outPtr -= numBytes;
232	memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
233    }
234}
235
236/*-
237 *-----------------------------------------------------------------------
238 * Buf_GetByte --
239 *	Return the next byte from the buffer. Actually returns an integer.
240 *
241 * Results:
242 *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
243 *	itself if there is one.
244 *
245 * Side Effects:
246 *	outPtr is incremented and both outPtr and inPtr will be reset if
247 *	the buffer is emptied.
248 *
249 *-----------------------------------------------------------------------
250 */
251int
252Buf_GetByte (bp)
253    Buffer bp;
254{
255    int	    res;
256
257    if (bp->inPtr == bp->outPtr) {
258	return (BUF_ERROR);
259    } else {
260	res = (int) *bp->outPtr;
261	bp->outPtr += 1;
262	if (bp->outPtr == bp->inPtr) {
263	    bp->outPtr = bp->inPtr = bp->buffer;
264	    bp->left = bp->size;
265	    *bp->inPtr = 0;
266	}
267	return (res);
268    }
269}
270
271/*-
272 *-----------------------------------------------------------------------
273 * Buf_GetBytes --
274 *	Extract a number of bytes from the buffer.
275 *
276 * Results:
277 *	The number of bytes gotten.
278 *
279 * Side Effects:
280 *	The passed array is overwritten.
281 *
282 *-----------------------------------------------------------------------
283 */
284int
285Buf_GetBytes (bp, numBytes, bytesPtr)
286    Buffer  bp;
287    int	    numBytes;
288    Byte    *bytesPtr;
289{
290
291    if (bp->inPtr - bp->outPtr < numBytes) {
292	numBytes = bp->inPtr - bp->outPtr;
293    }
294    memcpy (bytesPtr, bp->outPtr, numBytes);
295    bp->outPtr += numBytes;
296
297    if (bp->outPtr == bp->inPtr) {
298	bp->outPtr = bp->inPtr = bp->buffer;
299	bp->left = bp->size;
300	*bp->inPtr = 0;
301    }
302    return (numBytes);
303}
304
305/*-
306 *-----------------------------------------------------------------------
307 * Buf_GetAll --
308 *	Get all the available data at once.
309 *
310 * Results:
311 *	A pointer to the data and the number of bytes available.
312 *
313 * Side Effects:
314 *	None.
315 *
316 *-----------------------------------------------------------------------
317 */
318Byte *
319Buf_GetAll (bp, numBytesPtr)
320    Buffer  bp;
321    int	    *numBytesPtr;
322{
323
324    if (numBytesPtr != (int *)NULL) {
325	*numBytesPtr = bp->inPtr - bp->outPtr;
326    }
327
328    return (bp->outPtr);
329}
330
331/*-
332 *-----------------------------------------------------------------------
333 * Buf_Discard --
334 *	Throw away bytes in a buffer.
335 *
336 * Results:
337 *	None.
338 *
339 * Side Effects:
340 *	The bytes are discarded.
341 *
342 *-----------------------------------------------------------------------
343 */
344void
345Buf_Discard (bp, numBytes)
346    Buffer  bp;
347    int	    numBytes;
348{
349
350    if (bp->inPtr - bp->outPtr <= numBytes) {
351	bp->inPtr = bp->outPtr = bp->buffer;
352	bp->left = bp->size;
353	*bp->inPtr = 0;
354    } else {
355	bp->outPtr += numBytes;
356    }
357}
358
359/*-
360 *-----------------------------------------------------------------------
361 * Buf_Size --
362 *	Returns the number of bytes in the given buffer. Doesn't include
363 *	the null-terminating byte.
364 *
365 * Results:
366 *	The number of bytes.
367 *
368 * Side Effects:
369 *	None.
370 *
371 *-----------------------------------------------------------------------
372 */
373int
374Buf_Size (buf)
375    Buffer  buf;
376{
377    return (buf->inPtr - buf->outPtr);
378}
379
380/*-
381 *-----------------------------------------------------------------------
382 * Buf_Init --
383 *	Initialize a buffer. If no initial size is given, a reasonable
384 *	default is used.
385 *
386 * Results:
387 *	A buffer to be given to other functions in this library.
388 *
389 * Side Effects:
390 *	The buffer is created, the space allocated and pointers
391 *	initialized.
392 *
393 *-----------------------------------------------------------------------
394 */
395Buffer
396Buf_Init (size)
397    int	    size; 	/* Initial size for the buffer */
398{
399    Buffer bp;	  	/* New Buffer */
400
401    bp = (Buffer)emalloc(sizeof(*bp));
402
403    if (size <= 0) {
404	size = BUF_DEF_SIZE;
405    }
406    bp->left = bp->size = size;
407    bp->buffer = (Byte *)emalloc(size);
408    bp->inPtr = bp->outPtr = bp->buffer;
409    *bp->inPtr = 0;
410
411    return (bp);
412}
413
414/*-
415 *-----------------------------------------------------------------------
416 * Buf_Destroy --
417 *	Nuke a buffer and all its resources.
418 *
419 * Results:
420 *	None.
421 *
422 * Side Effects:
423 *	The buffer is freed.
424 *
425 *-----------------------------------------------------------------------
426 */
427void
428Buf_Destroy (buf, freeData)
429    Buffer  buf;  	/* Buffer to destroy */
430    Boolean freeData;	/* TRUE if the data should be destroyed as well */
431{
432
433    if (freeData) {
434	free ((char *)buf->buffer);
435    }
436    free ((char *)buf);
437}
438
439/*-
440 *-----------------------------------------------------------------------
441 * Buf_ReplaceLastByte --
442 *     Replace the last byte in a buffer.
443 *
444 * Results:
445 *     None.
446 *
447 * Side Effects:
448 *     If the buffer was empty intially, then a new byte will be added.
449 *     Otherwise, the last byte is overwritten.
450 *
451 *-----------------------------------------------------------------------
452 */
453void
454Buf_ReplaceLastByte (buf, byte)
455    Buffer buf;	/* buffer to augment */
456    int byte;	/* byte to be written */
457{
458    if (buf->inPtr == buf->outPtr)
459        Buf_AddByte(buf, byte);
460    else
461        *(buf->inPtr - 1) = byte;
462}
463