OpenCores
URL https://opencores.org/ocsvn/c16/c16/trunk

Subversion Repositories c16

[/] [c16/] [trunk/] [compiler/] [Node.cc] - Rev 31

Go to most recent revision | Compare with Previous | Blame | View Log

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

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.