1228072Sbapt/* flex - tool to generate fast lexical analyzers */ 2228072Sbapt 3228072Sbapt/* Copyright (c) 1990 The Regents of the University of California. */ 4228072Sbapt/* All rights reserved. */ 5228072Sbapt 6228072Sbapt/* This code is derived from software contributed to Berkeley by */ 7228072Sbapt/* Vern Paxson. */ 8228072Sbapt 9228072Sbapt/* The United States Government has rights in this work pursuant */ 10228072Sbapt/* to contract no. DE-AC03-76SF00098 between the United States */ 11228072Sbapt/* Department of Energy and the University of California. */ 12228072Sbapt 13228072Sbapt/* This file is part of flex. */ 14228072Sbapt 15228072Sbapt/* Redistribution and use in source and binary forms, with or without */ 16228072Sbapt/* modification, are permitted provided that the following conditions */ 17228072Sbapt/* are met: */ 18228072Sbapt 19228072Sbapt/* 1. Redistributions of source code must retain the above copyright */ 20228072Sbapt/* notice, this list of conditions and the following disclaimer. */ 21228072Sbapt/* 2. Redistributions in binary form must reproduce the above copyright */ 22228072Sbapt/* notice, this list of conditions and the following disclaimer in the */ 23228072Sbapt/* documentation and/or other materials provided with the distribution. */ 24228072Sbapt 25228072Sbapt/* Neither the name of the University nor the names of its contributors */ 26228072Sbapt/* may be used to endorse or promote products derived from this software */ 27228072Sbapt/* without specific prior written permission. */ 28228072Sbapt 29228072Sbapt/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 30228072Sbapt/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 31228072Sbapt/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 32228072Sbapt/* PURPOSE. */ 33228072Sbapt 34228072Sbapt#include "flexdef.h" 35228072Sbapt 36228072Sbapt/* Take note: The buffer object is sometimes used as a String buffer (one 37228072Sbapt * continuous string), and sometimes used as a list of strings, usually line by 38228072Sbapt * line. 39228072Sbapt * 40228072Sbapt * The type is specified in buf_init by the elt_size. If the elt_size is 41228072Sbapt * sizeof(char), then the buffer should be treated as string buffer. If the 42228072Sbapt * elt_size is sizeof(char*), then the buffer should be treated as a list of 43228072Sbapt * strings. 44228072Sbapt * 45228072Sbapt * Certain functions are only appropriate for one type or the other. 46228072Sbapt */ 47228072Sbapt 48228072Sbapt/* global buffers. */ 49228072Sbaptstruct Buf userdef_buf; /**< for user #definitions triggered by cmd-line. */ 50228072Sbaptstruct Buf defs_buf; /**< for #define's autogenerated. List of strings. */ 51228072Sbaptstruct Buf yydmap_buf; /**< string buffer to hold yydmap elements */ 52228072Sbaptstruct Buf m4defs_buf; /**< m4 definitions. List of strings. */ 53228072Sbaptstruct Buf top_buf; /**< contains %top code. String buffer. */ 54228072Sbapt 55228072Sbaptstruct Buf *buf_print_strings(struct Buf * buf, FILE* out) 56228072Sbapt{ 57228072Sbapt int i; 58228072Sbapt 59228072Sbapt if(!buf || !out) 60228072Sbapt return buf; 61228072Sbapt 62228072Sbapt for (i=0; i < buf->nelts; i++){ 63228072Sbapt const char * s = ((char**)buf->elts)[i]; 64228072Sbapt if(s) 65228072Sbapt fprintf(out, "%s", s); 66228072Sbapt } 67228072Sbapt return buf; 68228072Sbapt} 69228072Sbapt 70228072Sbapt/* Append a "%s" formatted string to a string buffer */ 71228072Sbaptstruct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s) 72228072Sbapt{ 73228072Sbapt char *t; 74228072Sbapt size_t tsz; 75228072Sbapt 76228072Sbapt t = flex_alloc (tsz = strlen (fmt) + strlen (s) + 1); 77250125Sjkim if (!t) 78250125Sjkim flexfatal (_("Allocation of buffer to print string failed")); 79228072Sbapt snprintf (t, tsz, fmt, s); 80228072Sbapt buf = buf_strappend (buf, t); 81228072Sbapt flex_free (t); 82228072Sbapt return buf; 83228072Sbapt} 84228072Sbapt 85228072Sbapt/** Append a line directive to the string buffer. 86228072Sbapt * @param buf A string buffer. 87228072Sbapt * @param filename file name 88228072Sbapt * @param lineno line number 89228072Sbapt * @return buf 90228072Sbapt */ 91228072Sbaptstruct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno) 92228072Sbapt{ 93250875Sjkim char *dst, *t; 94250875Sjkim const char *src; 95250125Sjkim 96250125Sjkim t = flex_alloc (strlen ("#line \"\"\n") + /* constant parts */ 97250125Sjkim 2 * strlen (filename) + /* filename with possibly all backslashes escaped */ 98250876Sjkim NUMCHARLINES + /* line number */ 99250125Sjkim 1); /* NUL */ 100250125Sjkim if (!t) 101250125Sjkim flexfatal (_("Allocation of buffer for line directive failed")); 102250125Sjkim for (dst = t + sprintf (t, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++) 103250125Sjkim if (*src == '\\') /* escape backslashes */ 104250125Sjkim *dst++ = '\\'; 105250125Sjkim *dst++ = '"'; 106250125Sjkim *dst++ = '\n'; 107250125Sjkim *dst = '\0'; 108228072Sbapt buf = buf_strappend (buf, t); 109228072Sbapt flex_free (t); 110228072Sbapt return buf; 111228072Sbapt} 112228072Sbapt 113228072Sbapt 114228072Sbapt/** Append the contents of @a src to @a dest. 115228072Sbapt * @param @a dest the destination buffer 116228072Sbapt * @param @a dest the source buffer 117228072Sbapt * @return @a dest 118228072Sbapt */ 119228072Sbaptstruct Buf *buf_concat(struct Buf* dest, const struct Buf* src) 120228072Sbapt{ 121228072Sbapt buf_append(dest, src->elts, src->nelts); 122228072Sbapt return dest; 123228072Sbapt} 124228072Sbapt 125228072Sbapt 126228072Sbapt/* Appends n characters in str to buf. */ 127228072Sbaptstruct Buf *buf_strnappend (buf, str, n) 128228072Sbapt struct Buf *buf; 129228072Sbapt const char *str; 130228072Sbapt int n; 131228072Sbapt{ 132228072Sbapt buf_append (buf, str, n + 1); 133228072Sbapt 134228072Sbapt /* "undo" the '\0' character that buf_append() already copied. */ 135228072Sbapt buf->nelts--; 136228072Sbapt 137228072Sbapt return buf; 138228072Sbapt} 139228072Sbapt 140228072Sbapt/* Appends characters in str to buf. */ 141228072Sbaptstruct Buf *buf_strappend (buf, str) 142228072Sbapt struct Buf *buf; 143228072Sbapt const char *str; 144228072Sbapt{ 145228072Sbapt return buf_strnappend (buf, str, strlen (str)); 146228072Sbapt} 147228072Sbapt 148228072Sbapt/* appends "#define str def\n" */ 149228072Sbaptstruct Buf *buf_strdefine (buf, str, def) 150228072Sbapt struct Buf *buf; 151228072Sbapt const char *str; 152228072Sbapt const char *def; 153228072Sbapt{ 154228072Sbapt buf_strappend (buf, "#define "); 155228072Sbapt buf_strappend (buf, " "); 156228072Sbapt buf_strappend (buf, str); 157228072Sbapt buf_strappend (buf, " "); 158228072Sbapt buf_strappend (buf, def); 159228072Sbapt buf_strappend (buf, "\n"); 160228072Sbapt return buf; 161228072Sbapt} 162228072Sbapt 163228072Sbapt/** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer. 164228072Sbapt * @param buf A buffer as a list of strings. 165228072Sbapt * @param def The m4 symbol to define. 166228072Sbapt * @param val The definition; may be NULL. 167228072Sbapt * @return buf 168228072Sbapt */ 169228072Sbaptstruct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val) 170228072Sbapt{ 171228072Sbapt const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 172228072Sbapt char * str; 173228072Sbapt size_t strsz; 174228072Sbapt 175228072Sbapt val = val?val:""; 176228072Sbapt str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + strlen(val) + 2); 177250125Sjkim if (!str) 178250125Sjkim flexfatal (_("Allocation of buffer for m4 def failed")); 179228072Sbapt 180228072Sbapt snprintf(str, strsz, fmt, def, val); 181228072Sbapt buf_append(buf, &str, 1); 182228072Sbapt return buf; 183228072Sbapt} 184228072Sbapt 185228072Sbapt/** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer. 186228072Sbapt * @param buf A buffer as a list of strings. 187228072Sbapt * @param def The m4 symbol to undefine. 188228072Sbapt * @return buf 189228072Sbapt */ 190228072Sbaptstruct Buf *buf_m4_undefine (struct Buf *buf, const char* def) 191228072Sbapt{ 192228072Sbapt const char * fmt = "m4_undefine( [[%s]])m4_dnl\n"; 193228072Sbapt char * str; 194228072Sbapt size_t strsz; 195228072Sbapt 196228072Sbapt str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2); 197250125Sjkim if (!str) 198250125Sjkim flexfatal (_("Allocation of buffer for m4 undef failed")); 199228072Sbapt 200228072Sbapt snprintf(str, strsz, fmt, def); 201228072Sbapt buf_append(buf, &str, 1); 202228072Sbapt return buf; 203228072Sbapt} 204228072Sbapt 205228072Sbapt/* create buf with 0 elements, each of size elem_size. */ 206228072Sbaptvoid buf_init (buf, elem_size) 207228072Sbapt struct Buf *buf; 208228072Sbapt size_t elem_size; 209228072Sbapt{ 210228072Sbapt buf->elts = (void *) 0; 211228072Sbapt buf->nelts = 0; 212228072Sbapt buf->elt_size = elem_size; 213228072Sbapt buf->nmax = 0; 214228072Sbapt} 215228072Sbapt 216228072Sbapt/* frees memory */ 217228072Sbaptvoid buf_destroy (buf) 218228072Sbapt struct Buf *buf; 219228072Sbapt{ 220228072Sbapt if (buf && buf->elts) 221228072Sbapt flex_free (buf->elts); 222228072Sbapt buf->elts = (void *) 0; 223228072Sbapt} 224228072Sbapt 225228072Sbapt 226228072Sbapt/* appends ptr[] to buf, grow if necessary. 227228072Sbapt * n_elem is number of elements in ptr[], NOT bytes. 228228072Sbapt * returns buf. 229228072Sbapt * We grow by mod(512) boundaries. 230228072Sbapt */ 231228072Sbapt 232228072Sbaptstruct Buf *buf_append (buf, ptr, n_elem) 233228072Sbapt struct Buf *buf; 234228072Sbapt const void *ptr; 235228072Sbapt int n_elem; 236228072Sbapt{ 237228072Sbapt int n_alloc = 0; 238228072Sbapt 239228072Sbapt if (!ptr || n_elem == 0) 240228072Sbapt return buf; 241228072Sbapt 242228072Sbapt /* May need to alloc more. */ 243228072Sbapt if (n_elem + buf->nelts > buf->nmax) { 244228072Sbapt 245228072Sbapt /* exact amount needed... */ 246228072Sbapt n_alloc = (n_elem + buf->nelts) * buf->elt_size; 247228072Sbapt 248228072Sbapt /* ...plus some extra */ 249228072Sbapt if (((n_alloc * buf->elt_size) % 512) != 0 250228072Sbapt && buf->elt_size < 512) 251228072Sbapt n_alloc += 252228072Sbapt (512 - 253228072Sbapt ((n_alloc * buf->elt_size) % 512)) / 254228072Sbapt buf->elt_size; 255228072Sbapt 256228072Sbapt if (!buf->elts) 257228072Sbapt buf->elts = 258228072Sbapt allocate_array (n_alloc, buf->elt_size); 259228072Sbapt else 260228072Sbapt buf->elts = 261228072Sbapt reallocate_array (buf->elts, n_alloc, 262228072Sbapt buf->elt_size); 263228072Sbapt 264228072Sbapt buf->nmax = n_alloc; 265228072Sbapt } 266228072Sbapt 267228072Sbapt memcpy ((char *) buf->elts + buf->nelts * buf->elt_size, ptr, 268228072Sbapt n_elem * buf->elt_size); 269228072Sbapt buf->nelts += n_elem; 270228072Sbapt 271228072Sbapt return buf; 272228072Sbapt} 273228072Sbapt 274228072Sbapt/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */ 275