* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)printsym.c 5.5 (Berkeley) %G%";
static char rcsid
[] = "$Header: printsym.c,v 1.4 87/04/15 00:23:35 donn Exp $";
* Printing of symbolic information.
* 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.
* 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", "array",
"dynarray", "subarray", "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
)
return clname
[ord(s
->class)];
* Note the entry of the given block, unless it's the main program.
printf("\nentering %s ", classname(s
));
* Note the exit of the given block
printf("leaving %s ", classname(s
));
* Note the call of s from t.
printf(" from %s ", classname(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.
if (s
->class == FUNC
&& (!istypename(s
->type
,"void"))) {
isindirect
= (Boolean
) (t
->class == RECORD
or t
->class == VARNT
);
pushretval(len
, isindirect
);
printf("(value too large) ");
* 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
)
if (param
!= nil
or n
> 0) {
s
= psize(param
) div
sizeof(Word
);
printparamv(param
, frame
);
printf("0x%x", argn(n
- m
, frame
));
* 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
)
* Print out a parameter value.
* Since this is intended to be printed on a single line with other information
* aggregate values are not printed.
public printparamv (p
, frame
)
if (compatible(t
, t_char
)) {
printf("%s = (...)", symname(p
));
printf("%s = (...)", symname(p
));
* Print the name and value of a variable.
if (isambiguous(s
) and ismodule(container(s
))) {
printf("%s = ", symname(s
));
if (isvarparam(s
) and not isopenarray(s
)) {
rpush(address(s
, frame
), sizeof(Address
));
addr
= address(s
, frame
);
printf("*** expression too large ***");
* Print out the name of a symbol.
} else if (s
== program
) {
} else if (isredirected() or isambiguous(s
)) {
fprintf(f
, "%s", symname(s
));
* Print the fully specified variable that is described by the given identifer.
printouter(f
, container(s
));
fprintf(f
, "%s", symname(s
));
* Print the fully qualified name of each symbol that has the same name
public printwhereis(f
, s
)
if (outer
!= nil
and outer
!= program
) {
fprintf(f
, "%s.", symname(s
));
if (s
->language
== nil
or s
->language
== primlang
) {
lang
= findlanguage(".s");
(*language_op(lang
, L_PRINTDECL
))(s
);
* Straight dump of symbol information.
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
!= nil
and s
->block
->name
!= nil
) {
printname(stdout
, s
->block
);
printf("size\t%d\n", size(s
));
printf("reg\t%d\n", s
->symvalue
.offset
);
printf("offset\t%d\n", s
->symvalue
.offset
);
printf("address\t0x%x\n", s
->symvalue
.offset
);
printf("size\t%d\n", size(s
));
printf("size\t%d\n", s
->symvalue
.offset
);
printf("offset\t%d\n", s
->symvalue
.field
.offset
);
printf("size\t%d\n", s
->symvalue
.field
.length
);
printf("address\t0x%x\n", s
->symvalue
.funcv
.beginaddr
);
printf("inline procedure\n");
printf("does not have source information\n");
printf("has source information\n");
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
);
* Print out the value on top of the stack according to the given type.
if (t
->class == TYPEREF
) {
printf("%s", symname(s
));
if (t
->language
== nil
or t
->language
== primlang
) {
(*language_op(findlanguage(".c"), L_PRINTVAL
))(t
);
(*language_op(t
->language
, L_PRINTVAL
))(t
);
* Print out the value of a record, field by field.
error("record has no fields");
printf("%s = ", symname(f
));
off
= f
->symvalue
.field
.offset
;
len
= f
->symvalue
.field
.length
;
sp
+= ((off
+ len
+ BITSPERBYTE
- 1) div BITSPERBYTE
);
* 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.
if (eltype
->class == RECORD
or eltype
->class == ARRAY
or
eltype
->class == VARNT
) {
for (sp
+= elsize
; sp
<= savesp
; sp
+= 2*elsize
) {
if (sp
- elsize
!= newsp
) {
* Print out the value of a real number in Pascal notation.
* This is, unfortunately, different than what one gets
} else if (buf
[0] == '-' and buf
[1] == '.') {
if (index(buf
, '.') == nil
) {
* Print out a character using ^? notation for unprintables.
} else if (c
> 0 and c
< ' ') {
} else if (c
>= ' ' && c
<= '~') {
* Print out a value for a range type (integer, char, or boolean).
public printRangeVal (val
, t
)
if (t
== t_boolean
->type
or istypename(t
->type
, "boolean")) {
} else if (t
== t_char
->type
or istypename(t
->type
, "char")) {
if (varIsSet("$hexchars")) {
} else if (varIsSet("$hexints")) {
} else if (t
->symvalue
.rangev
.lower
>= 0) {
* Print out an enumerated value by finding the corresponding
* name in the enumeration list.
while (e
!= nil
and e
->symvalue
.constval
->value
.lcon
!= i
) {
printf("%s", symname(e
));
* Print out a null-terminated string (pointer to char)
* starting at the given address.
public printString (addr
, quotes
)
register boolean endofstring
;
register int unprintables
;
if (varIsSet("$hexstrings")) {
while (not endofstring
) {
if (!isascii(u
.ch
[i
]) and ++unprintables
> MAXGARBAGE
) {
} while (i
< sizeof(Word
) and not endofstring
);