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