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