|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <assert.h>
|
#include <assert.h>
|
#include "Node.hh"
|
#include "Node.hh"
|
#include "Name.hh"
|
#include "Name.hh"
|
#include "Backend.hh"
|
#include "Backend.hh"
|
|
|
int Node::indent = 0;
|
int Node::indent = 0;
|
int Node::semantic_errors = 0;
|
int Node::semantic_errors = 0;
|
|
|
int Enumerator::current = 0;
|
int Enumerator::current = 0;
|
int TypeSpecifier::anonymous_number = 1;
|
int TypeSpecifier::anonymous_number = 1;
|
|
|
extern FILE * out;
|
extern FILE * out;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void NumericConstant::EmitValue_RR(FILE * out)
|
void NumericConstant::EmitValue_RR(FILE * out)
|
{
|
{
|
Backend::load_rr_constant(value);
|
Backend::load_rr_constant(value);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void NumericConstant::EmitValue_LL(FILE * out)
|
void NumericConstant::EmitValue_LL(FILE * out)
|
{
|
{
|
Backend::load_ll_constant(value);
|
Backend::load_ll_constant(value);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StringConstant::EmitValue_RR(FILE * out)
|
void StringConstant::EmitValue_RR(FILE * out)
|
{
|
{
|
Backend::load_rr_string(string_number, 0);
|
Backend::load_rr_string(string_number, 0);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StringConstant::EmitValue_LL(FILE * out)
|
void StringConstant::EmitValue_LL(FILE * out)
|
{
|
{
|
Backend::load_ll_string(string_number, 0);
|
Backend::load_ll_string(string_number, 0);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Node::Node(const char * ntype)
|
Node::Node(const char * ntype)
|
: node_type(ntype)
|
: node_type(ntype)
|
{
|
{
|
// printf("Creating %s\n", node_type);
|
// printf("Creating %s\n", node_type);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Node::Emit(FILE * out)
|
void Node::Emit(FILE * out)
|
{
|
{
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "MISSING : %s\n", node_type);
|
fprintf(out, "MISSING : %s\n", node_type);
|
fprintf(stderr, "\n\nMISSING : %s::Emit()\n\n", node_type);
|
fprintf(stderr, "\n\nMISSING : %s::Emit()\n\n", node_type);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Node::EmitIndent(FILE * out)
|
void Node::EmitIndent(FILE * out)
|
{
|
{
|
fprintf(out, ";;; ");
|
fprintf(out, ";;; ");
|
for (int i = 0; i < indent; i++) fprintf(out, " ");
|
for (int i = 0; i < indent; i++) fprintf(out, " ");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Node::EmitStart(FILE * out)
|
void Node::EmitStart(FILE * out)
|
{
|
{
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "{ %d %s\n", indent, node_type);
|
fprintf(out, "{ %d %s\n", indent, node_type);
|
indent++;
|
indent++;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Node::EmitEnd(FILE * out)
|
void Node::EmitEnd(FILE * out)
|
{
|
{
|
indent--;
|
indent--;
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "} %d %s\n", indent, node_type);
|
fprintf(out, "} %d %s\n", indent, node_type);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StatementList ::Emit(FILE * out) { EmitList(out); }
|
void StatementList ::Emit(FILE * out) { EmitList(out); }
|
void DeclarationList ::Emit(FILE * out) { EmitList(out); }
|
void DeclarationList ::Emit(FILE * out) { EmitList(out); }
|
void InitializerList ::Emit(FILE * out) { EmitList(out); }
|
void InitializerList ::Emit(FILE * out) { EmitList(out); }
|
void ParameterDeclarationList::Emit(FILE * out) { EmitList(out); }
|
void ParameterDeclarationList::Emit(FILE * out) { EmitList(out); }
|
void IdentifierList ::Emit(FILE * out) { EmitList(out); }
|
void IdentifierList ::Emit(FILE * out) { EmitList(out); }
|
void StructDeclaratorList ::Emit(FILE * out) { assert(0); }
|
void StructDeclaratorList ::Emit(FILE * out) { assert(0); }
|
void StructDeclarationList ::Emit(FILE * out) { assert(0); }
|
void StructDeclarationList ::Emit(FILE * out) { assert(0); }
|
void InitDeclaratorList ::Emit(FILE * out) { EmitList(out); }
|
void InitDeclaratorList ::Emit(FILE * out) { EmitList(out); }
|
void TypeSpecifierList ::Emit(FILE * out) { EmitList(out); }
|
void TypeSpecifierList ::Emit(FILE * out) { EmitList(out); }
|
void Declarator ::Emit(FILE * out) { EmitList(out); }
|
void Declarator ::Emit(FILE * out) { EmitList(out); }
|
void Pointer ::Emit(FILE * out) { EmitList(out); }
|
void Pointer ::Emit(FILE * out) { EmitList(out); }
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StructDeclarator::Emit(FILE * out)
|
void StructDeclarator::Emit(FILE * out)
|
{
|
{
|
assert(declarator);
|
assert(declarator);
|
EmitStart(out);
|
EmitStart(out);
|
declarator->Emit(out);
|
declarator->Emit(out);
|
if (expression)
|
if (expression)
|
{
|
{
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, " : bitfield\n");
|
fprintf(out, " : bitfield\n");
|
}
|
}
|
|
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, " at position %d\n", position);
|
fprintf(out, " at position %d\n", position);
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int StructDeclarator::EmitMember(FILE * out, const char * struct_name,
|
int StructDeclarator::EmitMember(FILE * out, const char * struct_name,
|
TypeSpecifier * tspec, int pos, bool is_union)
|
TypeSpecifier * tspec, int pos, bool is_union)
|
{
|
{
|
position = pos;
|
position = pos;
|
if (is_union) assert(position == 0);
|
if (is_union) assert(position == 0);
|
|
|
if (0)
|
if (0)
|
{
|
{
|
const char * member_name = GetDeclaredName(declarator);
|
const char * member_name = GetDeclaredName(declarator);
|
|
|
assert(struct_name);
|
assert(struct_name);
|
if (member_name == 0) member_name = "anonymous member";
|
if (member_name == 0) member_name = "anonymous member";
|
|
|
fprintf(stderr, "%s->%s at position %d\n",
|
fprintf(stderr, "%s->%s at position %d\n",
|
struct_name, member_name, position);
|
struct_name, member_name, position);
|
}
|
}
|
|
|
return tspec->GetSize(declarator);
|
return tspec->GetSize(declarator);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void EnumeratorList::Emit(FILE * out)
|
void EnumeratorList::Emit(FILE * out)
|
{
|
{
|
Enumerator::current = 0;
|
Enumerator::current = 0;
|
|
|
for (EnumeratorList * el = this; el; el = el->tail)
|
for (EnumeratorList * el = this; el; el = el->tail)
|
el->head->Emit(out);
|
el->head->Emit(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Enumerator::Emit(FILE * out)
|
void Enumerator::Emit(FILE * out)
|
{
|
{
|
assert(name);
|
assert(name);
|
|
|
int val = current++;
|
int val = current++;
|
if (value)
|
if (value)
|
{
|
{
|
if (!value->IsNumericConstant())
|
if (!value->IsNumericConstant())
|
{
|
{
|
fprintf(stderr, "enum value for %s is not constant\n", name);
|
fprintf(stderr, "enum value for %s is not constant\n", name);
|
semantic_errors++;
|
semantic_errors++;
|
}
|
}
|
else
|
else
|
{
|
{
|
val = value->GetConstantNumericValue();
|
val = value->GetConstantNumericValue();
|
current = val + 1;
|
current = val + 1;
|
}
|
}
|
}
|
}
|
Name::AddEnum(name, val);
|
Name::AddEnum(name, val);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
ParameterDeclaration::ParameterDeclaration(TypeSpecifier * ds,
|
ParameterDeclaration::ParameterDeclaration(TypeSpecifier * ds,
|
Declarator * decl)
|
Declarator * decl)
|
: Node("ParameterDeclaration"),
|
: Node("ParameterDeclaration"),
|
isEllipsis(false)
|
isEllipsis(false)
|
{
|
{
|
type = new TypeName(ds, decl);
|
type = new TypeName(ds, decl);
|
|
|
const char * pname = type->GetDeclaredName();
|
const char * pname = type->GetDeclaredName();
|
|
|
if (pname) Name::AddAuto(pname, type);
|
if (pname) Name::AddAuto(pname, type);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void ParameterDeclaration::Emit(FILE * out)
|
void ParameterDeclaration::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "isEllipsis = ");
|
fprintf(out, "isEllipsis = ");
|
if (isEllipsis) fprintf(out, "true\r\n");
|
if (isEllipsis) fprintf(out, "true\r\n");
|
else fprintf(out, "false\r\n");
|
else fprintf(out, "false\r\n");
|
type->Emit(out);
|
type->Emit(out);
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int ParameterDeclaration::AllocateParameters(int offset)
|
int ParameterDeclaration::AllocateParameters(int offset)
|
{
|
{
|
const int size = type->GetSize();
|
const int size = type->GetSize();
|
const char * pname = GetDeclaredName(0);
|
const char * pname = GetDeclaredName(0);
|
|
|
if (pname) Name::SetAutoPos(pname, offset);
|
if (pname) Name::SetAutoPos(pname, offset);
|
|
|
return size;
|
return size;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * ParameterDeclaration::GetDeclaredName(int skip)
|
const char * ParameterDeclaration::GetDeclaredName(int skip)
|
{
|
{
|
for (Declarator * d = type->GetDeclarator(); d; d = d->Tail())
|
for (Declarator * d = type->GetDeclarator(); d; d = d->Tail())
|
{
|
{
|
const char * n = d->Head()->GetName();
|
const char * n = d->Head()->GetName();
|
if (n == 0) continue;
|
if (n == 0) continue;
|
if (skip == 0) return n;
|
if (skip == 0) return n;
|
skip--;
|
skip--;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
FunctionDefinition::FunctionDefinition(TypeSpecifier * ds,
|
FunctionDefinition::FunctionDefinition(TypeSpecifier * ds,
|
Declarator * decl,
|
Declarator * decl,
|
DeclarationList * dl)
|
DeclarationList * dl)
|
: Node("FunctionDefinition"),
|
: Node("FunctionDefinition"),
|
fun_declarator(decl),
|
fun_declarator(decl),
|
decl_list(dl),
|
decl_list(dl),
|
body(0)
|
body(0)
|
{
|
{
|
// these are always present...
|
// these are always present...
|
//
|
//
|
assert(decl);
|
assert(decl);
|
|
|
// no type means int
|
// no type means int
|
//
|
//
|
if (ds == 0) ds = new TypeSpecifier(TS_INT);
|
if (ds == 0) ds = new TypeSpecifier(TS_INT);
|
|
|
Declarator * ret_decl = 0;
|
Declarator * ret_decl = 0;
|
|
|
// copy decl to ret_decl up to FUN_DECL
|
// copy decl to ret_decl up to FUN_DECL
|
//
|
//
|
for (Declarator * d = decl; d; d = d->Tail())
|
for (Declarator * d = decl; d; d = d->Tail())
|
{
|
{
|
DeclItem * di = d->Head();
|
DeclItem * di = d->Head();
|
assert(di);
|
assert(di);
|
if (di->GetWhat() == DECL_FUN) break;
|
if (di->GetWhat() == DECL_FUN) break;
|
ret_decl = new Declarator(di, ret_decl);
|
ret_decl = new Declarator(di, ret_decl);
|
}
|
}
|
|
|
const char * fun_name = ::GetDeclaredName(fun_declarator);
|
const char * fun_name = ::GetDeclaredName(fun_declarator);
|
assert(fun_name);
|
assert(fun_name);
|
|
|
ret_type = new TypeName(ds, ret_decl);
|
ret_type = new TypeName(ds, ret_decl);
|
|
|
TypeName * fun_type = new TypeName(ds, fun_declarator);
|
TypeName * fun_type = new TypeName(ds, fun_declarator);
|
Name::AddLocal(fun_name, fun_type);
|
Name::AddLocal(fun_name, fun_type);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void FunctionDefinition::Emit(FILE * out)
|
void FunctionDefinition::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(ret_type);
|
assert(ret_type);
|
ret_type->Emit(out);
|
ret_type->Emit(out);
|
|
|
assert(fun_declarator);
|
assert(fun_declarator);
|
fun_declarator->Emit(out);
|
fun_declarator->Emit(out);
|
|
|
if (decl_list) decl_list->Emit(out);
|
if (decl_list) decl_list->Emit(out);
|
|
|
assert(body);
|
assert(body);
|
|
|
const char * funname = GetDeclaredName(fun_declarator);
|
const char * funname = GetDeclaredName(fun_declarator);
|
assert(funname);
|
assert(funname);
|
Backend::new_function(funname);
|
Backend::new_function(funname);
|
|
|
int ret_size = ret_type->GetSize();
|
int ret_size = ret_type->GetSize();
|
if (ret_size <= 4) ret_size = 0; // return value in register
|
if (ret_size <= 4) ret_size = 0; // return value in register
|
ret_size += 2; // call return address
|
ret_size += 2; // return address
|
|
|
ParameterDeclarationList * pdl = ::GetParameters(fun_declarator);
|
ParameterDeclarationList * pdl = ::GetParameters(fun_declarator);
|
|
|
int offset = ret_size;
|
int offset = ret_size;
|
for (ParameterDeclarationList * p = pdl; p; p = p->Tail())
|
for (ParameterDeclarationList * p = pdl; p; p = p->Tail())
|
{
|
{
|
ParameterDeclaration * pd = p->Head();
|
ParameterDeclaration * pd = p->Head();
|
assert(pd);
|
assert(pd);
|
offset += pd->AllocateParameters(offset);
|
offset += pd->AllocateParameters(offset);
|
}
|
}
|
|
|
const int autosize = body->EmitAutovars(out);
|
|
|
|
body->Emit(out);
|
body->Emit(out);
|
Backend::ret(autosize);
|
|
EmitEnd(out);
|
|
|
|
|
Backend::ret();
|
Name::RemoveAuto();
|
Name::RemoveAuto();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void InitDeclarator::Emit(FILE * out)
|
void InitDeclarator::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
if (declarator) declarator->Emit(out);
|
if (declarator) declarator->Emit(out);
|
// don't emit initializer
|
// don't emit initializer
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * InitDeclarator::GetDeclaredName(int skip)
|
const char * InitDeclarator::GetDeclaredName(int skip)
|
{
|
{
|
const char * ret = ::GetDeclaredName(declarator);
|
const char * ret = ::GetDeclaredName(declarator);
|
|
|
assert(ret);
|
assert(ret);
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int InitDeclarator::EmitAutovars(FILE * out, TypeSpecifier * typespec)
|
int InitDeclarator::EmitAutovars(FILE * out, TypeSpecifier * typespec)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
assert(declarator);
|
assert(declarator);
|
declarator->Emit(out);
|
declarator->Emit(out);
|
|
|
assert(typespec);
|
assert(typespec);
|
TypeName type(typespec, declarator);
|
TypeName type(typespec, declarator);
|
const Specifier spec = typespec->GetType();
|
const Specifier spec = typespec->GetType();
|
|
|
assert(!(spec & SC_TYPEDEF));
|
assert(!(spec & SC_TYPEDEF));
|
assert(!(spec & SC_EXTERN));
|
assert(!(spec & SC_EXTERN));
|
|
|
const int size = typespec->GetSize(declarator);
|
const int size = typespec->GetSize(declarator);
|
const char * name = ::GetDeclaredName(declarator);
|
const char * name = ::GetDeclaredName(declarator);
|
assert(name);
|
assert(name);
|
|
|
Name::SetAutoPos(name, Backend::GetSP() - size);
|
Name::SetAutoPos(name, Backend::GetSP() - size);
|
|
|
const int ret = typespec->GetSize(declarator);
|
const int ret = typespec->GetSize(declarator);
|
if (ret < 0)
|
if (ret < 0)
|
{
|
{
|
type.Print(stderr);
|
type.Print(stderr);
|
assert(0);
|
assert(0);
|
}
|
}
|
|
|
if (initializer) initializer->InitAutovar(out, type.GetSUW());
|
if (initializer) initializer->InitAutovar(out, type.GetSUW());
|
else Backend::push_zero(ret);
|
else Backend::push_zero(ret);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void InitDeclarator::Allocate(FILE * out, TypeSpecifier * typespec)
|
void InitDeclarator::Allocate(FILE * out, TypeSpecifier * typespec)
|
{
|
{
|
const Specifier spec = typespec->GetType();
|
const Specifier spec = typespec->GetType();
|
|
|
if (spec & SC_TYPEDEF) return;
|
if (spec & SC_TYPEDEF) return;
|
|
|
const char * name = ::GetDeclaredName(declarator);
|
const char * name = ::GetDeclaredName(declarator);
|
assert(name);
|
assert(name);
|
|
|
if (spec & SC_EXTERN)
|
if (spec & SC_EXTERN)
|
{
|
{
|
fprintf(out, "\t.EXTERN\tC%s\n", name);
|
fprintf(out, "\t.EXTERN\tC%s\n", name);
|
}
|
}
|
else if (spec & SC_STATIC)
|
else if (spec & SC_STATIC)
|
{
|
{
|
// forward declaration
|
// forward declaration
|
fprintf(out, "\t.STATIC\tC%s\n", name);
|
fprintf(out, "\t.STATIC\tC%s\n", name);
|
}
|
}
|
else if (!IsFunction(declarator))
|
else if (!IsFunction(declarator))
|
{
|
{
|
fprintf(out, "C%s:\t\t\t; \n", name);
|
fprintf(out, "C%s:\t\t\t; \n", name);
|
if (initializer)
|
if (initializer)
|
{
|
{
|
TypeName tn(typespec, declarator);
|
TypeName tn(typespec, declarator);
|
initializer->EmitValue(out, &tn);
|
initializer->EmitValue(out, &tn);
|
}
|
}
|
else
|
else
|
{
|
{
|
const int size = typespec->GetSize(declarator);
|
const int size = typespec->GetSize(declarator);
|
for (int b = 0; b < size; b++)
|
for (int b = 0; b < size; b++)
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID [%d]\r\n", b);
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID [%d]\r\n", b);
|
}
|
}
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Declaration::Declaration(TypeSpecifier * ds, InitDeclaratorList * il)
|
Declaration::Declaration(TypeSpecifier * ds, InitDeclaratorList * il)
|
: Node("Declaration"),
|
: Node("Declaration"),
|
base_type(ds),
|
base_type(ds),
|
init_list(il)
|
init_list(il)
|
{
|
{
|
assert(ds);
|
assert(ds);
|
|
|
for (InitDeclaratorList * i = init_list; i; i = i->Tail())
|
for (InitDeclaratorList * i = init_list; i; i = i->Tail())
|
{
|
{
|
InitDeclarator * id = i->Head();
|
InitDeclarator * id = i->Head();
|
assert(id);
|
assert(id);
|
Declarator * decl = id->GetDeclarator();
|
Declarator * decl = id->GetDeclarator();
|
|
|
const char * dn = ::GetDeclaredName(decl);
|
const char * dn = ::GetDeclaredName(decl);
|
assert(dn);
|
assert(dn);
|
|
|
assert(base_type);
|
assert(base_type);
|
const Specifier spec = base_type->GetType();
|
const Specifier spec = base_type->GetType();
|
|
|
if (spec & SC_TYPEDEF)
|
if (spec & SC_TYPEDEF)
|
{
|
{
|
const Specifier real_spec = (Specifier)(spec & ~SC_TYPEDEF);
|
const Specifier real_spec = (Specifier)(spec & ~SC_TYPEDEF);
|
TypeSpecifier * real_type = new TypeSpecifier(real_spec,
|
TypeSpecifier * real_type = new TypeSpecifier(real_spec,
|
base_type->GetName(),
|
base_type->GetName(),
|
base_type->GetStructDecl());
|
base_type->GetStructDecl());
|
Declarator * ret = 0;
|
Declarator * ret = 0;
|
for (Declarator * d = decl; d; d = d->Tail())
|
for (Declarator * d = decl; d; d = d->Tail())
|
{
|
{
|
DeclItem * di = d->Head();
|
DeclItem * di = d->Head();
|
assert(di);
|
assert(di);
|
if (di->GetWhat() != DECL_NAME)
|
if (di->GetWhat() != DECL_NAME)
|
ret = new Declarator(di, ret);
|
ret = new Declarator(di, ret);
|
}
|
}
|
|
|
TypeName * tn = new TypeName(real_type, ret);
|
TypeName * tn = new TypeName(real_type, ret);
|
TypedefName::Add(dn, tn);
|
TypedefName::Add(dn, tn);
|
}
|
}
|
else
|
else
|
{
|
{
|
TypeName * tn = new TypeName(base_type, decl);
|
TypeName * tn = new TypeName(base_type, decl);
|
|
|
if (spec & SC_EXTERN) Name::AddExtern(dn, tn);
|
if (spec & SC_EXTERN) Name::AddExtern(dn, tn);
|
else if (spec & SC_STATIC) Name::AddStatic(dn, tn);
|
else if (spec & SC_STATIC) Name::AddStatic(dn, tn);
|
else Name::AddAuto(dn, tn);
|
else Name::AddAuto(dn, tn);
|
}
|
}
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Declaration::Emit(FILE * out)
|
void Declaration::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
if (base_type) base_type->Emit(out);
|
if (base_type) base_type->Emit(out);
|
// if (init_list) init_list->Emit(out);
|
// if (init_list) init_list->Emit(out);
|
|
|
Allocate(out);
|
Allocate(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
Name::AutoToLocal();
|
Name::AutoToLocal();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Declaration::Allocate(FILE * out)
|
void Declaration::Allocate(FILE * out)
|
{
|
{
|
for (InitDeclaratorList * il = init_list; il; il = il->Tail())
|
for (InitDeclaratorList * il = init_list; il; il = il->Tail())
|
{
|
{
|
InitDeclarator * id = il->Head();
|
InitDeclarator * id = il->Head();
|
assert(id);
|
assert(id);
|
id->Allocate(out, base_type);
|
id->Allocate(out, base_type);
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Declaration::EmitAutovars(FILE * out)
|
int Declaration::EmitAutovars(FILE * out)
|
{
|
{
|
int ret = 0;
|
int ret = 0;
|
|
|
for (InitDeclaratorList * il = init_list; il; il = il->Tail())
|
for (InitDeclaratorList * il = init_list; il; il = il->Tail())
|
{
|
{
|
InitDeclarator * id = il->Head();
|
InitDeclarator * id = il->Head();
|
assert(id);
|
assert(id);
|
ret += id->EmitAutovars(out, base_type);
|
ret += id->EmitAutovars(out, base_type);
|
}
|
}
|
|
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Ptr::Emit(FILE * out)
|
void Ptr::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
if (decl_specs) decl_specs->Emit(out);
|
if (decl_specs) decl_specs->Emit(out);
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Initializer::Emit(FILE * out)
|
void Initializer::Emit(FILE * out)
|
{
|
{
|
// debug only: must call EmitValue() or EmitAutovars()
|
// debug only: must call EmitValue() or EmitAutovars()
|
EmitStart(out);
|
EmitStart(out);
|
if (skalar_value) skalar_value->Emit(out);
|
if (skalar_value) skalar_value->Emit(out);
|
if (array_value) array_value ->Emit(out);
|
if (array_value) array_value ->Emit(out);
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Initializer::EmitValue(FILE * out, TypeName * tn)
|
void Initializer::EmitValue(FILE * out, TypeName * tn)
|
{
|
{
|
if (tn->IsUnion())
|
if (tn->IsUnion())
|
{
|
{
|
int union_size = tn->GetSize();
|
int union_size = tn->GetSize();
|
TypeName * first = tn->FirstUnionMember(union_size);
|
TypeName * first = tn->FirstUnionMember(union_size);
|
if (first) EmitValue(out, first);
|
if (first) EmitValue(out, first);
|
return;
|
return;
|
}
|
}
|
|
|
if (skalar_value)
|
if (skalar_value)
|
{
|
{
|
if (tn->IsArray()) // char x[] = "abc" ?
|
if (tn->IsArray()) // char x[] = "abc" ?
|
{
|
{
|
if (tn->GetElementType()->GetSize() != 1)
|
if (tn->GetElementType()->GetSize() != 1)
|
{
|
{
|
fprintf(stderr,
|
fprintf(stderr,
|
"Initialization of array with skalar or string\n");
|
"Initialization of array with skalar or string\n");
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
if (!skalar_value->IsStringConstant())
|
if (!skalar_value->IsStringConstant())
|
{
|
{
|
fprintf(stderr,
|
fprintf(stderr,
|
"Initialization of char array with non-string\n");
|
"Initialization of char array with non-string\n");
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
int len = tn->GetSize();
|
int len = tn->GetSize();
|
if (len == -1)
|
if (len == -1)
|
{
|
{
|
len = skalar_value->GetSize(); // x[] = "..."
|
len = skalar_value->GetSize(); // x[] = "..."
|
tn->SetArrayLength(len);
|
tn->SetArrayLength(len);
|
}
|
}
|
|
|
StringConstant * sc = skalar_value->GetStringConstant();
|
StringConstant * sc = skalar_value->GetStringConstant();
|
assert(sc);
|
assert(sc);
|
sc->EmitAndRemove(out, len);
|
sc->EmitAndRemove(out, len);
|
return;
|
return;
|
}
|
}
|
|
|
skalar_value->EmitInitialization(out, tn->GetSize());
|
skalar_value->EmitInitialization(out, tn->GetSize());
|
return;
|
return;
|
}
|
}
|
|
|
assert(array_value);
|
assert(array_value);
|
|
|
// array or struct...
|
// array or struct...
|
// check for array
|
// check for array
|
//
|
//
|
if (tn->IsArray())
|
if (tn->IsArray())
|
{
|
{
|
int elements;
|
int elements;
|
Expression * alen = tn->ArrayLength();
|
Expression * alen = tn->ArrayLength();
|
if (alen) // a[len]
|
if (alen) // a[len]
|
{
|
{
|
elements = alen->GetConstantNumericValue();
|
elements = alen->GetConstantNumericValue();
|
}
|
}
|
else // a[]
|
else // a[]
|
{
|
{
|
elements = List<Initializer>::Length(array_value);
|
elements = List<Initializer>::Length(array_value);
|
tn->SetArrayLength(elements);
|
tn->SetArrayLength(elements);
|
}
|
}
|
|
|
TypeName * etype = tn->GetElementType();
|
TypeName * etype = tn->GetElementType();
|
assert(etype);
|
assert(etype);
|
const int size = etype->GetSize();
|
const int size = etype->GetSize();
|
int done = 0;
|
int done = 0;
|
|
|
for (InitializerList * il = array_value; il; il = il->Tail())
|
for (InitializerList * il = array_value; il; il = il->Tail())
|
{
|
{
|
if (done == elements)
|
if (done == elements)
|
{
|
{
|
fprintf(stderr, "Too many array initializers\n");
|
fprintf(stderr, "Too many array initializers\n");
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
Initializer * in = il->Head();
|
Initializer * in = il->Head();
|
assert(in);
|
assert(in);
|
in->EmitValue(out, etype);
|
in->EmitValue(out, etype);
|
done++;
|
done++;
|
}
|
}
|
|
|
// init unspecified array elements to 0
|
// init unspecified array elements to 0
|
//
|
//
|
for (int b = done; b < elements; b++)
|
for (int b = done; b < elements; b++)
|
{
|
{
|
if (size == 1)
|
if (size == 1)
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID[%d]\r\n", b);
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID[%d]\r\n", b);
|
else if (size == 2)
|
else if (size == 2)
|
fprintf(out, "\t.WORD\t0\t\t\t; VOID[%d]\r\n", b);
|
fprintf(out, "\t.WORD\t0\t\t\t; VOID[%d]\r\n", b);
|
else
|
else
|
{
|
{
|
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID[%d]\r\n", b);
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID[%d]\r\n", b);
|
}
|
}
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
// struct...
|
// struct...
|
//
|
//
|
if (!tn->IsStruct())
|
if (!tn->IsStruct())
|
{
|
{
|
fprintf(stderr, "Initialization of skalar type with array\n");
|
fprintf(stderr, "Initialization of skalar type with array\n");
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
TypeSpecifier * ts = tn->GetTypeSpecifier();
|
TypeSpecifier * ts = tn->GetTypeSpecifier();
|
assert(ts);
|
assert(ts);
|
|
|
const char * sname = ts->GetName();
|
const char * sname = ts->GetName();
|
if (sname == 0)
|
if (sname == 0)
|
{
|
{
|
fprintf(stderr, "No struct name in struct initializer\n");
|
fprintf(stderr, "No struct name in struct initializer\n");
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
StructDeclarationList * sdl = StructName::Find(sname);
|
StructDeclarationList * sdl = StructName::Find(sname);
|
if (sdl == 0)
|
if (sdl == 0)
|
{
|
{
|
fprintf(stderr, "No struct %s defined\n", sname);
|
fprintf(stderr, "No struct %s defined\n", sname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
InitializerList * il = array_value;
|
InitializerList * il = array_value;
|
|
|
for (; sdl; sdl = sdl->Tail())
|
for (; sdl; sdl = sdl->Tail())
|
{
|
{
|
StructDeclaration * sd = sdl->Head();
|
StructDeclaration * sd = sdl->Head();
|
assert(sd);
|
assert(sd);
|
TypeSpecifier * ts = sd->GetSpecifier();
|
TypeSpecifier * ts = sd->GetSpecifier();
|
assert(ts);
|
assert(ts);
|
|
|
for (StructDeclaratorList * sr = sd->GetDeclarators(); sr;
|
for (StructDeclaratorList * sr = sd->GetDeclarators(); sr;
|
sr = sr->Tail())
|
sr = sr->Tail())
|
{
|
{
|
StructDeclarator * sor = sr->Head();
|
StructDeclarator * sor = sr->Head();
|
assert(sor);
|
assert(sor);
|
|
|
Declarator * decl = sor->GetDeclarator();
|
Declarator * decl = sor->GetDeclarator();
|
assert(decl);
|
assert(decl);
|
|
|
const char * membname = sor->GetMemberName();
|
const char * membname = sor->GetMemberName();
|
if (membname == 0) membname = "anonymous";
|
if (membname == 0) membname = "anonymous";
|
|
|
TypeName type(ts, decl);
|
TypeName type(ts, decl);
|
if (il == 0)
|
if (il == 0)
|
{
|
{
|
const int size = type.GetSize();
|
const int size = type.GetSize();
|
if (size == 1)
|
if (size == 1)
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID %s\r\n", membname);
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID %s\r\n", membname);
|
else if (size == 2)
|
else if (size == 2)
|
fprintf(out, "\t.WORD\t0\t\t\t; VOID %s\r\n", membname);
|
fprintf(out, "\t.WORD\t0\t\t\t; VOID %s\r\n", membname);
|
else
|
else
|
{
|
{
|
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID %s\r\n", membname);
|
fprintf(out, "\t.BYTE\t0\t\t\t; VOID %s\r\n", membname);
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
Initializer * ini = il->Head();
|
Initializer * ini = il->Head();
|
assert(ini);
|
assert(ini);
|
il = il->Tail();
|
il = il->Tail();
|
ini->EmitValue(out, &type);
|
ini->EmitValue(out, &type);
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Initializer::InitAutovar(FILE * out, SUW suw)
|
int Initializer::InitAutovar(FILE * out, SUW suw)
|
{
|
{
|
int ret = 0;
|
int ret = 0;
|
|
|
assert( skalar_value || array_value);
|
assert( skalar_value || array_value);
|
assert(!skalar_value || !array_value);
|
assert(!skalar_value || !array_value);
|
|
|
EmitStart(out);
|
EmitStart(out);
|
|
|
if (skalar_value)
|
if (skalar_value)
|
{
|
{
|
ret = 1; if (suw == WO) ret = 2;
|
ret = 1; if (suw == WO) ret = 2;
|
|
|
if (skalar_value->IsNumericConstant())
|
if (skalar_value->IsNumericConstant())
|
{
|
{
|
int value = skalar_value->GetConstantNumericValue();
|
int value = skalar_value->GetConstantNumericValue();
|
if (value == 0)
|
if (value == 0)
|
{
|
{
|
Backend::push_zero(ret);
|
Backend::push_zero(ret);
|
}
|
}
|
else
|
else
|
{
|
{
|
skalar_value->Emit(out);
|
skalar_value->Emit(out);
|
Backend::push_rr(suw);
|
Backend::push_rr(suw);
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
skalar_value->Emit(out);
|
skalar_value->Emit(out);
|
Backend::push_rr(suw);
|
Backend::push_rr(suw);
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
fprintf(stderr, "TODO: aggregate initializer\r\n");
|
fprintf(stderr, "TODO: aggregate initializer\r\n");
|
}
|
}
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeSpecifier::GetMemberType(const char * member)
|
TypeName * TypeSpecifier::GetMemberType(const char * member)
|
{
|
{
|
const int is_union = spec & TS_UNION;
|
const int is_union = spec & TS_UNION;
|
const int is_struct = spec & TS_STRUCT;
|
const int is_struct = spec & TS_STRUCT;
|
|
|
if (!is_union && !is_struct)
|
if (!is_union && !is_struct)
|
{
|
{
|
fprintf(stderr, "access member %s of non-aggregate\n", member);
|
fprintf(stderr, "access member %s of non-aggregate\n", member);
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
StructDeclarationList * sdl = StructName::Find(name);
|
StructDeclarationList * sdl = StructName::Find(name);
|
if (sdl == 0)
|
if (sdl == 0)
|
{
|
{
|
fprintf(stderr, "No struct %s defined\n", name);
|
fprintf(stderr, "No struct %s defined\n", name);
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
for (; sdl ; sdl = sdl->Tail())
|
for (; sdl ; sdl = sdl->Tail())
|
{
|
{
|
StructDeclaration * sd = sdl->Head();
|
StructDeclaration * sd = sdl->Head();
|
assert(sd);
|
assert(sd);
|
TypeName * st = sd->GetMemberType(name, member);
|
TypeName * st = sd->GetMemberType(name, member);
|
if (st) return st;
|
if (st) return st;
|
}
|
}
|
|
|
fprintf(stderr, "aggregate %s has no member %s\n", name, member);
|
fprintf(stderr, "aggregate %s has no member %s\n", name, member);
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int StructDeclaration::Emit(FILE * out, const char * struct_name, int pos,
|
int StructDeclaration::Emit(FILE * out, const char * struct_name, int pos,
|
bool is_union)
|
bool is_union)
|
{
|
{
|
size = 0;
|
size = 0;
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
{
|
{
|
StructDeclarator * sd = sl->Head();
|
StructDeclarator * sd = sl->Head();
|
assert(sd);
|
assert(sd);
|
|
|
if (is_union)
|
if (is_union)
|
{
|
{
|
int tsize = sd->EmitMember(out, struct_name,
|
int tsize = sd->EmitMember(out, struct_name,
|
decl_specifiers, 0, true);
|
decl_specifiers, 0, true);
|
if (size < tsize) size = tsize;
|
if (size < tsize) size = tsize;
|
}
|
}
|
else
|
else
|
{
|
{
|
size += sd->EmitMember(out, struct_name,
|
size += sd->EmitMember(out, struct_name,
|
decl_specifiers, pos + size, false);
|
decl_specifiers, pos + size, false);
|
}
|
}
|
}
|
}
|
|
|
return size;
|
return size;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * StructDeclaration::GetMemberType(const char * struct_name,
|
TypeName * StructDeclaration::GetMemberType(const char * struct_name,
|
const char * member)
|
const char * member)
|
{
|
{
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
{
|
{
|
StructDeclarator * sd = sl->Head();
|
StructDeclarator * sd = sl->Head();
|
assert(sd);
|
assert(sd);
|
TypeName * st = sd->GetMemberType(decl_specifiers, member);
|
TypeName * st = sd->GetMemberType(decl_specifiers, member);
|
if (st) return st;
|
if (st) return st;
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * StructDeclaration::FirstUnionMember(int union_size) const
|
TypeName * StructDeclaration::FirstUnionMember(int union_size) const
|
{
|
{
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
{
|
{
|
StructDeclarator * sd = sl->Head();
|
StructDeclarator * sd = sl->Head();
|
assert(sd);
|
assert(sd);
|
TypeName * st = sd->FirstUnionMember(decl_specifiers, union_size);
|
TypeName * st = sd->FirstUnionMember(decl_specifiers, union_size);
|
if (st) return st;
|
if (st) return st;
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int StructDeclaration::GetMemberPosition(const char * struct_name,
|
int StructDeclaration::GetMemberPosition(const char * struct_name,
|
const char * member,
|
const char * member,
|
bool is_union) const
|
bool is_union) const
|
{
|
{
|
if (is_union) return 0;
|
if (is_union) return 0;
|
|
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
|
{
|
{
|
StructDeclarator * sd = sl->Head();
|
StructDeclarator * sd = sl->Head();
|
assert(sd);
|
assert(sd);
|
int position = sd->GetMemberPosition(member);
|
int position = sd->GetMemberPosition(member);
|
if (position >= 0) return position;
|
if (position >= 0) return position;
|
}
|
}
|
|
|
return -1;
|
return -1;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * StructDeclarator::GetMemberType(TypeSpecifier * tspec,
|
TypeName * StructDeclarator::GetMemberType(TypeSpecifier * tspec,
|
const char * member)
|
const char * member)
|
{
|
{
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
if (di->GetWhat() != DECL_NAME) continue;
|
if (di->GetWhat() != DECL_NAME) continue;
|
assert(di->GetName());
|
assert(di->GetName());
|
if (strcmp(member, di->GetName())) continue;
|
if (strcmp(member, di->GetName())) continue;
|
return new TypeName(tspec, declarator);
|
return new TypeName(tspec, declarator);
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * StructDeclarator::FirstUnionMember(TypeSpecifier * tspec,
|
TypeName * StructDeclarator::FirstUnionMember(TypeSpecifier * tspec,
|
int union_size) const
|
int union_size) const
|
{
|
{
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
{
|
{
|
TypeName tn(tspec, declarator);
|
TypeName tn(tspec, declarator);
|
if (tn.GetSize() != union_size) continue;
|
if (tn.GetSize() != union_size) continue;
|
|
|
return new TypeName(tspec, declarator);
|
return new TypeName(tspec, declarator);
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * StructDeclarator::GetMemberName() const
|
const char * StructDeclarator::GetMemberName() const
|
{
|
{
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
if (di->GetWhat() != DECL_NAME) continue;
|
if (di->GetWhat() != DECL_NAME) continue;
|
assert(di->GetName());
|
assert(di->GetName());
|
return di->GetName();
|
return di->GetName();
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int StructDeclarator::GetMemberPosition(const char * member) const
|
int StructDeclarator::GetMemberPosition(const char * member) const
|
{
|
{
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = declarator; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
if (di->GetWhat() != DECL_NAME) continue;
|
if (di->GetWhat() != DECL_NAME) continue;
|
assert(di->GetName());
|
assert(di->GetName());
|
if (strcmp(member, di->GetName())) continue;
|
if (strcmp(member, di->GetName())) continue;
|
return position;
|
return position;
|
}
|
}
|
|
|
return -1;
|
return -1;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeSpecifier::IsNumericType() const
|
bool TypeSpecifier::IsNumericType() const
|
{
|
{
|
if (spec & TS_NUMERIC) return true;
|
if (spec & TS_NUMERIC) return true;
|
if (spec != TS_TYPE_NAME) return false;
|
if (spec != TS_TYPE_NAME) return false;
|
|
|
assert(name);
|
assert(name);
|
TypeName * tname = TypedefName::Find(name);
|
TypeName * tname = TypedefName::Find(name);
|
assert(tname);
|
assert(tname);
|
return tname->IsNumericType();
|
return tname->IsNumericType();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int TypeSpecifier::GetBaseSize() const
|
int TypeSpecifier::GetBaseSize() const
|
{
|
{
|
if (spec & TS_VOID) return 0;
|
if (spec & TS_VOID) return 0;
|
if (spec & TS_CHAR) return 1;
|
if (spec & TS_CHAR) return 1;
|
if (spec & TS_SHORT) return 2;
|
if (spec & TS_SHORT) return 2;
|
if (spec & TS_INT) return 2;
|
if (spec & TS_INT) return 2;
|
if (spec & TS_LONG) return 4;
|
if (spec & TS_LONG) return 4;
|
if (spec & TS_FLOAT) return 4;
|
if (spec & TS_FLOAT) return 4;
|
if (spec & TS_DOUBLE) return 8;
|
if (spec & TS_DOUBLE) return 8;
|
if (spec & TS_ENUM) return 2;
|
if (spec & TS_ENUM) return 2;
|
if (spec & (TS_STRUCT | TS_UNION))
|
if (spec & (TS_STRUCT | TS_UNION))
|
{
|
{
|
assert(name);
|
assert(name);
|
StructDeclarationList * sdl = StructName::Find(name);
|
StructDeclarationList * sdl = StructName::Find(name);
|
if (sdl == 0)
|
if (sdl == 0)
|
{
|
{
|
fprintf(stderr, "No struct %s defined\n", name);
|
fprintf(stderr, "No struct %s defined\n", name);
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int size = 0;
|
int size = 0;
|
for (; sdl; sdl = sdl->Tail())
|
for (; sdl; sdl = sdl->Tail())
|
{
|
{
|
assert(sdl->Head());
|
assert(sdl->Head());
|
int tsize = sdl->Head()->GetSize();
|
int tsize = sdl->Head()->GetSize();
|
if (spec & TS_UNION)
|
if (spec & TS_UNION)
|
{
|
{
|
if (size < tsize) size = tsize;
|
if (size < tsize) size = tsize;
|
}
|
}
|
else
|
else
|
{
|
{
|
size += tsize;
|
size += tsize;
|
}
|
}
|
}
|
}
|
return size;
|
return size;
|
}
|
}
|
|
|
if (spec & TS_TYPE_NAME)
|
if (spec & TS_TYPE_NAME)
|
{
|
{
|
assert(name);
|
assert(name);
|
TypeName * tname = TypedefName::Find(name);
|
TypeName * tname = TypedefName::Find(name);
|
assert(tname);
|
assert(tname);
|
return tname->GetTypeSpecifier()->GetBaseSize();
|
return tname->GetTypeSpecifier()->GetBaseSize();
|
}
|
}
|
|
|
return 2; // no type -> int
|
return 2; // no type -> int
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int TypeSpecifier::GetSize(Declarator * decl) const
|
int TypeSpecifier::GetSize(Declarator * decl) const
|
{
|
{
|
int size = -2;
|
int size = -2;
|
|
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
const DeclItem * ditem = decl->Head();
|
const DeclItem * ditem = decl->Head();
|
assert(ditem);
|
assert(ditem);
|
|
|
switch(ditem->GetWhat())
|
switch(ditem->GetWhat())
|
{
|
{
|
case DECL_FUNPTR:
|
case DECL_FUNPTR:
|
size = 2;
|
size = 2;
|
continue;
|
continue;
|
|
|
case DECL_POINTER:
|
case DECL_POINTER:
|
size = 2;
|
size = 2;
|
continue;
|
continue;
|
|
|
case DECL_FUN:
|
case DECL_FUN:
|
size = 2;
|
size = 2;
|
continue;
|
continue;
|
|
|
case DECL_ARRAY:
|
case DECL_ARRAY:
|
if (ditem->GetArraySize()) // type[num]
|
if (ditem->GetArraySize()) // type[num]
|
{
|
{
|
if (size == -2) size = GetBaseSize();
|
if (size == -2) size = GetBaseSize();
|
size *= ditem->GetArraySize()
|
size *= ditem->GetArraySize()
|
->GetConstantNumericValue();
|
->GetConstantNumericValue();
|
}
|
}
|
else // type[]
|
else // type[]
|
{
|
{
|
size = -1;
|
size = -1;
|
}
|
}
|
continue;
|
continue;
|
|
|
case DECL_NAME:
|
case DECL_NAME:
|
continue; // varname
|
continue; // varname
|
|
|
default: assert(0 && "BAD what");
|
default: assert(0 && "BAD what");
|
}
|
}
|
}
|
}
|
|
|
if (size == -2) return GetBaseSize();
|
if (size == -2) return GetBaseSize();
|
return size;
|
return size;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int TypeSpecifier::GetFunReturnSize(Declarator * decl) const
|
int TypeSpecifier::GetFunReturnSize(Declarator * decl) const
|
{
|
{
|
assert(this);
|
assert(this);
|
if (decl == 0)
|
if (decl == 0)
|
{
|
{
|
fprintf(stderr, "Can't get parameters of (undeclared ?) function\n");
|
fprintf(stderr, "Can't get parameters of (undeclared ?) function\n");
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int base_size = GetBaseSize();
|
int base_size = GetBaseSize();
|
|
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
const Expression * asize = di->GetArraySize();
|
const Expression * asize = di->GetArraySize();
|
|
|
switch(di->GetWhat())
|
switch(di->GetWhat())
|
{
|
{
|
case DECL_NAME:
|
case DECL_NAME:
|
continue;
|
continue;
|
|
|
case DECL_FUNPTR:
|
case DECL_FUNPTR:
|
base_size = 2;
|
base_size = 2;
|
continue;
|
continue;
|
|
|
case DECL_ARRAY:
|
case DECL_ARRAY:
|
if (asize == 0) // []
|
if (asize == 0) // []
|
base_size = 2;
|
base_size = 2;
|
else // [const expr]
|
else // [const expr]
|
base_size *= asize->GetConstantNumericValue();
|
base_size *= asize->GetConstantNumericValue();
|
continue;
|
continue;
|
|
|
case DECL_FUN:
|
case DECL_FUN:
|
continue;
|
continue;
|
|
|
case DECL_POINTER:
|
case DECL_POINTER:
|
base_size = 2;
|
base_size = 2;
|
continue;
|
continue;
|
|
|
default: assert(0 && "Bad InitDeclarator::what");
|
default: assert(0 && "Bad InitDeclarator::what");
|
}
|
}
|
}
|
}
|
|
|
return base_size;
|
return base_size;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeSpecifier * TypeSpecifier::operator +(TypeSpecifier & other)
|
TypeSpecifier * TypeSpecifier::operator +(TypeSpecifier & other)
|
{
|
{
|
int sc_cnt = 0;
|
int sc_cnt = 0;
|
int tq_cnt = 0;
|
int tq_cnt = 0;
|
int si_cnt = 0;
|
int si_cnt = 0;
|
int ty_cnt = 0;
|
int ty_cnt = 0;
|
|
|
if (spec & SC_MASK) sc_cnt++;
|
if (spec & SC_MASK) sc_cnt++;
|
if (spec & TQ_MASK) tq_cnt++;
|
if (spec & TQ_MASK) tq_cnt++;
|
if (spec & TS_SIGN_MASK) si_cnt++;
|
if (spec & TS_SIGN_MASK) si_cnt++;
|
if (spec & TS_MASK) ty_cnt++;
|
if (spec & TS_MASK) ty_cnt++;
|
|
|
if (other.spec & SC_MASK) sc_cnt++;
|
if (other.spec & SC_MASK) sc_cnt++;
|
if (other.spec & TQ_MASK) tq_cnt++;
|
if (other.spec & TQ_MASK) tq_cnt++;
|
if (other.spec & TS_SIGN_MASK) si_cnt++;
|
if (other.spec & TS_SIGN_MASK) si_cnt++;
|
if (other.spec & TS_MASK) ty_cnt++;
|
if (other.spec & TS_MASK) ty_cnt++;
|
|
|
if (sc_cnt > 1)
|
if (sc_cnt > 1)
|
{
|
{
|
fprintf(stderr, "Multiple or contradicting storage class (ignored)\n");
|
fprintf(stderr, "Multiple or contradicting storage class (ignored)\n");
|
semantic_errors++;
|
semantic_errors++;
|
delete other.self();
|
delete other.self();
|
return this;
|
return this;
|
}
|
}
|
|
|
if (tq_cnt > 1)
|
if (tq_cnt > 1)
|
{
|
{
|
fprintf(stderr, "Multiple or contradicting qualifiers (ignored)\n");
|
fprintf(stderr, "Multiple or contradicting qualifiers (ignored)\n");
|
semantic_errors++;
|
semantic_errors++;
|
delete other.self();
|
delete other.self();
|
return this;
|
return this;
|
}
|
}
|
|
|
if (si_cnt > 1)
|
if (si_cnt > 1)
|
{
|
{
|
fprintf(stderr,
|
fprintf(stderr,
|
"Multiple or Contradicting signed/unsigned (ignored)\n");
|
"Multiple or Contradicting signed/unsigned (ignored)\n");
|
semantic_errors++;
|
semantic_errors++;
|
delete other.self();
|
delete other.self();
|
return this;
|
return this;
|
}
|
}
|
|
|
if (ty_cnt > 1)
|
if (ty_cnt > 1)
|
{
|
{
|
fprintf(stderr, "Multiple or Contradicting types (ignored)\n");
|
fprintf(stderr, "Multiple or Contradicting types (ignored)\n");
|
semantic_errors++;
|
semantic_errors++;
|
delete other.self();
|
delete other.self();
|
return this;
|
return this;
|
}
|
}
|
|
|
if (other.enum_list) enum_list = other.enum_list;
|
if (other.enum_list) enum_list = other.enum_list;
|
if (other.name) name = other.name;
|
if (other.name) name = other.name;
|
if (other.struct_decl_list) struct_decl_list = other.struct_decl_list;
|
if (other.struct_decl_list) struct_decl_list = other.struct_decl_list;
|
|
|
spec = (Specifier)(spec | other.spec);
|
spec = (Specifier)(spec | other.spec);
|
delete other.self();
|
delete other.self();
|
return this;
|
return this;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int TypeSpecifier::Print(FILE * out) const
|
int TypeSpecifier::Print(FILE * out) const
|
{
|
{
|
int len = 0;
|
int len = 0;
|
|
|
if (spec & SC_TYPEDEF) len += fprintf(out, "typedef ");
|
if (spec & SC_TYPEDEF) len += fprintf(out, "typedef ");
|
if (spec & SC_EXTERN) len += fprintf(out, "extern ");
|
if (spec & SC_EXTERN) len += fprintf(out, "extern ");
|
if (spec & SC_STATIC) len += fprintf(out, "static ");
|
if (spec & SC_STATIC) len += fprintf(out, "static ");
|
if (spec & SC_AUTO) len += fprintf(out, "auto ");
|
if (spec & SC_AUTO) len += fprintf(out, "auto ");
|
if (spec & SC_REGISTER) len += fprintf(out, "register ");
|
if (spec & SC_REGISTER) len += fprintf(out, "register ");
|
|
|
if (spec & TQ_CONST) len += fprintf(out, "const ");
|
if (spec & TQ_CONST) len += fprintf(out, "const ");
|
if (spec & TQ_VOLATILE) len += fprintf(out, "volatile ");
|
if (spec & TQ_VOLATILE) len += fprintf(out, "volatile ");
|
|
|
if (spec & TS_SIGNED) len += fprintf(out, "signed ");
|
if (spec & TS_SIGNED) len += fprintf(out, "signed ");
|
if (spec & TS_UNSIGNED) len += fprintf(out, "unsigned ");
|
if (spec & TS_UNSIGNED) len += fprintf(out, "unsigned ");
|
|
|
if (spec & TS_VOID) len += fprintf(out, "void ");
|
if (spec & TS_VOID) len += fprintf(out, "void ");
|
if (spec & TS_CHAR) len += fprintf(out, "char ");
|
if (spec & TS_CHAR) len += fprintf(out, "char ");
|
if (spec & TS_SHORT) len += fprintf(out, "short ");
|
if (spec & TS_SHORT) len += fprintf(out, "short ");
|
if (spec & TS_INT) len += fprintf(out, "int ");
|
if (spec & TS_INT) len += fprintf(out, "int ");
|
if (spec & TS_LONG) len += fprintf(out, "long ");
|
if (spec & TS_LONG) len += fprintf(out, "long ");
|
if (spec & TS_FLOAT) len += fprintf(out, "float ");
|
if (spec & TS_FLOAT) len += fprintf(out, "float ");
|
if (spec & TS_DOUBLE) len += fprintf(out, "double ");
|
if (spec & TS_DOUBLE) len += fprintf(out, "double ");
|
|
|
if (spec & TS_STRUCT)
|
if (spec & TS_STRUCT)
|
{
|
{
|
assert(name);
|
assert(name);
|
len += fprintf(out, "struct '%s' ", name);
|
len += fprintf(out, "struct '%s' ", name);
|
}
|
}
|
|
|
if (spec & TS_UNION)
|
if (spec & TS_UNION)
|
{
|
{
|
assert(name);
|
assert(name);
|
len += fprintf(out, "union '%s' ", name);
|
len += fprintf(out, "union '%s' ", name);
|
}
|
}
|
|
|
if (spec & TS_ENUM)
|
if (spec & TS_ENUM)
|
{
|
{
|
if (name) len += fprintf(out, "enum '%s' ", name);
|
if (name) len += fprintf(out, "enum '%s' ", name);
|
else len += fprintf(out, "anonymous enum ");
|
else len += fprintf(out, "anonymous enum ");
|
}
|
}
|
|
|
if (spec & TS_TYPE_NAME)
|
if (spec & TS_TYPE_NAME)
|
{
|
{
|
if (name) len += fprintf(out, "'%s' ", name);
|
if (name) len += fprintf(out, "'%s' ", name);
|
else len += fprintf(out, "<user type> ");
|
else len += fprintf(out, "<user type> ");
|
}
|
}
|
|
|
return len;
|
return len;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// struct, union, or typedef
|
// struct, union, or typedef
|
//
|
//
|
TypeSpecifier::TypeSpecifier(Specifier sp, const char * n,
|
TypeSpecifier::TypeSpecifier(Specifier sp, const char * n,
|
StructDeclarationList * sdl)
|
StructDeclarationList * sdl)
|
: Node("TypeSpecifier (struct/union)"),
|
: Node("TypeSpecifier (struct/union)"),
|
spec(sp),
|
spec(sp),
|
name(n),
|
name(n),
|
struct_decl_list(sdl),
|
struct_decl_list(sdl),
|
enum_list(0)
|
enum_list(0)
|
{
|
{
|
if (name == 0) // anonymous struct or union
|
if (name == 0) // anonymous struct or union
|
{
|
{
|
char * cp = new char[20];
|
char * cp = new char[20];
|
sprintf(cp, "anonymous-%d", anonymous_number++);
|
sprintf(cp, "anonymous-%d", anonymous_number++);
|
name = cp;
|
name = cp;
|
}
|
}
|
|
|
if (struct_decl_list) StructName::Add(name, struct_decl_list);
|
if (struct_decl_list) StructName::Add(name, struct_decl_list);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void TypeSpecifier::Emit(FILE * out)
|
void TypeSpecifier::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "spec = ");
|
fprintf(out, "spec = ");
|
|
|
Print(out);
|
Print(out);
|
|
|
fprintf(out, "(%X)\n", spec);
|
fprintf(out, "(%X)\n", spec);
|
|
|
if (name)
|
if (name)
|
{
|
{
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "name = %s\n", name);
|
fprintf(out, "name = %s\n", name);
|
}
|
}
|
|
|
if (struct_decl_list)
|
if (struct_decl_list)
|
{
|
{
|
int pos = 0;
|
int pos = 0;
|
for (StructDeclarationList * sl = struct_decl_list; sl; sl = sl->Tail())
|
for (StructDeclarationList * sl = struct_decl_list; sl; sl = sl->Tail())
|
{
|
{
|
assert(sl->Head());
|
assert(sl->Head());
|
pos += sl->Head()->Emit(out, name, pos, IsUnion());
|
pos += sl->Head()->Emit(out, name, pos, IsUnion());
|
}
|
}
|
}
|
}
|
|
|
if (enum_list)
|
if (enum_list)
|
{
|
{
|
if (name) TypedefName::Add(name, new TypeName(TS_INT));
|
if (name) TypedefName::Add(name, new TypeName(TS_INT));
|
enum_list->Emit(out);
|
enum_list->Emit(out);
|
}
|
}
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Ptr::Print(FILE * out) const
|
int Ptr::Print(FILE * out) const
|
{
|
{
|
return fprintf(out, "* ");
|
return fprintf(out, "* ");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void DeclItem::SetArraySize(int len)
|
void DeclItem::SetArraySize(int len)
|
{
|
{
|
assert(!array_size);
|
assert(!array_size);
|
assert(len >= 0);
|
assert(len >= 0);
|
array_size = new NumericExpression(len);
|
array_size = new NumericExpression(len);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int DeclItem::Print(FILE * out) const
|
int DeclItem::Print(FILE * out) const
|
{
|
{
|
switch(what)
|
switch(what)
|
{
|
{
|
case DECL_FUNPTR: return fprintf(out, "*() ");
|
case DECL_FUNPTR: return fprintf(out, "*() ");
|
case DECL_ARRAY: if (!array_size) return fprintf(out, "[] ");
|
case DECL_ARRAY: if (!array_size) return fprintf(out, "[] ");
|
return fprintf(out, "[%d] ",
|
return fprintf(out, "[%d] ",
|
array_size->GetConstantNumericValue());
|
array_size->GetConstantNumericValue());
|
case DECL_FUN: return fprintf(out, "() ");
|
case DECL_FUN: return fprintf(out, "() ");
|
case DECL_POINTER: {
|
case DECL_POINTER: {
|
assert(pointer);
|
assert(pointer);
|
int len = 0;
|
int len = 0;
|
for (Pointer * p = pointer; p; p = p->Tail())
|
for (Pointer * p = pointer; p; p = p->Tail())
|
len += p->Head()->Print(out);
|
len += p->Head()->Print(out);
|
return len;
|
return len;
|
}
|
}
|
case DECL_NAME: assert(name);
|
case DECL_NAME: assert(name);
|
return fprintf(out, "%s ", name);
|
return fprintf(out, "%s ", name);
|
}
|
}
|
|
|
assert(0 ** "Bad what");
|
assert(0 ** "Bad what");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void DeclItem::Emit(FILE * out)
|
void DeclItem::Emit(FILE * out)
|
{
|
{
|
const char * s = "BAD DECL";
|
const char * s = "BAD DECL";
|
|
|
EmitStart(out);
|
EmitStart(out);
|
switch(what)
|
switch(what)
|
{
|
{
|
case DECL_NAME: s = "DECL_NAME"; break;
|
case DECL_NAME: s = "DECL_NAME"; break;
|
case DECL_FUNPTR: s = "DECL_FUNPTR"; break;
|
case DECL_FUNPTR: s = "DECL_FUNPTR"; break;
|
case DECL_ARRAY: s = "DECL_ARRAY"; break;
|
case DECL_ARRAY: s = "DECL_ARRAY"; break;
|
case DECL_FUN: s = "DECL_FUN"; break;
|
case DECL_FUN: s = "DECL_FUN"; break;
|
case DECL_POINTER: s = "DECL_POINTER"; break;
|
case DECL_POINTER: s = "DECL_POINTER"; break;
|
}
|
}
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "what = %s\r\n", s);
|
fprintf(out, "what = %s\r\n", s);
|
|
|
if (name)
|
if (name)
|
{
|
{
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "name = %s\r\n", name);
|
fprintf(out, "name = %s\r\n", name);
|
}
|
}
|
|
|
if (funptr) funptr->Emit(out);
|
if (funptr) funptr->Emit(out);
|
// don't emit array_size
|
// don't emit array_size
|
if (fun_params) fun_params->Emit(out);
|
if (fun_params) fun_params->Emit(out);
|
if (fun_identifiers) fun_identifiers->Emit(out);
|
if (fun_identifiers) fun_identifiers->Emit(out);
|
if (pointer) pointer->Emit(out);
|
if (pointer) pointer->Emit(out);
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName::TypeName(TypeSpecifier * ds, Declarator * ad)
|
TypeName::TypeName(TypeSpecifier * ds, Declarator * ad)
|
: Node("TypeName"),
|
: Node("TypeName"),
|
decl_spec(ds),
|
decl_spec(ds),
|
abs_declarator(ad)
|
abs_declarator(ad)
|
{
|
{
|
assert(ds);
|
assert(ds);
|
if (ds->GetType() & TS_TYPE_NAME)
|
if (ds->GetType() & TS_TYPE_NAME)
|
{
|
{
|
const char * name = decl_spec->GetName();
|
const char * name = decl_spec->GetName();
|
assert(name);
|
assert(name);
|
|
|
TypeName * def = TypedefName::Find(name);
|
TypeName * def = TypedefName::Find(name);
|
assert(def);
|
assert(def);
|
|
|
// copy type specifier from definition...
|
// copy type specifier from definition...
|
//
|
//
|
decl_spec = def->GetTypeSpecifier();
|
decl_spec = def->GetTypeSpecifier();
|
assert(decl_spec);
|
assert(decl_spec);
|
|
|
// prepend declarator from definition
|
// prepend declarator from definition
|
//
|
//
|
for (Declarator * decl = def->abs_declarator->Reverse();
|
for (Declarator * decl = def->abs_declarator->Reverse();
|
decl; decl = decl->Tail())
|
decl; decl = decl->Tail())
|
abs_declarator = new Declarator(decl->Head(), abs_declarator);
|
abs_declarator = new Declarator(decl->Head(), abs_declarator);
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName::TypeName(Specifier sp)
|
TypeName::TypeName(Specifier sp)
|
: Node("TypeName (internal)"),
|
: Node("TypeName (internal)"),
|
decl_spec(new TypeSpecifier(sp)),
|
decl_spec(new TypeSpecifier(sp)),
|
abs_declarator(0)
|
abs_declarator(0)
|
{
|
{
|
assert((sp & TS_TYPE_NAME) == 0);
|
assert((sp & TS_TYPE_NAME) == 0);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void TypeName::Emit(FILE * out)
|
void TypeName::Emit(FILE * out)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
if (decl_spec) decl_spec->Emit(out);
|
if (decl_spec) decl_spec->Emit(out);
|
if (abs_declarator) abs_declarator->Emit(out);
|
if (abs_declarator) abs_declarator->Emit(out);
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
SUW TypeName::GetSUW()
|
SUW TypeName::GetSUW()
|
{
|
{
|
if (IsPointer()) return WO;
|
if (IsPointer()) return WO;
|
|
|
const int size = GetSize();
|
const int size = GetSize();
|
|
|
if (size == 2) return WO;
|
if (size == 2) return WO;
|
if (size != 1)
|
if (size != 1)
|
{
|
{
|
fprintf(stderr, "---- Size not 1 or 2:\n");
|
fprintf(stderr, "---- Size not 1 or 2:\n");
|
Emit(stderr);
|
Emit(stderr);
|
fprintf(stderr, "\n====\n");
|
fprintf(stderr, "\n====\n");
|
*(char*)0 = 0;
|
*(char*)0 = 0;
|
fprintf(stderr, "\n====\n");
|
fprintf(stderr, "\n====\n");
|
}
|
}
|
assert(size == 1);
|
assert(size == 1);
|
if (IsUnsigned()) return UB;
|
if (IsUnsigned()) return UB;
|
return SB;
|
return SB;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeName::IsUnsigned() const
|
bool TypeName::IsUnsigned() const
|
{
|
{
|
if (IsPointer()) return true;
|
if (IsPointer()) return true;
|
return decl_spec->IsUnsigned();
|
return decl_spec->IsUnsigned();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeName::IsNumericType() const
|
bool TypeName::IsNumericType() const
|
{
|
{
|
if (!decl_spec->IsNumericType()) return false;
|
if (!decl_spec->IsNumericType()) return false;
|
|
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
{
|
{
|
DeclItem * di = d->Head();
|
DeclItem * di = d->Head();
|
assert(di);
|
assert(di);
|
switch(di->GetWhat())
|
switch(di->GetWhat())
|
{
|
{
|
case DECL_NAME: continue;
|
case DECL_NAME: continue;
|
case DECL_FUNPTR: return false;
|
case DECL_FUNPTR: return false;
|
case DECL_ARRAY: return false;
|
case DECL_ARRAY: return false;
|
case DECL_FUN: return true;
|
case DECL_FUN: return true;
|
case DECL_POINTER: return false;
|
case DECL_POINTER: return false;
|
default: assert(0 && "Bad what");
|
default: assert(0 && "Bad what");
|
}
|
}
|
}
|
}
|
return true;
|
return true;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeName::GetFunReturnType()
|
TypeName * TypeName::GetFunReturnType()
|
{
|
{
|
assert(this);
|
assert(this);
|
|
|
if (abs_declarator)
|
if (abs_declarator)
|
{
|
{
|
Declarator * ret = 0;
|
Declarator * ret = 0;
|
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
|
{
|
{
|
DECL_WHAT what = decl->Head()->GetWhat();
|
DECL_WHAT what = decl->Head()->GetWhat();
|
if (what == DECL_FUNPTR || what == DECL_FUN)
|
if (what == DECL_FUNPTR || what == DECL_FUN)
|
return new TypeName(decl_spec, ret->Reverse());
|
return new TypeName(decl_spec, ret->Reverse());
|
|
|
ret = new Declarator(decl->Head(), ret);
|
ret = new Declarator(decl->Head(), ret);
|
}
|
}
|
}
|
}
|
|
|
Print(stderr);
|
Print(stderr);
|
fprintf(stderr, " is not a function\n");
|
fprintf(stderr, " is not a function\n");
|
semantic_errors++;
|
semantic_errors++;
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeName::GetMemberType(const char * member)
|
TypeName * TypeName::GetMemberType(const char * member)
|
{
|
{
|
TypeName * tn = decl_spec->GetMemberType(member);
|
TypeName * tn = decl_spec->GetMemberType(member);
|
if (tn) return tn;
|
if (tn) return tn;
|
|
|
const char * sname = decl_spec->GetName();
|
const char * sname = decl_spec->GetName();
|
assert(sname);
|
assert(sname);
|
|
|
fprintf(stderr, "aggregate %s has no member %s\n", sname, member);
|
fprintf(stderr, "aggregate %s has no member %s\n", sname, member);
|
semantic_errors++;
|
semantic_errors++;
|
return this;
|
return this;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeName::FirstUnionMember(int union_size) const
|
TypeName * TypeName::FirstUnionMember(int union_size) const
|
{
|
{
|
assert(IsUnion());
|
assert(IsUnion());
|
assert(decl_spec);
|
assert(decl_spec);
|
|
|
const char * uname = decl_spec->GetName();
|
const char * uname = decl_spec->GetName();
|
assert(uname);
|
assert(uname);
|
|
|
StructDeclarationList * sdl = StructName::Find(uname);
|
StructDeclarationList * sdl = StructName::Find(uname);
|
if (sdl == 0)
|
if (sdl == 0)
|
{
|
{
|
fprintf(stderr, "No struct %s defined\n", uname);
|
fprintf(stderr, "No struct %s defined\n", uname);
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
for (; sdl; sdl = sdl->Tail())
|
for (; sdl; sdl = sdl->Tail())
|
{
|
{
|
StructDeclaration * sd = sdl->Head();
|
StructDeclaration * sd = sdl->Head();
|
assert(sd);
|
assert(sd);
|
|
|
TypeName * ret = sd->FirstUnionMember(union_size);
|
TypeName * ret = sd->FirstUnionMember(union_size);
|
if (ret) return ret;
|
if (ret) return ret;
|
}
|
}
|
|
|
assert(0);
|
assert(0);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeName::AddressOf() const
|
TypeName * TypeName::AddressOf() const
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(decl_spec);
|
assert(decl_spec);
|
|
|
Ptr * newptr = new Ptr(0);
|
Ptr * newptr = new Ptr(0);
|
|
|
if (abs_declarator == 0 || abs_declarator->Head()->GetWhat() != DECL_POINTER)
|
if (abs_declarator == 0 || abs_declarator->Head()->GetWhat() != DECL_POINTER)
|
{
|
{
|
Pointer * pointer = new Pointer(newptr, 0);
|
Pointer * pointer = new Pointer(newptr, 0);
|
DeclItem * di = new DeclItem(pointer);
|
DeclItem * di = new DeclItem(pointer);
|
Declarator * decl = new Declarator(di, abs_declarator);
|
Declarator * decl = new Declarator(di, abs_declarator);
|
return new TypeName(decl_spec, decl);
|
return new TypeName(decl_spec, decl);
|
}
|
}
|
|
|
DeclItem * hd = abs_declarator->Head();
|
DeclItem * hd = abs_declarator->Head();
|
assert(hd);
|
assert(hd);
|
assert(hd->GetWhat() == DECL_POINTER);
|
assert(hd->GetWhat() == DECL_POINTER);
|
|
|
Pointer * pointer = new Pointer(newptr, hd->GetPointer());
|
Pointer * pointer = new Pointer(newptr, hd->GetPointer());
|
DeclItem * di = new DeclItem(pointer);
|
DeclItem * di = new DeclItem(pointer);
|
Declarator * decl = new Declarator(di, abs_declarator->Tail());
|
Declarator * decl = new Declarator(di, abs_declarator->Tail());
|
return new TypeName(decl_spec, decl);
|
return new TypeName(decl_spec, decl);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeName::ContentOf() const
|
TypeName * TypeName::ContentOf() const
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(decl_spec);
|
assert(decl_spec);
|
|
|
if (!abs_declarator)
|
if (!abs_declarator)
|
{
|
{
|
semantic_errors++;
|
semantic_errors++;
|
Print(stderr);
|
Print(stderr);
|
fprintf(stderr, " is not a pointer\n");
|
fprintf(stderr, " is not a pointer\n");
|
return new TypeName(new TypeSpecifier(TS_INT), 0);
|
return new TypeName(new TypeSpecifier(TS_INT), 0);
|
}
|
}
|
|
|
DeclItem * hd = abs_declarator->Head();
|
DeclItem * hd = abs_declarator->Head();
|
assert(hd);
|
assert(hd);
|
|
|
if (hd->GetWhat() != DECL_POINTER)
|
if (hd->GetWhat() != DECL_POINTER)
|
{
|
{
|
if (IsArray())
|
if (IsArray())
|
{
|
{
|
Declarator * ret = 0;
|
Declarator * ret = 0;
|
Declarator * last = 0;
|
Declarator * last = 0;
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
{
|
{
|
DeclItem * di = d->Head();
|
DeclItem * di = d->Head();
|
assert(di);
|
assert(di);
|
if (di->GetWhat() == DECL_ARRAY) last = d;
|
if (di->GetWhat() == DECL_ARRAY) last = d;
|
}
|
}
|
|
|
assert(last);
|
assert(last);
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
{
|
{
|
if (d != last) ret = new Declarator(d->Head(), ret);
|
if (d != last) ret = new Declarator(d->Head(), ret);
|
}
|
}
|
ret = ret->Reverse();
|
ret = ret->Reverse();
|
return new TypeName(decl_spec, ret);
|
return new TypeName(decl_spec, ret);
|
}
|
}
|
semantic_errors++;
|
semantic_errors++;
|
Print(stderr);
|
Print(stderr);
|
fprintf(stderr, " is not a pointer\n");
|
fprintf(stderr, " is not a pointer\n");
|
return new TypeName(new TypeSpecifier(TS_INT), 0);
|
return new TypeName(new TypeSpecifier(TS_INT), 0);
|
}
|
}
|
|
|
Pointer * pointer = hd->GetPointer();
|
Pointer * pointer = hd->GetPointer();
|
assert(pointer);
|
assert(pointer);
|
pointer = pointer->Tail();
|
pointer = pointer->Tail();
|
if (!pointer) return new TypeName(decl_spec, abs_declarator->Tail());
|
if (!pointer) return new TypeName(decl_spec, abs_declarator->Tail());
|
|
|
DeclItem * new_hd = new DeclItem(pointer);
|
DeclItem * new_hd = new DeclItem(pointer);
|
Declarator * decl = new Declarator(new_hd, abs_declarator->Tail());
|
Declarator * decl = new Declarator(new_hd, abs_declarator->Tail());
|
return new TypeName(decl_spec, decl);
|
return new TypeName(decl_spec, decl);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int TypeName::Print(FILE * out) const
|
int TypeName::Print(FILE * out) const
|
{
|
{
|
assert(this);
|
assert(this);
|
|
|
int len = 0;
|
int len = 0;
|
if (decl_spec) len += decl_spec->Print(out);
|
if (decl_spec) len += decl_spec->Print(out);
|
|
|
for (Declarator * dl = abs_declarator; dl; dl = dl->Tail())
|
for (Declarator * dl = abs_declarator; dl; dl = dl->Tail())
|
{
|
{
|
DeclItem * di = dl->Head();
|
DeclItem * di = dl->Head();
|
assert(di);
|
assert(di);
|
len += fprintf(out, " ");
|
len += fprintf(out, " ");
|
len += di->Print(out);
|
len += di->Print(out);
|
}
|
}
|
|
|
return len;
|
return len;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * TypeName::GetDeclaredName()
|
const char * TypeName::GetDeclaredName()
|
{
|
{
|
const char * ret = 0;
|
const char * ret = 0;
|
|
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
for (Declarator * d = abs_declarator; d; d = d->Tail())
|
{
|
{
|
DeclItem * di = d->Head();
|
DeclItem * di = d->Head();
|
assert(di);
|
assert(di);
|
const char * n = di->GetName();
|
const char * n = di->GetName();
|
if (n == 0) continue;
|
if (n == 0) continue;
|
assert (ret == 0);
|
assert (ret == 0);
|
ret = n;
|
ret = n;
|
}
|
}
|
|
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * GetDeclaredName(Declarator * decl)
|
const char * GetDeclaredName(Declarator * decl)
|
{
|
{
|
const char * ret = 0;
|
const char * ret = 0;
|
int count = 0;
|
int count = 0;
|
|
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
switch(di->GetWhat())
|
switch(di->GetWhat())
|
{
|
{
|
case DECL_NAME: ret = di->GetName();
|
case DECL_NAME: ret = di->GetName();
|
assert(ret);
|
assert(ret);
|
count++;
|
count++;
|
continue;
|
continue;
|
|
|
case DECL_FUNPTR: assert(!di->GetName());
|
case DECL_FUNPTR: assert(!di->GetName());
|
assert(di->GetFunptr());
|
assert(di->GetFunptr());
|
ret = GetDeclaredName(di->GetFunptr());
|
ret = GetDeclaredName(di->GetFunptr());
|
assert(ret);
|
assert(ret);
|
count++;
|
count++;
|
continue;
|
continue;
|
|
|
case DECL_ARRAY:
|
case DECL_ARRAY:
|
case DECL_FUN:
|
case DECL_FUN:
|
case DECL_POINTER: assert(!di->GetName());
|
case DECL_POINTER: assert(!di->GetName());
|
continue;
|
continue;
|
|
|
default: assert("Bad What");
|
default: assert("Bad What");
|
|
|
}
|
}
|
}
|
}
|
|
|
assert(count <= 1);
|
assert(count <= 1);
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int TypeName::GetPointeeSize() const
|
int TypeName::GetPointeeSize() const
|
{
|
{
|
assert(abs_declarator);
|
assert(abs_declarator);
|
assert(IsPointer() || IsArray());
|
assert(IsPointer() || IsArray());
|
|
|
return ContentOf()->GetSize();
|
return ContentOf()->GetSize();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeName::IsPointer() const
|
bool TypeName::IsPointer() const
|
{
|
{
|
if (abs_declarator) return ::IsPointer(abs_declarator);
|
if (abs_declarator) return ::IsPointer(abs_declarator);
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeName::IsArray() const
|
bool TypeName::IsArray() const
|
{
|
{
|
if (abs_declarator) return ::IsArray(abs_declarator);
|
if (abs_declarator) return ::IsArray(abs_declarator);
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * TypeName::GetElementType() const
|
TypeName * TypeName::GetElementType() const
|
{
|
{
|
DeclItem * last = 0;
|
DeclItem * last = 0;
|
|
|
assert(abs_declarator);
|
assert(abs_declarator);
|
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_ARRAY) last = di;
|
if (di->GetWhat() == DECL_ARRAY) last = di;
|
}
|
}
|
|
|
assert(last);
|
assert(last);
|
|
|
// copy decl items except name and last...
|
// copy decl items except name and last...
|
//
|
//
|
Declarator * ret = 0;
|
Declarator * ret = 0;
|
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
|
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
if (di == last) continue;
|
if (di == last) continue;
|
if (di->GetWhat() == DECL_NAME) continue;
|
if (di->GetWhat() == DECL_NAME) continue;
|
|
|
ret = new Declarator(di, ret);
|
ret = new Declarator(di, ret);
|
}
|
}
|
|
|
|
|
return new TypeName(decl_spec, ret);
|
return new TypeName(decl_spec, ret);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void TypeName::SetArrayLength(int len)
|
void TypeName::SetArrayLength(int len)
|
{
|
{
|
assert(abs_declarator);
|
assert(abs_declarator);
|
::SetArrayLength(abs_declarator, len);
|
::SetArrayLength(abs_declarator, len);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * TypeName::ArrayLength() const
|
Expression * TypeName::ArrayLength() const
|
{
|
{
|
if (abs_declarator) return ::ArrayLength(abs_declarator);
|
if (abs_declarator) return ::ArrayLength(abs_declarator);
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeName::IsStruct() const
|
bool TypeName::IsStruct() const
|
{
|
{
|
assert(decl_spec);
|
assert(decl_spec);
|
if (decl_spec->GetType() & TS_STRUCT) return true;
|
if (decl_spec->GetType() & TS_STRUCT) return true;
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool TypeName::IsUnion() const
|
bool TypeName::IsUnion() const
|
{
|
{
|
assert(decl_spec);
|
assert(decl_spec);
|
if (decl_spec->GetType() & TS_UNION) return true;
|
if (decl_spec->GetType() & TS_UNION) return true;
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool IsPointer(Declarator * decl)
|
bool IsPointer(Declarator * decl)
|
{
|
{
|
assert(decl);
|
assert(decl);
|
|
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_POINTER) return true;
|
if (di->GetWhat() == DECL_POINTER) return true;
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool IsArray(Declarator * decl)
|
bool IsArray(Declarator * decl)
|
{
|
{
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_ARRAY) return true;
|
if (di->GetWhat() == DECL_ARRAY) return true;
|
}
|
}
|
|
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * ArrayLength(Declarator * decl)
|
Expression * ArrayLength(Declarator * decl)
|
{
|
{
|
DeclItem * last = 0;
|
DeclItem * last = 0;
|
|
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_ARRAY) last = di;
|
if (di->GetWhat() == DECL_ARRAY) last = di;
|
}
|
}
|
|
|
if (last) return last->GetArraySize();
|
if (last) return last->GetArraySize();
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void SetArrayLength(Declarator * decl, int len)
|
void SetArrayLength(Declarator * decl, int len)
|
{
|
{
|
DeclItem * last = 0;
|
DeclItem * last = 0;
|
|
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_ARRAY) last = di;
|
if (di->GetWhat() == DECL_ARRAY) last = di;
|
}
|
}
|
|
|
assert(last);
|
assert(last);
|
last->SetArraySize(len);
|
last->SetArraySize(len);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool IsFunPtr(Declarator * decl)
|
bool IsFunPtr(Declarator * decl)
|
{
|
{
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_FUNPTR) return true;
|
if (di->GetWhat() == DECL_FUNPTR) return true;
|
}
|
}
|
|
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool IsFunction(Declarator * decl)
|
bool IsFunction(Declarator * decl)
|
{
|
{
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_FUN) return true;
|
if (di->GetWhat() == DECL_FUN) return true;
|
}
|
}
|
|
|
return false;
|
return false;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
ParameterDeclarationList * GetParameters(Declarator * decl)
|
ParameterDeclarationList * GetParameters(Declarator * decl)
|
{
|
{
|
for (; decl; decl = decl->Tail())
|
for (; decl; decl = decl->Tail())
|
{
|
{
|
DeclItem * di = decl->Head();
|
DeclItem * di = decl->Head();
|
assert(di);
|
assert(di);
|
|
|
if (di->GetWhat() == DECL_FUN) return di->GetParameters();
|
if (di->GetWhat() == DECL_FUN) return di->GetParameters();
|
if (di->GetWhat() == DECL_FUNPTR) return di->GetParameters();
|
if (di->GetWhat() == DECL_FUNPTR) return di->GetParameters();
|
}
|
}
|
|
|
fprintf(stderr, "Can't get parameters of undeclared function\n");
|
fprintf(stderr, "Can't get parameters of undeclared function\n");
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|