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