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