1 /* $NetBSD: emit.c,v 1.3 2002/01/31 19:36:53 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.3 2002/01/31 19:36:53 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 */ 46 static const char *loname; 47 static FILE *lout; 48 49 /* output buffer data */ 50 ob_t ob; 51 52 static void outxbuf(void); 53 54 55 /* 56 * initialize output 57 */ 58 void 59 outopen(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 */ 76 void 77 outclose(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 */ 88 static void 89 outxbuf(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 */ 103 void 104 outclr(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 */ 122 void 123 outchar(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 */ 134 void 135 outqchar(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 */ 187 void 188 outstrg(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 */ 201 void 202 outint(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 */ 214 void 215 outname(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 */ 227 void 228 outsrc(const char *name) 229 { 230 231 outclr(); 232 outchar('S'); 233 outstrg(name); 234 } 235