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