1 /* $NetBSD: buf.c,v 1.2 2016/01/09 17:38:57 christos Exp $ */ 2 3 /* flex - tool to generate fast lexical analyzers */ 4 5 /* Copyright (c) 1990 The Regents of the University of California. */ 6 /* All rights reserved. */ 7 8 /* This code is derived from software contributed to Berkeley by */ 9 /* Vern Paxson. */ 10 11 /* The United States Government has rights in this work pursuant */ 12 /* to contract no. DE-AC03-76SF00098 between the United States */ 13 /* Department of Energy and the University of California. */ 14 15 /* This file is part of flex. */ 16 17 /* Redistribution and use in source and binary forms, with or without */ 18 /* modification, are permitted provided that the following conditions */ 19 /* are met: */ 20 21 /* 1. Redistributions of source code must retain the above copyright */ 22 /* notice, this list of conditions and the following disclaimer. */ 23 /* 2. Redistributions in binary form must reproduce the above copyright */ 24 /* notice, this list of conditions and the following disclaimer in the */ 25 /* documentation and/or other materials provided with the distribution. */ 26 27 /* Neither the name of the University nor the names of its contributors */ 28 /* may be used to endorse or promote products derived from this software */ 29 /* without specific prior written permission. */ 30 31 /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 32 /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 33 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 34 /* PURPOSE. */ 35 #include "flexdef.h" 36 __RCSID("$NetBSD: buf.c,v 1.2 2016/01/09 17:38:57 christos Exp $"); 37 38 39 /* Take note: The buffer object is sometimes used as a String buffer (one 40 * continuous string), and sometimes used as a list of strings, usually line by 41 * line. 42 * 43 * The type is specified in buf_init by the elt_size. If the elt_size is 44 * sizeof(char), then the buffer should be treated as string buffer. If the 45 * elt_size is sizeof(char*), then the buffer should be treated as a list of 46 * strings. 47 * 48 * Certain functions are only appropriate for one type or the other. 49 */ 50 51 /* global buffers. */ 52 struct Buf userdef_buf; /**< for user #definitions triggered by cmd-line. */ 53 struct Buf defs_buf; /**< for #define's autogenerated. List of strings. */ 54 struct Buf yydmap_buf; /**< string buffer to hold yydmap elements */ 55 struct Buf m4defs_buf; /**< m4 definitions. List of strings. */ 56 struct Buf top_buf; /**< contains %top code. String buffer. */ 57 58 struct Buf *buf_print_strings(struct Buf * buf, FILE* out) 59 { 60 int i; 61 62 if(!buf || !out) 63 return buf; 64 65 for (i=0; i < buf->nelts; i++){ 66 const char * s = ((char**)buf->elts)[i]; 67 if(s) 68 fprintf(out, "%s", s); 69 } 70 return buf; 71 } 72 73 /* Append a "%s" formatted string to a string buffer */ 74 struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s) 75 { 76 char *t; 77 size_t tsz; 78 79 t = flex_alloc (tsz = strlen (fmt) + strlen (s) + 1); 80 if (!t) 81 flexfatal (_("Allocation of buffer to print string failed")); 82 snprintf (t, tsz, fmt, s); 83 buf = buf_strappend (buf, t); 84 flex_free (t); 85 return buf; 86 } 87 88 /** Append a line directive to the string buffer. 89 * @param buf A string buffer. 90 * @param filename file name 91 * @param lineno line number 92 * @return buf 93 */ 94 struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno) 95 { 96 char *dst, *t; 97 const char *src; 98 99 t = flex_alloc (strlen ("#line \"\"\n") + /* constant parts */ 100 2 * strlen (filename) + /* filename with possibly all backslashes escaped */ 101 (int) (1 + log10 (abs (lineno))) + /* line number */ 102 1); /* NUL */ 103 if (!t) 104 flexfatal (_("Allocation of buffer for line directive failed")); 105 for (dst = t + sprintf (t, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++) 106 if (*src == '\\') /* escape backslashes */ 107 *dst++ = '\\'; 108 *dst++ = '"'; 109 *dst++ = '\n'; 110 *dst = '\0'; 111 buf = buf_strappend (buf, t); 112 flex_free (t); 113 return buf; 114 } 115 116 117 /** Append the contents of @a src to @a dest. 118 * @param @a dest the destination buffer 119 * @param @a dest the source buffer 120 * @return @a dest 121 */ 122 struct Buf *buf_concat(struct Buf* dest, const struct Buf* src) 123 { 124 buf_append(dest, src->elts, src->nelts); 125 return dest; 126 } 127 128 129 /* Appends n characters in str to buf. */ 130 struct Buf *buf_strnappend (buf, str, n) 131 struct Buf *buf; 132 const char *str; 133 int n; 134 { 135 buf_append (buf, str, n + 1); 136 137 /* "undo" the '\0' character that buf_append() already copied. */ 138 buf->nelts--; 139 140 return buf; 141 } 142 143 /* Appends characters in str to buf. */ 144 struct Buf *buf_strappend (buf, str) 145 struct Buf *buf; 146 const char *str; 147 { 148 return buf_strnappend (buf, str, strlen (str)); 149 } 150 151 /* appends "#define str def\n" */ 152 struct Buf *buf_strdefine (buf, str, def) 153 struct Buf *buf; 154 const char *str; 155 const char *def; 156 { 157 buf_strappend (buf, "#define "); 158 buf_strappend (buf, " "); 159 buf_strappend (buf, str); 160 buf_strappend (buf, " "); 161 buf_strappend (buf, def); 162 buf_strappend (buf, "\n"); 163 return buf; 164 } 165 166 /** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer. 167 * @param buf A buffer as a list of strings. 168 * @param def The m4 symbol to define. 169 * @param val The definition; may be NULL. 170 * @return buf 171 */ 172 struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val) 173 { 174 const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 175 char * str; 176 size_t strsz; 177 178 val = val?val:""; 179 str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + strlen(val) + 2); 180 if (!str) 181 flexfatal (_("Allocation of buffer for m4 def failed")); 182 183 snprintf(str, strsz, fmt, def, val); 184 buf_append(buf, &str, 1); 185 return buf; 186 } 187 188 /** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer. 189 * @param buf A buffer as a list of strings. 190 * @param def The m4 symbol to undefine. 191 * @return buf 192 */ 193 struct Buf *buf_m4_undefine (struct Buf *buf, const char* def) 194 { 195 const char * fmt = "m4_undefine( [[%s]])m4_dnl\n"; 196 char * str; 197 size_t strsz; 198 199 str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2); 200 if (!str) 201 flexfatal (_("Allocation of buffer for m4 undef failed")); 202 203 snprintf(str, strsz, fmt, def); 204 buf_append(buf, &str, 1); 205 return buf; 206 } 207 208 /* create buf with 0 elements, each of size elem_size. */ 209 void buf_init (buf, elem_size) 210 struct Buf *buf; 211 size_t elem_size; 212 { 213 buf->elts = (void *) 0; 214 buf->nelts = 0; 215 buf->elt_size = elem_size; 216 buf->nmax = 0; 217 } 218 219 /* frees memory */ 220 void buf_destroy (buf) 221 struct Buf *buf; 222 { 223 if (buf && buf->elts) 224 flex_free (buf->elts); 225 buf->elts = (void *) 0; 226 } 227 228 229 /* appends ptr[] to buf, grow if necessary. 230 * n_elem is number of elements in ptr[], NOT bytes. 231 * returns buf. 232 * We grow by mod(512) boundaries. 233 */ 234 235 struct Buf *buf_append (buf, ptr, n_elem) 236 struct Buf *buf; 237 const void *ptr; 238 int n_elem; 239 { 240 int n_alloc = 0; 241 242 if (!ptr || n_elem == 0) 243 return buf; 244 245 /* May need to alloc more. */ 246 if (n_elem + buf->nelts > buf->nmax) { 247 248 /* exact amount needed... */ 249 n_alloc = (n_elem + buf->nelts) * buf->elt_size; 250 251 /* ...plus some extra */ 252 if (((n_alloc * buf->elt_size) % 512) != 0 253 && buf->elt_size < 512) 254 n_alloc += 255 (512 - 256 ((n_alloc * buf->elt_size) % 512)) / 257 buf->elt_size; 258 259 if (!buf->elts) 260 buf->elts = 261 allocate_array (n_alloc, buf->elt_size); 262 else 263 buf->elts = 264 reallocate_array (buf->elts, n_alloc, 265 buf->elt_size); 266 267 buf->nmax = n_alloc; 268 } 269 270 memcpy ((char *) buf->elts + buf->nelts * buf->elt_size, ptr, 271 n_elem * buf->elt_size); 272 buf->nelts += n_elem; 273 274 return buf; 275 } 276 277 /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */ 278