add log device ; unused reset routines are nulldev
[unix-history] / usr / src / old / dbx / printsym.c
/* Copyright (c) 1982 Regents of the University of California */
static char sccsid[] = "@(#)printsym.c 1.13 (Berkeley) %G%";
/*
* Printing of symbolic information.
*/
#include "defs.h"
#include "symbols.h"
#include "languages.h"
#include "printsym.h"
#include "tree.h"
#include "eval.h"
#include "mappings.h"
#include "process.h"
#include "runtime.h"
#include "machine.h"
#include "names.h"
#include "main.h"
#ifndef public
#endif
/*
* Maximum number of arguments to a function.
* This is used as a check for the possibility that the stack has been
* overwritten and therefore a saved argument pointer might indicate
* to an absurdly large number of arguments.
*/
#define MAXARGSPASSED 20
/*
* Return a pointer to the string for the name of the class that
* the given symbol belongs to.
*/
private String clname[] = {
"bad use", "constant", "type", "variable", "array", "fileptr",
"record", "field", "procedure", "function", "funcvar",
"ref", "pointer", "file", "set", "range", "label", "withptr",
"scalar", "string", "program", "improper", "variant",
"procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
};
public String classname(s)
Symbol s;
{
return clname[ord(s->class)];
}
/*
* Note the entry of the given block, unless it's the main program.
*/
public printentry(s)
Symbol s;
{
if (s != program) {
printf("\nentering %s %s\n", classname(s), symname(s));
}
}
/*
* Note the exit of the given block
*/
public printexit(s)
Symbol s;
{
if (s != program) {
printf("leaving %s %s\n\n", classname(s), symname(s));
}
}
/*
* Note the call of s from t.
*/
public printcall(s, t)
Symbol s, t;
{
printf("calling %s", symname(s));
printparams(s, nil);
printf(" from %s %s\n", classname(t), symname(t));
}
/*
* Note the return from s. If s is a function, print the value
* it is returning. This is somewhat painful, since the function
* has actually just returned.
*/
public printrtn(s)
Symbol s;
{
register Symbol t;
register int len;
Boolean isindirect;
printf("returning ");
if (s->class == FUNC && (!istypename(s->type,"void"))) {
len = size(s->type);
if (canpush(len)) {
t = rtype(s->type);
isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
pushretval(len, isindirect);
printval(s->type);
putchar(' ');
} else {
printf("(value too large) ");
}
}
printf("from %s\n", symname(s));
}
/*
* Print the values of the parameters of the given procedure or function.
* The frame distinguishes recursive instances of a procedure.
*
* If the procedure or function is internal, the argument count is
* not valid so we ignore it.
*/
public printparams(f, frame)
Symbol f;
Frame frame;
{
Symbol param;
int n, m, s;
n = nargspassed(frame);
if (isinternal(f)) {
n = 0;
}
param = f->chain;
if (param != nil or n > 0) {
printf("(");
m = n;
if (param != nil) {
for (;;) {
s = size(param) div sizeof(Word);
if (s == 0) {
s = 1;
}
m -= s;
printv(param, frame);
param = param->chain;
if (param == nil) break;
printf(", ");
}
}
if (m > 0) {
if (m > MAXARGSPASSED) {
m = MAXARGSPASSED;
}
if (f->chain != nil) {
printf(", ");
}
for (;;) {
--m;
printf("0x%x", argn(n - m, frame));
if (m <= 0) break;
printf(", ");
}
}
printf(")");
}
}
/*
* Test if a symbol should be printed. We don't print files,
* for example, simply because there's no good way to do it.
* The symbol must be within the given function.
*/
public Boolean should_print(s)
Symbol s;
{
Boolean b;
register Symbol t;
switch (s->class) {
case VAR:
case FVAR:
if (isparam(s)) {
b = false;
} else {
t = rtype(s->type);
if (t == nil) {
b = false;
} else {
switch (t->class) {
case FILET:
case SET:
case BADUSE:
b = false;
break;
default:
b = true;
break;
}
}
}
break;
default:
b = false;
break;
}
return b;
}
/*
* Print the name and value of a variable.
*/
public printv(s, frame)
Symbol s;
Frame frame;
{
Address addr;
int len;
Symbol t;
if (isambiguous(s) and ismodule(container(s))) {
printname(stdout, s);
printf(" = ");
} else {
printf("%s = ", symname(s));
}
/*
* Not today.
t = rtype(s->type);
if (t->class == ARRAY and not istypename(t->type, "char")) {
printf("ARRAY");
} else {
*/
if (isvarparam(s)) {
rpush(address(s, frame), sizeof(Address));
addr = pop(Address);
len = size(s->type);
} else {
addr = address(s, frame);
len = size(s);
}
if (canpush(len)) {
rpush(addr, len);
printval(s->type);
} else {
printf("*** expression too large ***");
}
/*
* Matches brace commented out above.
}
*/
}
/*
* Print out the name of a symbol.
*/
public printname(f, s)
File f;
Symbol s;
{
if (s == nil) {
fprintf(f, "(noname)");
} else if (s == program) {
fprintf(f, ".");
} else if (isredirected() or isambiguous(s)) {
printwhich(f, s);
} else {
fprintf(f, "%s", symname(s));
}
}
/*
* Print the fully specified variable that is described by the given identifer.
*/
public printwhich(f, s)
File f;
Symbol s;
{
printouter(f, container(s));
fprintf(f, "%s", symname(s));
}
/*
* Print the fully qualified name of each symbol that has the same name
* as the given symbol.
*/
public printwhereis(f, s)
File f;
Symbol s;
{
register Name n;
register Symbol t;
checkref(s);
n = s->name;
t = lookup(n);
printwhich(f, t);
t = t->next_sym;
while (t != nil) {
if (t->name == n) {
putc(' ', f);
printwhich(f, t);
}
t = t->next_sym;
}
putc('\n', f);
}
private printouter(f, s)
File f;
Symbol s;
{
Symbol outer;
if (s != nil) {
outer = container(s);
if (outer != nil and outer != program) {
printouter(f, outer);
}
fprintf(f, "%s.", symname(s));
}
}
public printdecl(s)
Symbol s;
{
checkref(s);
(*language_op(s->language, L_PRINTDECL))(s);
}
/*
* Straight dump of symbol information.
*/
public psym(s)
Symbol s;
{
printf("name\t%s\n", symname(s));
printf("lang\t%s\n", language_name(s->language));
printf("level\t%d\n", s->level);
printf("class\t%s\n", classname(s));
printf("type\t0x%x", s->type);
if (s->type != nil and s->type->name != nil) {
printf(" (%s)", symname(s->type));
}
printf("\nchain\t0x%x", s->chain);
if (s->chain != nil and s->chain->name != nil) {
printf(" (%s)", symname(s->chain));
}
printf("\nblock\t0x%x", s->block);
if (s->block->name != nil) {
printf(" (");
printname(stdout, s->block);
putchar(')');
}
putchar('\n');
switch (s->class) {
case VAR:
case REF:
if (s->level >= 3) {
printf("address\t0x%x\n", s->symvalue.offset);
} else {
printf("offset\t%d\n", s->symvalue.offset);
}
printf("size\t%d\n", size(s));
break;
case RECORD:
case VARNT:
printf("size\t%d\n", s->symvalue.offset);
break;
case FIELD:
printf("offset\t%d\n", s->symvalue.field.offset);
printf("size\t%d\n", s->symvalue.field.length);
break;
case PROG:
case PROC:
case FUNC:
printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
if (isinline(s)) {
printf("inline procedure\n");
}
if (nosource(s)) {
printf("does not have source information\n");
} else {
printf("has source information\n");
}
break;
case RANGE:
prangetype(s->symvalue.rangev.lowertype);
printf("lower\t%d\n", s->symvalue.rangev.lower);
prangetype(s->symvalue.rangev.uppertype);
printf("upper\t%d\n", s->symvalue.rangev.upper);
break;
default:
/* do nothing */
break;
}
}
private prangetype(r)
Rangetype r;
{
switch (r) {
case R_CONST:
printf("CONST");
break;
case R_ARG:
printf("ARG");
break;
case R_TEMP:
printf("TEMP");
break;
case R_ADJUST:
printf("ADJUST");
break;
}
}
/*
* Print out the value on top of the stack according to the given type.
*/
public printval(t)
Symbol t;
{
Symbol s;
checkref(t);
if (t->class == TYPEREF) {
resolveRef(t);
}
switch (t->class) {
case PROC:
case FUNC:
s = pop(Symbol);
printf("%s", symname(s));
break;
default:
if (t->language == nil) {
error("unknown language");
} else if (t->language == primlang) {
(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
} else {
(*language_op(t->language, L_PRINTVAL))(t);
}
break;
}
}
/*
* Print out the value of a record, field by field.
*/
public printrecord(s)
Symbol s;
{
Symbol f;
if (s->chain == nil) {
error("record has no fields");
}
printf("(");
sp -= size(s);
f = s->chain;
if (f != nil) {
for (;;) {
printfield(f);
f = f->chain;
if (f == nil) break;
printf(", ");
}
}
printf(")");
}
/*
* Print out a field.
*/
private printfield(f)
Symbol f;
{
Stack *savesp;
register int off, len;
printf("%s = ", symname(f));
savesp = sp;
off = f->symvalue.field.offset;
len = f->symvalue.field.length;
sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
printval(f);
sp = savesp;
}
/*
* Print out the contents of an array.
* Haven't quite figured out what the best format is.
*
* This is rather inefficient.
*
* The "2*elsize" is there since "printval" drops the stack by elsize.
*/
public printarray(a)
Symbol a;
{
Stack *savesp, *newsp;
Symbol eltype;
long elsize;
String sep;
savesp = sp;
sp -= (size(a));
newsp = sp;
eltype = rtype(a->type);
elsize = size(eltype);
printf("(");
if (eltype->class == RECORD or eltype->class == ARRAY or
eltype->class == VARNT) {
sep = "\n";
putchar('\n');
} else {
sep = ", ";
}
for (sp += elsize; sp <= savesp; sp += 2*elsize) {
if (sp - elsize != newsp) {
fputs(sep, stdout);
}
printval(eltype);
}
sp = newsp;
if (streq(sep, "\n")) {
putchar('\n');
}
printf(")");
}
/*
* Print out the value of a real number in Pascal notation.
* This is, unfortunately, different than what one gets
* from "%g" in printf.
*/
public prtreal(r)
double r;
{
extern char *index();
char buf[256];
sprintf(buf, "%g", r);
if (buf[0] == '.') {
printf("0%s", buf);
} else if (buf[0] == '-' and buf[1] == '.') {
printf("-0%s", &buf[1]);
} else {
printf("%s", buf);
}
if (index(buf, '.') == nil) {
printf(".0");
}
}
/*
* Print out a character using ^? notation for unprintables.
*/
public printchar(c)
char c;
{
if (c == 0) {
putchar('\\');
putchar('0');
} else if (c == '\n') {
putchar('\\');
putchar('n');
} else if (c > 0 and c < ' ') {
putchar('^');
putchar(c - 1 + 'A');
} else if (c >= ' ' && c <= '~') {
putchar(c);
} else {
printf("\\0%o",c);
}
}