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