ack/lang/cem/cemcom/dumpidf.c

387 lines
7.5 KiB
C
Raw Normal View History

1986-03-10 13:07:55 +00:00
/* $Header$ */
/* DUMP ROUTINES */
#include "debug.h"
#ifdef DEBUG
#include "nopp.h"
#include "nobitfield.h"
#include "arith.h"
#include "stack.h"
#include "idf.h"
#include "def.h"
#include "type.h"
#include "struct.h"
#include "field.h"
#include "Lpars.h"
#include "label.h"
#include "expr.h"
/* Some routines (symbol2str, token2str, type2str) which should have
* yielded strings are written to yield a pointer to a transient piece
* of memory, containing the string, since this is the only reasonable
* thing to do in C. `Transient' means that the result may soon
* disappear, which is generally not a problem, since normally it is
* consumed immediately. Sometimes we need more than one of them, and
* MAXTRANS is the maximum number we will need simultaneously.
*/
#define MAXTRANS 6
extern char options[];
1986-04-03 14:32:56 +00:00
extern char *sprint();
1986-03-10 13:07:55 +00:00
extern struct idf *idf_hashtable[];
extern char *symbol2str(), *type2str(), *next_transient();
enum sdef_kind {selector, field}; /* parameter for dumpsdefs */
static int dumplevel;
static
newline() {
int dl = dumplevel;
1986-04-03 14:32:56 +00:00
print("\n");
1986-03-10 13:07:55 +00:00
while (dl >= 2) {
1986-04-03 14:32:56 +00:00
print("\t");
1986-03-10 13:07:55 +00:00
dl -= 2;
}
if (dl)
1986-04-03 14:32:56 +00:00
print(" ");
1986-03-10 13:07:55 +00:00
}
dumpidftab(msg, opt)
char msg[];
{
/* Dumps the identifier table in readable form (but in
arbitrary order).
Unless opt & 1, macros are not dumped.
Unless opt & 2, reserved identifiers are not dumped.
Unless opt & 4, universal identifiers are not dumped.
*/
int i;
1986-04-03 14:32:56 +00:00
print(">>> DUMPIDF, %s (start)", msg);
1986-03-10 13:07:55 +00:00
dumpstack();
for (i = 0; i < HASHSIZE; i++) {
struct idf *notch = idf_hashtable[i];
while (notch) {
dumpidf(notch, opt);
notch = notch->next;
}
}
newline();
1986-04-03 14:32:56 +00:00
print(">>> DUMPIDF, %s (end)\n", msg);
1986-03-10 13:07:55 +00:00
}
dumpstack() {
/* Dumps the identifier stack, starting at the top.
*/
struct stack_level *stl = local_level;
while (stl) {
struct stack_entry *se = stl->sl_entry;
newline();
1986-04-03 14:32:56 +00:00
print("%3d: ", stl->sl_level);
1986-03-10 13:07:55 +00:00
while (se) {
1986-04-03 14:32:56 +00:00
print("%s ", se->se_idf->id_text);
1986-03-10 13:07:55 +00:00
se = se->next;
}
stl = stl->sl_previous;
}
1986-04-03 14:32:56 +00:00
print("\n");
1986-03-10 13:07:55 +00:00
}
dumpidf(idf, opt)
struct idf *idf;
{
/* All information about the identifier idf is divulged in a
hopefully readable format.
*/
int started = 0;
if (!idf)
return;
#ifndef NOPP
if ((opt&1) && idf->id_macro) {
if (!started++) {
newline();
1986-04-03 14:32:56 +00:00
print("%s:", idf->id_text);
1986-03-10 13:07:55 +00:00
}
1986-04-03 14:32:56 +00:00
print(" macro");
1986-03-10 13:07:55 +00:00
}
#endif NOPP
if ((opt&2) && idf->id_reserved) {
if (!started++) {
newline();
1986-04-03 14:32:56 +00:00
print("%s:", idf->id_text);
1986-03-10 13:07:55 +00:00
}
1986-04-03 14:32:56 +00:00
print(" reserved: %d;", idf->id_reserved);
1986-03-10 13:07:55 +00:00
}
if (idf->id_def && ((opt&4) || idf->id_def->df_level)) {
if (!started++) {
newline();
1986-04-03 14:32:56 +00:00
print("%s:", idf->id_text);
1986-03-10 13:07:55 +00:00
}
dumpdefs(idf->id_def, opt);
}
if (idf->id_sdef) {
if (!started++) {
newline();
1986-04-03 14:32:56 +00:00
print("%s:", idf->id_text);
1986-03-10 13:07:55 +00:00
}
dumpsdefs(idf->id_sdef, selector);
}
if (idf->id_struct) {
if (!started++) {
newline();
1986-04-03 14:32:56 +00:00
print("%s:", idf->id_text);
1986-03-10 13:07:55 +00:00
}
dumptags(idf->id_struct);
}
if (idf->id_enum) {
if (!started++) {
newline();
1986-04-03 14:32:56 +00:00
print("%s:", idf->id_text);
1986-03-10 13:07:55 +00:00
}
dumptags(idf->id_enum);
}
}
dumpdefs(def, opt)
register struct def *def;
{
dumplevel++;
while (def && ((opt&4) || def->df_level)) {
newline();
1986-04-03 14:32:56 +00:00
print("L%d: %s %s%s%s%s%s %lo;",
1986-03-10 13:07:55 +00:00
def->df_level,
symbol2str(def->df_sc),
(def->df_register != REG_NONE) ? "reg " : "",
def->df_initialized ? "init'd " : "",
def->df_used ? "used " : "",
type2str(def->df_type),
def->df_sc == ENUM ? ", =" : " at",
def->df_address
);
def = def->next;
}
dumplevel--;
}
dumptags(tag)
struct tag *tag;
{
dumplevel++;
while (tag) {
register struct type *tp = tag->tg_type;
register int fund = tp->tp_fund;
newline();
1986-04-03 14:32:56 +00:00
print("L%d: %s %s",
1986-03-10 13:07:55 +00:00
tag->tg_level,
fund == STRUCT ? "struct" :
fund == UNION ? "union" :
fund == ENUM ? "enum" : "<UNKNOWN>",
tp->tp_idf->id_text
);
if (is_struct_or_union(fund)) {
1986-04-03 14:32:56 +00:00
print(" {");
1986-03-10 13:07:55 +00:00
dumpsdefs(tp->tp_sdef, field);
newline();
1986-04-03 14:32:56 +00:00
print("}");
1986-03-10 13:07:55 +00:00
}
1986-04-03 14:32:56 +00:00
print(";");
1986-03-10 13:07:55 +00:00
tag = tag->next;
}
dumplevel--;
}
dumpsdefs(sdef, sdk)
struct sdef *sdef;
enum sdef_kind sdk;
{
/* Since sdef's are members of two chains, there are actually
two dumpsdefs's, one following the chain of all selectors
belonging to the same idf, starting at idf->id_sdef;
and the other following the chain of all selectors belonging
to the same struct, starting at stp->tp_sdef.
*/
dumplevel++;
while (sdef) {
newline();
1986-04-03 14:32:56 +00:00
print("L%d: ", sdef->sd_level);
1986-03-10 13:07:55 +00:00
#ifndef NOBITFIELD
if (sdk == selector)
#endif NOBITFIELD
1986-04-03 14:32:56 +00:00
print("selector %s at offset %lu in %s;",
1986-03-10 13:07:55 +00:00
type2str(sdef->sd_type),
sdef->sd_offset, type2str(sdef->sd_stype)
);
#ifndef NOBITFIELD
1986-04-03 14:32:56 +00:00
else print("field %s at offset %lu;",
1986-03-10 13:07:55 +00:00
type2str(sdef->sd_type), sdef->sd_offset
);
#endif NOBITFIELD
sdef = (sdk == selector ? sdef->next : sdef->sd_sdef);
}
dumplevel--;
}
char *
type2str(tp)
struct type *tp;
{
/* Yields a pointer to a one-line description of the type tp.
*/
char *buf = next_transient();
int ops = 1;
buf[0] = '\0';
if (!tp) {
1986-04-03 14:32:56 +00:00
sprint(buf, "<NILTYPE>");
1986-03-10 13:07:55 +00:00
return buf;
}
1986-04-03 14:32:56 +00:00
sprint(buf, "(@%lx, #%ld, &%d) ",
1986-03-17 17:47:04 +00:00
tp, (long)tp->tp_size, tp->tp_align);
1986-03-10 13:07:55 +00:00
while (ops) {
switch (tp->tp_fund) {
case POINTER:
1986-04-03 14:32:56 +00:00
sprint(buf, "%spointer to ", buf);
1986-03-10 13:07:55 +00:00
break;
case ARRAY:
1986-04-03 14:32:56 +00:00
sprint(buf, "%sarray [%ld] of ", buf, tp->tp_size);
1986-03-10 13:07:55 +00:00
break;
case FUNCTION:
1986-04-03 14:32:56 +00:00
sprint(buf, "%sfunction yielding ", buf);
1986-03-10 13:07:55 +00:00
break;
default:
1986-04-03 14:32:56 +00:00
sprint(buf, "%s%s%s", buf,
1986-03-10 13:07:55 +00:00
tp->tp_unsigned ? "unsigned " : "",
symbol2str(tp->tp_fund)
);
if (tp->tp_idf)
1986-04-03 14:32:56 +00:00
sprint(buf, "%s %s", buf,
1986-03-10 13:07:55 +00:00
tp->tp_idf->id_text);
#ifndef NOBITFIELD
if (tp->tp_field) {
struct field *fd = tp->tp_field;
1986-04-03 14:32:56 +00:00
sprint(buf, "%s [s=%ld,w=%ld]", buf,
1986-03-10 13:07:55 +00:00
fd->fd_shift, fd->fd_width);
}
#endif NOBITFIELD
ops = 0;
break;
}
tp = tp->tp_up;
}
return buf;
}
char * /* the ultimate transient buffer supplier */
next_transient()
{
1986-03-10 13:07:55 +00:00
static int bnum;
static char buf[MAXTRANS][300];
if (++bnum == MAXTRANS)
bnum = 0;
return buf[bnum];
}
print_expr(msg, expr)
char msg[];
struct expr *expr;
{
/* Provisional routine to print an expression preceded by a
message msg.
*/
if (options['x']) {
1986-04-03 14:32:56 +00:00
print("\n%s: ", msg);
print("(L=line, T=type, r/lV=r/lvalue, F=flags, D=depth)\n");
1986-03-10 13:07:55 +00:00
p1_expr(0, expr);
}
}
p1_expr(lvl, expr)
struct expr *expr;
{
extern char *type2str(), *symbol2str();
p1_indent(lvl);
if (!expr) {
1986-04-03 14:32:56 +00:00
print("NILEXPR\n");
1986-03-10 13:07:55 +00:00
return;
}
1986-04-03 14:32:56 +00:00
print("expr: L=%u, T=%s, %cV, F=%03o, D=%d, %s: ",
1986-03-10 13:07:55 +00:00
expr->ex_line,
type2str(expr->ex_type),
expr->ex_lvalue ? 'l' : 'r',
expr->ex_flags & 0xFF,
1986-03-10 13:07:55 +00:00
expr->ex_depth,
expr->ex_class == Value ? "Value" :
expr->ex_class == String ? "String" :
expr->ex_class == Float ? "Float" :
expr->ex_class == Oper ? "Oper" :
expr->ex_class == Type ? "Type" : "UNKNOWN CLASS"
);
switch (expr->ex_class) {
struct oper *o;
case Value:
switch (expr->VL_CLASS) {
case Const:
1986-04-03 14:32:56 +00:00
print("(Const) ");
break;
case Name:
1986-04-03 14:32:56 +00:00
print("(Name) %s + ", expr->VL_IDF->id_text);
break;
case Label:
1986-04-03 14:32:56 +00:00
print("(Label) .%lu + ", expr->VL_LBL);
break;
default:
1986-04-03 14:32:56 +00:00
print("(Unknown) ");
break;
}
1986-04-03 14:32:56 +00:00
print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
expr->VL_VALUE);
1986-03-10 13:07:55 +00:00
break;
case String:
{
char bts2str();
1986-04-03 14:32:56 +00:00
print(
"%s\n",
bts2str(expr->SG_VALUE, expr->SG_LEN, next_transient())
);
1986-03-10 13:07:55 +00:00
break;
}
1986-03-10 13:07:55 +00:00
case Float:
1986-04-03 14:32:56 +00:00
print("%s\n", expr->FL_VALUE);
1986-03-10 13:07:55 +00:00
break;
case Oper:
o = &expr->ex_object.ex_oper;
1986-04-03 14:32:56 +00:00
print("\n");
1986-03-10 13:07:55 +00:00
p1_expr(lvl+1, o->op_left);
1986-04-03 14:32:56 +00:00
p1_indent(lvl); print("%s\n", symbol2str(o->op_oper));
1986-03-10 13:07:55 +00:00
p1_expr(lvl+1, o->op_right);
break;
case Type:
1986-04-03 14:32:56 +00:00
print("\n");
1986-03-10 13:07:55 +00:00
break;
default:
1986-04-03 14:32:56 +00:00
print("UNKNOWN CLASS\n");
1986-03-10 13:07:55 +00:00
break;
}
}
p1_indent(lvl) {
while (lvl--)
1986-04-03 14:32:56 +00:00
print(" ");
1986-03-10 13:07:55 +00:00
}
#endif DEBUG