/* Copyright (c) 1982 Regents of the University of California */
static char sccsid
[] = "@(#)c.c 1.7 %G%";
* C-dependent symbol routines.
#define isdouble(range) ( \
range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \
#define isrange(t, name) (t->class == RANGE and istypename(t->type, name))
* Initialize C language information.
lang
= language_define("c", ".c");
language_setop(lang
, L_PRINTDECL
, c_printdecl
);
language_setop(lang
, L_PRINTVAL
, c_printval
);
language_setop(lang
, L_TYPEMATCH
, c_typematch
);
language_setop(lang
, L_BUILDAREF
, c_buildaref
);
language_setop(lang
, L_EVALAREF
, c_evalaref
);
* Test if two types are compatible.
public Boolean
c_typematch(type1
, type2
)
register Symbol t1
, t2
, tmp
;
if (t1
->type
== t_char
or t1
->type
== t_int
or t1
->type
== t_real
) {
(t2
->type
== t_int
or t2
->type
== t_char
)
(t2
->type
== t_char
or t2
->type
== t_int
)
t1
->class == RANGE
and isdouble(t1
) and t2
->type
== t_real
t1
->type
== t2
->type
and (
(t1
->class == t2
->class) or
(t1
->class == SCAL
and t2
->class == CONST
) or
(t1
->class == CONST
and t2
->class == SCAL
)
* Decide if a field is a bit field.
private Boolean
isbitfield(s
)
register Integer off
, len
;
off
= s
->symvalue
.field
.offset
;
len
= s
->symvalue
.field
.length
;
if ((off mod BITSPERBYTE
) != 0 or (len mod BITSPERBYTE
) != 0) {
(t
->class == SCAL
and len
!= (sizeof(int)*BITSPERBYTE
) or
len
!= (size(t
)*BITSPERBYTE
)
* Print out the declaration of a C variable.
private printdecl(s
, indent
)
Boolean semicolon
, newline
;
printf("%*c", indent
, ' ');
if (s
->type
->class == SCAL
) {
printf("(enumeration constant, ord %ld)",
printf("const %s = ", symname(s
));
} else if (s
->level
< 0) {
if (s
->type
->class == ARRAY
) {
printtype(s
->type
, s
->type
->type
, indent
);
t
= rtype(s
->type
->chain
);
assert(t
->class == RANGE
);
printf(" %s[%d]", symname(s
), t
->symvalue
.rangev
.upper
+ 1);
printtype(s
, s
->type
, indent
);
if (s
->type
->class != PTR
) {
printf("%s", symname(s
));
if (s
->type
->class == ARRAY
) {
printtype(s
->type
, s
->type
->type
, indent
);
t
= rtype(s
->type
->chain
);
assert(t
->class == RANGE
);
printf(" %s[%d]", symname(s
), t
->symvalue
.rangev
.upper
+ 1);
printtype(s
, s
->type
, indent
);
if (s
->type
->class != PTR
) {
printf("%s", symname(s
));
printf(" : %d", s
->symvalue
.field
.length
);
error("unexpected missing type information");
printtype(s
, s
->type
, indent
);
printf("%s", symname(s
));
if (not istypename(s
->type
, "void")) {
printtype(s
, s
->type
, indent
);
printf("%s", symname(s
));
printf("source file \"%s.c\"", symname(s
));
printf("executable file \"%s\"", symname(s
));
error("class %s in c_printdecl", classname(s
));
* Recursive whiz-bang procedure to print the type portion
* The symbol associated with the type is passed to allow
* searching for type names without getting "type blah = blah".
private printtype(s
, t
, indent
)
panic("printtype: class %s", classname(t
));
printtype(t
, t
->type
, indent
);
printf("%s ", c_classname(t
));
if (s
->name
!= nil
and s
->class == TAG
) {
if (p
[0] == '$' and p
[1] == '$') {
printf("{\n", t
->class == RECORD
? "struct" : "union");
for (i
= t
->chain
; i
!= nil
; i
= i
->chain
) {
assert(i
->class == FIELD
);
printf("%*c", indent
, ' ');
r0
= t
->symvalue
.rangev
.lower
;
r1
= t
->symvalue
.rangev
.upper
;
if (istypename(t
->type
, "char")) {
if (r0
< 0x20 or r0
> 0x7e) {
printf("'%c'..", (char) r0
);
if (r1
< 0x20 or r1
> 0x7e) {
printf("'%c'", (char) r1
);
} else if (r0
> 0 and r1
== 0) {
printf("%ld byte real", r0
);
printf("%lu..%lu", r0
, r1
);
printf("%ld..%ld", r0
, r1
);
printtype(t
, t
->type
, indent
);
if (t
->type
->class != PTR
) {
printtype(t
, t
->type
, indent
);
printf("%s", symname(t
));
printtype(t
, t
->type
, indent
);
printf("@%s", symname(t
));
if (s
->name
!= nil
and s
->class == TAG
) {
printf("%s ", symname(s
));
printf("%s", symname(i
));
printf("unresolved tag %s", symname(t
));
printf("%s %s", c_classname(i
), symname(t
));
printf("(class %d)", t
->class);
* List the parameters of a procedure or function.
* No attempt is made to combine like types.
for (t
= s
->chain
; t
!= nil
; t
= t
->chain
) {
printf("%s", symname(t
));
for (t
= s
->chain
; t
!= nil
; t
= t
->chain
) {
panic("unexpected class %d for parameter", t
->class);
* Print out the value on the top of the expression stack
* in the format for the type of the given symbol.
len
= s
->symvalue
.field
.length
;
if (len
<= BITSPERBYTE
) {
} else if (len
<= sizeof(short)*BITSPERBYTE
) {
i
>>= (s
->symvalue
.field
.offset mod BITSPERBYTE
);
if (t
->class == RANGE
and istypename(t
->type
, "char")) {
printf("\"%.*s\"", len
, sp
);
if (istypename(s
->type
, "boolean")) {
printrange(popsmall(s
), s
);
} else if (istypename(s
->type
, "char")) {
printrange(pop(char), s
);
} else if (isdouble(s
)) {
switch (s
->symvalue
.rangev
.lower
) {
panic("bad real size %d", t
->symvalue
.rangev
.lower
);
printrange(popsmall(s
), s
);
} else if (t
->class == RANGE
and istypename(t
->type
, "char")) {
if (ord(s
->class) > ord(TYPEREF
)) {
panic("printval: bad class %d", ord(s
->class));
printf("<%s>", c_classname(s
));
* Print out a C structure.
register Integer n
, off
, len
;
off
= f
->symvalue
.field
.offset
;
len
= f
->symvalue
.field
.length
;
n
= (off
+ len
+ 7) div BITSPERBYTE
;
printf("%s = ", symname(f
));
* Print out a range type (integer, char, or boolean).
if (istypename(t
->type
, "boolean")) {
printf(((Boolean
) i
) == true ? "true" : "false");
} else if (istypename(t
->type
, "char")) {
} else if (t
->symvalue
.rangev
.lower
>= 0) {
* Print out a null-terminated string (pointer to char)
* starting at the given address.
private printstring(addr
)
register Boolean endofstring
;
while (not endofstring
) {
} while (i
< sizeof(Word
) and not endofstring
);
* Print out an enumerated value by finding the corresponding
* name in the enumeration list.
while (e
!= nil
and e
->symvalue
.iconval
!= i
) {
printf("%s", symname(e
));
* Return the C name for the particular class of a symbol.
public String
c_classname(s
)
public Node
c_buildaref(a
, slist
)
Symbol etype
, atype
, eltype
;
if (not compatible(p
->nodetype
, t_int
)) {
fprintf(stderr
, "bad type for subscript of ");
r
= build(O_MUL
, p
, build(O_LCON
, (long) size(eltype
)));
r
= build(O_ADD
, build(O_RVAL
, a
), r
);
} else if (t
->class != ARRAY
) {
fprintf(stderr
, " is not an array");
for (; p
!= nil
and t
!= nil
; p
= p
->value
.arg
[1], t
= t
->chain
) {
etype
= rtype(esub
->nodetype
);
if (not compatible(atype
, etype
)) {
fprintf(stderr
, "subscript ");
fprintf(stderr
, " is the wrong type");
r
= build(O_INDEX
, r
, esub
);
if (p
!= nil
or t
!= nil
) {
fprintf(stderr
, "too many subscripts for ");
fprintf(stderr
, "not enough subscripts for ");
* Evaluate a subscript index.
public int c_evalaref(s
, i
)
lb
= s
->symvalue
.rangev
.lower
;
ub
= s
->symvalue
.rangev
.upper
;
error("subscript out of range");