Make GCC 3.4 the default compiler.
[dragonfly.git] / usr.bin / make / buf.c
1 /*-
2  * Copyright (c) 2005 Max Okumoto
3  * Copyright (c) 1988, 1989, 1990, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  * Copyright (c) 1988, 1989 by Adam de Boor
6  * Copyright (c) 1989 by Berkeley Softworks
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Adam de Boor.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *      This product includes software developed by the University of
23  *      California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * @(#)buf.c    8.1 (Berkeley) 6/6/93
41  * $FreeBSD: src/usr.bin/make/buf.c,v 1.32 2005/02/07 11:27:47 harti Exp $
42  * $DragonFly: src/usr.bin/make/buf.c,v 1.37 2005/04/01 01:15:20 okumoto Exp $
43  */
44
45 /*
46  * buf.c
47  *      Functions for automatically-expanded buffers.
48  */
49
50 #include <string.h>
51 #include <stdlib.h>
52
53 #include "buf.h"
54 #include "sprite.h"
55 #include "util.h"
56
57 /**
58  * Returns the number of bytes in the buffer.  Doesn't include the
59  * null-terminating byte.
60  *
61  * @return The number of bytes in Buffer object.
62  */
63 inline size_t
64 Buf_Size(const Buffer *buf)
65 {
66
67         return (buf->end - buf->buf);
68 }
69
70 /**
71  * Returns a reference to the data contained in the buffer.
72  *  
73  * @note Adding data to the Buffer object may invalidate the reference.
74  */
75 inline char *
76 Buf_Data(const Buffer *bp)
77 {
78
79         return (bp->buf);
80 }
81
82 /**
83  * Expand the buffer to hold the number of additional bytes, plus
84  * space to store a terminating NULL byte.
85  */
86 static inline void
87 BufExpand(Buffer *bp, size_t nb)
88 {
89         size_t  len = Buf_Size(bp);
90         if (bp->size < len + nb + 1) {
91                 int size = bp->size + MAX(nb + 1, BUF_ADD_INC);
92
93                 bp->buf         = erealloc(bp->buf, size);
94                 bp->size        = size;
95                 bp->end         = bp->buf + len;
96         }
97 }
98
99 /**
100  * Add a single byte to the buffer.
101  */
102 inline void
103 Buf_AddByte(Buffer *bp, Byte byte)
104 {
105
106         BufExpand(bp, 1);
107
108         *bp->end = byte;
109         bp->end++;
110         *bp->end = '\0';
111 }
112
113 /**
114  * Add bytes to the buffer.
115  */
116 void
117 Buf_AddBytes(Buffer *bp, size_t len, const Byte *bytes)
118 {
119         BufExpand(bp, len);
120
121         memcpy(bp->end, bytes, len);
122         bp->end += len;
123         *bp->end = '\0';
124 }
125
126 /**
127  * Get a reference to the internal buffer.
128  *
129  * @param len   Pointer to where we return the number of bytes in
130  *              the internal buffer.
131  *
132  * @return A pointer to the data.
133  */
134 Byte *
135 Buf_GetAll(Buffer *bp, size_t *len)
136 {
137
138         if (len != NULL)
139                 *len = Buf_Size(bp);
140
141         return (bp->buf);
142 }
143
144 /**
145  * Get the contents of a buffer and destroy the buffer. If the buffer
146  * is NULL, return NULL.
147  *
148  * Returns:
149  *      the pointer to the data.
150  */
151 char *
152 Buf_Peel(Buffer *bp)
153 {
154         char *ret;
155
156         if (bp == NULL)
157                 return (NULL);
158         ret = bp->buf;
159         free(bp);
160         return (ret);
161 }
162
163 /**
164  * Initialize a buffer. If no initial size is given, a reasonable
165  * default is used.
166  *
167  * @return A buffer object to be given to other functions in this library.
168  *
169  * Side Effects:
170  *      Space is allocated for the Buffer object and a internal buffer.
171  */
172 Buffer *
173 Buf_Init(size_t size)
174 {
175         Buffer *bp;     /* New Buffer */
176
177         if (size <= 0)
178                 size = BUF_DEF_SIZE;
179
180         bp = emalloc(sizeof(*bp));
181         bp->size        = size;
182         bp->buf         = emalloc(size);
183         bp->end         = bp->buf;
184         *bp->end        = '\0';
185
186         return (bp);
187 }
188
189 /**
190  * Destroy a buffer, and optionally free its data, too.
191  *
192  * Side Effects:
193  *      Space for the Buffer object and possibly the internal buffer
194  *      is de-allocated.
195  */
196 void
197 Buf_Destroy(Buffer *buf, Boolean freeData)
198 {
199
200         if (freeData)
201                 free(buf->buf);
202         free(buf);
203 }
204
205 /**
206  * Replace the last byte in a buffer.  If the buffer was empty
207  * intially, then a new byte will be added.
208  */
209 void
210 Buf_ReplaceLastByte(Buffer *bp, Byte byte)
211 {
212
213         if (bp->end == bp->buf) {
214                 Buf_AddByte(bp, byte);
215         } else {
216                 *(bp->end - 1) = byte;
217         }
218 }
219
220 /**
221  * Append characters in str to Buffer object
222  */
223 void
224 Buf_Append(Buffer *bp, const char str[])
225 {
226
227         Buf_AddBytes(bp, strlen(str), str);
228 }
229
230 /**
231  * Append characters in buf to Buffer object
232  */
233 void
234 Buf_AppendBuf(Buffer *bp, const Buffer *buf)
235 {
236
237         Buf_AddBytes(bp, Buf_Size(buf), buf->buf);
238 }
239
240 /**
241  * Append characters between str and end to Buffer object.
242  */
243 void
244 Buf_AppendRange(Buffer *bp, const char str[], const char *end)
245 {
246
247         Buf_AddBytes(bp, end - str, str);
248 }
249
250 /**
251  * Convert newlines in buffer to spaces.  The trailing newline is
252  * removed.
253  */
254 void
255 Buf_StripNewlines(Buffer *bp)
256 {
257         char *ptr = bp->end;
258
259         /*
260          * If there is anything in the buffer, remove the last
261          * newline character.
262          */
263         if (ptr != bp->buf) {
264                 if (*(ptr - 1) == '\n') {
265                         /* shorten buffer */
266                         *(ptr - 1) = '\0';
267                         --bp->end;
268                 }
269                 --ptr;
270         }
271
272         /* Convert newline characters to a space characters.  */
273         while (ptr != bp->buf) {
274                 if (*ptr == '\n') {
275                         *ptr = ' ';
276                 }
277                 --ptr;
278         }
279 }
280
281 /**
282  * Clear the contents of the buffer.
283  */
284 void
285 Buf_Clear(Buffer *bp)
286 {
287
288         bp->end = bp->buf;
289         *bp->end = '\0';
290 }
291