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