1/*	$NetBSD: emit.c,v 1.2 1995/07/03 21:24:00 cgd 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 * $FreeBSD$
34 */
35
36#ifndef lint
37static char rcsid[] = "$NetBSD: emit.c,v 1.2 1995/07/03 21:24:00 cgd Exp $";
38#endif
39
40#include <stdio.h>
41#include <string.h>
42#include <ctype.h>
43#include <err.h>
44
45#include "lint.h"
46
47/* name and handle of output file */
48static	const	char *loname;
49static	FILE	*lout;
50
51/* output buffer data */
52ob_t	ob;
53
54static	void	outxbuf(void);
55
56
57/*
58 * initialize output
59 */
60void
61outopen(name)
62	const	char *name;
63{
64	loname = name;
65
66	/* Ausgabedatei oeffnen */
67	if ((lout = fopen(name, "w")) == NULL)
68		err(1, "cannot open '%s'", name);
69
70	/* Ausgabepuffer anlegen */
71	ob.o_len = 1024;
72	ob.o_end = (ob.o_buf = ob.o_nxt = xmalloc(ob.o_len)) + ob.o_len;
73}
74
75/*
76 * flush output buffer and close file
77 */
78void
79outclose()
80{
81	outclr();
82	if (fclose(lout) == EOF)
83		err(1, "cannot close '%s'", loname);
84}
85
86/*
87 * resize output buffer
88 */
89static void
90outxbuf()
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 */
104void
105outclr()
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 */
123void
124outchar(c)
125	int	c;
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 */
135void
136outqchar(c)
137	int	c;
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#ifdef __STDC__
169		case '\v':
170#else
171		case '\013':
172#endif
173			outchar('v');
174			break;
175#ifdef __STDC__
176		case '\a':
177#else
178		case '\007':
179#endif
180			outchar('a');
181			break;
182		default:
183			outchar((((u_int)c >> 6) & 07) + '0');
184			outchar((((u_int)c >> 3) & 07) + '0');
185			outchar((c & 07) + '0');
186			break;
187		}
188	}
189}
190
191/*
192 * write a strint to the output buffer
193 * the string must not contain any characters which
194 * should be quoted
195 */
196void
197outstrg(s)
198	const	char *s;
199{
200	while (*s != '\0') {
201		if (ob.o_nxt == ob.o_end)
202			outxbuf();
203		*ob.o_nxt++ = *s++;
204	}
205}
206
207/*
208 * write an integer value to toe output buffer
209 */
210void
211outint(i)
212	int	i;
213{
214	if ((ob.o_end - ob.o_nxt) < 3 * sizeof (int))
215		outxbuf();
216	ob.o_nxt += sprintf(ob.o_nxt, "%d", i);
217}
218
219/*
220 * write the name of a symbol to the output buffer
221 * the name is preceded by its length
222 */
223void
224outname(name)
225	const	char *name;
226{
227	if (name == NULL)
228		errx(1, "internal error: outname() 1");
229	outint((int)strlen(name));
230	outstrg(name);
231}
232
233/*
234 * write the name of the .c source
235 */
236void
237outsrc(name)
238	const	char *name;
239{
240	outclr();
241	outchar('S');
242	outstrg(name);
243}
244