Merge from vendor branch BINUTILS:
[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.11 2004/12/16 22:23:59 okumoto 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) do {                                          \
65         if ((bp)->left < (nb) + 1) {                                    \
66                 int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC);  \
67                 Byte *newBuf = 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     } while (0)
76
77 #define BUF_DEF_SIZE    256     /* Default buffer size */
78 #define BUF_ADD_INC     256     /* Expansion increment when Adding */
79 #define BUF_UNGET_INC   16      /* Expansion increment when Ungetting */
80
81 /*-
82  *-----------------------------------------------------------------------
83  * Buf_OvAddByte --
84  *      Add a single byte to the buffer.  left is zero or negative.
85  *
86  * Results:
87  *      None.
88  *
89  * Side Effects:
90  *      The buffer may be expanded.
91  *
92  *-----------------------------------------------------------------------
93  */
94 void
95 Buf_OvAddByte(Buffer bp, Byte byte)
96 {
97
98         bp->left = 0;
99         BufExpand(bp, 1);
100
101         *bp->inPtr++ = byte;
102         bp->left--;
103
104         /*
105          * Null-terminate
106          */
107         *bp->inPtr = 0;
108 }
109
110 /*-
111  *-----------------------------------------------------------------------
112  * Buf_AddBytes --
113  *      Add a number of bytes to the buffer.
114  *
115  * Results:
116  *      None.
117  *
118  * Side Effects:
119  *      Guess what?
120  *
121  *-----------------------------------------------------------------------
122  */
123 void
124 Buf_AddBytes(Buffer bp, size_t numBytes, const Byte *bytesPtr)
125 {
126
127         BufExpand(bp, numBytes);
128
129         memcpy(bp->inPtr, bytesPtr, numBytes);
130         bp->inPtr += numBytes;
131         bp->left -= numBytes;
132
133         /*
134          * Null-terminate
135          */
136         *bp->inPtr = 0;
137 }
138
139 /*-
140  *-----------------------------------------------------------------------
141  * Buf_UngetByte --
142  *      Place the byte back at the beginning of the buffer.
143  *
144  * Results:
145  *      SUCCESS if the byte was added ok. FAILURE if not.
146  *
147  * Side Effects:
148  *      The byte is stuffed in the buffer and outPtr is decremented.
149  *
150  *-----------------------------------------------------------------------
151  */
152 void
153 Buf_UngetByte(Buffer bp, Byte byte)
154 {
155
156         if (bp->outPtr != bp->buffer) {
157                 bp->outPtr--;
158                 *bp->outPtr = byte;
159
160         } else if (bp->outPtr == bp->inPtr) {
161                 *bp->inPtr = byte;
162                 bp->inPtr++;
163                 bp->left--;
164                 *bp->inPtr = 0;
165
166         } else {
167                 /*
168                  * Yech. have to expand the buffer to stuff this thing in.
169                  * We use a different expansion constant because people don't
170                  * usually push back many bytes when they're doing it a byte at
171                  * a time...
172                  */
173                 size_t numBytes = bp->inPtr - bp->outPtr;
174                 Byte *newBuf;
175
176                 newBuf = emalloc(bp->size + BUF_UNGET_INC);
177                 memcpy(newBuf + BUF_UNGET_INC, bp->outPtr, numBytes + 1);
178                 bp->outPtr = newBuf + BUF_UNGET_INC;
179                 bp->inPtr = bp->outPtr + numBytes;
180                 free(bp->buffer);
181                 bp->buffer = newBuf;
182                 bp->size += BUF_UNGET_INC;
183                 bp->left = bp->size - (bp->inPtr - bp->buffer);
184                 bp->outPtr -= 1;
185                 *bp->outPtr = byte;
186         }
187 }
188
189 /*-
190  *-----------------------------------------------------------------------
191  * Buf_UngetBytes --
192  *      Push back a series of bytes at the beginning of the buffer.
193  *
194  * Results:
195  *      None.
196  *
197  * Side Effects:
198  *      outPtr is decremented and the bytes copied into the buffer.
199  *
200  *-----------------------------------------------------------------------
201  */
202 void
203 Buf_UngetBytes(Buffer bp, size_t numBytes, Byte *bytesPtr)
204 {
205
206         if ((size_t)(bp->outPtr - bp->buffer) >= numBytes) {
207                 bp->outPtr -= numBytes;
208                 memcpy(bp->outPtr, bytesPtr, numBytes);
209         } else if (bp->outPtr == bp->inPtr) {
210                 Buf_AddBytes(bp, numBytes, bytesPtr);
211         } else {
212                 size_t curNumBytes = bp->inPtr - bp->outPtr;
213                 Byte *newBuf;
214                 size_t newBytes = max(numBytes, BUF_UNGET_INC);
215
216                 newBuf = emalloc(bp->size + newBytes);
217                 memcpy(newBuf + newBytes, bp->outPtr, curNumBytes + 1);
218                 bp->outPtr = newBuf + newBytes;
219                 bp->inPtr = bp->outPtr + curNumBytes;
220                 free(bp->buffer);
221                 bp->buffer = newBuf;
222                 bp->size += newBytes;
223                 bp->left = bp->size - (bp->inPtr - bp->buffer);
224                 bp->outPtr -= numBytes;
225                 memcpy(bp->outPtr, bytesPtr, numBytes);
226         }
227 }
228
229 /*-
230  *-----------------------------------------------------------------------
231  * Buf_GetByte --
232  *      Return the next byte from the buffer. Actually returns an integer.
233  *
234  * Results:
235  *      Returns BUF_ERROR if there's no byte in the buffer, or the byte
236  *      itself if there is one.
237  *
238  * Side Effects:
239  *      outPtr is incremented and both outPtr and inPtr will be reset if
240  *      the buffer is emptied.
241  *
242  *-----------------------------------------------------------------------
243  */
244 int
245 Buf_GetByte(Buffer bp)
246 {
247         int res;
248
249         if (bp->inPtr == bp->outPtr)
250                 return (BUF_ERROR);
251
252         res = (int)*bp->outPtr;
253         bp->outPtr += 1;
254         if (bp->outPtr == bp->inPtr) {
255                 bp->outPtr = bp->inPtr = bp->buffer;
256                 bp->left = bp->size;
257                 *bp->inPtr = 0;
258         }
259         return (res);
260 }
261
262 /*-
263  *-----------------------------------------------------------------------
264  * Buf_GetBytes --
265  *      Extract a number of bytes from the buffer.
266  *
267  * Results:
268  *      The number of bytes gotten.
269  *
270  * Side Effects:
271  *      The passed array is overwritten.
272  *
273  *-----------------------------------------------------------------------
274  */
275 int
276 Buf_GetBytes(Buffer bp, size_t numBytes, Byte *bytesPtr)
277 {
278
279         if ((size_t)(bp->inPtr - bp->outPtr) < numBytes)
280                 numBytes = bp->inPtr - bp->outPtr;
281
282         memcpy(bytesPtr, bp->outPtr, numBytes);
283         bp->outPtr += numBytes;
284
285         if (bp->outPtr == bp->inPtr) {
286                 bp->outPtr = bp->inPtr = bp->buffer;
287                 bp->left = bp->size;
288                 *bp->inPtr = 0;
289         }
290         return (numBytes);
291 }
292
293 /*-
294  *-----------------------------------------------------------------------
295  * Buf_GetAll --
296  *      Get all the available data at once.
297  *
298  * Results:
299  *      A pointer to the data and the number of bytes available.
300  *
301  * Side Effects:
302  *      None.
303  *
304  *-----------------------------------------------------------------------
305  */
306 Byte *
307 Buf_GetAll(Buffer bp, size_t *numBytesPtr)
308 {
309
310         if (numBytesPtr != NULL)
311                 *numBytesPtr = bp->inPtr - bp->outPtr;
312
313         return (bp->outPtr);
314 }
315
316 /*-
317  *-----------------------------------------------------------------------
318  * Buf_Discard --
319  *      Throw away bytes in a buffer.
320  *
321  * Results:
322  *      None.
323  *
324  * Side Effects:
325  *      The bytes are discarded.
326  *
327  *-----------------------------------------------------------------------
328  */
329 void
330 Buf_Discard(Buffer bp, size_t numBytes)
331 {
332
333         if ((size_t)(bp->inPtr - bp->outPtr) <= numBytes) {
334                 bp->inPtr = bp->outPtr = bp->buffer;
335                 bp->left = bp->size;
336                 *bp->inPtr = 0;
337         } else
338                 bp->outPtr += numBytes;
339 }
340
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 size_t
356 Buf_Size(Buffer buf)
357 {
358
359         return (buf->inPtr - buf->outPtr);
360 }
361
362 /*-
363  *-----------------------------------------------------------------------
364  * Buf_Init --
365  *      Initialize a buffer. If no initial size is given, a reasonable
366  *      default is used.
367  *
368  * Results:
369  *      A buffer to be given to other functions in this library.
370  *
371  * Side Effects:
372  *      The buffer is created, the space allocated and pointers
373  *      initialized.
374  *
375  *-----------------------------------------------------------------------
376  */
377 Buffer
378 Buf_Init(size_t size)
379 {
380         Buffer bp;              /* New Buffer */
381
382         bp = emalloc(sizeof(*bp));
383
384         if (size <= 0)
385                 size = BUF_DEF_SIZE;
386
387         bp->left = bp->size = size;
388         bp->buffer = emalloc(size);
389         bp->inPtr = bp->outPtr = bp->buffer;
390         *bp->inPtr = 0;
391
392         return (bp);
393 }
394
395 /*-
396  *-----------------------------------------------------------------------
397  * Buf_Destroy --
398  *      Destroy a buffer, and optionally free its data, too.
399  *
400  * Results:
401  *      None.
402  *
403  * Side Effects:
404  *      The buffer is freed.
405  *
406  *-----------------------------------------------------------------------
407  */
408 void
409 Buf_Destroy(Buffer buf, Boolean freeData)
410 {
411
412         if (freeData)
413                 free(buf->buffer);
414         free(buf);
415 }
416
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, Byte byte)
433 {
434         if (buf->inPtr == buf->outPtr)
435                 Buf_AddByte(buf, byte);
436         else
437                 *(buf->inPtr - 1) = byte;
438 }