112099Sjoerg/*	$NetBSD: emit.c,v 1.2 1995/07/03 21:24:00 cgd Exp $	*/
212099Sjoerg
312099Sjoerg/*
412099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl
512099Sjoerg * All Rights Reserved.
612099Sjoerg *
712099Sjoerg * Redistribution and use in source and binary forms, with or without
812099Sjoerg * modification, are permitted provided that the following conditions
912099Sjoerg * are met:
1012099Sjoerg * 1. Redistributions of source code must retain the above copyright
1112099Sjoerg *    notice, this list of conditions and the following disclaimer.
1212099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1312099Sjoerg *    notice, this list of conditions and the following disclaimer in the
1412099Sjoerg *    documentation and/or other materials provided with the distribution.
1512099Sjoerg * 3. All advertising materials mentioning features or use of this software
1612099Sjoerg *    must display the following acknowledgement:
1712099Sjoerg *      This product includes software developed by Jochen Pohl for
1812099Sjoerg *	The NetBSD Project.
1912099Sjoerg * 4. The name of the author may not be used to endorse or promote products
2012099Sjoerg *    derived from this software without specific prior written permission.
2112099Sjoerg *
2212099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2312099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2412099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2512099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2612099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2712099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2812099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2912099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3012099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3112099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3292922Simp *
3392922Simp * $FreeBSD$
3412099Sjoerg */
3512099Sjoerg
3612099Sjoerg#ifndef lint
3712099Sjoergstatic char rcsid[] = "$NetBSD: emit.c,v 1.2 1995/07/03 21:24:00 cgd Exp $";
3812099Sjoerg#endif
3912099Sjoerg
4012099Sjoerg#include <stdio.h>
4112099Sjoerg#include <string.h>
4212099Sjoerg#include <ctype.h>
4312099Sjoerg#include <err.h>
4412099Sjoerg
4512099Sjoerg#include "lint.h"
4612099Sjoerg
4712099Sjoerg/* name and handle of output file */
4812099Sjoergstatic	const	char *loname;
4912099Sjoergstatic	FILE	*lout;
5012099Sjoerg
5112099Sjoerg/* output buffer data */
5212099Sjoergob_t	ob;
5312099Sjoerg
5492922Simpstatic	void	outxbuf(void);
5512099Sjoerg
5612099Sjoerg
5712099Sjoerg/*
5812099Sjoerg * initialize output
5912099Sjoerg */
6012099Sjoergvoid
6112099Sjoergoutopen(name)
6212099Sjoerg	const	char *name;
6312099Sjoerg{
6412099Sjoerg	loname = name;
6512099Sjoerg
6612099Sjoerg	/* Ausgabedatei oeffnen */
6712099Sjoerg	if ((lout = fopen(name, "w")) == NULL)
6812099Sjoerg		err(1, "cannot open '%s'", name);
6912099Sjoerg
7012099Sjoerg	/* Ausgabepuffer anlegen */
7112099Sjoerg	ob.o_len = 1024;
7212099Sjoerg	ob.o_end = (ob.o_buf = ob.o_nxt = xmalloc(ob.o_len)) + ob.o_len;
7312099Sjoerg}
7412099Sjoerg
7512099Sjoerg/*
7612099Sjoerg * flush output buffer and close file
7712099Sjoerg */
7812099Sjoergvoid
7912099Sjoergoutclose()
8012099Sjoerg{
8112099Sjoerg	outclr();
8212099Sjoerg	if (fclose(lout) == EOF)
8312099Sjoerg		err(1, "cannot close '%s'", loname);
8412099Sjoerg}
8512099Sjoerg
8612099Sjoerg/*
8712099Sjoerg * resize output buffer
8812099Sjoerg */
8912099Sjoergstatic void
9012099Sjoergoutxbuf()
9112099Sjoerg{
9212099Sjoerg	ptrdiff_t coffs;
9312099Sjoerg
9412099Sjoerg	coffs = ob.o_nxt - ob.o_buf;
9512099Sjoerg	ob.o_len *= 2;
9612099Sjoerg	ob.o_end = (ob.o_buf = xrealloc(ob.o_buf, ob.o_len)) + ob.o_len;
9712099Sjoerg	ob.o_nxt = ob.o_buf + coffs;
9812099Sjoerg}
9912099Sjoerg
10012099Sjoerg/*
10112099Sjoerg * reset output buffer
10212099Sjoerg * if it is not empty, it is flushed
10312099Sjoerg */
10412099Sjoergvoid
10512099Sjoergoutclr()
10612099Sjoerg{
10712099Sjoerg	size_t	sz;
10812099Sjoerg
10912099Sjoerg	if (ob.o_buf != ob.o_nxt) {
11012099Sjoerg		outchar('\n');
11112099Sjoerg		sz = ob.o_nxt - ob.o_buf;
11212099Sjoerg		if (sz > ob.o_len)
11312099Sjoerg			errx(1, "internal error: outclr() 1");
11412099Sjoerg		if (fwrite(ob.o_buf, sz, 1, lout) != 1)
11512099Sjoerg			err(1, "cannot write to %s", loname);
11612099Sjoerg		ob.o_nxt = ob.o_buf;
11712099Sjoerg	}
11812099Sjoerg}
11912099Sjoerg
12012099Sjoerg/*
12112099Sjoerg * write a character to the output buffer
12212099Sjoerg */
12312099Sjoergvoid
12412099Sjoergoutchar(c)
12512099Sjoerg	int	c;
12612099Sjoerg{
12712099Sjoerg	if (ob.o_nxt == ob.o_end)
12812099Sjoerg		outxbuf();
12912099Sjoerg	*ob.o_nxt++ = (char)c;
13012099Sjoerg}
13112099Sjoerg
13212099Sjoerg/*
13312099Sjoerg * write a character to the output buffer, qouted if necessary
13412099Sjoerg */
13512099Sjoergvoid
13612099Sjoergoutqchar(c)
13712099Sjoerg	int	c;
13812099Sjoerg{
13912099Sjoerg	if (isprint(c) && c != '\\' && c != '"' && c != '\'') {
14012099Sjoerg		outchar(c);
14112099Sjoerg	} else {
14212099Sjoerg		outchar('\\');
14312099Sjoerg		switch (c) {
14412099Sjoerg		case '\\':
14512099Sjoerg			outchar('\\');
14612099Sjoerg			break;
14712099Sjoerg		case '"':
14812099Sjoerg			outchar('"');
14912099Sjoerg			break;
15012099Sjoerg		case '\'':
15112099Sjoerg			outchar('\'');
15212099Sjoerg			break;
15312099Sjoerg		case '\b':
15412099Sjoerg			outchar('b');
15512099Sjoerg			break;
15612099Sjoerg		case '\t':
15712099Sjoerg			outchar('t');
15812099Sjoerg			break;
15912099Sjoerg		case '\n':
16012099Sjoerg			outchar('n');
16112099Sjoerg			break;
16212099Sjoerg		case '\f':
16312099Sjoerg			outchar('f');
16412099Sjoerg			break;
16512099Sjoerg		case '\r':
16612099Sjoerg			outchar('r');
16712099Sjoerg			break;
16812099Sjoerg#ifdef __STDC__
16912099Sjoerg		case '\v':
17012099Sjoerg#else
17112099Sjoerg		case '\013':
17212099Sjoerg#endif
17312099Sjoerg			outchar('v');
17412099Sjoerg			break;
17512099Sjoerg#ifdef __STDC__
17612099Sjoerg		case '\a':
17712099Sjoerg#else
17812099Sjoerg		case '\007':
17912099Sjoerg#endif
18012099Sjoerg			outchar('a');
18112099Sjoerg			break;
18212099Sjoerg		default:
18312099Sjoerg			outchar((((u_int)c >> 6) & 07) + '0');
18412099Sjoerg			outchar((((u_int)c >> 3) & 07) + '0');
18512099Sjoerg			outchar((c & 07) + '0');
18612099Sjoerg			break;
18712099Sjoerg		}
18812099Sjoerg	}
18912099Sjoerg}
19012099Sjoerg
19112099Sjoerg/*
19212099Sjoerg * write a strint to the output buffer
19312099Sjoerg * the string must not contain any characters which
19412099Sjoerg * should be quoted
19512099Sjoerg */
19612099Sjoergvoid
19712099Sjoergoutstrg(s)
19812099Sjoerg	const	char *s;
19912099Sjoerg{
20012099Sjoerg	while (*s != '\0') {
20112099Sjoerg		if (ob.o_nxt == ob.o_end)
20212099Sjoerg			outxbuf();
20312099Sjoerg		*ob.o_nxt++ = *s++;
20412099Sjoerg	}
20512099Sjoerg}
20612099Sjoerg
20712099Sjoerg/*
20812099Sjoerg * write an integer value to toe output buffer
20912099Sjoerg */
21012099Sjoergvoid
21112099Sjoergoutint(i)
21212099Sjoerg	int	i;
21312099Sjoerg{
21412099Sjoerg	if ((ob.o_end - ob.o_nxt) < 3 * sizeof (int))
21512099Sjoerg		outxbuf();
21612099Sjoerg	ob.o_nxt += sprintf(ob.o_nxt, "%d", i);
21712099Sjoerg}
21812099Sjoerg
21912099Sjoerg/*
22012099Sjoerg * write the name of a symbol to the output buffer
221165628Syar * the name is preceded by its length
22212099Sjoerg */
22312099Sjoergvoid
22412099Sjoergoutname(name)
22512099Sjoerg	const	char *name;
22612099Sjoerg{
22712099Sjoerg	if (name == NULL)
22812099Sjoerg		errx(1, "internal error: outname() 1");
22912099Sjoerg	outint((int)strlen(name));
23012099Sjoerg	outstrg(name);
23112099Sjoerg}
23212099Sjoerg
23312099Sjoerg/*
23412099Sjoerg * write the name of the .c source
23512099Sjoerg */
23612099Sjoergvoid
23712099Sjoergoutsrc(name)
23812099Sjoerg	const	char *name;
23912099Sjoerg{
24012099Sjoerg	outclr();
24112099Sjoerg	outchar('S');
24212099Sjoerg	outstrg(name);
24312099Sjoerg}
244