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