[BACK]Return to buf.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / lex

Annotation of src/usr.bin/lex/buf.c, Revision 1.2

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