emit.c revision 1.1 1 /* $NetBSD: emit.c,v 1.1 2002/01/18 20:39:22 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1994, 1995 Jochen Pohl
5 * All Rights Reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Jochen Pohl for
18 * The NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 #ifndef lint
36 __RCSID("$NetBSD: emit.c,v 1.1 2002/01/18 20:39:22 thorpej Exp $");
37 #endif
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <err.h>
43
44 #include "lint.h"
45
46 /* name and handle of output file */
47 static const char *loname;
48 static FILE *lout;
49
50 /* output buffer data */
51 ob_t ob;
52
53 static void outxbuf(void);
54
55
56 /*
57 * initialize output
58 */
59 void
60 outopen(const char *name)
61 {
62
63 loname = name;
64
65 /* Open output file */
66 if ((lout = fopen(name, "w")) == NULL)
67 err(1, "cannot open '%s'", name);
68
69 /* Create output buffer */
70 ob.o_len = 1024;
71 ob.o_end = (ob.o_buf = ob.o_nxt = xmalloc(ob.o_len)) + ob.o_len;
72 }
73
74 /*
75 * flush output buffer and close file
76 */
77 void
78 outclose(void)
79 {
80
81 outclr();
82 if (fclose(lout) == EOF)
83 err(1, "cannot close '%s'", loname);
84 }
85
86 /*
87 * resize output buffer
88 */
89 static void
90 outxbuf(void)
91 {
92 ptrdiff_t coffs;
93
94 coffs = ob.o_nxt - ob.o_buf;
95 ob.o_len *= 2;
96 ob.o_end = (ob.o_buf = xrealloc(ob.o_buf, ob.o_len)) + ob.o_len;
97 ob.o_nxt = ob.o_buf + coffs;
98 }
99
100 /*
101 * reset output buffer
102 * if it is not empty, it is flushed
103 */
104 void
105 outclr(void)
106 {
107 size_t sz;
108
109 if (ob.o_buf != ob.o_nxt) {
110 outchar('\n');
111 sz = ob.o_nxt - ob.o_buf;
112 if (sz > ob.o_len)
113 errx(1, "internal error: outclr() 1");
114 if (fwrite(ob.o_buf, sz, 1, lout) != 1)
115 err(1, "cannot write to %s", loname);
116 ob.o_nxt = ob.o_buf;
117 }
118 }
119
120 /*
121 * write a character to the output buffer
122 */
123 void
124 outchar(int c)
125 {
126
127 if (ob.o_nxt == ob.o_end)
128 outxbuf();
129 *ob.o_nxt++ = (char)c;
130 }
131
132 /*
133 * write a character to the output buffer, qouted if necessary
134 */
135 void
136 outqchar(int c)
137 {
138
139 if (isprint(c) && c != '\\' && c != '"' && c != '\'') {
140 outchar(c);
141 } else {
142 outchar('\\');
143 switch (c) {
144 case '\\':
145 outchar('\\');
146 break;
147 case '"':
148 outchar('"');
149 break;
150 case '\'':
151 outchar('\'');
152 break;
153 case '\b':
154 outchar('b');
155 break;
156 case '\t':
157 outchar('t');
158 break;
159 case '\n':
160 outchar('n');
161 break;
162 case '\f':
163 outchar('f');
164 break;
165 case '\r':
166 outchar('r');
167 break;
168 case '\v':
169 outchar('v');
170 break;
171 case '\a':
172 outchar('a');
173 break;
174 default:
175 outchar((((u_int)c >> 6) & 07) + '0');
176 outchar((((u_int)c >> 3) & 07) + '0');
177 outchar((c & 07) + '0');
178 break;
179 }
180 }
181 }
182
183 /*
184 * write a strint to the output buffer
185 * the string must not contain any characters which
186 * should be quoted
187 */
188 void
189 outstrg(const char *s)
190 {
191
192 while (*s != '\0') {
193 if (ob.o_nxt == ob.o_end)
194 outxbuf();
195 *ob.o_nxt++ = *s++;
196 }
197 }
198
199 /*
200 * write an integer value to toe output buffer
201 */
202 void
203 outint(int i)
204 {
205
206 if ((ob.o_end - ob.o_nxt) < 3 * sizeof (int))
207 outxbuf();
208 ob.o_nxt += sprintf(ob.o_nxt, "%d", i);
209 }
210
211 /*
212 * write the name of a symbol to the output buffer
213 * the name is preceded by its length
214 */
215 void
216 outname(const char *name)
217 {
218
219 if (name == NULL)
220 errx(1, "internal error: outname() 1");
221 outint((int)strlen(name));
222 outstrg(name);
223 }
224
225 /*
226 * write the name of the .c source
227 */
228 void
229 outsrc(const char *name)
230 {
231
232 outclr();
233 outchar('S');
234 outstrg(name);
235 }
236