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