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: }