Home | History | Annotate | Line # | Download | only in common
emit.c revision 1.11
      1  1.11    rillig /*	$NetBSD: emit.c,v 1.11 2021/03/27 11:08:00 rillig Exp $	*/
      2   1.1   thorpej 
      3   1.1   thorpej /*
      4   1.1   thorpej  * Copyright (c) 1994, 1995 Jochen Pohl
      5   1.1   thorpej  * All Rights Reserved.
      6   1.1   thorpej  *
      7   1.1   thorpej  * Redistribution and use in source and binary forms, with or without
      8   1.1   thorpej  * modification, are permitted provided that the following conditions
      9   1.1   thorpej  * are met:
     10   1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     11   1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     12   1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     14   1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     15   1.1   thorpej  * 3. All advertising materials mentioning features or use of this software
     16   1.1   thorpej  *    must display the following acknowledgement:
     17   1.1   thorpej  *      This product includes software developed by Jochen Pohl for
     18   1.1   thorpej  *	The NetBSD Project.
     19   1.1   thorpej  * 4. The name of the author may not be used to endorse or promote products
     20   1.1   thorpej  *    derived from this software without specific prior written permission.
     21   1.1   thorpej  *
     22   1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23   1.1   thorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24   1.1   thorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25   1.1   thorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26   1.1   thorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27   1.1   thorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28   1.1   thorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29   1.1   thorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30   1.1   thorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31   1.1   thorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32   1.1   thorpej  */
     33   1.1   thorpej 
     34   1.4       jmc #if HAVE_NBTOOL_CONFIG_H
     35   1.4       jmc #include "nbtool_config.h"
     36   1.4       jmc #endif
     37   1.4       jmc 
     38   1.1   thorpej #include <sys/cdefs.h>
     39   1.3        tv #if defined(__RCSID) && !defined(lint)
     40  1.11    rillig __RCSID("$NetBSD: emit.c,v 1.11 2021/03/27 11:08:00 rillig Exp $");
     41   1.1   thorpej #endif
     42   1.1   thorpej 
     43   1.2        tv #include <ctype.h>
     44   1.1   thorpej #include <stdio.h>
     45   1.1   thorpej #include <string.h>
     46   1.1   thorpej 
     47   1.1   thorpej #include "lint.h"
     48   1.1   thorpej 
     49   1.1   thorpej /* name and handle of output file */
     50   1.1   thorpej static	const	char *loname;
     51   1.1   thorpej static	FILE	*lout;
     52   1.1   thorpej 
     53   1.1   thorpej /* output buffer data */
     54   1.1   thorpej ob_t	ob;
     55   1.1   thorpej 
     56   1.1   thorpej static	void	outxbuf(void);
     57   1.1   thorpej 
     58   1.1   thorpej 
     59   1.1   thorpej /*
     60   1.1   thorpej  * initialize output
     61   1.1   thorpej  */
     62   1.1   thorpej void
     63   1.1   thorpej outopen(const char *name)
     64   1.1   thorpej {
     65   1.1   thorpej 
     66   1.1   thorpej 	loname = name;
     67   1.1   thorpej 
     68   1.1   thorpej 	/* Open output file */
     69   1.1   thorpej 	if ((lout = fopen(name, "w")) == NULL)
     70   1.1   thorpej 		err(1, "cannot open '%s'", name);
     71   1.1   thorpej 
     72   1.1   thorpej 	/* Create output buffer */
     73   1.1   thorpej 	ob.o_len = 1024;
     74   1.8    rillig 	ob.o_end = (ob.o_buf = ob.o_next = xmalloc(ob.o_len)) + ob.o_len;
     75   1.1   thorpej }
     76   1.1   thorpej 
     77   1.1   thorpej /*
     78   1.1   thorpej  * flush output buffer and close file
     79   1.1   thorpej  */
     80   1.1   thorpej void
     81   1.1   thorpej outclose(void)
     82   1.1   thorpej {
     83   1.1   thorpej 
     84   1.1   thorpej 	outclr();
     85   1.1   thorpej 	if (fclose(lout) == EOF)
     86   1.1   thorpej 		err(1, "cannot close '%s'", loname);
     87   1.1   thorpej }
     88   1.1   thorpej 
     89   1.1   thorpej /*
     90   1.1   thorpej  * resize output buffer
     91   1.1   thorpej  */
     92   1.1   thorpej static void
     93   1.1   thorpej outxbuf(void)
     94   1.1   thorpej {
     95   1.1   thorpej 	ptrdiff_t coffs;
     96   1.1   thorpej 
     97   1.8    rillig 	coffs = ob.o_next - ob.o_buf;
     98   1.1   thorpej 	ob.o_len *= 2;
     99   1.1   thorpej 	ob.o_end = (ob.o_buf = xrealloc(ob.o_buf, ob.o_len)) + ob.o_len;
    100   1.8    rillig 	ob.o_next = ob.o_buf + coffs;
    101   1.1   thorpej }
    102   1.1   thorpej 
    103   1.1   thorpej /*
    104   1.1   thorpej  * reset output buffer
    105   1.1   thorpej  * if it is not empty, it is flushed
    106   1.1   thorpej  */
    107   1.1   thorpej void
    108   1.1   thorpej outclr(void)
    109   1.1   thorpej {
    110   1.1   thorpej 	size_t	sz;
    111   1.1   thorpej 
    112   1.8    rillig 	if (ob.o_buf != ob.o_next) {
    113   1.1   thorpej 		outchar('\n');
    114   1.8    rillig 		sz = ob.o_next - ob.o_buf;
    115   1.1   thorpej 		if (sz > ob.o_len)
    116   1.1   thorpej 			errx(1, "internal error: outclr() 1");
    117   1.1   thorpej 		if (fwrite(ob.o_buf, sz, 1, lout) != 1)
    118   1.1   thorpej 			err(1, "cannot write to %s", loname);
    119   1.8    rillig 		ob.o_next = ob.o_buf;
    120   1.1   thorpej 	}
    121   1.1   thorpej }
    122   1.1   thorpej 
    123   1.1   thorpej /*
    124   1.1   thorpej  * write a character to the output buffer
    125   1.1   thorpej  */
    126   1.1   thorpej void
    127   1.1   thorpej outchar(int c)
    128   1.1   thorpej {
    129   1.1   thorpej 
    130   1.8    rillig 	if (ob.o_next == ob.o_end)
    131   1.1   thorpej 		outxbuf();
    132   1.8    rillig 	*ob.o_next++ = (char)c;
    133   1.1   thorpej }
    134   1.1   thorpej 
    135   1.1   thorpej /*
    136   1.9    rillig  * write a character to the output buffer, quoted if necessary
    137   1.1   thorpej  */
    138   1.1   thorpej void
    139   1.1   thorpej outqchar(int c)
    140   1.1   thorpej {
    141   1.1   thorpej 
    142  1.10    rillig 	if (ch_isprint(c) && c != '\\' && c != '"' && c != '\'') {
    143   1.1   thorpej 		outchar(c);
    144   1.1   thorpej 	} else {
    145   1.1   thorpej 		outchar('\\');
    146   1.1   thorpej 		switch (c) {
    147   1.1   thorpej 		case '\\':
    148   1.1   thorpej 			outchar('\\');
    149   1.1   thorpej 			break;
    150   1.1   thorpej 		case '"':
    151   1.1   thorpej 			outchar('"');
    152   1.1   thorpej 			break;
    153   1.1   thorpej 		case '\'':
    154   1.1   thorpej 			outchar('\'');
    155   1.1   thorpej 			break;
    156   1.1   thorpej 		case '\b':
    157   1.1   thorpej 			outchar('b');
    158   1.1   thorpej 			break;
    159   1.1   thorpej 		case '\t':
    160   1.1   thorpej 			outchar('t');
    161   1.1   thorpej 			break;
    162   1.1   thorpej 		case '\n':
    163   1.1   thorpej 			outchar('n');
    164   1.1   thorpej 			break;
    165   1.1   thorpej 		case '\f':
    166   1.1   thorpej 			outchar('f');
    167   1.1   thorpej 			break;
    168   1.1   thorpej 		case '\r':
    169   1.1   thorpej 			outchar('r');
    170   1.1   thorpej 			break;
    171   1.1   thorpej 		case '\v':
    172   1.1   thorpej 			outchar('v');
    173   1.1   thorpej 			break;
    174   1.1   thorpej 		case '\a':
    175   1.1   thorpej 			outchar('a');
    176   1.1   thorpej 			break;
    177   1.1   thorpej 		default:
    178   1.9    rillig 			outchar((((unsigned char)c >> 6) & 07) + '0');
    179   1.9    rillig 			outchar((((unsigned char)c >> 3) & 07) + '0');
    180   1.1   thorpej 			outchar((c & 07) + '0');
    181   1.1   thorpej 			break;
    182   1.1   thorpej 		}
    183   1.1   thorpej 	}
    184   1.1   thorpej }
    185   1.1   thorpej 
    186   1.1   thorpej /*
    187   1.7    rillig  * write a string to the output buffer
    188   1.1   thorpej  * the string must not contain any characters which
    189   1.1   thorpej  * should be quoted
    190   1.1   thorpej  */
    191   1.1   thorpej void
    192   1.1   thorpej outstrg(const char *s)
    193   1.1   thorpej {
    194   1.1   thorpej 
    195   1.1   thorpej 	while (*s != '\0') {
    196   1.8    rillig 		if (ob.o_next == ob.o_end)
    197   1.1   thorpej 			outxbuf();
    198   1.8    rillig 		*ob.o_next++ = *s++;
    199   1.1   thorpej 	}
    200   1.1   thorpej }
    201   1.1   thorpej 
    202   1.1   thorpej /*
    203   1.7    rillig  * write an integer value to the output buffer
    204   1.1   thorpej  */
    205   1.1   thorpej void
    206   1.1   thorpej outint(int i)
    207   1.1   thorpej {
    208   1.1   thorpej 
    209  1.11    rillig 	if ((size_t)(ob.o_end - ob.o_next) < 3 * sizeof(int))
    210   1.1   thorpej 		outxbuf();
    211   1.8    rillig 	ob.o_next += sprintf(ob.o_next, "%d", i);
    212   1.1   thorpej }
    213   1.1   thorpej 
    214   1.1   thorpej /*
    215   1.1   thorpej  * write the name of a symbol to the output buffer
    216   1.1   thorpej  * the name is preceded by its length
    217   1.1   thorpej  */
    218   1.1   thorpej void
    219   1.6  christos outname1(const char *file, size_t line, const char *name)
    220   1.1   thorpej {
    221   1.1   thorpej 
    222   1.1   thorpej 	if (name == NULL)
    223   1.6  christos 		errx(1, "%s, %zu: internal error: outname(NULL)", file, line);
    224   1.1   thorpej 	outint((int)strlen(name));
    225   1.1   thorpej 	outstrg(name);
    226   1.1   thorpej }
    227   1.1   thorpej 
    228   1.1   thorpej /*
    229   1.1   thorpej  * write the name of the .c source
    230   1.1   thorpej  */
    231   1.1   thorpej void
    232   1.1   thorpej outsrc(const char *name)
    233   1.1   thorpej {
    234   1.1   thorpej 
    235   1.1   thorpej 	outclr();
    236   1.1   thorpej 	outchar('S');
    237   1.1   thorpej 	outstrg(name);
    238   1.1   thorpej }
    239