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