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