xref: /minix3/external/bsd/flex/dist/buf.c (revision cdfb5ab81f82cdcb0f58d139385d626df29f4069)
1 /*	$NetBSD: buf.c,v 1.1.1.1 2009/10/26 00:25:04 christos Exp $	*/
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 	snprintf (t, tsz, fmt, s);
80 	buf = buf_strappend (buf, t);
81 	flex_free (t);
82 	return buf;
83 }
84 
85 /** Append a line directive to the string buffer.
86  * @param buf A string buffer.
87  * @param filename file name
88  * @param lineno line number
89  * @return buf
90  */
91 struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno)
92 {
93     char   *t, *fmt = "#line %d \"%s\"\n";
94     size_t tsz;
95 
96     t = flex_alloc (tsz = strlen (fmt) + strlen (filename) + (int)(1 + log10(lineno>=0?lineno:-lineno)) + 1);
97     snprintf (t, tsz, fmt, lineno, filename);
98     buf = buf_strappend (buf, t);
99     flex_free (t);
100     return buf;
101 }
102 
103 
104 /** Append the contents of @a src to @a dest.
105  * @param @a dest the destination buffer
106  * @param @a dest the source buffer
107  * @return @a dest
108  */
109 struct Buf *buf_concat(struct Buf* dest, const struct Buf* src)
110 {
111     buf_append(dest, src->elts, src->nelts);
112     return dest;
113 }
114 
115 
116 /* Appends n characters in str to buf. */
117 struct Buf *buf_strnappend (buf, str, n)
118      struct Buf *buf;
119      const char *str;
120      int n;
121 {
122 	buf_append (buf, str, n + 1);
123 
124 	/* "undo" the '\0' character that buf_append() already copied. */
125 	buf->nelts--;
126 
127 	return buf;
128 }
129 
130 /* Appends characters in str to buf. */
131 struct Buf *buf_strappend (buf, str)
132      struct Buf *buf;
133      const char *str;
134 {
135 	return buf_strnappend (buf, str, strlen (str));
136 }
137 
138 /* appends "#define str def\n" */
139 struct Buf *buf_strdefine (buf, str, def)
140      struct Buf *buf;
141      const char *str;
142      const char *def;
143 {
144 	buf_strappend (buf, "#define ");
145 	buf_strappend (buf, " ");
146 	buf_strappend (buf, str);
147 	buf_strappend (buf, " ");
148 	buf_strappend (buf, def);
149 	buf_strappend (buf, "\n");
150 	return buf;
151 }
152 
153 /** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer.
154  * @param buf A buffer as a list of strings.
155  * @param def The m4 symbol to define.
156  * @param val The definition; may be NULL.
157  * @return buf
158  */
159 struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val)
160 {
161     const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
162     char * str;
163     size_t strsz;
164 
165     val = val?val:"";
166     str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + strlen(val) + 2);
167 
168     snprintf(str, strsz, fmt, def, val);
169     buf_append(buf, &str, 1);
170     return buf;
171 }
172 
173 /** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer.
174  * @param buf A buffer as a list of strings.
175  * @param def The m4 symbol to undefine.
176  * @return buf
177  */
178 struct Buf *buf_m4_undefine (struct Buf *buf, const char* def)
179 {
180     const char * fmt = "m4_undefine( [[%s]])m4_dnl\n";
181     char * str;
182     size_t strsz;
183 
184     str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2);
185 
186     snprintf(str, strsz, fmt, def);
187     buf_append(buf, &str, 1);
188     return buf;
189 }
190 
191 /* create buf with 0 elements, each of size elem_size. */
192 void buf_init (buf, elem_size)
193      struct Buf *buf;
194      size_t elem_size;
195 {
196 	buf->elts = (void *) 0;
197 	buf->nelts = 0;
198 	buf->elt_size = elem_size;
199 	buf->nmax = 0;
200 }
201 
202 /* frees memory */
203 void buf_destroy (buf)
204      struct Buf *buf;
205 {
206 	if (buf && buf->elts)
207 		flex_free (buf->elts);
208 	buf->elts = (void *) 0;
209 }
210 
211 
212 /* appends ptr[] to buf, grow if necessary.
213  * n_elem is number of elements in ptr[], NOT bytes.
214  * returns buf.
215  * We grow by mod(512) boundaries.
216  */
217 
218 struct Buf *buf_append (buf, ptr, n_elem)
219      struct Buf *buf;
220      const void *ptr;
221      int n_elem;
222 {
223 	int     n_alloc = 0;
224 
225 	if (!ptr || n_elem == 0)
226 		return buf;
227 
228 	/* May need to alloc more. */
229 	if (n_elem + buf->nelts > buf->nmax) {
230 
231 		/* exact amount needed... */
232 		n_alloc = (n_elem + buf->nelts) * buf->elt_size;
233 
234 		/* ...plus some extra */
235 		if (((n_alloc * buf->elt_size) % 512) != 0
236 		    && buf->elt_size < 512)
237 			n_alloc +=
238 				(512 -
239 				 ((n_alloc * buf->elt_size) % 512)) /
240 				buf->elt_size;
241 
242 		if (!buf->elts)
243 			buf->elts =
244 				allocate_array (n_alloc, buf->elt_size);
245 		else
246 			buf->elts =
247 				reallocate_array (buf->elts, n_alloc,
248 						  buf->elt_size);
249 
250 		buf->nmax = n_alloc;
251 	}
252 
253 	memcpy ((char *) buf->elts + buf->nelts * buf->elt_size, ptr,
254 		n_elem * buf->elt_size);
255 	buf->nelts += n_elem;
256 
257 	return buf;
258 }
259 
260 /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */
261