Initial import of binutils 2.22 on the new vendor branch
[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.43 2005/09/24 07:37:38 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 "util.h"
55
56 /**
57  * Returns the number of bytes in the buffer.  Doesn't include the
58  * null-terminating byte.
59  *
60  * @return The number of bytes in Buffer object.
61  */
62 inline size_t
63 Buf_Size(const Buffer *buf)
64 {
65         return (buf->end - buf->buf);
66 }
67
68 /**
69  * Returns a reference to the data contained in the buffer.
70  *
71  * @note Adding data to the Buffer object may invalidate the reference.
72  */
73 inline char *
74 Buf_Data(const Buffer *bp)
75 {
76         return (bp->buf);
77 }
78
79 /**
80  * Expand the buffer to hold the number of additional bytes, plus
81  * space to store a terminating NULL byte.
82  */
83 static inline void
84 BufExpand(Buffer *bp, size_t nb)
85 {
86         size_t  len = Buf_Size(bp);
87         if (bp->size < len + nb + 1) {
88                 int size = bp->size + MAX(nb + 1, BUF_ADD_INC);
89
90                 bp->buf         = erealloc(bp->buf, size);
91                 bp->size        = size;
92                 bp->end         = bp->buf + len;
93         }
94 }
95
96 /**
97  * Add a single byte to the buffer.
98  */
99 inline void
100 Buf_AddByte(Buffer *bp, char byte)
101 {
102         BufExpand(bp, 1);
103
104         *bp->end = byte;
105         bp->end++;
106         *bp->end = '\0';
107 }
108
109 /**
110  * Add bytes to the buffer.
111  */
112 void
113 Buf_AddBytes(Buffer *bp, size_t len, const char bytes[])
114 {
115         BufExpand(bp, len);
116
117         memcpy(bp->end, bytes, len);
118         bp->end += len;
119         *bp->end = '\0';
120 }
121
122 /**
123  * Get the contents of a buffer and destroy the buffer. If the buffer
124  * is NULL, return NULL.
125  *
126  * Returns:
127  *      the pointer to the data.
128  */
129 char *
130 Buf_Peel(Buffer *bp)
131 {
132         char *ret;
133
134         if (bp == NULL)
135                 return (NULL);
136         ret = bp->buf;
137         free(bp);
138         return (ret);
139 }
140
141 /**
142  * Initialize a buffer. If no initial size is given, a reasonable
143  * default is used.
144  *
145  * @return A buffer object to be given to other functions in this library.
146  *
147  * Side Effects:
148  *      Space is allocated for the Buffer object and a internal buffer.
149  */
150 Buffer *
151 Buf_Init(size_t size)
152 {
153         Buffer *bp;     /* New Buffer */
154
155         if (size <= 0)
156                 size = BUF_DEF_SIZE;
157
158         bp = emalloc(sizeof(*bp));
159         bp->size        = size;
160         bp->buf         = emalloc(size);
161         bp->end         = bp->buf;
162         *bp->end        = '\0';
163
164         return (bp);
165 }
166
167 /**
168  * Destroy a buffer, and optionally free its data, too.
169  *
170  * Side Effects:
171  *      Space for the Buffer object and possibly the internal buffer
172  *      is de-allocated.
173  */
174 void
175 Buf_Destroy(Buffer *buf, bool freeData)
176 {
177         if (freeData)
178                 free(buf->buf);
179         free(buf);
180 }
181
182 /**
183  * Replace the last byte in a buffer.  If the buffer was empty
184  * intially, then a new byte will be added.
185  */
186 void
187 Buf_ReplaceLastByte(Buffer *bp, char byte)
188 {
189         if (bp->end == bp->buf) {
190                 Buf_AddByte(bp, byte);
191         } else {
192                 *(bp->end - 1) = byte;
193         }
194 }
195
196 /**
197  * Append characters in str to Buffer object
198  */
199 void
200 Buf_Append(Buffer *bp, const char str[])
201 {
202         Buf_AddBytes(bp, strlen(str), str);
203 }
204
205 /**
206  * Append characters in buf to Buffer object
207  */
208 void
209 Buf_AppendBuf(Buffer *bp, const Buffer *buf)
210 {
211         Buf_AddBytes(bp, Buf_Size(buf), buf->buf);
212 }
213
214 /**
215  * Append characters between str and end to Buffer object.
216  */
217 void
218 Buf_AppendRange(Buffer *bp, const char str[], const char *end)
219 {
220         Buf_AddBytes(bp, end - str, str);
221 }
222
223 /**
224  * Convert newlines in buffer to spaces.  The trailing newline is
225  * removed.
226  */
227 void
228 Buf_StripNewlines(Buffer *bp)
229 {
230         char *ptr = bp->end;
231
232         /*
233          * If there is anything in the buffer, remove the last
234          * newline character.
235          */
236         if (ptr != bp->buf) {
237                 if (*(ptr - 1) == '\n') {
238                         /* shorten buffer */
239                         *(ptr - 1) = '\0';
240                         --bp->end;
241                 }
242                 --ptr;
243         }
244
245         /* Convert newline characters to a space characters.  */
246         while (ptr != bp->buf) {
247                 if (*ptr == '\n') {
248                         *ptr = ' ';
249                 }
250                 --ptr;
251         }
252 }
253
254 /**
255  * Clear the contents of the buffer.
256  */
257 void
258 Buf_Clear(Buffer *bp)
259 {
260         bp->end = bp->buf;
261         *bp->end = '\0';
262 }
263