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, *t; 94 const char *src; 95 96 t = flex_alloc (strlen ("#line \"\"\n") + /* constant parts */ 97 2 * strlen (filename) + /* filename with possibly all backslashes escaped */ 98 NUMCHARLINES + /* line number */ 99 1); /* NUL */ 100 if (!t) 101 flexfatal (_("Allocation of buffer for line directive failed")); 102 for (dst = t + sprintf (t, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++) 103 if (*src == '\\') /* escape backslashes */ 104 *dst++ = '\\'; 105 *dst++ = '"'; 106 *dst++ = '\n'; 107 *dst = '\0'; 108 buf = buf_strappend (buf, t); 109 flex_free (t); 110 return buf; 111} 112 113 114/** Append the contents of @a src to @a dest. 115 * @param @a dest the destination buffer 116 * @param @a dest the source buffer 117 * @return @a dest 118 */ 119struct Buf *buf_concat(struct Buf* dest, const struct Buf* src) 120{ 121 buf_append(dest, src->elts, src->nelts); 122 return dest; 123} 124 125 126/* Appends n characters in str to buf. */ 127struct Buf *buf_strnappend (buf, str, n) 128 struct Buf *buf; 129 const char *str; 130 int n; 131{ 132 buf_append (buf, str, n + 1); 133 134 /* "undo" the '\0' character that buf_append() already copied. */ 135 buf->nelts--; 136 137 return buf; 138} 139 140/* Appends characters in str to buf. */ 141struct Buf *buf_strappend (buf, str) 142 struct Buf *buf; 143 const char *str; 144{ 145 return buf_strnappend (buf, str, strlen (str)); 146} 147 148/* appends "#define str def\n" */ 149struct Buf *buf_strdefine (buf, str, def) 150 struct Buf *buf; 151 const char *str; 152 const char *def; 153{ 154 buf_strappend (buf, "#define "); 155 buf_strappend (buf, " "); 156 buf_strappend (buf, str); 157 buf_strappend (buf, " "); 158 buf_strappend (buf, def); 159 buf_strappend (buf, "\n"); 160 return buf; 161} 162 163/** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer. 164 * @param buf A buffer as a list of strings. 165 * @param def The m4 symbol to define. 166 * @param val The definition; may be NULL. 167 * @return buf 168 */ 169struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val) 170{ 171 const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 172 char * str; 173 size_t strsz; 174 175 val = val?val:""; 176 str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + strlen(val) + 2); 177 if (!str) 178 flexfatal (_("Allocation of buffer for m4 def failed")); 179 180 snprintf(str, strsz, fmt, def, val); 181 buf_append(buf, &str, 1); 182 return buf; 183} 184 185/** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer. 186 * @param buf A buffer as a list of strings. 187 * @param def The m4 symbol to undefine. 188 * @return buf 189 */ 190struct Buf *buf_m4_undefine (struct Buf *buf, const char* def) 191{ 192 const char * fmt = "m4_undefine( [[%s]])m4_dnl\n"; 193 char * str; 194 size_t strsz; 195 196 str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2); 197 if (!str) 198 flexfatal (_("Allocation of buffer for m4 undef failed")); 199 200 snprintf(str, strsz, fmt, def); 201 buf_append(buf, &str, 1); 202 return buf; 203} 204 205/* create buf with 0 elements, each of size elem_size. */ 206void buf_init (buf, elem_size) 207 struct Buf *buf; 208 size_t elem_size; 209{ 210 buf->elts = (void *) 0; 211 buf->nelts = 0; 212 buf->elt_size = elem_size; 213 buf->nmax = 0; 214} 215 216/* frees memory */ 217void buf_destroy (buf) 218 struct Buf *buf; 219{ 220 if (buf && buf->elts) 221 flex_free (buf->elts); 222 buf->elts = (void *) 0; 223} 224 225 226/* appends ptr[] to buf, grow if necessary. 227 * n_elem is number of elements in ptr[], NOT bytes. 228 * returns buf. 229 * We grow by mod(512) boundaries. 230 */ 231 232struct Buf *buf_append (buf, ptr, n_elem) 233 struct Buf *buf; 234 const void *ptr; 235 int n_elem; 236{ 237 int n_alloc = 0; 238 239 if (!ptr || n_elem == 0) 240 return buf; 241 242 /* May need to alloc more. */ 243 if (n_elem + buf->nelts > buf->nmax) { 244 245 /* exact amount needed... */ 246 n_alloc = (n_elem + buf->nelts) * buf->elt_size; 247 248 /* ...plus some extra */ 249 if (((n_alloc * buf->elt_size) % 512) != 0 250 && buf->elt_size < 512) 251 n_alloc += 252 (512 - 253 ((n_alloc * buf->elt_size) % 512)) / 254 buf->elt_size; 255 256 if (!buf->elts) 257 buf->elts = 258 allocate_array (n_alloc, buf->elt_size); 259 else 260 buf->elts = 261 reallocate_array (buf->elts, n_alloc, 262 buf->elt_size); 263 264 buf->nmax = n_alloc; 265 } 266 267 memcpy ((char *) buf->elts + buf->nelts * buf->elt_size, ptr, 268 n_elem * buf->elt_size); 269 buf->nelts += n_elem; 270 271 return buf; 272} 273 274/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */ 275