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