1/* $NetBSD: emit.c,v 1.2 2002/01/21 19:49:51 tv 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#if defined(__RCSID) && !defined(lint) 36__RCSID("$NetBSD: emit.c,v 1.2 2002/01/21 19:49:51 tv Exp $"); 37#endif 38 39#include <ctype.h> 40#include <stdio.h> 41#include <string.h> 42 43#include "lint.h" 44 45/* name and handle of output file */ 46static const char *loname; 47static FILE *lout; 48 49/* output buffer data */ 50ob_t ob; 51 52static void outxbuf(void); 53 54 55/* 56 * initialize output 57 */ 58void 59outopen(const char *name) 60{ 61 62 loname = name; 63 64 /* Open output file */ 65 if ((lout = fopen(name, "w")) == NULL) 66 err(1, "cannot open '%s'", name); 67 68 /* Create output buffer */ 69 ob.o_len = 1024; 70 ob.o_end = (ob.o_buf = ob.o_nxt = xmalloc(ob.o_len)) + ob.o_len; 71} 72 73/* 74 * flush output buffer and close file 75 */ 76void 77outclose(void) 78{ 79 80 outclr(); 81 if (fclose(lout) == EOF) 82 err(1, "cannot close '%s'", loname); 83} 84 85/* 86 * resize output buffer 87 */ 88static void 89outxbuf(void) 90{ 91 ptrdiff_t coffs; 92 93 coffs = ob.o_nxt - ob.o_buf; 94 ob.o_len *= 2; 95 ob.o_end = (ob.o_buf = xrealloc(ob.o_buf, ob.o_len)) + ob.o_len; 96 ob.o_nxt = ob.o_buf + coffs; 97} 98 99/* 100 * reset output buffer 101 * if it is not empty, it is flushed 102 */ 103void 104outclr(void) 105{ 106 size_t sz; 107 108 if (ob.o_buf != ob.o_nxt) { 109 outchar('\n'); 110 sz = ob.o_nxt - ob.o_buf; 111 if (sz > ob.o_len) 112 errx(1, "internal error: outclr() 1"); 113 if (fwrite(ob.o_buf, sz, 1, lout) != 1) 114 err(1, "cannot write to %s", loname); 115 ob.o_nxt = ob.o_buf; 116 } 117} 118 119/* 120 * write a character to the output buffer 121 */ 122void 123outchar(int c) 124{ 125 126 if (ob.o_nxt == ob.o_end) 127 outxbuf(); 128 *ob.o_nxt++ = (char)c; 129} 130 131/* 132 * write a character to the output buffer, qouted if necessary 133 */ 134void 135outqchar(int c) 136{ 137 138 if (isprint(c) && c != '\\' && c != '"' && c != '\'') { 139 outchar(c); 140 } else { 141 outchar('\\'); 142 switch (c) { 143 case '\\': 144 outchar('\\'); 145 break; 146 case '"': 147 outchar('"'); 148 break; 149 case '\'': 150 outchar('\''); 151 break; 152 case '\b': 153 outchar('b'); 154 break; 155 case '\t': 156 outchar('t'); 157 break; 158 case '\n': 159 outchar('n'); 160 break; 161 case '\f': 162 outchar('f'); 163 break; 164 case '\r': 165 outchar('r'); 166 break; 167 case '\v': 168 outchar('v'); 169 break; 170 case '\a': 171 outchar('a'); 172 break; 173 default: 174 outchar((((u_int)c >> 6) & 07) + '0'); 175 outchar((((u_int)c >> 3) & 07) + '0'); 176 outchar((c & 07) + '0'); 177 break; 178 } 179 } 180} 181 182/* 183 * write a strint to the output buffer 184 * the string must not contain any characters which 185 * should be quoted 186 */ 187void 188outstrg(const char *s) 189{ 190 191 while (*s != '\0') { 192 if (ob.o_nxt == ob.o_end) 193 outxbuf(); 194 *ob.o_nxt++ = *s++; 195 } 196} 197 198/* 199 * write an integer value to toe output buffer 200 */ 201void 202outint(int i) 203{ 204 205 if ((ob.o_end - ob.o_nxt) < 3 * sizeof (int)) 206 outxbuf(); 207 ob.o_nxt += sprintf(ob.o_nxt, "%d", i); 208} 209 210/* 211 * write the name of a symbol to the output buffer 212 * the name is preceded by its length 213 */ 214void 215outname(const char *name) 216{ 217 218 if (name == NULL) 219 errx(1, "internal error: outname() 1"); 220 outint((int)strlen(name)); 221 outstrg(name); 222} 223 224/* 225 * write the name of the .c source 226 */ 227void 228outsrc(const char *name) 229{ 230 231 outclr(); 232 outchar('S'); 233 outstrg(name); 234} 235