V8/usr/src/cmd/cyntax/cem/diag.c

Compare this file to the similar file:
Show the results in this format:

#define	STD_OBJ	1
#include	"stdobj.h"
#include	"types.h"
#include	"cem.h"
#include	"symbol.h"
#include	"type.h"

/*
 *	Routines for generating diagnostics.
 */

#define	err(c)		putchar(c)
#define	err_str(s)	printf(str_fmt, (s))
#define	err_num(l)	printf(num_fmt, (l))

static char	*num_fmt	= "%ld";
static char	*str_fmt	= "%s";
static int	time_forced;

extern char	*strchr();

/*
 *	File names match and so do modtimes.
 */
int
match_times(s, t)
symbol	*s;
symbol	*t;
{
	return s == t && strchr(s->sy_name, TIME_SEP) != NULL;
}

/*
 *	Print the name of a basetype.
 */
void
print_basetype(my_type)
register int	my_type;
{
	register int	bit;
	register int	spoken;

	static char		*type_names[] =
	{
		"unsigned",
		"long",
		"char",
		"short",
		"int",
		"float",
		"void",
		"<bad type>",
	};

	if (!pedantic)
	{
		if ((my_type & (LONG | FLOAT)) == (LONG | FLOAT))
		{
			err_str("double");
			return;
		}
		else if ((my_type & (LONG | SHORT)) != 0)
			my_type &= ~INT;
	}

	spoken = 0;
	
	for (bit = 0; my_type != 0; bit++, my_type >>= 1)
	{
		if ((my_type & 1) != 0)
		{
			if (spoken)
				err(' ');

			spoken++;
			err_str(type_names[bit]);
		}
	}
}

/*
 *	Print a type as one might say it.
 */
static void
put_verbose_type(t)
register type	*t;
{
	register int	spoken;
	register int	plural;

	spoken = 0;
	plural = 0;

	while (t != NULL)
	{
		if (spoken)
			err(' ');

		switch (t->t_type)
		{
		case t_arrayof:
			printf("array[%ld]", t->d.dim);

			if (plural)
				err('s');

			err_str(" of");
			plural = 1;
			break;

		case t_basetype:
			print_basetype(t->d.mask);

			if (plural)
				err('s');

			return;

		case t_bitfield:
			err_str("bitfield");

			if (plural)
				err('s');

			err_str(" of");
			break;

		case t_dimless:
			err_str("array[]");

			if (plural)
				err('s');

			err_str(" of");
			plural = 1;
			break;

		case t_ftnreturning:
			err_str("function");

			if (plural)
				err('s');

			err_str(" returning");
			break;

		case t_ptrto:
			err_str("pointer");

			if (plural)
				err('s');

			err_str(" to");
			break;

		case t_enum:
			err_str("enum");

			if (t->d.e->e_name != NULL)
				printf(" %s", t->d.e->e_name->sy_name);

			err_str(" (");
			put_file(t->d.e->e_file, t->d.e->e_line);
			err(')');
			return;

		case t_structof:
			err_str("struct");

			if (t->d.s->s_name != NULL)
				printf(" %s", t->d.s->s_name->sy_name);

			err_str(" (");
			put_file(t->d.s->s_file, t->d.s->s_line);
			err(')');
			return;

		case t_unionof:
			err_str("union");

			if (t->d.u->u_name != NULL)
				printf(" %s", t->d.u->u_name->sy_name);

			err_str(" (");
			put_file(t->d.u->u_file, t->d.u->u_line);
			err(')');
			return;

		default:
			err_str("unknown");

			if (plural)
				err('s');
		}

		t = t->t_subtype;
		spoken = 1;
	}
}

/*
 *	Stash routines for 'put_c_type'.  We need to be able
 *	to build up a type by 'outputing' characters before and
 *	after what we have already said.  The average type is
 *	expected to take up no more than TYPE_SIZE chars (not counting
 *	basetype or complex base which always comes first).  The
 *	amount of backup is expected not to exceed HEAD_SIZE chars.
 *	If these are exceeded we extend in the appropriate direction
 *	by TYPE_EXTEND chars.
 *
 *	str_buff:
 *
 *	0 - unused - str_head - stuff - str_tail - unused - str_limit
 */
static int	str_head;
static int	str_tail;
static int	str_start;
static int	str_limit;
static char	*str_buff;

#define	TYPE_SIZE	64
#define	TYPE_EXTEND	32
#define	HEAD_SIZE	16

