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