Annotation of src/usr.bin/lex/buf.c, Revision 1.1
1.1 ! tedu 1: /* $OpenBSD$ */
! 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: }
! 276:
! 277: /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */