Home | History | Annotate | Line # | Download | only in src
      1 /*	$NetBSD: buf.c,v 1.3 2017/01/02 17:45:27 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 #include "flexdef.h"
     36 __RCSID("$NetBSD: buf.c,v 1.3 2017/01/02 17:45:27 christos Exp $");
     37 
     38 
     40 /* Take note: The buffer object is sometimes used as a String buffer (one
     41  * continuous string), and sometimes used as a list of strings, usually line by
     42  * line.
     43  *
     44  * The type is specified in buf_init by the elt_size. If the elt_size is
     45  * sizeof(char), then the buffer should be treated as string buffer. If the
     46  * elt_size is sizeof(char*), then the buffer should be treated as a list of
     47  * strings.
     48  *
     49  * Certain functions are only appropriate for one type or the other.
     50  */
     51 
     52 /* global buffers. */
     53 struct Buf userdef_buf;		/**< for user #definitions triggered by cmd-line. */
     54 struct Buf defs_buf;		/**< for #define's autogenerated. List of strings. */
     55 struct Buf yydmap_buf;		/**< string buffer to hold yydmap elements */
     56 struct Buf m4defs_buf;          /**< m4 definitions. List of strings. */
     57 struct Buf top_buf;             /**< contains %top code. String buffer. */
     58 
     59 struct Buf *buf_print_strings(struct Buf * buf, FILE* out)
     60 {
     61     int i;
     62 
     63     if(!buf || !out)
     64         return buf;
     65 
     66     for (i=0; i < buf->nelts; i++){
     67         const char * s = ((char**)buf->elts)[i];
     68         if(s)
     69             fprintf(out, "%s", s);
     70     }
     71     return buf;
     72 }
     73 
     74 /* Append a "%s" formatted string to a string buffer */
     75 struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s)
     76 {
     77 	char   *t;
     78         size_t tsz;
     79 
     80 	tsz = strlen(fmt) + strlen(s) + 1;
     81 	t = malloc(tsz);
     82 	if (!t)
     83 	    flexfatal (_("Allocation of buffer to print string failed"));
     84 	snprintf (t, tsz, fmt, s);
     85 	buf = buf_strappend (buf, t);
     86 	free(t);
     87 	return buf;
     88 }
     89 
     90 /** Append a line directive to the string buffer.
     91  * @param buf A string buffer.
     92  * @param filename file name
     93  * @param lineno line number
     94  * @return buf
     95  */
     96 struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno)
     97 {
     98     char *dst, *t;
     99     const char *src;
    100     size_t tsz;
    101 
    102     if (gen_line_dirs)
    103 	return buf;
    104 
    105     tsz = strlen("#line \"\"\n")                +   /* constant parts */
    106                2 * strlen (filename)            +   /* filename with possibly all backslashes escaped */
    107                (size_t) (1 + ceil (log10 (abs (lineno)))) +   /* line number */
    108                1;                                   /* NUL */
    109     t = malloc(tsz);
    110     if (!t)
    111       flexfatal (_("Allocation of buffer for line directive failed"));
    112     for (dst = t + snprintf (t, tsz, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++)
    113       if (*src == '\\')   /* escape backslashes */
    114         *dst++ = '\\';
    115     *dst++ = '"';
    116     *dst++ = '\n';
    117     *dst   = '\0';
    118     buf = buf_strappend (buf, t);
    119     free(t);
    120     return buf;
    121 }
    122 
    123 
    124 /** Append the contents of @a src to @a dest.
    125  * @param @a dest the destination buffer
    126  * @param @a dest the source buffer
    127  * @return @a dest
    128  */
    129 struct Buf *buf_concat(struct Buf* dest, const struct Buf* src)
    130 {
    131     buf_append(dest, src->elts, src->nelts);
    132     return dest;
    133 }
    134 
    135 
    136 /* Appends n characters in str to buf. */
    137 struct Buf *buf_strnappend (struct Buf *buf, const char *str, int n)
    138 {
    139 	buf_append (buf, str, n + 1);
    140 
    141 	/* "undo" the '\0' character that buf_append() already copied. */
    142 	buf->nelts--;
    143 
    144 	return buf;
    145 }
    146 
    147 /* Appends characters in str to buf. */
    148 struct Buf *buf_strappend (struct Buf *buf, const char *str)
    149 {
    150 	return buf_strnappend (buf, str, (int) strlen (str));
    151 }
    152 
    153 /* appends "#define str def\n" */
    154 struct Buf *buf_strdefine (struct Buf *buf, const char *str, const char *def)
    155 {
    156 	buf_strappend (buf, "#define ");
    157 	buf_strappend (buf, " ");
    158 	buf_strappend (buf, str);
    159 	buf_strappend (buf, " ");
    160 	buf_strappend (buf, def);
    161 	buf_strappend (buf, "\n");
    162 	return buf;
    163 }
    164 
    165 /** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer.
    166  * @param buf A buffer as a list of strings.
    167  * @param def The m4 symbol to define.
    168  * @param val The definition; may be NULL.
    169  * @return buf
    170  */
    171 struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val)
    172 {
    173     const char * fmt = "m4_define( [[%s]], [[[[%s]]]])m4_dnl\n";
    174     char * str;
    175     size_t strsz;
    176 
    177     val = val?val:"";
    178     strsz = strlen(fmt) + strlen(def) + strlen(val) + 2;
    179     str = malloc(strsz);
    180     if (!str)
    181         flexfatal (_("Allocation of buffer for m4 def failed"));
    182 
    183     snprintf(str, strsz, fmt, def, val);
    184     buf_append(buf, &str, 1);
    185     return buf;
    186 }
    187 
    188 /** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer.
    189  * @param buf A buffer as a list of strings.
    190  * @param def The m4 symbol to undefine.
    191  * @return buf
    192  */
    193 struct Buf *buf_m4_undefine (struct Buf *buf, const char* def)
    194 {
    195     const char * fmt = "m4_undefine( [[%s]])m4_dnl\n";
    196     char * str;
    197     size_t strsz;
    198 
    199     strsz = strlen(fmt) + strlen(def) + 2;
    200     str = malloc(strsz);
    201     if (!str)
    202         flexfatal (_("Allocation of buffer for m4 undef failed"));
    203 
    204     snprintf(str, strsz, fmt, def);
    205     buf_append(buf, &str, 1);
    206     return buf;
    207 }
    208 
    209 /* create buf with 0 elements, each of size elem_size. */
    210 void buf_init (struct Buf *buf, size_t elem_size)
    211 {
    212 	buf->elts = NULL;
    213 	buf->nelts = 0;
    214 	buf->elt_size = elem_size;
    215 	buf->nmax = 0;
    216 }
    217 
    218 /* frees memory */
    219 void buf_destroy (struct Buf *buf)
    220 {
    221 	if (buf) {
    222 		free(buf->elts);
    223 		buf->elts = NULL;
    224 	}
    225 }
    226 
    227 
    228 /* appends ptr[] to buf, grow if necessary.
    229  * n_elem is number of elements in ptr[], NOT bytes.
    230  * returns buf.
    231  * We grow by mod(512) boundaries.
    232  */
    233 
    234 struct Buf *buf_append (struct Buf *buf, const void *ptr, 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 count needed... */
    245 		n_alloc = n_elem + buf->nelts;
    246 
    247 		/* ...plus some extra */
    248 		if ((((size_t) n_alloc * buf->elt_size) % 512) != 0
    249 		    && buf->elt_size < 512)
    250 			n_alloc += (int)
    251 				((512 -
    252 				 (((size_t) n_alloc * buf->elt_size) % 512)) /
    253 				buf->elt_size);
    254 
    255 		if (!buf->elts)
    256 			buf->elts =
    257 				allocate_array ((int) n_alloc, buf->elt_size);
    258 		else
    259 			buf->elts =
    260 				reallocate_array (buf->elts, (int) n_alloc,
    261 						  buf->elt_size);
    262 
    263 		buf->nmax = n_alloc;
    264 	}
    265 
    266 	memcpy ((char *) buf->elts + (size_t) buf->nelts * buf->elt_size, ptr,
    267 		(size_t) 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