LDC 2 compiles again.

This commit is contained in:
Robert Clipsham
2009-05-30 17:23:32 +01:00
parent 6619190ba5
commit c5be82c5ae
97 changed files with 67333 additions and 56949 deletions

View File

@@ -1,424 +1,425 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "root.h"
#include "mem.h"
#include "enum.h"
#include "aggregate.h"
#include "init.h"
#include "attrib.h"
#include "scope.h"
#include "id.h"
#include "mtype.h"
#include "declaration.h"
#include "aggregate.h"
#include "expression.h"
#include "module.h"
#define LOG 0
/* Code to do access checks
*/
int hasPackageAccess(Scope *sc, Dsymbol *s);
/****************************************
* Return PROT access for Dsymbol smember in this declaration.
*/
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
{
return PROTpublic;
}
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
{
enum PROT access_ret = PROTnone;
#if LOG
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
toChars(), smember->toChars());
#endif
if (smember->toParent() == this)
{
access_ret = smember->prot();
}
else if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
return access_ret;
}
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
{
enum PROT access_ret = PROTnone;
#if LOG
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
toChars(), smember->toChars());
#endif
if (smember->toParent() == this)
{
access_ret = smember->prot();
}
else
{
enum PROT access;
int i;
if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
for (i = 0; i < baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
access = b->base->getAccess(smember);
switch (access)
{
case PROTnone:
break;
case PROTprivate:
access = PROTnone; // private members of base class not accessible
break;
case PROTpackage:
case PROTprotected:
case PROTpublic:
case PROTexport:
// If access is to be tightened
if (b->protection < access)
access = b->protection;
// Pick path with loosest access
if (access > access_ret)
access_ret = access;
break;
default:
assert(0);
}
}
}
#if LOG
printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
toChars(), smember->toChars(), access_ret);
#endif
return access_ret;
}
/********************************************************
* Helper function for ClassDeclaration::accessCheck()
* Returns:
* 0 no access
* 1 access
*/
static int accessCheckX(
Dsymbol *smember,
Dsymbol *sfunc,
AggregateDeclaration *dthis,
AggregateDeclaration *cdscope)
{
assert(dthis);
#if 0
printf("accessCheckX for %s.%s in function %s() in scope %s\n",
dthis->toChars(), smember->toChars(),
sfunc ? sfunc->toChars() : "NULL",
cdscope ? cdscope->toChars() : "NULL");
#endif
if (dthis->hasPrivateAccess(sfunc) ||
dthis->isFriendOf(cdscope))
{
if (smember->toParent() == dthis)
return 1;
else
{
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
enum PROT access;
access = b->base->getAccess(smember);
if (access >= PROTprotected ||
accessCheckX(smember, sfunc, b->base, cdscope)
)
return 1;
}
}
}
}
else
{
if (smember->toParent() != dthis)
{
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
if (accessCheckX(smember, sfunc, b->base, cdscope))
return 1;
}
}
}
}
return 0;
}
/*******************************
* Do access check for member of this class, this class being the
* type of the 'this' pointer used to access smember.
*/
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
{
int result;
FuncDeclaration *f = sc->func;
AggregateDeclaration *cdscope = sc->getStructClassScope();
enum PROT access;
#if LOG
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
toChars(), smember->toChars(),
f ? f->toChars() : NULL,
cdscope ? cdscope->toChars() : NULL);
#endif
Dsymbol *smemberparent = smember->toParent();
if (!smemberparent || !smemberparent->isAggregateDeclaration())
{
#if LOG
printf("not an aggregate member\n");
#endif
return; // then it is accessible
}
// BUG: should enable this check
//assert(smember->parent->isBaseOf(this, NULL));
if (smemberparent == this)
{ enum PROT access = smember->prot();
result = access >= PROTpublic ||
hasPrivateAccess(f) ||
isFriendOf(cdscope) ||
(access == PROTpackage && hasPackageAccess(sc, this));
#if LOG
printf("result1 = %d\n", result);
#endif
}
else if ((access = this->getAccess(smember)) >= PROTpublic)
{
result = 1;
#if LOG
printf("result2 = %d\n", result);
#endif
}
else if (access == PROTpackage && hasPackageAccess(sc, this))
{
result = 1;
#if LOG
printf("result3 = %d\n", result);
#endif
}
else
{
result = accessCheckX(smember, f, this, cdscope);
#if LOG
printf("result4 = %d\n", result);
#endif
}
if (!result)
{
error(loc, "member %s is not accessible", smember->toChars());
halt();
}
}
/****************************************
* Determine if this is the same or friend of cd.
*/
int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
{
#if LOG
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
#endif
if (this == cd)
return 1;
// Friends if both are in the same module
//if (toParent() == cd->toParent())
if (cd && getModule() == cd->getModule())
{
#if LOG
printf("\tin same module\n");
#endif
return 1;
}
#if LOG
printf("\tnot friend\n");
#endif
return 0;
}
/****************************************
* Determine if scope sc has package level access to s.
*/
int hasPackageAccess(Scope *sc, Dsymbol *s)
{
#if LOG
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
#endif
for (; s; s = s->parent)
{
if (s->isPackage() && !s->isModule())
break;
}
#if LOG
if (s)
printf("\tthis is in package '%s'\n", s->toChars());
#endif
if (s && s == sc->module->parent)
{
#if LOG
printf("\ts is in same package as sc\n");
#endif
return 1;
}
#if LOG
printf("\tno package access\n");
#endif
return 0;
}
/**********************************
* Determine if smember has access to private members of this declaration.
*/
int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
{
if (smember)
{ AggregateDeclaration *cd = NULL;
Dsymbol *smemberparent = smember->toParent();
if (smemberparent)
cd = smemberparent->isAggregateDeclaration();
#if LOG
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
toChars(), smember->toChars());
#endif
if (this == cd) // smember is a member of this class
{
#if LOG
printf("\tyes 1\n");
#endif
return 1; // so we get private access
}
// If both are members of the same module, grant access
while (1)
{ Dsymbol *sp = smember->toParent();
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
smember = sp;
else
break;
}
if (!cd && toParent() == smember->toParent())
{
#if LOG
printf("\tyes 2\n");
#endif
return 1;
}
if (!cd && getModule() == smember->getModule())
{
#if LOG
printf("\tyes 3\n");
#endif
return 1;
}
}
#if LOG
printf("\tno\n");
#endif
return 0;
}
/****************************************
* Check access to d for expression e.d
*/
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
{
#if LOG
if (e)
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
printf("\te->type = %s\n", e->type->toChars());
}
else
{
//printf("accessCheck(%s)\n", d->toChars());
}
#endif
if (!e)
{
if (d->prot() == PROTprivate && d->getModule() != sc->module ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
}
else if (e->type->ty == Tclass)
{ // Do access check
ClassDeclaration *cd;
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
#if 1
if (e->op == TOKsuper)
{ ClassDeclaration *cd2;
cd2 = sc->func->toParent()->isClassDeclaration();
if (cd2)
cd = cd2;
}
#endif
cd->accessCheck(loc, sc, d);
}
else if (e->type->ty == Tstruct)
{ // Do access check
StructDeclaration *cd;
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
cd->accessCheck(loc, sc, d);
}
}
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "root.h"
#include "rmem.h"
#include "enum.h"
#include "aggregate.h"
#include "init.h"
#include "attrib.h"
#include "scope.h"
#include "id.h"
#include "mtype.h"
#include "declaration.h"
#include "aggregate.h"
#include "expression.h"
#include "module.h"
#define LOG 0
/* Code to do access checks
*/
int hasPackageAccess(Scope *sc, Dsymbol *s);
/****************************************
* Return PROT access for Dsymbol smember in this declaration.
*/
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
{
return PROTpublic;
}
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
{
enum PROT access_ret = PROTnone;
#if LOG
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
toChars(), smember->toChars());
#endif
if (smember->toParent() == this)
{
access_ret = smember->prot();
}
else if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
return access_ret;
}
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
{
enum PROT access_ret = PROTnone;
#if LOG
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
toChars(), smember->toChars());
#endif
if (smember->toParent() == this)
{
access_ret = smember->prot();
}
else
{
enum PROT access;
int i;
if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
for (i = 0; i < baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
access = b->base->getAccess(smember);
switch (access)
{
case PROTnone:
break;
case PROTprivate:
access = PROTnone; // private members of base class not accessible
break;
case PROTpackage:
case PROTprotected:
case PROTpublic:
case PROTexport:
// If access is to be tightened
if (b->protection < access)
access = b->protection;
// Pick path with loosest access
if (access > access_ret)
access_ret = access;
break;
default:
assert(0);
}
}
}
#if LOG
printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
toChars(), smember->toChars(), access_ret);
#endif
return access_ret;
}
/********************************************************
* Helper function for ClassDeclaration::accessCheck()
* Returns:
* 0 no access
* 1 access
*/
static int accessCheckX(
Dsymbol *smember,
Dsymbol *sfunc,
AggregateDeclaration *dthis,
AggregateDeclaration *cdscope)
{
assert(dthis);
#if 0
printf("accessCheckX for %s.%s in function %s() in scope %s\n",
dthis->toChars(), smember->toChars(),
sfunc ? sfunc->toChars() : "NULL",
cdscope ? cdscope->toChars() : "NULL");
#endif
if (dthis->hasPrivateAccess(sfunc) ||
dthis->isFriendOf(cdscope))
{
if (smember->toParent() == dthis)
return 1;
else
{
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
enum PROT access;
access = b->base->getAccess(smember);
if (access >= PROTprotected ||
accessCheckX(smember, sfunc, b->base, cdscope)
)
return 1;
}
}
}
}
else
{
if (smember->toParent() != dthis)
{
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
if (accessCheckX(smember, sfunc, b->base, cdscope))
return 1;
}
}
}
}
return 0;
}
/*******************************
* Do access check for member of this class, this class being the
* type of the 'this' pointer used to access smember.
*/
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
{
int result;
FuncDeclaration *f = sc->func;
AggregateDeclaration *cdscope = sc->getStructClassScope();
enum PROT access;
#if LOG
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
toChars(), smember->toChars(),
f ? f->toChars() : NULL,
cdscope ? cdscope->toChars() : NULL);
#endif
Dsymbol *smemberparent = smember->toParent();
if (!smemberparent || !smemberparent->isAggregateDeclaration())
{
#if LOG
printf("not an aggregate member\n");
#endif
return; // then it is accessible
}
// BUG: should enable this check
//assert(smember->parent->isBaseOf(this, NULL));
if (smemberparent == this)
{ enum PROT access = smember->prot();
result = access >= PROTpublic ||
hasPrivateAccess(f) ||
isFriendOf(cdscope) ||
(access == PROTpackage && hasPackageAccess(sc, this));
#if LOG
printf("result1 = %d\n", result);
#endif
}
else if ((access = this->getAccess(smember)) >= PROTpublic)
{
result = 1;
#if LOG
printf("result2 = %d\n", result);
#endif
}
else if (access == PROTpackage && hasPackageAccess(sc, this))
{
result = 1;
#if LOG
printf("result3 = %d\n", result);
#endif
}
else
{
result = accessCheckX(smember, f, this, cdscope);
#if LOG
printf("result4 = %d\n", result);
#endif
}
if (!result)
{
error(loc, "member %s is not accessible", smember->toChars());
halt();
}
}
/****************************************
* Determine if this is the same or friend of cd.
*/
int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
{
#if LOG
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
#endif
if (this == cd)
return 1;
// Friends if both are in the same module
//if (toParent() == cd->toParent())
if (cd && getModule() == cd->getModule())
{
#if LOG
printf("\tin same module\n");
#endif
return 1;
}
#if LOG
printf("\tnot friend\n");
#endif
return 0;
}
/****************************************
* Determine if scope sc has package level access to s.
*/
int hasPackageAccess(Scope *sc, Dsymbol *s)
{
#if LOG
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
#endif
for (; s; s = s->parent)
{
if (s->isPackage() && !s->isModule())
break;
}
#if LOG
if (s)
printf("\tthis is in package '%s'\n", s->toChars());
#endif
if (s && s == sc->module->parent)
{
#if LOG
printf("\ts is in same package as sc\n");
#endif
return 1;
}
#if LOG
printf("\tno package access\n");
#endif
return 0;
}
/**********************************
* Determine if smember has access to private members of this declaration.
*/
int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
{
if (smember)
{ AggregateDeclaration *cd = NULL;
Dsymbol *smemberparent = smember->toParent();
if (smemberparent)
cd = smemberparent->isAggregateDeclaration();
#if LOG
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
toChars(), smember->toChars());
#endif
if (this == cd) // smember is a member of this class
{
#if LOG
printf("\tyes 1\n");
#endif
return 1; // so we get private access
}
// If both are members of the same module, grant access
while (1)
{ Dsymbol *sp = smember->toParent();
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
smember = sp;
else
break;
}
if (!cd && toParent() == smember->toParent())
{
#if LOG
printf("\tyes 2\n");
#endif
return 1;
}
if (!cd && getModule() == smember->getModule())
{
#if LOG
printf("\tyes 3\n");
#endif
return 1;
}
}
#if LOG
printf("\tno\n");
#endif
return 0;
}
/****************************************
* Check access to d for expression e.d
*/
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
{
#if LOG
if (e)
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
printf("\te->type = %s\n", e->type->toChars());
}
else
{
//printf("accessCheck(%s)\n", d->toChars());
}
#endif
if (!e)
{
if (d->getModule() != sc->module)
if (d->prot() == PROTprivate ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
}
else if (e->type->ty == Tclass)
{ // Do access check
ClassDeclaration *cd;
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
#if 1
if (e->op == TOKsuper)
{ ClassDeclaration *cd2;
cd2 = sc->func->toParent()->isClassDeclaration();
if (cd2)
cd = cd2;
}
#endif
cd->accessCheck(loc, sc, d);
}
else if (e->type->ty == Tstruct)
{ // Do access check
StructDeclaration *cd;
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
cd->accessCheck(loc, sc, d);
}
}

View File

@@ -1,292 +1,320 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_AGGREGATE_H
#define DMD_AGGREGATE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
#include <vector>
#include <set>
#include <map>
struct Identifier;
struct Type;
struct TypeFunction;
struct Expression;
struct FuncDeclaration;
struct CtorDeclaration;
struct DtorDeclaration;
struct InvariantDeclaration;
struct NewDeclaration;
struct DeleteDeclaration;
struct InterfaceDeclaration;
struct ClassInfoDeclaration;
struct VarDeclaration;
struct dt_t;
namespace llvm
{
class Type;
class Value;
class Constant;
class ConstantStruct;
class GlobalVariable;
}
struct AggregateDeclaration : ScopeDsymbol
{
Type *type;
unsigned storage_class;
enum PROT protection;
Type *handle; // 'this' type
unsigned structsize; // size of struct
unsigned alignsize; // size of struct for alignment purposes
unsigned structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields
Array fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated
Scope *scope; // !=NULL means context to use
// Special member functions
InvariantDeclaration *inv; // invariant
NewDeclaration *aggNew; // allocator
DeleteDeclaration *aggDelete; // deallocator
#if DMDV2
CtorDeclaration *ctor;
CtorDeclaration *defaultCtor; // default constructor
#endif
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
#ifdef IN_GCC
Array methods; // flat list of all methods for debug information
#endif
AggregateDeclaration(Loc loc, Identifier *id);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
unsigned size(Loc loc);
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
Type *getType();
void addField(Scope *sc, VarDeclaration *v);
int isDeprecated(); // is aggregate deprecated?
FuncDeclaration *buildDtor(Scope *sc);
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
// For access checking
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
int isFriendOf(AggregateDeclaration *cd);
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
enum PROT prot();
// Back end
Symbol *stag; // tag symbol for debug data
Symbol *sinit;
Symbol *toInitializer();
AggregateDeclaration *isAggregateDeclaration() { return this; }
};
struct AnonymousAggregateDeclaration : AggregateDeclaration
{
AnonymousAggregateDeclaration()
: AggregateDeclaration(0, NULL)
{
}
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
};
struct StructDeclaration : AggregateDeclaration
{
int zeroInit; // !=0 if initialize with 0 fill
#if DMDV2
int hasIdentityAssign; // !=0 if has identity opAssign
FuncDeclaration *cpctor; // generated copy-constructor, if any
FuncDeclarations postblits; // Array of postblit functions
FuncDeclaration *postblit; // aggregate postblit
#endif
StructDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
const char *kind();
int needOpAssign();
FuncDeclaration *buildOpAssign(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc);
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
void toObjFile(int multiobj); // compile to .obj file
void toDt(dt_t **pdt);
void toDebug(); // to symbolic debug info
StructDeclaration *isStructDeclaration() { return this; }
};
struct UnionDeclaration : StructDeclaration
{
UnionDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
const char *kind();
UnionDeclaration *isUnionDeclaration() { return this; }
};
struct BaseClass
{
Type *type; // (before semantic processing)
enum PROT protection; // protection for the base interface
ClassDeclaration *base;
int offset; // 'this' pointer offset
Array vtbl; // for interfaces: Array of FuncDeclaration's
// making up the vtbl[]
int baseInterfaces_dim;
BaseClass *baseInterfaces; // if BaseClass is an interface, these
// are a copy of the InterfaceDeclaration::interfaces
BaseClass();
BaseClass(Type *type, enum PROT protection);
int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
void copyBaseInterfaces(BaseClasses *);
};
#if DMDV2
#define CLASSINFO_SIZE (0x3C+16) // value of ClassInfo.size
#else
#define CLASSINFO_SIZE (0x3C+12) // value of ClassInfo.size
#endif
struct ClassDeclaration : AggregateDeclaration
{
static ClassDeclaration *object;
static ClassDeclaration *classinfo;
ClassDeclaration *baseClass; // NULL only if this is Object
FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor;
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
BaseClasses baseclasses; // Array of BaseClass's; first is super,
// rest are Interface's
int interfaces_dim;
BaseClass **interfaces; // interfaces[interfaces_dim] for this class
// (does not include baseClass)
BaseClasses *vtblInterfaces; // array of base interfaces that have
// their own vtbl[]
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
int com; // !=0 if this is a COM class (meaning
// it derives from IUnknown)
int isauto; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
int isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this class is nested
int inuse; // to prevent recursive attempts
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isBaseOf2(ClassDeclaration *cd);
#define OFFSET_RUNTIME 0x76543210
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
Dsymbol *search(Loc, Identifier *ident, int flags);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
int isNested();
int isCOMclass();
virtual int isCOMinterface();
#if DMDV2
virtual int isCPPinterface();
#endif
int isAbstract();
virtual int vtblOffset();
const char *kind();
char *mangle();
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
void addLocalClass(ClassDeclarations *);
// Back end
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
unsigned baseVtblOffset(BaseClass *bc);
Symbol *toSymbol();
Symbol *toVtblSymbol();
void toDt(dt_t **pdt);
void toDt2(dt_t **pdt, ClassDeclaration *cd);
Symbol *vtblsym;
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
};
struct InterfaceDeclaration : ClassDeclaration
{
#if DMDV2
int cpp; // !=0 if this is a C++ interface
#endif
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int isBaseOf(ClassDeclaration *cd, int *poffset);
int isBaseOf(BaseClass *bc, int *poffset);
const char *kind();
int vtblOffset();
#if DMDV2
int isCPPinterface();
#endif
virtual int isCOMinterface();
void toObjFile(int multiobj); // compile to .obj file
Symbol *toSymbol();
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
};
#endif /* DMD_AGGREGATE_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_AGGREGATE_H
#define DMD_AGGREGATE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
#if IN_LLVM
#include <vector>
#include <set>
#include <map>
#endif
struct Identifier;
struct Type;
struct TypeFunction;
struct Expression;
struct FuncDeclaration;
struct CtorDeclaration;
struct DtorDeclaration;
struct InvariantDeclaration;
struct NewDeclaration;
struct DeleteDeclaration;
struct InterfaceDeclaration;
struct ClassInfoDeclaration;
struct VarDeclaration;
struct dt_t;
#if IN_LLVM
namespace llvm
{
class Type;
class Value;
class Constant;
class ConstantStruct;
class GlobalVariable;
}
#endif
struct AggregateDeclaration : ScopeDsymbol
{
Type *type;
unsigned storage_class;
enum PROT protection;
Type *handle; // 'this' type
unsigned structsize; // size of struct
unsigned alignsize; // size of struct for alignment purposes
unsigned structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields
Array fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated
Scope *scope; // !=NULL means context to use
int isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
// Special member functions
InvariantDeclaration *inv; // invariant
NewDeclaration *aggNew; // allocator
DeleteDeclaration *aggDelete; // deallocator
#if DMDV2
//CtorDeclaration *ctor;
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
CtorDeclaration *defaultCtor; // default constructor
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
#endif
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
#ifdef IN_GCC
Array methods; // flat list of all methods for debug information
#endif
AggregateDeclaration(Loc loc, Identifier *id);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
unsigned size(Loc loc);
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
Type *getType();
void addField(Scope *sc, VarDeclaration *v);
int isDeprecated(); // is aggregate deprecated?
FuncDeclaration *buildDtor(Scope *sc);
int isNested();
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
// For access checking
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
int isFriendOf(AggregateDeclaration *cd);
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
enum PROT prot();
#if IN_DMD
// Back end
Symbol *stag; // tag symbol for debug data
Symbol *sinit;
Symbol *toInitializer();
#endif
AggregateDeclaration *isAggregateDeclaration() { return this; }
};
struct AnonymousAggregateDeclaration : AggregateDeclaration
{
AnonymousAggregateDeclaration()
: AggregateDeclaration(0, NULL)
{
}
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
};
struct StructDeclaration : AggregateDeclaration
{
int zeroInit; // !=0 if initialize with 0 fill
#if DMDV2
int hasIdentityAssign; // !=0 if has identity opAssign
FuncDeclaration *cpctor; // generated copy-constructor, if any
FuncDeclarations postblits; // Array of postblit functions
FuncDeclaration *postblit; // aggregate postblit
#endif
StructDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
const char *kind();
int needOpAssign();
FuncDeclaration *buildOpAssign(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc);
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
void toDt(dt_t **pdt);
void toDebug(); // to symbolic debug info
#endif
StructDeclaration *isStructDeclaration() { return this; }
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct UnionDeclaration : StructDeclaration
{
UnionDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
const char *kind();
UnionDeclaration *isUnionDeclaration() { return this; }
};
// warning: two classes with the same base class share the same
// BaseClass instance.
struct BaseClass
{
Type *type; // (before semantic processing)
enum PROT protection; // protection for the base interface
ClassDeclaration *base;
int offset; // 'this' pointer offset
Array vtbl; // for interfaces: Array of FuncDeclaration's
// making up the vtbl[]
int baseInterfaces_dim;
BaseClass *baseInterfaces; // if BaseClass is an interface, these
// are a copy of the InterfaceDeclaration::interfaces
BaseClass();
BaseClass(Type *type, enum PROT protection);
int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
void copyBaseInterfaces(BaseClasses *);
};
#if DMDV2
#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size
#else
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#endif
struct ClassDeclaration : AggregateDeclaration
{
static ClassDeclaration *object;
static ClassDeclaration *classinfo;
ClassDeclaration *baseClass; // NULL only if this is Object
FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor;
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
BaseClasses baseclasses; // Array of BaseClass's; first is super,
// rest are Interface's
int interfaces_dim;
BaseClass **interfaces; // interfaces[interfaces_dim] for this class
// (does not include baseClass)
BaseClasses *vtblInterfaces; // array of base interfaces that have
// their own vtbl[]
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
int com; // !=0 if this is a COM class (meaning
// it derives from IUnknown)
int isauto; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
int inuse; // to prevent recursive attempts
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isBaseOf2(ClassDeclaration *cd);
#define OFFSET_RUNTIME 0x76543210
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
Dsymbol *search(Loc, Identifier *ident, int flags);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
int isCOMclass();
virtual int isCOMinterface();
#if DMDV2
virtual int isCPPinterface();
#endif
int isAbstract();
virtual int vtblOffset();
const char *kind();
char *mangle();
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
void addLocalClass(ClassDeclarations *);
#if IN_DMD
// Back end
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
unsigned baseVtblOffset(BaseClass *bc);
Symbol *toSymbol();
Symbol *toVtblSymbol();
void toDt(dt_t **pdt);
void toDt2(dt_t **pdt, ClassDeclaration *cd);
Symbol *vtblsym;
#endif
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
#if IN_LLVM
virtual void codegen(Ir*);
#endif
};
struct InterfaceDeclaration : ClassDeclaration
{
#if DMDV2
int cpp; // !=0 if this is a C++ interface
#endif
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int isBaseOf(ClassDeclaration *cd, int *poffset);
int isBaseOf(BaseClass *bc, int *poffset);
const char *kind();
int vtblOffset();
#if DMDV2
int isCPPinterface();
#endif
virtual int isCOMinterface();
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
Symbol *toSymbol();
#endif
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
#if IN_LLVM
void codegen(Ir*);
#endif
};
#endif /* DMD_AGGREGATE_H */

72
dmd2/aliasthis.c Normal file
View File

@@ -0,0 +1,72 @@
// Compiler implementation of the D programming language
// Copyright (c) 2009-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "identifier.h"
#include "aliasthis.h"
#include "scope.h"
#include "aggregate.h"
#include "dsymbol.h"
#if DMDV2
AliasThis::AliasThis(Loc loc, Identifier *ident)
: Dsymbol(NULL) // it's anonymous (no identifier)
{
this->loc = loc;
this->ident = ident;
}
Dsymbol *AliasThis::syntaxCopy(Dsymbol *s)
{
assert(!s);
/* Since there is no semantic information stored here,
* we don't need to copy it.
*/
return this;
}
void AliasThis::semantic(Scope *sc)
{
Dsymbol *parent = sc->parent;
if (parent)
parent = parent->pastMixin();
AggregateDeclaration *ad = NULL;
if (parent)
ad = parent->isAggregateDeclaration();
if (ad)
{
if (ad->aliasthis)
error("there can be only one alias this");
assert(ad->members);
Dsymbol *s = ad->search(loc, ident, 0);
ad->aliasthis = s;
}
else
error("alias this can only appear in struct or class declaration, not %s", parent ? parent->toChars() : "nowhere");
}
const char *AliasThis::kind()
{
return "alias this";
}
void AliasThis::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("alias ");
buf->writestring(ident->toChars());
buf->writestring(" this;\n");
}
#endif

41
dmd2/aliasthis.h Normal file
View File

@@ -0,0 +1,41 @@
// Compiler implementation of the D programming language
// Copyright (c) 2009-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ALIASTHIS_H
#define DMD_ALIASTHIS_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "mars.h"
#include "dsymbol.h"
/**************************************************************/
#if DMDV2
struct AliasThis : Dsymbol
{
// alias Identifier this;
Identifier *ident;
AliasThis(Loc loc, Identifier *ident);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
const char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AliasThis *isAliasThis() { return this; }
};
#endif
#endif

View File

@@ -1,494 +1,505 @@
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#if _WIN32 || IN_GCC || IN_LLVM
#include "mem.h"
#else
#include "../root/mem.h"
#endif
#include "stringtable.h"
#include "expression.h"
#include "statement.h"
#include "mtype.h"
#include "declaration.h"
#include "scope.h"
#include "id.h"
#include "module.h"
#include "init.h"
/***********************************
* Construct the array operation expression.
*/
Expression *BinExp::arrayOp(Scope *sc)
{
Expressions *arguments = new Expressions();
/* The expression to generate an array operation for is mangled
* into a name to use as the array operation function name.
* Mangle in the operands and operators in RPN order, and type.
*/
OutBuffer buf;
buf.writestring("_array");
buildArrayIdent(&buf, arguments);
buf.writeByte('_');
/* Append deco of array element type
*/
#if DMDV2
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
#else
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
#endif
size_t namelen = buf.offset;
buf.writeByte(0);
char *name = (char *)buf.extractData();
/* Look up name in hash table
*/
StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
if (!fd)
{
// /* Some of the array op functions are written as library functions,
// * presumably to optimize them with special CPU vector instructions.
// * List those library functions here, in alpha order.
// */
// static const char *libArrayopFuncs[] =
// {
// "_arrayExpSliceAddass_a",
// "_arrayExpSliceAddass_d", // T[]+=T
// "_arrayExpSliceAddass_f", // T[]+=T
// "_arrayExpSliceAddass_g",
// "_arrayExpSliceAddass_h",
// "_arrayExpSliceAddass_i",
// "_arrayExpSliceAddass_k",
// "_arrayExpSliceAddass_s",
// "_arrayExpSliceAddass_t",
// "_arrayExpSliceAddass_u",
// "_arrayExpSliceAddass_w",
//
// "_arrayExpSliceDivass_d", // T[]/=T
// "_arrayExpSliceDivass_f", // T[]/=T
//
// "_arrayExpSliceMinSliceAssign_a",
// "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
// "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
// "_arrayExpSliceMinSliceAssign_g",
// "_arrayExpSliceMinSliceAssign_h",
// "_arrayExpSliceMinSliceAssign_i",
// "_arrayExpSliceMinSliceAssign_k",
// "_arrayExpSliceMinSliceAssign_s",
// "_arrayExpSliceMinSliceAssign_t",
// "_arrayExpSliceMinSliceAssign_u",
// "_arrayExpSliceMinSliceAssign_w",
//
// "_arrayExpSliceMinass_a",
// "_arrayExpSliceMinass_d", // T[]-=T
// "_arrayExpSliceMinass_f", // T[]-=T
// "_arrayExpSliceMinass_g",
// "_arrayExpSliceMinass_h",
// "_arrayExpSliceMinass_i",
// "_arrayExpSliceMinass_k",
// "_arrayExpSliceMinass_s",
// "_arrayExpSliceMinass_t",
// "_arrayExpSliceMinass_u",
// "_arrayExpSliceMinass_w",
//
// "_arrayExpSliceMulass_d", // T[]*=T
// "_arrayExpSliceMulass_f", // T[]*=T
// "_arrayExpSliceMulass_i",
// "_arrayExpSliceMulass_k",
// "_arrayExpSliceMulass_s",
// "_arrayExpSliceMulass_t",
// "_arrayExpSliceMulass_u",
// "_arrayExpSliceMulass_w",
//
// "_arraySliceExpAddSliceAssign_a",
// "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
// "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
// "_arraySliceExpAddSliceAssign_g",
// "_arraySliceExpAddSliceAssign_h",
// "_arraySliceExpAddSliceAssign_i",
// "_arraySliceExpAddSliceAssign_k",
// "_arraySliceExpAddSliceAssign_s",
// "_arraySliceExpAddSliceAssign_t",
// "_arraySliceExpAddSliceAssign_u",
// "_arraySliceExpAddSliceAssign_w",
//
// "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
// "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
//
// "_arraySliceExpMinSliceAssign_a",
// "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
// "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
// "_arraySliceExpMinSliceAssign_g",
// "_arraySliceExpMinSliceAssign_h",
// "_arraySliceExpMinSliceAssign_i",
// "_arraySliceExpMinSliceAssign_k",
// "_arraySliceExpMinSliceAssign_s",
// "_arraySliceExpMinSliceAssign_t",
// "_arraySliceExpMinSliceAssign_u",
// "_arraySliceExpMinSliceAssign_w",
//
// "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
// "_arraySliceExpMulSliceAddass_f",
// "_arraySliceExpMulSliceAddass_r",
//
// "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
// "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
// "_arraySliceExpMulSliceAssign_i",
// "_arraySliceExpMulSliceAssign_k",
// "_arraySliceExpMulSliceAssign_s",
// "_arraySliceExpMulSliceAssign_t",
// "_arraySliceExpMulSliceAssign_u",
// "_arraySliceExpMulSliceAssign_w",
//
// "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
// "_arraySliceExpMulSliceMinass_f",
// "_arraySliceExpMulSliceMinass_r",
//
// "_arraySliceSliceAddSliceAssign_a",
// "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
// "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
// "_arraySliceSliceAddSliceAssign_g",
// "_arraySliceSliceAddSliceAssign_h",
// "_arraySliceSliceAddSliceAssign_i",
// "_arraySliceSliceAddSliceAssign_k",
// "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
// "_arraySliceSliceAddSliceAssign_s",
// "_arraySliceSliceAddSliceAssign_t",
// "_arraySliceSliceAddSliceAssign_u",
// "_arraySliceSliceAddSliceAssign_w",
//
// "_arraySliceSliceAddass_a",
// "_arraySliceSliceAddass_d", // T[]+=T[]
// "_arraySliceSliceAddass_f", // T[]+=T[]
// "_arraySliceSliceAddass_g",
// "_arraySliceSliceAddass_h",
// "_arraySliceSliceAddass_i",
// "_arraySliceSliceAddass_k",
// "_arraySliceSliceAddass_s",
// "_arraySliceSliceAddass_t",
// "_arraySliceSliceAddass_u",
// "_arraySliceSliceAddass_w",
//
// "_arraySliceSliceMinSliceAssign_a",
// "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
// "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
// "_arraySliceSliceMinSliceAssign_g",
// "_arraySliceSliceMinSliceAssign_h",
// "_arraySliceSliceMinSliceAssign_i",
// "_arraySliceSliceMinSliceAssign_k",
// "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
// "_arraySliceSliceMinSliceAssign_s",
// "_arraySliceSliceMinSliceAssign_t",
// "_arraySliceSliceMinSliceAssign_u",
// "_arraySliceSliceMinSliceAssign_w",
//
// "_arraySliceSliceMinass_a",
// "_arraySliceSliceMinass_d", // T[]-=T[]
// "_arraySliceSliceMinass_f", // T[]-=T[]
// "_arraySliceSliceMinass_g",
// "_arraySliceSliceMinass_h",
// "_arraySliceSliceMinass_i",
// "_arraySliceSliceMinass_k",
// "_arraySliceSliceMinass_s",
// "_arraySliceSliceMinass_t",
// "_arraySliceSliceMinass_u",
// "_arraySliceSliceMinass_w",
//
// "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
// "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
// "_arraySliceSliceMulSliceAssign_i",
// "_arraySliceSliceMulSliceAssign_k",
// "_arraySliceSliceMulSliceAssign_s",
// "_arraySliceSliceMulSliceAssign_t",
// "_arraySliceSliceMulSliceAssign_u",
// "_arraySliceSliceMulSliceAssign_w",
//
// "_arraySliceSliceMulass_d", // T[]*=T[]
// "_arraySliceSliceMulass_f", // T[]*=T[]
// "_arraySliceSliceMulass_i",
// "_arraySliceSliceMulass_k",
// "_arraySliceSliceMulass_s",
// "_arraySliceSliceMulass_t",
// "_arraySliceSliceMulass_u",
// "_arraySliceSliceMulass_w",
// };
//
// int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
// if (i == -1)
// {
// #ifdef DEBUG // Make sure our array is alphabetized
// for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
// {
// if (strcmp(name, libArrayopFuncs[i]) == 0)
// assert(0);
// }
// #endif
/* Not in library, so generate it.
* Construct the function body:
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
* loopbody;
* return p;
*/
Arguments *fparams = new Arguments();
Expression *loopbody = buildArrayLoop(fparams);
Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
#if DMDV1
// for (size_t i = 0; i < p.length; i++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
Statement *s1 = new ForStatement(0,
new DeclarationStatement(0, d),
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
new ExpStatement(0, loopbody));
#else
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
new Argument(0, NULL, Id::p, NULL),
new IntegerExp(0, 0, Type::tint32),
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
new ExpStatement(0, loopbody));
#endif
Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
//printf("s2: %s\n", s2->toChars());
Statement *fbody = new CompoundStatement(0, s1, s2);
/* Construct the function
*/
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
//printf("ftype: %s\n", ftype->toChars());
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTprotected;
fd->linkage = LINKd;
// special attention for array ops
fd->isArrayOp = true;
sc->module->members->push(fd);
sc = sc->push();
sc->parent = sc->module;
sc->stc = 0;
sc->linkage = LINKd;
fd->semantic(sc);
sc->pop();
// }
// else
// { /* In library, refer to it.
// */
// // FIXME
// fd = FuncDeclaration::genCfunc(NULL, type, name);
// }
sv->ptrvalue = fd; // cache symbol in hash table
}
/* Call the function fd(arguments)
*/
Expression *ec = new VarExp(0, fd);
Expression *e = new CallExp(loc, ec, arguments);
e->type = type;
return e;
}
/******************************************
* Construct the identifier for the array operation function,
* and build the argument list to pass to it.
*/
void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Exp");
arguments->shift(this);
}
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Slice");
arguments->shift(this);
}
void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
/* Evaluate assign expressions right to left
*/
e2->buildArrayIdent(buf, arguments);
e1->buildArrayIdent(buf, arguments);
buf->writestring("Assign");
}
#define X(Str) \
void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
{ \
/* Evaluate assign expressions right to left \
*/ \
e2->buildArrayIdent(buf, arguments); \
e1->buildArrayIdent(buf, arguments); \
buf->writestring(#Str); \
buf->writestring("ass"); \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
e1->buildArrayIdent(buf, arguments);
buf->writestring("Neg");
}
void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
e1->buildArrayIdent(buf, arguments);
buf->writestring("Com");
}
#define X(Str) \
void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
{ \
/* Evaluate assign expressions left to right \
*/ \
e1->buildArrayIdent(buf, arguments); \
e2->buildArrayIdent(buf, arguments); \
buf->writestring(#Str); \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
/******************************************
* Construct the inner loop for the array operation function,
* and build the parameter list.
*/
Expression *Expression::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("c", fparams->dim);
Argument *param = new Argument(0, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
return e;
}
Expression *SliceExp::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
Argument *param = new Argument(STCconst, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
Expressions *arguments = new Expressions();
Expression *index = new IdentifierExp(0, Id::p);
arguments->push(index);
e = new ArrayExp(0, e, arguments);
return e;
}
Expression *AssignExp::buildArrayLoop(Arguments *fparams)
{
/* Evaluate assign expressions right to left
*/
Expression *ex2 = e2->buildArrayLoop(fparams);
Expression *ex1 = e1->buildArrayLoop(fparams);
Argument *param = (Argument *)fparams->data[0];
param->storageClass = 0;
Expression *e = new AssignExp(0, ex1, ex2);
return e;
}
#define X(Str) \
Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \
{ \
/* Evaluate assign expressions right to left \
*/ \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Argument *param = (Argument *)fparams->data[0]; \
param->storageClass = 0; \
Expression *e = new Str##AssignExp(0, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
Expression *NegExp::buildArrayLoop(Arguments *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new NegExp(0, ex1);
return e;
}
Expression *ComExp::buildArrayLoop(Arguments *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new ComExp(0, ex1);
return e;
}
#define X(Str) \
Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \
{ \
/* Evaluate assign expressions left to right \
*/ \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *e = new Str##Exp(0, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "rmem.h"
#include "stringtable.h"
#include "expression.h"
#include "statement.h"
#include "mtype.h"
#include "declaration.h"
#include "scope.h"
#include "id.h"
#include "module.h"
#include "init.h"
#if IN_DMD
extern int binary(const char *p , const char **tab, int high);
/**************************************
* Hash table of array op functions already generated or known about.
*/
StringTable arrayfuncs;
#endif
/***********************************
* Construct the array operation expression.
*/
Expression *BinExp::arrayOp(Scope *sc)
{
Expressions *arguments = new Expressions();
/* The expression to generate an array operation for is mangled
* into a name to use as the array operation function name.
* Mangle in the operands and operators in RPN order, and type.
*/
OutBuffer buf;
buf.writestring("_array");
buildArrayIdent(&buf, arguments);
buf.writeByte('_');
/* Append deco of array element type
*/
#if DMDV2
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
#else
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
#endif
size_t namelen = buf.offset;
buf.writeByte(0);
char *name = (char *)buf.extractData();
/* Look up name in hash table
*/
#if IN_LLVM
StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
#else
StringValue *sv = arrayfuncs.update(name, namelen);
#endif
FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
if (!fd)
{
#if IN_DMD
/* Some of the array op functions are written as library functions,
* presumably to optimize them with special CPU vector instructions.
* List those library functions here, in alpha order.
*/
static const char *libArrayopFuncs[] =
{
"_arrayExpSliceAddass_a",
"_arrayExpSliceAddass_d", // T[]+=T
"_arrayExpSliceAddass_f", // T[]+=T
"_arrayExpSliceAddass_g",
"_arrayExpSliceAddass_h",
"_arrayExpSliceAddass_i",
"_arrayExpSliceAddass_k",
"_arrayExpSliceAddass_s",
"_arrayExpSliceAddass_t",
"_arrayExpSliceAddass_u",
"_arrayExpSliceAddass_w",
"_arrayExpSliceDivass_d", // T[]/=T
"_arrayExpSliceDivass_f", // T[]/=T
"_arrayExpSliceMinSliceAssign_a",
"_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_g",
"_arrayExpSliceMinSliceAssign_h",
"_arrayExpSliceMinSliceAssign_i",
"_arrayExpSliceMinSliceAssign_k",
"_arrayExpSliceMinSliceAssign_s",
"_arrayExpSliceMinSliceAssign_t",
"_arrayExpSliceMinSliceAssign_u",
"_arrayExpSliceMinSliceAssign_w",
"_arrayExpSliceMinass_a",
"_arrayExpSliceMinass_d", // T[]-=T
"_arrayExpSliceMinass_f", // T[]-=T
"_arrayExpSliceMinass_g",
"_arrayExpSliceMinass_h",
"_arrayExpSliceMinass_i",
"_arrayExpSliceMinass_k",
"_arrayExpSliceMinass_s",
"_arrayExpSliceMinass_t",
"_arrayExpSliceMinass_u",
"_arrayExpSliceMinass_w",
"_arrayExpSliceMulass_d", // T[]*=T
"_arrayExpSliceMulass_f", // T[]*=T
"_arrayExpSliceMulass_i",
"_arrayExpSliceMulass_k",
"_arrayExpSliceMulass_s",
"_arrayExpSliceMulass_t",
"_arrayExpSliceMulass_u",
"_arrayExpSliceMulass_w",
"_arraySliceExpAddSliceAssign_a",
"_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_g",
"_arraySliceExpAddSliceAssign_h",
"_arraySliceExpAddSliceAssign_i",
"_arraySliceExpAddSliceAssign_k",
"_arraySliceExpAddSliceAssign_s",
"_arraySliceExpAddSliceAssign_t",
"_arraySliceExpAddSliceAssign_u",
"_arraySliceExpAddSliceAssign_w",
"_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
"_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
"_arraySliceExpMinSliceAssign_a",
"_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_g",
"_arraySliceExpMinSliceAssign_h",
"_arraySliceExpMinSliceAssign_i",
"_arraySliceExpMinSliceAssign_k",
"_arraySliceExpMinSliceAssign_s",
"_arraySliceExpMinSliceAssign_t",
"_arraySliceExpMinSliceAssign_u",
"_arraySliceExpMinSliceAssign_w",
"_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
"_arraySliceExpMulSliceAddass_f",
"_arraySliceExpMulSliceAddass_r",
"_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_i",
"_arraySliceExpMulSliceAssign_k",
"_arraySliceExpMulSliceAssign_s",
"_arraySliceExpMulSliceAssign_t",
"_arraySliceExpMulSliceAssign_u",
"_arraySliceExpMulSliceAssign_w",
"_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
"_arraySliceExpMulSliceMinass_f",
"_arraySliceExpMulSliceMinass_r",
"_arraySliceSliceAddSliceAssign_a",
"_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_g",
"_arraySliceSliceAddSliceAssign_h",
"_arraySliceSliceAddSliceAssign_i",
"_arraySliceSliceAddSliceAssign_k",
"_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_s",
"_arraySliceSliceAddSliceAssign_t",
"_arraySliceSliceAddSliceAssign_u",
"_arraySliceSliceAddSliceAssign_w",
"_arraySliceSliceAddass_a",
"_arraySliceSliceAddass_d", // T[]+=T[]
"_arraySliceSliceAddass_f", // T[]+=T[]
"_arraySliceSliceAddass_g",
"_arraySliceSliceAddass_h",
"_arraySliceSliceAddass_i",
"_arraySliceSliceAddass_k",
"_arraySliceSliceAddass_s",
"_arraySliceSliceAddass_t",
"_arraySliceSliceAddass_u",
"_arraySliceSliceAddass_w",
"_arraySliceSliceMinSliceAssign_a",
"_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_g",
"_arraySliceSliceMinSliceAssign_h",
"_arraySliceSliceMinSliceAssign_i",
"_arraySliceSliceMinSliceAssign_k",
"_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_s",
"_arraySliceSliceMinSliceAssign_t",
"_arraySliceSliceMinSliceAssign_u",
"_arraySliceSliceMinSliceAssign_w",
"_arraySliceSliceMinass_a",
"_arraySliceSliceMinass_d", // T[]-=T[]
"_arraySliceSliceMinass_f", // T[]-=T[]
"_arraySliceSliceMinass_g",
"_arraySliceSliceMinass_h",
"_arraySliceSliceMinass_i",
"_arraySliceSliceMinass_k",
"_arraySliceSliceMinass_s",
"_arraySliceSliceMinass_t",
"_arraySliceSliceMinass_u",
"_arraySliceSliceMinass_w",
"_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_i",
"_arraySliceSliceMulSliceAssign_k",
"_arraySliceSliceMulSliceAssign_s",
"_arraySliceSliceMulSliceAssign_t",
"_arraySliceSliceMulSliceAssign_u",
"_arraySliceSliceMulSliceAssign_w",
"_arraySliceSliceMulass_d", // T[]*=T[]
"_arraySliceSliceMulass_f", // T[]*=T[]
"_arraySliceSliceMulass_i",
"_arraySliceSliceMulass_k",
"_arraySliceSliceMulass_s",
"_arraySliceSliceMulass_t",
"_arraySliceSliceMulass_u",
"_arraySliceSliceMulass_w",
};
int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
if (i == -1)
{
#ifdef DEBUG // Make sure our array is alphabetized
for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
{
if (strcmp(name, libArrayopFuncs[i]) == 0)
assert(0);
}
#endif
#endif
/* Not in library, so generate it.
* Construct the function body:
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
* loopbody;
* return p;
*/
Arguments *fparams = new Arguments();
Expression *loopbody = buildArrayLoop(fparams);
Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
#if DMDV1
// for (size_t i = 0; i < p.length; i++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
Statement *s1 = new ForStatement(0,
new DeclarationStatement(0, d),
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
new ExpStatement(0, loopbody));
#else
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
new Argument(0, NULL, Id::p, NULL),
new IntegerExp(0, 0, Type::tint32),
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
new ExpStatement(0, loopbody));
#endif
Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
//printf("s2: %s\n", s2->toChars());
Statement *fbody = new CompoundStatement(0, s1, s2);
/* Construct the function
*/
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
//printf("ftype: %s\n", ftype->toChars());
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKd;
// special attention for array ops
fd->isArrayOp = true;
sc->module->importedFrom->members->push(fd);
sc = sc->push();
sc->parent = sc->module->importedFrom;
sc->stc = 0;
sc->linkage = LINKc;
fd->semantic(sc);
sc->pop();
#if IN_DMD
}
else
{ /* In library, refer to it.
*/
fd = FuncDeclaration::genCfunc(type, name);
}
#endif
sv->ptrvalue = fd; // cache symbol in hash table
}
/* Call the function fd(arguments)
*/
Expression *ec = new VarExp(0, fd);
Expression *e = new CallExp(loc, ec, arguments);
e->type = type;
return e;
}
/******************************************
* Construct the identifier for the array operation function,
* and build the argument list to pass to it.
*/
void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Exp");
arguments->shift(this);
}
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Slice");
arguments->shift(this);
}
void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
/* Evaluate assign expressions right to left
*/
e2->buildArrayIdent(buf, arguments);
e1->buildArrayIdent(buf, arguments);
buf->writestring("Assign");
}
#define X(Str) \
void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
{ \
/* Evaluate assign expressions right to left \
*/ \
e2->buildArrayIdent(buf, arguments); \
e1->buildArrayIdent(buf, arguments); \
buf->writestring(#Str); \
buf->writestring("ass"); \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
e1->buildArrayIdent(buf, arguments);
buf->writestring("Neg");
}
void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
e1->buildArrayIdent(buf, arguments);
buf->writestring("Com");
}
#define X(Str) \
void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
{ \
/* Evaluate assign expressions left to right \
*/ \
e1->buildArrayIdent(buf, arguments); \
e2->buildArrayIdent(buf, arguments); \
buf->writestring(#Str); \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
/******************************************
* Construct the inner loop for the array operation function,
* and build the parameter list.
*/
Expression *Expression::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("c", fparams->dim);
Argument *param = new Argument(0, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
return e;
}
Expression *SliceExp::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
Argument *param = new Argument(STCconst, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
Expressions *arguments = new Expressions();
Expression *index = new IdentifierExp(0, Id::p);
arguments->push(index);
e = new ArrayExp(0, e, arguments);
return e;
}
Expression *AssignExp::buildArrayLoop(Arguments *fparams)
{
/* Evaluate assign expressions right to left
*/
Expression *ex2 = e2->buildArrayLoop(fparams);
Expression *ex1 = e1->buildArrayLoop(fparams);
Argument *param = (Argument *)fparams->data[0];
param->storageClass = 0;
Expression *e = new AssignExp(0, ex1, ex2);
return e;
}
#define X(Str) \
Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \
{ \
/* Evaluate assign expressions right to left \
*/ \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Argument *param = (Argument *)fparams->data[0]; \
param->storageClass = 0; \
Expression *e = new Str##AssignExp(0, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X
Expression *NegExp::buildArrayLoop(Arguments *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new NegExp(0, ex1);
return e;
}
Expression *ComExp::buildArrayLoop(Arguments *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new ComExp(0, ex1);
return e;
}
#define X(Str) \
Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \
{ \
/* Evaluate assign expressions left to right \
*/ \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *e = new Str##Exp(0, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#undef X

File diff suppressed because it is too large Load Diff

View File

@@ -50,8 +50,14 @@ struct AttribDeclaration : Dsymbol
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AttribDeclaration *isAttribDeclaration() { return this; }
virtual void toObjFile(int multiobj); // compile to .obj file
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
#endif
#if IN_LLVM
virtual void codegen(Ir*);
#endif
};
struct StorageClassDeclaration: AttribDeclaration
@@ -62,6 +68,8 @@ struct StorageClassDeclaration: AttribDeclaration
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void stcToCBuffer(OutBuffer *buf, int stc);
};
struct LinkDeclaration : AttribDeclaration
@@ -107,9 +115,6 @@ struct AnonDeclaration : AttribDeclaration
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
// LDC
void toObjFile(int multiobj); // compile to .obj file
};
struct PragmaDeclaration : AttribDeclaration
@@ -122,7 +127,14 @@ struct PragmaDeclaration : AttribDeclaration
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
#endif
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct ConditionalDeclaration : AttribDeclaration

42
dmd2/backendlicense.txt Normal file
View File

@@ -0,0 +1,42 @@
The Software is not generally available software. It has not undergone
testing and may contain errors. The Software was not designed to operate
after December 31, 1999. It may be incomplete and it may not function
properly. No support or maintenance is provided with this Software. Do
not install or distribute the Software if
you are not accustomed to using or distributing experimental software.
Do not use this software for life critical applications, or applications
that could cause significant harm or property damage.
Digital Mars licenses the Software to you on an "AS IS" basis, without
warranty of any kind. DIGITAL MARS AND SYMANTEC HEREBY EXPRESSLY DISCLAIM
ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY,
NONINFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. You are solely
responsible for determining the appropriateness of using this Software and
assume all risks associated with the use of this Software, including but not
limited to the risks of program errors, damage
to or loss of data, programs or equipment, unavailability or interruption of
operations and third party claims. You agree to defend, indemnify and hold
Digital Mars and Symantec, its subsidiaries, affiliates, directors, officers,
employees and agents harmless from all claims or demands made against them
(and any related losses, damages, expenses
and costs) arising out of your use of the Software. DIGITAL MARS AND SYMANTEC
WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, INCIDENTAL, OR
INDIRECT DAMAGES OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING
LOST PROFITS OR SAVINGS), EVEN IF DIGITAL MARS OR SYMANTEC HAS BEEN ADVISED
OF THE POSSIBILITY OF SUCH DAMAGES.
Digital Mars and Symantec will not be liable for the loss of, or damage to,
your records or data, the records or
data of any third party, or any damages claimed by you based on a third party
claim.
If you send any messages to Digital Mars, on either the Digital Mars
newsgroups, the Digital Mars mailing list, or via email, you agree not
to make any claims of intellectual
property rights over the contents of those messages.
The Software is copyrighted and comes with a single user license,
and may not be redistributed. If you wish to obtain a redistribution license,
please contact Digital Mars.

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -23,12 +23,15 @@
#include "id.h"
#include "module.h"
#if DMDV2
/**********************************
* Determine if function is a builtin one.
* Determine if function is a builtin one that we can
* evaluate at compile time.
*/
enum BUILTIN FuncDeclaration::isBuiltin()
{
static const char FeZe[] = "FeZe"; // real function(real)
static const char FeZe[] = "FNaNbeZe"; // pure nothrow real function(real)
//printf("FuncDeclaration::isBuiltin() %s\n", toChars());
if (builtin == BUILTINunknown)
@@ -36,10 +39,12 @@ enum BUILTIN FuncDeclaration::isBuiltin()
builtin = BUILTINnot;
if (parent && parent->isModule())
{
// If it's in the std.math package
if (parent->ident == Id::math &&
parent->parent && parent->parent->ident == Id::std &&
!parent->parent->parent)
{
//printf("deco = %s\n", type->deco);
if (strcmp(type->deco, FeZe) == 0)
{
if (ident == Id::sin)
@@ -54,6 +59,13 @@ enum BUILTIN FuncDeclaration::isBuiltin()
builtin = BUILTINfabs;
//printf("builtin = %d\n", builtin);
}
// if float or double versions
else if (strcmp(type->deco, "FNaNbdZd") == 0 ||
strcmp(type->deco, "FNaNbfZf") == 0)
{
if (ident == Id::_sqrt)
builtin = BUILTINsqrt;
}
}
}
}
@@ -75,28 +87,30 @@ Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments)
{
case BUILTINsin:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sinl(arg0->toReal()), Type::tfloat80);
e = new RealExp(0, sinl(arg0->toReal()), arg0->type);
break;
case BUILTINcos:
if (arg0->op == TOKfloat64)
e = new RealExp(0, cosl(arg0->toReal()), Type::tfloat80);
e = new RealExp(0, cosl(arg0->toReal()), arg0->type);
break;
case BUILTINtan:
if (arg0->op == TOKfloat64)
e = new RealExp(0, tanl(arg0->toReal()), Type::tfloat80);
e = new RealExp(0, tanl(arg0->toReal()), arg0->type);
break;
case BUILTINsqrt:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sqrtl(arg0->toReal()), Type::tfloat80);
e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type);
break;
case BUILTINfabs:
if (arg0->op == TOKfloat64)
e = new RealExp(0, fabsl(arg0->toReal()), Type::tfloat80);
e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
break;
}
return e;
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,437 +1,443 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "aggregate.h"
#include "scope.h"
#include "mtype.h"
#include "declaration.h"
#include "module.h"
#include "id.h"
#include "expression.h"
#include "statement.h"
#include "init.h"
/*******************************************
* We need an opAssign for the struct if
* it has a destructor or a postblit.
* We need to generate one if a user-specified one does not exist.
*/
int StructDeclaration::needOpAssign()
{
#define X 0
if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
if (hasIdentityAssign)
goto Ldontneed;
if (dtor || postblit)
goto Lneed;
/* If any of the fields need an opAssign, then we
* need it too.
*/
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
Type *tv = v->type->toBasetype();
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->needOpAssign())
goto Lneed;
}
}
Ldontneed:
if (X) printf("\tdontneed\n");
return 0;
Lneed:
if (X) printf("\tneed\n");
return 1;
#undef X
}
/******************************************
* Build opAssign for struct.
* S* opAssign(S s) { ... }
*/
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
{
if (!needOpAssign())
return NULL;
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
FuncDeclaration *fop = NULL;
Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
Arguments *fparams = new Arguments;
fparams->push(param);
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
#if STRUCTTHISREF
((TypeFunction *)ftype)->isref = 1;
#endif
fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
Expression *e = NULL;
if (postblit)
{ /* Swap:
* tmp = *this; *this = s; tmp.dtor();
*/
//printf("\tswap copy\n");
Identifier *idtmp = Lexer::uniqueId("__tmp");
VarDeclaration *tmp;
AssignExp *ec = NULL;
if (dtor)
{
tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
tmp->noauto = 1;
e = new DeclarationExp(0, tmp);
ec = new AssignExp(0,
new VarExp(0, tmp),
#if STRUCTTHISREF
new ThisExp(0)
#else
new PtrExp(0, new ThisExp(0))
#endif
);
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
ec = new AssignExp(0,
#if STRUCTTHISREF
new ThisExp(0),
#else
new PtrExp(0, new ThisExp(0)),
#endif
new IdentifierExp(0, Id::p));
ec->op = TOKblit;
e = Expression::combine(e, ec);
if (dtor)
{
/* Instead of running the destructor on s, run it
* on tmp. This avoids needing to copy tmp back in to s.
*/
Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
ec = new CallExp(0, ec);
e = Expression::combine(e, ec);
}
}
else
{ /* Do memberwise copy
*/
//printf("\tmemberwise copy\n");
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
// this.v = s.v;
AssignExp *ec = new AssignExp(0,
new DotVarExp(0, new ThisExp(0), v, 0),
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
}
Statement *s1 = new ExpStatement(0, e);
/* Add:
* return this;
*/
e = new ThisExp(0);
Statement *s2 = new ReturnStatement(0, e);
fop->fbody = new CompoundStatement(0, s1, s2);
members->push(fop);
fop->addMember(sc, this, 1);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fop->semantic(sc);
sc->pop();
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
return fop;
}
/*******************************************
* Build copy constructor for struct.
* Copy constructors are compiler generated only, and are only
* callable from the compiler. They are not user accessible.
* A copy constructor is:
* void cpctpr(ref S s)
* {
* *this = s;
* this.postBlit();
* }
* This is done so:
* - postBlit() never sees uninitialized data
* - memcpy can be much more efficient than memberwise copy
* - no fields are overlooked
*/
FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
{
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
FuncDeclaration *fcp = NULL;
/* Copy constructor is only necessary if there is a postblit function,
* otherwise the code generator will just do a bit copy.
*/
if (postblit)
{
//printf("generating cpctor\n");
Argument *param = new Argument(STCref, type, Id::p, NULL);
Arguments *fparams = new Arguments;
fparams->push(param);
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
// Build *this = p;
Expression *e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
// Build postBlit();
e = new VarExp(0, postblit, 0);
e = new CallExp(0, e);
s = new CompoundStatement(0, s, new ExpStatement(0, e));
fcp->fbody = s;
members->push(fcp);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fcp->semantic(sc);
sc->pop();
}
return fcp;
}
/*****************************************
* Create inclusive postblit for struct by aggregating
* all the postblits in postblits[] with the postblits for
* all the members.
* Note the close similarity with AggregateDeclaration::buildDtor(),
* and the ordering changes (runs forward instead of backwards).
*/
#if DMDV2
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
{
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
Expression *e = NULL;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
Type *tv = v->type->toBasetype();
size_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->postblit)
{ Expression *ex;
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
{ // this.v.dtor()
ex = new DotVarExp(0, ex, sd->postblit, 0);
ex = new CallExp(0, ex);
}
else
{
// Typeinfo.postblit(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::postblit);
ex = new CallExp(0, et, ea);
}
e = Expression::combine(e, ex); // combine in forward order
}
}
}
/* Build our own "postblit" which executes e
*/
if (e)
{ //printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
dd->fbody = new ExpStatement(0, e);
dtors.push(dd);
members->push(dd);
dd->semantic(sc);
}
switch (postblits.dim)
{
case 0:
return NULL;
case 1:
return (FuncDeclaration *)postblits.data[0];
default:
e = NULL;
for (size_t i = 0; i < postblits.dim; i++)
{ FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
e = Expression::combine(e, ex);
}
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}
#endif
/*****************************************
* Create inclusive destructor for struct/class by aggregating
* all the destructors in dtors[] with the destructors for
* all the members.
* Note the close similarity with StructDeclaration::buildPostBlit(),
* and the ordering changes (runs backward instead of forwards).
*/
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
{
//printf("AggregateDeclaration::buildDtor() %s\n", toChars());
Expression *e = NULL;
#if DMDV2
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
Type *tv = v->type->toBasetype();
size_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->dtor)
{ Expression *ex;
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
{ // this.v.dtor()
ex = new DotVarExp(0, ex, sd->dtor, 0);
ex = new CallExp(0, ex);
}
else
{
// Typeinfo.destroy(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::destroy);
ex = new CallExp(0, et, ea);
}
e = Expression::combine(ex, e); // combine in reverse order
}
}
}
/* Build our own "destructor" which executes e
*/
if (e)
{ //printf("Building __fieldDtor()\n");
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
dd->fbody = new ExpStatement(0, e);
dtors.shift(dd);
members->push(dd);
dd->semantic(sc);
}
#endif
switch (dtors.dim)
{
case 0:
return NULL;
case 1:
return (FuncDeclaration *)dtors.data[0];
default:
e = NULL;
for (size_t i = 0; i < dtors.dim; i++)
{ FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
e = Expression::combine(ex, e);
}
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "aggregate.h"
#include "scope.h"
#include "mtype.h"
#include "declaration.h"
#include "module.h"
#include "id.h"
#include "expression.h"
#include "statement.h"
#include "init.h"
/*******************************************
* We need an opAssign for the struct if
* it has a destructor or a postblit.
* We need to generate one if a user-specified one does not exist.
*/
int StructDeclaration::needOpAssign()
{
#define X 0
if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
if (hasIdentityAssign)
goto Ldontneed;
if (dtor || postblit)
goto Lneed;
/* If any of the fields need an opAssign, then we
* need it too.
*/
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->needOpAssign())
goto Lneed;
}
}
Ldontneed:
if (X) printf("\tdontneed\n");
return 0;
Lneed:
if (X) printf("\tneed\n");
return 1;
#undef X
}
/******************************************
* Build opAssign for struct.
* S* opAssign(S s) { ... }
*/
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
{
if (!needOpAssign())
return NULL;
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
FuncDeclaration *fop = NULL;
Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
Arguments *fparams = new Arguments;
fparams->push(param);
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
#if STRUCTTHISREF
((TypeFunction *)ftype)->isref = 1;
#endif
fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
Expression *e = NULL;
if (postblit)
{ /* Swap:
* tmp = *this; *this = s; tmp.dtor();
*/
//printf("\tswap copy\n");
Identifier *idtmp = Lexer::uniqueId("__tmp");
VarDeclaration *tmp;
AssignExp *ec = NULL;
if (dtor)
{
tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
tmp->noauto = 1;
e = new DeclarationExp(0, tmp);
ec = new AssignExp(0,
new VarExp(0, tmp),
#if STRUCTTHISREF
new ThisExp(0)
#else
new PtrExp(0, new ThisExp(0))
#endif
);
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
ec = new AssignExp(0,
#if STRUCTTHISREF
new ThisExp(0),
#else
new PtrExp(0, new ThisExp(0)),
#endif
new IdentifierExp(0, Id::p));
ec->op = TOKblit;
e = Expression::combine(e, ec);
if (dtor)
{
/* Instead of running the destructor on s, run it
* on tmp. This avoids needing to copy tmp back in to s.
*/
Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
ec = new CallExp(0, ec);
e = Expression::combine(e, ec);
}
}
else
{ /* Do memberwise copy
*/
//printf("\tmemberwise copy\n");
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
// this.v = s.v;
AssignExp *ec = new AssignExp(0,
new DotVarExp(0, new ThisExp(0), v, 0),
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
}
Statement *s1 = new ExpStatement(0, e);
/* Add:
* return this;
*/
e = new ThisExp(0);
Statement *s2 = new ReturnStatement(0, e);
fop->fbody = new CompoundStatement(0, s1, s2);
members->push(fop);
fop->addMember(sc, this, 1);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fop->semantic(sc);
sc->pop();
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
return fop;
}
/*******************************************
* Build copy constructor for struct.
* Copy constructors are compiler generated only, and are only
* callable from the compiler. They are not user accessible.
* A copy constructor is:
* void cpctpr(ref S s)
* {
* *this = s;
* this.postBlit();
* }
* This is done so:
* - postBlit() never sees uninitialized data
* - memcpy can be much more efficient than memberwise copy
* - no fields are overlooked
*/
FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
{
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
FuncDeclaration *fcp = NULL;
/* Copy constructor is only necessary if there is a postblit function,
* otherwise the code generator will just do a bit copy.
*/
if (postblit)
{
//printf("generating cpctor\n");
Argument *param = new Argument(STCref, type, Id::p, NULL);
Arguments *fparams = new Arguments;
fparams->push(param);
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
// Build *this = p;
Expression *e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
// Build postBlit();
e = new VarExp(0, postblit, 0);
e = new CallExp(0, e);
s = new CompoundStatement(0, s, new ExpStatement(0, e));
fcp->fbody = s;
members->push(fcp);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fcp->semantic(sc);
sc->pop();
}
return fcp;
}
/*****************************************
* Create inclusive postblit for struct by aggregating
* all the postblits in postblits[] with the postblits for
* all the members.
* Note the close similarity with AggregateDeclaration::buildDtor(),
* and the ordering changes (runs forward instead of backwards).
*/
#if DMDV2
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
{
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
Expression *e = NULL;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
size_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->postblit)
{ Expression *ex;
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
{ // this.v.postblit()
ex = new DotVarExp(0, ex, sd->postblit, 0);
ex = new CallExp(0, ex);
}
else
{
// Typeinfo.postblit(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::postblit);
ex = new CallExp(0, et, ea);
}
e = Expression::combine(e, ex); // combine in forward order
}
}
}
/* Build our own "postblit" which executes e
*/
if (e)
{ //printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
dd->fbody = new ExpStatement(0, e);
postblits.shift(dd);
members->push(dd);
dd->semantic(sc);
}
switch (postblits.dim)
{
case 0:
return NULL;
case 1:
return (FuncDeclaration *)postblits.data[0];
default:
e = NULL;
for (size_t i = 0; i < postblits.dim; i++)
{ FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
e = Expression::combine(e, ex);
}
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}
#endif
/*****************************************
* Create inclusive destructor for struct/class by aggregating
* all the destructors in dtors[] with the destructors for
* all the members.
* Note the close similarity with StructDeclaration::buildPostBlit(),
* and the ordering changes (runs backward instead of forwards).
*/
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
{
//printf("AggregateDeclaration::buildDtor() %s\n", toChars());
Expression *e = NULL;
#if DMDV2
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
size_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->dtor)
{ Expression *ex;
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
{ // this.v.dtor()
ex = new DotVarExp(0, ex, sd->dtor, 0);
ex = new CallExp(0, ex);
}
else
{
// Typeinfo.destroy(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::destroy);
ex = new CallExp(0, et, ea);
}
e = Expression::combine(ex, e); // combine in reverse order
}
}
}
/* Build our own "destructor" which executes e
*/
if (e)
{ //printf("Building __fieldDtor()\n");
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
dd->fbody = new ExpStatement(0, e);
dtors.shift(dd);
members->push(dd);
dd->semantic(sc);
}
#endif
switch (dtors.dim)
{
case 0:
return NULL;
case 1:
return (FuncDeclaration *)dtors.data[0];
default:
e = NULL;
for (size_t i = 0; i < dtors.dim; i++)
{ FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
e = Expression::combine(ex, e);
}
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}

View File

@@ -1,391 +1,405 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "id.h"
#include "init.h"
#include "declaration.h"
#include "identifier.h"
#include "expression.h"
#include "cond.h"
#include "module.h"
#include "template.h"
#include "lexer.h"
#ifdef _DH
#include "mtype.h"
#include "scope.h"
#endif
int findCondition(Array *ids, Identifier *ident)
{
if (ids)
{
for (int i = 0; i < ids->dim; i++)
{
const char *id = (const char *)ids->data[i];
if (strcmp(id, ident->toChars()) == 0)
return TRUE;
}
}
return FALSE;
}
/* ============================================================ */
Condition::Condition(Loc loc)
{
this->loc = loc;
inc = 0;
}
/* ============================================================ */
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
: Condition(0)
{
this->mod = mod;
this->level = level;
this->ident = ident;
}
Condition *DVCondition::syntaxCopy()
{
return this; // don't need to copy
}
/* ============================================================ */
void DebugCondition::setGlobalLevel(unsigned level)
{
global.params.debuglevel = level;
}
void DebugCondition::addGlobalIdent(const char *ident)
{
if (!global.params.debugids)
global.params.debugids = new Array();
global.params.debugids->push((void *)ident);
}
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
: DVCondition(mod, level, ident)
{
}
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
{
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
if (inc == 0)
{
inc = 2;
if (ident)
{
if (findCondition(mod->debugids, ident))
inc = 1;
else if (findCondition(global.params.debugids, ident))
inc = 1;
else
{ if (!mod->debugidsNot)
mod->debugidsNot = new Array();
mod->debugidsNot->push(ident->toChars());
}
}
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
inc = 1;
}
return (inc == 1);
}
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (ident)
buf->printf("debug (%s)", ident->toChars());
else
buf->printf("debug (%u)", level);
}
/* ============================================================ */
void VersionCondition::setGlobalLevel(unsigned level)
{
global.params.versionlevel = level;
}
void VersionCondition::checkPredefined(Loc loc, const char *ident)
{
static const char* reserved[] =
{
"DigitalMars", "LLVM", "LDC", "LLVM64",
"X86", "X86_64", "PPC", "PPC64",
"Windows", "Win32", "Win64",
"linux", "darwin", "Posix",
"LittleEndian", "BigEndian",
"all",
"none",
};
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
{
if (strcmp(ident, reserved[i]) == 0)
goto Lerror;
}
if (ident[0] == 'D' && ident[1] == '_')
goto Lerror;
return;
Lerror:
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
}
void VersionCondition::addGlobalIdent(const char *ident)
{
checkPredefined(0, ident);
addPredefinedGlobalIdent(ident);
}
void VersionCondition::addPredefinedGlobalIdent(const char *ident)
{
if (!global.params.versionids)
global.params.versionids = new Array();
global.params.versionids->push((void *)ident);
}
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
: DVCondition(mod, level, ident)
{
}
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
{
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
//if (ident) printf("\tident = '%s'\n", ident->toChars());
if (inc == 0)
{
inc = 2;
if (ident)
{
if (findCondition(mod->versionids, ident))
inc = 1;
else if (findCondition(global.params.versionids, ident))
inc = 1;
else
{
if (!mod->versionidsNot)
mod->versionidsNot = new Array();
mod->versionidsNot->push(ident->toChars());
}
}
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
inc = 1;
}
return (inc == 1);
}
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (ident)
buf->printf("version (%s)", ident->toChars());
else
buf->printf("version (%u)", level);
}
/**************************** StaticIfCondition *******************************/
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
: Condition(loc)
{
this->exp = exp;
}
Condition *StaticIfCondition::syntaxCopy()
{
return new StaticIfCondition(loc, exp->syntaxCopy());
}
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
#if 0
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
if (s)
{
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
}
#endif
if (inc == 0)
{
if (!sc)
{
error(loc, "static if conditional cannot be at global scope");
inc = 2;
return 0;
}
sc = sc->push(sc->scopesym);
sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
sc->pop();
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(TRUE))
inc = 1;
else if (e->isBool(FALSE))
inc = 2;
else
{
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
inc = 2;
}
}
return (inc == 1);
}
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("static if(");
exp->toCBuffer(buf, hgs);
buf->writeByte(')');
}
/**************************** IftypeCondition *******************************/
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
: Condition(loc)
{
this->targ = targ;
this->id = id;
this->tok = tok;
this->tspec = tspec;
}
Condition *IftypeCondition::syntaxCopy()
{
return new IftypeCondition(loc,
targ->syntaxCopy(),
id,
tok,
tspec ? tspec->syntaxCopy() : NULL);
}
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
{
//printf("IftypeCondition::include()\n");
if (inc == 0)
{
if (!sc)
{
error(loc, "iftype conditional cannot be at global scope");
inc = 2;
return 0;
}
unsigned errors = global.errors;
global.gag++; // suppress printing of error messages
targ = targ->semantic(loc, sc);
global.gag--;
if (errors != global.errors) // if any errors happened
{ inc = 2; // then condition is false
global.errors = errors;
}
else if (id && tspec)
{
/* Evaluate to TRUE if targ matches tspec.
* If TRUE, declare id as an alias for the specialized type.
*/
MATCH m;
TemplateTypeParameter tp(loc, id, NULL, NULL);
TemplateParameters parameters;
parameters.setDim(1);
parameters.data[0] = (void *)&tp;
Objects dedtypes;
dedtypes.setDim(1);
m = targ->deduceType(NULL, tspec, &parameters, &dedtypes);
if (m == MATCHnomatch ||
(m != MATCHexact && tok == TOKequal))
inc = 2;
else
{
inc = 1;
Type *tded = (Type *)dedtypes.data[0];
if (!tded)
tded = targ;
Dsymbol *s = new AliasDeclaration(loc, id, tded);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
}
}
else if (id)
{
/* Declare id as an alias for type targ. Evaluate to TRUE
*/
Dsymbol *s = new AliasDeclaration(loc, id, targ);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
inc = 1;
}
else if (tspec)
{
/* Evaluate to TRUE if targ matches tspec
*/
tspec = tspec->semantic(loc, sc);
//printf("targ = %s\n", targ->toChars());
//printf("tspec = %s\n", tspec->toChars());
if (tok == TOKcolon)
{ if (targ->implicitConvTo(tspec))
inc = 1;
else
inc = 2;
}
else /* == */
{ if (targ->equals(tspec))
inc = 1;
else
inc = 2;
}
}
else
inc = 1;
//printf("inc = %d\n", inc);
}
return (inc == 1);
}
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("iftype(");
targ->toCBuffer(buf, id, hgs);
if (tspec)
{
if (tok == TOKcolon)
buf->writestring(" : ");
else
buf->writestring(" == ");
tspec->toCBuffer(buf, NULL, hgs);
}
buf->writeByte(')');
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "id.h"
#include "init.h"
#include "declaration.h"
#include "identifier.h"
#include "expression.h"
#include "cond.h"
#include "module.h"
#include "template.h"
#include "lexer.h"
#ifdef _DH
#include "mtype.h"
#include "scope.h"
#endif
int findCondition(Array *ids, Identifier *ident)
{
if (ids)
{
for (int i = 0; i < ids->dim; i++)
{
const char *id = (const char *)ids->data[i];
if (strcmp(id, ident->toChars()) == 0)
return TRUE;
}
}
return FALSE;
}
/* ============================================================ */
Condition::Condition(Loc loc)
{
this->loc = loc;
inc = 0;
}
/* ============================================================ */
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
: Condition(0)
{
this->mod = mod;
this->level = level;
this->ident = ident;
}
Condition *DVCondition::syntaxCopy()
{
return this; // don't need to copy
}
/* ============================================================ */
void DebugCondition::setGlobalLevel(unsigned level)
{
global.params.debuglevel = level;
}
void DebugCondition::addGlobalIdent(const char *ident)
{
if (!global.params.debugids)
global.params.debugids = new Array();
global.params.debugids->push((void *)ident);
}
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
: DVCondition(mod, level, ident)
{
}
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
{
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
if (inc == 0)
{
inc = 2;
if (ident)
{
if (findCondition(mod->debugids, ident))
inc = 1;
else if (findCondition(global.params.debugids, ident))
inc = 1;
else
{ if (!mod->debugidsNot)
mod->debugidsNot = new Array();
mod->debugidsNot->push(ident->toChars());
}
}
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
inc = 1;
}
return (inc == 1);
}
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (ident)
buf->printf("debug (%s)", ident->toChars());
else
buf->printf("debug (%u)", level);
}
/* ============================================================ */
void VersionCondition::setGlobalLevel(unsigned level)
{
global.params.versionlevel = level;
}
void VersionCondition::checkPredefined(Loc loc, const char *ident)
{
static const char* reserved[] =
{
"DigitalMars", "X86", "X86_64",
"Windows", "Win32", "Win64",
"linux",
#if DMDV2
/* Although Posix is predefined by D1, disallowing its
* redefinition breaks makefiles and older builds.
*/
"Posix",
"D_NET",
#endif
"OSX", "FreeBSD",
"Solaris",
"LittleEndian", "BigEndian",
"all",
"none",
// LDC
"LLVM", "LDC", "LLVM64",
"PPC", "PPC64",
"darwin","solaris","freebsd"
};
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
{
if (strcmp(ident, reserved[i]) == 0)
goto Lerror;
}
if (ident[0] == 'D' && ident[1] == '_')
goto Lerror;
return;
Lerror:
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
}
void VersionCondition::addGlobalIdent(const char *ident)
{
checkPredefined(0, ident);
addPredefinedGlobalIdent(ident);
}
void VersionCondition::addPredefinedGlobalIdent(const char *ident)
{
if (!global.params.versionids)
global.params.versionids = new Array();
global.params.versionids->push((void *)ident);
}
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
: DVCondition(mod, level, ident)
{
}
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
{
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
//if (ident) printf("\tident = '%s'\n", ident->toChars());
if (inc == 0)
{
inc = 2;
if (ident)
{
if (findCondition(mod->versionids, ident))
inc = 1;
else if (findCondition(global.params.versionids, ident))
inc = 1;
else
{
if (!mod->versionidsNot)
mod->versionidsNot = new Array();
mod->versionidsNot->push(ident->toChars());
}
}
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
inc = 1;
}
return (inc == 1);
}
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (ident)
buf->printf("version (%s)", ident->toChars());
else
buf->printf("version (%u)", level);
}
/**************************** StaticIfCondition *******************************/
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
: Condition(loc)
{
this->exp = exp;
}
Condition *StaticIfCondition::syntaxCopy()
{
return new StaticIfCondition(loc, exp->syntaxCopy());
}
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
#if 0
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
if (s)
{
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
}
#endif
if (inc == 0)
{
if (!sc)
{
error(loc, "static if conditional cannot be at global scope");
inc = 2;
return 0;
}
sc = sc->push(sc->scopesym);
sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
sc->pop();
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(TRUE))
inc = 1;
else if (e->isBool(FALSE))
inc = 2;
else
{
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
inc = 2;
}
}
return (inc == 1);
}
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("static if(");
exp->toCBuffer(buf, hgs);
buf->writeByte(')');
}
/**************************** IftypeCondition *******************************/
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
: Condition(loc)
{
this->targ = targ;
this->id = id;
this->tok = tok;
this->tspec = tspec;
}
Condition *IftypeCondition::syntaxCopy()
{
return new IftypeCondition(loc,
targ->syntaxCopy(),
id,
tok,
tspec ? tspec->syntaxCopy() : NULL);
}
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
{
//printf("IftypeCondition::include()\n");
if (inc == 0)
{
if (!sc)
{
error(loc, "iftype conditional cannot be at global scope");
inc = 2;
return 0;
}
Type *t = targ->trySemantic(loc, sc);
if (t)
targ = t;
else
inc = 2; // condition is false
if (!t)
{
}
else if (id && tspec)
{
/* Evaluate to TRUE if targ matches tspec.
* If TRUE, declare id as an alias for the specialized type.
*/
MATCH m;
TemplateTypeParameter tp(loc, id, NULL, NULL);
TemplateParameters parameters;
parameters.setDim(1);
parameters.data[0] = (void *)&tp;
Objects dedtypes;
dedtypes.setDim(1);
m = targ->deduceType(NULL, tspec, &parameters, &dedtypes);
if (m == MATCHnomatch ||
(m != MATCHexact && tok == TOKequal))
inc = 2;
else
{
inc = 1;
Type *tded = (Type *)dedtypes.data[0];
if (!tded)
tded = targ;
Dsymbol *s = new AliasDeclaration(loc, id, tded);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
}
}
else if (id)
{
/* Declare id as an alias for type targ. Evaluate to TRUE
*/
Dsymbol *s = new AliasDeclaration(loc, id, targ);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
inc = 1;
}
else if (tspec)
{
/* Evaluate to TRUE if targ matches tspec
*/
tspec = tspec->semantic(loc, sc);
//printf("targ = %s\n", targ->toChars());
//printf("tspec = %s\n", tspec->toChars());
if (tok == TOKcolon)
{ if (targ->implicitConvTo(tspec))
inc = 1;
else
inc = 2;
}
else /* == */
{ if (targ->equals(tspec))
inc = 1;
else
inc = 2;
}
}
else
inc = 1;
//printf("inc = %d\n", inc);
}
return (inc == 1);
}
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("iftype(");
targ->toCBuffer(buf, id, hgs);
if (tspec)
{
if (tok == TOKcolon)
buf->writestring(" : ");
else
buf->writestring(" == ");
tspec->toCBuffer(buf, NULL, hgs);
}
buf->writeByte(')');
}

File diff suppressed because it is too large Load Diff

381
dmd2/cppmangle.c Normal file
View File

@@ -0,0 +1,381 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "dsymbol.h"
#include "mtype.h"
#include "scope.h"
#include "init.h"
#include "expression.h"
#include "attrib.h"
#include "declaration.h"
#include "template.h"
#include "id.h"
#include "enum.h"
#include "import.h"
#include "aggregate.h"
#if DMDV2
/* Do mangling for C++ linkage.
* Follows Itanium C++ ABI 1.86
* No attempt is made to support mangling of templates, operator
* overloading, or special functions.
*
* So why don't we use the C++ ABI for D name mangling?
* Because D supports a lot of things (like modules) that the C++
* ABI has no concept of. These affect every D mangled name,
* so nothing would be compatible anyway.
*/
struct CppMangleState
{
static Array components;
int substitute(OutBuffer *buf, void *p);
};
Array CppMangleState::components;
void writeBase36(OutBuffer *buf, unsigned i)
{
if (i >= 36)
{
writeBase36(buf, i / 36);
i %= 36;
}
if (i < 10)
buf->writeByte(i + '0');
else if (i < 36)
buf->writeByte(i - 10 + 'A');
else
assert(0);
}
int CppMangleState::substitute(OutBuffer *buf, void *p)
{
for (size_t i = 0; i < components.dim; i++)
{
if (p == components.data[i])
{
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
*/
buf->writeByte('S');
if (i)
writeBase36(buf, i - 1);
buf->writeByte('_');
return 1;
}
}
components.push(p);
return 0;
}
void source_name(OutBuffer *buf, Dsymbol *s)
{
char *name = s->ident->toChars();
buf->printf("%d%s", strlen(name), name);
}
void prefix_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
{
if (!cms->substitute(buf, s))
{
Dsymbol *p = s->toParent();
if (p && !p->isModule())
{
prefix_name(buf, cms, p);
}
source_name(buf, s);
}
}
void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
{
Dsymbol *p = s->toParent();
if (p && !p->isModule())
{
buf->writeByte('N');
FuncDeclaration *fd = s->isFuncDeclaration();
if (fd->isConst())
buf->writeByte('K');
prefix_name(buf, cms, p);
source_name(buf, s);
buf->writeByte('E');
}
else
source_name(buf, s);
}
char *cpp_mangle(Dsymbol *s)
{
/*
* <mangled-name> ::= _Z <encoding>
* <encoding> ::= <function name> <bare-function-type>
* ::= <data name>
* ::= <special-name>
*/
CppMangleState cms;
memset(&cms, 0, sizeof(cms));
cms.components.setDim(0);
OutBuffer buf;
#if MACHOBJ
buf.writestring("__Z");
#else
buf.writestring("_Z");
#endif
cpp_mangle_name(&buf, &cms, s);
FuncDeclaration *fd = s->isFuncDeclaration();
if (fd)
{ // add <bare-function-type>
TypeFunction *tf = (TypeFunction *)fd->type;
assert(tf->ty == Tfunction);
Argument::argsCppMangle(&buf, &cms, tf->parameters, tf->varargs);
}
buf.writeByte(0);
return (char *)buf.extractData();
}
/* ============= Type Encodings ============================================= */
void Type::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
/* Make this the 'vendor extended type' when there is no
* C++ analog.
* u <source-name>
*/
if (!cms->substitute(buf, this))
{ assert(deco);
buf->printf("u%d%s", strlen(deco), deco);
}
}
void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{ char c;
char p = 0;
/* ABI spec says:
* v void
* w wchar_t
* b bool
* c char
* a signed char
* h unsigned char
* s short
* t unsigned short
* i int
* j unsigned int
* l long
* m unsigned long
* x long long, __int64
* y unsigned long long, __int64
* n __int128
* o unsigned __int128
* f float
* d double
* e long double, __float80
* g __float128
* z ellipsis
* u <source-name> # vendor extended type
*/
switch (ty)
{
case Tvoid: c = 'v'; break;
case Tint8: c = 'a'; break;
case Tuns8: c = 'h'; break;
case Tint16: c = 's'; break;
case Tuns16: c = 't'; break;
case Tint32: c = 'i'; break;
case Tuns32: c = 'j'; break;
case Tfloat32: c = 'f'; break;
case Tint64: c = 'x'; break;
case Tuns64: c = 'y'; break;
case Tfloat64: c = 'd'; break;
case Tfloat80: c = 'e'; break;
case Tbool: c = 'b'; break;
case Tchar: c = 'c'; break;
case Twchar: c = 't'; break;
case Tdchar: c = 'w'; break;
case Timaginary32: p = 'G'; c = 'f'; break;
case Timaginary64: p = 'G'; c = 'd'; break;
case Timaginary80: p = 'G'; c = 'e'; break;
case Tcomplex32: p = 'C'; c = 'f'; break;
case Tcomplex64: p = 'C'; c = 'd'; break;
case Tcomplex80: p = 'C'; c = 'e'; break;
default: assert(0);
}
if (p)
{
if (cms->substitute(buf, this))
return;
buf->writeByte(p);
}
buf->writeByte(c);
}
void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->printf("A%ju_", dim ? dim->toInteger() : 0);
next->toCppMangle(buf, cms);
}
}
void TypeDArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
Type::toCppMangle(buf, cms);
}
void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
Type::toCppMangle(buf, cms);
}
void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->writeByte('P');
next->toCppMangle(buf, cms);
}
}
void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->writeByte('R');
next->toCppMangle(buf, cms);
}
}
void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{ /*
* <function-type> ::= F [Y] <bare-function-type> E
* <bare-function-type> ::= <signature type>+
* # types are possible return type, then parameter types
*/
/* ABI says:
"The type of a non-static member function is considered to be different,
for the purposes of substitution, from the type of a namespace-scope or
static member function whose type appears similar. The types of two
non-static member functions are considered to be different, for the
purposes of substitution, if the functions are members of different
classes. In other words, for the purposes of substitution, the class of
which the function is a member is considered part of the type of
function."
BUG: Right now, types of functions are never merged, so our simplistic
component matcher always finds them to be different.
We should use Type::equals on these, and use different
TypeFunctions for non-static member functions, and non-static
member functions of different classes.
*/
if (!cms->substitute(buf, this))
{
buf->writeByte('F');
if (linkage == LINKc)
buf->writeByte('Y');
next->toCppMangle(buf, cms);
Argument::argsCppMangle(buf, cms, parameters, varargs);
buf->writeByte('E');
}
}
void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
Type::toCppMangle(buf, cms);
}
void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, sym))
cpp_mangle_name(buf, cms, sym);
}
void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, sym))
cpp_mangle_name(buf, cms, sym);
}
void TypeTypedef::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
Type::toCppMangle(buf, cms);
}
void TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->writeByte('P');
if (!cms->substitute(buf, sym))
cpp_mangle_name(buf, cms, sym);
}
}
void Argument::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs)
{ int n = 0;
if (arguments)
{
for (size_t i = 0; i < arguments->dim; i++)
{ Argument *arg = (Argument *)arguments->data[i];
Type *t = arg->type;
if (arg->storageClass & (STCout | STCref))
t = t->referenceTo();
else if (arg->storageClass & STClazy)
{ // Mangle as delegate
Type *td = new TypeFunction(NULL, t, 0, LINKd);
td = new TypeDelegate(td);
t = t->merge();
}
if (t->ty == Tsarray)
{ // Mangle static arrays as pointers
t = t->pointerTo();
}
t->toCppMangle(buf, cms);
n++;
}
}
if (varargs)
buf->writestring("z");
else if (!n)
buf->writeByte('v'); // encode ( ) arguments
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4047
dmd2/doc.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,326 +1,352 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_DSYMBOL_H
#define DMD_DSYMBOL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "stringtable.h"
#include "mars.h"
#include "arraytypes.h"
// llvm
#include "../ir/irsymbol.h"
struct Identifier;
struct Scope;
struct DsymbolTable;
struct Declaration;
struct TupleDeclaration;
struct TypedefDeclaration;
struct AliasDeclaration;
struct AggregateDeclaration;
struct EnumDeclaration;
struct ClassDeclaration;
struct InterfaceDeclaration;
struct StructDeclaration;
struct UnionDeclaration;
struct FuncDeclaration;
struct FuncAliasDeclaration;
struct FuncLiteralDeclaration;
struct CtorDeclaration;
struct PostBlitDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct VarDeclaration;
struct AttribDeclaration;
struct Symbol;
struct Package;
struct Module;
struct Import;
struct Type;
struct TypeTuple;
struct WithStatement;
struct LabelDsymbol;
struct TemplateDeclaration;
struct TemplateInstance;
struct TemplateMixin;
struct EnumMember;
struct ScopeDsymbol;
struct WithScopeSymbol;
struct ArrayScopeSymbol;
struct StaticStructInitDeclaration;
struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
struct OverloadSet;
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
#else
struct TYPE;
#endif
// llvm
#if IN_LLVM
namespace llvm
{
class Value;
}
#endif
enum PROT
{
PROTundefined,
PROTnone, // no access
PROTprivate,
PROTpackage,
PROTprotected,
PROTpublic,
PROTexport,
};
struct Dsymbol : Object
{
Identifier *ident;
Identifier *c_ident;
Dsymbol *parent;
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
char *toPrettyChars();
char *locToChars();
int equals(Object *o);
int isAnonymous();
void error(Loc loc, const char *format, ...);
void error(const char *format, ...);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule();
Module *getCompilationModule(); // possibly different for templates
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
TemplateInstance *inTemplateInstance();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
static Array *arraySyntaxCopy(Array *a);
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
virtual void inlineScan();
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
#ifdef _DH
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
#endif
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
virtual ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
virtual int isOverloadable();
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
virtual char *mangle();
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps);
static int oneMembers(Array *members, Dsymbol **ps);
virtual int hasPointers();
virtual void addLocalClass(ClassDeclarations *) { }
virtual void checkCtorConstInit() { }
virtual void addComment(unsigned char *comment);
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);
// Backend
virtual Symbol *toSymbol(); // to backend symbol
virtual void toObjFile(int multiobj); // compile to .obj file
virtual int cvMember(unsigned char *p); // emit cv debug info for member
Symbol *toImport(); // to backend import symbol
static Symbol *toImport(Symbol *s); // to backend import symbol
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
// Eliminate need for dynamic_cast
virtual Package *isPackage() { return NULL; }
virtual Module *isModule() { return NULL; }
virtual EnumMember *isEnumMember() { return NULL; }
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
virtual TemplateInstance *isTemplateInstance() { return NULL; }
virtual TemplateMixin *isTemplateMixin() { return NULL; }
virtual Declaration *isDeclaration() { return NULL; }
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
virtual NewDeclaration *isNewDeclaration() { return NULL; }
virtual VarDeclaration *isVarDeclaration() { return NULL; }
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
virtual StructDeclaration *isStructDeclaration() { return NULL; }
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
#ifdef _DH
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
#endif
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
// llvm stuff
int llvmInternal;
IrDsymbol ir;
};
// Dsymbol that generates a scope
struct ScopeDsymbol : Dsymbol
{
Array *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
Array *imports; // imported ScopeDsymbol's
unsigned char *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void importScope(ScopeDsymbol *s, enum PROT protection);
int isforwardRef();
void defineRef(Dsymbol *s);
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
Dsymbol *nameCollision(Dsymbol *s);
const char *kind();
FuncDeclaration *findGetMembers();
void emitMemberComments(Scope *sc);
static size_t dim(Array *members);
static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
ScopeDsymbol *isScopeDsymbol() { return this; }
};
// With statement scope
struct WithScopeSymbol : ScopeDsymbol
{
WithStatement *withstate;
WithScopeSymbol(WithStatement *withstate);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
WithScopeSymbol *isWithScopeSymbol() { return this; }
};
// Array Index/Slice scope
struct ArrayScopeSymbol : ScopeDsymbol
{
Expression *exp; // IndexExp or SliceExp
TypeTuple *type; // for tuple[length]
TupleDeclaration *td; // for tuples of objects
Scope *sc;
ArrayScopeSymbol(Scope *sc, Expression *e);
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
};
// Overload Sets
struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
// Table of Dsymbol's
struct DsymbolTable : Object
{
StringTable *tab;
DsymbolTable();
~DsymbolTable();
// Look up Identifier. Return Dsymbol if found, NULL if not.
Dsymbol *lookup(Identifier *ident);
// Insert Dsymbol in table. Return NULL if already there.
Dsymbol *insert(Dsymbol *s);
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
Dsymbol *update(Dsymbol *s);
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
};
#endif /* DMD_DSYMBOL_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_DSYMBOL_H
#define DMD_DSYMBOL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "stringtable.h"
#include "mars.h"
#include "arraytypes.h"
#if IN_LLVM
#include "../ir/irdsymbol.h"
#endif
struct Identifier;
struct Scope;
struct DsymbolTable;
struct Declaration;
struct ThisDeclaration;
struct TupleDeclaration;
struct TypedefDeclaration;
struct AliasDeclaration;
struct AggregateDeclaration;
struct EnumDeclaration;
struct ClassDeclaration;
struct InterfaceDeclaration;
struct StructDeclaration;
struct UnionDeclaration;
struct FuncDeclaration;
struct FuncAliasDeclaration;
struct FuncLiteralDeclaration;
struct CtorDeclaration;
struct PostBlitDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct VarDeclaration;
struct AttribDeclaration;
#if IN_DMD
struct Symbol;
#endif
struct Package;
struct Module;
struct Import;
struct Type;
struct TypeTuple;
struct WithStatement;
struct LabelDsymbol;
struct TemplateDeclaration;
struct TemplateInstance;
struct TemplateMixin;
struct EnumMember;
struct ScopeDsymbol;
struct WithScopeSymbol;
struct ArrayScopeSymbol;
struct StaticStructInitDeclaration;
struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
struct OverloadSet;
#if IN_LLVM
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#endif
#if IN_DMD
struct Symbol;
#endif
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
#else
struct TYPE;
#endif
#if IN_LLVM
class Ir;
class IrSymbol;
namespace llvm
{
class Value;
}
#endif
#if IN_DMD
// Back end
struct Classsym;
#endif
enum PROT
{
PROTundefined,
PROTnone, // no access
PROTprivate,
PROTpackage,
PROTprotected,
PROTpublic,
PROTexport,
};
struct Dsymbol : Object
{
Identifier *ident;
Identifier *c_ident;
Dsymbol *parent;
#if IN_DMD
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
#endif
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
char *toPrettyChars();
char *locToChars();
int equals(Object *o);
int isAnonymous();
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void error(const char *format, ...) IS_PRINTF(2);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getCompilationModule(); // possibly different for templates
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
TemplateInstance *inTemplateInstance();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
static Array *arraySyntaxCopy(Array *a);
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
virtual void inlineScan();
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
#ifdef _DH
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
#endif
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
virtual ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
virtual int isOverloadable();
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
virtual char *mangle();
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps);
static int oneMembers(Array *members, Dsymbol **ps);
virtual int hasPointers();
virtual void addLocalClass(ClassDeclarations *) { }
virtual void checkCtorConstInit() { }
virtual void addComment(unsigned char *comment);
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);
#if IN_DMD
// Backend
virtual Symbol *toSymbol(); // to backend symbol
virtual void toObjFile(int multiobj); // compile to .obj file
virtual int cvMember(unsigned char *p); // emit cv debug info for member
Symbol *toImport(); // to backend import symbol
static Symbol *toImport(Symbol *s); // to backend import symbol
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
#endif
// Eliminate need for dynamic_cast
virtual Package *isPackage() { return NULL; }
virtual Module *isModule() { return NULL; }
virtual EnumMember *isEnumMember() { return NULL; }
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
virtual TemplateInstance *isTemplateInstance() { return NULL; }
virtual TemplateMixin *isTemplateMixin() { return NULL; }
virtual Declaration *isDeclaration() { return NULL; }
virtual ThisDeclaration *isThisDeclaration() { return NULL; }
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
virtual NewDeclaration *isNewDeclaration() { return NULL; }
virtual VarDeclaration *isVarDeclaration() { return NULL; }
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
virtual StructDeclaration *isStructDeclaration() { return NULL; }
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
#ifdef _DH
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
#endif
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
// llvm stuff
int llvmInternal;
IrDsymbol ir;
IrSymbol* irsym;
#endif
};
// Dsymbol that generates a scope
struct ScopeDsymbol : Dsymbol
{
Array *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
Array *imports; // imported ScopeDsymbol's
unsigned char *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void importScope(ScopeDsymbol *s, enum PROT protection);
int isforwardRef();
void defineRef(Dsymbol *s);
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
Dsymbol *nameCollision(Dsymbol *s);
const char *kind();
FuncDeclaration *findGetMembers();
void emitMemberComments(Scope *sc);
static size_t dim(Array *members);
static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
ScopeDsymbol *isScopeDsymbol() { return this; }
};
// With statement scope
struct WithScopeSymbol : ScopeDsymbol
{
WithStatement *withstate;
WithScopeSymbol(WithStatement *withstate);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
WithScopeSymbol *isWithScopeSymbol() { return this; }
};
// Array Index/Slice scope
struct ArrayScopeSymbol : ScopeDsymbol
{
Expression *exp; // IndexExp or SliceExp
TypeTuple *type; // for tuple[length]
TupleDeclaration *td; // for tuples of objects
Scope *sc;
ArrayScopeSymbol(Scope *sc, Expression *e);
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
};
// Overload Sets
struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
// Table of Dsymbol's
struct DsymbolTable : Object
{
StringTable *tab;
DsymbolTable();
~DsymbolTable();
// Look up Identifier. Return Dsymbol if found, NULL if not.
Dsymbol *lookup(Identifier *ident);
// Insert Dsymbol in table. Return NULL if already there.
Dsymbol *insert(Dsymbol *s);
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
Dsymbol *update(Dsymbol *s);
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
};
#endif /* DMD_DSYMBOL_H */

View File

@@ -52,7 +52,7 @@ void Expression::dump(int i)
void IntegerExp::dump(int i)
{
indent(i);
printf("%p %lld type=%s\n", this, (intmax_t)value, type_print(type));
printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
}
void IdentifierExp::dump(int i)

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com

View File

@@ -30,7 +30,9 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
maxval = NULL;
minval = NULL;
defaultval = NULL;
#if IN_DMD
sinit = NULL;
#endif
scope = NULL;
isdeprecated = 0;
}

View File

@@ -1,90 +1,96 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ENUM_H
#define DMD_ENUM_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct Identifier;
struct Type;
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct EnumDeclaration : ScopeDsymbol
{ /* enum ident : memtype { ... }
*/
Type *type; // the TypeEnum
Type *memtype; // type of the members
#if DMDV1
integer_t maxval;
integer_t minval;
integer_t defaultval; // default initializer
#else
Expression *maxval;
Expression *minval;
Expression *defaultval; // default initializer
Scope *scope; // !=NULL means context to use
#endif
int isdeprecated;
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
const char *kind();
#if DMDV2
Dsymbol *search(Loc, Identifier *ident, int flags);
#endif
int isDeprecated(); // is Dsymbol deprecated?
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumDeclaration *isEnumDeclaration() { return this; }
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
Symbol *sinit;
Symbol *toInitializer();
};
struct EnumMember : Dsymbol
{
Expression *value;
Type *type;
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumMember *isEnumMember() { return this; }
};
#endif /* DMD_ENUM_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ENUM_H
#define DMD_ENUM_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct Identifier;
struct Type;
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct EnumDeclaration : ScopeDsymbol
{ /* enum ident : memtype { ... }
*/
Type *type; // the TypeEnum
Type *memtype; // type of the members
#if DMDV1
dinteger_t maxval;
dinteger_t minval;
dinteger_t defaultval; // default initializer
#else
Expression *maxval;
Expression *minval;
Expression *defaultval; // default initializer
Scope *scope; // !=NULL means context to use
#endif
int isdeprecated;
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
const char *kind();
#if DMDV2
Dsymbol *search(Loc, Identifier *ident, int flags);
#endif
int isDeprecated(); // is Dsymbol deprecated?
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumDeclaration *isEnumDeclaration() { return this; }
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
Symbol *sinit;
Symbol *toInitializer();
#endif
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct EnumMember : Dsymbol
{
Expression *value;
Type *type;
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumMember *isEnumMember() { return this; }
};
#endif /* DMD_ENUM_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -24,17 +24,7 @@
#include <complex.h>
#endif
#if IN_GCC || IN_LLVM
#include "mem.h"
#else
#if _WIN32
#include "..\root\mem.h"
#elif POSIX
#include "../root/mem.h"
#else
#error "fix this"
#endif
#endif
#include "rmem.h"
#include "id.h"
#include "init.h"

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2006 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -107,10 +107,10 @@ void Html::extractCode(OutBuffer *buf)
{ // Comments start with <!--
scanComment();
}
else if(p[1] == '!' && isCDATAStart())
{
scanCDATA();
}
else if(p[1] == '!' && isCDATAStart())
{
scanCDATA();
}
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
skipTag();
else if (istagstart(*skipWhite(p + 1)))
@@ -550,6 +550,7 @@ void Html::scanCDATA()
}
}
/********************************************
* Convert an HTML character entity into a character.
* Forms are:
@@ -716,3 +717,4 @@ static int isLineSeparator(const unsigned char* p)
return 0;
}

View File

@@ -1,9 +1,8 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -27,7 +26,7 @@ struct Html
Html(const char *sourcename, unsigned char *base, unsigned length);
void error(const char *format, ...);
void error(const char *format, ...) IS_PRINTF(2);
void extractCode(OutBuffer *buf);
void skipTag();
void skipString();

463
dmd2/id.c Normal file
View File

@@ -0,0 +1,463 @@
// File generated by idgen.c
#include "id.h"
#include "identifier.h"
#include "lexer.h"
Identifier *Id::IUnknown;
Identifier *Id::Object;
Identifier *Id::object;
Identifier *Id::max;
Identifier *Id::min;
Identifier *Id::This;
Identifier *Id::ctor;
Identifier *Id::dtor;
Identifier *Id::cpctor;
Identifier *Id::_postblit;
Identifier *Id::classInvariant;
Identifier *Id::unitTest;
Identifier *Id::init;
Identifier *Id::size;
Identifier *Id::__sizeof;
Identifier *Id::alignof;
Identifier *Id::mangleof;
Identifier *Id::stringof;
Identifier *Id::tupleof;
Identifier *Id::length;
Identifier *Id::remove;
Identifier *Id::ptr;
Identifier *Id::funcptr;
Identifier *Id::dollar;
Identifier *Id::offset;
Identifier *Id::offsetof;
Identifier *Id::ModuleInfo;
Identifier *Id::ClassInfo;
Identifier *Id::classinfo;
Identifier *Id::typeinfo;
Identifier *Id::outer;
Identifier *Id::Exception;
Identifier *Id::Throwable;
Identifier *Id::withSym;
Identifier *Id::result;
Identifier *Id::returnLabel;
Identifier *Id::delegate;
Identifier *Id::line;
Identifier *Id::empty;
Identifier *Id::p;
Identifier *Id::coverage;
Identifier *Id::__vptr;
Identifier *Id::__monitor;
Identifier *Id::system;
Identifier *Id::TypeInfo;
Identifier *Id::TypeInfo_Class;
Identifier *Id::TypeInfo_Interface;
Identifier *Id::TypeInfo_Struct;
Identifier *Id::TypeInfo_Enum;
Identifier *Id::TypeInfo_Typedef;
Identifier *Id::TypeInfo_Pointer;
Identifier *Id::TypeInfo_Array;
Identifier *Id::TypeInfo_StaticArray;
Identifier *Id::TypeInfo_AssociativeArray;
Identifier *Id::TypeInfo_Function;
Identifier *Id::TypeInfo_Delegate;
Identifier *Id::TypeInfo_Tuple;
Identifier *Id::TypeInfo_Const;
Identifier *Id::TypeInfo_Invariant;
Identifier *Id::TypeInfo_Shared;
Identifier *Id::elements;
Identifier *Id::_arguments_typeinfo;
Identifier *Id::_arguments;
Identifier *Id::_argptr;
Identifier *Id::_match;
Identifier *Id::destroy;
Identifier *Id::postblit;
Identifier *Id::LINE;
Identifier *Id::FILE;
Identifier *Id::DATE;
Identifier *Id::TIME;
Identifier *Id::TIMESTAMP;
Identifier *Id::VENDOR;
Identifier *Id::VERSIONX;
Identifier *Id::EOFX;
Identifier *Id::nan;
Identifier *Id::infinity;
Identifier *Id::dig;
Identifier *Id::epsilon;
Identifier *Id::mant_dig;
Identifier *Id::max_10_exp;
Identifier *Id::max_exp;
Identifier *Id::min_10_exp;
Identifier *Id::min_exp;
Identifier *Id::re;
Identifier *Id::im;
Identifier *Id::C;
Identifier *Id::D;
Identifier *Id::Windows;
Identifier *Id::Pascal;
Identifier *Id::System;
Identifier *Id::exit;
Identifier *Id::success;
Identifier *Id::failure;
Identifier *Id::keys;
Identifier *Id::values;
Identifier *Id::rehash;
Identifier *Id::sort;
Identifier *Id::reverse;
Identifier *Id::dup;
Identifier *Id::idup;
Identifier *Id::___out;
Identifier *Id::___in;
Identifier *Id::__int;
Identifier *Id::__dollar;
Identifier *Id::__LOCAL_SIZE;
Identifier *Id::uadd;
Identifier *Id::neg;
Identifier *Id::com;
Identifier *Id::add;
Identifier *Id::add_r;
Identifier *Id::sub;
Identifier *Id::sub_r;
Identifier *Id::mul;
Identifier *Id::mul_r;
Identifier *Id::div;
Identifier *Id::div_r;
Identifier *Id::mod;
Identifier *Id::mod_r;
Identifier *Id::eq;
Identifier *Id::cmp;
Identifier *Id::iand;
Identifier *Id::iand_r;
Identifier *Id::ior;
Identifier *Id::ior_r;
Identifier *Id::ixor;
Identifier *Id::ixor_r;
Identifier *Id::shl;
Identifier *Id::shl_r;
Identifier *Id::shr;
Identifier *Id::shr_r;
Identifier *Id::ushr;
Identifier *Id::ushr_r;
Identifier *Id::cat;
Identifier *Id::cat_r;
Identifier *Id::assign;
Identifier *Id::addass;
Identifier *Id::subass;
Identifier *Id::mulass;
Identifier *Id::divass;
Identifier *Id::modass;
Identifier *Id::andass;
Identifier *Id::orass;
Identifier *Id::xorass;
Identifier *Id::shlass;
Identifier *Id::shrass;
Identifier *Id::ushrass;
Identifier *Id::catass;
Identifier *Id::postinc;
Identifier *Id::postdec;
Identifier *Id::index;
Identifier *Id::indexass;
Identifier *Id::slice;
Identifier *Id::sliceass;
Identifier *Id::call;
Identifier *Id::cast;
Identifier *Id::match;
Identifier *Id::next;
Identifier *Id::opIn;
Identifier *Id::opIn_r;
Identifier *Id::opStar;
Identifier *Id::opDot;
Identifier *Id::opImplicitCast;
Identifier *Id::classNew;
Identifier *Id::classDelete;
Identifier *Id::apply;
Identifier *Id::applyReverse;
Identifier *Id::Fempty;
Identifier *Id::Fhead;
Identifier *Id::Ftoe;
Identifier *Id::Fnext;
Identifier *Id::Fretreat;
Identifier *Id::adDup;
Identifier *Id::adReverse;
Identifier *Id::aaLen;
Identifier *Id::aaKeys;
Identifier *Id::aaValues;
Identifier *Id::aaRehash;
Identifier *Id::GNU_asm;
Identifier *Id::lib;
Identifier *Id::msg;
Identifier *Id::startaddress;
Identifier *Id::intrinsic;
Identifier *Id::va_intrinsic;
Identifier *Id::no_typeinfo;
Identifier *Id::no_moduleinfo;
Identifier *Id::Alloca;
Identifier *Id::vastart;
Identifier *Id::vacopy;
Identifier *Id::vaend;
Identifier *Id::vaarg;
Identifier *Id::ldc;
Identifier *Id::allow_inline;
Identifier *Id::llvm_inline_asm;
Identifier *Id::tohash;
Identifier *Id::tostring;
Identifier *Id::getmembers;
Identifier *Id::main;
Identifier *Id::WinMain;
Identifier *Id::DllMain;
Identifier *Id::tls_get_addr;
Identifier *Id::std;
Identifier *Id::math;
Identifier *Id::sin;
Identifier *Id::cos;
Identifier *Id::tan;
Identifier *Id::_sqrt;
Identifier *Id::fabs;
Identifier *Id::isAbstractClass;
Identifier *Id::isArithmetic;
Identifier *Id::isAssociativeArray;
Identifier *Id::isFinalClass;
Identifier *Id::isFloating;
Identifier *Id::isIntegral;
Identifier *Id::isScalar;
Identifier *Id::isStaticArray;
Identifier *Id::isUnsigned;
Identifier *Id::isVirtualFunction;
Identifier *Id::isAbstractFunction;
Identifier *Id::isFinalFunction;
Identifier *Id::hasMember;
Identifier *Id::getMember;
Identifier *Id::getVirtualFunctions;
Identifier *Id::classInstanceSize;
Identifier *Id::allMembers;
Identifier *Id::derivedMembers;
Identifier *Id::isSame;
Identifier *Id::compiles;
void Id::initialize()
{
IUnknown = Lexer::idPool("IUnknown");
Object = Lexer::idPool("Object");
object = Lexer::idPool("object");
max = Lexer::idPool("max");
min = Lexer::idPool("min");
This = Lexer::idPool("this");
ctor = Lexer::idPool("__ctor");
dtor = Lexer::idPool("__dtor");
cpctor = Lexer::idPool("__cpctor");
_postblit = Lexer::idPool("__postblit");
classInvariant = Lexer::idPool("__invariant");
unitTest = Lexer::idPool("__unitTest");
init = Lexer::idPool("init");
size = Lexer::idPool("size");
__sizeof = Lexer::idPool("sizeof");
alignof = Lexer::idPool("alignof");
mangleof = Lexer::idPool("mangleof");
stringof = Lexer::idPool("stringof");
tupleof = Lexer::idPool("tupleof");
length = Lexer::idPool("length");
remove = Lexer::idPool("remove");
ptr = Lexer::idPool("ptr");
funcptr = Lexer::idPool("funcptr");
dollar = Lexer::idPool("__dollar");
offset = Lexer::idPool("offset");
offsetof = Lexer::idPool("offsetof");
ModuleInfo = Lexer::idPool("ModuleInfo");
ClassInfo = Lexer::idPool("ClassInfo");
classinfo = Lexer::idPool("classinfo");
typeinfo = Lexer::idPool("typeinfo");
outer = Lexer::idPool("outer");
Exception = Lexer::idPool("Exception");
Throwable = Lexer::idPool("Throwable");
withSym = Lexer::idPool("__withSym");
result = Lexer::idPool("__result");
returnLabel = Lexer::idPool("__returnLabel");
delegate = Lexer::idPool("delegate");
line = Lexer::idPool("line");
empty = Lexer::idPool("");
p = Lexer::idPool("p");
coverage = Lexer::idPool("__coverage");
__vptr = Lexer::idPool("__vptr");
__monitor = Lexer::idPool("__monitor");
system = Lexer::idPool("system");
TypeInfo = Lexer::idPool("TypeInfo");
TypeInfo_Class = Lexer::idPool("TypeInfo_Class");
TypeInfo_Interface = Lexer::idPool("TypeInfo_Interface");
TypeInfo_Struct = Lexer::idPool("TypeInfo_Struct");
TypeInfo_Enum = Lexer::idPool("TypeInfo_Enum");
TypeInfo_Typedef = Lexer::idPool("TypeInfo_Typedef");
TypeInfo_Pointer = Lexer::idPool("TypeInfo_Pointer");
TypeInfo_Array = Lexer::idPool("TypeInfo_Array");
TypeInfo_StaticArray = Lexer::idPool("TypeInfo_StaticArray");
TypeInfo_AssociativeArray = Lexer::idPool("TypeInfo_AssociativeArray");
TypeInfo_Function = Lexer::idPool("TypeInfo_Function");
TypeInfo_Delegate = Lexer::idPool("TypeInfo_Delegate");
TypeInfo_Tuple = Lexer::idPool("TypeInfo_Tuple");
TypeInfo_Const = Lexer::idPool("TypeInfo_Const");
TypeInfo_Invariant = Lexer::idPool("TypeInfo_Invariant");
TypeInfo_Shared = Lexer::idPool("TypeInfo_Shared");
elements = Lexer::idPool("elements");
_arguments_typeinfo = Lexer::idPool("_arguments_typeinfo");
_arguments = Lexer::idPool("_arguments");
_argptr = Lexer::idPool("_argptr");
_match = Lexer::idPool("_match");
destroy = Lexer::idPool("destroy");
postblit = Lexer::idPool("postblit");
LINE = Lexer::idPool("__LINE__");
FILE = Lexer::idPool("__FILE__");
DATE = Lexer::idPool("__DATE__");
TIME = Lexer::idPool("__TIME__");
TIMESTAMP = Lexer::idPool("__TIMESTAMP__");
VENDOR = Lexer::idPool("__VENDOR__");
VERSIONX = Lexer::idPool("__VERSION__");
EOFX = Lexer::idPool("__EOF__");
nan = Lexer::idPool("nan");
infinity = Lexer::idPool("infinity");
dig = Lexer::idPool("dig");
epsilon = Lexer::idPool("epsilon");
mant_dig = Lexer::idPool("mant_dig");
max_10_exp = Lexer::idPool("max_10_exp");
max_exp = Lexer::idPool("max_exp");
min_10_exp = Lexer::idPool("min_10_exp");
min_exp = Lexer::idPool("min_exp");
re = Lexer::idPool("re");
im = Lexer::idPool("im");
C = Lexer::idPool("C");
D = Lexer::idPool("D");
Windows = Lexer::idPool("Windows");
Pascal = Lexer::idPool("Pascal");
System = Lexer::idPool("System");
exit = Lexer::idPool("exit");
success = Lexer::idPool("success");
failure = Lexer::idPool("failure");
keys = Lexer::idPool("keys");
values = Lexer::idPool("values");
rehash = Lexer::idPool("rehash");
sort = Lexer::idPool("sort");
reverse = Lexer::idPool("reverse");
dup = Lexer::idPool("dup");
idup = Lexer::idPool("idup");
___out = Lexer::idPool("out");
___in = Lexer::idPool("in");
__int = Lexer::idPool("int");
__dollar = Lexer::idPool("$");
__LOCAL_SIZE = Lexer::idPool("__LOCAL_SIZE");
uadd = Lexer::idPool("opPos");
neg = Lexer::idPool("opNeg");
com = Lexer::idPool("opCom");
add = Lexer::idPool("opAdd");
add_r = Lexer::idPool("opAdd_r");
sub = Lexer::idPool("opSub");
sub_r = Lexer::idPool("opSub_r");
mul = Lexer::idPool("opMul");
mul_r = Lexer::idPool("opMul_r");
div = Lexer::idPool("opDiv");
div_r = Lexer::idPool("opDiv_r");
mod = Lexer::idPool("opMod");
mod_r = Lexer::idPool("opMod_r");
eq = Lexer::idPool("opEquals");
cmp = Lexer::idPool("opCmp");
iand = Lexer::idPool("opAnd");
iand_r = Lexer::idPool("opAnd_r");
ior = Lexer::idPool("opOr");
ior_r = Lexer::idPool("opOr_r");
ixor = Lexer::idPool("opXor");
ixor_r = Lexer::idPool("opXor_r");
shl = Lexer::idPool("opShl");
shl_r = Lexer::idPool("opShl_r");
shr = Lexer::idPool("opShr");
shr_r = Lexer::idPool("opShr_r");
ushr = Lexer::idPool("opUShr");
ushr_r = Lexer::idPool("opUShr_r");
cat = Lexer::idPool("opCat");
cat_r = Lexer::idPool("opCat_r");
assign = Lexer::idPool("opAssign");
addass = Lexer::idPool("opAddAssign");
subass = Lexer::idPool("opSubAssign");
mulass = Lexer::idPool("opMulAssign");
divass = Lexer::idPool("opDivAssign");
modass = Lexer::idPool("opModAssign");
andass = Lexer::idPool("opAndAssign");
orass = Lexer::idPool("opOrAssign");
xorass = Lexer::idPool("opXorAssign");
shlass = Lexer::idPool("opShlAssign");
shrass = Lexer::idPool("opShrAssign");
ushrass = Lexer::idPool("opUShrAssign");
catass = Lexer::idPool("opCatAssign");
postinc = Lexer::idPool("opPostInc");
postdec = Lexer::idPool("opPostDec");
index = Lexer::idPool("opIndex");
indexass = Lexer::idPool("opIndexAssign");
slice = Lexer::idPool("opSlice");
sliceass = Lexer::idPool("opSliceAssign");
call = Lexer::idPool("opCall");
cast = Lexer::idPool("opCast");
match = Lexer::idPool("opMatch");
next = Lexer::idPool("opNext");
opIn = Lexer::idPool("opIn");
opIn_r = Lexer::idPool("opIn_r");
opStar = Lexer::idPool("opStar");
opDot = Lexer::idPool("opDot");
opImplicitCast = Lexer::idPool("opImplicitCast");
classNew = Lexer::idPool("new");
classDelete = Lexer::idPool("delete");
apply = Lexer::idPool("opApply");
applyReverse = Lexer::idPool("opApplyReverse");
Fempty = Lexer::idPool("empty");
Fhead = Lexer::idPool("front");
Ftoe = Lexer::idPool("back");
Fnext = Lexer::idPool("popFront");
Fretreat = Lexer::idPool("popBack");
adDup = Lexer::idPool("_adDupT");
adReverse = Lexer::idPool("_adReverse");
aaLen = Lexer::idPool("_aaLen");
aaKeys = Lexer::idPool("_aaKeys");
aaValues = Lexer::idPool("_aaValues");
aaRehash = Lexer::idPool("_aaRehash");
GNU_asm = Lexer::idPool("GNU_asm");
lib = Lexer::idPool("lib");
msg = Lexer::idPool("msg");
startaddress = Lexer::idPool("startaddress");
intrinsic = Lexer::idPool("intrinsic");
va_intrinsic = Lexer::idPool("va_intrinsic");
no_typeinfo = Lexer::idPool("no_typeinfo");
no_moduleinfo = Lexer::idPool("no_moduleinfo");
Alloca = Lexer::idPool("alloca");
vastart = Lexer::idPool("va_start");
vacopy = Lexer::idPool("va_copy");
vaend = Lexer::idPool("va_end");
vaarg = Lexer::idPool("va_arg");
ldc = Lexer::idPool("ldc");
allow_inline = Lexer::idPool("allow_inline");
llvm_inline_asm = Lexer::idPool("llvm_inline_asm");
tohash = Lexer::idPool("toHash");
tostring = Lexer::idPool("toString");
getmembers = Lexer::idPool("getMembers");
main = Lexer::idPool("main");
WinMain = Lexer::idPool("WinMain");
DllMain = Lexer::idPool("DllMain");
tls_get_addr = Lexer::idPool("___tls_get_addr");
std = Lexer::idPool("std");
math = Lexer::idPool("math");
sin = Lexer::idPool("sin");
cos = Lexer::idPool("cos");
tan = Lexer::idPool("tan");
_sqrt = Lexer::idPool("sqrt");
fabs = Lexer::idPool("fabs");
isAbstractClass = Lexer::idPool("isAbstractClass");
isArithmetic = Lexer::idPool("isArithmetic");
isAssociativeArray = Lexer::idPool("isAssociativeArray");
isFinalClass = Lexer::idPool("isFinalClass");
isFloating = Lexer::idPool("isFloating");
isIntegral = Lexer::idPool("isIntegral");
isScalar = Lexer::idPool("isScalar");
isStaticArray = Lexer::idPool("isStaticArray");
isUnsigned = Lexer::idPool("isUnsigned");
isVirtualFunction = Lexer::idPool("isVirtualFunction");
isAbstractFunction = Lexer::idPool("isAbstractFunction");
isFinalFunction = Lexer::idPool("isFinalFunction");
hasMember = Lexer::idPool("hasMember");
getMember = Lexer::idPool("getMember");
getVirtualFunctions = Lexer::idPool("getVirtualFunctions");
classInstanceSize = Lexer::idPool("classInstanceSize");
allMembers = Lexer::idPool("allMembers");
derivedMembers = Lexer::idPool("derivedMembers");
isSame = Lexer::idPool("isSame");
compiles = Lexer::idPool("compiles");
}

237
dmd2/id.h Normal file
View File

@@ -0,0 +1,237 @@
// File generated by idgen.c
#ifndef DMD_ID_H
#define DMD_ID_H 1
struct Identifier;
struct Id
{
static Identifier *IUnknown;
static Identifier *Object;
static Identifier *object;
static Identifier *max;
static Identifier *min;
static Identifier *This;
static Identifier *ctor;
static Identifier *dtor;
static Identifier *cpctor;
static Identifier *_postblit;
static Identifier *classInvariant;
static Identifier *unitTest;
static Identifier *init;
static Identifier *size;
static Identifier *__sizeof;
static Identifier *alignof;
static Identifier *mangleof;
static Identifier *stringof;
static Identifier *tupleof;
static Identifier *length;
static Identifier *remove;
static Identifier *ptr;
static Identifier *funcptr;
static Identifier *dollar;
static Identifier *offset;
static Identifier *offsetof;
static Identifier *ModuleInfo;
static Identifier *ClassInfo;
static Identifier *classinfo;
static Identifier *typeinfo;
static Identifier *outer;
static Identifier *Exception;
static Identifier *Throwable;
static Identifier *withSym;
static Identifier *result;
static Identifier *returnLabel;
static Identifier *delegate;
static Identifier *line;
static Identifier *empty;
static Identifier *p;
static Identifier *coverage;
static Identifier *__vptr;
static Identifier *__monitor;
static Identifier *system;
static Identifier *TypeInfo;
static Identifier *TypeInfo_Class;
static Identifier *TypeInfo_Interface;
static Identifier *TypeInfo_Struct;
static Identifier *TypeInfo_Enum;
static Identifier *TypeInfo_Typedef;
static Identifier *TypeInfo_Pointer;
static Identifier *TypeInfo_Array;
static Identifier *TypeInfo_StaticArray;
static Identifier *TypeInfo_AssociativeArray;
static Identifier *TypeInfo_Function;
static Identifier *TypeInfo_Delegate;
static Identifier *TypeInfo_Tuple;
static Identifier *TypeInfo_Const;
static Identifier *TypeInfo_Invariant;
static Identifier *TypeInfo_Shared;
static Identifier *elements;
static Identifier *_arguments_typeinfo;
static Identifier *_arguments;
static Identifier *_argptr;
static Identifier *_match;
static Identifier *destroy;
static Identifier *postblit;
static Identifier *LINE;
static Identifier *FILE;
static Identifier *DATE;
static Identifier *TIME;
static Identifier *TIMESTAMP;
static Identifier *VENDOR;
static Identifier *VERSIONX;
static Identifier *EOFX;
static Identifier *nan;
static Identifier *infinity;
static Identifier *dig;
static Identifier *epsilon;
static Identifier *mant_dig;
static Identifier *max_10_exp;
static Identifier *max_exp;
static Identifier *min_10_exp;
static Identifier *min_exp;
static Identifier *re;
static Identifier *im;
static Identifier *C;
static Identifier *D;
static Identifier *Windows;
static Identifier *Pascal;
static Identifier *System;
static Identifier *exit;
static Identifier *success;
static Identifier *failure;
static Identifier *keys;
static Identifier *values;
static Identifier *rehash;
static Identifier *sort;
static Identifier *reverse;
static Identifier *dup;
static Identifier *idup;
static Identifier *___out;
static Identifier *___in;
static Identifier *__int;
static Identifier *__dollar;
static Identifier *__LOCAL_SIZE;
static Identifier *uadd;
static Identifier *neg;
static Identifier *com;
static Identifier *add;
static Identifier *add_r;
static Identifier *sub;
static Identifier *sub_r;
static Identifier *mul;
static Identifier *mul_r;
static Identifier *div;
static Identifier *div_r;
static Identifier *mod;
static Identifier *mod_r;
static Identifier *eq;
static Identifier *cmp;
static Identifier *iand;
static Identifier *iand_r;
static Identifier *ior;
static Identifier *ior_r;
static Identifier *ixor;
static Identifier *ixor_r;
static Identifier *shl;
static Identifier *shl_r;
static Identifier *shr;
static Identifier *shr_r;
static Identifier *ushr;
static Identifier *ushr_r;
static Identifier *cat;
static Identifier *cat_r;
static Identifier *assign;
static Identifier *addass;
static Identifier *subass;
static Identifier *mulass;
static Identifier *divass;
static Identifier *modass;
static Identifier *andass;
static Identifier *orass;
static Identifier *xorass;
static Identifier *shlass;
static Identifier *shrass;
static Identifier *ushrass;
static Identifier *catass;
static Identifier *postinc;
static Identifier *postdec;
static Identifier *index;
static Identifier *indexass;
static Identifier *slice;
static Identifier *sliceass;
static Identifier *call;
static Identifier *cast;
static Identifier *match;
static Identifier *next;
static Identifier *opIn;
static Identifier *opIn_r;
static Identifier *opStar;
static Identifier *opDot;
static Identifier *opImplicitCast;
static Identifier *classNew;
static Identifier *classDelete;
static Identifier *apply;
static Identifier *applyReverse;
static Identifier *Fempty;
static Identifier *Fhead;
static Identifier *Ftoe;
static Identifier *Fnext;
static Identifier *Fretreat;
static Identifier *adDup;
static Identifier *adReverse;
static Identifier *aaLen;
static Identifier *aaKeys;
static Identifier *aaValues;
static Identifier *aaRehash;
static Identifier *GNU_asm;
static Identifier *lib;
static Identifier *msg;
static Identifier *startaddress;
static Identifier *intrinsic;
static Identifier *va_intrinsic;
static Identifier *no_typeinfo;
static Identifier *no_moduleinfo;
static Identifier *Alloca;
static Identifier *vastart;
static Identifier *vacopy;
static Identifier *vaend;
static Identifier *vaarg;
static Identifier *ldc;
static Identifier *allow_inline;
static Identifier *llvm_inline_asm;
static Identifier *tohash;
static Identifier *tostring;
static Identifier *getmembers;
static Identifier *main;
static Identifier *WinMain;
static Identifier *DllMain;
static Identifier *tls_get_addr;
static Identifier *std;
static Identifier *math;
static Identifier *sin;
static Identifier *cos;
static Identifier *tan;
static Identifier *_sqrt;
static Identifier *fabs;
static Identifier *isAbstractClass;
static Identifier *isArithmetic;
static Identifier *isAssociativeArray;
static Identifier *isFinalClass;
static Identifier *isFloating;
static Identifier *isIntegral;
static Identifier *isScalar;
static Identifier *isStaticArray;
static Identifier *isUnsigned;
static Identifier *isVirtualFunction;
static Identifier *isAbstractFunction;
static Identifier *isFinalFunction;
static Identifier *hasMember;
static Identifier *getMember;
static Identifier *getVirtualFunctions;
static Identifier *classInstanceSize;
static Identifier *allMembers;
static Identifier *derivedMembers;
static Identifier *isSame;
static Identifier *compiles;
static void initialize();
};
#endif

View File

@@ -1,101 +1,102 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include "root.h"
#include "identifier.h"
#include "mars.h"
#include "lexer.h"
#include "id.h"
Identifier::Identifier(const char *string, int value)
{
//printf("Identifier('%s', %d)\n", string, value);
this->string = string;
this->value = value;
this->len = strlen(string);
}
hash_t Identifier::hashCode()
{
return String::calcHash(string);
}
int Identifier::equals(Object *o)
{
return this == o || memcmp(string,o->toChars(),len+1) == 0;
}
int Identifier::compare(Object *o)
{
return memcmp(string, o->toChars(), len + 1);
}
char *Identifier::toChars()
{
return (char *)string;
}
const char *Identifier::toHChars2()
{
const char *p = NULL;
if (this == Id::ctor) p = "this";
else if (this == Id::dtor) p = "~this";
else if (this == Id::classInvariant) p = "invariant";
else if (this == Id::unitTest) p = "unittest";
else if (this == Id::dollar) p = "$";
else if (this == Id::withSym) p = "with";
else if (this == Id::result) p = "result";
else if (this == Id::returnLabel) p = "return";
else
{ p = toChars();
if (*p == '_')
{
if (memcmp(p, "_staticCtor", 11) == 0)
p = "static this";
else if (memcmp(p, "_staticDtor", 11) == 0)
p = "static ~this";
}
}
return p;
}
void Identifier::print()
{
fprintf(stdmsg, "%s",string);
}
int Identifier::dyncast()
{
return DYNCAST_IDENTIFIER;
}
Identifier *Identifier::generateId(const char *prefix)
{
static size_t i;
return generateId(prefix, ++i);
}
Identifier *Identifier::generateId(const char *prefix, size_t i)
{ OutBuffer buf;
buf.writestring(prefix);
buf.printf("%"PRIuSIZE, i);
char *id = buf.toChars();
buf.data = NULL;
return Lexer::idPool(id);
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include "root.h"
#include "identifier.h"
#include "mars.h"
#include "lexer.h"
#include "id.h"
Identifier::Identifier(const char *string, int value)
{
//printf("Identifier('%s', %d)\n", string, value);
this->string = string;
this->value = value;
this->len = strlen(string);
}
hash_t Identifier::hashCode()
{
return String::calcHash(string);
}
int Identifier::equals(Object *o)
{
return this == o || memcmp(string,o->toChars(),len+1) == 0;
}
int Identifier::compare(Object *o)
{
return memcmp(string, o->toChars(), len + 1);
}
char *Identifier::toChars()
{
return (char *)string;
}
const char *Identifier::toHChars2()
{
const char *p = NULL;
if (this == Id::ctor) p = "this";
else if (this == Id::dtor) p = "~this";
else if (this == Id::classInvariant) p = "invariant";
else if (this == Id::unitTest) p = "unittest";
else if (this == Id::dollar) p = "$";
else if (this == Id::withSym) p = "with";
else if (this == Id::result) p = "result";
else if (this == Id::returnLabel) p = "return";
else
{ p = toChars();
if (*p == '_')
{
if (memcmp(p, "_staticCtor", 11) == 0)
p = "static this";
else if (memcmp(p, "_staticDtor", 11) == 0)
p = "static ~this";
}
}
return p;
}
void Identifier::print()
{
fprintf(stdmsg, "%s",string);
}
int Identifier::dyncast()
{
return DYNCAST_IDENTIFIER;
}
// BUG: these are redundant with Lexer::uniqueId()
Identifier *Identifier::generateId(const char *prefix)
{
static size_t i;
return generateId(prefix, ++i);
}
Identifier *Identifier::generateId(const char *prefix, size_t i)
{ OutBuffer buf;
buf.writestring(prefix);
buf.printf("%zu", i);
char *id = buf.toChars();
buf.data = NULL;
return Lexer::idPool(id);
}

View File

@@ -17,10 +17,12 @@
#include "root.h"
#if IN_LLVM
namespace llvm
{
class Value;
}
#endif
struct Identifier : Object
{

BIN
dmd2/idgen Executable file

Binary file not shown.

View File

@@ -1,363 +1,379 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
// Program to generate string files in d data structures.
// Saves much tedious typing, and eliminates typo problems.
// Generates:
// id.h
// id.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
struct Msgtable
{
const char *ident; // name to use in DMD source
const char *name; // name in D executable
};
Msgtable msgtable[] =
{
{ "IUnknown" },
{ "Object" },
{ "object" },
{ "max" },
{ "min" },
{ "This", "this" },
{ "ctor", "__ctor" },
{ "dtor", "__dtor" },
{ "cpctor", "__cpctor" },
{ "_postblit", "__postblit" },
{ "classInvariant", "__invariant" },
{ "unitTest", "__unitTest" },
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },
{ "alignof" },
{ "mangleof" },
{ "stringof" },
{ "tupleof" },
{ "length" },
{ "remove" },
{ "ptr" },
{ "funcptr" },
{ "dollar", "__dollar" },
{ "offset" },
{ "offsetof" },
{ "ModuleInfo" },
{ "ClassInfo" },
{ "classinfo" },
{ "typeinfo" },
{ "outer" },
{ "Exception" },
{ "withSym", "__withSym" },
{ "result", "__result" },
{ "returnLabel", "__returnLabel" },
{ "delegate" },
{ "line" },
{ "empty", "" },
{ "p" },
{ "coverage", "__coverage" },
{ "__vptr" },
{ "__monitor" },
{ "system" },
{ "TypeInfo" },
{ "TypeInfo_Class" },
{ "TypeInfo_Interface" },
{ "TypeInfo_Struct" },
{ "TypeInfo_Enum" },
{ "TypeInfo_Typedef" },
{ "TypeInfo_Pointer" },
{ "TypeInfo_Array" },
{ "TypeInfo_StaticArray" },
{ "TypeInfo_AssociativeArray" },
{ "TypeInfo_Function" },
{ "TypeInfo_Delegate" },
{ "TypeInfo_Tuple" },
{ "TypeInfo_Const" },
{ "TypeInfo_Invariant" },
{ "elements" },
{ "_arguments_typeinfo" },
{ "_arguments" },
{ "_argptr" },
{ "_match" },
{ "destroy" },
{ "postblit" },
{ "LINE", "__LINE__" },
{ "FILE", "__FILE__" },
{ "DATE", "__DATE__" },
{ "TIME", "__TIME__" },
{ "TIMESTAMP", "__TIMESTAMP__" },
{ "VENDOR", "__VENDOR__" },
{ "VERSIONX", "__VERSION__" },
{ "EOFX", "__EOF__" },
{ "nan" },
{ "infinity" },
{ "dig" },
{ "epsilon" },
{ "mant_dig" },
{ "max_10_exp" },
{ "max_exp" },
{ "min_10_exp" },
{ "min_exp" },
{ "re" },
{ "im" },
{ "C" },
{ "D" },
{ "Windows" },
{ "Pascal" },
{ "System" },
{ "exit" },
{ "success" },
{ "failure" },
{ "keys" },
{ "values" },
{ "rehash" },
{ "sort" },
{ "reverse" },
{ "dup" },
{ "idup" },
// For inline assembler
{ "___out", "out" },
{ "___in", "in" },
{ "__int", "int" },
{ "__dollar", "$" },
{ "__LOCAL_SIZE" },
// For operator overloads
{ "uadd", "opPos" },
{ "neg", "opNeg" },
{ "com", "opCom" },
{ "add", "opAdd" },
{ "add_r", "opAdd_r" },
{ "sub", "opSub" },
{ "sub_r", "opSub_r" },
{ "mul", "opMul" },
{ "mul_r", "opMul_r" },
{ "div", "opDiv" },
{ "div_r", "opDiv_r" },
{ "mod", "opMod" },
{ "mod_r", "opMod_r" },
{ "eq", "opEquals" },
{ "cmp", "opCmp" },
{ "iand", "opAnd" },
{ "iand_r", "opAnd_r" },
{ "ior", "opOr" },
{ "ior_r", "opOr_r" },
{ "ixor", "opXor" },
{ "ixor_r", "opXor_r" },
{ "shl", "opShl" },
{ "shl_r", "opShl_r" },
{ "shr", "opShr" },
{ "shr_r", "opShr_r" },
{ "ushr", "opUShr" },
{ "ushr_r", "opUShr_r" },
{ "cat", "opCat" },
{ "cat_r", "opCat_r" },
{ "assign", "opAssign" },
{ "addass", "opAddAssign" },
{ "subass", "opSubAssign" },
{ "mulass", "opMulAssign" },
{ "divass", "opDivAssign" },
{ "modass", "opModAssign" },
{ "andass", "opAndAssign" },
{ "orass", "opOrAssign" },
{ "xorass", "opXorAssign" },
{ "shlass", "opShlAssign" },
{ "shrass", "opShrAssign" },
{ "ushrass", "opUShrAssign" },
{ "catass", "opCatAssign" },
{ "postinc", "opPostInc" },
{ "postdec", "opPostDec" },
{ "index", "opIndex" },
{ "indexass", "opIndexAssign" },
{ "slice", "opSlice" },
{ "sliceass", "opSliceAssign" },
{ "call", "opCall" },
{ "cast", "opCast" },
{ "match", "opMatch" },
{ "next", "opNext" },
{ "opIn" },
{ "opIn_r" },
{ "opStar" },
{ "opDot" },
{ "opImplicitCast" },
{ "classNew", "new" },
{ "classDelete", "delete" },
// For foreach
{ "apply", "opApply" },
{ "applyReverse", "opApplyReverse" },
{ "Fempty", "empty" },
{ "Fhead", "head" },
{ "Ftoe", "toe" },
{ "Fnext", "next" },
{ "Fretreat", "retreat" },
{ "adDup", "_adDupT" },
{ "adReverse", "_adReverse" },
// For internal functions
{ "aaLen", "_aaLen" },
{ "aaKeys", "_aaKeys" },
{ "aaValues", "_aaValues" },
{ "aaRehash", "_aaRehash" },
// For pragma's
{ "GNU_asm" },
{ "lib" },
{ "msg" },
{ "startaddress" },
// LDC pragma's
{ "intrinsic" },
{ "va_intrinsic" },
{ "no_typeinfo" },
{ "no_moduleinfo" },
{ "Alloca", "alloca" },
{ "vastart", "va_start" },
{ "vacopy", "va_copy" },
{ "vaend", "va_end" },
{ "vaarg", "va_arg" },
{ "ldc" },
{ "allow_inline" },
// For special functions
{ "tohash", "toHash" },
{ "tostring", "toString" },
{ "getmembers", "getMembers" },
// Special functions
//{ "alloca" },
{ "main" },
{ "WinMain" },
{ "DllMain" },
// Builtin functions
{ "std" },
{ "math" },
{ "sin" },
{ "cos" },
{ "tan" },
{ "_sqrt", "sqrt" },
{ "fabs" },
// Traits
{ "isAbstractClass" },
{ "isArithmetic" },
{ "isAssociativeArray" },
{ "isFinalClass" },
{ "isFloating" },
{ "isIntegral" },
{ "isScalar" },
{ "isStaticArray" },
{ "isUnsigned" },
{ "isVirtualFunction" },
{ "isAbstractFunction" },
{ "isFinalFunction" },
{ "hasMember" },
{ "getMember" },
{ "getVirtualFunctions" },
{ "classInstanceSize" },
{ "allMembers" },
{ "derivedMembers" },
{ "isSame" },
{ "compiles" },
};
int main()
{
FILE *fp;
unsigned i;
{
fp = fopen("id.h","w");
if (!fp)
{ printf("can't open id.h\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "// File generated by idgen.c\n");
#if __DMC__
fprintf(fp, "#pragma once\n");
#endif
fprintf(fp, "#ifndef DMD_ID_H\n");
fprintf(fp, "#define DMD_ID_H 1\n");
fprintf(fp, "struct Identifier;\n");
fprintf(fp, "struct Id\n");
fprintf(fp, "{\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ const char *id = msgtable[i].ident;
fprintf(fp," static Identifier *%s;\n", id);
}
fprintf(fp, " static void initialize();\n");
fprintf(fp, "};\n");
fprintf(fp, "#endif\n");
fclose(fp);
}
{
fp = fopen("id.c","w");
if (!fp)
{ printf("can't open id.c\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "// File generated by idgen.c\n");
fprintf(fp, "#include \"id.h\"\n");
fprintf(fp, "#include \"identifier.h\"\n");
fprintf(fp, "#include \"lexer.h\"\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ const char *id = msgtable[i].ident;
const char *p = msgtable[i].name;
if (!p)
p = id;
fprintf(fp,"Identifier *Id::%s;\n", id);
}
fprintf(fp, "void Id::initialize()\n");
fprintf(fp, "{\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ const char *id = msgtable[i].ident;
const char *p = msgtable[i].name;
if (!p)
p = id;
fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p);
}
fprintf(fp, "}\n");
fclose(fp);
}
return EXIT_SUCCESS;
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
// Program to generate string files in d data structures.
// Saves much tedious typing, and eliminates typo problems.
// Generates:
// id.h
// id.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
struct Msgtable
{
const char *ident; // name to use in DMD source
const char *name; // name in D executable
};
Msgtable msgtable[] =
{
{ "IUnknown" },
{ "Object" },
{ "object" },
{ "max" },
{ "min" },
{ "This", "this" },
{ "ctor", "__ctor" },
{ "dtor", "__dtor" },
{ "cpctor", "__cpctor" },
{ "_postblit", "__postblit" },
{ "classInvariant", "__invariant" },
{ "unitTest", "__unitTest" },
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },
{ "alignof" },
{ "mangleof" },
{ "stringof" },
{ "tupleof" },
{ "length" },
{ "remove" },
{ "ptr" },
{ "funcptr" },
{ "dollar", "__dollar" },
{ "offset" },
{ "offsetof" },
{ "ModuleInfo" },
{ "ClassInfo" },
{ "classinfo" },
{ "typeinfo" },
{ "outer" },
{ "Exception" },
{ "Throwable" },
{ "withSym", "__withSym" },
{ "result", "__result" },
{ "returnLabel", "__returnLabel" },
{ "delegate" },
{ "line" },
{ "empty", "" },
{ "p" },
{ "coverage", "__coverage" },
{ "__vptr" },
{ "__monitor" },
{ "system" },
{ "TypeInfo" },
{ "TypeInfo_Class" },
{ "TypeInfo_Interface" },
{ "TypeInfo_Struct" },
{ "TypeInfo_Enum" },
{ "TypeInfo_Typedef" },
{ "TypeInfo_Pointer" },
{ "TypeInfo_Array" },
{ "TypeInfo_StaticArray" },
{ "TypeInfo_AssociativeArray" },
{ "TypeInfo_Function" },
{ "TypeInfo_Delegate" },
{ "TypeInfo_Tuple" },
{ "TypeInfo_Const" },
{ "TypeInfo_Invariant" },
{ "TypeInfo_Shared" },
{ "elements" },
{ "_arguments_typeinfo" },
{ "_arguments" },
{ "_argptr" },
{ "_match" },
{ "destroy" },
{ "postblit" },
{ "LINE", "__LINE__" },
{ "FILE", "__FILE__" },
{ "DATE", "__DATE__" },
{ "TIME", "__TIME__" },
{ "TIMESTAMP", "__TIMESTAMP__" },
{ "VENDOR", "__VENDOR__" },
{ "VERSIONX", "__VERSION__" },
{ "EOFX", "__EOF__" },
{ "nan" },
{ "infinity" },
{ "dig" },
{ "epsilon" },
{ "mant_dig" },
{ "max_10_exp" },
{ "max_exp" },
{ "min_10_exp" },
{ "min_exp" },
{ "re" },
{ "im" },
{ "C" },
{ "D" },
{ "Windows" },
{ "Pascal" },
{ "System" },
{ "exit" },
{ "success" },
{ "failure" },
{ "keys" },
{ "values" },
{ "rehash" },
{ "sort" },
{ "reverse" },
{ "dup" },
{ "idup" },
// For inline assembler
{ "___out", "out" },
{ "___in", "in" },
{ "__int", "int" },
{ "__dollar", "$" },
{ "__LOCAL_SIZE" },
// For operator overloads
{ "uadd", "opPos" },
{ "neg", "opNeg" },
{ "com", "opCom" },
{ "add", "opAdd" },
{ "add_r", "opAdd_r" },
{ "sub", "opSub" },
{ "sub_r", "opSub_r" },
{ "mul", "opMul" },
{ "mul_r", "opMul_r" },
{ "div", "opDiv" },
{ "div_r", "opDiv_r" },
{ "mod", "opMod" },
{ "mod_r", "opMod_r" },
{ "eq", "opEquals" },
{ "cmp", "opCmp" },
{ "iand", "opAnd" },
{ "iand_r", "opAnd_r" },
{ "ior", "opOr" },
{ "ior_r", "opOr_r" },
{ "ixor", "opXor" },
{ "ixor_r", "opXor_r" },
{ "shl", "opShl" },
{ "shl_r", "opShl_r" },
{ "shr", "opShr" },
{ "shr_r", "opShr_r" },
{ "ushr", "opUShr" },
{ "ushr_r", "opUShr_r" },
{ "cat", "opCat" },
{ "cat_r", "opCat_r" },
{ "assign", "opAssign" },
{ "addass", "opAddAssign" },
{ "subass", "opSubAssign" },
{ "mulass", "opMulAssign" },
{ "divass", "opDivAssign" },
{ "modass", "opModAssign" },
{ "andass", "opAndAssign" },
{ "orass", "opOrAssign" },
{ "xorass", "opXorAssign" },
{ "shlass", "opShlAssign" },
{ "shrass", "opShrAssign" },
{ "ushrass", "opUShrAssign" },
{ "catass", "opCatAssign" },
{ "postinc", "opPostInc" },
{ "postdec", "opPostDec" },
{ "index", "opIndex" },
{ "indexass", "opIndexAssign" },
{ "slice", "opSlice" },
{ "sliceass", "opSliceAssign" },
{ "call", "opCall" },
{ "cast", "opCast" },
{ "match", "opMatch" },
{ "next", "opNext" },
{ "opIn" },
{ "opIn_r" },
{ "opStar" },
{ "opDot" },
{ "opImplicitCast" },
{ "classNew", "new" },
{ "classDelete", "delete" },
// For foreach
{ "apply", "opApply" },
{ "applyReverse", "opApplyReverse" },
#if 1
{ "Fempty", "empty" },
{ "Fhead", "front" },
{ "Ftoe", "back" },
{ "Fnext", "popFront" },
{ "Fretreat", "popBack" },
#else
{ "Fempty", "empty" },
{ "Fhead", "head" },
{ "Ftoe", "toe" },
{ "Fnext", "next" },
{ "Fretreat", "retreat" },
#endif
{ "adDup", "_adDupT" },
{ "adReverse", "_adReverse" },
// For internal functions
{ "aaLen", "_aaLen" },
{ "aaKeys", "_aaKeys" },
{ "aaValues", "_aaValues" },
{ "aaRehash", "_aaRehash" },
// For pragma's
{ "GNU_asm" },
{ "lib" },
{ "msg" },
{ "startaddress" },
#if IN_LLVM
// LDC pragma's
{ "intrinsic" },
{ "va_intrinsic" },
{ "no_typeinfo" },
{ "no_moduleinfo" },
{ "Alloca", "alloca" },
{ "vastart", "va_start" },
{ "vacopy", "va_copy" },
{ "vaend", "va_end" },
{ "vaarg", "va_arg" },
{ "ldc" },
{ "allow_inline" },
{ "llvm_inline_asm" },
#endif
// For special functions
{ "tohash", "toHash" },
{ "tostring", "toString" },
{ "getmembers", "getMembers" },
// Special functions
#if IN_DMD
{ "alloca" },
#endif
{ "main" },
{ "WinMain" },
{ "DllMain" },
{ "tls_get_addr", "___tls_get_addr" },
// Builtin functions
{ "std" },
{ "math" },
{ "sin" },
{ "cos" },
{ "tan" },
{ "_sqrt", "sqrt" },
{ "fabs" },
// Traits
{ "isAbstractClass" },
{ "isArithmetic" },
{ "isAssociativeArray" },
{ "isFinalClass" },
{ "isFloating" },
{ "isIntegral" },
{ "isScalar" },
{ "isStaticArray" },
{ "isUnsigned" },
{ "isVirtualFunction" },
{ "isAbstractFunction" },
{ "isFinalFunction" },
{ "hasMember" },
{ "getMember" },
{ "getVirtualFunctions" },
{ "classInstanceSize" },
{ "allMembers" },
{ "derivedMembers" },
{ "isSame" },
{ "compiles" },
};
int main()
{
FILE *fp;
unsigned i;
{
fp = fopen("id.h","w");
if (!fp)
{ printf("can't open id.h\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "// File generated by idgen.c\n");
#if __DMC__
fprintf(fp, "#pragma once\n");
#endif
fprintf(fp, "#ifndef DMD_ID_H\n");
fprintf(fp, "#define DMD_ID_H 1\n");
fprintf(fp, "struct Identifier;\n");
fprintf(fp, "struct Id\n");
fprintf(fp, "{\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ const char *id = msgtable[i].ident;
fprintf(fp," static Identifier *%s;\n", id);
}
fprintf(fp, " static void initialize();\n");
fprintf(fp, "};\n");
fprintf(fp, "#endif\n");
fclose(fp);
}
{
fp = fopen("id.c","w");
if (!fp)
{ printf("can't open id.c\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "// File generated by idgen.c\n");
fprintf(fp, "#include \"id.h\"\n");
fprintf(fp, "#include \"identifier.h\"\n");
fprintf(fp, "#include \"lexer.h\"\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ const char *id = msgtable[i].ident;
const char *p = msgtable[i].name;
if (!p)
p = id;
fprintf(fp,"Identifier *Id::%s;\n", id);
}
fprintf(fp, "void Id::initialize()\n");
fprintf(fp, "{\n");
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
{ const char *id = msgtable[i].ident;
const char *p = msgtable[i].name;
if (!p)
p = id;
fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p);
}
fprintf(fp, "}\n");
fclose(fp);
}
return EXIT_SUCCESS;
}

BIN
dmd2/impcnvgen Executable file

Binary file not shown.

182
dmd2/impcnvtab.c Normal file
View File

@@ -0,0 +1,182 @@
// This file is generated by impcnvgen.c
#include "mtype.h"
unsigned char Type::impcnvResult[TMAX][TMAX] =
{
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
};
unsigned char Type::impcnvType1[TMAX][TMAX] =
{
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,22,23,24,36,19,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,22,23,24,36,20,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,22,23,24,36,21,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,22,23,24,36,22,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,23,23,24,36,23,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,36,24,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,25,25,25,25,25,25,25,25,25,26,27,25,26,27,25,26,27,36,25,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,26,26,26,26,26,26,26,26,26,26,27,26,26,27,26,26,27,36,26,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,36,27,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,32,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
};
unsigned char Type::impcnvType2[TMAX][TMAX] =
{
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
};
unsigned char Type::impcnvWarn[TMAX][TMAX] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

View File

@@ -1,262 +1,373 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "dsymbol.h"
#include "import.h"
#include "identifier.h"
#include "module.h"
#include "scope.h"
#include "hdrgen.h"
#include "mtype.h"
#include "declaration.h"
#include "id.h"
/********************************* Import ****************************/
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
{
this->loc = loc;
this->packages = packages;
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
protection = PROTundefined;
pkg = NULL;
mod = NULL;
if (aliasId)
this->ident = aliasId;
// Kludge to change Import identifier to first package
else if (packages && packages->dim)
this->ident = (Identifier *)packages->data[0];
}
void Import::addAlias(Identifier *name, Identifier *alias)
{
if (isstatic)
error("cannot have an import bind list");
if (!aliasId)
this->ident = NULL; // make it an anonymous import
names.push(name);
aliases.push(alias);
}
const char *Import::kind()
{
return isstatic ? (char *)"static import" : (char *)"import";
}
enum PROT Import::prot()
{
return protection;
}
Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
}
return si;
}
void Import::load(Scope *sc)
{
DsymbolTable *dst;
Dsymbol *s;
//printf("Import::load('%s')\n", toChars());
// See if existing module
dst = Package::resolve(packages, NULL, &pkg);
s = dst->lookup(id);
if (s)
{
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
}
if (!mod)
{
// Load module
mod = Module::load(loc, packages, id);
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
if (!pkg)
pkg = mod;
mod->semantic();
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
load(sc);
if (mod)
{
#if 0
if (mod->loc.linnum != 0)
{ /* If the line number is not 0, then this is not
* a 'root' module, i.e. it was not specified on the command line.
*/
mod->importedFrom = sc->module->importedFrom;
assert(mod->importedFrom);
}
#endif
/* Default to private importing
*/
protection = sc->protection;
if (!sc->explicitProtection)
protection = PROTprivate;
if (!isstatic && !aliasId && !names.dim)
{
sc->scopesym->importScope(mod, protection);
}
// Modules need a list of each imported module
sc->module->aimports.push(mod);
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, (Identifier *)names.data[i], 0))
error("%s not found", ((Identifier *)names.data[i])->toChars());
ad->semantic(sc);
ad->protection = protection;
}
sc = sc->pop();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)
{
//printf("Import::semantic2('%s')\n", toChars());
mod->semantic2();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
}
Dsymbol *Import::toAlias()
{
if (aliasId)
return mod;
return this;
}
/*****************************
* Add import to sd's symbol table.
*/
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int result = 0;
if (names.dim == 0)
return Dsymbol::addMember(sc, sd, memnum);
if (aliasId)
result = Dsymbol::addMember(sc, sd, memnum);
/* Instead of adding the import to sd's symbol table,
* add each of the alias=name pairs
*/
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias)
alias = name;
TypeIdentifier *tname = new TypeIdentifier(loc, name);
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
}
return result;
}
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
if (!pkg)
load(NULL);
// Forward it to the package/module
return pkg->search(loc, ident, flags);
}
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen && id == Id::object)
return; // object is imported by default
if (isstatic)
buf->writestring("static ");
buf->writestring("import ");
if (aliasId)
{
buf->printf("%s = ", aliasId->toChars());
}
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s;", id->toChars());
buf->writenl();
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "dsymbol.h"
#include "import.h"
#include "identifier.h"
#include "module.h"
#include "scope.h"
#include "hdrgen.h"
#include "mtype.h"
#include "declaration.h"
#include "id.h"
/********************************* Import ****************************/
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
{
assert(id);
this->loc = loc;
this->packages = packages;
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
#if IN_LLVM
protection = PROTundefined;
#endif
pkg = NULL;
mod = NULL;
if (aliasId)
this->ident = aliasId;
// Kludge to change Import identifier to first package
else if (packages && packages->dim)
this->ident = (Identifier *)packages->data[0];
}
void Import::addAlias(Identifier *name, Identifier *alias)
{
if (isstatic)
error("cannot have an import bind list");
if (!aliasId)
this->ident = NULL; // make it an anonymous import
names.push(name);
aliases.push(alias);
}
const char *Import::kind()
{
return isstatic ? (char *)"static import" : (char *)"import";
}
#if IN_LLVM
enum PROT Import::prot()
{
return protection;
}
#endif
Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
}
return si;
}
void Import::load(Scope *sc)
{
DsymbolTable *dst;
Dsymbol *s;
//printf("Import::load('%s')\n", toChars());
// See if existing module
dst = Package::resolve(packages, NULL, &pkg);
s = dst->lookup(id);
if (s)
{
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
}
if (!mod)
{
// Load module
mod = Module::load(loc, packages, id);
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
if (!pkg)
pkg = mod;
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
#if IN_LLVM
char* escapePath(char* fname, char* buffer, int bufLen) {
char* res = buffer;
bufLen -= 2; // for \0 and an occasional escape char
int dst = 0;
for (; dst < bufLen && *fname; ++dst, ++fname) {
switch (*fname) {
case '(':
case ')':
case '\\':
buffer[dst++] = '\\';
// fall through
default:
buffer[dst] = *fname;
}
}
buffer[dst] = '\0';
return buffer;
}
#endif
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
load(sc);
if (mod)
{
#if 0
if (mod->loc.linnum != 0)
{ /* If the line number is not 0, then this is not
* a 'root' module, i.e. it was not specified on the command line.
*/
mod->importedFrom = sc->module->importedFrom;
assert(mod->importedFrom);
}
#endif
// Modules need a list of each imported module
//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
sc->module->aimports.push(mod);
mod->semantic();
if (!isstatic && !aliasId && !names.dim)
{
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
sc->scopesym->importScope(mod, prot);
}
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, (Identifier *)names.data[i], 0))
error("%s not found", ((Identifier *)names.data[i])->toChars());
ad->importprot = protection;
ad->semantic(sc);
}
sc = sc->pop();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
if (global.params.moduleDeps != NULL) {
char fnameBuf[262]; // MAX_PATH+2
OutBuffer *const ob = global.params.moduleDeps;
ob->printf("%s (%s) : ",
sc->module->toPrettyChars(),
escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
);
char* protStr = "";
switch (sc->protection) {
case PROTpublic: protStr = "public"; break;
case PROTprivate: protStr = "private"; break;
case PROTpackage: protStr = "package"; break;
default: break;
}
ob->writestring(protStr);
if (isstatic) {
ob->writestring(" static");
}
ob->writestring(" : ");
if (this->packages) {
for (size_t i = 0; i < this->packages->dim; i++) {
Identifier *pid = (Identifier *)this->packages->data[i];
ob->printf("%s.", pid->toChars());
}
}
ob->printf("%s (%s)",
this->id->toChars(),
mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???"
);
if (aliasId) {
ob->printf(" -> %s", aliasId->toChars());
} else {
if (names.dim > 0) {
ob->writestring(" : ");
for (size_t i = 0; i < names.dim; i++)
{
if (i > 0) {
ob->writebyte(',');
}
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias) {
ob->printf("%s", name->toChars());
alias = name;
} else {
ob->printf("%s=%s", alias->toChars(), name->toChars());
}
}
}
}
ob->writenl();
}
}
void Import::semantic2(Scope *sc)
{
//printf("Import::semantic2('%s')\n", toChars());
mod->semantic2();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
}
Dsymbol *Import::toAlias()
{
if (aliasId)
return mod;
return this;
}
/*****************************
* Add import to sd's symbol table.
*/
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int result = 0;
if (names.dim == 0)
return Dsymbol::addMember(sc, sd, memnum);
if (aliasId)
result = Dsymbol::addMember(sc, sd, memnum);
/* Instead of adding the import to sd's symbol table,
* add each of the alias=name pairs
*/
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias)
alias = name;
TypeIdentifier *tname = new TypeIdentifier(loc, name);
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
}
return result;
}
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
if (!pkg)
{ load(NULL);
mod->semantic();
}
// Forward it to the package/module
return pkg->search(loc, ident, flags);
}
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen && id == Id::object)
return; // object is imported by default
if (isstatic)
buf->writestring("static ");
buf->writestring("import ");
if (aliasId)
{
buf->printf("%s = ", aliasId->toChars());
}
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (Identifier *)packages->data[i];
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s", id->toChars());
if (names.dim > 0) {
buf->writebyte(':');
for (size_t i = 0; i < names.dim; i++)
{
if (i > 0) {
buf->writebyte(',');
}
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias) {
buf->printf("%s", name->toChars());
alias = name;
} else {
buf->printf("%s=%s", alias->toChars(), name->toChars());
}
}
}
buf->writebyte(';');
buf->writenl();
}

View File

@@ -1,300 +1,316 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "root.h"
#include "mem.h"
#ifdef __MINGW32__
#include <malloc.h>
#endif
#define LOG 0
char *skipspace(const char *p);
#if __GNUC__
char *strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
#endif /* unix */
/*****************************
* Read and analyze .ini file.
* Input:
* argv0 program name (argv[0])
* inifile .ini file name
*/
void inifile(char *argv0x, const char *inifilex)
{
char *argv0 = (char *)argv0x;
char *inifile = (char *)inifilex; // do const-correct later
char *path; // need path for @P macro
char *filename;
OutBuffer buf;
int i;
int k;
int envsection = 0;
#if LOG
printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
#endif
if (FileName::absolute(inifile))
{
filename = inifile;
}
else
{
/* Look for inifile in the following sequence of places:
* o current directory
* o home directory
* o directory off of argv0
* o /etc/
*/
if (FileName::exists(inifile))
{
filename = inifile;
}
else
{
filename = FileName::combine(getenv("HOME"), inifile);
if (!FileName::exists(filename))
{
filename = FileName::replaceName(argv0, inifile);
if (!FileName::exists(filename))
{
#if POSIX
#if 0
#if __GLIBC__ // This fix by Thomas Kuehne
/* argv0 might be a symbolic link,
* so try again looking past it to the real path
*/
char* real_argv0 = realpath(argv0, NULL);
if (real_argv0)
{
filename = FileName::replaceName(real_argv0, inifile);
free(real_argv0);
if (FileName::exists(filename))
goto Ldone;
}
#else
#error use of glibc non-standard extension realpath(char*, NULL)
#endif
#endif
// old way; problem is that argv0 might not be on the PATH at all
// and some other instance might be found
// Search PATH for argv0
const char *p = getenv("PATH");
Array *paths = FileName::splitPath(p);
filename = FileName::searchPath(paths, argv0, 0);
if (!filename)
goto Letc; // argv0 not found on path
filename = FileName::replaceName(filename, inifile);
if (FileName::exists(filename))
goto Ldone;
#endif
// Search /etc/ for inifile
Letc:
filename = FileName::combine((char *)"/etc/", inifile);
Ldone:
;
}
}
}
}
path = FileName::path(filename);
#if LOG
printf("\tpath = '%s', filename = '%s'\n", path, filename);
#endif
File file(filename);
if (file.read())
return; // error reading file
// Parse into lines
int eof = 0;
for (i = 0; i < file.len && !eof; i++)
{
int linestart = i;
for (; i < file.len; i++)
{
switch (file.buffer[i])
{
case '\r':
break;
case '\n':
// Skip if it was preceded by '\r'
if (i && file.buffer[i - 1] == '\r')
goto Lskip;
break;
case 0:
case 0x1A:
eof = 1;
break;
default:
continue;
}
break;
}
// The line is file.buffer[linestart..i]
char *line;
int len;
char *p;
char *pn;
line = (char *)&file.buffer[linestart];
len = i - linestart;
buf.reset();
// First, expand the macros.
// Macros are bracketed by % characters.
for (k = 0; k < len; k++)
{
if (line[k] == '%')
{
int j;
for (j = k + 1; j < len; j++)
{
if (line[j] == '%')
{
if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
{
// %@P% is special meaning the path to the .ini file
p = path;
if (!*p)
p = (char *)".";
}
else
{ int len = j - k;
char tmp[10]; // big enough most of the time
if (len <= sizeof(tmp))
p = tmp;
else
p = (char *)alloca(len);
len--;
memcpy(p, &line[k + 1], len);
p[len] = 0;
strupr(p);
p = getenv(p);
if (!p)
p = (char *)"";
}
buf.writestring(p);
k = j;
goto L1;
}
}
}
buf.writeByte(line[k]);
L1:
;
}
// Remove trailing spaces
while (buf.offset && isspace(buf.data[buf.offset - 1]))
buf.offset--;
p = buf.toChars();
// The expanded line is in p.
// Now parse it for meaning.
p = skipspace(p);
switch (*p)
{
case ';': // comment
case 0: // blank
break;
case '[': // look for [Environment]
p = skipspace(p + 1);
for (pn = p; isalnum(*pn); pn++)
;
if (pn - p == 11 &&
memicmp(p, "Environment", 11) == 0 &&
*skipspace(pn) == ']'
)
envsection = 1;
else
envsection = 0;
break;
default:
if (envsection)
{
pn = p;
// Convert name to upper case;
// remove spaces bracketing =
for (p = pn; *p; p++)
{ if (islower(*p))
*p &= ~0x20;
else if (isspace(*p))
memmove(p, p + 1, strlen(p));
else if (*p == '=')
{
p++;
while (isspace(*p))
memmove(p, p + 1, strlen(p));
break;
}
}
putenv(strdup(pn));
#if LOG
printf("\tputenv('%s')\n", pn);
//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
#endif
}
break;
}
Lskip:
;
}
}
/********************
* Skip spaces.
*/
char *skipspace(const char *p)
{
while (isspace(*p))
p++;
return (char *)p;
}
/*
* Some portions copyright (c) 1994-1995 by Symantec
* Copyright (c) 1999-2009 by Digital Mars
* All Rights Reserved
* http://www.digitalmars.com
* Written by Walter Bright
*
* This source file is made available for personal use
* only. The license is in /dmd/src/dmd/backendlicense.txt
* For any other uses, please contact Digital Mars.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#if __APPLE__
#include <sys/syslimits.h>
#endif
#if __FreeBSD__ || __sun&&__SVR4
// for PATH_MAX
#include <limits.h>
#endif
#if __sun&&__SVR4
#include <alloca.h>
#endif
#include "root.h"
#include "rmem.h"
#define LOG 0
char *skipspace(const char *p);
#if __GNUC__
char *strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
#endif /* unix */
/*****************************
* Read and analyze .ini file.
* Input:
* argv0 program name (argv[0])
* inifile .ini file name
*/
void inifile(const char *argv0x, const char *inifilex)
{
char *argv0 = (char *)argv0x;
char *inifile = (char *)inifilex; // do const-correct later
char *path; // need path for @P macro
char *filename;
OutBuffer buf;
int i;
int k;
int envsection = 0;
#if LOG
printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
#endif
if (FileName::absolute(inifile))
{
filename = inifile;
}
else
{
/* Look for inifile in the following sequence of places:
* o current directory
* o home directory
* o directory off of argv0
* o /etc/
*/
if (FileName::exists(inifile))
{
filename = inifile;
}
else
{
filename = FileName::combine(getenv("HOME"), inifile);
if (!FileName::exists(filename))
{
filename = (char *)FileName::replaceName(argv0, inifile);
if (!FileName::exists(filename))
{
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#if __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 // This fix by Thomas Kuehne
/* argv0 might be a symbolic link,
* so try again looking past it to the real path
*/
#if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
char resolved_name[PATH_MAX + 1];
char* real_argv0 = realpath(argv0, resolved_name);
#else
char* real_argv0 = realpath(argv0, NULL);
#endif
//printf("argv0 = %s, real_argv0 = %p\n", argv0, real_argv0);
if (real_argv0)
{
filename = (char *)FileName::replaceName(real_argv0, inifile);
#if !(__APPLE__ || __FreeBSD__ || __sun&&__SVR4)
free(real_argv0);
#endif
if (FileName::exists(filename))
goto Ldone;
}
#else
#error use of glibc non-standard extension realpath(char*, NULL)
#endif
if (1){
// Search PATH for argv0
const char *p = getenv("PATH");
Array *paths = FileName::splitPath(p);
filename = FileName::searchPath(paths, argv0, 0);
if (!filename)
goto Letc; // argv0 not found on path
filename = (char *)FileName::replaceName(filename, inifile);
if (FileName::exists(filename))
goto Ldone;
}
#endif
// Search /etc/ for inifile
Letc:
filename = FileName::combine((char *)"/etc/", inifile);
Ldone:
;
}
}
}
}
path = FileName::path(filename);
#if LOG
printf("\tpath = '%s', filename = '%s'\n", path, filename);
#endif
File file(filename);
if (file.read())
return; // error reading file
// Parse into lines
int eof = 0;
for (i = 0; i < file.len && !eof; i++)
{
int linestart = i;
for (; i < file.len; i++)
{
switch (file.buffer[i])
{
case '\r':
break;
case '\n':
// Skip if it was preceded by '\r'
if (i && file.buffer[i - 1] == '\r')
goto Lskip;
break;
case 0:
case 0x1A:
eof = 1;
break;
default:
continue;
}
break;
}
// The line is file.buffer[linestart..i]
char *line;
int len;
char *p;
char *pn;
line = (char *)&file.buffer[linestart];
len = i - linestart;
buf.reset();
// First, expand the macros.
// Macros are bracketed by % characters.
for (k = 0; k < len; k++)
{
if (line[k] == '%')
{
int j;
for (j = k + 1; j < len; j++)
{
if (line[j] == '%')
{
if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
{
// %@P% is special meaning the path to the .ini file
p = path;
if (!*p)
p = (char *)".";
}
else
{ int len = j - k;
char tmp[10]; // big enough most of the time
if (len <= sizeof(tmp))
p = tmp;
else
p = (char *)alloca(len);
len--;
memcpy(p, &line[k + 1], len);
p[len] = 0;
strupr(p);
p = getenv(p);
if (!p)
p = (char *)"";
}
buf.writestring(p);
k = j;
goto L1;
}
}
}
buf.writeByte(line[k]);
L1:
;
}
// Remove trailing spaces
while (buf.offset && isspace(buf.data[buf.offset - 1]))
buf.offset--;
p = buf.toChars();
// The expanded line is in p.
// Now parse it for meaning.
p = skipspace(p);
switch (*p)
{
case ';': // comment
case 0: // blank
break;
case '[': // look for [Environment]
p = skipspace(p + 1);
for (pn = p; isalnum(*pn); pn++)
;
if (pn - p == 11 &&
memicmp(p, "Environment", 11) == 0 &&
*skipspace(pn) == ']'
)
envsection = 1;
else
envsection = 0;
break;
default:
if (envsection)
{
pn = p;
// Convert name to upper case;
// remove spaces bracketing =
for (p = pn; *p; p++)
{ if (islower(*p))
*p &= ~0x20;
else if (isspace(*p))
memmove(p, p + 1, strlen(p));
else if (*p == '=')
{
p++;
while (isspace(*p))
memmove(p, p + 1, strlen(p));
break;
}
}
putenv(strdup(pn));
#if LOG
printf("\tputenv('%s')\n", pn);
//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
#endif
}
break;
}
Lskip:
;
}
}
/********************
* Skip spaces.
*/
char *skipspace(const char *p)
{
while (isspace(*p))
p++;
return (char *)p;
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,6 @@ struct VoidInitializer;
struct StructInitializer;
struct ArrayInitializer;
struct ExpInitializer;
struct StructInitializer;
#ifdef _DH
struct HdrGenState;
#endif
@@ -45,7 +44,9 @@ struct Initializer : Object
static Initializers *arraySyntaxCopy(Initializers *ai);
#if IN_DMD
virtual dt_t *toDt();
#endif
virtual VoidInitializer *isVoidInitializer() { return NULL; }
virtual StructInitializer *isStructInitializer() { return NULL; }
@@ -63,7 +64,9 @@ struct VoidInitializer : Initializer
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
#endif
virtual VoidInitializer *isVoidInitializer() { return this; }
};
@@ -83,9 +86,11 @@ struct StructInitializer : Initializer
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
#endif
StructInitializer *isStructInitializer() { return this; }
StructInitializer *isStructInitializer() { return this; }
};
struct ArrayInitializer : Initializer
@@ -105,8 +110,10 @@ struct ArrayInitializer : Initializer
Initializer *toAssocArrayInitializer();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
dt_t *toDtBit(); // for bit arrays
#endif
ArrayInitializer *isArrayInitializer() { return this; }
};
@@ -122,7 +129,9 @@ struct ExpInitializer : Initializer
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
#endif
virtual ExpInitializer *isExpInitializer() { return this; }
};

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
#include <stdlib.h>
#include <assert.h>
#include "mem.h"
#include "rmem.h"
#include "statement.h"
#include "expression.h"
@@ -69,7 +69,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
else if (ident == Id::aaValues)
return interpret_aaValues(istate, arguments);
if (cantInterpret || semanticRun == 1)
if (cantInterpret || semanticRun == 3)
return NULL;
if (needThis() || isNested() || !fbody)
@@ -77,13 +77,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
return NULL;
}
if (semanticRun == 0 && scope)
if (semanticRun < 3 && scope)
{
semantic3(scope);
if (global.errors) // if errors compiling this function
return NULL;
if (global.errors) // if errors compiling this function
return NULL;
}
if (semanticRun < 2)
if (semanticRun < 4)
return NULL;
Type *tb = type->toBasetype();
@@ -987,7 +987,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
{
Expression *e = EXP_CANT_INTERPRET;
VarDeclaration *v = d->isVarDeclaration();
#if IN_LLVM
StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration();
#else
SymbolDeclaration *s = d->isSymbolDeclaration();
#endif
if (v)
{
#if DMDV2
@@ -1512,6 +1516,80 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
}
}
}
/* Assignment to struct member of the form:
* v.var = e2
*/
else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar)
{ VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v->isDataseg())
return EXP_CANT_INTERPRET;
if (fp && !v->value)
{ error("variable %s is used before initialization", v->toChars());
return e;
}
if (v->value == NULL && v->init->isVoidInitializer())
{ /* Since a void initializer initializes to undefined
* values, it is valid here to use the default initializer.
* No attempt is made to determine if someone actually relies
* on the void value - to do that we'd need a VoidExp.
* That's probably a good enhancement idea.
*/
v->value = v->type->defaultInit();
}
Expression *vie = v->value;
if (vie->op == TOKvar)
{
Declaration *d = ((VarExp *)vie)->var;
vie = getVarExp(e1->loc, istate, d);
}
if (vie->op != TOKstructliteral)
return EXP_CANT_INTERPRET;
StructLiteralExp *se = (StructLiteralExp *)vie;
VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
if (!vf)
return EXP_CANT_INTERPRET;
int fieldi = se->getFieldIndex(type, vf->offset);
if (fieldi == -1)
return EXP_CANT_INTERPRET;
Expression *ev = se->getField(type, vf->offset);
if (fp)
e2 = (*fp)(type, ev, e2);
else
e2 = Cast(type, type, e2);
if (e2 == EXP_CANT_INTERPRET)
return e2;
if (!v->isParameter())
{
for (size_t i = 0; 1; i++)
{
if (i == istate->vars.dim)
{ istate->vars.push(v);
break;
}
if (v == (VarDeclaration *)istate->vars.data[i])
break;
}
}
/* Create new struct literal reflecting updated fieldi
*/
Expressions *expsx = new Expressions();
expsx->setDim(se->elements->dim);
for (size_t j = 0; j < expsx->dim; j++)
{
if (j == fieldi)
expsx->data[j] = (void *)e2;
else
expsx->data[j] = se->elements->data[j];
}
v->value = new StructLiteralExp(se->loc, se->sd, expsx);
v->value->type = se->type;
e = Cast(type, type, post ? ev : e2);
}
/* Assignment to struct member of the form:
* *(symoffexp) = e2
*/
@@ -2159,21 +2237,29 @@ Expression *PtrExp::interpret(InterState *istate)
Expression *DotVarExp::interpret(InterState *istate)
{ Expression *e = EXP_CANT_INTERPRET;
#if LOG
printf("DotVarExp::interpret() %s\n", toChars());
#endif
Expression *ex = e1->interpret(istate);
// Constant fold structliteral.member
if (ex != EXP_CANT_INTERPRET && ex->op == TOKstructliteral)
{ StructLiteralExp *se = (StructLiteralExp *)ex;
VarDeclaration* v;
if (v = var->isVarDeclaration())
{
e = se->getField(type, v->offset);
if (!e)
e = EXP_CANT_INTERPRET;
if (ex != EXP_CANT_INTERPRET)
{
if (ex->op == TOKstructliteral)
{ StructLiteralExp *se = (StructLiteralExp *)ex;
VarDeclaration *v = var->isVarDeclaration();
if (v)
{ e = se->getField(type, v->offset);
if (!e)
e = EXP_CANT_INTERPRET;
return e;
}
}
}
#if LOG
if (e == EXP_CANT_INTERPRET)
printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
#endif
return e;
}

164
dmd2/irstate.c Normal file
View File

@@ -0,0 +1,164 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include <stdio.h>
#include "irstate.h"
IRState::IRState(IRState *irs, Statement *s)
{
prev = irs;
statement = s;
symbol = NULL;
breakBlock = NULL;
contBlock = NULL;
switchBlock = NULL;
defaultBlock = NULL;
ident = NULL;
ehidden = NULL;
startaddress = NULL;
if (irs)
{
m = irs->m;
shidden = irs->shidden;
sclosure = irs->sclosure;
sthis = irs->sthis;
blx = irs->blx;
deferToObj = irs->deferToObj;
}
else
{
m = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
}
}
IRState::IRState(IRState *irs, Dsymbol *s)
{
prev = irs;
statement = NULL;
symbol = s;
breakBlock = NULL;
contBlock = NULL;
switchBlock = NULL;
defaultBlock = NULL;
ident = NULL;
ehidden = NULL;
startaddress = NULL;
if (irs)
{
m = irs->m;
shidden = irs->shidden;
sclosure = irs->sclosure;
sthis = irs->sthis;
blx = irs->blx;
deferToObj = irs->deferToObj;
}
else
{
m = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
}
}
IRState::IRState(Module *m, Dsymbol *s)
{
prev = NULL;
statement = NULL;
this->m = m;
symbol = s;
breakBlock = NULL;
contBlock = NULL;
switchBlock = NULL;
defaultBlock = NULL;
ident = NULL;
ehidden = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
startaddress = NULL;
}
block *IRState::getBreakBlock(Identifier *ident)
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (ident)
{
if (bc->prev && bc->prev->ident == ident)
return bc->breakBlock;
}
else if (bc->breakBlock)
return bc->breakBlock;
}
return NULL;
}
block *IRState::getContBlock(Identifier *ident)
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (ident)
{
if (bc->prev && bc->prev->ident == ident)
return bc->contBlock;
}
else if (bc->contBlock)
return bc->contBlock;
}
return NULL;
}
block *IRState::getSwitchBlock()
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (bc->switchBlock)
return bc->switchBlock;
}
return NULL;
}
block *IRState::getDefaultBlock()
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (bc->defaultBlock)
return bc->defaultBlock;
}
return NULL;
}
FuncDeclaration *IRState::getFunc()
{
IRState *bc;
for (bc = this; bc->prev; bc = bc->prev)
{
}
return (FuncDeclaration *)(bc->symbol);
}

57
dmd2/irstate.h Normal file
View File

@@ -0,0 +1,57 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#ifndef DMD_CONTEXT_H
#define DMD_CONTEXT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
struct Module;
struct Statement;
struct block;
struct Dsymbol;
struct Identifier;
struct Symbol;
struct FuncDeclaration;
struct Blockx;
struct Array;
struct elem;
struct IRState
{
IRState *prev;
Statement *statement;
Module *m; // module
Dsymbol *symbol;
Identifier *ident;
Symbol *shidden; // hidden parameter to function
Symbol *sthis; // 'this' parameter to function (member and nested)
Symbol *sclosure; // pointer to closure instance
Blockx *blx;
Array *deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later
elem *ehidden; // transmit hidden pointer to CallExp::toElem()
Symbol *startaddress;
block *breakBlock;
block *contBlock;
block *switchBlock;
block *defaultBlock;
IRState(IRState *irs, Statement *s);
IRState(IRState *irs, Dsymbol *s);
IRState(Module *m, Dsymbol *s);
block *getBreakBlock(Identifier *ident);
block *getContBlock(Identifier *ident);
block *getSwitchBlock();
block *getDefaultBlock();
FuncDeclaration *getFunc();
};
#endif /* DMD_CONTEXT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,307 +1,309 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_LEXER_H
#define DMD_LEXER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "mars.h"
struct StringTable;
struct Identifier;
struct Module;
/* Tokens:
( )
[ ]
{ }
< > <= >= == != === !==
<< >> <<= >>= >>> >>>=
+ - += -=
* / % *= /= %=
& | ^ &= |= ^=
= ! ~
++ --
. -> : ,
? && ||
*/
enum TOK
{
TOKreserved,
// Other
TOKlparen, TOKrparen,
TOKlbracket, TOKrbracket,
TOKlcurly, TOKrcurly,
TOKcolon, TOKneg,
TOKsemicolon, TOKdotdotdot,
TOKeof, TOKcast,
TOKnull, TOKassert,
TOKtrue, TOKfalse,
TOKarray, TOKcall,
TOKaddress, TOKtypedot,
TOKtype, TOKthrow,
TOKnew, TOKdelete,
TOKstar, TOKsymoff,
TOKvar, TOKdotvar,
TOKdotti, TOKdotexp,
TOKdottype, TOKslice,
TOKarraylength, TOKversion,
TOKmodule, TOKdollar,
TOKtemplate, TOKdottd,
TOKdeclaration, TOKtypeof,
TOKpragma, TOKdsymbol,
TOKtypeid, TOKuadd,
TOKremove,
TOKnewanonclass, TOKcomment,
TOKarrayliteral, TOKassocarrayliteral,
TOKstructliteral,
// Operators
TOKlt, TOKgt,
TOKle, TOKge,
TOKequal, TOKnotequal,
TOKidentity, TOKnotidentity,
TOKindex, TOKis,
TOKtobool,
// 60
// NCEG floating point compares
// !<>= <> <>= !> !>= !< !<= !<>
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
TOKshl, TOKshr,
TOKshlass, TOKshrass,
TOKushr, TOKushrass,
TOKcat, TOKcatass, // ~ ~=
TOKadd, TOKmin, TOKaddass, TOKminass,
TOKmul, TOKdiv, TOKmod,
TOKmulass, TOKdivass, TOKmodass,
TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde,
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
// 104
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
TOKfloat32v, TOKfloat64v, TOKfloat80v,
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
// Char constants
TOKcharv, TOKwcharv, TOKdcharv,
// Leaf operators
TOKidentifier, TOKstring,
TOKthis, TOKsuper,
TOKhalt, TOKtuple,
// Basic types
TOKvoid,
TOKint8, TOKuns8,
TOKint16, TOKuns16,
TOKint32, TOKuns32,
TOKint64, TOKuns64,
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// Aggregates
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
TOKmixin,
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
TOKasm, TOKforeach, TOKforeach_reverse,
TOKscope,
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
// Contracts
TOKbody, TOKinvariant,
// Testing
TOKunittest,
// Added after 1.0
TOKref,
TOKmacro,
#if DMDV2
TOKtraits,
TOKoverloadset,
TOKpure,
TOKnothrow,
TOKtls,
TOKline,
TOKfile,
TOKshared,
#endif
// LDC specific
#if IN_LLVM
TOKgep,
#endif
TOKMAX
};
#define CASE_BASIC_TYPES \
case TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
case TOKint8: case TOKuns8: \
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
case TOKint64: case TOKuns64: \
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
case TOKvoid
#define CASE_BASIC_TYPES_X(t) \
case TOKvoid: t = Type::tvoid; goto LabelX; \
case TOKint8: t = Type::tint8; goto LabelX; \
case TOKuns8: t = Type::tuns8; goto LabelX; \
case TOKint16: t = Type::tint16; goto LabelX; \
case TOKuns16: t = Type::tuns16; goto LabelX; \
case TOKint32: t = Type::tint32; goto LabelX; \
case TOKuns32: t = Type::tuns32; goto LabelX; \
case TOKint64: t = Type::tint64; goto LabelX; \
case TOKuns64: t = Type::tuns64; goto LabelX; \
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
case TOKbit: t = Type::tbit; goto LabelX; \
case TOKbool: t = Type::tbool; goto LabelX; \
case TOKchar: t = Type::tchar; goto LabelX; \
case TOKwchar: t = Type::twchar; goto LabelX; \
case TOKdchar: t = Type::tdchar; goto LabelX; \
LabelX
struct Token
{
Token *next;
unsigned char *ptr; // pointer to first character of this token within buffer
enum TOK value;
unsigned char *blockComment; // doc comment string prior to this token
unsigned char *lineComment; // doc comment for previous token
union
{
// Integers
d_int32 int32value;
d_uns32 uns32value;
d_int64 int64value;
d_uns64 uns64value;
// Floats
#ifdef IN_GCC
// real_t float80value; // can't use this in a union!
#else
d_float80 float80value;
#endif
struct
{ unsigned char *ustring; // UTF8 string
unsigned len;
unsigned char postfix; // 'c', 'w', 'd'
};
Identifier *ident;
};
#ifdef IN_GCC
real_t float80value; // can't use this in a union!
#endif
static const char *tochars[TOKMAX];
static void *operator new(size_t sz);
int isKeyword();
void print();
const char *toChars();
static const char *toChars(enum TOK);
};
struct Lexer
{
static StringTable stringtable;
static OutBuffer stringbuffer;
static Token *freelist;
Loc loc; // for error messages
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
Token token;
Module *mod;
int doDocComment; // collect doc comment information
int anyToken; // !=0 means seen at least one token
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
int doDocComment, int commentToken);
static void initKeywords();
static Identifier *idPool(const char *s);
static Identifier *uniqueId(const char *s);
static Identifier *uniqueId(const char *s, int num);
TOK nextToken();
TOK peekNext();
void scan(Token *t);
Token *peek(Token *t);
Token *peekPastParen(Token *t);
unsigned escapeSequence();
TOK wysiwygStringConstant(Token *t, int tc);
TOK hexStringConstant(Token *t);
#if DMDV2
TOK delimitedStringConstant(Token *t);
TOK tokenStringConstant(Token *t);
#endif
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...);
void error(Loc loc, const char *format, ...);
void pragma();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
};
#endif /* DMD_LEXER_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_LEXER_H
#define DMD_LEXER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "mars.h"
struct StringTable;
struct Identifier;
struct Module;
/* Tokens:
( )
[ ]
{ }
< > <= >= == != === !==
<< >> <<= >>= >>> >>>=
+ - += -=
* / % *= /= %=
& | ^ &= |= ^=
= ! ~
++ --
. -> : ,
? && ||
*/
enum TOK
{
TOKreserved,
// Other
TOKlparen, TOKrparen,
TOKlbracket, TOKrbracket,
TOKlcurly, TOKrcurly,
TOKcolon, TOKneg,
TOKsemicolon, TOKdotdotdot,
TOKeof, TOKcast,
TOKnull, TOKassert,
TOKtrue, TOKfalse,
TOKarray, TOKcall,
TOKaddress,
TOKtype, TOKthrow,
TOKnew, TOKdelete,
TOKstar, TOKsymoff,
TOKvar, TOKdotvar,
TOKdotti, TOKdotexp,
TOKdottype, TOKslice,
TOKarraylength, TOKversion,
TOKmodule, TOKdollar,
TOKtemplate, TOKdottd,
TOKdeclaration, TOKtypeof,
TOKpragma, TOKdsymbol,
TOKtypeid, TOKuadd,
TOKremove,
TOKnewanonclass, TOKcomment,
TOKarrayliteral, TOKassocarrayliteral,
TOKstructliteral,
// Operators
TOKlt, TOKgt,
TOKle, TOKge,
TOKequal, TOKnotequal,
TOKidentity, TOKnotidentity,
TOKindex, TOKis,
TOKtobool,
// 60
// NCEG floating point compares
// !<>= <> <>= !> !>= !< !<= !<>
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
TOKshl, TOKshr,
TOKshlass, TOKshrass,
TOKushr, TOKushrass,
TOKcat, TOKcatass, // ~ ~=
TOKadd, TOKmin, TOKaddass, TOKminass,
TOKmul, TOKdiv, TOKmod,
TOKmulass, TOKdivass, TOKmodass,
TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde,
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
// 104
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
TOKfloat32v, TOKfloat64v, TOKfloat80v,
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
// Char constants
TOKcharv, TOKwcharv, TOKdcharv,
// Leaf operators
TOKidentifier, TOKstring,
TOKthis, TOKsuper,
TOKhalt, TOKtuple,
// Basic types
TOKvoid,
TOKint8, TOKuns8,
TOKint16, TOKuns16,
TOKint32, TOKuns32,
TOKint64, TOKuns64,
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// Aggregates
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
TOKmixin,
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
TOKasm, TOKforeach, TOKforeach_reverse,
TOKscope,
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
// Contracts
TOKbody, TOKinvariant,
// Testing
TOKunittest,
// Added after 1.0
TOKref,
TOKmacro,
#if DMDV2
TOKtraits,
TOKoverloadset,
TOKpure,
TOKnothrow,
TOKtls,
TOKgshared,
TOKline,
TOKfile,
TOKshared,
#endif
// LDC specific
#if IN_LLVM
TOKgep,
#endif
TOKMAX
};
#define CASE_BASIC_TYPES \
case TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
case TOKint8: case TOKuns8: \
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
case TOKint64: case TOKuns64: \
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
case TOKvoid
#define CASE_BASIC_TYPES_X(t) \
case TOKvoid: t = Type::tvoid; goto LabelX; \
case TOKint8: t = Type::tint8; goto LabelX; \
case TOKuns8: t = Type::tuns8; goto LabelX; \
case TOKint16: t = Type::tint16; goto LabelX; \
case TOKuns16: t = Type::tuns16; goto LabelX; \
case TOKint32: t = Type::tint32; goto LabelX; \
case TOKuns32: t = Type::tuns32; goto LabelX; \
case TOKint64: t = Type::tint64; goto LabelX; \
case TOKuns64: t = Type::tuns64; goto LabelX; \
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
case TOKbit: t = Type::tbit; goto LabelX; \
case TOKbool: t = Type::tbool; goto LabelX; \
case TOKchar: t = Type::tchar; goto LabelX; \
case TOKwchar: t = Type::twchar; goto LabelX; \
case TOKdchar: t = Type::tdchar; goto LabelX; \
LabelX
struct Token
{
Token *next;
unsigned char *ptr; // pointer to first character of this token within buffer
enum TOK value;
unsigned char *blockComment; // doc comment string prior to this token
unsigned char *lineComment; // doc comment for previous token
union
{
// Integers
d_int32 int32value;
d_uns32 uns32value;
d_int64 int64value;
d_uns64 uns64value;
// Floats
#ifdef IN_GCC
// real_t float80value; // can't use this in a union!
#else
d_float80 float80value;
#endif
struct
{ unsigned char *ustring; // UTF8 string
unsigned len;
unsigned char postfix; // 'c', 'w', 'd'
};
Identifier *ident;
};
#ifdef IN_GCC
real_t float80value; // can't use this in a union!
#endif
static const char *tochars[TOKMAX];
static void *operator new(size_t sz);
int isKeyword();
void print();
const char *toChars();
static const char *toChars(enum TOK);
};
struct Lexer
{
static StringTable stringtable;
static OutBuffer stringbuffer;
static Token *freelist;
Loc loc; // for error messages
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
Token token;
Module *mod;
int doDocComment; // collect doc comment information
int anyToken; // !=0 means seen at least one token
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
int doDocComment, int commentToken);
static void initKeywords();
static Identifier *idPool(const char *s);
static Identifier *uniqueId(const char *s);
static Identifier *uniqueId(const char *s, int num);
TOK nextToken();
TOK peekNext();
TOK peekNext2();
void scan(Token *t);
Token *peek(Token *t);
Token *peekPastParen(Token *t);
unsigned escapeSequence();
TOK wysiwygStringConstant(Token *t, int tc);
TOK hexStringConstant(Token *t);
#if DMDV2
TOK delimitedStringConstant(Token *t);
TOK tokenStringConstant(Token *t);
#endif
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void pragma();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
};
#endif /* DMD_LEXER_H */

49
dmd2/lib.h Normal file
View File

@@ -0,0 +1,49 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_LIB_H
#define DMD_LIB_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
struct ObjModule;
struct ObjSymbol
{
char *name;
ObjModule *om;
};
struct Library
{
File *libfile;
Array objmodules; // ObjModule[]
Array objsymbols; // ObjSymbol[]
StringTable tab;
Library();
void setFilename(char *dir, char *filename);
void addObject(const char *module_name, void *buf, size_t buflen);
void addLibrary(void *buf, size_t buflen);
void write();
private:
void addSymbol(ObjModule *om, char *name, int pickAny = 0);
void scanObjModule(ObjModule *om);
unsigned short numDictPages(unsigned padding);
int FillDict(unsigned char *bucketsP, unsigned short uNumPages);
void WriteLibToBuffer(OutBuffer *libbuf);
};
#endif /* DMD_LIB_H */

View File

@@ -16,19 +16,9 @@
#include <ctype.h>
#include <assert.h>
#if IN_GCC || IN_LLVM
#include "mem.h"
#else
#if _WIN32
#include "..\root\mem.h"
#elif POSIX
#include "../root/mem.h"
#else
#error "fix this"
#endif
#endif
#include "rmem.h"
#include "root.h"
#include "macro.h"
#define isidstart(c) (isalpha(c) || (c) == '_')

View File

@@ -1,291 +1,298 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "root.h"
#include "init.h"
#include "declaration.h"
#include "aggregate.h"
#include "mtype.h"
#include "attrib.h"
#include "template.h"
#include "id.h"
#include "module.h"
#if TARGET_LINUX
char *cpp_mangle(Dsymbol *s);
#endif
char *mangle(Declaration *sthis)
{
OutBuffer buf;
char *id;
Dsymbol *s;
//printf("::mangle(%s)\n", sthis->toChars());
s = sthis;
do
{
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
if (s->ident)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (s != sthis && fd)
{
id = mangle(fd);
buf.prependstring(id);
goto L1;
}
else
{
id = s->ident->toChars();
int len = strlen(id);
char tmp[sizeof(len) * 3 + 1];
buf.prependstring(id);
sprintf(tmp, "%d", len);
buf.prependstring(tmp);
}
}
else
buf.prependstring("0");
s = s->parent;
} while (s);
// buf.prependstring("_D");
L1:
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
//printf("sthis->type = %s\n", sthis->type->toChars());
FuncDeclaration *fd = sthis->isFuncDeclaration();
if (fd && (fd->needThis() || fd->isNested()))
buf.writeByte(Type::needThisPrefix());
if (sthis->type->deco)
buf.writestring(sthis->type->deco);
else
{ assert(fd->inferRetType);
}
id = buf.toChars();
buf.data = NULL;
return id;
}
char *Declaration::mangle()
#if __DMC__
__out(result)
{
int len = strlen(result);
assert(len > 0);
//printf("mangle: '%s' => '%s'\n", toChars(), result);
for (int i = 0; i < len; i++)
{
assert(result[i] == '_' ||
result[i] == '@' ||
isalnum(result[i]) || result[i] & 0x80);
}
}
__body
#endif
{
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
{
// If it's not a D declaration, no mangling
switch (linkage)
{
case LINKd:
break;
// LDC
case LINKintrinsic:
case LINKc:
case LINKwindows:
case LINKpascal:
return ident->toChars();
case LINKcpp:
#if TARGET_LINUX
return cpp_mangle(this);
#else
// Windows C++ mangling is done by C++ back end
return ident->toChars();
#endif
case LINKdefault:
error("forward declaration");
return ident->toChars();
default:
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
char *p = ::mangle(this);
OutBuffer buf;
buf.writestring("_D");
buf.writestring(p);
p = buf.toChars();
buf.data = NULL;
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
return p;
}
char *FuncDeclaration::mangle()
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
if (isMain())
return (char *)"_Dmain";
if (isWinMain() || isDllMain())
return ident->toChars();
assert(this);
return Declaration::mangle();
}
char *StructDeclaration::mangle()
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *TypedefDeclaration::mangle()
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *ClassDeclaration::mangle()
{
Dsymbol *parentsave = parent;
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
/* These are reserved to the compiler, so keep simple
* names for them.
*/
if (ident == Id::Exception)
{ if (parent->ident == Id::object)
parent = NULL;
}
else if (ident == Id::TypeInfo ||
// ident == Id::Exception ||
ident == Id::TypeInfo_Struct ||
ident == Id::TypeInfo_Class ||
ident == Id::TypeInfo_Typedef ||
ident == Id::TypeInfo_Tuple ||
this == object ||
this == classinfo ||
this == Module::moduleinfo ||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
)
parent = NULL;
char *id = Dsymbol::mangle();
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateInstance::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (tempdecl->parent)
{
char *p = tempdecl->parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
return id;
}
char *TemplateMixin::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateMixin::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
return id;
}
char *Dsymbol::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("Dsymbol::mangle() '%s'", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
return id;
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "root.h"
#include "init.h"
#include "declaration.h"
#include "aggregate.h"
#include "mtype.h"
#include "attrib.h"
#include "template.h"
#include "id.h"
#include "module.h"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
char *cpp_mangle(Dsymbol *s);
#endif
char *mangle(Declaration *sthis)
{
OutBuffer buf;
char *id;
Dsymbol *s;
//printf("::mangle(%s)\n", sthis->toChars());
s = sthis;
do
{
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
if (s->ident)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (s != sthis && fd)
{
id = mangle(fd);
buf.prependstring(id);
goto L1;
}
else
{
id = s->ident->toChars();
int len = strlen(id);
char tmp[sizeof(len) * 3 + 1];
buf.prependstring(id);
sprintf(tmp, "%d", len);
buf.prependstring(tmp);
}
}
else
buf.prependstring("0");
s = s->parent;
} while (s);
// buf.prependstring("_D");
L1:
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
//printf("sthis->type = %s\n", sthis->type->toChars());
FuncDeclaration *fd = sthis->isFuncDeclaration();
if (fd && (fd->needThis() || fd->isNested()))
buf.writeByte(Type::needThisPrefix());
if (sthis->type->deco)
buf.writestring(sthis->type->deco);
else
{
#ifdef DEBUG
if (!fd->inferRetType)
printf("%s\n", fd->toChars());
#endif
assert(fd->inferRetType);
}
id = buf.toChars();
buf.data = NULL;
return id;
}
char *Declaration::mangle()
#if __DMC__
__out(result)
{
int len = strlen(result);
assert(len > 0);
//printf("mangle: '%s' => '%s'\n", toChars(), result);
for (int i = 0; i < len; i++)
{
assert(result[i] == '_' ||
result[i] == '@' ||
isalnum(result[i]) || result[i] & 0x80);
}
}
__body
#endif
{
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
{
// If it's not a D declaration, no mangling
switch (linkage)
{
case LINKd:
break;
// LDC
case LINKintrinsic:
case LINKc:
case LINKwindows:
case LINKpascal:
return ident->toChars();
case LINKcpp:
#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
return cpp_mangle(this);
#else
// Windows C++ mangling is done by C++ back end
return ident->toChars();
#endif
case LINKdefault:
error("forward declaration");
return ident->toChars();
default:
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
char *p = ::mangle(this);
OutBuffer buf;
buf.writestring("_D");
buf.writestring(p);
p = buf.toChars();
buf.data = NULL;
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
return p;
}
char *FuncDeclaration::mangle()
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
if (isMain())
return (char *)"_Dmain";
if (isWinMain() || isDllMain() || ident == Id::tls_get_addr)
return ident->toChars();
assert(this);
return Declaration::mangle();
}
char *StructDeclaration::mangle()
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *TypedefDeclaration::mangle()
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *ClassDeclaration::mangle()
{
Dsymbol *parentsave = parent;
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
/* These are reserved to the compiler, so keep simple
* names for them.
*/
if (ident == Id::Exception)
{ if (parent->ident == Id::object)
parent = NULL;
}
else if (ident == Id::TypeInfo ||
// ident == Id::Exception ||
ident == Id::TypeInfo_Struct ||
ident == Id::TypeInfo_Class ||
ident == Id::TypeInfo_Typedef ||
ident == Id::TypeInfo_Tuple ||
this == object ||
this == classinfo ||
this == Module::moduleinfo ||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
)
parent = NULL;
char *id = Dsymbol::mangle();
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateInstance::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (!tempdecl)
error("is not defined");
else if (tempdecl->parent)
{
char *p = tempdecl->parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
return id;
}
#if IN_LLVM
char *TemplateMixin::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateMixin::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
return id;
}
#endif
char *Dsymbol::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("Dsymbol::mangle() '%s'", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
return id;
}

View File

@@ -1,278 +1,352 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>
#include <string>
#include <cstdarg>
#if __DMC__
#include <dos.h>
#endif
#if POSIX
#include <errno.h>
#elif _WIN32
#include <windows.h>
#endif
#include "mem.h"
#include "root.h"
#include "mars.h"
#include "module.h"
#include "mtype.h"
#include "id.h"
#include "cond.h"
#include "expression.h"
#include "lexer.h"
#include "revisions.h"
Global global;
Global::Global()
{
mars_ext = "d";
sym_ext = "d";
hdr_ext = "di";
doc_ext = "html";
ddoc_ext = "ddoc";
// LDC
ll_ext = "ll";
bc_ext = "bc";
s_ext = "s";
obj_ext = "o";
#if _WIN32
obj_ext_alt = "obj";
#endif
copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v2.021";
ldc_version = LDC_REV;
llvm_version = LLVM_REV_STR;
global.structalign = 8;
// This should only be used as a global, so the other fields are
// automatically initialized to zero when the program is loaded.
// In particular, DO NOT zero-initialize .params here (like DMD
// does) because command-line options initialize some of those
// fields to non-zero defaults, and do so from constructors that
// may run before this one.
}
char *Loc::toChars() const
{
OutBuffer buf;
if (filename)
{
buf.printf("%s", filename);
}
if (linnum)
buf.printf("(%d)", linnum);
buf.writeByte(0);
return (char *)buf.extractData();
}
Loc::Loc(Module *mod, unsigned linnum)
{
this->linnum = linnum;
this->filename = mod ? mod->srcfile->toChars() : NULL;
}
/**************************************
* Print error message and exit.
*/
void error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
va_end( ap );
}
void verror(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Error: ");
vfprintf(stdmsg, format, ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
global.errors++;
}
/***************************************
* Call this after printing out fatal error messages to clean up and exit
* the compiler.
*/
void fatal()
{
#if 0
halt();
#endif
exit(EXIT_FAILURE);
}
/**************************************
* Try to stop forgetting to remove the breakpoints from
* release builds.
*/
void halt()
{
#ifdef DEBUG
*(char*)0=0;
#endif
}
/***********************************
* Parse and append contents of environment variable envvar
* to argc and argv[].
* The string is separated into arguments, processing \ and ".
*/
void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
{
char *env;
char *p;
Array *argv;
int argc;
int wildcard; // do wildcard expansion
int instring;
int slash;
char c;
int j;
env = getenv(envvar);
if (!env)
return;
env = mem.strdup(env); // create our own writable copy
argc = *pargc;
argv = new Array();
argv->setDim(argc);
int argc_left = 0;
for (int i = 0; i < argc; i++) {
if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
// HACK: set flag to indicate we saw '-run' here
global.params.run = true;
// Don't eat -run yet so the program arguments don't get changed
argc_left = argc - i;
argc = i;
*pargv = &(*pargv)[i];
argv->setDim(i);
break;
} else {
argv->data[i] = (void *)(*pargv)[i];
}
}
// HACK to stop required values from command line being drawn from DFLAGS
argv->push((char*)"");
argc++;
j = 1; // leave argv[0] alone
while (1)
{
wildcard = 1;
switch (*env)
{
case ' ':
case '\t':
env++;
break;
case 0:
goto Ldone;
case '"':
wildcard = 0;
default:
argv->push(env); // append
//argv->insert(j, env); // insert at position j
j++;
argc++;
p = env;
slash = 0;
instring = 0;
c = 0;
while (1)
{
c = *env++;
switch (c)
{
case '"':
p -= (slash >> 1);
if (slash & 1)
{ p--;
goto Laddc;
}
instring ^= 1;
slash = 0;
continue;
case ' ':
case '\t':
if (instring)
goto Laddc;
*p = 0;
//if (wildcard)
//wildcardexpand(); // not implemented
break;
case '\\':
slash++;
*p++ = c;
continue;
case 0:
*p = 0;
//if (wildcard)
//wildcardexpand(); // not implemented
goto Ldone;
default:
Laddc:
slash = 0;
*p++ = c;
continue;
}
break;
}
}
}
Ldone:
assert(argc == argv->dim);
argv->reserve(argc_left);
for (int i = 0; i < argc_left; i++)
argv->data[argc++] = (void *)(*pargv)[i];
*pargc = argc;
*pargv = (char **)argv->data;
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>
#include <string>
#include <cstdarg>
#if POSIX
#include <errno.h>
#elif _WIN32
#include <windows.h>
#endif
#include "rmem.h"
#include "root.h"
#if !IN_LLVM
#include "async.h"
#endif
#include "mars.h"
#include "module.h"
#include "mtype.h"
#include "id.h"
#include "cond.h"
#include "expression.h"
#include "lexer.h"
#if IN_LLVM
#include "gen/revisions.h"
#else
#include "lib.h"
#if WINDOWS_SEH
#include <windows.h>
long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
#endif
int response_expand(int *pargc, char ***pargv);
void browse(const char *url);
void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
#endif
Global global;
Global::Global()
{
mars_ext = "d";
sym_ext = "d";
hdr_ext = "di";
doc_ext = "html";
ddoc_ext = "ddoc";
#if IN_LLVM
ll_ext = "ll";
bc_ext = "bc";
s_ext = "s";
obj_ext = "o";
#if _WIN32
obj_ext_alt = "obj";
#endif
#else
#if TARGET_WINDOS
obj_ext = "obj";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
obj_ext = "o";
#elif TARGET_NET
#else
#error "fix this"
#endif
#if TARGET_WINDOS
lib_ext = "lib";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
lib_ext = "a";
#elif TARGET_NET
#else
#error "fix this"
#endif
#endif
copyright = "Copyright (c) 1999-2009 by Digital Mars";
written = "written by Walter Bright"
#if TARGET_NET
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.030";
#if IN_LLVM
ldc_version = LDC_REV;
llvm_version = LLVM_REV_STR;
#endif
global.structalign = 8;
// This should only be used as a global, so the other fields are
// automatically initialized to zero when the program is loaded.
// In particular, DO NOT zero-initialize .params here (like DMD
// does) because command-line options initialize some of those
// fields to non-zero defaults, and do so from constructors that
// may run before this one.
}
char *Loc::toChars()
{
OutBuffer buf;
if (filename)
{
buf.printf("%s", filename);
}
if (linnum)
buf.printf("(%d)", linnum);
buf.writeByte(0);
return (char *)buf.extractData();
}
Loc::Loc(Module *mod, unsigned linnum)
{
this->linnum = linnum;
this->filename = mod ? mod->srcfile->toChars() : NULL;
}
bool Loc::equals(const Loc& loc)
{
return linnum == loc.linnum && FileName::equals(filename, loc.filename);
}
/**************************************
* Print error message and exit.
*/
void error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
va_end( ap );
}
void warning(Loc loc, const char *format, ...)
{
if (global.params.warnings && !global.gag)
{
va_list ap;
va_start(ap, format);
vwarning(loc, format, ap);
va_end( ap );
}
}
void verror(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Error: ");
vfprintf(stdmsg, format, ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
global.errors++;
}
void vwarning(Loc loc, const char *format, va_list ap)
{
if (global.params.warnings && !global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Warning: ");
vfprintf(stdmsg, format, ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
}
/***************************************
* Call this after printing out fatal error messages to clean up and exit
* the compiler.
*/
void fatal()
{
#if 0
halt();
#endif
exit(EXIT_FAILURE);
}
/**************************************
* Try to stop forgetting to remove the breakpoints from
* release builds.
*/
void halt()
{
#ifdef DEBUG
*(char*)0=0;
#endif
}
/***********************************
* Parse and append contents of environment variable envvar
* to argc and argv[].
* The string is separated into arguments, processing \ and ".
*/
void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
{
char *env;
char *p;
Array *argv;
int argc;
int wildcard; // do wildcard expansion
int instring;
int slash;
char c;
int j;
env = getenv(envvar);
if (!env)
return;
env = mem.strdup(env); // create our own writable copy
argc = *pargc;
argv = new Array();
argv->setDim(argc);
int argc_left = 0;
for (int i = 0; i < argc; i++) {
if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
// HACK: set flag to indicate we saw '-run' here
global.params.run = true;
// Don't eat -run yet so the program arguments don't get changed
argc_left = argc - i;
argc = i;
*pargv = &(*pargv)[i];
argv->setDim(i);
break;
} else {
argv->data[i] = (void *)(*pargv)[i];
}
}
// HACK to stop required values from command line being drawn from DFLAGS
argv->push((char*)"");
argc++;
j = 1; // leave argv[0] alone
while (1)
{
wildcard = 1;
switch (*env)
{
case ' ':
case '\t':
env++;
break;
case 0:
goto Ldone;
case '"':
wildcard = 0;
default:
argv->push(env); // append
//argv->insert(j, env); // insert at position j
j++;
argc++;
p = env;
slash = 0;
instring = 0;
c = 0;
while (1)
{
c = *env++;
switch (c)
{
case '"':
p -= (slash >> 1);
if (slash & 1)
{ p--;
goto Laddc;
}
instring ^= 1;
slash = 0;
continue;
case ' ':
case '\t':
if (instring)
goto Laddc;
*p = 0;
//if (wildcard)
//wildcardexpand(); // not implemented
break;
case '\\':
slash++;
*p++ = c;
continue;
case 0:
*p = 0;
//if (wildcard)
//wildcardexpand(); // not implemented
goto Ldone;
default:
Laddc:
slash = 0;
*p++ = c;
continue;
}
break;
}
}
}
Ldone:
assert(argc == argv->dim);
argv->reserve(argc_left);
for (int i = 0; i < argc_left; i++)
argv->data[argc++] = (void *)(*pargv)[i];
*pargc = argc;
*pargv = (char **)argv->data;
}

View File

@@ -1,353 +1,458 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MARS_H
#define DMD_MARS_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <stdarg.h>
#ifdef __DMC__
#ifdef DEBUG
#undef assert
#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
#endif
#endif
#ifdef IN_GCC
/* Changes for the GDC compiler by David Friedman */
#endif
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
#define STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer
struct Array;
// LDC
enum ARCH
{
ARCHinvalid,
ARCHx86,
ARCHx86_64,
ARCHppc,
ARCHppc_64,
ARCHarm,
ARCHthumb
};
enum OUTPUTFLAG
{
OUTPUTFLAGno,
OUTPUTFLAGdefault, // for the .o default
OUTPUTFLAGset // for -output
};
enum OS
{
OSinvalid,
OSLinux,
OSWindows,
OSMacOSX,
OSFreeBSD,
OSSolaris,
};
// Put command line switches in here
struct Param
{
bool obj; // write object file
bool link; // perform link
bool verbose; // verbose compile
char symdebug; // insert debug symbolic information
#if !IN_LLVM
// LDC uses a different mechanism
bool optimize; // run optimizer
char optimizeLevel; // optimization level
#endif
ARCH cpu; // target CPU
OS os; // target OS
bool is64bit; // generate 64 bit code
bool isLE; // generate little endian code
bool useDeprecated; // allow use of deprecated features
bool useAssert; // generate runtime code for assert()'s
bool useInvariants; // generate class invariant checks
bool useIn; // generate precondition checks
bool useOut; // generate postcondition checks
bool useArrayBounds; // generate array bounds checks
bool useSwitchError; // check for switches without a default
bool useUnitTests; // generate unittest code
bool useInline; // inline expand functions
bool warnings; // enable warnings
bool safe; // enforce safe memory model
char Dversion; // D version number
char *argv0; // program name
Array *imppath; // array of char*'s of where to look for import modules
Array *fileImppath; // array of char*'s of where to look for file import modules
char *objdir; // .obj file output directory
char *objname; // .obj file output name
bool doDocComments; // process embedded documentation comments
char *docdir; // write documentation file to docdir directory
char *docname; // write documentation file to docname
Array *ddocfiles; // macro include files for Ddoc
bool doHdrGeneration; // process embedded documentation comments
char *hdrdir; // write 'header' file to docdir directory
char *hdrname; // write 'header' file to docname
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
unsigned versionlevel; // version level
Array *versionids; // version identifiers
bool dump_source;
Array *defaultlibnames; // default libraries for non-debug builds
Array *debuglibnames; // default libraries for debug builds
char *xmlname; // filename for XML output
// Hidden debug switches
bool debuga;
bool debugb;
bool debugc;
bool debugf;
bool debugr;
bool debugw;
bool debugx;
bool debugy;
bool run; // run resulting executable
// Linker stuff
Array *objfiles;
Array *linkswitches;
Array *libfiles;
char *deffile;
char *resfile;
char *exefile;
// LDC stuff
OUTPUTFLAG output_ll;
OUTPUTFLAG output_bc;
OUTPUTFLAG output_s;
OUTPUTFLAG output_o;
bool llvmAnnotate;
bool useInlineAsm;
// target stuff
const char* llvmArch;
const char *targetTriple;
const char *dataLayout;
};
struct Global
{
char *mars_ext;
char *sym_ext;
char *obj_ext;
#if _WIN32
char *obj_ext_alt;
#endif
char *ll_ext;
char *bc_ext;
char *s_ext;
char *doc_ext; // for Ddoc generated files
char *ddoc_ext; // for Ddoc macro include files
char *hdr_ext; // for D 'header' import files
char *copyright;
char *written;
Array *path; // Array of char*'s which form the import lookup path
Array *filePath; // Array of char*'s which form the file import lookup path
int structalign;
char *version;
char *ldc_version;
char *llvm_version;
Param params;
unsigned errors; // number of errors reported so far
unsigned gag; // !=0 means gag reporting of errors
Global();
};
extern Global global;
/* Set if Windows Structured Exception Handling C extensions are supported.
* Apparently, VC has dropped support for these?
*/
#define WINDOWS_SEH (_WIN32 && __DMC__)
#if __GNUC__
//#define memicmp strncasecmp
//#define stricmp strcasecmp
#endif
#ifdef __DMC__
typedef _Complex long double complex_t;
#else
#ifndef IN_GCC
#include "complex_t.h"
#endif
#ifdef __APPLE__
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
#define integer_t dmd_integer_t
#endif
#endif
// Be careful not to care about sign when using integer_t
typedef uint64_t integer_t;
// Signed and unsigned variants
typedef int64_t sinteger_t;
typedef uint64_t uinteger_t;
typedef int8_t d_int8;
typedef uint8_t d_uns8;
typedef int16_t d_int16;
typedef uint16_t d_uns16;
typedef int32_t d_int32;
typedef uint32_t d_uns32;
typedef int64_t d_int64;
typedef uint64_t d_uns64;
typedef float d_float32;
typedef double d_float64;
typedef long double d_float80;
typedef d_uns8 d_char;
typedef d_uns16 d_wchar;
typedef d_uns32 d_dchar;
#ifdef IN_GCC
#include "d-gcc-real.h"
#else
typedef long double real_t;
#endif
// Modify OutBuffer::writewchar to write the correct size of wchar
#if _WIN32
#define writewchar writeword
#else
// This needs a configuration test...
#define writewchar write4
#endif
#ifdef IN_GCC
#include "d-gcc-complex_t.h"
#endif
// taken from GDC
// for handling printf incompatibilities
#if __MSVCRT__
#define PRIuSIZE "Iu"
#define PRIxSIZE "Ix"
#elif __MINGW32__
#define PRIuSIZE "u"
#define PRIxSIZE "x"
#else
#define PRIuSIZE "zu"
#define PRIxSIZE "zx"
#endif
struct Module;
//typedef unsigned Loc; // file location
struct Loc
{
char *filename;
unsigned linnum;
Loc()
{
linnum = 0;
filename = NULL;
}
Loc(int x)
{
linnum = x;
filename = NULL;
}
Loc(Module *mod, unsigned linnum);
char *toChars() const;
};
#ifndef GCC_SAFE_DMD
#define TRUE 1
#define FALSE 0
#endif
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
// in interface vtbl[]'s
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
// in the inheritance graph multiple
// times, only one is used
enum LINK
{
LINKdefault,
LINKd,
LINKc,
LINKcpp,
LINKwindows,
LINKpascal,
// LDC
LINKintrinsic,
};
enum DYNCAST
{
DYNCAST_OBJECT,
DYNCAST_EXPRESSION,
DYNCAST_DSYMBOL,
DYNCAST_TYPE,
DYNCAST_IDENTIFIER,
DYNCAST_TUPLE,
};
enum MATCH
{
MATCHnomatch, // no match
MATCHconvert, // match with conversions
#if DMDV2
MATCHconst, // match with conversion to const
#endif
MATCHexact // exact match
};
void error(Loc loc, const char *format, ...);
void verror(Loc loc, const char *format, va_list);
void fatal();
void err_nomem();
void inifile(char *argv0, const char *inifile);
void halt();
/*** Where to send error messages ***/
#if IN_GCC || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stdout
#endif
#endif /* DMD_MARS_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MARS_H
#define DMD_MARS_H
#ifdef __DMC__
#pragma once
#endif
/*
It is very important to use version control macros correctly - the
idea is that host and target are independent. If these are done
correctly, cross compilers can be built.
The host compiler and host operating system are also different,
and are predefined by the host compiler. The ones used in
dmd are:
Macros defined by the compiler, not the code:
Compiler:
__DMC__ Digital Mars compiler
_MSC_VER Microsoft compiler
__GNUC__ Gnu compiler
Host operating system:
_WIN32 Microsoft NT, Windows 95, Windows 98, Win32s,
Windows 2000, Win XP, Vista
_WIN64 Windows for AMD64
linux Linux
__APPLE__ Mac OSX
__FreeBSD__ FreeBSD
__sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary)
For the target systems, there are the target operating system and
the target object file format:
Target operating system:
TARGET_WINDOS Covers 32 bit windows and 64 bit windows
TARGET_LINUX Covers 32 and 64 bit linux
TARGET_OSX Covers 32 and 64 bit Mac OSX
TARGET_FREEBSD Covers 32 and 64 bit FreeBSD
TARGET_SOLARIS Covers 32 and 64 bit Solaris
TARGET_NET Covers .Net
It is expected that the compiler for each platform will be able
to generate 32 and 64 bit code from the same compiler binary.
Target object module format:
OMFOBJ Intel Object Module Format, used on Windows
ELFOBJ Elf Object Module Format, used on linux, FreeBSD and Solaris
MACHOBJ Mach-O Object Module Format, used on Mac OSX
There are currently no macros for byte endianness order.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <stdarg.h>
#ifdef __DMC__
#ifdef DEBUG
#undef assert
#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
#endif
#endif
#ifndef IS_PRINTF
# ifdef __GNUC__
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
# else
# define IS_PRINTF(FMTARG)
# endif
#endif
#ifdef IN_GCC
/* Changes for the GDC compiler by David Friedman */
#endif
#define DMDV1 0
#define DMDV2 1 // Version 2.0 features
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
#define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and
* TARGET_SOLARIS, which are
* set on the command line via the compiler makefile.
*/
#if _WIN32
#define TARGET_WINDOS 1 // Windows dmd generates Windows targets
#define OMFOBJ 1
#endif
#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
#ifndef ELFOBJ
#define ELFOBJ 1
#endif
#endif
#if TARGET_OSX
#ifndef MACHOBJ
#define MACHOBJ 1
#endif
#endif
struct Array;
struct OutBuffer;
#if IN_LLVM
enum ARCH
{
ARCHinvalid,
ARCHx86,
ARCHx86_64,
ARCHppc,
ARCHppc_64,
ARCHarm,
ARCHthumb
};
enum OUTPUTFLAG
{
OUTPUTFLAGno,
OUTPUTFLAGdefault, // for the .o default
OUTPUTFLAGset // for -output
};
enum OS
{
OSinvalid,
OSLinux,
OSWindows,
OSMacOSX,
OSFreeBSD,
OSSolaris,
};
typedef unsigned char ubyte;
#endif
// Put command line switches in here
struct Param
{
bool obj; // write object file
bool link; // perform link
bool verbose; // verbose compile
bool vtls; // identify thread local variables
ubyte symdebug; // insert debug symbolic information
#if !IN_LLVM
// LDC uses a different mechanism
bool optimize; // run optimizer
char optimizeLevel; // optimization level
#endif
ARCH cpu; // target CPU
OS os;
bool is64bit; // generate X86_64 bit code
bool isLE; // generate little endian code
bool useDeprecated; // allow use of deprecated features
bool useAssert; // generate runtime code for assert()'s
bool useInvariants; // generate class invariant checks
bool useIn; // generate precondition checks
bool useOut; // generate postcondition checks
bool useArrayBounds; // generate array bounds checks
bool useSwitchError; // check for switches without a default
bool useUnitTests; // generate unittest code
bool useInline; // inline expand functions
bool warnings; // enable warnings
ubyte Dversion; // D version number
char safe; // enforce safe memory model
char *argv0; // program name
Array *imppath; // array of char*'s of where to look for import modules
Array *fileImppath; // array of char*'s of where to look for file import modules
char *objdir; // .obj file output directory
char *objname; // .obj file output name
bool doDocComments; // process embedded documentation comments
char *docdir; // write documentation file to docdir directory
char *docname; // write documentation file to docname
Array *ddocfiles; // macro include files for Ddoc
bool doHdrGeneration; // process embedded documentation comments
char *hdrdir; // write 'header' file to docdir directory
char *hdrname; // write 'header' file to docname
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
unsigned versionlevel; // version level
Array *versionids; // version identifiers
bool dump_source;
Array *defaultlibnames; // default libraries for non-debug builds
Array *debuglibnames; // default libraries for debug builds
const char *xmlname; // filename for XML output
OutBuffer *moduleDeps; // buffer and filename for emitting module deps
char *moduleDepsFile;
// Hidden debug switches
bool debuga;
bool debugb;
bool debugc;
bool debugf;
bool debugr;
bool debugw;
bool debugx;
bool debugy;
bool run; // run resulting executable
// Linker stuff
Array *objfiles;
Array *linkswitches;
Array *libfiles;
char *deffile;
char *resfile;
char *exefile;
#if IN_LLVM
// LDC stuff
OUTPUTFLAG output_ll;
OUTPUTFLAG output_bc;
OUTPUTFLAG output_s;
OUTPUTFLAG output_o;
bool llvmAnnotate;
bool useInlineAsm;
bool verbose_cg;
// target stuff
const char* llvmArch;
const char *targetTriple;
const char *dataLayout;
#endif
};
struct Global
{
const char *mars_ext;
const char *sym_ext;
const char *obj_ext;
#if IN_LLVM
#if _WIN32
char *obj_ext_alt;
#endif
char *ll_ext;
char *bc_ext;
char *s_ext;
#endif
const char *lib_ext;
const char *doc_ext; // for Ddoc generated files
const char *ddoc_ext; // for Ddoc macro include files
const char *hdr_ext; // for D 'header' import files
const char *copyright;
const char *written;
Array *path; // Array of char*'s which form the import lookup path
Array *filePath; // Array of char*'s which form the file import lookup path
int structalign;
const char *version;
#if IN_LLVM
char *ldc_version;
char *llvm_version;
#endif
Param params;
unsigned errors; // number of errors reported so far
unsigned gag; // !=0 means gag reporting of errors
Global();
};
extern Global global;
/* Set if Windows Structured Exception Handling C extensions are supported.
* Apparently, VC has dropped support for these?
*/
#define WINDOWS_SEH (_WIN32 && __DMC__)
#ifdef __DMC__
typedef _Complex long double complex_t;
#else
#ifndef IN_GCC
#include "complex_t.h"
#endif
#ifdef __APPLE__
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
#endif
#endif
// Be careful not to care about sign when using dinteger_t
//typedef uint64_t integer_t;
typedef uint64_t dinteger_t; // use this instead of integer_t to
// avoid conflicts with system #include's
// Signed and unsigned variants
typedef int64_t sinteger_t;
typedef uint64_t uinteger_t;
typedef int8_t d_int8;
typedef uint8_t d_uns8;
typedef int16_t d_int16;
typedef uint16_t d_uns16;
typedef int32_t d_int32;
typedef uint32_t d_uns32;
typedef int64_t d_int64;
typedef uint64_t d_uns64;
typedef float d_float32;
typedef double d_float64;
typedef long double d_float80;
typedef d_uns8 d_char;
typedef d_uns16 d_wchar;
typedef d_uns32 d_dchar;
#ifdef IN_GCC
#include "d-gcc-real.h"
#else
typedef long double real_t;
#endif
// Modify OutBuffer::writewchar to write the correct size of wchar
#if _WIN32
#define writewchar writeword
#else
// This needs a configuration test...
#define writewchar write4
#endif
#ifdef IN_GCC
#include "d-gcc-complex_t.h"
#endif
struct Module;
//typedef unsigned Loc; // file location
struct Loc
{
const char *filename;
unsigned linnum;
Loc()
{
linnum = 0;
filename = NULL;
}
Loc(int x)
{
linnum = x;
filename = NULL;
}
Loc(Module *mod, unsigned linnum);
char *toChars();
bool equals(const Loc& loc);
};
#ifndef GCC_SAFE_DMD
#define TRUE 1
#define FALSE 0
#endif
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
// in interface vtbl[]'s
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
// in the inheritance graph multiple
// times, only one is used
enum LINK
{
LINKdefault,
LINKd,
LINKc,
LINKcpp,
LINKwindows,
LINKpascal,
#if IN_LLVM
LINKintrinsic,
#endif
};
enum DYNCAST
{
DYNCAST_OBJECT,
DYNCAST_EXPRESSION,
DYNCAST_DSYMBOL,
DYNCAST_TYPE,
DYNCAST_IDENTIFIER,
DYNCAST_TUPLE,
};
enum MATCH
{
MATCHnomatch, // no match
MATCHconvert, // match with conversions
#if DMDV2
MATCHconst, // match with conversion to const
#endif
MATCHexact // exact match
};
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
void vwarning(Loc loc, const char *format, va_list);
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
void verror(Loc loc, const char *format, va_list);
void fatal();
void err_nomem();
#if IN_LLVM
void inifile(char *argv0, const char *inifile);
#else
int runLINK();
void deleteExeFile();
int runProgram();
void inifile(const char *argv0, const char *inifile);
#endif
void halt();
#if !IN_LLVM
void util_progress();
#endif
/*** Where to send error messages ***/
#if IN_GCC || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stdout
#endif
#if !IN_LLVM
struct Dsymbol;
struct Library;
struct File;
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
void obj_append(Dsymbol *s);
void obj_write_deferred(Library *library);
#endif
#endif /* DMD_MARS_H */

View File

@@ -7,7 +7,7 @@
#include <cstring>
#include <cassert>
#include "mem.h"
#include "rmem.h"
#if USE_BOEHM_GC
// I needed to perfix the dir after upgrading to gc 7.0

File diff suppressed because it is too large Load Diff

View File

@@ -1,197 +1,212 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MODULE_H
#define DMD_MODULE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct ModuleInfoDeclaration;
struct ClassDeclaration;
struct ModuleDeclaration;
struct Macro;
struct Escape;
struct VarDeclaration;
struct Library;
// Back end
#if IN_LLVM
struct DValue;
typedef DValue elem;
#else
#ifdef IN_GCC
union tree_node; typedef union tree_node elem;
#else
struct elem;
#endif
#endif
struct Package : ScopeDsymbol
{
Package(Identifier *ident);
const char *kind();
static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
Package *isPackage() { return this; }
virtual void semantic(Scope *sc) { }
};
struct Module : Package
{
static Module *rootModule;
static DsymbolTable *modules; // symbol table of all modules
static Array amodules; // array of all modules
static Array deferred; // deferred Dsymbol's needing semantic() run on them
static unsigned dprogress; // progress resolving the deferred list
static void init();
static ClassDeclaration *moduleinfo;
const char *arg; // original argument name
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
File *srcfile; // input source file
File *objfile; // output object file
File *docfile; // output doc file
File *hdrfile; // output hdr file
unsigned errors; // if any errors in file
unsigned numlines; // number of lines in source file
int isHtml; // if it is an HTML file
int isDocFile; // if it is a documentation input file, not D source
int needmoduleinfo;
#ifdef IN_GCC
int strictlyneedmoduleinfo;
#endif
int insearch;
Identifier *searchCacheIdent;
Dsymbol *searchCacheSymbol; // cached value of search
int searchCacheFlags; // cached flags
int semanticstarted; // has semantic() been started?
int semanticdone; // has semantic() been done?
int root; // != 0 if this is a 'root' module,
// i.e. a module that will be taken all the
// way to an object file
Module *importedFrom; // module from command line we're imported from,
// i.e. a module that will be taken all the
// way to an object file
Array *decldefs; // top level declarations for this Module
Array aimports; // all imported modules
ModuleInfoDeclaration *vmoduleinfo;
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
Array *debugidsNot; // forward referenced debug identifiers
unsigned versionlevel; // version level
Array *versionids; // version identifiers
Array *versionidsNot; // forward referenced version identifiers
Macro *macrotable; // document comment macros
struct Escape *escapetable; // document comment escapes
int doDocComment; // enable generating doc comments for this module
int doHdrGen; // enable generating header file for this module
bool safe;
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
~Module();
static Module *load(Loc loc, Array *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
void read(Loc loc); // read file
#if IN_GCC
void parse(bool dump_source = false); // syntactic parse
#else
void parse(); // syntactic parse
#endif
void semantic(Scope* unused_sc = NULL); // semantic analysis
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
void inlineScan(); // scan for functions to inline
#ifdef _DH
void genhdrfile(); // generate D import file
#endif
void genobjfile(int multiobj);
// void gensymfile();
void gendocfile();
int needModuleInfo();
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void deleteObjFile();
void addDeferredSemantic(Dsymbol *s);
void runDeferredSemantic();
// Back end
int doppelganger; // sub-module
Symbol *cov; // private uint[] __coverage;
unsigned *covb; // bit array of valid code line numbers
Symbol *sictor; // module order independent constructor
Symbol *sctor; // module constructor
Symbol *sdtor; // module destructor
Symbol *stest; // module unit test
Symbol *sfilename; // symbol for filename
Symbol *massert; // module assert function
Symbol *toModuleAssert(); // get module assert function
Symbol *marray; // module array bounds function
Symbol *toModuleArray(); // get module array bounds function
static Symbol *gencritsec();
elem *toEfilename();
elem *toEmodulename();
Symbol *toSymbol();
void genmoduleinfo();
// LDC
void buildTargetFiles();
File* buildFilePath(char* forcename, const char* path, const char* ext);
Module *isModule() { return this; }
bool llvmForceLogging;
// array ops emitted in this module already
StringTable arrayfuncs;
};
struct ModuleDeclaration
{
Identifier *id;
Array *packages; // array of Identifier's representing packages
bool safe;
ModuleDeclaration(Array *packages, Identifier *id, bool safe);
char *toChars();
};
#endif /* DMD_MODULE_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_MODULE_H
#define DMD_MODULE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct ModuleInfoDeclaration;
struct ClassDeclaration;
struct ModuleDeclaration;
struct Macro;
struct Escape;
struct VarDeclaration;
struct Library;
// Back end
#if IN_LLVM
class Ir;
struct DValue;
typedef DValue elem;
namespace llvm { class Module; }
#else
#ifdef IN_GCC
union tree_node; typedef union tree_node elem;
#else
struct elem;
#endif
#endif
struct Package : ScopeDsymbol
{
Package(Identifier *ident);
const char *kind();
static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
Package *isPackage() { return this; }
virtual void semantic(Scope *sc) { }
};
struct Module : Package
{
static Module *rootModule;
static DsymbolTable *modules; // symbol table of all modules
static Array amodules; // array of all modules
static Array deferred; // deferred Dsymbol's needing semantic() run on them
static unsigned dprogress; // progress resolving the deferred list
static void init();
static ClassDeclaration *moduleinfo;
const char *arg; // original argument name
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
File *srcfile; // input source file
File *objfile; // output object file
File *docfile; // output doc file
File *hdrfile; // output hdr file
unsigned errors; // if any errors in file
unsigned numlines; // number of lines in source file
int isHtml; // if it is an HTML file
int isDocFile; // if it is a documentation input file, not D source
int needmoduleinfo;
#ifdef IN_GCC
int strictlyneedmoduleinfo;
#endif
int selfimports; // 0: don't know, 1: does not, 2: does
int selfImports(); // returns !=0 if module imports itself
int insearch;
Identifier *searchCacheIdent;
Dsymbol *searchCacheSymbol; // cached value of search
int searchCacheFlags; // cached flags
int semanticstarted; // has semantic() been started?
int semanticdone; // has semantic() been done?
int root; // != 0 if this is a 'root' module,
// i.e. a module that will be taken all the
// way to an object file
Module *importedFrom; // module from command line we're imported from,
// i.e. a module that will be taken all the
// way to an object file
Array *decldefs; // top level declarations for this Module
Array aimports; // all imported modules
ModuleInfoDeclaration *vmoduleinfo;
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
Array *debugidsNot; // forward referenced debug identifiers
unsigned versionlevel; // version level
Array *versionids; // version identifiers
Array *versionidsNot; // forward referenced version identifiers
Macro *macrotable; // document comment macros
Escape *escapetable; // document comment escapes
bool safe; // TRUE if module is marked as 'safe'
int doDocComment; // enable generating doc comments for this module
int doHdrGen; // enable generating header file for this module
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
~Module();
static Module *load(Loc loc, Array *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
#if !IN_LLVM
void setDocfile(); // set docfile member
#endif
void read(Loc loc); // read file
#if IN_GCC
void parse(bool dump_source = false); // syntactic parse
#else
void parse(); // syntactic parse
#endif
void semantic(Scope* unused_sc = NULL); // semantic analysis
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
void inlineScan(); // scan for functions to inline
#if !IN_LLVM
void setHdrfile(); // set hdrfile member
#endif
#ifdef _DH
void genhdrfile(); // generate D import file
#endif
// void gensymfile();
void gendocfile();
int needModuleInfo();
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void deleteObjFile();
void addDeferredSemantic(Dsymbol *s);
void runDeferredSemantic();
int imports(Module *m);
// Back end
#if IN_DMD
int doppelganger; // sub-module
Symbol *cov; // private uint[] __coverage;
unsigned *covb; // bit array of valid code line numbers
Symbol *sictor; // module order independent constructor
Symbol *sctor; // module constructor
Symbol *sdtor; // module destructor
Symbol *stest; // module unit test
Symbol *sfilename; // symbol for filename
Symbol *massert; // module assert function
Symbol *toModuleAssert(); // get module assert function
Symbol *marray; // module array bounds function
Symbol *toModuleArray(); // get module array bounds function
static Symbol *gencritsec();
elem *toEfilename();
elem *toEmodulename();
Symbol *toSymbol();
#endif
void genmoduleinfo();
#if IN_LLVM
// LDC
llvm::Module* genLLVMModule(Ir* sir);
void buildTargetFiles();
File* buildFilePath(const char* forcename, const char* path, const char* ext);
Module *isModule() { return this; }
bool llvmForceLogging;
// array ops emitted in this module already
StringTable arrayfuncs;
#endif
};
struct ModuleDeclaration
{
Identifier *id;
Array *packages; // array of Identifier's representing packages
bool safe;
ModuleDeclaration(Array *packages, Identifier *id, bool safe);
char *toChars();
};
#endif /* DMD_MODULE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

61
dmd2/objfile.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef OBJFILE_H
#define OBJFILE_H
#include "root.h"
typedef void *SymHandle;
typedef unsigned SegOffset;
enum ObjFormat
{
NTCOFF,
ELF
};
struct ObjFile : File
{
ObjFile(FileName *);
~ObjFile();
ObjFile *init(ObjFormat);
void comment(const char *); // insert comment into object file
void modulename(const char *); // set module name
void library(const char *); // add default library
void startaddress(SegHandle seg, SegOffset offset); // set start address
// Segments
enum SegHandle
{ code = 1,
data, bss
};
SymHandle defineSym(const char *name, SegHandle seg, SegOffset offset);
SymHandle externSym(const char *name);
SegOffset write(SegHandle seg, const void *data, unsigned nbytes);
SegOffset writestring(SegHandle seg, char *string);
SegOffset write8(SegHandle seg, unsigned b);
SegOffset write16(SegHandle seg, unsigned w);
SegOffset write32(SegHandle seg, unsigned long v);
SegOffset write64(SegHandle seg, unsigned long long v);
SegOffset fill0(SegHandle seg, unsigned nbytes);
SegOffset align(SegHandle seg, unsigned size);
SegOffset writefixup(SegHandle seg, SymHandle sym, unsigned value, int selfrelative);
// Non-binding hint as to how big seg will grow
void reserve(SegHandle seg, SegOffset size);
// Set actual size
void setSize(SegHandle seg, SegOffset size);
// Get/set offset for subsequent writes
void setOffset(SegHandle seg, SegOffset offset);
SegOffset getOffset(SegHandle seg);
SegHandle createSeg(const char *name);
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

11645
dmd2/parse.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -70,6 +70,7 @@ struct Parser : Lexer
Array *parseDeclDefs(int once);
Array *parseAutoDeclarations(unsigned storageClass, unsigned char *comment);
Array *parseBlock();
void composeStorageClass(unsigned stc);
Expression *parseConstraint();
TemplateDeclaration *parseTemplateDeclaration();
TemplateParameters *parseTemplateParameterList(int flag = 0);
@@ -83,7 +84,7 @@ struct Parser : Lexer
Condition *parseDebugCondition();
Condition *parseVersionCondition();
Condition *parseStaticIfCondition();
FuncDeclaration *parseCtor();
Dsymbol *parseCtor();
PostBlitDeclaration *parsePostBlit();
DtorDeclaration *parseDtor();
StaticCtorDeclaration *parseStaticCtor();

View File

@@ -1,26 +1,23 @@
The D Programming Language
Compiler Front End Source
Copyright (c) 1999-2002, by Digital Mars
www.digitalmars.com
Copyright (c) 1999-2009, by Digital Mars
http://www.digitalmars.com
All Rights Reserved
This is the source code to the front end Digital Mars D compiler.
It covers the lexical analysis, parsing, and semantic analysis
of the D Programming Language defined in the documents at
www.digitalmars.com/d/
The optimizer, code generator, and object file generator are not part
of this source, hence the source does not currently constitute a complete,
compilable program. However, many people have expressed a strong interested
in producing a D compiler with the GNU compiler sources. This release should
enable that.
http://www.digitalmars.com/d/
These sources are free, they are redistributable and modifiable
under the terms of the GNU General Public License (attached as gpl.txt),
or the Artistic License (attached as artistic.txt).
The optimizer and code generator sources are
covered under a separate license, backendlicense.txt.
It does not apply to anything else distributed by Digital Mars,
including D compiler executables.

224
dmd2/root/array.c Normal file
View File

@@ -0,0 +1,224 @@
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#if (defined (__SVR4) && defined (__sun))
#include <alloca.h>
#endif
#if _MSC_VER || __MINGW32__
#include <malloc.h>
#endif
#if IN_GCC
#include "gdc_alloca.h"
#endif
#if _WIN32
#include <windows.h>
#endif
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <utime.h>
#endif
#include "port.h"
#include "root.h"
#include "dchar.h"
#include "rmem.h"
/********************************* Array ****************************/
Array::Array()
{
data = NULL;
dim = 0;
allocdim = 0;
}
Array::~Array()
{
mem.free(data);
}
void Array::mark()
{ unsigned u;
mem.mark(data);
for (u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
void Array::reserve(unsigned nentries)
{
//printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
if (allocdim - dim < nentries)
{
allocdim = dim + nentries;
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
}
}
void Array::setDim(unsigned newdim)
{
if (dim < newdim)
{
reserve(newdim - dim);
}
dim = newdim;
}
void Array::fixDim()
{
if (dim != allocdim)
{ data = (void **)mem.realloc(data, dim * sizeof(*data));
allocdim = dim;
}
}
void Array::push(void *ptr)
{
reserve(1);
data[dim++] = ptr;
}
void *Array::pop()
{
return data[--dim];
}
void Array::shift(void *ptr)
{
reserve(1);
memmove(data + 1, data, dim * sizeof(*data));
data[0] = ptr;
dim++;
}
void Array::insert(unsigned index, void *ptr)
{
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = ptr;
dim++;
}
void Array::insert(unsigned index, Array *a)
{
if (a)
{ unsigned d;
d = a->dim;
reserve(d);
if (dim != index)
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
memcpy(data + index, a->data, d * sizeof(*data));
dim += d;
}
}
/***********************************
* Append array a to this array.
*/
void Array::append(Array *a)
{
insert(dim, a);
}
void Array::remove(unsigned i)
{
memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0]));
dim--;
}
char *Array::toChars()
{
unsigned len;
unsigned u;
char **buf;
char *str;
char *p;
buf = (char **)alloca(dim * sizeof(char *));
len = 2;
for (u = 0; u < dim; u++)
{
buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1;
}
str = (char *)mem.malloc(len);
str[0] = '[';
p = str + 1;
for (u = 0; u < dim; u++)
{
if (u)
*p++ = ',';
len = strlen(buf[u]);
memcpy(p,buf[u],len);
p += len;
}
*p++ = ']';
*p = 0;
return str;
}
void Array::zero()
{
memset(data,0,dim * sizeof(data[0]));
}
void *Array::tos()
{
return dim ? data[dim - 1] : NULL;
}
int
#if _WIN32
__cdecl
#endif
Array_sort_compare(const void *x, const void *y)
{
Object *ox = *(Object **)x;
Object *oy = *(Object **)y;
return ox->compare(oy);
}
void Array::sort()
{
if (dim)
{
qsort(data, dim, sizeof(Object *), Array_sort_compare);
}
}
Array *Array::copy()
{
Array *a = new Array();
a->setDim(dim);
memcpy(a->data, data, dim * sizeof(void *));
return a;
}

177
dmd2/root/async.c Normal file
View File

@@ -0,0 +1,177 @@
#define _MT 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#include <stdio.h>
#include <errno.h>
#include <process.h>
#include "root.h"
#include "rmem.h"
static unsigned __stdcall startthread(void *p);
struct FileData
{
File *file;
int result;
HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
WaitForSingleObject(f->event, INFINITE);
Sleep(0); // give up time slice
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
}
unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
SetEvent(f->event);
}
_endthreadex(EXIT_SUCCESS);
return EXIT_SUCCESS; // if skidding
}
#else
#include <stdio.h>
#include <errno.h>
#include "root.h"
#include "rmem.h"
struct FileData
{
File *file;
int result;
//HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
//HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
//ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
f->result = f->file->read();
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
}
#endif

33
dmd2/root/async.h Normal file
View File

@@ -0,0 +1,33 @@
// Copyright (c) 2009-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef ASYNC_H
#define ASYNC_H
#if __DMC__
#pragma once
#endif
/*******************
* Simple interface to read files asynchronously in another
* thread.
*/
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
};
#endif

482
dmd2/root/dchar.c Normal file
View File

@@ -0,0 +1,482 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "dchar.h"
#include "rmem.h"
#if M_UNICODE
// Converts a char string to Unicode
dchar *Dchar::dup(char *p)
{
dchar *s;
size_t len;
if (!p)
return NULL;
len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++)
{
s[i] = (dchar)(p[i] & 0xFF);
}
s[len] = 0;
return s;
}
dchar *Dchar::memchr(dchar *p, int c, int count)
{
int u;
for (u = 0; u < count; u++)
{
if (p[u] == c)
return p + u;
}
return NULL;
}
#if _WIN32 && __DMC__
__declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len)
{
__asm
{
mov ECX,4[ESP]
mov EDX,8[ESP]
xor EAX,EAX
test EDX,EDX
je L92
LC8: cmp EDX,1
je L98
cmp EDX,2
je LAE
add EAX,[ECX]
// imul EAX,EAX,025h
lea EAX,[EAX][EAX*8]
add ECX,4
sub EDX,2
jmp LC8
L98: mov DX,[ECX]
and EDX,0FFFFh
add EAX,EDX
ret
LAE: add EAX,[ECX]
L92: ret
}
}
#else
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
unsigned hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str;
return hash;
case 2:
hash += *(const uint32_t *)str;
return hash;
default:
hash += *(const uint32_t *)str;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#endif
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str | 0x20;
return hash;
case 2:
hash += *(const uint32_t *)str | 0x200020;
return hash;
default:
hash += *(const uint32_t *)str | 0x200020;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
#elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
};
dchar *Dchar::dec(dchar *pstart, dchar *p)
{
while ((p[-1] & 0xC0) == 0x80)
p--;
return p;
}
int Dchar::get(dchar *p)
{
unsigned c;
unsigned char *q = (unsigned char *)p;
c = q[0];
switch (mblen[c])
{
case 2:
c = ((c - 0xC0) << 6) |
(q[1] - 0x80);
break;
case 3:
c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) |
(q[2] - 0x80);
break;
case 4:
c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) |
(q[3] - 0x80);
break;
case 5:
c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) |
(q[4] - 0x80);
break;
case 6:
c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) |
(q[5] - 0x80);
break;
}
return c;
}
dchar *Dchar::put(dchar *p, unsigned c)
{
if (c <= 0x7F)
{
*p++ = c;
}
else if (c <= 0x7FF)
{
p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F);
p += 2;
}
else if (c <= 0xFFFF)
{
p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F);
p += 3;
}
else if (c <= 0x1FFFFF)
{
p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F);
p += 4;
}
else if (c <= 0x3FFFFFF)
{
p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F);
p += 5;
}
else if (c <= 0x7FFFFFFF)
{
p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F);
p += 6;
}
else
assert(0); // not a UCS-4 character
return p;
}
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if __I86__
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if __I86__
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if __I86__
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
#else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if __I86__
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if __I86__
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if __I86__
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020;
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str | 0x20202020;
str += 4;
len -= 4;
break;
}
}
}
#endif
#if 0
#include <stdio.h>
void main()
{
// Print out values to hardcode into Dchar::mblen[]
int c;
int s;
for (c = 0; c < 256; c++)
{
s = 1;
if (c >= 0xC0 && c <= 0xDF)
s = 2;
if (c >= 0xE0 && c <= 0xEF)
s = 3;
if (c >= 0xF0 && c <= 0xF7)
s = 4;
if (c >= 0xF8 && c <= 0xFB)
s = 5;
if (c >= 0xFC && c <= 0xFD)
s = 6;
printf("%d", s);
if ((c & 15) == 15)
printf(",\n");
else
printf(",");
}
}
#endif

194
dmd2/root/dchar.h Normal file
View File

@@ -0,0 +1,194 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DCHAR_H
#define DCHAR_H
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif
//#include "root.h"
typedef size_t hash_t;
#undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE
#include <string.h>
#include <wchar.h>
typedef wchar_t dchar;
#define TEXT(x) L##x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2)
{
#if __DMC__
if (!*s1 && !*s2) // wcscmp is broken
return 0;
#endif
return wcscmp(s1, s2);
#if 0
return (*s1 == *s2)
? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2);
#endif
}
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#elif MCBS
#include <limits.h>
#include <mbstring.h>
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX
#elif UTF8
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 6
struct Dchar
{
static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
};
#else
#include <string.h>
#ifndef GCC_SAFE_DMD
#include <ctype.h>
#endif
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha(c); }
static int isUpper(dchar c) { return isupper(c); }
static int isLower(dchar c) { return islower(c); }
static int isLocaleUpper(dchar c) { return isupper(c); }
static int isLocaleLower(dchar c) { return islower(c); }
static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
#ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#endif
#endif

55
dmd2/root/gnuc.c Normal file
View File

@@ -0,0 +1,55 @@
// Put functions in here missing from gnu C
#include "gnuc.h"
int memicmp(const char *s1, const char *s2, int n)
{
int result = 0;
for (int i = 0; i < n; i++)
{ char c1 = s1[i];
char c2 = s2[i];
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
}
return result;
}
int stricmp(const char *s1, const char *s2)
{
int result = 0;
for (;;)
{ char c1 = *s1;
char c2 = *s2;
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
if (!c1)
break;
s1++;
s2++;
}
return result;
}

8
dmd2/root/gnuc.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef _GNUC_H
#define _GNUC_H 1
int memicmp(const char *s1, const char *s2, int n);
int stricmp(const char *s1, const char *s2);
#endif

63
dmd2/root/lstring.c Normal file
View File

@@ -0,0 +1,63 @@
// lstring.c
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdlib.h>
#include "dchar.h"
#include "rmem.h"
#include "lstring.h"
#ifdef _MSC_VER // prevent compiler internal crash
Lstring Lstring::zero;
#else
Lstring Lstring::zero = LSTRING_EMPTY();
#endif
Lstring *Lstring::ctor(const dchar *p, unsigned length)
{
Lstring *s;
s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar));
return s;
}
Lstring *Lstring::alloc(unsigned length)
{
Lstring *s;
s = (Lstring *)mem.malloc(size(length));
s->length = length;
s->string[length] = 0;
return s;
}
Lstring *Lstring::append(const Lstring *s)
{
Lstring *t;
if (!s->length)
return this;
t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t;
}
Lstring *Lstring::substring(int start, int end)
{
Lstring *t;
if (start == end)
return &zero;
t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t;
}

72
dmd2/root/lstring.h Normal file
View File

@@ -0,0 +1,72 @@
// lstring.h
// length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef LSTRING_H
#define LSTRING_H 1
#include "dchar.h"
struct Lstring
{
unsigned length;
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
dchar string[];
static Lstring zero; // 0 length string
// No constructors because we want to be able to statically
// initialize Lstring's, and Lstrings are of variable size.
#if M_UNICODE
#define LSTRING(p,length) { length, L##p }
#else
#define LSTRING(p,length) { length, p }
#endif
#if __GNUC__
#define LSTRING_EMPTY() { 0 }
#else
#define LSTRING_EMPTY() LSTRING("", 0)
#endif
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
Lstring *clone();
unsigned len() { return length; }
dchar *toDchars() { return string; }
hash_t hash() { return Dchar::calcHash(string, length); }
hash_t ihash() { return Dchar::icalcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
}
static int icmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
}
Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
};
#endif

100
dmd2/root/man.c Normal file
View File

@@ -0,0 +1,100 @@
// Compiler implementation of the D programming language
// Copyright (c) 2008-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#pragma comment(lib,"shell32.lib")
void browse(const char *url)
{
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
}
#endif
#if linux || __FreeBSD__ || __sun&&__SVR4
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void browse(const char *url)
{
pid_t childpid;
const char *args[3];
char *browser = getenv("BROWSER");
if (browser)
browser = strdup(browser);
else
browser = "x-www-browser";
args[0] = browser;
args[1] = url;
args[2] = NULL;
childpid = fork();
if (childpid == 0)
{
execvp(args[0], (char**)args);
perror(args[0]); // failed to execute
return;
}
}
#endif
#if __APPLE__
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void browse(const char *url)
{
pid_t childpid;
const char *args[5];
char *browser = getenv("BROWSER");
if (browser)
{ browser = strdup(browser);
args[0] = browser;
args[1] = url;
args[2] = NULL;
}
else
{
//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
args[0] = "open";
args[1] = "-a";
args[2] = "/Applications/Safari.app";
args[3] = url;
args[4] = NULL;
}
childpid = fork();
if (childpid == 0)
{
execvp(args[0], (char**)args);
perror(args[0]); // failed to execute
return;
}
}
#endif

759
dmd2/root/port.c Normal file
View File

@@ -0,0 +1,759 @@
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include "port.h"
#if __DMC__
#include <math.h>
#include <float.h>
#include <fp.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
double Port::nan = NAN;
double Port::infinity = INFINITY;
double Port::dbl_max = DBL_MAX;
double Port::dbl_min = DBL_MIN;
long double Port::ldbl_max = LDBL_MAX;
int Port::isNan(double r)
{
return ::isnan(r);
}
int Port::isNan(long double r)
{
return ::isnan(r);
}
int Port::isSignallingNan(double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
*/
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
}
int Port::isSignallingNan(long double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 62 of 0..79 for 80 bit reals.
*/
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
int Port::isFinite(double r)
{
return ::isfinite(r);
}
int Port::isInfinity(double r)
{
return (::fpclassify(r) == FP_INFINITE);
}
int Port::Signbit(double r)
{
return ::signbit(r);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
// LOCALE_SLIST for Windows
return ",";
}
const wchar_t *Port::wlist_separator()
{
// LOCALE_SLIST for Windows
return L",";
}
char *Port::strupr(char *s)
{
return ::strupr(s);
}
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#include <math.h>
#include <float.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits> // for std::numeric_limits
static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
//static unsigned long nanarray[2] = {0,0x7FF80000 };
double Port::nan = (*(double *)nanarray);
//static unsigned long infinityarray[2] = {0,0x7FF00000 };
static double zero = 0;
double Port::infinity = 1 / zero;
double Port::dbl_max = DBL_MAX;
double Port::dbl_min = DBL_MIN;
long double Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
PortInitializer();
};
static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
Port::infinity = std::numeric_limits<long double>::infinity();
}
int Port::isNan(double r)
{
return ::_isnan(r);
}
int Port::isNan(long double r)
{
return ::_isnan(r);
}
int Port::isSignallingNan(double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
*/
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
}
int Port::isSignallingNan(long double r)
{
/* MSVC doesn't have 80 bit long doubles
*/
return isSignallingNan((double) r);
}
int Port::isFinite(double r)
{
return ::_finite(r);
}
int Port::isInfinity(double r)
{
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
}
int Port::Signbit(double r)
{
return (long)(((long *)&(r))[1] & 0x80000000);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
if (y == 0)
return 1; // even if x is NAN
return ::pow(x, y);
}
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
{
unsigned _int64 number = 0;
int c;
int error;
#define ULLONG_MAX ((unsigned _int64)~0I64)
while (isspace(*p)) /* skip leading white space */
p++;
if (*p == '+')
p++;
switch (base)
{ case 0:
base = 10; /* assume decimal base */
if (*p == '0')
{ base = 8; /* could be octal */
p++;
switch (*p)
{ case 'x':
case 'X':
base = 16; /* hex */
p++;
break;
#if BINARY
case 'b':
case 'B':
base = 2; /* binary */
p++;
break;
#endif
}
}
break;
case 16: /* skip over '0x' and '0X' */
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
p += 2;
break;
#if BINARY
case 2: /* skip over '0b' and '0B' */
if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
p += 2;
break;
#endif
}
error = 0;
for (;;)
{ c = *p;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c = (c & ~0x20) - ('A' - 10);
else /* unrecognized character */
break;
if (c >= base) /* not in number base */
break;
if ((ULLONG_MAX - c) / base < number)
error = 1;
number = number * base + c;
p++;
}
if (pend)
*pend = (char *)p;
if (error)
{ number = ULLONG_MAX;
errno = ERANGE;
}
return number;
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
_ui64toa(ull, buffer, 10);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
_ui64tow(ull, buffer, 10);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{ double d;
if ((__int64) ull < 0)
{
// MSVC doesn't implement the conversion
d = (double) (__int64)(ull - 0x8000000000000000i64);
d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
}
else
d = (double)(__int64)ull;
return d;
}
const char *Port::list_separator()
{
// LOCALE_SLIST for Windows
return ",";
}
const wchar_t *Port::wlist_separator()
{
// LOCALE_SLIST for Windows
return L",";
}
char *Port::strupr(char *s)
{
return ::strupr(s);
}
#endif
#if linux || __APPLE__ || __FreeBSD__
#include <math.h>
#if linux
#include <bits/nan.h>
#include <bits/mathdef.h>
#endif
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <float.h>
static double zero = 0;
double Port::nan = NAN;
double Port::infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
long double Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
PortInitializer();
};
static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
// gcc nan's have the sign bit set by default, so turn it off
// Need the volatile to prevent gcc from doing incorrect
// constant folding.
volatile long double foo;
foo = NAN;
if (signbit(foo)) // signbit sometimes, not always, set
foo = -foo; // turn off sign bit
Port::nan = foo;
#if __FreeBSD__
// LDBL_MAX comes out as infinity. Fix.
static unsigned char x[sizeof(long double)] =
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
Port::ldbl_max = *(long double *)&x[0];
#endif
}
#undef isnan
int Port::isNan(double r)
{
#if __APPLE__
return __inline_isnan(r);
#else
return ::isnan(r);
#endif
}
int Port::isNan(long double r)
{
#if __APPLE__
return __inline_isnan(r);
#else
return ::isnan(r);
#endif
}
int Port::isSignallingNan(double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
*/
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
}
int Port::isSignallingNan(long double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 62 of 0..79 for 80 bit reals.
*/
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
#undef isfinite
int Port::isFinite(double r)
{
return ::finite(r);
}
#undef isinf
int Port::isInfinity(double r)
{
#if __APPLE__
return fpclassify(r) == FP_INFINITE;
#else
return ::isinf(r);
#endif
}
#undef signbit
int Port::Signbit(double r)
{
return (long)(((long *)&r)[1] & 0x80000000);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
return ",";
}
const wchar_t *Port::wlist_separator()
{
return L",";
}
char *Port::strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
#endif
#if __sun&&__SVR4
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <float.h>
#include <ieeefp.h>
static double zero = 0;
double Port::nan = NAN;
double Port::infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
long double Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
PortInitializer();
};
static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
// gcc nan's have the sign bit set by default, so turn it off
// Need the volatile to prevent gcc from doing incorrect
// constant folding.
volatile long double foo;
foo = NAN;
if (signbit(foo)) // signbit sometimes, not always, set
foo = -foo; // turn off sign bit
Port::nan = foo;
}
int Port::isNan(double r)
{
return isnan(r);
}
int Port::isNan(long double r)
{
return isnan(r);
}
int Port::isSignallingNan(double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
*/
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
}
int Port::isSignallingNan(long double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 62 of 0..79 for 80 bit reals.
*/
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
#undef isfinite
int Port::isFinite(double r)
{
return finite(r);
}
int Port::isInfinity(double r)
{
return isinf(r);
}
#undef signbit
int Port::Signbit(double r)
{
return (long)(((long *)&r)[1] & 0x80000000);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
return ",";
}
const wchar_t *Port::wlist_separator()
{
return L",";
}
char *Port::strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
#endif
#if IN_GCC
#include <math.h>
#include <bits/nan.h>
#include <bits/mathdef.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
static double zero = 0;
double Port::nan = NAN;
double Port::infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
long double Port::ldbl_max = LDBL_MAX;
#include "d-gcc-real.h"
extern "C" bool real_isnan (const real_t *);
struct PortInitializer
{
PortInitializer();
};
static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
Port::infinity = real_t::getinfinity();
Port::nan = real_t::getnan(real_t::LongDouble);
}
#undef isnan
int Port::isNan(double r)
{
#if __APPLE__
return __inline_isnan(r);
#else
return ::isnan(r);
#endif
}
int Port::isNan(long double r)
{
return real_isnan(&r);
}
int Port::isSignallingNan(double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
*/
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
}
int Port::isSignallingNan(long double r)
{
/* A signalling NaN is a NaN with 0 as the most significant bit of
* its significand, which is bit 62 of 0..79 for 80 bit reals.
*/
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
}
#undef isfinite
int Port::isFinite(double r)
{
return ::finite(r);
}
#undef isinf
int Port::isInfinity(double r)
{
return ::isinf(r);
}
#undef signbit
int Port::Signbit(double r)
{
return (long)(((long *)&r)[1] & 0x80000000);
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
}
char *Port::ull_to_string(char *buffer, ulonglong ull)
{
sprintf(buffer, "%llu", ull);
return buffer;
}
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
swprintf(buffer, L"%llu", ull);
return buffer;
}
double Port::ull_to_double(ulonglong ull)
{
return (double) ull;
}
const char *Port::list_separator()
{
return ",";
}
const wchar_t *Port::wlist_separator()
{
return L",";
}
char *Port::strupr(char *s)
{
char *t = s;
while (*s)
{
*s = toupper(*s);
s++;
}
return t;
}
#endif

78
dmd2/root/port.h Normal file
View File

@@ -0,0 +1,78 @@
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#ifndef PORT_H
#define PORT_H
// Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code.
#ifndef TYPEDEFS
#define TYPEDEFS
#include <wchar.h>
#if _MSC_VER
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
// According to VC 8.0 docs, long double is the same as double
#define strtold strtod
#define strtof strtod
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
typedef double d_time;
struct Port
{
static double nan;
static double infinity;
static double dbl_max;
static double dbl_min;
static long double ldbl_max;
#if __GNUC__
// These conflict with macros in math.h, should rename them
#undef isnan
#undef isfinite
#undef isinfinity
#undef signbit
#endif
static int isNan(double);
static int isNan(long double);
static int isSignallingNan(double);
static int isSignallingNan(long double);
static int isFinite(double);
static int isInfinity(double);
static int Signbit(double);
static double floor(double);
static double pow(double x, double y);
static ulonglong strtoull(const char *p, char **pend, int base);
static char *ull_to_string(char *buffer, ulonglong ull);
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
// Convert ulonglong to double
static double ull_to_double(ulonglong ull);
// Get locale-dependent list separator
static const char *list_separator();
static const wchar_t *wlist_separator();
static char *strupr(char *);
};
#endif

278
dmd2/root/response.c Normal file
View File

@@ -0,0 +1,278 @@
// Copyright (C) 1990-1998 by Symantec
// Copyright (C) 2000-2009 by Digital Mars
// All Rights Reserved
// http://www.digitalmars.com
// Written by Walter Bright
/*
* This source file is made available for personal use
* only. The license is in /dmd/src/dmd/backendlicense.txt
* For any other uses, please contact Digital Mars.
*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#if !__DMC__
#include <sys/stat.h>
#endif
#if _WIN32
#include <tchar.h>
#include <io.h>
#endif
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <utime.h>
#endif
/*********************************
* #include <stdlib.h>
* int response_expand(int *pargc,char ***pargv);
*
* Expand any response files in command line.
* Response files are arguments that look like:
* @NAME
* The name is first searched for in the environment. If it is not
* there, it is searched for as a file name.
* Arguments are separated by spaces, tabs, or newlines. These can be
* imbedded within arguments by enclosing the argument in '' or "".
* Recursively expands nested response files.
*
* To use, put the line:
* response_expand(&argc,&argv);
* as the first executable statement in main(int argc, char **argv).
* argc and argv are adjusted to be the new command line arguments
* after response file expansion.
*
* Digital Mars's MAKE program can be notified that a program can accept
* long command lines via environment variables by preceding the rule
* line for the program with a *.
*
* Returns:
* 0 success
* !=0 failure (argc, argv unchanged)
*/
struct Narg
{
int argc; /* arg count */
int argvmax; /* dimension of nargv[] */
char **argv;
};
static int addargp(struct Narg *n, char *p)
{
/* The 2 is to always allow room for a NULL argp at the end */
if (n->argc + 2 >= n->argvmax)
{
n->argvmax = n->argc + 2;
n->argv = (char **) realloc(n->argv,n->argvmax * sizeof(char *));
if (!n->argv)
return 1;
}
n->argv[n->argc++] = p;
return 0;
}
int response_expand(int *pargc, char ***pargv)
{
struct Narg n;
int i;
char *cp;
int recurse = 0;
n.argc = 0;
n.argvmax = 0; /* dimension of n.argv[] */
n.argv = NULL;
for(i=0; i<*pargc; ++i)
{
cp = (*pargv)[i];
if (*cp == '@')
{
char *buffer;
char *bufend;
char *p;
cp++;
p = getenv(cp);
if (p)
{
buffer = strdup(p);
if (!buffer)
goto noexpand;
bufend = buffer + strlen(buffer);
}
else
{
long length;
int fd;
int nread;
size_t len;
#if __DMC__
length = filesize(cp);
#else
struct stat statbuf;
if (stat(cp, &statbuf))
goto noexpand;
length = statbuf.st_size;
#endif
if (length & 0xF0000000) /* error or file too big */
goto noexpand;
len = length;
buffer = (char *)malloc(len + 1);
if (!buffer)
goto noexpand;
bufend = &buffer[len];
/* Read file into buffer */
#if _WIN32
fd = open(cp,O_RDONLY|O_BINARY);
#else
fd = open(cp,O_RDONLY);
#endif
if (fd == -1)
goto noexpand;
nread = read(fd,buffer,len);
close(fd);
if (nread != len)
goto noexpand;
}
// The logic of this should match that in setargv()
for (p = buffer; p < bufend; p++)
{
char *d;
char c,lastc;
unsigned char instring;
int num_slashes,non_slashes;
switch (*p)
{
case 26: /* ^Z marks end of file */
goto L2;
case 0xD:
case 0:
case ' ':
case '\t':
case '\n':
continue; // scan to start of argument
case '@':
recurse = 1;
default: /* start of new argument */
if (addargp(&n,p))
goto noexpand;
instring = 0;
c = 0;
num_slashes = 0;
for (d = p; 1; p++)
{
lastc = c;
if (p >= bufend)
goto Lend;
c = *p;
switch (c)
{
case '"':
/*
Yes this looks strange,but this is so that we are
MS Compatible, tests have shown that:
\\\\"foo bar" gets passed as \\foo bar
\\\\foo gets passed as \\\\foo
\\\"foo gets passed as \"foo
and \"foo gets passed as "foo in VC!
*/
non_slashes = num_slashes % 2;
num_slashes = num_slashes / 2;
for (; num_slashes > 0; num_slashes--)
{
d--;
*d = '\0';
}
if (non_slashes)
{
*(d-1) = c;
}
else
{
instring ^= 1;
}
break;
case 26:
Lend:
*d = 0; // terminate argument
goto L2;
case 0xD: // CR
c = lastc;
continue; // ignore
case '@':
recurse = 1;
goto Ladd;
case ' ':
case '\t':
if (!instring)
{
case '\n':
case 0:
*d = 0; // terminate argument
goto Lnextarg;
}
default:
Ladd:
if (c == '\\')
num_slashes++;
else
num_slashes = 0;
*d++ = c;
break;
}
#ifdef _MBCS
if (_istlead (c)) {
*d++ = *++p;
if (*(d - 1) == '\0') {
d--;
goto Lnextarg;
}
}
#endif
}
break;
}
Lnextarg:
;
}
L2:
;
}
else if (addargp(&n,(*pargv)[i]))
goto noexpand;
}
n.argv[n.argc] = NULL;
if (recurse)
{
/* Recursively expand @filename */
if (response_expand(&n.argc,&n.argv))
goto noexpand;
}
*pargc = n.argc;
*pargv = n.argv;
return 0; /* success */
noexpand: /* error */
free(n.argv);
/* BUG: any file buffers are not free'd */
return 1;
}

143
dmd2/root/rmem.c Normal file
View File

@@ -0,0 +1,143 @@
/* Copyright (c) 2000 Digital Mars */
/* All Rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#include "../root/rmem.h"
#else
#include "rmem.h"
#endif
/* This implementation of the storage allocator uses the standard C allocation package.
*/
Mem mem;
void Mem::init()
{
}
char *Mem::strdup(const char *s)
{
char *p;
if (s)
{
p = ::strdup(s);
if (p)
return p;
error();
}
return NULL;
}
void *Mem::malloc(size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = ::malloc(size);
if (!p)
error();
}
return p;
}
void *Mem::calloc(size_t size, size_t n)
{ void *p;
if (!size || !n)
p = NULL;
else
{
p = ::calloc(size, n);
if (!p)
error();
}
return p;
}
void *Mem::realloc(void *p, size_t size)
{
if (!size)
{ if (p)
{ ::free(p);
p = NULL;
}
}
else if (!p)
{
p = ::malloc(size);
if (!p)
error();
}
else
{
p = ::realloc(p, size);
if (!p)
error();
}
return p;
}
void Mem::free(void *p)
{
if (p)
::free(p);
}
void *Mem::mallocdup(void *o, size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = ::malloc(size);
if (!p)
error();
else
memcpy(p,o,size);
}
return p;
}
void Mem::error()
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
}
void Mem::mark(void *pointer)
{
(void) pointer; // necessary for VC /W4
}
/* =================================================== */
void * operator new(size_t m_size)
{
void *p = malloc(m_size);
if (p)
return p;
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
return p;
}
void operator delete(void *p)
{
free(p);
}

51
dmd2/root/rmem.h Normal file
View File

@@ -0,0 +1,51 @@
// Copyright (C) 2000-2001 by Chromium Communications
// All Rights Reserved
#ifndef ROOT_MEM_H
#define ROOT_MEM_H
#include <stddef.h> // for size_t
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
struct GC; // thread specific allocator
struct Mem
{
GC *gc; // pointer to our thread specific allocator
Mem() { gc = NULL; }
void init();
// Derive from Mem to get these storage allocators instead of global new/delete
void * operator new(size_t m_size);
void * operator new(size_t m_size, Mem *mem);
void * operator new(size_t m_size, GC *gc);
void operator delete(void *p);
void * operator new[](size_t m_size);
void operator delete[](void *p);
char *strdup(const char *s);
void *malloc(size_t size);
void *malloc_uncollectable(size_t size);
void *calloc(size_t size, size_t n);
void *realloc(void *p, size_t size);
void free(void *p);
void free_uncollectable(void *p);
void *mallocdup(void *o, size_t size);
void error();
void check(void *p); // validate pointer
void fullcollect(); // do full garbage collection
void fullcollectNoStack(); // do full garbage collection, no scan stack
void mark(void *pointer);
void addroots(char* pStart, char* pEnd);
void removeroots(char* pStart);
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
void setStackBottom(void *bottom);
GC *getThreadGC(); // get apartment allocator for this thread
};
extern Mem mem;
#endif /* ROOT_MEM_H */

1948
dmd2/root/root.c Normal file

File diff suppressed because it is too large Load Diff

359
dmd2/root/root.h Normal file
View File

@@ -0,0 +1,359 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef ROOT_H
#define ROOT_H
#include <stdlib.h>
#include <stdarg.h>
#if __DMC__
#pragma once
#endif
typedef size_t hash_t;
#include "dchar.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *);
char *wchar2ascii(wchar_t *, unsigned len);
int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b);
void error(const char *format, ...);
void error(const wchar_t *format, ...);
void warning(const char *format, ...);
#ifndef TYPEDEFS
#define TYPEDEFS
#if _MSC_VER
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double
#define strtold strtod
#define strtof strtod
#define isnan _isnan
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
longlong randomx();
/*
* Root of our class library.
*/
struct OutBuffer;
struct Array;
struct Object
{
Object() { }
virtual ~Object() { }
virtual int equals(Object *o);
/**
* Returns a hash code, useful for things like building hash tables of Objects.
*/
virtual hash_t hashCode();
/**
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
* Useful for sorting Objects.
*/
virtual int compare(Object *obj);
/**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
*/
virtual void print();
virtual char *toChars();
virtual dchar *toDchars();
virtual void toBuffer(OutBuffer *buf);
/**
* Used as a replacement for dynamic_cast. Returns a unique number
* defined by the library user. For Object, the return value is 0.
*/
virtual int dyncast();
/**
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
*/
/*virtual*/ // not used, disable for now
void mark();
};
struct String : Object
{
int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself
String(char *str, int ref = 1);
~String();
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str);
hash_t hashCode();
unsigned len();
int equals(Object *obj);
int compare(Object *obj);
char *toChars();
void print();
void mark();
};
struct FileName : String
{
FileName(char *str, int ref);
FileName(char *path, char *name);
hash_t hashCode();
int equals(Object *obj);
static int equals(const char *name1, const char *name2);
int compare(Object *obj);
static int compare(const char *name1, const char *name2);
static int absolute(const char *name);
static char *ext(const char *);
char *ext();
static char *removeExt(const char *str);
static char *name(const char *);
char *name();
static char *path(const char *);
static const char *replaceName(const char *path, const char *name);
static char *combine(const char *path, const char *name);
static Array *splitPath(const char *path);
static FileName *defaultExt(const char *name, const char *ext);
static FileName *forceExt(const char *name, const char *ext);
int equalsExt(const char *ext);
void CopyTo(FileName *to);
static char *searchPath(Array *path, const char *name, int cwd);
static int exists(const char *name);
static void ensurePathExists(const char *path);
};
struct File : Object
{
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
unsigned len; // amount of data in buffer[]
void *touchtime; // system time to use for file
FileName *name; // name of our file
File(char *);
File(FileName *);
~File();
void mark();
char *toChars();
/* Read file, return !=0 if error
*/
int read();
/* Write file, either succeed or fail
* with error message & exit.
*/
void readv();
/* Read file, return !=0 if error
*/
int mmread();
/* Write file, either succeed or fail
* with error message & exit.
*/
void mmreadv();
/* Write file, return !=0 if error
*/
int write();
/* Write file, either succeed or fail
* with error message & exit.
*/
void writev();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
/* Append to file, return !=0 if error
*/
int append();
/* Append to file, either succeed or fail
* with error message & exit.
*/
void appendv();
/* Return !=0 if file exists.
* 0: file doesn't exist
* 1: normal file
* 2: directory
*/
int exists();
/* Given wildcard filespec, return an array of
* matching File's.
*/
static Array *match(char *);
static Array *match(FileName *);
// Compare file times.
// Return <0 this < f
// =0 this == f
// >0 this > f
int compareTime(File *f);
// Read system file statistics
void stat();
/* Set buffer
*/
void setbuffer(void *buffer, unsigned len)
{
this->buffer = (unsigned char *)buffer;
this->len = len;
}
void checkoffset(size_t offset, size_t nbytes);
void remove(); // delete file
};
struct OutBuffer : Object
{
unsigned char *data;
unsigned offset;
unsigned size;
OutBuffer();
~OutBuffer();
void *extractData();
void mark();
void reserve(unsigned nbytes);
void setsize(unsigned size);
void reset();
void write(const void *data, unsigned nbytes);
void writebstring(unsigned char *string);
void writestring(const char *string);
void writedstring(const char *string);
void writedstring(const wchar_t *string);
void prependstring(const char *string);
void writenl(); // write newline
void writeByte(unsigned b);
void writebyte(unsigned b) { writeByte(b); }
void writeUTF8(unsigned b);
void writedchar(unsigned b);
void prependbyte(unsigned b);
void writeword(unsigned w);
void writeUTF16(unsigned w);
void write4(unsigned w);
void write(OutBuffer *buf);
void write(Object *obj);
void fill0(unsigned nbytes);
void align(unsigned size);
void vprintf(const char *format, va_list args);
void printf(const char *format, ...);
#if M_UNICODE
void vprintf(const unsigned short *format, va_list args);
void printf(const unsigned short *format, ...);
#endif
void bracket(char left, char right);
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
void spread(unsigned offset, unsigned nbytes);
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
void remove(unsigned offset, unsigned nbytes);
char *toChars();
char *extractString();
};
struct Array : Object
{
unsigned dim;
unsigned allocdim;
void **data;
Array();
~Array();
void mark();
char *toChars();
void reserve(unsigned nentries);
void setDim(unsigned newdim);
void fixDim();
void push(void *ptr);
void *pop();
void shift(void *ptr);
void insert(unsigned index, void *ptr);
void insert(unsigned index, Array *a);
void append(Array *a);
void remove(unsigned i);
void zero();
void *tos();
void sort();
Array *copy();
};
struct Bits : Object
{
unsigned bitdim;
unsigned allocdim;
unsigned *data;
Bits();
~Bits();
void mark();
void resize(unsigned bitdim);
void set(unsigned bitnum);
void clear(unsigned bitnum);
int test(unsigned bitnum);
void set();
void clear();
void copy(Bits *from);
Bits *clone();
void sub(Bits *b);
};
#endif

139
dmd2/root/stringtable.c Normal file
View File

@@ -0,0 +1,139 @@
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "root.h"
#include "rmem.h"
#include "dchar.h"
#include "lstring.h"
#include "stringtable.h"
StringTable::StringTable(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;
count = 0;
}
StringTable::~StringTable()
{
unsigned i;
// Zero out dangling pointers to help garbage collector.
// Should zero out StringEntry's too.
for (i = 0; i < count; i++)
table[i] = NULL;
mem.free(table);
table = NULL;
}
struct StringEntry
{
StringEntry *left;
StringEntry *right;
hash_t hash;
StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len);
};
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
{
StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
return se;
}
void **StringTable::search(const dchar *s, unsigned len)
{
hash_t hash;
unsigned u;
int cmp;
StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len);
u = hash % tabledim;
se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u);
while (*se)
{
cmp = (*se)->hash - hash;
if (cmp == 0)
{
cmp = (*se)->value.lstring.len() - len;
if (cmp == 0)
{
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
if (cmp == 0)
break;
}
}
if (cmp < 0)
se = &(*se)->left;
else
se = &(*se)->right;
}
//printf("\treturn %p, %p\n",se, (*se));
return (void **)se;
}
StringValue *StringTable::lookup(const dchar *s, unsigned len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
if (se)
return &se->value;
else
return NULL;
}
StringValue *StringTable::update(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (!se) // not in table: so create new entry
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}
StringValue *StringTable::insert(const dchar *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
pse = (StringEntry **)search(s,len);
se = *pse;
if (se)
return NULL; // error: already in table
else
{
se = StringEntry::alloc(s, len);
*pse = se;
}
return &se->value;
}

48
dmd2/root/stringtable.h Normal file
View File

@@ -0,0 +1,48 @@
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef STRINGTABLE_H
#define STRINGTABLE_H
#if __SC__
#pragma once
#endif
#include "root.h"
#include "dchar.h"
#include "lstring.h"
struct StringValue
{
union
{ int intvalue;
void *ptrvalue;
dchar *string;
};
Lstring lstring;
};
struct StringTable : Object
{
void **table;
unsigned count;
unsigned tabledim;
StringTable(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len);
private:
void **search(const dchar *s, unsigned len);
};
#endif

View File

@@ -1,364 +1,361 @@
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "mars.h"
#include "init.h"
#include "identifier.h"
#include "attrib.h"
#include "dsymbol.h"
#include "scope.h"
#include "declaration.h"
#include "aggregate.h"
#include "module.h"
#include "id.h"
Scope *Scope::freelist = NULL;
void *Scope::operator new(size_t size)
{
if (freelist)
{
Scope *s = freelist;
freelist = s->enclosing;
//printf("freelist %p\n", s);
assert(s->flags & SCOPEfree);
s->flags &= ~SCOPEfree;
return s;
}
void *p = ::operator new(size);
//printf("new %p\n", p);
return p;
}
Scope::Scope()
{ // Create root scope
//printf("Scope::Scope() %p\n", this);
this->module = NULL;
this->scopesym = NULL;
this->sd = NULL;
this->enclosing = NULL;
this->parent = NULL;
this->sw = NULL;
this->tf = NULL;
this->tfOfTry = NULL;
this->tinst = NULL;
this->sbreak = NULL;
this->scontinue = NULL;
this->fes = NULL;
this->structalign = global.structalign;
this->func = NULL;
this->slabel = NULL;
this->linkage = LINKd;
this->protection = PROTpublic;
this->explicitProtection = 0;
this->stc = 0;
this->offset = 0;
this->inunion = 0;
this->incontract = 0;
this->nofree = 0;
this->noctor = 0;
this->noaccesscheck = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->callSuper = 0;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
}
Scope::Scope(Scope *enclosing)
{
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
assert(!(enclosing->flags & SCOPEfree));
this->module = enclosing->module;
this->func = enclosing->func;
this->parent = enclosing->parent;
this->scopesym = NULL;
this->sd = NULL;
this->sw = enclosing->sw;
this->tf = enclosing->tf;
this->tfOfTry = enclosing->tfOfTry;
this->tinst = enclosing->tinst;
this->sbreak = enclosing->sbreak;
this->scontinue = enclosing->scontinue;
this->fes = enclosing->fes;
this->structalign = enclosing->structalign;
this->enclosing = enclosing;
#ifdef DEBUG
if (enclosing->enclosing)
assert(!(enclosing->enclosing->flags & SCOPEfree));
if (this == enclosing->enclosing)
{
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
}
assert(this != enclosing->enclosing);
#endif
this->slabel = NULL;
this->linkage = enclosing->linkage;
this->protection = enclosing->protection;
this->explicitProtection = enclosing->explicitProtection;
this->stc = enclosing->stc;
this->offset = 0;
this->inunion = enclosing->inunion;
this->incontract = enclosing->incontract;
this->nofree = 0;
this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
assert(this != enclosing);
}
Scope *Scope::createGlobal(Module *module)
{
Scope *sc;
sc = new Scope();
sc->module = module;
sc->scopesym = new ScopeDsymbol();
sc->scopesym->symtab = new DsymbolTable();
// Add top level package as member of this global scope
Dsymbol *m = module;
while (m->parent)
m = m->parent;
m->addMember(NULL, sc->scopesym, 1);
m->parent = NULL; // got changed by addMember()
// Create the module scope underneath the global scope
sc = sc->push(module);
sc->parent = module;
return sc;
}
Scope *Scope::push()
{
//printf("Scope::push()\n");
Scope *s = new Scope(this);
assert(this != s);
return s;
}
Scope *Scope::push(ScopeDsymbol *ss)
{
//printf("Scope::push(%s)\n", ss->toChars());
Scope *s = push();
s->scopesym = ss;
return s;
}
Scope *Scope::pop()
{
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
Scope *enc = enclosing;
if (enclosing)
enclosing->callSuper |= callSuper;
if (!nofree)
{ enclosing = freelist;
freelist = this;
flags |= SCOPEfree;
}
return enc;
}
void Scope::mergeCallSuper(Loc loc, unsigned cs)
{
// This does a primitive flow analysis to support the restrictions
// regarding when and how constructors can appear.
// It merges the results of two paths.
// The two paths are callSuper and cs; the result is merged into callSuper.
if (cs != callSuper)
{ int a;
int b;
callSuper |= cs & (CSXany_ctor | CSXlabel);
if (cs & CSXreturn)
{
}
else if (callSuper & CSXreturn)
{
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
}
else
{
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
if (a != b)
error(loc, "one path skips constructor");
callSuper |= cs;
}
}
}
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
{ Dsymbol *s;
Scope *sc;
//printf("Scope::search(%p, '%s')\n", this, ident->toChars());
if (ident == Id::empty)
{
// Look for module scope
for (sc = this; sc; sc = sc->enclosing)
{
assert(sc != sc->enclosing);
if (sc->scopesym)
{
s = sc->scopesym->isModule();
if (s)
{
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
if (pscopesym)
*pscopesym = sc->scopesym;
return s;
}
}
}
return NULL;
}
for (sc = this; sc; sc = sc->enclosing)
{
assert(sc != sc->enclosing);
if (sc->scopesym)
{
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
s = sc->scopesym->search(loc, ident, 0);
if (s)
{
if ((global.params.warnings ||
global.params.Dversion > 1) &&
ident == Id::length &&
sc->scopesym->isArrayScopeSymbol() &&
sc->enclosing &&
sc->enclosing->search(loc, ident, NULL))
{
// WTF ?
if (global.params.warnings)
fprintf(stdmsg, "warning - ");
error(s->loc, "array 'length' hides other 'length' name in outer scope");
}
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
if (pscopesym)
*pscopesym = sc->scopesym;
return s;
}
}
}
return NULL;
}
Dsymbol *Scope::insert(Dsymbol *s)
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
if (sc->scopesym)
{
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
if (!sc->scopesym->symtab)
sc->scopesym->symtab = new DsymbolTable();
return sc->scopesym->symtab->insert(s);
}
}
assert(0);
return NULL;
}
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
ClassDeclaration *Scope::getClassScope()
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
ClassDeclaration *cd;
if (sc->scopesym)
{
cd = sc->scopesym->isClassDeclaration();
if (cd)
return cd;
}
}
return NULL;
}
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
AggregateDeclaration *Scope::getStructClassScope()
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
AggregateDeclaration *ad;
if (sc->scopesym)
{
ad = sc->scopesym->isClassDeclaration();
if (ad)
return ad;
else
{ ad = sc->scopesym->isStructDeclaration();
if (ad)
return ad;
}
}
}
return NULL;
}
/*******************************************
* For TemplateDeclarations, we need to remember the Scope
* where it was declared. So mark the Scope as not
* to be free'd.
*/
void Scope::setNoFree()
{ Scope *sc;
//int i = 0;
//printf("Scope::setNoFree(this = %p)\n", this);
for (sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
sc->nofree = 1;
assert(!(flags & SCOPEfree));
//assert(sc != sc->enclosing);
//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
//if (++i == 10)
//assert(0);
}
}
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "mars.h"
#include "init.h"
#include "identifier.h"
#include "attrib.h"
#include "dsymbol.h"
#include "scope.h"
#include "declaration.h"
#include "aggregate.h"
#include "module.h"
#include "id.h"
Scope *Scope::freelist = NULL;
void *Scope::operator new(size_t size)
{
if (freelist)
{
Scope *s = freelist;
freelist = s->enclosing;
//printf("freelist %p\n", s);
assert(s->flags & SCOPEfree);
s->flags &= ~SCOPEfree;
return s;
}
void *p = ::operator new(size);
//printf("new %p\n", p);
return p;
}
Scope::Scope()
{ // Create root scope
//printf("Scope::Scope() %p\n", this);
this->module = NULL;
this->scopesym = NULL;
this->sd = NULL;
this->enclosing = NULL;
this->parent = NULL;
this->sw = NULL;
this->enclosingFinally = NULL;
this->enclosingScopeExit = NULL;
this->tinst = NULL;
this->sbreak = NULL;
this->scontinue = NULL;
this->fes = NULL;
this->structalign = global.structalign;
this->func = NULL;
this->slabel = NULL;
this->linkage = LINKd;
this->protection = PROTpublic;
this->explicitProtection = 0;
this->stc = 0;
this->offset = 0;
this->inunion = 0;
this->incontract = 0;
this->nofree = 0;
this->noctor = 0;
this->noaccesscheck = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->callSuper = 0;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
}
Scope::Scope(Scope *enclosing)
{
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
assert(!(enclosing->flags & SCOPEfree));
this->module = enclosing->module;
this->func = enclosing->func;
this->parent = enclosing->parent;
this->scopesym = NULL;
this->sd = NULL;
this->sw = enclosing->sw;
this->enclosingFinally = enclosing->enclosingFinally;
this->enclosingScopeExit = enclosing->enclosingScopeExit;
this->tinst = enclosing->tinst;
this->sbreak = enclosing->sbreak;
this->scontinue = enclosing->scontinue;
this->fes = enclosing->fes;
this->structalign = enclosing->structalign;
this->enclosing = enclosing;
#ifdef DEBUG
if (enclosing->enclosing)
assert(!(enclosing->enclosing->flags & SCOPEfree));
if (this == enclosing->enclosing)
{
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
}
assert(this != enclosing->enclosing);
#endif
this->slabel = NULL;
this->linkage = enclosing->linkage;
this->protection = enclosing->protection;
this->explicitProtection = enclosing->explicitProtection;
this->stc = enclosing->stc;
this->offset = 0;
this->inunion = enclosing->inunion;
this->incontract = enclosing->incontract;
this->nofree = 0;
this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
assert(this != enclosing);
}
Scope *Scope::createGlobal(Module *module)
{
Scope *sc;
sc = new Scope();
sc->module = module;
sc->scopesym = new ScopeDsymbol();
sc->scopesym->symtab = new DsymbolTable();
// Add top level package as member of this global scope
Dsymbol *m = module;
while (m->parent)
m = m->parent;
m->addMember(NULL, sc->scopesym, 1);
m->parent = NULL; // got changed by addMember()
// Create the module scope underneath the global scope
sc = sc->push(module);
sc->parent = module;
return sc;
}
Scope *Scope::push()
{
//printf("Scope::push()\n");
Scope *s = new Scope(this);
assert(this != s);
return s;
}
Scope *Scope::push(ScopeDsymbol *ss)
{
//printf("Scope::push(%s)\n", ss->toChars());
Scope *s = push();
s->scopesym = ss;
return s;
}
Scope *Scope::pop()
{
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
Scope *enc = enclosing;
if (enclosing)
enclosing->callSuper |= callSuper;
if (!nofree)
{ enclosing = freelist;
freelist = this;
flags |= SCOPEfree;
}
return enc;
}
void Scope::mergeCallSuper(Loc loc, unsigned cs)
{
// This does a primitive flow analysis to support the restrictions
// regarding when and how constructors can appear.
// It merges the results of two paths.
// The two paths are callSuper and cs; the result is merged into callSuper.
if (cs != callSuper)
{ int a;
int b;
callSuper |= cs & (CSXany_ctor | CSXlabel);
if (cs & CSXreturn)
{
}
else if (callSuper & CSXreturn)
{
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
}
else
{
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
if (a != b)
error(loc, "one path skips constructor");
callSuper |= cs;
}
}
}
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
{ Dsymbol *s;
Scope *sc;
//printf("Scope::search(%p, '%s')\n", this, ident->toChars());
if (ident == Id::empty)
{
// Look for module scope
for (sc = this; sc; sc = sc->enclosing)
{
assert(sc != sc->enclosing);
if (sc->scopesym)
{
s = sc->scopesym->isModule();
if (s)
{
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
if (pscopesym)
*pscopesym = sc->scopesym;
return s;
}
}
}
return NULL;
}
for (sc = this; sc; sc = sc->enclosing)
{
assert(sc != sc->enclosing);
if (sc->scopesym)
{
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
s = sc->scopesym->search(loc, ident, 0);
if (s)
{
if ((global.params.warnings ||
global.params.Dversion > 1) &&
ident == Id::length &&
sc->scopesym->isArrayScopeSymbol() &&
sc->enclosing &&
sc->enclosing->search(loc, ident, NULL))
{
warning(s->loc, "array 'length' hides other 'length' name in outer scope");
}
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
if (pscopesym)
*pscopesym = sc->scopesym;
return s;
}
}
}
return NULL;
}
Dsymbol *Scope::insert(Dsymbol *s)
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
if (sc->scopesym)
{
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
if (!sc->scopesym->symtab)
sc->scopesym->symtab = new DsymbolTable();
return sc->scopesym->symtab->insert(s);
}
}
assert(0);
return NULL;
}
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
ClassDeclaration *Scope::getClassScope()
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
ClassDeclaration *cd;
if (sc->scopesym)
{
cd = sc->scopesym->isClassDeclaration();
if (cd)
return cd;
}
}
return NULL;
}
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
AggregateDeclaration *Scope::getStructClassScope()
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
AggregateDeclaration *ad;
if (sc->scopesym)
{
ad = sc->scopesym->isClassDeclaration();
if (ad)
return ad;
else
{ ad = sc->scopesym->isStructDeclaration();
if (ad)
return ad;
}
}
}
return NULL;
}
/*******************************************
* For TemplateDeclarations, we need to remember the Scope
* where it was declared. So mark the Scope as not
* to be free'd.
*/
void Scope::setNoFree()
{ Scope *sc;
//int i = 0;
//printf("Scope::setNoFree(this = %p)\n", this);
for (sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
sc->nofree = 1;
assert(!(flags & SCOPEfree));
//assert(sc != sc->enclosing);
//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
//if (++i == 10)
//assert(0);
}
}

View File

@@ -1,119 +1,125 @@
// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_SCOPE_H
#define DMD_SCOPE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
struct Dsymbol;
struct ScopeDsymbol;
struct Array;
struct Identifier;
struct Module;
struct Statement;
struct SwitchStatement;
struct TryFinallyStatement;
struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct EnclosingHandler;
struct AnonDeclaration;
#if __GNUC__
#include "dsymbol.h" // PROT
#include "mars.h" // LINK
#else
enum LINK;
enum PROT;
#endif
struct Scope
{
Scope *enclosing; // enclosing Scope
Module *module; // Root module
ScopeDsymbol *scopesym; // current symbol
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
// sd gets the addMember()
FuncDeclaration *func; // function we are in
Dsymbol *parent; // parent to use
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
TryFinallyStatement *tf; // enclosing try finally statement; set inside its finally block
EnclosingHandler *tfOfTry; // enclosing try-finally, volatile or synchronized statement; set inside its try or body block
TemplateInstance *tinst; // enclosing template instance
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
unsigned structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
enum PROT protection; // protection for class members
int explicitProtection; // set if in an explicit protection attribute
unsigned stc; // storage class
unsigned flags;
#define SCOPEctor 1 // constructor type
#define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
OutBuffer *docbuf; // buffer for documentation output
static Scope *freelist;
static void *operator new(size_t sz);
static Scope *createGlobal(Module *module);
Scope();
Scope(Module *module);
Scope(Scope *enclosing);
Scope *push();
Scope *push(ScopeDsymbol *ss);
Scope *pop();
void mergeCallSuper(Loc loc, unsigned cs);
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
Dsymbol *insert(Dsymbol *s);
ClassDeclaration *getClassScope();
AggregateDeclaration *getStructClassScope();
void setNoFree();
};
#endif /* DMD_SCOPE_H */
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_SCOPE_H
#define DMD_SCOPE_H
#ifdef __DMC__
#pragma once
#endif
struct Dsymbol;
struct ScopeDsymbol;
struct Array;
struct Identifier;
struct Module;
struct Statement;
struct SwitchStatement;
struct TryFinallyStatement;
struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct TemplateInstance;
#if IN_LLVM
struct EnclosingHandler;
struct AnonDeclaration;
#endif
#if __GNUC__
// Requires a full definition for PROT and LINK
#include "dsymbol.h" // PROT
#include "mars.h" // LINK
#else
enum LINK;
enum PROT;
#endif
struct Scope
{
Scope *enclosing; // enclosing Scope
Module *module; // Root module
ScopeDsymbol *scopesym; // current symbol
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
// sd gets the addMember()
FuncDeclaration *func; // function we are in
Dsymbol *parent; // parent to use
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
TemplateInstance *tinst; // enclosing template instance
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
unsigned structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
enum PROT protection; // protection for class members
int explicitProtection; // set if in an explicit protection attribute
unsigned stc; // storage class
unsigned flags;
#define SCOPEctor 1 // constructor type
#define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
OutBuffer *docbuf; // buffer for documentation output
static Scope *freelist;
static void *operator new(size_t sz);
static Scope *createGlobal(Module *module);
Scope();
Scope(Module *module);
Scope(Scope *enclosing);
Scope *push();
Scope *push(ScopeDsymbol *ss);
Scope *pop();
void mergeCallSuper(Loc loc, unsigned cs);
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
Dsymbol *insert(Dsymbol *s);
ClassDeclaration *getClassScope();
AggregateDeclaration *getStructClassScope();
void setNoFree();
};
#endif /* DMD_SCOPE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@
#include "scope.h"
#include "template.h"
/********************************* AttribDeclaration ****************************/
StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
@@ -47,6 +48,10 @@ void StaticAssert::semantic(Scope *sc)
{
}
#include "scope.h"
#include "template.h"
#include "declaration.h"
void StaticAssert::semantic2(Scope *sc)
{
Expression *e;
@@ -67,11 +72,12 @@ void StaticAssert::semantic2(Scope *sc)
error("%s", buf.toChars());
}
else
error("is false");
if(sc->tinst)
error("(%s) is false", exp->toChars());
if(sc->tinst)
sc->tinst->printInstantiationTrace();
if (!global.gag)
fatal();
if (!global.gag) {
fatal();
}
}
else if (!e->isBool(TRUE))
{

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -19,6 +19,7 @@
#include "module.h"
#include "id.h"
#include "statement.h"
#include "template.h"
/********************************* AggregateDeclaration ****************************/
@@ -41,13 +42,20 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
aggNew = NULL;
aggDelete = NULL;
#if IN_DMD
stag = NULL;
sinit = NULL;
#endif
scope = NULL;
dtor = NULL;
isnested = 0;
vthis = NULL;
#if DMDV2
ctor = NULL;
defaultCtor = NULL;
aliasthis = NULL;
#endif
dtor = NULL;
}
enum PROT AggregateDeclaration::prot()
@@ -132,31 +140,21 @@ int AggregateDeclaration::isDeprecated()
* Align sizes of 0, as we may not know array sizes yet.
*/
void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset)
void AggregateDeclaration::alignmember(
unsigned salign, // struct alignment that is in effect
unsigned size, // alignment requirement of field
unsigned *poffset)
{
//printf("salign = %d, size = %d, offset = %d\n",salign,size,*poffset);
//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
if (salign > 1)
{ int sa;
switch (size)
{ case 1:
break;
case 2:
case_2:
*poffset = (*poffset + 1) & ~1; // align to word
break;
case 3:
case 4:
if (salign == 2)
goto case_2;
*poffset = (*poffset + 3) & ~3; // align to dword
break;
default:
*poffset = (*poffset + size - 1) & ~(size - 1);
break;
}
{
assert(size != 3);
int sa = size;
if (sa == 0 || salign < sa)
sa = salign;
*poffset = (*poffset + sa - 1) & ~(sa - 1);
}
//printf("result = %d\n",*poffset);
//printf("result = %d\n",offset);
}
@@ -171,13 +169,18 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
// Check for forward referenced types which will fail the size() call
Type *t = v->type->toBasetype();
if (v->storage_class & STCref)
{ // References are the size of a pointer
t = Type::tvoidptr;
}
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
{ TypeStruct *ts = (TypeStruct *)t;
#if DMDV2
if (ts->sym == this)
{
error("cannot have field %s with same struct type", v->toChars());
}
#endif
if (ts->sym->sizeok != 1)
{
@@ -191,9 +194,9 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
return;
}
memsize = v->type->size(loc);
memalignsize = v->type->alignsize();
xalign = v->type->memalign(sc->structalign);
memsize = t->size(loc);
memalignsize = t->alignsize();
xalign = t->memalign(sc->structalign);
alignmember(xalign, memalignsize, &sc->offset);
v->offset = sc->offset;
sc->offset += memsize;
@@ -211,15 +214,28 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
}
/****************************************
* Returns !=0 if there's an extra member which is the 'this'
* pointer to the enclosing context (enclosing aggregate or function)
*/
int AggregateDeclaration::isNested()
{
return isnested;
}
/********************************* StructDeclaration ****************************/
StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
: AggregateDeclaration(loc, id)
{
zeroInit = 0; // assume false until we do semantic processing
#if DMDV2
hasIdentityAssign = 0;
cpctor = NULL;
postblit = NULL;
#endif
// For forward references
type = new TypeStruct(this);
@@ -277,24 +293,64 @@ void StructDeclaration::semantic(Scope *sc)
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
if (storage_class & STCinvariant)
#if DMDV2
if (storage_class & STCimmutable)
type = type->invariantOf();
else if (storage_class & STCconst)
type = type->constOf();
else if (storage_class & STCshared)
type = type->sharedOf();
#endif
if (sizeok == 0) // if not already done the addMember step
{
int hasfunctions = 0;
for (i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
s->addMember(sc, this, 1);
if (s->isFuncDeclaration())
hasfunctions = 1;
}
// If nested struct, add in hidden 'this' pointer to outer scope
if (hasfunctions && !(storage_class & STCstatic))
{ Dsymbol *s = toParent2();
if (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
TemplateInstance *ti;
if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
{ isnested = 1;
Type *t;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad = fd->isMember2();
if (ad)
t = ad->handle;
else
t = Type::tvoidptr;
}
else
assert(0);
if (t->ty == Tstruct)
t = Type::tvoidptr; // t should not be a ref type
assert(!vthis);
vthis = new ThisDeclaration(loc, t);
//vthis->storage_class |= STCref;
members->push(vthis);
}
}
}
}
sizeok = 0;
sc2 = sc->push(this);
sc2->stc &= storage_class & (STCconst | STCinvariant);
sc2->stc &= storage_class & STC_TYPECTOR;
sc2->parent = this;
if (isUnionDeclaration())
sc2->inunion = 1;
@@ -314,6 +370,14 @@ void StructDeclaration::semantic(Scope *sc)
break;
}
#endif
Type *t;
if (s->isDeclaration() &&
(t = s->isDeclaration()->type) != NULL &&
t->toBasetype()->ty == Tstruct)
{ StructDeclaration *sd = (StructDeclaration *)t->toDsymbol(sc);
if (sd->isnested)
error("inner struct %s cannot be a field", sd->toChars());
}
}
/* The TypeInfo_Struct is expecting an opEquals and opCmp with
@@ -349,9 +413,9 @@ void StructDeclaration::semantic(Scope *sc)
Dsymbol *s = search_function(this, id);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
if (!fd)
{ fd = fdx->overloadExactMatch(tfeq);
{ fd = fdx->overloadExactMatch(tfeq, getModule());
if (fd)
{ // Create the thunk, fdptr
FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
@@ -373,11 +437,12 @@ void StructDeclaration::semantic(Scope *sc)
id = Id::cmp;
}
#if DMDV2
dtor = buildDtor(sc2);
postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2);
buildOpAssign(sc2);
#endif
sc2->pop();
@@ -429,7 +494,7 @@ void StructDeclaration::semantic(Scope *sc)
}
else
{
if (!vd->type->isZeroInit())
if (!vd->type->isZeroInit(loc))
{
zeroInit = 0;
break;
@@ -440,7 +505,9 @@ void StructDeclaration::semantic(Scope *sc)
/* Look for special member functions.
*/
ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
#if DMDV2
ctor = search(0, Id::ctor, 0);
#endif
inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0);
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);

File diff suppressed because it is too large Load Diff

View File

@@ -1,363 +1,381 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_TEMPLATE_H
#define DMD_TEMPLATE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include <string>
#include "root.h"
#include "arraytypes.h"
#include "dsymbol.h"
#include "mtype.h"
struct OutBuffer;
struct Identifier;
struct TemplateInstance;
struct TemplateParameter;
struct TemplateTypeParameter;
struct TemplateThisParameter;
struct TemplateValueParameter;
struct TemplateAliasParameter;
struct TemplateTupleParameter;
struct Type;
struct TypeTypeof;
struct Scope;
struct Expression;
struct AliasDeclaration;
struct FuncDeclaration;
struct HdrGenState;
enum MATCH;
struct Tuple : Object
{
Objects objects;
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
};
struct TemplateDeclaration : ScopeDsymbol
{
TemplateParameters *parameters; // array of TemplateParameter's
TemplateParameters *origParameters; // originals for Ddoc
Expression *constraint;
Array instances; // array of TemplateInstance's
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list
Scope *scope;
Dsymbol *onemember; // if !=NULL then one member of this template
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
Expression *constraint, Array *decldefs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
char *toChars();
void emitComment(Scope *sc);
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
MATCH leastAsSpecialized(TemplateDeclaration *td2);
MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
TemplateDeclaration *isTemplateDeclaration() { return this; }
TemplateTupleParameter *isVariadic();
int isOverloadable();
// LDC
std::string intrinsicName;
};
struct TemplateParameter
{
/* For type-parameter:
* template Foo(ident) // specType is set to NULL
* template Foo(ident : specType)
* For value-parameter:
* template Foo(valType ident) // specValue is set to NULL
* template Foo(valType ident : specValue)
* For alias-parameter:
* template Foo(alias ident)
* For this-parameter:
* template Foo(this ident)
*/
Loc loc;
Identifier *ident;
Declaration *sparam;
TemplateParameter(Loc loc, Identifier *ident);
virtual TemplateTypeParameter *isTemplateTypeParameter();
virtual TemplateValueParameter *isTemplateValueParameter();
virtual TemplateAliasParameter *isTemplateAliasParameter();
virtual TemplateThisParameter *isTemplateThisParameter();
virtual TemplateTupleParameter *isTemplateTupleParameter();
virtual TemplateParameter *syntaxCopy() = 0;
virtual void declareParameter(Scope *sc) = 0;
virtual void semantic(Scope *) = 0;
virtual void print(Object *oarg, Object *oded) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
virtual Object *specialization() = 0;
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
/* If TemplateParameter's match as far as overloading goes.
*/
virtual int overloadMatch(TemplateParameter *) = 0;
/* Match actual argument against parameter.
*/
virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
/* Create dummy argument based on parameter.
*/
virtual void *dummyArg() = 0;
};
struct TemplateTypeParameter : TemplateParameter
{
/* Syntax:
* ident : specType = defaultType
*/
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
TemplateTypeParameter *isTemplateTypeParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
#if DMDV2
struct TemplateThisParameter : TemplateTypeParameter
{
/* Syntax:
* this ident : specType = defaultType
*/
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
TemplateThisParameter *isTemplateThisParameter();
TemplateParameter *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
struct TemplateValueParameter : TemplateParameter
{
/* Syntax:
* valType ident : specValue = defaultValue
*/
Type *valType;
Expression *specValue;
Expression *defaultValue;
static Expression *edummy;
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
TemplateValueParameter *isTemplateValueParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
struct TemplateAliasParameter : TemplateParameter
{
/* Syntax:
* specType ident : specAlias = defaultAlias
*/
Type *specType;
Object *specAlias;
Object *defaultAlias;
static Dsymbol *sdummy;
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
TemplateAliasParameter *isTemplateAliasParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
struct TemplateTupleParameter : TemplateParameter
{
/* Syntax:
* ident ...
*/
TemplateTupleParameter(Loc loc, Identifier *ident);
TemplateTupleParameter *isTemplateTupleParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
struct TemplateInstance : ScopeDsymbol
{
/* Given:
* foo!(args) =>
* name = foo
* tiargs = args
*/
Identifier *name;
//Array idents;
Objects *tiargs; // Array of Types/Expressions of template
// instance arguments [int*, char, 10*10]
Objects tdtypes; // Array of Types/Expressions corresponding
// to TemplateDeclaration.parameters
// [int, char, 100]
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
TemplateInstance *inst; // refer to existing instance
ScopeDsymbol *argsym; // argument symbol table
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
WithScopeSymbol *withsym; // if a member of a with statement
int semanticdone; // has semantic() been done?
int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context
int errors; // 1 if compiled with errors
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
will be emitted in the output or not before the symbol
is used. This can be different from getModule(). */
Module * objFileModule;
#endif
TemplateInstance(Loc loc, Identifier *temp_id);
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
static Objects *arraySyntaxCopy(Objects *objs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *toAlias(); // resolve real symbol
const char *kind();
int oneMember(Dsymbol **ps);
char *toChars();
char *mangle();
void toObjFile(int multiobj); // compile to .obj file
// Internal
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
void semanticTiargs(Scope *sc);
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
TemplateDeclaration *findBestMatch(Scope *sc);
void declareParameters(Scope *sc);
int isNested(Objects *tiargs);
Identifier *genIdent();
TemplateInstance *isTemplateInstance() { return this; }
AliasDeclaration *isAliasDeclaration();
// LDC
TemplateInstance *tinst; // enclosing template instance
Module* tmodule; // module from outermost enclosing template instantiation
void printInstantiationTrace();
};
struct TemplateMixin : TemplateInstance
{
Array *idents;
Type *tqual;
Scope *scope; // for forward referencing
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
const char *kind();
int oneMember(Dsymbol **ps);
int hasPointers();
char *toChars();
char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toObjFile(int multiobj); // compile to .obj file
TemplateMixin *isTemplateMixin() { return this; }
};
Expression *isExpression(Object *o);
Dsymbol *isDsymbol(Object *o);
Type *isType(Object *o);
Tuple *isTuple(Object *o);
Type *getType(Object *o);
Dsymbol *getDsymbol(Object *o);
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
#endif /* DMD_TEMPLATE_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_TEMPLATE_H
#define DMD_TEMPLATE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#if IN_LLVM
#include <string>
#endif
#include "root.h"
#include "arraytypes.h"
#include "dsymbol.h"
#if IN_LLVM
#include "mtype.h"
#endif
struct OutBuffer;
struct Identifier;
struct TemplateInstance;
struct TemplateParameter;
struct TemplateTypeParameter;
struct TemplateThisParameter;
struct TemplateValueParameter;
struct TemplateAliasParameter;
struct TemplateTupleParameter;
struct Type;
struct TypeTypeof;
struct Scope;
struct Expression;
struct AliasDeclaration;
struct FuncDeclaration;
struct HdrGenState;
enum MATCH;
struct Tuple : Object
{
Objects objects;
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
};
struct TemplateDeclaration : ScopeDsymbol
{
TemplateParameters *parameters; // array of TemplateParameter's
TemplateParameters *origParameters; // originals for Ddoc
Expression *constraint;
Array instances; // array of TemplateInstance's
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list
Scope *scope;
Dsymbol *onemember; // if !=NULL then one member of this template
int literal; // this template declaration is a literal
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
Expression *constraint, Array *decldefs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
char *toChars();
void emitComment(Scope *sc);
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
MATCH leastAsSpecialized(TemplateDeclaration *td2);
MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
TemplateDeclaration *isTemplateDeclaration() { return this; }
TemplateTupleParameter *isVariadic();
int isOverloadable();
#if IN_LLVM
// LDC
std::string intrinsicName;
#endif
};
struct TemplateParameter
{
/* For type-parameter:
* template Foo(ident) // specType is set to NULL
* template Foo(ident : specType)
* For value-parameter:
* template Foo(valType ident) // specValue is set to NULL
* template Foo(valType ident : specValue)
* For alias-parameter:
* template Foo(alias ident)
* For this-parameter:
* template Foo(this ident)
*/
Loc loc;
Identifier *ident;
Declaration *sparam;
TemplateParameter(Loc loc, Identifier *ident);
virtual TemplateTypeParameter *isTemplateTypeParameter();
virtual TemplateValueParameter *isTemplateValueParameter();
virtual TemplateAliasParameter *isTemplateAliasParameter();
#if DMDV2
virtual TemplateThisParameter *isTemplateThisParameter();
#endif
virtual TemplateTupleParameter *isTemplateTupleParameter();
virtual TemplateParameter *syntaxCopy() = 0;
virtual void declareParameter(Scope *sc) = 0;
virtual void semantic(Scope *) = 0;
virtual void print(Object *oarg, Object *oded) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
virtual Object *specialization() = 0;
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
/* If TemplateParameter's match as far as overloading goes.
*/
virtual int overloadMatch(TemplateParameter *) = 0;
/* Match actual argument against parameter.
*/
virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
/* Create dummy argument based on parameter.
*/
virtual void *dummyArg() = 0;
};
struct TemplateTypeParameter : TemplateParameter
{
/* Syntax:
* ident : specType = defaultType
*/
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
TemplateTypeParameter *isTemplateTypeParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
#if DMDV2
struct TemplateThisParameter : TemplateTypeParameter
{
/* Syntax:
* this ident : specType = defaultType
*/
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
TemplateThisParameter *isTemplateThisParameter();
TemplateParameter *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
struct TemplateValueParameter : TemplateParameter
{
/* Syntax:
* valType ident : specValue = defaultValue
*/
Type *valType;
Expression *specValue;
Expression *defaultValue;
static Expression *edummy;
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
TemplateValueParameter *isTemplateValueParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
struct TemplateAliasParameter : TemplateParameter
{
/* Syntax:
* specType ident : specAlias = defaultAlias
*/
Type *specType;
Object *specAlias;
Object *defaultAlias;
static Dsymbol *sdummy;
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
TemplateAliasParameter *isTemplateAliasParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
struct TemplateTupleParameter : TemplateParameter
{
/* Syntax:
* ident ...
*/
TemplateTupleParameter(Loc loc, Identifier *ident);
TemplateTupleParameter *isTemplateTupleParameter();
TemplateParameter *syntaxCopy();
void declareParameter(Scope *sc);
void semantic(Scope *);
void print(Object *oarg, Object *oded);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
void *dummyArg();
};
struct TemplateInstance : ScopeDsymbol
{
/* Given:
* foo!(args) =>
* name = foo
* tiargs = args
*/
Identifier *name;
//Array idents;
Objects *tiargs; // Array of Types/Expressions of template
// instance arguments [int*, char, 10*10]
Objects tdtypes; // Array of Types/Expressions corresponding
// to TemplateDeclaration.parameters
// [int, char, 100]
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
TemplateInstance *inst; // refer to existing instance
TemplateInstance *tinst; // enclosing template instance
ScopeDsymbol *argsym; // argument symbol table
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
WithScopeSymbol *withsym; // if a member of a with statement
int semanticdone; // has semantic() been done?
int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context
int errors; // 1 if compiled with errors
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
will be emitted in the output or not before the symbol
is used. This can be different from getModule(). */
Module * objFileModule;
#endif
TemplateInstance(Loc loc, Identifier *temp_id);
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
static Objects *arraySyntaxCopy(Objects *objs);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *toAlias(); // resolve real symbol
const char *kind();
int oneMember(Dsymbol **ps);
char *toChars();
char *mangle();
void printInstantiationTrace();
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
#endif
// Internal
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
void semanticTiargs(Scope *sc);
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
TemplateDeclaration *findBestMatch(Scope *sc);
void declareParameters(Scope *sc);
int hasNestedArgs(Objects *tiargs);
Identifier *genIdent();
TemplateInstance *isTemplateInstance() { return this; }
AliasDeclaration *isAliasDeclaration();
#if IN_LLVM
// LDC
Module* tmodule; // module from outermost enclosing template instantiation
Module* emittedInModule; // which module this template instance has been emitted in
void codegen(Ir*);
#endif
};
struct TemplateMixin : TemplateInstance
{
Array *idents;
Type *tqual;
Scope *scope; // for forward referencing
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
const char *kind();
int oneMember(Dsymbol **ps);
int hasPointers();
char *toChars();
char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
#endif
TemplateMixin *isTemplateMixin() { return this; }
#if IN_LLVM
void codegen(Ir*);
#endif
};
Expression *isExpression(Object *o);
Dsymbol *isDsymbol(Object *o);
Type *isType(Object *o);
Tuple *isTuple(Object *o);
Type *getType(Object *o);
Dsymbol *getDsymbol(Object *o);
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
#endif /* DMD_TEMPLATE_H */

View File

@@ -41,5 +41,6 @@
#include "id.h"
#include "cond.h"
#include "version.h"
#include "lib.h"
#endif /* DMD_TOTAL_H */

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -12,25 +12,9 @@
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <complex.h>
#include <math.h>
#if IN_GCC
// Issues with using -include total.h (defines integer_t) and then complex.h fails...
#undef integer_t
#endif
#ifdef __APPLE__
#define integer_t dmd_integer_t
#endif
#if IN_GCC || IN_LLVM
#include "mem.h"
#elif _WIN32
#include "..\root\mem.h"
#elif linux
#include "../root/mem.h"
#endif
#include "rmem.h"
//#include "port.h"
#include "mtype.h"
@@ -53,6 +37,8 @@
#define LOGSEMANTIC 0
#if DMDV2
/************************************************
* Delegate to be passed to overloadApply() that looks
* for virtual functions.
@@ -197,7 +183,7 @@ Expression *TraitsExp::semantic(Scope *sc)
e = isExpression(o);
Dsymbol *s = isDsymbol(o);
if (t)
e = new TypeDotIdExp(loc, t, id);
e = typeDotIdExp(loc, t, id);
else if (e)
e = new DotIdExp(loc, e, id);
else if (s)
@@ -212,13 +198,10 @@ Expression *TraitsExp::semantic(Scope *sc)
if (ident == Id::hasMember)
{ /* Take any errors as meaning it wasn't found
*/
unsigned errors = global.errors;
global.gag++;
e = e->semantic(sc);
global.gag--;
if (errors != global.errors)
{ if (global.gag == 0)
global.errors = errors;
e = e->trySemantic(sc);
if (!e)
{ if (global.gag)
global.errors++;
goto Lfalse;
}
else
@@ -255,7 +238,7 @@ Expression *TraitsExp::semantic(Scope *sc)
Pvirtuals p;
p.exps = exps;
p.e1 = e;
overloadApply(f, fpvirtuals, &p);
overloadApply(f->getModule(), f, fpvirtuals, &p);
TupleExp *tup = new TupleExp(loc, exps);
return tup->semantic(sc);
@@ -340,16 +323,15 @@ Expression *TraitsExp::semantic(Scope *sc)
for (size_t i = 0; i < dim; i++)
{ Object *o = (Object *)args->data[i];
Type *t;
Expression *e;
Dsymbol *s;
unsigned errors = global.errors;
global.gag++;
t = isType(o);
Type *t = isType(o);
if (t)
{ t->resolve(loc, sc, &e, &t, &s);
{ Dsymbol *s;
t->resolve(loc, sc, &e, &t, &s);
if (t)
t->semantic(loc, sc);
else if (e)
@@ -438,3 +420,4 @@ Ltrue:
}
#endif

View File

@@ -1422,8 +1422,13 @@ bool hasUnalignedFields(Type* t)
{
t = t->toBasetype();
if (t->ty == Tsarray) {
#if DMDV2
assert(t->nextOf()->size() % t->nextOf()->alignsize() == 0);
return hasUnalignedFields(t->nextOf());
#else
assert(t->next->size() % t->next->alignsize() == 0);
return hasUnalignedFields(t->next);
#endif
} else if (t->ty != Tstruct)
return false;

View File

@@ -434,7 +434,11 @@ void TypeInfoEnumDeclaration::llvmDefine()
else
{
const LLType* memty = DtoType(sd->memtype);
#if DMDV2
LLConstant* C = llvm::ConstantInt::get(memty, sd->defaultval->toInteger(), !sd->memtype->isunsigned());
#else
LLConstant* C = llvm::ConstantInt::get(memty, sd->defaultval, !sd->memtype->isunsigned());
#endif
b.push_void_array(C, sd->memtype, sd);
}

View File

@@ -111,7 +111,11 @@ LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
"don't implement any interfaces");
VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
#if DMDV2
const llvm::Type* InterfaceTy = DtoType(idx->type->nextOf());
#else
const llvm::Type* InterfaceTy = DtoType(idx->type->next);
#endif
// create Interface[N]
const llvm::ArrayType* array_type = llvm::ArrayType::get(InterfaceTy,n);
@@ -328,7 +332,11 @@ llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instan
// start with the interface info
VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
#if DMDV2
Type* first = interfaces_idx->type->nextOf()->pointerTo();
#else
Type* first = interfaces_idx->type->next->pointerTo();
#endif
// index into the interfaces array
llvm::Constant* idxs[2] = {

View File

@@ -171,7 +171,11 @@ void IrTypeClass::addBaseClassData(
ArrayIter<BaseClass> it2(*base->vtblInterfaces);
VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
#if DMDV2
Type* first = interfaces_idx->type->nextOf()->pointerTo();
#else
Type* first = interfaces_idx->type->next->pointerTo();
#endif
// align offset
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);