1 /* $OpenBSD: buf.c,v 1.27 2015/04/29 00:42:12 millert Exp $ */ 2 /* $NetBSD: buf.c,v 1.9 1996/12/31 17:53:21 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1999 Marc Espie. 6 * 7 * Extensive code changes for the OpenBSD project. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 32 * Copyright (c) 1988, 1989 by Adam de Boor 33 * Copyright (c) 1989 by Berkeley Softworks 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Adam de Boor. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64 /*- 65 * buf.c -- 66 * Functions for automatically expanded buffers. 67 */ 68 69 #include <ctype.h> 70 #include <limits.h> 71 #include <stddef.h> 72 #include <stdint.h> 73 #include <stdlib.h> 74 #include <string.h> 75 #include <stdio.h> 76 #include <stdarg.h> 77 #include "config.h" 78 #include "defines.h" 79 #include "buf.h" 80 #include "stats.h" 81 #include "memory.h" 82 83 #ifdef STATS_BUF 84 #define DO_STAT_BUF(bp, nb) \ 85 STAT_BUFS_EXPANSION++; \ 86 if ((bp)->endPtr - (bp)->buffer == 1) \ 87 STAT_WEIRD_INEFFICIENT++; 88 #else 89 #define DO_STAT_BUF(a, b) 90 #endif 91 92 static void 93 fatal_overflow() 94 { 95 fprintf(stderr, "buffer size overflow\n"); 96 exit(2); 97 } 98 99 /* BufExpand(bp, nb) 100 * Expand buffer bp to hold upto nb additional 101 * chars. Makes sure there's room for an extra '\0' char at 102 * the end of the buffer to terminate the string. */ 103 #define BufExpand(bp,nb) \ 104 do { \ 105 size_t occupied = (bp)->inPtr - (bp)->buffer; \ 106 size_t size = (bp)->endPtr - (bp)->buffer; \ 107 DO_STAT_BUF(bp, nb); \ 108 \ 109 do { \ 110 if (size <= SIZE_MAX/2) { \ 111 size *= 2 ; \ 112 } else { \ 113 fatal_overflow(); \ 114 } \ 115 } while (size - occupied < (nb)+1+BUF_MARGIN); \ 116 (bp)->buffer = (bp)->inPtr = (bp)->endPtr = \ 117 erealloc((bp)->buffer, size); \ 118 (bp)->inPtr += occupied; \ 119 (bp)->endPtr += size; \ 120 } while (0); 121 122 #define BUF_DEF_SIZE 256 /* Default buffer size */ 123 #define BUF_MARGIN 256 /* Make sure we are comfortable */ 124 125 /* the hard case for Buf_AddChar: buffer must be expanded to accommodate 126 * one more char. */ 127 void 128 BufOverflow(Buffer bp) 129 { 130 BufExpand(bp, 1); 131 } 132 133 134 void 135 Buf_AddChars(Buffer bp, size_t numBytes, const char *bytesPtr) 136 { 137 138 if ((size_t)(bp->endPtr - bp->inPtr) < numBytes+1) 139 BufExpand(bp, numBytes); 140 141 memcpy(bp->inPtr, bytesPtr, numBytes); 142 bp->inPtr += numBytes; 143 } 144 145 void 146 Buf_printf(Buffer bp, const char *fmt, ...) 147 { 148 va_list va; 149 int n; 150 va_start(va, fmt); 151 n = vsnprintf(bp->inPtr, bp->endPtr - bp->inPtr, fmt, va); 152 va_end(va); 153 if (n > bp->endPtr - bp->inPtr) { 154 va_list vb; 155 BufExpand(bp, n); 156 va_start(vb, fmt); 157 (void)vsnprintf(bp->inPtr, bp->endPtr - bp->inPtr, fmt, vb); 158 va_end(vb); 159 } 160 bp->inPtr += n; 161 } 162 163 void 164 Buf_Init(Buffer bp, size_t size) 165 { 166 #ifdef STATS_BUF 167 STAT_TOTAL_BUFS++; 168 if (size == 0) 169 STAT_DEFAULT_BUFS++; 170 if (size == 1) 171 STAT_WEIRD_BUFS++; 172 #endif 173 if (size == 0) 174 size = BUF_DEF_SIZE; 175 bp->inPtr = bp->endPtr = bp->buffer = emalloc(size); 176 bp->endPtr += size; 177 } 178