xref: /netbsd-src/usr.bin/make/buf.c (revision fdecd6a253f999ae92b139670d9e15cc9df4497c)
1 /*	$NetBSD: buf.c,v 1.10 1997/07/01 21:17:08 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 #include <sys/cdefs.h>
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)buf.c	8.1 (Berkeley) 6/6/93";
45 #else
46 __RCSID("$NetBSD: buf.c,v 1.10 1997/07/01 21:17:08 christos Exp $");
47 #endif
48 #endif /* not lint */
49 
50 /*-
51  * buf.c --
52  *	Functions for automatically-expanded buffers.
53  */
54 
55 #include    "sprite.h"
56 #include    "make.h"
57 #include    "buf.h"
58 
59 #ifndef max
60 #define max(a,b)  ((a) > (b) ? (a) : (b))
61 #endif
62 
63 /*
64  * BufExpand --
65  * 	Expand the given buffer to hold the given number of additional
66  *	bytes.
67  *	Makes sure there's room for an extra NULL byte at the end of the
68  *	buffer in case it holds a string.
69  */
70 #define BufExpand(bp,nb) \
71  	if (bp->left < (nb)+1) {\
72 	    int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
73 	    Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
74 	    \
75 	    (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
76 	    (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
77 	    (bp)->buffer = newBuf;\
78 	    (bp)->size = newSize;\
79 	    (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
80 	}
81 
82 #define BUF_DEF_SIZE	256 	/* Default buffer size */
83 #define BUF_ADD_INC	256 	/* Expansion increment when Adding */
84 #define BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
85 
86 /*-
87  *-----------------------------------------------------------------------
88  * Buf_OvAddByte --
89  *	Add a single byte to the buffer.  left is zero or negative.
90  *
91  * Results:
92  *	None.
93  *
94  * Side Effects:
95  *	The buffer may be expanded.
96  *
97  *-----------------------------------------------------------------------
98  */
99 void
100 Buf_OvAddByte (bp, byte)
101     register Buffer bp;
102     int    byte;
103 {
104     int nbytes = 1;
105     bp->left = 0;
106     BufExpand (bp, nbytes);
107 
108     *bp->inPtr++ = byte;
109     bp->left--;
110 
111     /*
112      * Null-terminate
113      */
114     *bp->inPtr = 0;
115 }
116 
117 /*-
118  *-----------------------------------------------------------------------
119  * Buf_AddBytes --
120  *	Add a number of bytes to the buffer.
121  *
122  * Results:
123  *	None.
124  *
125  * Side Effects:
126  *	Guess what?
127  *
128  *-----------------------------------------------------------------------
129  */
130 void
131 Buf_AddBytes (bp, numBytes, bytesPtr)
132     register Buffer bp;
133     int	    numBytes;
134     const Byte *bytesPtr;
135 {
136 
137     BufExpand (bp, numBytes);
138 
139     memcpy (bp->inPtr, bytesPtr, numBytes);
140     bp->inPtr += numBytes;
141     bp->left -= numBytes;
142 
143     /*
144      * Null-terminate
145      */
146     *bp->inPtr = 0;
147 }
148 
149 /*-
150  *-----------------------------------------------------------------------
151  * Buf_UngetByte --
152  *	Place the byte back at the beginning of the buffer.
153  *
154  * Results:
155  *	SUCCESS if the byte was added ok. FAILURE if not.
156  *
157  * Side Effects:
158  *	The byte is stuffed in the buffer and outPtr is decremented.
159  *
160  *-----------------------------------------------------------------------
161  */
162 void
163 Buf_UngetByte (bp, byte)
164     register Buffer bp;
165     int    byte;
166 {
167 
168     if (bp->outPtr != bp->buffer) {
169 	bp->outPtr--;
170 	*bp->outPtr = byte;
171     } else if (bp->outPtr == bp->inPtr) {
172 	*bp->inPtr = byte;
173 	bp->inPtr++;
174 	bp->left--;
175 	*bp->inPtr = 0;
176     } else {
177 	/*
178 	 * Yech. have to expand the buffer to stuff this thing in.
179 	 * We use a different expansion constant because people don't
180 	 * usually push back many bytes when they're doing it a byte at
181 	 * a time...
182 	 */
183 	int 	  numBytes = bp->inPtr - bp->outPtr;
184 	Byte	  *newBuf;
185 
186 	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
187 	memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
188 	bp->outPtr = newBuf + BUF_UNGET_INC;
189 	bp->inPtr = bp->outPtr + numBytes;
190 	free ((char *)bp->buffer);
191 	bp->buffer = newBuf;
192 	bp->size += BUF_UNGET_INC;
193 	bp->left = bp->size - (bp->inPtr - bp->buffer);
194 	bp->outPtr -= 1;
195 	*bp->outPtr = byte;
196     }
197 }
198 
199 /*-
200  *-----------------------------------------------------------------------
201  * Buf_UngetBytes --
202  *	Push back a series of bytes at the beginning of the buffer.
203  *
204  * Results:
205  *	None.
206  *
207  * Side Effects:
208  *	outPtr is decremented and the bytes copied into the buffer.
209  *
210  *-----------------------------------------------------------------------
211  */
212 void
213 Buf_UngetBytes (bp, numBytes, bytesPtr)
214     register Buffer bp;
215     int	    numBytes;
216     Byte    *bytesPtr;
217 {
218 
219     if (bp->outPtr - bp->buffer >= numBytes) {
220 	bp->outPtr -= numBytes;
221 	memcpy (bp->outPtr, bytesPtr, numBytes);
222     } else if (bp->outPtr == bp->inPtr) {
223 	Buf_AddBytes (bp, numBytes, bytesPtr);
224     } else {
225 	int 	  curNumBytes = bp->inPtr - bp->outPtr;
226 	Byte	  *newBuf;
227 	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
228 
229 	newBuf = (Byte *)emalloc (bp->size + newBytes);
230 	memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
231 	bp->outPtr = newBuf + newBytes;
232 	bp->inPtr = bp->outPtr + curNumBytes;
233 	free ((char *)bp->buffer);
234 	bp->buffer = newBuf;
235 	bp->size += newBytes;
236 	bp->left = bp->size - (bp->inPtr - bp->buffer);
237 	bp->outPtr -= numBytes;
238 	memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
239     }
240 }
241 
242 /*-
243  *-----------------------------------------------------------------------
244  * Buf_GetByte --
245  *	Return the next byte from the buffer. Actually returns an integer.
246  *
247  * Results:
248  *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
249  *	itself if there is one.
250  *
251  * Side Effects:
252  *	outPtr is incremented and both outPtr and inPtr will be reset if
253  *	the buffer is emptied.
254  *
255  *-----------------------------------------------------------------------
256  */
257 int
258 Buf_GetByte (bp)
259     register Buffer bp;
260 {
261     int	    res;
262 
263     if (bp->inPtr == bp->outPtr) {
264 	return (BUF_ERROR);
265     } else {
266 	res = (int) *bp->outPtr;
267 	bp->outPtr += 1;
268 	if (bp->outPtr == bp->inPtr) {
269 	    bp->outPtr = bp->inPtr = bp->buffer;
270 	    bp->left = bp->size;
271 	    *bp->inPtr = 0;
272 	}
273 	return (res);
274     }
275 }
276 
277 /*-
278  *-----------------------------------------------------------------------
279  * Buf_GetBytes --
280  *	Extract a number of bytes from the buffer.
281  *
282  * Results:
283  *	The number of bytes gotten.
284  *
285  * Side Effects:
286  *	The passed array is overwritten.
287  *
288  *-----------------------------------------------------------------------
289  */
290 int
291 Buf_GetBytes (bp, numBytes, bytesPtr)
292     register Buffer bp;
293     int	    numBytes;
294     Byte    *bytesPtr;
295 {
296 
297     if (bp->inPtr - bp->outPtr < numBytes) {
298 	numBytes = bp->inPtr - bp->outPtr;
299     }
300     memcpy (bytesPtr, bp->outPtr, numBytes);
301     bp->outPtr += numBytes;
302 
303     if (bp->outPtr == bp->inPtr) {
304 	bp->outPtr = bp->inPtr = bp->buffer;
305 	bp->left = bp->size;
306 	*bp->inPtr = 0;
307     }
308     return (numBytes);
309 }
310 
311 /*-
312  *-----------------------------------------------------------------------
313  * Buf_GetAll --
314  *	Get all the available data at once.
315  *
316  * Results:
317  *	A pointer to the data and the number of bytes available.
318  *
319  * Side Effects:
320  *	None.
321  *
322  *-----------------------------------------------------------------------
323  */
324 Byte *
325 Buf_GetAll (bp, numBytesPtr)
326     register Buffer bp;
327     int	    *numBytesPtr;
328 {
329 
330     if (numBytesPtr != (int *)NULL) {
331 	*numBytesPtr = bp->inPtr - bp->outPtr;
332     }
333 
334     return (bp->outPtr);
335 }
336 
337 /*-
338  *-----------------------------------------------------------------------
339  * Buf_Discard --
340  *	Throw away bytes in a buffer.
341  *
342  * Results:
343  *	None.
344  *
345  * Side Effects:
346  *	The bytes are discarded.
347  *
348  *-----------------------------------------------------------------------
349  */
350 void
351 Buf_Discard (bp, numBytes)
352     register Buffer bp;
353     int	    numBytes;
354 {
355 
356     if (bp->inPtr - bp->outPtr <= numBytes) {
357 	bp->inPtr = bp->outPtr = bp->buffer;
358 	bp->left = bp->size;
359 	*bp->inPtr = 0;
360     } else {
361 	bp->outPtr += numBytes;
362     }
363 }
364 
365 /*-
366  *-----------------------------------------------------------------------
367  * Buf_Size --
368  *	Returns the number of bytes in the given buffer. Doesn't include
369  *	the null-terminating byte.
370  *
371  * Results:
372  *	The number of bytes.
373  *
374  * Side Effects:
375  *	None.
376  *
377  *-----------------------------------------------------------------------
378  */
379 int
380 Buf_Size (buf)
381     Buffer  buf;
382 {
383     return (buf->inPtr - buf->outPtr);
384 }
385 
386 /*-
387  *-----------------------------------------------------------------------
388  * Buf_Init --
389  *	Initialize a buffer. If no initial size is given, a reasonable
390  *	default is used.
391  *
392  * Results:
393  *	A buffer to be given to other functions in this library.
394  *
395  * Side Effects:
396  *	The buffer is created, the space allocated and pointers
397  *	initialized.
398  *
399  *-----------------------------------------------------------------------
400  */
401 Buffer
402 Buf_Init (size)
403     int	    size; 	/* Initial size for the buffer */
404 {
405     Buffer bp;	  	/* New Buffer */
406 
407     bp = (Buffer)emalloc(sizeof(*bp));
408 
409     if (size <= 0) {
410 	size = BUF_DEF_SIZE;
411     }
412     bp->left = bp->size = size;
413     bp->buffer = (Byte *)emalloc(size);
414     bp->inPtr = bp->outPtr = bp->buffer;
415     *bp->inPtr = 0;
416 
417     return (bp);
418 }
419 
420 /*-
421  *-----------------------------------------------------------------------
422  * Buf_Destroy --
423  *	Nuke a buffer and all its resources.
424  *
425  * Results:
426  *	None.
427  *
428  * Side Effects:
429  *	The buffer is freed.
430  *
431  *-----------------------------------------------------------------------
432  */
433 void
434 Buf_Destroy (buf, freeData)
435     Buffer  buf;  	/* Buffer to destroy */
436     Boolean freeData;	/* TRUE if the data should be destroyed as well */
437 {
438 
439     if (freeData) {
440 	free ((char *)buf->buffer);
441     }
442     free ((char *)buf);
443 }
444 
445 /*-
446  *-----------------------------------------------------------------------
447  * Buf_ReplaceLastByte --
448  *     Replace the last byte in a buffer.
449  *
450  * Results:
451  *     None.
452  *
453  * Side Effects:
454  *     If the buffer was empty intially, then a new byte will be added.
455  *     Otherwise, the last byte is overwritten.
456  *
457  *-----------------------------------------------------------------------
458  */
459 void
460 Buf_ReplaceLastByte (buf, byte)
461     Buffer buf;	/* buffer to augment */
462     int byte;	/* byte to be written */
463 {
464     if (buf->inPtr == buf->outPtr)
465         Buf_AddByte(buf, byte);
466     else
467         *(buf->inPtr - 1) = byte;
468 }
469