static void
str_init()
{
	str_limit = TYPE_SIZE;
	str_start = HEAD_SIZE;
	str_buff = salloc((long)str_limit);
}

static void
str_extend(ext, head)
int	ext;
int	head;
{
	register char	*p;
	register char	*q;

	str_limit += ext;
	str_buff = srealloc(str_buff, (long)str_limit);

	if (head)
	{
		str_start += ext;
		str_head += ext;
		str_tail += ext;
		p = str_buff + str_limit;
		q = p - ext;

		while (q > str_buff)
			*--p = *--q;
	}
}

static void
head_char(c)
int	c;
{
	if (--str_head < 0)
		str_extend(HEAD_SIZE, 1);

	str_buff[str_head] = c;
}

static void
tail_char(c)
int	c;
{
	if (str_tail == str_limit)
		str_extend(TYPE_EXTEND, 0);

	str_buff[str_tail++] = c;
}

static void
tail_str(s)
register char	*s;
{
	while (*s != '\0')
		tail_char(*s++);
}

/*
 *	Print a type as it may have been declared.
 */
static void
put_c_type(ct)
type	*ct;
{
	register type	*t;
	char		buff[16];

	for (t = ct; t != NULL; t = t->t_subtype)
	{
		switch (t->t_type)
		{
		case t_arrayof:
			sprintf(buff, "[%ld]", t->d.dim);
			tail_str(buff);
			break;

		case t_basetype:
			print_basetype(t->d.mask);
			goto finish;

		case t_bitfield:
			sprintf(buff, ":%ld", t->d.size);
			tail_str(buff);
			break;

		case t_dimless:
			tail_str("[]");
			break;

		case t_ftnreturning:
			if (t != ct)
			{
				head_char('(');
				tail_char(')');
			}

			tail_str("()");
			break;

		case t_ptrto:
			head_char('*');
			break;

		case t_enum:
			err_str("enum");

			if (t->d.e->e_name != NULL)
				printf(" %s", t->d.e->e_name->sy_name);

			err_str(" (");
			put_file(t->d.e->e_file, t->d.e->e_line);
			err(')');
			goto finish;

		case t_structof:
			err_str("struct");

			if (t->d.s->s_name != NULL)
				printf(" %s", t->d.s->s_name->sy_name);

			err_str(" (");
			put_file(t->d.s->s_file, t->d.s->s_line);
			err(')');
			goto finish;

		case t_unionof:
			err_str("union");

			if (t->d.u->u_name != NULL)
				printf(" %s", t->d.u->u_name->sy_name);

			err_str(" (");
			put_file(t->d.u->u_file, t->d.u->u_line);
			err(')');
			goto finish;

		default:
			err_str("unknown");

		finish:
			if (t != ct)
				err(' ');

			return;
		}
	}
}

/*
 *	Print a type, choose between the two formats.
 */
void
put_type(t, force)
register type	*t;
int		force;
{
	time_forced = force;

	if (verbose)
		put_verbose_type(t);
	else
	{
		if (str_buff == NULL)
			str_init();

		str_head = str_start;
		str_tail = str_start;
		put_c_type(t);
		tail_char('\0');
		err_str(&str_buff[str_head]);
	}

	time_forced = 0;
}

/*
 *	Print a filename.  Strip leading occurences of "./".
 *	Perhaps also print the mod time.
 */
static void
format_filename(s)
register char	*s;
{
	register char	*p;
	register long	l;
	extern char	*strrchr();
	extern long	atol();

	while (s[0] == '.' && s[1] == '/' && s[2] != '\0')
		s += 2;

	if ((p = strrchr(s, TIME_SEP)) == NULL)
		printf("%s", s);
	else
	{
		*p++ = '\0';
		err_str(s);

		if ((time_forced || tell_times) && (l = atol(p)) != 0)
			printf(" [%s]", stime(l));

		*--p = TIME_SEP;
	}
}

/*
 *	Print the current filename and note that this file has errors.
 *	Used for file-static errors.
 */
void
say_file()
{
	format_filename(src_file->sy_name);
	file_errors = 1;
}

/*
 *	Print a filename and line number.  Omit filename if it is
 *	the current file.
 */

void
put_file(f, l)
symbol	*f;
long	l;
{
	if (f == src_file)
		printf("%ld", l);
	else
	{
		format_filename(f->sy_name);

		if (l != 0)
			printf(": %ld", l);
	}	
}