1 /* $NetBSD: buf.c,v 1.2 2013/04/06 14:27:52 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 36 #include "flexdef.h" 37 38 /* Take note: The buffer object is sometimes used as a String buffer (one 39 * continuous string), and sometimes used as a list of strings, usually line by 40 * line. 41 * 42 * The type is specified in buf_init by the elt_size. If the elt_size is 43 * sizeof(char), then the buffer should be treated as string buffer. If the 44 * elt_size is sizeof(char*), then the buffer should be treated as a list of 45 * strings. 46 * 47 * Certain functions are only appropriate for one type or the other. 48 */ 49 50 /* global buffers. */ 51 struct Buf userdef_buf; /**< for user #definitions triggered by cmd-line. */ 52 struct Buf defs_buf; /**< for #define's autogenerated. List of strings. */ 53 struct Buf yydmap_buf; /**< string buffer to hold yydmap elements */ 54 struct Buf m4defs_buf; /**< m4 definitions. List of strings. */ 55 struct Buf top_buf; /**< contains %top code. String buffer. */ 56 57 struct Buf *buf_print_strings(struct Buf * buf, FILE* out) 58 { 59 int i; 60 61 if(!buf || !out) 62 return buf; 63 64 for (i=0; i < buf->nelts; i++){ 65 const char * s = ((char**)buf->elts)[i]; 66 if(s) 67 fprintf(out, "%s", s); 68 } 69 return buf; 70 } 71 72 /* Append a "%s" formatted string to a string buffer */ 73 struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s) 74 { 75 char *t; 76 size_t tsz; 77 78 t = flex_alloc (tsz = strlen (fmt) + strlen (s) + 1); 79 if (!t) 80 flexfatal (_("Allocation of buffer to print string failed")); 81 snprintf (t, tsz, fmt, s); 82 buf = buf_strappend (buf, t); 83 flex_free (t); 84 return buf; 85 } 86 87 /** Append a line directive to the string buffer. 88 * @param buf A string buffer. 89 * @param filename file name 90 * @param lineno line number 91 * @return buf 92 */ 93 struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno) 94 { 95 char *dst, *t; 96 const char *src; 97 98 t = flex_alloc (strlen ("#line \"\"\n") + /* constant parts */ 99 2 * strlen (filename) + /* filename with possibly all backslashes escaped */ 100 (int) (1 + log10 (abs (lineno))) + /* line number */ 101 1); /* NUL */ 102 if (!t) 103 flexfatal (_("Allocation of buffer for line directive failed")); 104 for (dst = t + sprintf (t, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++) 105 if (*src == '\\') /* escape backslashes */ 106 *dst++ = '\\'; 107 *dst++ = '"'; 108 *dst++ = '\n'; 109 *dst = '\0'; 110 buf = buf_strappend (buf, t); 111 flex_free (t); 112 return buf; 113 } 114 115 116 /** Append the contents of @a src to @a dest. 117 * @param @a dest the destination buffer 118 * @param @a dest the source buffer 119 * @return @a dest 120 */ 121 struct Buf *buf_concat(struct Buf* dest, const struct Buf* src) 122 { 123 buf_append(dest, src->elts, src->nelts); 124 return dest; 125 } 126 127 128 /* Appends n characters in str to buf. */ 129 struct Buf *buf_strnappend (buf, str, n) 130 struct Buf *buf; 131 const char *str; 132 int n; 133 { 134 buf_append (buf, str, n + 1); 135 136 /* "undo" the '\0' character that buf_append() already copied. */ 137 buf->nelts--; 138 139 return buf; 140 } 141 142 /* Appends characters in str to buf. */ 143 struct Buf *buf_strappend (buf, str) 144 struct Buf *buf; 145 const char *str; 146 { 147 return buf_strnappend (buf, str, strlen (str)); 148 } 149 150 /* appends "#define str def\n" */ 151 struct Buf *buf_strdefine (buf, str, def) 152 struct Buf *buf; 153 const char *str; 154 const char *def; 155 { 156 buf_strappend (buf, "#define "); 157 buf_strappend (buf, " "); 158 buf_strappend (buf, str); 159 buf_strappend (buf, " "); 160 buf_strappend (buf, def); 161 buf_strappend (buf, "\n"); 162 return buf; 163 } 164 165 /** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer. 166 * @param buf A buffer as a list of strings. 167 * @param def The m4 symbol to define. 168 * @param val The definition; may be NULL. 169 * @return buf 170 */ 171 struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val) 172 { 173 const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 174 char * str; 175 size_t strsz; 176 177 val = val?val:""; 178 str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + strlen(val) + 2); 179 if (!str) 180 flexfatal (_("Allocation of buffer for m4 def failed")); 181 182 snprintf(str, strsz, fmt, def, val); 183 buf_append(buf, &str, 1); 184 return buf; 185 } 186 187 /** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer. 188 * @param buf A buffer as a list of strings. 189 * @param def The m4 symbol to undefine. 190 * @return buf 191 */ 192 struct Buf *buf_m4_undefine (struct Buf *buf, const char* def) 193 { 194 const char * fmt = "m4_undefine( [[%s]])m4_dnl\n"; 195 char * str; 196 size_t strsz; 197 198 str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2); 199 if (!str) 200 flexfatal (_("Allocation of buffer for m4 undef failed")); 201 202 snprintf(str, strsz, fmt, def); 203 buf_append(buf, &str, 1); 204 return buf; 205 } 206 207 /* create buf with 0 elements, each of size elem_size. */ 208 void buf_init (buf, elem_size) 209 struct Buf *buf; 210 size_t elem_size; 211 { 212 buf->elts = (void *) 0; 213 buf->nelts = 0; 214 buf->elt_size = elem_size; 215 buf->nmax = 0; 216 } 217 218 /* frees memory */ 219 void buf_destroy (buf) 220 struct Buf *buf; 221 { 222 if (buf && buf->elts) 223 flex_free (buf->elts); 224 buf->elts = (void *) 0; 225 } 226 227 228 /* appends ptr[] to buf, grow if necessary. 229 * n_elem is number of elements in ptr[], NOT bytes. 230 * returns buf. 231 * We grow by mod(512) boundaries. 232 */ 233 234 struct Buf *buf_append (buf, ptr, n_elem) 235 struct Buf *buf; 236 const void *ptr; 237 int n_elem; 238 { 239 int n_alloc = 0; 240 241 if (!ptr || n_elem == 0) 242 return buf; 243 244 /* May need to alloc more. */ 245 if (n_elem + buf->nelts > buf->nmax) { 246 247 /* exact amount needed... */ 248 n_alloc = (n_elem + buf->nelts) * buf->elt_size; 249 250 /* ...plus some extra */ 251 if (((n_alloc * buf->elt_size) % 512) != 0 252 && buf->elt_size < 512) 253 n_alloc += 254 (512 - 255 ((n_alloc * buf->elt_size) % 512)) / 256 buf->elt_size; 257 258 if (!buf->elts) 259 buf->elts = 260 allocate_array (n_alloc, buf->elt_size); 261 else 262 buf->elts = 263 reallocate_array (buf->elts, n_alloc, 264 buf->elt_size); 265 266 buf->nmax = n_alloc; 267 } 268 269 memcpy ((char *) buf->elts + buf->nelts * buf->elt_size, ptr, 270 n_elem * buf->elt_size); 271 buf->nelts += n_elem; 272 273 return buf; 274 } 275 276 /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */ 277