xref: /netbsd-src/usr.bin/make/buf.c (revision d9158b13b5dfe46201430699a3f7a235ecf28df3)
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 
39 #ifndef lint
40 /* from: static char sccsid[] = "@(#)buf.c	5.5 (Berkeley) 12/28/90"; */
41 static char *rcsid = "$Id: buf.c,v 1.5 1994/06/06 22:45:19 jtc Exp $";
42 #endif /* not lint */
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 *) realloc((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  */
93 void
94 Buf_OvAddByte (bp, byte)
95     register 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  */
124 void
125 Buf_AddBytes (bp, numBytes, bytesPtr)
126     register Buffer bp;
127     int	    numBytes;
128     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  */
156 void
157 Buf_UngetByte (bp, byte)
158     register 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  */
206 void
207 Buf_UngetBytes (bp, numBytes, bytesPtr)
208     register 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  */
251 int
252 Buf_GetByte (bp)
253     register 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  */
284 int
285 Buf_GetBytes (bp, numBytes, bytesPtr)
286     register 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  */
318 Byte *
319 Buf_GetAll (bp, numBytesPtr)
320     register 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  */
344 void
345 Buf_Discard (bp, numBytes)
346     register 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  */
373 int
374 Buf_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  */
395 Buffer
396 Buf_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  */
427 void
428 Buf_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