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