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