buf.c revision 103503
1193323Sed/*
2193323Sed * Copyright (c) 1988, 1989, 1990, 1993
3193323Sed *	The Regents of the University of California.  All rights reserved.
4193323Sed * Copyright (c) 1988, 1989 by Adam de Boor
5193323Sed * Copyright (c) 1989 by Berkeley Softworks
6193323Sed * All rights reserved.
7193323Sed *
8193323Sed * This code is derived from software contributed to Berkeley by
9193323Sed * Adam de Boor.
10193323Sed *
11193323Sed * Redistribution and use in source and binary forms, with or without
12193323Sed * modification, are permitted provided that the following conditions
13193323Sed * are met:
14193323Sed * 1. Redistributions of source code must retain the above copyright
15193323Sed *    notice, this list of conditions and the following disclaimer.
16218893Sdim * 2. Redistributions in binary form must reproduce the above copyright
17193323Sed *    notice, this list of conditions and the following disclaimer in the
18193323Sed *    documentation and/or other materials provided with the distribution.
19193323Sed * 3. All advertising materials mentioning features or use of this software
20198090Srdivacky *    must display the following acknowledgement:
21193323Sed *	This product includes software developed by the University of
22198090Srdivacky *	California, Berkeley and its contributors.
23234353Sdim * 4. Neither the name of the University nor the names of its contributors
24198090Srdivacky *    may be used to endorse or promote products derived from this software
25193323Sed *    without specific prior written permission.
26234353Sdim *
27193323Sed * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29218893Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30204792Srdivacky * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33218893Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35218893Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36218893Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37218893Sdim * SUCH DAMAGE.
38218893Sdim *
39226633Sdim * @(#)buf.c	8.1 (Berkeley) 6/6/93
40218893Sdim */
41218893Sdim
42218893Sdim#include <sys/cdefs.h>
43218893Sdim__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 103503 2002-09-17 21:29:06Z jmallett $");
44218893Sdim
45218893Sdim/*-
46234353Sdim * buf.c --
47234353Sdim *	Functions for automatically-expanded buffers.
48234353Sdim */
49234353Sdim
50234353Sdim#include    "sprite.h"
51234353Sdim#include    "make.h"
52234353Sdim#include    "buf.h"
53234353Sdim
54234353Sdim#ifndef max
55234353Sdim#define	max(a,b)  ((a) > (b) ? (a) : (b))
56234353Sdim#endif
57234353Sdim
58234353Sdim/*
59234353Sdim * BufExpand --
60234353Sdim * 	Expand the given buffer to hold the given number of additional
61234353Sdim *	bytes.
62234353Sdim *	Makes sure there's room for an extra NULL byte at the end of the
63234353Sdim *	buffer in case it holds a string.
64234353Sdim */
65234353Sdim#define	BufExpand(bp,nb) \
66234353Sdim 	if (bp->left < (nb)+1) {\
67234353Sdim	    int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
68234353Sdim	    Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
69234353Sdim	    \
70234353Sdim	    (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
71234353Sdim	    (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
72234353Sdim	    (bp)->buffer = newBuf;\
73234353Sdim	    (bp)->size = newSize;\
74234353Sdim	    (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
75234353Sdim	}
76234353Sdim
77234353Sdim#define	BUF_DEF_SIZE	256 	/* Default buffer size */
78234353Sdim#define	BUF_ADD_INC	256 	/* Expansion increment when Adding */
79234353Sdim#define	BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
80234353Sdim
81234353Sdim/*-
82234353Sdim *-----------------------------------------------------------------------
83234353Sdim * Buf_OvAddByte --
84234353Sdim *	Add a single byte to the buffer.  left is zero or negative.
85234353Sdim *
86234353Sdim * Results:
87234353Sdim *	None.
88234353Sdim *
89234353Sdim * Side Effects:
90234353Sdim *	The buffer may be expanded.
91234353Sdim *
92234353Sdim *-----------------------------------------------------------------------
93234353Sdim */
94234353Sdimvoid
95234353SdimBuf_OvAddByte (bp, byte)
96234353Sdim    Buffer bp;
97234353Sdim    int    byte;
98234353Sdim{
99234353Sdim    bp->left = 0;
100234353Sdim    BufExpand (bp, 1);
101234353Sdim
102234353Sdim    *bp->inPtr++ = byte;
103234353Sdim    bp->left--;
104234353Sdim
105234353Sdim    /*
106234353Sdim     * Null-terminate
107234353Sdim     */
108234353Sdim    *bp->inPtr = 0;
109234353Sdim}
110234353Sdim
111234353Sdim/*-
112234353Sdim *-----------------------------------------------------------------------
113234353Sdim * Buf_AddBytes --
114234353Sdim *	Add a number of bytes to the buffer.
115234353Sdim *
116234353Sdim * Results:
117234353Sdim *	None.
118234353Sdim *
119234353Sdim * Side Effects:
120234353Sdim *	Guess what?
121234353Sdim *
122234353Sdim *-----------------------------------------------------------------------
123234353Sdim */
124234353Sdimvoid
125234353SdimBuf_AddBytes (bp, numBytes, bytesPtr)
126234353Sdim    Buffer bp;
127234353Sdim    int	     numBytes;
128234353Sdim    const Byte *bytesPtr;
129234353Sdim{
130234353Sdim
131234353Sdim    BufExpand (bp, numBytes);
132234353Sdim
133234353Sdim    memcpy (bp->inPtr, bytesPtr, numBytes);
134234353Sdim    bp->inPtr += numBytes;
135234353Sdim    bp->left -= numBytes;
136234353Sdim
137234353Sdim    /*
138234353Sdim     * Null-terminate
139234353Sdim     */
140234353Sdim    *bp->inPtr = 0;
141234353Sdim}
142234353Sdim
143234353Sdim/*-
144234353Sdim *-----------------------------------------------------------------------
145234353Sdim * Buf_UngetByte --
146234353Sdim *	Place the byte back at the beginning of the buffer.
147234353Sdim *
148234353Sdim * Results:
149234353Sdim *	SUCCESS if the byte was added ok. FAILURE if not.
150234353Sdim *
151234353Sdim * Side Effects:
152234353Sdim *	The byte is stuffed in the buffer and outPtr is decremented.
153234353Sdim *
154234353Sdim *-----------------------------------------------------------------------
155234353Sdim */
156234353Sdimvoid
157234353SdimBuf_UngetByte (bp, byte)
158234353Sdim    Buffer bp;
159234353Sdim    int    byte;
160234353Sdim{
161234353Sdim
162234353Sdim    if (bp->outPtr != bp->buffer) {
163234353Sdim	bp->outPtr--;
164234353Sdim	*bp->outPtr = byte;
165234353Sdim    } else if (bp->outPtr == bp->inPtr) {
166234353Sdim	*bp->inPtr = byte;
167234353Sdim	bp->inPtr++;
168234353Sdim	bp->left--;
169234353Sdim	*bp->inPtr = 0;
170234353Sdim    } else {
171234353Sdim	/*
172234353Sdim	 * Yech. have to expand the buffer to stuff this thing in.
173234353Sdim	 * We use a different expansion constant because people don't
174234353Sdim	 * usually push back many bytes when they're doing it a byte at
175234353Sdim	 * a time...
176234353Sdim	 */
177234353Sdim	int 	  numBytes = bp->inPtr - bp->outPtr;
178234353Sdim	Byte	  *newBuf;
179234353Sdim
180234353Sdim	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
181234353Sdim	memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
182234353Sdim	bp->outPtr = newBuf + BUF_UNGET_INC;
183234353Sdim	bp->inPtr = bp->outPtr + numBytes;
184234353Sdim	free ((char *)bp->buffer);
185234353Sdim	bp->buffer = newBuf;
186234353Sdim	bp->size += BUF_UNGET_INC;
187234353Sdim	bp->left = bp->size - (bp->inPtr - bp->buffer);
188234353Sdim	bp->outPtr -= 1;
189234353Sdim	*bp->outPtr = byte;
190234353Sdim    }
191234353Sdim}
192234353Sdim
193234353Sdim/*-
194234353Sdim *-----------------------------------------------------------------------
195234353Sdim * Buf_UngetBytes --
196234353Sdim *	Push back a series of bytes at the beginning of the buffer.
197234353Sdim *
198234353Sdim * Results:
199234353Sdim *	None.
200234353Sdim *
201234353Sdim * Side Effects:
202234353Sdim *	outPtr is decremented and the bytes copied into the buffer.
203234353Sdim *
204234353Sdim *-----------------------------------------------------------------------
205234353Sdim */
206234353Sdimvoid
207234353SdimBuf_UngetBytes (bp, numBytes, bytesPtr)
208234353Sdim    Buffer  bp;
209234353Sdim    int	    numBytes;
210234353Sdim    Byte    *bytesPtr;
211234353Sdim{
212234353Sdim
213234353Sdim    if (bp->outPtr - bp->buffer >= numBytes) {
214234353Sdim	bp->outPtr -= numBytes;
215234353Sdim	memcpy (bp->outPtr, bytesPtr, numBytes);
216193323Sed    } else if (bp->outPtr == bp->inPtr) {
217193323Sed	Buf_AddBytes (bp, numBytes, bytesPtr);
218193323Sed    } else {
219193323Sed	int 	  curNumBytes = bp->inPtr - bp->outPtr;
220193323Sed	Byte	  *newBuf;
221193323Sed	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
222198090Srdivacky
223198090Srdivacky	newBuf = (Byte *)emalloc (bp->size + newBytes);
224198090Srdivacky	memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
225234353Sdim	bp->outPtr = newBuf + newBytes;
226198090Srdivacky	bp->inPtr = bp->outPtr + curNumBytes;
227198090Srdivacky	free ((char *)bp->buffer);
228234353Sdim	bp->buffer = newBuf;
229198090Srdivacky	bp->size += newBytes;
230193323Sed	bp->left = bp->size - (bp->inPtr - bp->buffer);
231193323Sed	bp->outPtr -= numBytes;
232234353Sdim	memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
233234353Sdim    }
234234353Sdim}
235234353Sdim
236234353Sdim/*-
237194612Sed *-----------------------------------------------------------------------
238194612Sed * Buf_GetByte --
239203954Srdivacky *	Return the next byte from the buffer. Actually returns an integer.
240194612Sed *
241234353Sdim * Results:
242193323Sed *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
243193323Sed *	itself if there is one.
244193323Sed *
245193323Sed * Side Effects:
246193323Sed *	outPtr is incremented and both outPtr and inPtr will be reset if
247234353Sdim *	the buffer is emptied.
248234353Sdim *
249193323Sed *-----------------------------------------------------------------------
250193323Sed */
251194612Sedint
252194612SedBuf_GetByte (bp)
253194612Sed    Buffer bp;
254218893Sdim{
255234353Sdim    int	    res;
256193323Sed
257193323Sed    if (bp->inPtr == bp->outPtr) {
258194612Sed	return (BUF_ERROR);
259234353Sdim    } else {
260234353Sdim	res = (int) *bp->outPtr;
261234353Sdim	bp->outPtr += 1;
262234353Sdim	if (bp->outPtr == bp->inPtr) {
263234353Sdim	    bp->outPtr = bp->inPtr = bp->buffer;
264218893Sdim	    bp->left = bp->size;
265234353Sdim	    *bp->inPtr = 0;
266234353Sdim	}
267234353Sdim	return (res);
268234353Sdim    }
269234353Sdim}
270194612Sed
271194612Sed/*-
272194612Sed *-----------------------------------------------------------------------
273234353Sdim * Buf_GetBytes --
274193323Sed *	Extract a number of bytes from the buffer.
275193323Sed *
276193323Sed * Results:
277234353Sdim *	The number of bytes gotten.
278234353Sdim *
279234353Sdim * Side Effects:
280234353Sdim *	The passed array is overwritten.
281234353Sdim *
282234353Sdim *-----------------------------------------------------------------------
283234353Sdim */
284234353Sdimint
285234353SdimBuf_GetBytes (bp, numBytes, bytesPtr)
286234353Sdim    Buffer  bp;
287234353Sdim    int	    numBytes;
288234353Sdim    Byte    *bytesPtr;
289234353Sdim{
290198090Srdivacky
291193323Sed    if (bp->inPtr - bp->outPtr < numBytes) {
292234353Sdim	numBytes = bp->inPtr - bp->outPtr;
293234353Sdim    }
294193323Sed    memcpy (bytesPtr, bp->outPtr, numBytes);
295218893Sdim    bp->outPtr += numBytes;
296218893Sdim
297193323Sed    if (bp->outPtr == bp->inPtr) {
298193323Sed	bp->outPtr = bp->inPtr = bp->buffer;
299198090Srdivacky	bp->left = bp->size;
300198090Srdivacky	*bp->inPtr = 0;
301198090Srdivacky    }
302198090Srdivacky    return (numBytes);
303218893Sdim}
304198090Srdivacky
305234353Sdim/*-
306198090Srdivacky *-----------------------------------------------------------------------
307198090Srdivacky * Buf_GetAll --
308198090Srdivacky *	Get all the available data at once.
309223017Sdim *
310223017Sdim * Results:
311223017Sdim *	A pointer to the data and the number of bytes available.
312223017Sdim *
313223017Sdim * Side Effects:
314234353Sdim *	None.
315234353Sdim *
316223017Sdim *-----------------------------------------------------------------------
317223017Sdim */
318193323SedByte *
319223017SdimBuf_GetAll (bp, numBytesPtr)
320223017Sdim    Buffer  bp;
321193323Sed    int	    *numBytesPtr;
322234353Sdim{
323193323Sed
324193323Sed    if (numBytesPtr != (int *)NULL) {
325198090Srdivacky	*numBytesPtr = bp->inPtr - bp->outPtr;
326193323Sed    }
327193323Sed
328193323Sed    return (bp->outPtr);
329198090Srdivacky}
330193323Sed
331234353Sdim/*-
332234353Sdim *-----------------------------------------------------------------------
333234353Sdim * Buf_Discard --
334234353Sdim *	Throw away bytes in a buffer.
335193323Sed *
336193323Sed * Results:
337234353Sdim *	None.
338234353Sdim *
339193323Sed * Side Effects:
340193323Sed *	The bytes are discarded.
341193323Sed *
342193323Sed *-----------------------------------------------------------------------
343193323Sed */
344193323Sedvoid
345193323SedBuf_Discard (bp, numBytes)
346193323Sed    Buffer  bp;
347193323Sed    int	    numBytes;
348193323Sed{
349234353Sdim
350234353Sdim    if (bp->inPtr - bp->outPtr <= numBytes) {
351193323Sed	bp->inPtr = bp->outPtr = bp->buffer;
352193323Sed	bp->left = bp->size;
353193323Sed	*bp->inPtr = 0;
354193323Sed    } else {
355193323Sed	bp->outPtr += numBytes;
356193323Sed    }
357193323Sed}
358193323Sed
359193323Sed/*-
360193323Sed *-----------------------------------------------------------------------
361234353Sdim * Buf_Size --
362234353Sdim *	Returns the number of bytes in the given buffer. Doesn't include
363193323Sed *	the null-terminating byte.
364193323Sed *
365193323Sed * Results:
366193323Sed *	The number of bytes.
367193323Sed *
368193323Sed * Side Effects:
369193323Sed *	None.
370193323Sed *
371193323Sed *-----------------------------------------------------------------------
372193323Sed */
373193323Sedint
374234353SdimBuf_Size (buf)
375234353Sdim    Buffer  buf;
376234353Sdim{
377234353Sdim    return (buf->inPtr - buf->outPtr);
378193323Sed}
379193323Sed
380193323Sed/*-
381193323Sed *-----------------------------------------------------------------------
382193323Sed * Buf_Init --
383234353Sdim *	Initialize a buffer. If no initial size is given, a reasonable
384193323Sed *	default is used.
385193323Sed *
386218893Sdim * Results:
387218893Sdim *	A buffer to be given to other functions in this library.
388234353Sdim *
389193323Sed * Side Effects:
390193323Sed *	The buffer is created, the space allocated and pointers
391193323Sed *	initialized.
392193323Sed *
393193323Sed *-----------------------------------------------------------------------
394234353Sdim */
395193323SedBuffer
396193323SedBuf_Init (size)
397193323Sed    int	    size; 	/* Initial size for the buffer */
398234353Sdim{
399234353Sdim    Buffer bp;	  	/* New Buffer */
400193323Sed
401193323Sed    bp = (Buffer)emalloc(sizeof(*bp));
402193323Sed
403193323Sed    if (size <= 0) {
404193323Sed	size = BUF_DEF_SIZE;
405193323Sed    }
406193323Sed    bp->left = bp->size = size;
407193323Sed    bp->buffer = (Byte *)emalloc(size);
408193323Sed    bp->inPtr = bp->outPtr = bp->buffer;
409193323Sed    *bp->inPtr = 0;
410193323Sed
411193323Sed    return (bp);
412193323Sed}
413193323Sed
414193323Sed/*-
415193323Sed *-----------------------------------------------------------------------
416193323Sed * Buf_Destroy --
417193323Sed *	Nuke a buffer and all its resources.
418193323Sed *
419193323Sed * Results:
420193323Sed *	None.
421193323Sed *
422226633Sdim * Side Effects:
423198090Srdivacky *	The buffer is freed.
424198090Srdivacky *
425193323Sed *-----------------------------------------------------------------------
426193323Sed */
427204642Srdivackyvoid
428198090SrdivackyBuf_Destroy (buf, freeData)
429198090Srdivacky    Buffer  buf;  	/* Buffer to destroy */
430198090Srdivacky    Boolean freeData;	/* TRUE if the data should be destroyed as well */
431198090Srdivacky{
432218893Sdim
433218893Sdim    if (freeData) {
434234353Sdim	free ((char *)buf->buffer);
435218893Sdim    }
436218893Sdim    free ((char *)buf);
437193323Sed}
438193323Sed
439193323Sed/*-
440193323Sed *-----------------------------------------------------------------------
441193323Sed * Buf_ReplaceLastByte --
442193323Sed *     Replace the last byte in a buffer.
443226633Sdim *
444204642Srdivacky * Results:
445195340Sed *     None.
446195340Sed *
447204642Srdivacky * Side Effects:
448234353Sdim *     If the buffer was empty intially, then a new byte will be added.
449193323Sed *     Otherwise, the last byte is overwritten.
450193323Sed *
451193323Sed *-----------------------------------------------------------------------
452193323Sed */
453193323Sedvoid
454193323SedBuf_ReplaceLastByte (buf, byte)
455198090Srdivacky    Buffer buf;	/* buffer to augment */
456193323Sed    int byte;	/* byte to be written */
457218893Sdim{
458218893Sdim    if (buf->inPtr == buf->outPtr)
459234353Sdim        Buf_AddByte(buf, byte);
460193323Sed    else
461218893Sdim        *(buf->inPtr - 1) = byte;
462218893Sdim}
463193323Sed