|
|
researchv8 Dan Cross
#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);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.