Remerged dmd2 frontend using git subtree

This commit is contained in:
Alexey Prokhin
2012-04-05 11:10:48 +04:00
117 changed files with 107538 additions and 0 deletions

412
dmd2/access.c Normal file
View File

@@ -0,0 +1,412 @@
// Copyright (c) 1999-2012 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
{
if (smember->isDeclaration()->isStatic())
{
access_ret = smember->prot();
}
for (size_t i = 0; i < baseclasses->dim; i++)
{ BaseClass *b = (*baseclasses)[i];
enum PROT access = b->base->getAccess(smember);
switch (access)
{
case PROTnone:
break;
case PROTprivate:
access_ret = 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 (size_t i = 0; i < cdthis->baseclasses->dim; i++)
{ BaseClass *b = (*cdthis->baseclasses)[i];
enum PROT 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 (size_t i = 0; i < cdthis->baseclasses->dim; i++)
{ BaseClass *b = (*cdthis->baseclasses)[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 access2 = smember->prot();
result = access2 >= PROTpublic ||
hasPrivateAccess(f) ||
isFriendOf(cdscope) ||
(access2 == 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());
}
}
/****************************************
* 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 && getAccessModule() == cd->getAccessModule())
{
#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 && getAccessModule() == smember->getAccessModule())
{
#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->toPrettyChars());
}
#endif
if (!e)
{
if (d->prot() == PROTprivate && d->getAccessModule() != sc->module ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
{
error(loc, "%s %s is not accessible from module %s",
d->kind(), d->toPrettyChars(), sc->module->toChars());
}
}
else if (e->type->ty == Tclass)
{ // Do access check
ClassDeclaration *cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
if (e->op == TOKsuper)
{
ClassDeclaration *cd2 = sc->func->toParent()->isClassDeclaration();
if (cd2)
cd = cd2;
}
cd->accessCheck(loc, sc, d);
}
else if (e->type->ty == Tstruct)
{ // Do access check
StructDeclaration *cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
cd->accessCheck(loc, sc, d);
}
}

363
dmd2/aggregate.h Normal file
View File

@@ -0,0 +1,363 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 TypeInfoClassDeclaration;
struct VarDeclaration;
struct dt_t;
#if IN_LLVM
struct ClassInfoDeclaration;
namespace llvm
{
class Type;
class Value;
class Constant;
class ConstantStruct;
class GlobalVariable;
}
#endif
struct AggregateDeclaration : ScopeDsymbol
{
Type *type;
StorageClass 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
VarDeclarations fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
bool isdeprecated; // !=0 if deprecated
#if DMDV2
int isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
#endif
// 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
bool noDefaultCtor; // no default construction
#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 firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
int isDeprecated(); // is aggregate deprecated?
FuncDeclaration *buildDtor(Scope *sc);
int isNested();
int isExport();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
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; }
#if IN_LLVM
// Aggregates that wouldn't have gotten semantic3'ed if we weren't inlining set this flag.
bool availableExternally;
#endif
};
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
int hasIdentityEquals; // !=0 if has identity opEquals
FuncDeclaration *cpctor; // generated copy-constructor, if any
FuncDeclarations postblits; // Array of postblit functions
FuncDeclaration *postblit; // aggregate postblit
FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals
static FuncDeclaration *xerreq; // object.xopEquals
#endif
StructDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
Dsymbol *search(Loc, Identifier *ident, int flags);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
const char *kind();
void finalizeSize();
#if DMDV1
Expression *cloneMembers();
#endif
#if DMDV2
int needOpAssign();
int needOpEquals();
FuncDeclaration *buildOpAssign(Scope *sc);
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
#endif
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
FuncDeclarations vtbl; // for interfaces: Array of FuncDeclaration's
// making up the vtbl[]
size_t 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, FuncDeclarations *vtbl, int newinstance);
void copyBaseInterfaces(BaseClasses *);
};
#if DMDV2
#define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size
#define CLASSINFO_SIZE (0x3C+12+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;
static ClassDeclaration *throwable;
static ClassDeclaration *exception;
static ClassDeclaration *errorException;
ClassDeclaration *baseClass; // NULL only if this is Object
#if DMDV1
CtorDeclaration *ctor;
CtorDeclaration *defaultCtor; // default constructor
#endif
FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor;
Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[]
Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
BaseClasses *baseclasses; // Array of BaseClass's; first is super,
// rest are Interface's
size_t 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[]
TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
int com; // !=0 if this is a COM class (meaning
// it derives from IUnknown)
int isscope; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
#if DMDV1
int isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this class is nested
#endif
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);
virtual int isBaseInfoComplete();
Dsymbol *search(Loc, Identifier *ident, int flags);
Dsymbol *searchBase(Loc, Identifier *ident);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
#if DMDV1
int isNested();
#endif
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 isBaseInfoComplete();
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 */

79
dmd2/aliasthis.c Normal file
View File

@@ -0,0 +1,79 @@
// 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)
{
assert(ad->members);
Dsymbol *s = ad->search(loc, ident, 0);
if (!s)
{ s = sc->search(loc, ident, 0);
if (s)
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
else
::error(loc, "undefined identifier %s", ident->toChars());
}
else if (ad->aliasthis && s != ad->aliasthis)
error("there can be only one alias this");
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

165
dmd2/apply.c Normal file
View File

@@ -0,0 +1,165 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 "expression.h"
/**************************************
* An Expression tree walker that will visit each Expression e in the tree,
* in depth-first evaluation order, and call fp(e,param) on it.
* fp() signals whether the walking continues with its return value:
* Returns:
* 0 continue
* 1 done
* It's a bit slower than using virtual functions, but more encapsulated and less brittle.
* Creating an iterator for this would be much more complex.
*/
typedef int (*fp_t)(Expression *, void *);
int Expression::apply(fp_t fp, void *param)
{
return (*fp)(this, param);
}
/******************************
* Perform apply() on an array of Expressions.
*/
int arrayExpressionApply(Expressions *a, fp_t fp, void *param)
{
//printf("arrayExpressionApply(%p)\n", a);
if (a)
{
for (size_t i = 0; i < a->dim; i++)
{ Expression *e = (*a)[i];
if (e)
{
if (e->apply(fp, param))
return 1;
}
}
}
return 0;
}
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
}
int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
}
int UnaExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(*fp)(this, param);
}
int BinExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
e2->apply(fp, param) ||
(*fp)(this, param);
}
int AssertExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
(msg ? msg->apply(fp, param) : 0) ||
(*fp)(this, param);
}
int CallExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param);
}
int ArrayExp::apply(fp_t fp, void *param)
{
//printf("ArrayExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param);
}
int SliceExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(lwr ? lwr->apply(fp, param) : 0) ||
(upr ? upr->apply(fp, param) : 0) ||
(*fp)(this, param);
}
int ArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
(*fp)(this, param);
}
int AssocArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(keys, fp, param) ||
arrayExpressionApply(values, fp, param) ||
(*fp)(this, param);
}
int StructLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
(*fp)(this, param);
}
int TupleExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(exps, fp, param) ||
(*fp)(this, param);
}
int CondExp::apply(fp_t fp, void *param)
{
return econd->apply(fp, param) ||
e1->apply(fp, param) ||
e2->apply(fp, param) ||
(*fp)(this, param);
}

193
dmd2/argtypes.c Normal file
View File

@@ -0,0 +1,193 @@
// Compiler implementation of the D programming language
// Copyright (c) 2010-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/branches/dmd-1.x/src/argtypes.c
// 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"
#include "hdrgen.h"
/****************************************************
* This breaks a type down into 'simpler' types that can be passed to a function
* in registers, and returned in registers.
* It's highly platform dependent.
* Returning a tuple of zero length means the type cannot be passed/returned in registers.
*/
TypeTuple *Type::toArgTypes()
{
return NULL; // not valid for a parameter
}
TypeTuple *TypeBasic::toArgTypes()
{ Type *t1 = NULL;
Type *t2 = NULL;
switch (ty)
{
case Tvoid:
return NULL;
case Tbool:
case Tint8:
case Tuns8:
case Tint16:
case Tuns16:
case Tint32:
case Tuns32:
case Tfloat32:
case Tint64:
case Tuns64:
case Tfloat64:
case Tfloat80:
t1 = this;
break;
case Timaginary32:
t1 = Type::tfloat32;
break;
case Timaginary64:
t1 = Type::tfloat64;
break;
case Timaginary80:
t1 = Type::tfloat80;
break;
case Tcomplex32:
if (global.params.is64bit)
t1 = Type::tfloat64; // weird, eh?
else
{
t1 = Type::tfloat64;
t2 = Type::tfloat64;
}
break;
case Tcomplex64:
t1 = Type::tfloat64;
t2 = Type::tfloat64;
break;
case Tcomplex80:
t1 = Type::tfloat80;
t2 = Type::tfloat80;
break;
case Tascii:
t1 = Type::tuns8;
break;
case Twchar:
t1 = Type::tuns16;
break;
case Tdchar:
t1 = Type::tuns32;
break;
default: assert(0);
}
TypeTuple *t;
if (t1)
{
if (t2)
t = new TypeTuple(t1, t2);
else
t = new TypeTuple(t1);
}
else
t = new TypeTuple();
return t;
}
TypeTuple *TypeVector::toArgTypes()
{
return new TypeTuple(Type::tfloat64);
}
TypeTuple *TypeSArray::toArgTypes()
{
#if DMDV2
return new TypeTuple(); // pass on the stack for efficiency
#else
return new TypeTuple(Type::tvoidptr);
#endif
}
TypeTuple *TypeDArray::toArgTypes()
{
return new TypeTuple(); // pass on the stack for efficiency
}
TypeTuple *TypeAArray::toArgTypes()
{
return new TypeTuple(Type::tvoidptr);
}
TypeTuple *TypePointer::toArgTypes()
{
return new TypeTuple(this);
}
TypeTuple *TypeDelegate::toArgTypes()
{
return new TypeTuple(); // pass on the stack for efficiency
}
TypeTuple *TypeStruct::toArgTypes()
{
d_uns64 sz = size(0);
assert(sz < 0xFFFFFFFF);
switch ((unsigned)sz)
{
case 1:
return new TypeTuple(Type::tint8);
case 2:
return new TypeTuple(Type::tint16);
case 4:
return new TypeTuple(Type::tint32);
case 8:
return new TypeTuple(Type::tint64);
}
return new TypeTuple(); // pass on the stack
}
TypeTuple *TypeEnum::toArgTypes()
{
return toBasetype()->toArgTypes();
}
TypeTuple *TypeTypedef::toArgTypes()
{
return sym->basetype->toArgTypes();
}
TypeTuple *TypeClass::toArgTypes()
{
return new TypeTuple(Type::tvoidptr);
}

682
dmd2/arrayop.c Normal file
View File

@@ -0,0 +1,682 @@
// Copyright (c) 1999-2011 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 "aav.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.
*/
AA *arrayfuncs;
#else
int binary(const char *p , const char **tab, int high)
{
int i = 0, j = high, k, l;
do
{
k = (i + j) / 2;
l = strcmp(p, tab[k]);
if (!l)
return k;
else if (l < 0)
j = k;
else
i = k + 1;
}
while (i != j);
return -1;
}
#endif
/**********************************************
* Check that there are no uses of arrays without [].
*/
bool isArrayOpValid(Expression *e)
{
if (e->op == TOKslice)
return true;
Type *tb = e->type->toBasetype();
if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
{
switch (e->op)
{
case TOKadd:
case TOKmin:
case TOKmul:
case TOKdiv:
case TOKmod:
case TOKxor:
case TOKand:
case TOKor:
case TOKassign:
case TOKaddass:
case TOKminass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKxorass:
case TOKandass:
case TOKorass:
#if DMDV2
case TOKpow:
case TOKpowass:
#endif
return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2);
case TOKcall:
return false; // TODO: Decide if [] is required after arrayop calls.
case TOKneg:
case TOKtilde:
return isArrayOpValid(((UnaExp *)e)->e1);
default:
return false;
}
}
return true;
}
/***********************************
* Construct the array operation expression.
*/
Expression *BinExp::arrayOp(Scope *sc)
{
Type *tb = type->toBasetype();
assert(tb->ty == Tarray || tb->ty == Tsarray);
if (tb->nextOf()->toBasetype()->ty == Tvoid)
{
error("Cannot perform array operations on void[] arrays");
return new ErrorExp();
}
if (!isArrayOpValid(e2))
{
e2->error("invalid array operation %s (did you forget a [] ?)", toChars());
return new ErrorExp();
}
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 = buf.toChars();
Identifier *ident = Lexer::idPool(name);
/* Look up name in hash table
*/
#if IN_LLVM
FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&sc->module->arrayfuncs, ident);
#else
FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident);
#endif
FuncDeclaration *fd = (FuncDeclaration *)*pfd;
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;
*/
Parameters *fparams = new Parameters();
Expression *loopbody = buildArrayLoop(fparams);
Parameter *p = (*fparams)[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 Parameter(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(loc, 0, ident, STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKd;
fd->isArrayOp = 1;
sc->module->importedFrom->members->push(fd);
sc = sc->push();
sc->parent = sc->module->importedFrom;
sc->stc = 0;
sc->linkage = LINKc;
fd->semantic(sc);
fd->semantic2(sc);
fd->semantic3(sc);
sc->pop();
}
#if IN_LLVM
else
{ /* In library, refer to it.
*/
Parameters *fparams = new Parameters();
buildArrayLoop(fparams);
fd = FuncDeclaration::genCfunc(fparams, type, ident);
fd->isArrayOp = 2;
}
#else
else
{ /* In library, refer to it.
*/
fd = FuncDeclaration::genCfunc(type, ident);
}
#endif
*pfd = 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 CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
Type *tb = type->toBasetype();
if (tb->ty == Tarray || tb->ty == Tsarray)
{
e1->buildArrayIdent(buf, arguments);
}
else
Expression::buildArrayIdent(buf, arguments);
}
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)
#if DMDV2
X(Pow)
#endif
#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)
#if DMDV2
X(Pow)
#endif
#undef X
/******************************************
* Construct the inner loop for the array operation function,
* and build the parameter list.
*/
Expression *Expression::buildArrayLoop(Parameters *fparams)
{
Identifier *id = Identifier::generateId("c", fparams->dim);
Parameter *param = new Parameter(0, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
return e;
}
Expression *CastExp::buildArrayLoop(Parameters *fparams)
{
Type *tb = type->toBasetype();
if (tb->ty == Tarray || tb->ty == Tsarray)
{
return e1->buildArrayLoop(fparams);
}
else
return Expression::buildArrayLoop(fparams);
}
Expression *SliceExp::buildArrayLoop(Parameters *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
Parameter *param = new Parameter(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(Parameters *fparams)
{
/* Evaluate assign expressions right to left
*/
Expression *ex2 = e2->buildArrayLoop(fparams);
#if DMDV2
/* Need the cast because:
* b = c + p[i];
* where b is a byte fails because (c + p[i]) is an int
* which cannot be implicitly cast to byte.
*/
ex2 = new CastExp(0, ex2, e1->type->nextOf());
#endif
Expression *ex1 = e1->buildArrayLoop(fparams);
Parameter *param = (*fparams)[0];
param->storageClass = 0;
Expression *e = new AssignExp(0, ex1, ex2);
return e;
}
#define X(Str) \
Expression *Str##AssignExp::buildArrayLoop(Parameters *fparams) \
{ \
/* Evaluate assign expressions right to left \
*/ \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Parameter *param = (*fparams)[0]; \
param->storageClass = 0; \
Expression *e = new Str##AssignExp(loc, ex1, ex2); \
return e; \
}
X(Add)
X(Min)
X(Mul)
X(Div)
X(Mod)
X(Xor)
X(And)
X(Or)
#if DMDV2
X(Pow)
#endif
#undef X
Expression *NegExp::buildArrayLoop(Parameters *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new NegExp(0, ex1);
return e;
}
Expression *ComExp::buildArrayLoop(Parameters *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new ComExp(0, ex1);
return e;
}
#define X(Str) \
Expression *Str##Exp::buildArrayLoop(Parameters *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)
#if DMDV2
X(Pow)
#endif
#undef X
/***********************************************
* Test if operand is a valid array op operand.
*/
int Expression::isArrayOperand()
{
//printf("Expression::isArrayOperand() %s\n", toChars());
if (op == TOKslice)
return 1;
if (type->toBasetype()->ty == Tarray)
{
switch (op)
{
case TOKadd:
case TOKmin:
case TOKmul:
case TOKdiv:
case TOKmod:
case TOKxor:
case TOKand:
case TOKor:
case TOKassign:
case TOKaddass:
case TOKminass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKxorass:
case TOKandass:
case TOKorass:
#if DMDV2
case TOKpow:
case TOKpowass:
#endif
case TOKneg:
case TOKtilde:
return 1;
default:
break;
}
}
return 0;
}

77
dmd2/arraytypes.h Normal file
View File

@@ -0,0 +1,77 @@
// Compiler implementation of the D programming language
// Copyright (c) 2006-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_ARRAYTYPES_H
#define DMD_ARRAYTYPES_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
typedef ArrayBase<struct TemplateParameter> TemplateParameters;
typedef ArrayBase<struct Expression> Expressions;
typedef ArrayBase<struct Statement> Statements;
typedef ArrayBase<struct BaseClass> BaseClasses;
typedef ArrayBase<struct ClassDeclaration> ClassDeclarations;
typedef ArrayBase<struct Dsymbol> Dsymbols;
typedef ArrayBase<struct Object> Objects;
typedef ArrayBase<struct FuncDeclaration> FuncDeclarations;
typedef ArrayBase<struct Parameter> Parameters;
typedef ArrayBase<struct Identifier> Identifiers;
typedef ArrayBase<struct Initializer> Initializers;
typedef ArrayBase<struct VarDeclaration> VarDeclarations;
typedef ArrayBase<struct Type> Types;
typedef ArrayBase<struct ScopeDsymbol> ScopeDsymbols;
typedef ArrayBase<struct Catch> Catches;
typedef ArrayBase<struct StaticDtorDeclaration> StaticDtorDeclarations;
typedef ArrayBase<struct SharedStaticDtorDeclaration> SharedStaticDtorDeclarations;
typedef ArrayBase<struct AliasDeclaration> AliasDeclarations;
typedef ArrayBase<struct Module> Modules;
typedef ArrayBase<struct File> Files;
typedef ArrayBase<struct CaseStatement> CaseStatements;
typedef ArrayBase<struct CompoundStatement> CompoundStatements;
typedef ArrayBase<struct GotoCaseStatement> GotoCaseStatements;
typedef ArrayBase<struct TemplateInstance> TemplateInstances;
//typedef ArrayBase<char> Strings;
typedef ArrayBase<void> Voids;
typedef ArrayBase<struct block> Blocks;
typedef ArrayBase<struct Symbol> Symbols;
#endif

117
dmd2/artistic.txt Normal file
View File

@@ -0,0 +1,117 @@
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The source code and object code supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
8. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

1565
dmd2/attrib.c Normal file

File diff suppressed because it is too large Load Diff

202
dmd2/attrib.h Normal file
View File

@@ -0,0 +1,202 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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_ATTRIB_H
#define DMD_ATTRIB_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Expression;
struct Statement;
struct LabelDsymbol;
struct Initializer;
struct Module;
struct Condition;
struct HdrGenState;
/**************************************************************/
struct AttribDeclaration : Dsymbol
{
Dsymbols *decl; // array of Dsymbol's
AttribDeclaration(Dsymbols *decl);
virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void setScopeNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
void semanticNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void addComment(unsigned char *comment);
void emitComment(Scope *sc);
const char *kind();
int oneMember(Dsymbol **ps, Identifier *ident);
int hasPointers();
bool hasStaticCtorOrDtor();
void checkCtorConstInit();
void addLocalClass(ClassDeclarations *);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
AttribDeclaration *isAttribDeclaration() { return this; }
#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
{
StorageClass stc;
StorageClassDeclaration(StorageClass stc, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void stcToCBuffer(OutBuffer *buf, StorageClass stc);
};
struct LinkDeclaration : AttribDeclaration
{
enum LINK linkage;
LinkDeclaration(enum LINK p, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
void semantic3(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *toChars();
};
struct ProtDeclaration : AttribDeclaration
{
enum PROT protection;
ProtDeclaration(enum PROT p, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void importAll(Scope *sc);
void setScope(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void protectionToCBuffer(OutBuffer *buf, enum PROT protection);
};
struct AlignDeclaration : AttribDeclaration
{
unsigned salign;
AlignDeclaration(Loc loc, unsigned sa, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct AnonDeclaration : AttribDeclaration
{
int isunion;
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
};
struct PragmaDeclaration : AttribDeclaration
{
Expressions *args; // array of Expression's
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setScope(Scope *sc);
int oneMember(Dsymbol **ps, Identifier *ident);
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
{
Condition *condition;
Dsymbols *elsedecl; // array of Dsymbol's for else block
ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int oneMember(Dsymbol **ps, Identifier *ident);
void emitComment(Scope *sc);
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
void addComment(unsigned char *comment);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
void importAll(Scope *sc);
void setScope(Scope *sc);
};
struct StaticIfDeclaration : ConditionalDeclaration
{
ScopeDsymbol *sd;
int addisdone;
StaticIfDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
void importAll(Scope *sc);
void setScope(Scope *sc);
const char *kind();
};
// Mixin declarations
struct CompileDeclaration : AttribDeclaration
{
Expression *exp;
ScopeDsymbol *sd;
int compiled;
CompileDeclaration(Loc loc, Expression *exp);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
void compileIt(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif /* DMD_ATTRIB_H */

234
dmd2/builtin.c Normal file
View File

@@ -0,0 +1,234 @@
// 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 <math.h>
#if __FreeBSD__
extern "C"
{
long double sinl(long double);
long double cosl(long double);
long double tanl(long double);
long double sqrtl(long double);
}
#endif
#include "mars.h"
#include "declaration.h"
#include "attrib.h"
#include "expression.h"
#include "scope.h"
#include "mtype.h"
#include "aggregate.h"
#include "identifier.h"
#include "id.h"
#include "module.h"
#if DMDV2
/**********************************
* Determine if function is a builtin one that we can
* evaluate at compile time.
*/
enum BUILTIN FuncDeclaration::isBuiltin()
{
static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real)
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
static const char FuintZint[] = "FNaNbkZi"; // pure nothrow int function(uint)
static const char FuintZuint[] = "FNaNbkZk"; // pure nothrow uint function(uint)
static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong)
static const char FulongZint[] = "FNaNbmZi"; // pure nothrow int function(uint)
static const char FrealrealZreal [] = "FNaNbNfeeZe"; // @safe pure nothrow real function(real, real)
static const char FrealZlong [] = "FNaNbNfeZl"; // @safe pure nothrow long function(real)
//printf("FuncDeclaration::isBuiltin() %s, %d\n", toChars(), builtin);
if (builtin == BUILTINunknown)
{
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->ident == Id::core) &&
!parent->parent->parent)
{
//printf("deco = %s\n", type->deco);
if (strcmp(type->deco, FeZe) == 0 || strcmp(type->deco, FeZe2) == 0)
{
if (ident == Id::sin)
builtin = BUILTINsin;
else if (ident == Id::cos)
builtin = BUILTINcos;
else if (ident == Id::tan)
builtin = BUILTINtan;
else if (ident == Id::_sqrt)
builtin = BUILTINsqrt;
else if (ident == Id::fabs)
builtin = BUILTINfabs;
else if (ident == Id::expm1)
builtin = BUILTINexpm1;
else if (ident == Id::exp2)
builtin = BUILTINexp2;
//printf("builtin = %d\n", builtin);
}
// if float or double versions
else if (strcmp(type->deco, "FNaNbNfdZd") == 0 ||
strcmp(type->deco, "FNaNbNffZf") == 0)
{
if (ident == Id::_sqrt)
builtin = BUILTINsqrt;
}
else if (strcmp(type->deco, FrealrealZreal) == 0)
{
if (ident == Id::atan2)
builtin = BUILTINatan2;
else if (ident == Id::yl2x)
builtin = BUILTINyl2x;
else if (ident == Id::yl2xp1)
builtin = BUILTINyl2xp1;
}
else if (strcmp(type->deco, FrealZlong) == 0 && ident == Id::rndtol)
builtin = BUILTINrndtol;
}
if (parent->ident == Id::bitop &&
parent->parent && parent->parent->ident == Id::core &&
!parent->parent->parent)
{
//printf("deco = %s\n", type->deco);
if (strcmp(type->deco, FuintZint) == 0 || strcmp(type->deco, FulongZint) == 0)
{
if (ident == Id::bsf)
builtin = BUILTINbsf;
else if (ident == Id::bsr)
builtin = BUILTINbsr;
}
else if (strcmp(type->deco, FuintZuint) == 0)
{
if (ident == Id::bswap)
builtin = BUILTINbswap;
}
}
}
}
return builtin;
}
int eval_bsf(uinteger_t n)
{
n = (n ^ (n - 1)) >> 1; // convert trailing 0s to 1, and zero rest
int k = 0;
while( n )
{ ++k;
n >>=1;
}
return k;
}
int eval_bsr(uinteger_t n)
{ int k= 0;
while(n>>=1)
{
++k;
}
return k;
}
uinteger_t eval_bswap(Expression *arg0)
{ uinteger_t n = arg0->toInteger();
#define BYTEMASK 0x00FF00FF00FF00FFLL
#define SHORTMASK 0x0000FFFF0000FFFFLL
#define INTMASK 0x0000FFFF0000FFFFLL
// swap adjacent ubytes
n = ((n >> 8 ) & BYTEMASK) | ((n & BYTEMASK) << 8 );
// swap adjacent ushorts
n = ((n >> 16) & SHORTMASK) | ((n & SHORTMASK) << 16);
TY ty = arg0->type->toBasetype()->ty;
// If 64 bits, we need to swap high and low uints
if (ty == Tint64 || ty == Tuns64)
n = ((n >> 32) & INTMASK) | ((n & INTMASK) << 32);
return n;
}
/**************************************
* Evaluate builtin function.
* Return result; NULL if cannot evaluate it.
*/
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
{
assert(arguments && arguments->dim);
Expression *arg0 = arguments->tdata()[0];
Expression *e = NULL;
switch (builtin)
{
case BUILTINsin:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sinl(arg0->toReal()), arg0->type);
break;
case BUILTINcos:
if (arg0->op == TOKfloat64)
e = new RealExp(0, cosl(arg0->toReal()), arg0->type);
break;
case BUILTINtan:
if (arg0->op == TOKfloat64)
e = new RealExp(0, tanl(arg0->toReal()), arg0->type);
break;
case BUILTINsqrt:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type);
break;
case BUILTINfabs:
if (arg0->op == TOKfloat64)
e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
break;
// These math intrinsics are not yet implemented
case BUILTINatan2:
break;
case BUILTINrndtol:
break;
case BUILTINexpm1:
break;
case BUILTINexp2:
break;
case BUILTINyl2x:
break;
case BUILTINyl2xp1:
break;
case BUILTINbsf:
if (arg0->op == TOKint64)
{ if (arg0->toInteger()==0)
error(loc, "bsf(0) is undefined");
else
e = new IntegerExp(loc, eval_bsf(arg0->toInteger()), Type::tint32);
}
break;
case BUILTINbsr:
if (arg0->op == TOKint64)
{ if (arg0->toInteger()==0)
error(loc, "bsr(0) is undefined");
else
e = new IntegerExp(loc, eval_bsr(arg0->toInteger()), Type::tint32);
}
break;
case BUILTINbswap:
if (arg0->op == TOKint64)
e = new IntegerExp(loc, eval_bswap(arg0), arg0->type);
break;
}
return e;
}
#endif

189
dmd2/canthrow.c Normal file
View File

@@ -0,0 +1,189 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 "init.h"
#include "expression.h"
#include "template.h"
#include "statement.h"
#include "mtype.h"
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
#include "attrib.h"
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow);
int lambdaCanThrow(Expression *e, void *param);
/********************************************
* Convert from expression to delegate that returns the expression,
* i.e. convert:
* expr
* to:
* t delegate() { return expr; }
*/
struct CanThrow
{
bool can;
bool mustnot;
};
int Expression::canThrow(bool mustNotThrow)
{
CanThrow ct;
ct.can = FALSE;
ct.mustnot = mustNotThrow;
apply(&lambdaCanThrow, &ct);
return ct.can;
}
int lambdaCanThrow(Expression *e, void *param)
{
CanThrow *pct = (CanThrow *)param;
switch (e->op)
{
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
pct->can = Dsymbol_canThrow(de->declaration, pct->mustnot);
break;
}
case TOKcall:
{ CallExp *ce = (CallExp *)e;
if (global.errors && !ce->e1->type)
break; // error recovery
/* If calling a function or delegate that is typed as nothrow,
* then this expression cannot throw.
* Note that pure functions can throw.
*/
Type *t = ce->e1->type->toBasetype();
if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow)
;
else if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
;
else
{
if (pct->mustnot)
e->error("%s is not nothrow", ce->e1->toChars());
pct->can = TRUE;
}
break;
}
case TOKnew:
{ NewExp *ne = (NewExp *)e;
if (ne->member)
{
// See if constructor call can throw
Type *t = ne->member->type->toBasetype();
if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow)
{
if (pct->mustnot)
e->error("constructor %s is not nothrow", ne->member->toChars());
pct->can = TRUE;
}
}
// regard storage allocation failures as not recoverable
break;
}
case TOKnewanonclass:
assert(0); // should have been lowered by semantic()
break;
default:
break;
}
return pct->can; // stop walking if we determine this expression can throw
}
/**************************************
* Does symbol, when initialized, throw?
* Mirrors logic in Dsymbol_toElem().
*/
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
{
AttribDeclaration *ad;
VarDeclaration *vd;
TemplateMixin *tm;
TupleDeclaration *td;
//printf("Dsymbol_toElem() %s\n", s->toChars());
ad = s->isAttribDeclaration();
if (ad)
{
Dsymbols *decl = ad->include(NULL, NULL);
if (decl && decl->dim)
{
for (size_t i = 0; i < decl->dim; i++)
{
s = decl->tdata()[i];
if (Dsymbol_canThrow(s, mustNotThrow))
return 1;
}
}
}
else if ((vd = s->isVarDeclaration()) != NULL)
{
s = s->toAlias();
if (s != vd)
return Dsymbol_canThrow(s, mustNotThrow);
if (vd->storage_class & STCmanifest)
;
else if (vd->isStatic() || vd->storage_class & (STCextern | STCtls | STCgshared))
;
else
{
if (vd->init)
{ ExpInitializer *ie = vd->init->isExpInitializer();
if (ie && ie->exp->canThrow(mustNotThrow))
return 1;
}
if (vd->edtor && !vd->noscope)
return vd->edtor->canThrow(mustNotThrow);
}
}
else if ((tm = s->isTemplateMixin()) != NULL)
{
//printf("%s\n", tm->toChars());
if (tm->members)
{
for (size_t i = 0; i < tm->members->dim; i++)
{
Dsymbol *sm = tm->members->tdata()[i];
if (Dsymbol_canThrow(sm, mustNotThrow))
return 1;
}
}
}
else if ((td = s->isTupleDeclaration()) != NULL)
{
for (size_t i = 0; i < td->objects->dim; i++)
{ Object *o = td->objects->tdata()[i];
if (o->dyncast() == DYNCAST_EXPRESSION)
{ Expression *eo = (Expression *)o;
if (eo->op == TOKdsymbol)
{ DsymbolExp *se = (DsymbolExp *)eo;
if (Dsymbol_canThrow(se->s, mustNotThrow))
return 1;
}
}
}
}
return 0;
}

2641
dmd2/cast.c Normal file

File diff suppressed because it is too large Load Diff

1656
dmd2/class.c Normal file

File diff suppressed because it is too large Load Diff

694
dmd2/clone.c Normal file
View File

@@ -0,0 +1,694 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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"
#include "template.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 = fields.tdata()[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) { ... }
*
* Note that s will be constructed onto the stack, probably copy-constructed.
* Then, the body is:
* S tmp = *this; // bit copy
* *this = s; // bit copy
* tmp.dtor();
* Instead of running the destructor on s, run it on tmp instead.
*/
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
{
if (!needOpAssign())
return NULL;
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
FuncDeclaration *fop = NULL;
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCnodtor, type, Id::p, NULL));
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
#if STRUCTTHISREF
((TypeFunction *)ftype)->isref = 1;
#endif
fop = new FuncDeclaration(loc, 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->noscope = 1;
tmp->storage_class |= STCctfe;
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 *ec2 = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
ec2 = new CallExp(0, ec2);
e = Expression::combine(e, ec2);
}
}
else
{ /* Do memberwise copy
*/
//printf("\tmemberwise copy\n");
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[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;
}
/*******************************************
* We need an opEquals for the struct if
* any fields has an opEquals.
* Generate one if a user-specified one does not exist.
*/
int StructDeclaration::needOpEquals()
{
#define X 0
if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars());
if (hasIdentityEquals)
goto Lneed;
/* If any of the fields has an opEquals, then we
* need it too.
*/
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[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->needOpEquals())
goto Lneed;
}
}
if (X) printf("\tdontneed\n");
return 0;
Lneed:
if (X) printf("\tneed\n");
return 1;
#undef X
}
/******************************************
* Build opEquals for struct.
* const bool opEquals(const S s) { ... }
*/
FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
{
Dsymbol *eq = search_function(this, Id::eq);
if (eq)
{
for (size_t i = 0; i <= 1; i++)
{
Expression *e =
i == 0 ? new NullExp(loc, type->constOf()) // dummy rvalue
: type->constOf()->defaultInit(); // dummy lvalue
Expressions *arguments = new Expressions();
arguments->push(e);
// check identity opEquals exists
FuncDeclaration *fd = eq->isFuncDeclaration();
if (fd)
{ fd = fd->overloadResolve(loc, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
return fd;
}
TemplateDeclaration *td = eq->isTemplateDeclaration();
if (td)
{ fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
return fd;
}
}
return NULL;
}
if (!needOpEquals())
return NULL;
//printf("StructDeclaration::buildOpEquals() %s\n", toChars());
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCin, type, Id::p, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tf->mod = MODconst;
tf = (TypeFunction *)tf->semantic(loc, sc);
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::eq, STCundefined, tf);
Expression *e = NULL;
/* Do memberwise compare
*/
//printf("\tmemberwise compare\n");
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
assert(0); // what should we do with this?
// this.v == s.v;
EqualExp *ec = new EqualExp(TOKequal, loc,
new DotVarExp(loc, new ThisExp(loc), v, 0),
new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0));
if (e)
e = new AndAndExp(loc, e, ec);
else
e = ec;
}
if (!e)
e = new IntegerExp(loc, 1, Type::tbool);
fop->fbody = new ReturnStatement(loc, e);
members->push(fop);
fop->addMember(sc, this, 1);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fop->semantic(sc);
sc->pop();
//printf("-StructDeclaration::buildOpEquals() %s\n", toChars());
return fop;
}
/******************************************
* Build __xopEquals for TypeInfo_Struct
* bool __xopEquals(in void* p, in void* q) { ... }
*/
FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
{
if (!search_function(this, Id::eq))
return NULL;
/* static bool__xopEquals(in void* p, in void* q) {
* return ( *cast(const S*)(p) ).opEquals( *cast(const S*)(q) );
* }
*/
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::p, NULL));
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::q, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tf = (TypeFunction *)tf->semantic(loc, sc);
Identifier *id = Lexer::idPool("__xopEquals");
FuncDeclaration *fop = new FuncDeclaration(loc, 0, id, STCstatic, tf);
Expression *e = new CallExp(0,
new DotIdExp(0,
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::p), type->pointerTo()->constOf())),
Id::eq),
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::q), type->pointerTo()->constOf())));
fop->fbody = new ReturnStatement(loc, e);
size_t index = members->dim;
members->push(fop);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
unsigned errors = global.startGagging();
fop->semantic(sc);
if (errors == global.gaggedErrors)
{ fop->semantic2(sc);
if (errors == global.gaggedErrors)
{ fop->semantic3(sc);
if (errors == global.gaggedErrors)
fop->addMember(sc, this, 1);
}
}
if (global.endGagging(errors)) // if errors happened
{
members->remove(index);
if (!xerreq)
{
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals"));
e = e->semantic(sc);
Dsymbol *s = getDsymbol(e);
FuncDeclaration *fd = s->isFuncDeclaration();
xerreq = fd;
}
fop = xerreq;
}
sc->pop();
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 const S s) const
* {
* (*cast(S*)&this) = *cast(S*)s;
* (*cast(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");
StorageClass stc = postblit->storage_class &
(STCdisable | STCsafe | STCtrusted | STCsystem | STCpure | STCnothrow);
if (stc & (STCsafe | STCtrusted))
stc = stc & ~STCsafe | STCtrusted;
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCref, type->constOf(), Id::p, NULL));
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd, stc);
ftype->mod = MODconst;
fcp = new FuncDeclaration(loc, 0, Id::cpctor, stc, ftype);
if (!(fcp->storage_class & STCdisable))
{
// Build *this = p;
Expression *e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
AssignExp *ea = new AssignExp(0,
new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo())),
new PtrExp(0, new CastExp(0, new AddrExp(0, new IdentifierExp(0, Id::p)), type->mutableOf()->pointerTo()))
);
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
// Build postBlit();
e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
e = new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo()));
e = new DotVarExp(0, e, postblit, 0);
e = new CallExp(0, e);
s = new CompoundStatement(0, s, new ExpStatement(0, e));
fcp->fbody = s;
}
else
fcp->fbody = new ExpStatement(0, (Expression *)NULL);
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;
StorageClass stc = 0;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
dinteger_t dim = (tv->ty == Tsarray ? 1 : 0);
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)
{
stc |= sd->postblit->storage_class & STCdisable;
if (stc & STCdisable)
{
e = NULL;
break;
}
// this.v
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 0)
{ // 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 || (stc & STCdisable))
{ //printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__fieldPostBlit"));
dd->storage_class |= stc;
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 postblits.tdata()[0];
default:
e = NULL;
for (size_t i = 0; i < postblits.dim; i++)
{ FuncDeclaration *fd = postblits.tdata()[i];
stc |= fd->storage_class & STCdisable;
if (stc & STCdisable)
{
e = NULL;
break;
}
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(loc, 0, Lexer::idPool("__aggrPostBlit"));
dd->storage_class |= stc;
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 = fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
dinteger_t dim = (tv->ty == Tsarray ? 1 : 0);
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 == 0)
{ // 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(loc, 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 dtors.tdata()[0];
default:
e = NULL;
for (size_t i = 0; i < dtors.dim; i++)
{ FuncDeclaration *fd = dtors.tdata()[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(loc, 0, Lexer::idPool("__aggrDtor"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}

74
dmd2/complex_t.h Normal file
View File

@@ -0,0 +1,74 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright and Burton Radons
// 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_COMPLEX_T_H
#define DMD_COMPLEX_T_H
/* Roll our own complex type for compilers that don't support complex
*/
struct complex_t
{
long double re;
long double im;
complex_t() { this->re = 0; this->im = 0; }
complex_t(long double re) { this->re = re; this->im = 0; }
complex_t(long double re, long double im) { this->re = re; this->im = im; }
complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; }
complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; }
complex_t operator - () { complex_t r; r.re = -re; r.im = -im; return r; }
complex_t operator * (complex_t y) { return complex_t(re * y.re - im * y.im, im * y.re + re * y.im); }
complex_t operator / (complex_t y)
{
long double abs_y_re = y.re < 0 ? -y.re : y.re;
long double abs_y_im = y.im < 0 ? -y.im : y.im;
long double r, den;
if (abs_y_re < abs_y_im)
{
r = y.re / y.im;
den = y.im + r * y.re;
return complex_t((re * r + im) / den,
(im * r - re) / den);
}
else
{
r = y.im / y.re;
den = y.re + r * y.im;
return complex_t((re + r * im) / den,
(im - r * re) / den);
}
}
operator bool () { return re || im; }
int operator == (complex_t y) { return re == y.re && im == y.im; }
int operator != (complex_t y) { return re != y.re || im != y.im; }
};
inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; }
inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); }
inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); }
inline long double creall(complex_t x)
{
return x.re;
}
inline long double cimagl(complex_t x)
{
return x.im;
}
#endif

405
dmd2/cond.c Normal file
View File

@@ -0,0 +1,405 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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"
#include "mtype.h"
#include "scope.h"
int findCondition(Strings *ids, Identifier *ident)
{
if (ids)
{
for (size_t i = 0; i < ids->dim; i++)
{
const char *id = ids->tdata()[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 Strings();
global.params.debugids->push((char *)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 Strings();
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",
"OpenBSD",
"Solaris",
"LittleEndian", "BigEndian",
"all",
"none",
#if IN_LLVM
"LLVM", "LDC", "LLVM64",
"PPC", "PPC64",
"darwin","solaris","freebsd"
#endif
};
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 Strings();
global.params.versionids->push((char *)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 Strings();
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.tdata()[0] = &tp;
Objects dedtypes;
dedtypes.setDim(1);
m = targ->deduceType(sc, tspec, &parameters, &dedtypes);
if (m == MATCHnomatch ||
(m != MATCHexact && tok == TOKequal))
inc = 2;
else
{
inc = 1;
Type *tded = (Type *)dedtypes.tdata()[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(')');
}

105
dmd2/cond.h Normal file
View File

@@ -0,0 +1,105 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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_DEBCOND_H
#define DMD_DEBCOND_H
struct Expression;
struct Identifier;
struct OutBuffer;
struct Module;
struct Scope;
struct ScopeDsymbol;
struct DebugCondition;
#include "lexer.h" // dmdhg
enum TOK;
struct HdrGenState;
int findCondition(Strings *ids, Identifier *ident);
struct Condition
{
Loc loc;
int inc; // 0: not computed yet
// 1: include
// 2: do not include
Condition(Loc loc);
virtual Condition *syntaxCopy() = 0;
virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
virtual DebugCondition *isDebugCondition() { return NULL; }
};
struct DVCondition : Condition
{
unsigned level;
Identifier *ident;
Module *mod;
DVCondition(Module *mod, unsigned level, Identifier *ident);
Condition *syntaxCopy();
};
struct DebugCondition : DVCondition
{
static void setGlobalLevel(unsigned level);
static void addGlobalIdent(const char *ident);
static void addPredefinedGlobalIdent(const char *ident);
DebugCondition(Module *mod, unsigned level, Identifier *ident);
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
DebugCondition *isDebugCondition() { return this; }
};
struct VersionCondition : DVCondition
{
static void setGlobalLevel(unsigned level);
static void checkPredefined(Loc loc, const char *ident);
static void addGlobalIdent(const char *ident);
static void addPredefinedGlobalIdent(const char *ident);
VersionCondition(Module *mod, unsigned level, Identifier *ident);
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct StaticIfCondition : Condition
{
Expression *exp;
StaticIfCondition(Loc loc, Expression *exp);
Condition *syntaxCopy();
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct IftypeCondition : Condition
{
/* iftype (targ id tok tspec)
*/
Type *targ;
Identifier *id; // can be NULL
enum TOK tok; // ':' or '=='
Type *tspec; // can be NULL
IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec);
Condition *syntaxCopy();
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif

1876
dmd2/constfold.c Normal file

File diff suppressed because it is too large Load Diff

454
dmd2/cppmangle.c Normal file
View File

@@ -0,0 +1,454 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 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 CPP_MANGLE
/* 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 Voids components;
int substitute(OutBuffer *buf, void *p);
int exist(void *p);
void store(void *p);
};
Voids 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.tdata()[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;
}
int CppMangleState::exist(void *p)
{
for (size_t i = 0; i < components.dim; i++)
{
if (p == components.tdata()[i])
{
return 1;
}
}
return 0;
}
void CppMangleState::store(void *p)
{
components.push(p);
}
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)
{
s->error("C++ static variables not supported");
}
else
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);
Parameter::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 || isConst())
{
if (cms->substitute(buf, this))
return;
}
if (isConst())
buf->writeByte('K');
if (p)
buf->writeByte(p);
buf->writeByte(c);
}
void TypeVector::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->writestring("U8__vector");
basetype->toCppMangle(buf, cms);
}
}
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->exist(this))
{ buf->writeByte('P');
next->toCppMangle(buf, cms);
cms->store(this);
}
else
cms->substitute(buf, this);
}
void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->exist(this))
{ buf->writeByte('R');
next->toCppMangle(buf, cms);
cms->store(this);
}
else
cms->substitute(buf, this);
}
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);
Parameter::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->exist(this))
{
if (isConst())
buf->writeByte('K');
if (!cms->substitute(buf, sym))
cpp_mangle_name(buf, cms, sym);
if (isConst())
cms->store(this);
}
else
cms->substitute(buf, this);
}
void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->exist(this))
{
if (isConst())
buf->writeByte('K');
if (!cms->substitute(buf, sym))
cpp_mangle_name(buf, cms, sym);
if (isConst())
cms->store(this);
}
else
cms->substitute(buf, this);
}
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 Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs)
{ int n = 0;
if (arguments)
{
for (size_t i = 0; i < arguments->dim; i++)
{ Parameter *arg = arguments->tdata()[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();
}
/* If it is a basic, enum or struct type,
* then don't mark it const
*/
if ((t->ty == Tenum || t->ty == Tstruct || t->isTypeBasic()) && t->isConst())
t->mutableOf()->toCppMangle(buf, cms);
else
t->toCppMangle(buf, cms);
n++;
}
}
if (varargs)
buf->writestring("z");
else if (!n)
buf->writeByte('v'); // encode ( ) arguments
}
#endif

2327
dmd2/declaration.c Normal file

File diff suppressed because it is too large Load Diff

1107
dmd2/declaration.h Normal file

File diff suppressed because it is too large Load Diff

140
dmd2/delegatize.c Normal file
View File

@@ -0,0 +1,140 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 "expression.h"
#include "statement.h"
#include "mtype.h"
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
/********************************************
* Convert from expression to delegate that returns the expression,
* i.e. convert:
* expr
* to:
* t delegate() { return expr; }
*/
int lambdaSetParent(Expression *e, void *param);
int lambdaCheckForNestedRef(Expression *e, void *param);
Expression *Expression::toDelegate(Scope *sc, Type *t)
{
//printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars());
TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd);
FuncLiteralDeclaration *fld =
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
Expression *e;
sc = sc->push();
sc->parent = fld; // set current function to be the delegate
e = this;
e->apply(&lambdaSetParent, sc);
e->apply(&lambdaCheckForNestedRef, sc);
sc = sc->pop();
Statement *s;
if (t->ty == Tvoid)
s = new ExpStatement(loc, e);
else
s = new ReturnStatement(loc, e);
fld->fbody = s;
e = new FuncExp(loc, fld);
e = e->semantic(sc);
return e;
}
/******************************************
* Patch the parent of declarations to be the new function literal.
*/
int lambdaSetParent(Expression *e, void *param)
{
Scope *sc = (Scope *)param;
/* We could use virtual functions instead of a switch,
* but it doesn't seem worth the bother.
*/
switch (e->op)
{
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
de->declaration->parent = sc->parent;
break;
}
case TOKindex:
{ IndexExp *de = (IndexExp *)e;
if (de->lengthVar)
{ //printf("lengthVar\n");
de->lengthVar->parent = sc->parent;
}
break;
}
case TOKslice:
{ SliceExp *se = (SliceExp *)e;
if (se->lengthVar)
{ //printf("lengthVar\n");
se->lengthVar->parent = sc->parent;
}
break;
}
default:
break;
}
return 0;
}
/*******************************************
* Look for references to variables in a scope enclosing the new function literal.
*/
int lambdaCheckForNestedRef(Expression *e, void *param)
{
Scope *sc = (Scope *)param;
/* We could use virtual functions instead of a switch,
* but it doesn't seem worth the bother.
*/
switch (e->op)
{
case TOKsymoff:
{ SymOffExp *se = (SymOffExp *)e;
VarDeclaration *v = se->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
break;
}
case TOKvar:
{ VarExp *ve = (VarExp *)e;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
break;
}
case TOKthis:
case TOKsuper:
{ ThisExp *te = (ThisExp *)e;
VarDeclaration *v = te->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
break;
}
default:
break;
}
return 0;
}

2226
dmd2/doc.c Normal file

File diff suppressed because it is too large Load Diff

20
dmd2/doc.h Normal file
View File

@@ -0,0 +1,20 @@
// 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.
#ifndef DMD_DOC_H
#define DMD_DOC_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
void escapeDdocString(OutBuffer *buf, unsigned start);
#endif

1476
dmd2/dsymbol.c Normal file

File diff suppressed because it is too large Load Diff

389
dmd2/dsymbol.h Normal file
View File

@@ -0,0 +1,389 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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
#if defined(_MSC_VER)
#undef min
#undef max
#endif
#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 SharedStaticCtorDeclaration;
struct SharedStaticDtorDeclaration;
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 ScopeDsymbol;
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 AA;
#if TARGET_NET
struct PragmaScope;
#endif
#if IN_LLVM
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#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,
};
/* State of symbol in winding its way through the passes of the compiler
*/
enum PASS
{
PASSinit, // initial state
PASSsemantic, // semantic() started
PASSsemanticdone, // semantic() done
PASSsemantic2, // semantic2() run
PASSsemantic3, // semantic3() started
PASSsemantic3done, // semantic3() done
PASSobj, // toObjFile() run
};
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
Scope *scope; // !=NULL means context to use for semantic()
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
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 verror(Loc loc, const char *format, va_list ap);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getAccessModule();
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
TemplateInstance *inTemplateInstance();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
static Dsymbols *arraySyntaxCopy(Dsymbols *a);
virtual const char *toPrettyChars();
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc);
virtual void semantic0(Scope *sc);
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 *search_correct(Identifier *id);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual void toJsonBuffer(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
AggregateDeclaration *isAggregateMember(); // are we a member of an aggregate?
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?
#if DMDV2
virtual int isOverloadable();
#endif
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, Identifier *ident);
static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL);
virtual int hasPointers();
virtual bool hasStaticCtorOrDtor();
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 SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return NULL; }
virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { 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; }
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
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 TARGET_NET
virtual PragmaScope* isPragmaScope() { return NULL; }
#endif
#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
{
Dsymbols *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
Dsymbols *imports; // imported Dsymbol'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(Dsymbol *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();
virtual Dsymbol *symtabInsert(Dsymbol *s);
bool hasStaticCtorOrDtor();
void emitMemberComments(Scope *sc);
static size_t dim(Dsymbols *members);
static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL);
typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
static int foreach(Dsymbols *members, ForeachDg dg, void *ctx, 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
#if DMDV2
struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
#endif
// Table of Dsymbol's
struct DsymbolTable : Object
{
AA *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 */

152
dmd2/dump.c Normal file
View File

@@ -0,0 +1,152 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 <ctype.h>
#include <assert.h>
#include "mars.h"
#include "mtype.h"
#include "declaration.h"
#include "expression.h"
#include "template.h"
static void indent(int indent)
{
int i;
for (i = 0; i < indent; i++)
printf(" ");
}
static char *type_print(Type *type)
{
return type ? type->toChars() : (char *) "null";
}
void dumpExpressions(int i, Expressions *exps)
{
if (exps)
{
for (size_t j = 0; j < exps->dim; j++)
{ Expression *e = exps->tdata()[j];
indent(i);
printf("(\n");
e->dump(i + 2);
indent(i);
printf(")\n");
}
}
}
void Expression::dump(int i)
{
indent(i);
printf("%p %s type=%s\n", this, Token::toChars(op), type_print(type));
}
void IntegerExp::dump(int i)
{
indent(i);
printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
}
void IdentifierExp::dump(int i)
{
indent(i);
printf("%p ident '%s' type=%s\n", this, ident->toChars(), type_print(type));
}
void DsymbolExp::dump(int i)
{
indent(i);
printf("%p %s type=%s\n", this, s->toChars(), type_print(type));
}
void VarExp::dump(int i)
{
indent(i);
printf("%p %s var=%s type=%s\n", this, Token::toChars(op), var->toChars(), type_print(type));
}
void UnaExp::dump(int i)
{
indent(i);
printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1);
if (e1)
e1->dump(i + 2);
}
void CallExp::dump(int i)
{
UnaExp::dump(i);
dumpExpressions(i, arguments);
}
void SliceExp::dump(int i)
{
indent(i);
printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1);
if (e1)
e1->dump(i + 2);
if (lwr)
lwr->dump(i + 2);
if (upr)
upr->dump(i + 2);
}
void DotIdExp::dump(int i)
{
indent(i);
printf("%p %s type=%s ident=%s e1=%p\n", this, Token::toChars(op), type_print(type), ident->toChars(), e1);
if (e1)
e1->dump(i + 2);
}
void DotVarExp::dump(int i)
{
indent(i);
printf("%p %s type=%s var='%s' e1=%p\n", this, Token::toChars(op), type_print(type), var->toChars(), e1);
if (e1)
e1->dump(i + 2);
}
void DotTemplateInstanceExp::dump(int i)
{
indent(i);
printf("%p %s type=%s ti='%s' e1=%p\n", this, Token::toChars(op), type_print(type), ti->toChars(), e1);
if (e1)
e1->dump(i + 2);
}
void DelegateExp::dump(int i)
{
indent(i);
printf("%p %s func=%s type=%s e1=%p\n", this, Token::toChars(op), func->toChars(), type_print(type), e1);
if (e1)
e1->dump(i + 2);
}
void BinExp::dump(int i)
{
indent(i);
const char *sop = Token::toChars(op);
if (op == TOKblit)
sop = "blit";
else if (op == TOKconstruct)
sop = "construct";
printf("%p %s type=%s e1=%p e2=%p\n", this, sop, type_print(type), e1, e2);
if (e1)
e1->dump(i + 2);
if (e2)
e2->dump(i + 2);
}

2391
dmd2/entity.c Normal file

File diff suppressed because it is too large Load Diff

427
dmd2/enum.c Normal file
View File

@@ -0,0 +1,427 @@
// Copyright (c) 1999-2011 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 "enum.h"
#include "mtype.h"
#include "scope.h"
#include "id.h"
#include "expression.h"
#include "module.h"
#include "declaration.h"
/********************************* EnumDeclaration ****************************/
EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
: ScopeDsymbol(id)
{
this->loc = loc;
type = new TypeEnum(this);
this->memtype = memtype;
maxval = NULL;
minval = NULL;
defaultval = NULL;
#if IN_DMD
sinit = NULL;
#endif
isdeprecated = 0;
isdone = 0;
}
Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
{
Type *t = NULL;
if (memtype)
t = memtype->syntaxCopy();
EnumDeclaration *ed;
if (s)
{ ed = (EnumDeclaration *)s;
ed->memtype = t;
}
else
ed = new EnumDeclaration(loc, ident, t);
ScopeDsymbol::syntaxCopy(ed);
return ed;
}
void EnumDeclaration::semantic0(Scope *sc)
{
/* This function is a hack to get around a significant problem.
* The members of anonymous enums, like:
* enum { A, B, C }
* don't get installed into the symbol table until after they are
* semantically analyzed, yet they're supposed to go into the enclosing
* scope's table. Hence, when forward referenced, they come out as
* 'undefined'. The real fix is to add them in at addSymbol() time.
* But to get code to compile, we'll just do this quick hack at the moment
* to compile it if it doesn't depend on anything else.
*/
if (isdone || !scope)
return;
if (!isAnonymous() || memtype)
return;
for (size_t i = 0; i < members->dim; i++)
{
EnumMember *em = (*members)[i]->isEnumMember();
if (em && (em->type || em->value))
return;
}
// Can do it
semantic(sc);
}
void EnumDeclaration::semantic(Scope *sc)
{
Type *t;
Scope *sce;
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
//printf("EnumDeclaration::semantic() %s\n", toChars());
if (!members) // enum ident;
return;
if (!memtype && !isAnonymous())
{ // Set memtype if we can to reduce fwd reference errors
memtype = Type::tint32; // case 1) enum ident { ... }
}
if (symtab) // if already done
{ if (isdone || !scope)
return; // semantic() already completed
}
else
symtab = new DsymbolTable();
Scope *scx = NULL;
if (scope)
{ sc = scope;
scx = scope; // save so we don't make redundant copies
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
if (sc->stc & STCdeprecated)
isdeprecated = 1;
parent = sc->parent;
/* The separate, and distinct, cases are:
* 1. enum { ... }
* 2. enum : memtype { ... }
* 3. enum ident { ... }
* 4. enum ident : memtype { ... }
*/
if (memtype)
{
memtype = memtype->semantic(loc, sc);
/* Check to see if memtype is forward referenced
*/
if (memtype->ty == Tenum)
{ EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
{ // memtype is forward referenced, so try again later
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
Module::dprogress = dprogress_save;
//printf("\tdeferring %s\n", toChars());
return;
}
}
#if 0 // Decided to abandon this restriction for D 2.0
if (!memtype->isintegral())
{ error("base type must be of integral type, not %s", memtype->toChars());
memtype = Type::tint32;
}
#endif
}
isdone = 1;
Module::dprogress++;
type = type->semantic(loc, sc);
if (isAnonymous())
sce = sc;
else
{ sce = sc->push(this);
sce->parent = this;
}
if (members->dim == 0)
error("enum %s must have at least one member", toChars());
int first = 1;
Expression *elast = NULL;
for (size_t i = 0; i < members->dim; i++)
{
EnumMember *em = (*members)[i]->isEnumMember();
Expression *e;
if (!em)
/* The e->semantic(sce) can insert other symbols, such as
* template instances and function literals.
*/
continue;
//printf(" Enum member '%s'\n",em->toChars());
if (em->type)
em->type = em->type->semantic(em->loc, sce);
e = em->value;
if (e)
{
assert(e->dyncast() == DYNCAST_EXPRESSION);
e = e->semantic(sce);
e = e->optimize(WANTvalue | WANTinterpret);
if (memtype)
{
e = e->implicitCastTo(sce, memtype);
e = e->optimize(WANTvalue | WANTinterpret);
if (!isAnonymous())
e = e->castTo(sce, type);
t = memtype;
}
else if (em->type)
{
e = e->implicitCastTo(sce, em->type);
e = e->optimize(WANTvalue | WANTinterpret);
assert(isAnonymous());
t = e->type;
}
else
t = e->type;
}
else if (first)
{
if (memtype)
t = memtype;
else if (em->type)
t = em->type;
else
t = Type::tint32;
e = new IntegerExp(em->loc, 0, Type::tint32);
e = e->implicitCastTo(sce, t);
e = e->optimize(WANTvalue | WANTinterpret);
if (!isAnonymous())
e = e->castTo(sce, type);
}
else
{
// Set value to (elast + 1).
// But first check that (elast != t.max)
assert(elast);
e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
e = e->semantic(sce);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->toInteger())
error("overflow of enum value %s", elast->toChars());
// Now set e to (elast + 1)
e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
e = e->semantic(sce);
e = e->castTo(sce, elast->type);
e = e->optimize(WANTvalue | WANTinterpret);
}
elast = e;
em->value = e;
// Add to symbol table only after evaluating 'value'
if (isAnonymous())
{
/* Anonymous enum members get added to enclosing scope.
*/
for (Scope *sct = sce; sct; sct = sct->enclosing)
{
if (sct->scopesym)
{
if (!sct->scopesym->symtab)
sct->scopesym->symtab = new DsymbolTable();
em->addMember(sce, sct->scopesym, 1);
break;
}
}
}
else
em->addMember(sc, this, 1);
/* Compute .min, .max and .default values.
* If enum doesn't have a name, we can never identify the enum type,
* so there is no purpose for a .min, .max or .default
*/
if (!isAnonymous())
{
if (first)
{ defaultval = e;
minval = e;
maxval = e;
}
else
{ Expression *ec;
/* In order to work successfully with UDTs,
* build expressions to do the comparisons,
* and let the semantic analyzer and constant
* folder give us the result.
*/
// Compute if(e < minval)
ec = new CmpExp(TOKlt, em->loc, e, minval);
ec = ec->semantic(sce);
ec = ec->optimize(WANTvalue | WANTinterpret);
if (ec->toInteger())
minval = e;
ec = new CmpExp(TOKgt, em->loc, e, maxval);
ec = ec->semantic(sce);
ec = ec->optimize(WANTvalue | WANTinterpret);
if (ec->toInteger())
maxval = e;
}
}
first = 0;
}
//printf("defaultval = %lld\n", defaultval);
//if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
if (sc != sce)
sce->pop();
//members->print();
}
int EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
if (isAnonymous())
return Dsymbol::oneMembers(members, ps, ident);
return Dsymbol::oneMember(ps, ident);
}
void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("enum ");
if (ident)
{ buf->writestring(ident->toChars());
buf->writeByte(' ');
}
if (memtype)
{
buf->writestring(": ");
memtype->toCBuffer(buf, NULL, hgs);
}
if (!members)
{
buf->writeByte(';');
buf->writenl();
return;
}
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (size_t i = 0; i < members->dim; i++)
{
EnumMember *em = (*members)[i]->isEnumMember();
if (!em)
continue;
//buf->writestring(" ");
em->toCBuffer(buf, hgs);
buf->writeByte(',');
buf->writenl();
}
buf->writeByte('}');
buf->writenl();
}
Type *EnumDeclaration::getType()
{
return type;
}
const char *EnumDeclaration::kind()
{
return "enum";
}
int EnumDeclaration::isDeprecated()
{
return isdeprecated;
}
Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
if (scope)
// Try one last time to resolve this enum
semantic(scope);
if (!members || !symtab || scope)
{ error("is forward referenced when looking for '%s'", ident->toChars());
//*(char*)0=0;
return NULL;
}
Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
return s;
}
/********************************* EnumMember ****************************/
EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
: Dsymbol(id)
{
this->value = value;
this->type = type;
this->loc = loc;
}
Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
{
Expression *e = NULL;
if (value)
e = value->syntaxCopy();
Type *t = NULL;
if (type)
t = type->syntaxCopy();
EnumMember *em;
if (s)
{ em = (EnumMember *)s;
em->loc = loc;
em->value = e;
em->type = t;
}
else
em = new EnumMember(loc, ident, e, t);
return em;
}
void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (type)
type->toCBuffer(buf, ident, hgs);
else
buf->writestring(ident->toChars());
if (value)
{
buf->writestring(" = ");
value->toCBuffer(buf, hgs);
}
}
const char *EnumMember::kind()
{
return "enum member";
}

97
dmd2/enum.h Normal file
View File

@@ -0,0 +1,97 @@
// 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;
struct HdrGenState;
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
#endif
int isdeprecated;
int isdone; // 0: not done
// 1: semantic() successfully completed
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic0(Scope *sc);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps, Identifier *ident = NULL);
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 toJsonBuffer(OutBuffer *buf);
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 toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
EnumMember *isEnumMember() { return this; }
};
#endif /* DMD_ENUM_H */

12570
dmd2/expression.c Normal file

File diff suppressed because it is too large Load Diff

2141
dmd2/expression.h Normal file

File diff suppressed because it is too large Load Diff

4236
dmd2/func.c Normal file

File diff suppressed because it is too large Load Diff

248
dmd2/gpl.txt Normal file
View File

@@ -0,0 +1,248 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

100
dmd2/hdrgen.c Normal file
View File

@@ -0,0 +1,100 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// Initial header generation implementation by Dave Fladebo
// 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.
// Routines to emit header files
#define PRETTY_PRINT
#define TEST_EMIT_ALL 0 // For Testing
#define LOG 0
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if __DMC__
#include <complex.h>
#endif
#include "rmem.h"
#include "id.h"
#include "init.h"
#include "attrib.h"
#include "cond.h"
#include "enum.h"
#include "import.h"
#include "module.h"
#include "mtype.h"
#include "scope.h"
#include "staticassert.h"
#include "template.h"
#include "utf.h"
#include "version.h"
#include "declaration.h"
#include "aggregate.h"
#include "expression.h"
#include "statement.h"
#include "mtype.h"
#include "hdrgen.h"
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void Module::genhdrfile()
{
OutBuffer hdrbufr;
hdrbufr.printf("// D import file generated from '%s'", srcfile->toChars());
hdrbufr.writenl();
HdrGenState hgs;
memset(&hgs, 0, sizeof(hgs));
hgs.hdrgen = 1;
toCBuffer(&hdrbufr, &hgs);
// Transfer image to file
hdrfile->setbuffer(hdrbufr.data, hdrbufr.offset);
hdrbufr.data = NULL;
char *pt = FileName::path(hdrfile->toChars());
if (*pt)
FileName::ensurePathExists(pt);
mem.free(pt);
hdrfile->writev();
}
void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (md)
{
buf->writestring("module ");
buf->writestring(md->toChars());
buf->writebyte(';');
buf->writenl();
}
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
s->toHBuffer(buf, hgs);
}
}
void Dsymbol::toHBuffer(OutBuffer *buf, HdrGenState *hgs)
{
toCBuffer(buf, hgs);
}
/*************************************/

34
dmd2/hdrgen.h Normal file
View File

@@ -0,0 +1,34 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// initial header generation implementation by Dave Fladebo
// 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.
struct HdrGenState
{
int hdrgen; // 1 if generating header file
int ddoc; // 1 if generating Ddoc file
int console; // 1 if writing to console
int tpltMember;
int inCallExp;
int inPtrExp;
int inSlcExp;
int inDotExp;
int inBinExp;
int inArrExp;
int emitInst;
struct
{
int init;
int decl;
} FLinit;
HdrGenState() { memset(this, 0, sizeof(HdrGenState)); }
};

772
dmd2/html.c Normal file
View File

@@ -0,0 +1,772 @@
// 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 gpl.txt.
// See the included readme.txt for details.
/* HTML parser
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <errno.h>
#include <wchar.h>
#define MARS 1
#include "html.h"
#if MARS
#include <assert.h>
#include "root.h"
//#include "../mars/mars.h"
#else
#include "outbuf.h"
#include "msgs2.h"
extern void html_err(const char *, unsigned, unsigned, ...);
static char __file__[] = __FILE__; /* for tassert.h */
#include "tassert.h"
#endif
#if __GNUC__
int memicmp(const char *s1, const char *s2, int n);
#if 0
{
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;
}
#endif
#endif
extern int HtmlNamedEntity(unsigned char *p, int length);
static int isLineSeparator(const unsigned char* p);
/**********************************
* Determine if beginning of tag identifier
* or a continuation of a tag identifier.
*/
inline int istagstart(int c)
{
return (isalpha(c) || c == '_');
}
inline int istag(int c)
{
return (isalnum(c) || c == '_');
}
/**********************************************
*/
Html::Html(const char *sourcename, unsigned char *base, unsigned length)
{
//printf("Html::Html()\n");
this->sourcename = sourcename;
this->base = base;
p = base;
end = base + length;
linnum = 1;
dbuf = NULL;
inCode = 0;
}
/**********************************************
* Print error & quit.
*/
void Html::error(const char *format, ...)
{
printf("%s(%d) : HTML Error: ", sourcename, linnum);
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
printf("\n");
fflush(stdout);
//#if MARS
// global.errors++;
//#else
exit(EXIT_FAILURE);
//#endif
}
/**********************************************
* Extract all the code from an HTML file,
* concatenate it all together, and store in buf.
*/
#if MARS
void Html::extractCode(OutBuffer *buf)
#else
void Html::extractCode(Outbuffer *buf)
#endif
{
//printf("Html::extractCode()\n");
dbuf = buf; // save for other routines
buf->reserve(end - p);
inCode = 0;
while (1)
{
//printf("p = %p, *p = x%x\n", p, *p);
switch (*p)
{
#if 0 // strings are not recognized outside of tags
case '"':
case '\'':
skipString();
continue;
#endif
case '<':
if (p[1] == '!' && isCommentStart())
{ // Comments start with <!--
scanComment();
}
else if(p[1] == '!' && isCDATAStart())
{
scanCDATA();
}
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
skipTag();
else if (istagstart(*skipWhite(p + 1)))
skipTag();
else
goto Ldefault;
continue;
case 0:
case 0x1a:
break; // end of file
case '&':
if (inCode)
{ // Translate character entity into ascii for D parser
int c;
c = charEntity();
#if MARS
buf->writeUTF8(c);
#else
buf->writeByte(c);
#endif
}
else
p++;
continue;
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++;
// Always extract new lines, so that D lexer counts the
// lines right.
buf->writeByte(*p);
p++;
continue;
default:
Ldefault:
if (inCode)
buf->writeByte(*p);
p++;
continue;
}
break;
}
buf->writeByte(0); // ending sentinel
#if SCPP
//printf("Code is: '%s'\n", buf->toString() + 3);
#endif
#if MARS
//printf("D code is: '%s'\n", (char *)buf->data);
#endif
}
/***********************************************
* Scan to end of <> tag.
* Look for <code> and </code> tags to start/stop D processing.
* Input:
* p is on opening '<' of tag; it's already verified that
* it's a tag by lookahead
* Output:
* p is past closing '>' of tag
*/
void Html::skipTag()
{
enum TagState // what parsing state we're in
{
TStagstart, // start of tag name
TStag, // in a tag name
TSrest, // following tag name
};
enum TagState state = TStagstart;
int inot;
unsigned char *tagstart = NULL;
int taglen = 0;
p++;
inot = 0;
if (*p == '/')
{ inot = 1;
p++;
}
while (1)
{
switch (*p)
{
case '>': // found end of tag
p++;
break;
case '"':
case '\'':
state = TSrest;
skipString();
continue;
case '<':
if (p[1] == '!' && isCommentStart())
{ // Comments start with <!--
scanComment();
}
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
{ error("nested tag");
skipTag();
}
else if (istagstart(*skipWhite(p + 1)))
{ error("nested tag");
skipTag();
}
// Treat comments as if they were whitespace
state = TSrest;
continue;
case 0:
case 0x1a:
error("end of file before end of tag");
break; // end of file
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++;
// Always extract new lines, so that code lexer counts the
// lines right.
dbuf->writeByte(*p);
state = TSrest; // end of tag
p++;
continue;
case ' ':
case '\t':
case '\f':
case '\v':
if (state == TStagstart)
{ p++;
continue;
}
default:
Ldefault:
switch (state)
{
case TStagstart: // start of tag name
assert(istagstart(*p));
state = TStag;
tagstart = p;
taglen = 0;
break;
case TStag:
if (istag(*p))
{ // Continuing tag name
taglen++;
}
else
{ // End of tag name
state = TSrest;
}
break;
case TSrest:
break;
}
p++;
continue;
}
break;
}
// See if we parsed a <code> or </code> tag
if (taglen && memicmp((char *) tagstart, (char *) "CODE", taglen) == 0
&& *(p - 2) != '/') // ignore "<code />" (XHTML)
{
if (inot)
{ inCode--;
if (inCode < 0)
inCode = 0; // ignore extra </code>'s
}
else
inCode++;
}
}
/***********************************************
* Scan to end of attribute string.
*/
void Html::skipString()
{
int tc = *p;
while (1)
{
p++;
switch (*p)
{
case '"':
case '\'':
if (*p == tc)
{ p++;
break;
}
continue;
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++;
// Always extract new lines, so that D lexer counts the
// lines right.
dbuf->writeByte(*p);
continue;
case 0:
case 0x1a:
Leof:
error("end of file before closing %c of string", tc);
break;
default:
Ldefault:
continue;
}
break;
}
}
/*********************************
* If p points to any white space, skip it
* and return pointer just past it.
*/
unsigned char *Html::skipWhite(unsigned char *q)
{
for (; 1; q++)
{
switch (*q)
{
case ' ':
case '\t':
case '\f':
case '\v':
case '\r':
case '\n':
continue;
default:
break;
}
break;
}
return q;
}
/***************************************************
* Scan to end of comment.
* Comments are defined any of a number of ways.
* IE 5.0: <!-- followed by >
* "HTML The Definitive Guide": <!-- text with at least one space in it -->
* Netscape: <!-- --> comments nest
* w3c: whitespace can appear between -- and > of comment close
*/
void Html::scanComment()
{
// Most of the complexity is dealing with the case that
// an arbitrary amount of whitespace can appear between
// the -- and the > of a comment close.
int scangt = 0;
//printf("scanComment()\n");
if (*p == '\n')
{ linnum++;
// Always extract new lines, so that D lexer counts the
// lines right.
dbuf->writeByte(*p);
}
while (1)
{
//scangt = 1; // IE 5.0 compatibility
p++;
switch (*p)
{
case '-':
if (p[1] == '-')
{
if (p[2] == '>') // optimize for most common case
{
p += 3;
break;
}
p++;
scangt = 1;
}
else
scangt = 0;
continue;
case '>':
if (scangt)
{ // found -->
p++;
break;
}
continue;
case ' ':
case '\t':
case '\f':
case '\v':
// skip white space
continue;
case '\r':
if (p[1] == '\n')
goto Ldefault;
case '\n':
linnum++; // remember to count lines
// Always extract new lines, so that D lexer counts the
// lines right.
dbuf->writeByte(*p);
continue;
case 0:
case 0x1a:
error("end of file before closing --> of comment");
break;
default:
Ldefault:
scangt = 0; // it's not -->
continue;
}
break;
}
//printf("*p = '%c'\n", *p);
}
/********************************************
* Determine if we are at the start of a comment.
* Input:
* p is on the opening '<'
* Returns:
* 0 if not start of a comment
* 1 if start of a comment, p is adjusted to point past --
*/
int Html::isCommentStart()
#ifdef __DMC__
__out(result)
{
if (result == 0)
;
else if (result == 1)
{
assert(p[-2] == '-' && p[-1] == '-');
}
else
assert(0);
}
__body
#endif /* __DMC__ */
{ unsigned char *s;
if (p[0] == '<' && p[1] == '!')
{
for (s = p + 2; 1; s++)
{
switch (*s)
{
case ' ':
case '\t':
case '\r':
case '\f':
case '\v':
// skip white space, even though spec says no
// white space is allowed
continue;
case '-':
if (s[1] == '-')
{
p = s + 2;
return 1;
}
goto No;
default:
goto No;
}
}
}
No:
return 0;
}
int Html::isCDATAStart()
{
const char * CDATA_START_MARKER = "<![CDATA[";
size_t len = strlen(CDATA_START_MARKER);
if (strncmp((char*)p, CDATA_START_MARKER, len) == 0)
{
p += len;
return 1;
}
else
{
return 0;
}
}
void Html::scanCDATA()
{
while(*p && *p != 0x1A)
{
int lineSepLength = isLineSeparator(p);
if (lineSepLength>0)
{
/* Always extract new lines, so that D lexer counts the lines
* right.
*/
linnum++;
dbuf->writeByte('\n');
p += lineSepLength;
continue;
}
else if (p[0] == ']' && p[1] == ']' && p[2] == '>')
{
/* end of CDATA section */
p += 3;
return;
}
else if (inCode)
{
/* this CDATA section contains D code */
dbuf->writeByte(*p);
}
p++;
}
}
/********************************************
* Convert an HTML character entity into a character.
* Forms are:
* &name; named entity
* &#ddd; decimal
* &#xhhhh; hex
* Input:
* p is on the &
*/
int Html::charEntity()
{ int c = 0;
int v;
int hex;
unsigned char *pstart = p;
//printf("Html::charEntity('%c')\n", *p);
if (p[1] == '#')
{
p++;
if (p[1] == 'x' || p[1] == 'X')
{ p++;
hex = 1;
}
else
hex = 0;
if (p[1] == ';')
goto Linvalid;
while (1)
{
p++;
switch (*p)
{
case 0:
case 0x1a:
error("end of file before end of character entity");
goto Lignore;
case '\n':
case '\r':
case '<': // tag start
// Termination is assumed
break;
case ';':
// Termination is explicit
p++;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
v = *p - '0';
goto Lvalue;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
if (!hex)
goto Linvalid;
v = (*p - 'a') + 10;
goto Lvalue;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
if (!hex)
goto Linvalid;
v = (*p - 'A') + 10;
goto Lvalue;
Lvalue:
if (hex)
c = (c << 4) + v;
else
c = (c * 10) + v;
if (c > 0x10FFFF)
{
error("character entity out of range");
goto Lignore;
}
continue;
default:
Linvalid:
error("invalid numeric character reference");
goto Lignore;
}
break;
}
}
else
{
// It's a named entity; gather all characters until ;
unsigned char *idstart = p + 1;
while (1)
{
p++;
switch (*p)
{
case 0:
case 0x1a:
error("end of file before end of character entity");
break;
case '\n':
case '\r':
case '<': // tag start
// Termination is assumed
c = HtmlNamedEntity(idstart, p - idstart);
if (c == -1)
goto Lignore;
break;
case ';':
// Termination is explicit
c = HtmlNamedEntity(idstart, p - idstart);
if (c == -1)
goto Lignore;
p++;
break;
default:
continue;
}
break;
}
}
// Kludge to convert non-breaking space to ascii space
if (c == 160)
c = ' ';
return c;
Lignore:
//printf("Lignore\n");
p = pstart + 1;
return '&';
}
/**
* identify DOS, Linux, Mac, Next and Unicode line endings
* 0 if this is no line separator
* >0 the length of the separator
* Note: input has to be UTF-8
*/
static int isLineSeparator(const unsigned char* p)
{
// Linux
if( p[0]=='\n')
return 1;
// Mac & Dos
if( p[0]=='\r')
return (p[1]=='\n') ? 2 : 1;
// Unicode (line || paragraph sep.)
if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9))
return 3;
// Next
if( p[0]==0xC2 && p[1]==0x85)
return 2;
return 0;
}

50
dmd2/html.h Normal file
View File

@@ -0,0 +1,50 @@
// 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 gpl.txt.
// See the included readme.txt for details.
#if MARS
struct OutBuffer;
#else
struct Outbuffer;
#endif
struct Html
{
const char *sourcename;
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
unsigned linnum; // current line number
#if MARS
OutBuffer *dbuf; // code source buffer
#else
Outbuffer *dbuf; // code source buffer
#endif
int inCode; // !=0 if in code
Html(const char *sourcename, unsigned char *base, unsigned length);
void error(const char *format, ...);
#if MARS
void extractCode(OutBuffer *buf);
#else
void extractCode(Outbuffer *buf);
#endif
void skipTag();
void skipString();
unsigned char *skipWhite(unsigned char *q);
void scanComment();
int isCommentStart();
void scanCDATA();
int isCDATAStart();
int charEntity();
static int namedEntity(unsigned char *p, int length);
};

102
dmd2/identifier.c Normal file
View File

@@ -0,0 +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;
}
// 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);
}

47
dmd2/identifier.h Normal file
View File

@@ -0,0 +1,47 @@
// 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.
#ifndef DMD_IDENTIFIER_H
#define DMD_IDENTIFIER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#if IN_LLVM
namespace llvm
{
class Value;
}
#endif
struct Identifier : Object
{
int value;
const char *string;
unsigned len;
Identifier(const char *string, int value);
int equals(Object *o);
hash_t hashCode();
int compare(Object *o);
void print();
char *toChars();
char *toHChars();
const char *toHChars2();
int dyncast();
static Identifier *generateId(const char *prefix);
static Identifier *generateId(const char *prefix, size_t i);
};
#endif /* DMD_IDENTIFIER_H */

435
dmd2/idgen.c Normal file
View File

@@ -0,0 +1,435 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/idgen.c
// 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 <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" },
{ "super" },
{ "ctor", "__ctor" },
{ "dtor", "__dtor" },
{ "cpctor", "__cpctor" },
{ "_postblit", "__postblit" },
{ "classInvariant", "__invariant" },
{ "unitTest", "__unitTest" },
{ "require", "__require" },
{ "ensure", "__ensure" },
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },
{ "__xalignof", "alignof" },
{ "mangleof" },
{ "stringof" },
{ "tupleof" },
{ "length" },
{ "remove" },
{ "ptr" },
{ "array" },
{ "funcptr" },
{ "dollar", "__dollar" },
{ "ctfe", "__ctfe" },
{ "offset" },
{ "offsetof" },
{ "ModuleInfo" },
{ "ClassInfo" },
{ "classinfo" },
{ "typeinfo" },
{ "outer" },
{ "Exception" },
{ "AssociativeArray" },
{ "Throwable" },
{ "Error" },
{ "withSym", "__withSym" },
{ "result", "__result" },
{ "returnLabel", "__returnLabel" },
{ "delegate" },
{ "line" },
{ "empty", "" },
{ "p" },
{ "q" },
{ "coverage", "__coverage" },
{ "__vptr" },
{ "__monitor" },
{ "TypeInfo" },
{ "TypeInfo_Class" },
{ "TypeInfo_Interface" },
{ "TypeInfo_Struct" },
{ "TypeInfo_Enum" },
{ "TypeInfo_Typedef" },
{ "TypeInfo_Pointer" },
{ "TypeInfo_Vector" },
{ "TypeInfo_Array" },
{ "TypeInfo_StaticArray" },
{ "TypeInfo_AssociativeArray" },
{ "TypeInfo_Function" },
{ "TypeInfo_Delegate" },
{ "TypeInfo_Tuple" },
{ "TypeInfo_Const" },
{ "TypeInfo_Invariant" },
{ "TypeInfo_Shared" },
{ "TypeInfo_Wild", "TypeInfo_Inout" },
{ "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" },
{ "min_normal" },
{ "re" },
{ "im" },
{ "C" },
{ "D" },
{ "Windows" },
{ "Pascal" },
{ "System" },
{ "exit" },
{ "success" },
{ "failure" },
{ "keys" },
{ "values" },
{ "rehash" },
{ "sort" },
{ "reverse" },
{ "dup" },
{ "idup" },
{ "property" },
{ "safe" },
{ "trusted" },
{ "system" },
{ "disable" },
// 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" },
{ "opDispatch" },
{ "opDollar" },
{ "opUnary" },
{ "opIndexUnary" },
{ "opSliceUnary" },
{ "opBinary" },
{ "opBinaryRight" },
{ "opOpAssign" },
{ "opIndexOpAssign" },
{ "opSliceOpAssign" },
{ "pow", "opPow" },
{ "pow_r", "opPow_r" },
{ "powass", "opPowAssign" },
{ "classNew", "new" },
{ "classDelete", "delete" },
// For foreach
{ "apply", "opApply" },
{ "applyReverse", "opApplyReverse" },
// Ranges
{ "Fempty", "empty" },
{ "Ffront", "front" },
{ "Fback", "back" },
{ "FpopFront", "popFront" },
{ "FpopBack", "popBack" },
{ "adDup", "_adDupT" },
{ "adReverse", "_adReverse" },
// For internal functions
{ "aaLen", "_aaLen" },
{ "aaKeys", "_aaKeys" },
{ "aaValues", "_aaValues" },
{ "aaRehash", "_aaRehash" },
{ "monitorenter", "_d_monitorenter" },
{ "monitorexit", "_d_monitorexit" },
{ "criticalenter", "_d_criticalenter" },
{ "criticalexit", "_d_criticalexit" },
{ "_ArrayEq" },
// 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" },
{ "fence" },
{ "atomic_load" },
{ "atomic_store" },
{ "atomic_cmp_xchg" },
{ "atomic_rmw" },
#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" },
// varargs implementation
{ "va_argsave_t", "__va_argsave_t" },
{ "va_argsave", "__va_argsave" },
// Builtin functions
{ "std" },
{ "core" },
{ "math" },
{ "sin" },
{ "cos" },
{ "tan" },
{ "_sqrt", "sqrt" },
{ "_pow", "pow" },
{ "atan2" },
{ "rndtol" },
{ "expm1" },
{ "exp2" },
{ "yl2x" },
{ "yl2xp1" },
{ "fabs" },
{ "bitop" },
{ "bsf" },
{ "bsr" },
{ "bswap" },
// Traits
{ "isAbstractClass" },
{ "isArithmetic" },
{ "isAssociativeArray" },
{ "isFinalClass" },
{ "isFloating" },
{ "isIntegral" },
{ "isScalar" },
{ "isStaticArray" },
{ "isUnsigned" },
{ "isVirtualFunction" },
{ "isVirtualMethod" },
{ "isAbstractFunction" },
{ "isFinalFunction" },
{ "isStaticFunction" },
{ "isRef" },
{ "isOut" },
{ "isLazy" },
{ "hasMember" },
{ "identifier" },
{ "parent" },
{ "getMember" },
{ "getOverloads" },
{ "getVirtualFunctions" },
{ "getVirtualMethods" },
{ "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;
}

427
dmd2/impcnvgen.c Normal file
View File

@@ -0,0 +1,427 @@
// 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 "mtype.h"
TY impcnvResult[TMAX][TMAX];
TY impcnvType1[TMAX][TMAX];
TY impcnvType2[TMAX][TMAX];
int impcnvWarn[TMAX][TMAX];
int integral_promotion(int t)
{
switch (t)
{
case Tchar:
case Twchar:
case Tbool:
case Tint8:
case Tuns8:
case Tint16:
case Tuns16: return Tint32;
case Tdchar: return Tuns32;
default: return t;
}
}
void init()
{ int i, j;
// Set conversion tables
for (i = 0; i < TMAX; i++)
for (j = 0; j < TMAX; j++)
{ impcnvResult[i][j] = Terror;
impcnvType1[i][j] = Terror;
impcnvType2[i][j] = Terror;
impcnvWarn[i][j] = 0;
}
#define X(t1,t2, nt1,nt2, rt) \
impcnvResult[t1][t2] = rt; \
impcnvType1[t1][t2] = nt1; \
impcnvType2[t1][t2] = nt2;
/* ======================= */
X(Tbool,Tbool, Tbool,Tbool, Tbool)
X(Tbool,Tint8, Tint32,Tint32, Tint32)
X(Tbool,Tuns8, Tint32,Tint32, Tint32)
X(Tbool,Tint16, Tint32,Tint32, Tint32)
X(Tbool,Tuns16, Tint32,Tint32, Tint32)
X(Tbool,Tint32, Tint32,Tint32, Tint32)
X(Tbool,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tbool,Tint64, Tint64,Tint64, Tint64)
X(Tbool,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tbool,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tbool,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tbool,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tbool,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tbool,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tbool,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tbool,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tbool,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tbool,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint8,Tint8, Tint32,Tint32, Tint32)
X(Tint8,Tuns8, Tint32,Tint32, Tint32)
X(Tint8,Tint16, Tint32,Tint32, Tint32)
X(Tint8,Tuns16, Tint32,Tint32, Tint32)
X(Tint8,Tint32, Tint32,Tint32, Tint32)
X(Tint8,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tint8,Tint64, Tint64,Tint64, Tint64)
X(Tint8,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint8,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint8,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint8,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint8,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint8,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint8,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns8,Tuns8, Tint32,Tint32, Tint32)
X(Tuns8,Tint16, Tint32,Tint32, Tint32)
X(Tuns8,Tuns16, Tint32,Tint32, Tint32)
X(Tuns8,Tint32, Tint32,Tint32, Tint32)
X(Tuns8,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tuns8,Tint64, Tint64,Tint64, Tint64)
X(Tuns8,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns8,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns8,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns8,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns8,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns8,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns8,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint16,Tint16, Tint32,Tint32, Tint32)
X(Tint16,Tuns16, Tint32,Tint32, Tint32)
X(Tint16,Tint32, Tint32,Tint32, Tint32)
X(Tint16,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tint16,Tint64, Tint64,Tint64, Tint64)
X(Tint16,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint16,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint16,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint16,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint16,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint16,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint16,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns16,Tuns16, Tint32,Tint32, Tint32)
X(Tuns16,Tint32, Tint32,Tint32, Tint32)
X(Tuns16,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tuns16,Tint64, Tint64,Tint64, Tint64)
X(Tuns16,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns16,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns16,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns16,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns16,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns16,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns16,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint32,Tint32, Tint32,Tint32, Tint32)
X(Tint32,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tint32,Tint64, Tint64,Tint64, Tint64)
X(Tint32,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns32,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tuns32,Tint64, Tint64,Tint64, Tint64)
X(Tuns32,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tint64,Tint64, Tint64,Tint64, Tint64)
X(Tint64,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tint64,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tint64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tint64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tint64,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tint64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tint64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tint64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tint64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tint64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tuns64,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tuns64,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tuns64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tuns64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tuns64,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tuns64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tuns64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tuns64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tuns64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tuns64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tfloat32,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tfloat32,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tfloat32,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tfloat32,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tfloat32,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tfloat32,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tfloat32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tfloat32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tfloat64,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tfloat64,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tfloat64,Timaginary32, Tfloat64,Timaginary64, Tfloat64)
X(Tfloat64,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tfloat64,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat64,Tcomplex32, Tfloat64,Tcomplex64, Tcomplex64)
X(Tfloat64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tfloat64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tfloat80,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tfloat80,Timaginary32, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat80,Timaginary64, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat80,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tfloat80,Tcomplex32, Tfloat80,Tcomplex80, Tcomplex80)
X(Tfloat80,Tcomplex64, Tfloat80,Tcomplex80, Tcomplex80)
X(Tfloat80,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Timaginary32,Timaginary32, Timaginary32,Timaginary32, Timaginary32)
X(Timaginary32,Timaginary64, Timaginary64,Timaginary64, Timaginary64)
X(Timaginary32,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
X(Timaginary32,Tcomplex32, Timaginary32,Tcomplex32, Tcomplex32)
X(Timaginary32,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64)
X(Timaginary32,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Timaginary64,Timaginary64, Timaginary64,Timaginary64, Timaginary64)
X(Timaginary64,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
X(Timaginary64,Tcomplex32, Timaginary64,Tcomplex64, Tcomplex64)
X(Timaginary64,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64)
X(Timaginary64,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Timaginary80,Timaginary80, Timaginary80,Timaginary80, Timaginary80)
X(Timaginary80,Tcomplex32, Timaginary80,Tcomplex80, Tcomplex80)
X(Timaginary80,Tcomplex64, Timaginary80,Tcomplex80, Tcomplex80)
X(Timaginary80,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tcomplex32,Tcomplex32, Tcomplex32,Tcomplex32, Tcomplex32)
X(Tcomplex32,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64)
X(Tcomplex32,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tcomplex64,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64)
X(Tcomplex64,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
/* ======================= */
X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80)
#undef X
#define Y(t1,t2) impcnvWarn[t1][t2] = 1;
Y(Tuns8, Tint8)
Y(Tint16, Tint8)
Y(Tuns16, Tint8)
Y(Tint32, Tint8)
Y(Tuns32, Tint8)
Y(Tint64, Tint8)
Y(Tuns64, Tint8)
Y(Tint8, Tuns8)
Y(Tint16, Tuns8)
Y(Tuns16, Tuns8)
Y(Tint32, Tuns8)
Y(Tuns32, Tuns8)
Y(Tint64, Tuns8)
Y(Tuns64, Tuns8)
Y(Tint8, Tchar)
Y(Tint16, Tchar)
Y(Tuns16, Tchar)
Y(Tint32, Tchar)
Y(Tuns32, Tchar)
Y(Tint64, Tchar)
Y(Tuns64, Tchar)
Y(Tuns16, Tint16)
Y(Tint32, Tint16)
Y(Tuns32, Tint16)
Y(Tint64, Tint16)
Y(Tuns64, Tint16)
Y(Tint16, Tuns16)
Y(Tint32, Tuns16)
Y(Tuns32, Tuns16)
Y(Tint64, Tuns16)
Y(Tuns64, Tuns16)
Y(Tint16, Twchar)
Y(Tint32, Twchar)
Y(Tuns32, Twchar)
Y(Tint64, Twchar)
Y(Tuns64, Twchar)
// Y(Tuns32, Tint32)
Y(Tint64, Tint32)
Y(Tuns64, Tint32)
// Y(Tint32, Tuns32)
Y(Tint64, Tuns32)
Y(Tuns64, Tuns32)
Y(Tint64, Tdchar)
Y(Tuns64, Tdchar)
// Y(Tint64, Tuns64)
// Y(Tuns64, Tint64)
for (i = 0; i < TMAX; i++)
for (j = 0; j < TMAX; j++)
{
if (impcnvResult[i][j] == Terror)
{
impcnvResult[i][j] = impcnvResult[j][i];
impcnvType1[i][j] = impcnvType2[j][i];
impcnvType2[i][j] = impcnvType1[j][i];
}
}
}
int main()
{ FILE *fp;
int i;
int j;
init();
fp = fopen("impcnvtab.c","w");
fprintf(fp,"// This file is generated by impcnvgen.c\n");
fprintf(fp,"#include \"mtype.h\"\n");
fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvResult[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvType1[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvType2[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvWarn[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp,"};\n");
fclose(fp);
return EXIT_SUCCESS;
}

88
dmd2/imphint.c Normal file
View File

@@ -0,0 +1,88 @@
// Compiler implementation of the D programming language
// Copyright (c) 2010 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 <string.h>
#include "mars.h"
/******************************************
* Looks for undefined identifier s to see
* if it might be undefined because an import
* was not specified.
* Not meant to be a comprehensive list of names in each module,
* just the most common ones.
*/
const char *importHint(const char *s)
{
#if DMDV1
static const char *modules[] =
{ "std.c.stdio",
"std.stdio",
"std.math",
"std.c.stdarg",
};
static const char *names[] =
{
"printf", NULL,
"writefln", NULL,
"sin", "cos", "sqrt", "fabs", NULL,
"__va_argsave_t", NULL,
};
#else
static const char *modules[] =
{ "core.stdc.stdio",
"std.stdio",
"std.math",
"core.vararg",
};
static const char *names[] =
{
"printf", NULL,
"writeln", NULL,
"sin", "cos", "sqrt", "fabs", NULL,
"__va_argsave_t", NULL,
};
#endif
int m = 0;
for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++)
{
const char *p = names[n];
if (p == NULL)
{ m++;
continue;
}
assert(m < sizeof(modules)/sizeof(modules[0]));
if (strcmp(s, p) == 0)
return modules[m];
}
return NULL; // didn't find it
}
#if UNITTEST
void unittest_importHint()
{
const char *p;
p = importHint("printf");
assert(p);
p = importHint("fabs");
assert(p);
p = importHint("xxxxx");
assert(!p);
}
#endif

397
dmd2/import.c Normal file
View File

@@ -0,0 +1,397 @@
// 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"
#include "attrib.h"
/********************************* Import ****************************/
Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(NULL)
{
assert(id);
this->loc = loc;
this->packages = packages;
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
this->protection = PROTprivate; // default to private
this->pkg = NULL;
this->mod = NULL;
// Set symbol name (bracketed)
// import [cstdio] = std.stdio;
if (aliasId)
this->ident = aliasId;
// import [std].stdio;
else if (packages && packages->dim)
this->ident = packages->tdata()[0];
// import [foo];
else
this->ident = id;
}
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(names.tdata()[i], aliases.tdata()[i]);
}
return si;
}
void Import::load(Scope *sc)
{
//printf("Import::load('%s')\n", toChars());
// See if existing module
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
Dsymbol *s = dst->lookup(id);
if (s)
{
#if TARGET_NET
mod = (Module *)s;
#else
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
#endif
}
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);
}
void escapePath(OutBuffer *buf, const char *fname)
{
while (1)
{
switch (*fname)
{
case 0:
return;
case '(':
case ')':
case '\\':
buf->writebyte('\\');
default:
buf->writebyte(*fname);
break;
}
fname++;
}
}
void Import::importAll(Scope *sc)
{
if (!mod)
{
load(sc);
mod->importAll(0);
if (!isstatic && !aliasId && !names.dim)
{
if (sc->explicitProtection)
protection = sc->protection;
sc->scopesym->importScope(mod, protection);
}
}
}
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
// Load if not already done so
if (!mod)
{ load(sc);
mod->importAll(0);
}
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);
if (!isstatic && !aliasId && !names.dim)
{
if (sc->explicitProtection)
protection = sc->protection;
for (Scope *scd = sc; scd; scd = scd->enclosing)
{
if (scd->scopesym)
{
scd->scopesym->importScope(mod, protection);
break;
}
}
}
mod->semantic();
if (mod->needmoduleinfo)
{ //printf("module4 %s because of %s\n", sc->module->toChars(), mod->toChars());
sc->module->needmoduleinfo = 1;
}
sc = sc->push(mod);
/* BUG: Protection checks can't be enabled yet. The issue is
* that Dsymbol::search errors before overload resolution.
*/
#if 0
sc->protection = protection;
#else
sc->protection = PROTpublic;
#endif
for (size_t i = 0; i < aliasdecls.dim; i++)
{ Dsymbol *s = aliasdecls.tdata()[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, names.tdata()[i], 0))
error("%s not found", (names.tdata()[i])->toChars());
s->semantic(sc);
}
sc = sc->pop();
}
if (global.params.moduleDeps != NULL)
{
/* The grammar of the file is:
* ImportDeclaration
* ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
* ModuleAliasIdentifier ] "\n"
*
* BasicImportDeclaration
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
*
* FilePath
* - any string with '(', ')' and '\' escaped with the '\' character
*/
OutBuffer *ob = global.params.moduleDeps;
ob->writestring(sc->module->toPrettyChars());
ob->writestring(" (");
escapePath(ob, sc->module->srcfile->toChars());
ob->writestring(") : ");
ProtDeclaration::protectionToCBuffer(ob, sc->protection);
if (isstatic)
StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
ob->writestring(": ");
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{
Identifier *pid = packages->tdata()[i];
ob->printf("%s.", pid->toChars());
}
}
ob->writestring(id->toChars());
ob->writestring(" (");
if (mod)
escapePath(ob, mod->srcfile->toChars());
else
ob->writestring("???");
ob->writebyte(')');
for (size_t i = 0; i < names.dim; i++)
{
if (i == 0)
ob->writebyte(':');
else
ob->writebyte(',');
Identifier *name = names.tdata()[i];
Identifier *alias = aliases.tdata()[i];
if (!alias)
{
ob->printf("%s", name->toChars());
alias = name;
}
else
ob->printf("%s=%s", alias->toChars(), name->toChars());
}
if (aliasId)
ob->printf(" -> %s", aliasId->toChars());
ob->writenl();
}
//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)
{ //printf("module5 %s because of %s\n", sc->module->toChars(), mod->toChars());
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 = names.tdata()[i];
Identifier *alias = aliases.tdata()[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 = packages->tdata()[i];
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s;", id->toChars());
buf->writenl();
}

66
dmd2/import.h Normal file
View File

@@ -0,0 +1,66 @@
// 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_IMPORT_H
#define DMD_IMPORT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Identifier;
struct Scope;
struct OutBuffer;
struct Module;
struct Package;
struct AliasDeclaration;
struct HdrGenState;
struct Import : Dsymbol
{
Identifiers *packages; // array of Identifier's representing packages
Identifier *id; // module Identifier
Identifier *aliasId;
int isstatic; // !=0 if static import
enum PROT protection;
// Pairs of alias=name to bind into current namespace
Identifiers names;
Identifiers aliases;
AliasDeclarations aliasdecls; // AliasDeclarations for names/aliases
Module *mod;
Package *pkg; // leftmost package/module
Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
int isstatic);
void addAlias(Identifier *name, Identifier *alias);
const char *kind();
enum PROT prot();
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void importAll(Scope *sc);
void semantic(Scope *sc);
void semantic2(Scope *sc);
Dsymbol *toAlias();
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Import *isImport() { return this; }
};
#endif /* DMD_IMPORT_H */

328
dmd2/inifile.c Normal file
View File

@@ -0,0 +1,328 @@
/*
* Some portions copyright (c) 1994-1995 by Symantec
* Copyright (c) 1999-2011 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 _WIN32
#include <windows.h>
#endif
#if __APPLE__
#include <sys/syslimits.h>
#endif
#if __FreeBSD__ || __OpenBSD__ || __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
* Returns:
* file name of ini file
* Note: this is a memory leak
*/
const char *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 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))
{
#if _WIN32 // This fix by Tim Matthews
char resolved_name[MAX_PATH + 1];
if(GetModuleFileName(NULL, resolved_name, MAX_PATH + 1) && FileName::exists(resolved_name))
{
filename = (char *)FileName::replaceName(resolved_name, inifile);
if(FileName::exists(filename))
goto Ldone;
}
#endif
filename = (char *)FileName::replaceName(argv0, inifile);
if (!FileName::exists(filename))
{
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#if __GLIBC__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __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__ || __OpenBSD__ || __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");
Strings *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;
}
// Search /etc/ for inifile
Letc:
#endif
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 filename; // error reading file
// Parse into lines
int eof = 0;
for (size_t i = 0; i < file.len && !eof; i++)
{
size_t 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;
size_t 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 (size_t k = 0; k < len; k++)
{
if (line[k] == '%')
{
for (size_t 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
{ size_t len2 = j - k;
char tmp[10]; // big enough most of the time
if (len2 <= sizeof(tmp))
p = tmp;
else
p = (char *)alloca(len2);
len2--;
memcpy(p, &line[k + 1], len2);
p[len2] = 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((unsigned char)*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((unsigned char)*p))
*p &= ~0x20;
else if (isspace((unsigned char)*p))
memmove(p, p + 1, strlen(p));
else if (*p == '=')
{
p++;
while (isspace((unsigned char)*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:
;
}
return filename;
}
/********************
* Skip spaces.
*/
char *skipspace(const char *p)
{
while (isspace((unsigned char)*p))
p++;
return (char *)p;
}

911
dmd2/init.c Normal file
View File

@@ -0,0 +1,911 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 "init.h"
#include "expression.h"
#include "statement.h"
#include "identifier.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
#include "mtype.h"
#include "hdrgen.h"
/********************************** Initializer *******************************/
Initializer::Initializer(Loc loc)
{
this->loc = loc;
}
Initializer *Initializer::syntaxCopy()
{
return this;
}
Initializer *Initializer::semantic(Scope *sc, Type *t, int needInterpret)
{
return this;
}
Type *Initializer::inferType(Scope *sc)
{
error(loc, "cannot infer type from initializer");
return Type::terror;
}
Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
{ Initializers *a = NULL;
if (ai)
{
a = new Initializers();
a->setDim(ai->dim);
for (size_t i = 0; i < a->dim; i++)
{ Initializer *e = ai->tdata()[i];
e = e->syntaxCopy();
a->tdata()[i] = e;
}
}
return a;
}
char *Initializer::toChars()
{ OutBuffer *buf;
HdrGenState hgs;
memset(&hgs, 0, sizeof(hgs));
buf = new OutBuffer();
toCBuffer(buf, &hgs);
return buf->toChars();
}
/********************************** VoidInitializer ***************************/
VoidInitializer::VoidInitializer(Loc loc)
: Initializer(loc)
{
type = NULL;
}
Initializer *VoidInitializer::syntaxCopy()
{
return new VoidInitializer(loc);
}
Initializer *VoidInitializer::semantic(Scope *sc, Type *t, int needInterpret)
{
//printf("VoidInitializer::semantic(t = %p)\n", t);
type = t;
return this;
}
Expression *VoidInitializer::toExpression()
{
error(loc, "void initializer has no value");
return new IntegerExp(0);
}
void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("void");
}
/********************************** StructInitializer *************************/
StructInitializer::StructInitializer(Loc loc)
: Initializer(loc)
{
ad = NULL;
#if IN_LLVM
ltype = NULL;
#endif
}
Initializer *StructInitializer::syntaxCopy()
{
StructInitializer *ai = new StructInitializer(loc);
assert(field.dim == value.dim);
ai->field.setDim(field.dim);
ai->value.setDim(value.dim);
for (size_t i = 0; i < field.dim; i++)
{
ai->field.tdata()[i] = field.tdata()[i];
Initializer *init = value.tdata()[i];
init = init->syntaxCopy();
ai->value.tdata()[i] = init;
}
return ai;
}
void StructInitializer::addInit(Identifier *field, Initializer *value)
{
//printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
this->field.push(field);
this->value.push(value);
}
Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
{
int errors = 0;
//printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
vars.setDim(field.dim);
t = t->toBasetype();
if (t->ty == Tstruct)
{
unsigned fieldi = 0;
TypeStruct *ts = (TypeStruct *)t;
ad = ts->sym;
if (ad->ctor)
error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
ad->kind(), ad->toChars(), ad->toChars());
size_t nfields = ad->fields.dim;
if (((StructDeclaration *)ad)->isnested) nfields--;
for (size_t i = 0; i < field.dim; i++)
{
Identifier *id = field.tdata()[i];
Initializer *val = value.tdata()[i];
Dsymbol *s;
VarDeclaration *v;
if (id == NULL)
{
if (fieldi >= nfields)
{ error(loc, "too many initializers for %s", ad->toChars());
errors = 1;
field.remove(i);
i--;
continue;
}
else
{
s = ad->fields.tdata()[fieldi];
}
}
else
{
//s = ad->symtab->lookup(id);
s = ad->search(loc, id, 0);
if (!s)
{
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
errors = 1;
continue;
}
s = s->toAlias();
// Find out which field index it is
for (fieldi = 0; 1; fieldi++)
{
if (fieldi >= nfields)
{
error(loc, "%s.%s is not a per-instance initializable field",
t->toChars(), s->toChars());
errors = 1;
break;
}
if (s == ad->fields.tdata()[fieldi])
break;
}
}
if (s && (v = s->isVarDeclaration()) != NULL)
{
val = val->semantic(sc, v->type, needInterpret);
value.tdata()[i] = val;
vars.tdata()[i] = v;
}
else
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
errors = 1;
}
fieldi++;
}
}
else if (t->ty == Tdelegate && value.dim == 0)
{ /* Rewrite as empty delegate literal { }
*/
Parameters *arguments = new Parameters;
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
fd->fbody = new CompoundStatement(loc, new Statements());
fd->endloc = loc;
Expression *e = new FuncExp(loc, fd);
ExpInitializer *ie = new ExpInitializer(loc, e);
return ie->semantic(sc, t, needInterpret);
}
else
{
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
errors = 1;
}
if (errors)
{
field.setDim(0);
value.setDim(0);
vars.setDim(0);
}
return this;
}
/***************************************
* This works by transforming a struct initializer into
* a struct literal. In the future, the two should be the
* same thing.
*/
Expression *StructInitializer::toExpression()
{ Expression *e;
size_t offset;
//printf("StructInitializer::toExpression() %s\n", toChars());
if (!ad) // if fwd referenced
{
return NULL;
}
StructDeclaration *sd = ad->isStructDeclaration();
if (!sd)
return NULL;
Expressions *elements = new Expressions();
size_t nfields = ad->fields.dim;
#if DMDV2
if (sd->isnested)
nfields--;
#endif
elements->setDim(nfields);
for (size_t i = 0; i < elements->dim; i++)
{
elements->tdata()[i] = NULL;
}
unsigned fieldi = 0;
for (size_t i = 0; i < value.dim; i++)
{
Identifier *id = field.tdata()[i];
if (id)
{
Dsymbol * s = ad->search(loc, id, 0);
if (!s)
{
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
goto Lno;
}
s = s->toAlias();
// Find out which field index it is
for (fieldi = 0; 1; fieldi++)
{
if (fieldi >= nfields)
{
s->error("is not a per-instance initializable field");
goto Lno;
}
if (s == ad->fields.tdata()[fieldi])
break;
}
}
else if (fieldi >= nfields)
{ error(loc, "too many initializers for '%s'", ad->toChars());
goto Lno;
}
Initializer *iz = value.tdata()[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
goto Lno;
if (elements->tdata()[fieldi])
{ error(loc, "duplicate initializer for field '%s'",
ad->fields.tdata()[fieldi]->toChars());
goto Lno;
}
elements->tdata()[fieldi] = ex;
++fieldi;
}
// Now, fill in any missing elements with default initializers.
// We also need to validate any anonymous unions
offset = 0;
for (size_t i = 0; i < elements->dim; )
{
VarDeclaration * vd = ad->fields.tdata()[i]->isVarDeclaration();
//printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset);
if (vd->offset < offset)
{
// Only the first field of a union can have an initializer
if (elements->tdata()[i])
goto Lno;
}
else
{
if (!elements->tdata()[i])
// Default initialize
elements->tdata()[i] = vd->type->defaultInit();
}
offset = vd->offset + vd->type->size();
i++;
#if 0
int unionSize = ad->numFieldsInUnion(i);
if (unionSize == 1)
{ // Not a union -- default initialize if missing
if (!elements->tdata()[i])
elements->tdata()[i] = vd->type->defaultInit();
}
else
{ // anonymous union -- check for errors
int found = -1; // index of the first field with an initializer
for (int j = i; j < i + unionSize; ++j)
{
if (!elements->tdata()[j])
continue;
if (found >= 0)
{
VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration();
VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration();
error(loc, "%s cannot have initializers for fields %s and %s in same union",
ad->toChars(),
v1->toChars(), v->toChars());
goto Lno;
}
found = j;
}
if (found == -1)
{
error(loc, "no initializer for union that contains field %s",
vd->toChars());
goto Lno;
}
}
i += unionSize;
#endif
}
e = new StructLiteralExp(loc, sd, elements);
e->type = sd->type;
return e;
Lno:
delete elements;
return NULL;
}
void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
//printf("StructInitializer::toCBuffer()\n");
buf->writebyte('{');
for (size_t i = 0; i < field.dim; i++)
{
if (i > 0)
buf->writebyte(',');
Identifier *id = field.tdata()[i];
if (id)
{
buf->writestring(id->toChars());
buf->writebyte(':');
}
Initializer *iz = value.tdata()[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
buf->writebyte('}');
}
/********************************** ArrayInitializer ************************************/
ArrayInitializer::ArrayInitializer(Loc loc)
: Initializer(loc)
{
dim = 0;
type = NULL;
sem = 0;
}
Initializer *ArrayInitializer::syntaxCopy()
{
//printf("ArrayInitializer::syntaxCopy()\n");
ArrayInitializer *ai = new ArrayInitializer(loc);
assert(index.dim == value.dim);
ai->index.setDim(index.dim);
ai->value.setDim(value.dim);
for (size_t i = 0; i < ai->value.dim; i++)
{ Expression *e = index.tdata()[i];
if (e)
e = e->syntaxCopy();
ai->index.tdata()[i] = e;
Initializer *init = value.tdata()[i];
init = init->syntaxCopy();
ai->value.tdata()[i] = init;
}
return ai;
}
void ArrayInitializer::addInit(Expression *index, Initializer *value)
{
this->index.push(index);
this->value.push(value);
dim = 0;
type = NULL;
}
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
{ unsigned i;
unsigned length;
const unsigned amax = 0x80000000;
//printf("ArrayInitializer::semantic(%s)\n", t->toChars());
if (sem) // if semantic() already run
return this;
sem = 1;
type = t;
t = t->toBasetype();
switch (t->ty)
{
case Tpointer:
case Tsarray:
case Tarray:
break;
default:
error(loc, "cannot use array to initialize %s", type->toChars());
goto Lerr;
}
length = 0;
for (i = 0; i < index.dim; i++)
{
Expression *idx = index.tdata()[i];
if (idx)
{ idx = idx->semantic(sc);
idx = idx->optimize(WANTvalue | WANTinterpret);
index.tdata()[i] = idx;
length = idx->toInteger();
}
Initializer *val = value.tdata()[i];
val = val->semantic(sc, t->nextOf(), needInterpret);
value.tdata()[i] = val;
length++;
if (length == 0)
{ error(loc, "array dimension overflow");
goto Lerr;
}
if (length > dim)
dim = length;
}
if (t->ty == Tsarray)
{
dinteger_t edim = ((TypeSArray *)t)->dim->toInteger();
if (dim > edim)
{
error(loc, "array initializer has %u elements, but array length is %jd", dim, edim);
goto Lerr;
}
}
if ((unsigned long) dim * t->nextOf()->size() >= amax)
{ error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size());
goto Lerr;
}
return this;
Lerr:
return new ExpInitializer(loc, new ErrorExp());
}
/********************************
* If possible, convert array initializer to array literal.
* Otherwise return NULL.
*/
Expression *ArrayInitializer::toExpression()
{ Expressions *elements;
//printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
//static int i; if (++i == 2) halt();
size_t edim;
Type *t = NULL;
if (type)
{
if (type == Type::terror)
return new ErrorExp();
t = type->toBasetype();
switch (t->ty)
{
case Tsarray:
edim = ((TypeSArray *)t)->dim->toInteger();
break;
case Tpointer:
case Tarray:
edim = dim;
break;
default:
assert(0);
}
}
else
{
edim = value.dim;
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.tdata()[i])
j = index.tdata()[i]->toInteger();
if (j >= edim)
edim = j + 1;
}
}
elements = new Expressions();
elements->setDim(edim);
elements->zero();
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.tdata()[i])
j = (index.tdata()[i])->toInteger();
assert(j < edim);
Initializer *iz = value.tdata()[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
{
goto Lno;
}
elements->tdata()[j] = ex;
}
/* Fill in any missing elements with the default initializer
*/
{
Expression *init = NULL;
for (size_t i = 0; i < edim; i++)
{
if (!elements->tdata()[i])
{
if (!type)
goto Lno;
if (!init)
init = ((TypeNext *)t)->next->defaultInit();
elements->tdata()[i] = init;
}
}
Expression *e = new ArrayLiteralExp(loc, elements);
e->type = type;
return e;
}
Lno:
return NULL;
}
/********************************
* If possible, convert array initializer to associative array initializer.
*/
Expression *ArrayInitializer::toAssocArrayLiteral()
{
Expression *e;
//printf("ArrayInitializer::toAssocArrayInitializer()\n");
//static int i; if (++i == 2) halt();
Expressions *keys = new Expressions();
keys->setDim(value.dim);
Expressions *values = new Expressions();
values->setDim(value.dim);
for (size_t i = 0; i < value.dim; i++)
{
e = index.tdata()[i];
if (!e)
goto Lno;
keys->tdata()[i] = e;
Initializer *iz = value.tdata()[i];
if (!iz)
goto Lno;
e = iz->toExpression();
if (!e)
goto Lno;
values->tdata()[i] = e;
}
e = new AssocArrayLiteralExp(loc, keys, values);
return e;
Lno:
delete keys;
delete values;
error(loc, "not an associative array initializer");
return new ErrorExp();
}
int ArrayInitializer::isAssociativeArray()
{
for (size_t i = 0; i < value.dim; i++)
{
if (index.tdata()[i])
return 1;
}
return 0;
}
Type *ArrayInitializer::inferType(Scope *sc)
{
//printf("ArrayInitializer::inferType() %s\n", toChars());
assert(0);
return NULL;
#if 0
type = Type::terror;
for (size_t i = 0; i < value.dim; i++)
{
if (index.data[i])
goto Laa;
}
for (size_t i = 0; i < value.dim; i++)
{
Initializer *iz = (Initializer *)value.data[i];
if (iz)
{ Type *t = iz->inferType(sc);
if (i == 0)
{ /* BUG: This gets the type from the first element.
* Fix to use all the elements to figure out the type.
*/
t = new TypeSArray(t, new IntegerExp(value.dim));
t = t->semantic(loc, sc);
type = t;
}
}
}
return type;
Laa:
/* It's possibly an associative array initializer.
* BUG: inferring type from first member.
*/
Initializer *iz = (Initializer *)value.data[0];
Expression *indexinit = (Expression *)index.data[0];
if (iz && indexinit)
{ Type *t = iz->inferType(sc);
indexinit = indexinit->semantic(sc);
Type *indext = indexinit->type;
t = new TypeAArray(t, indext);
type = t->semantic(loc, sc);
}
else
error(loc, "cannot infer type from this array initializer");
return type;
#endif
}
void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writebyte('[');
for (size_t i = 0; i < index.dim; i++)
{
if (i > 0)
buf->writebyte(',');
Expression *ex = index.tdata()[i];
if (ex)
{
ex->toCBuffer(buf, hgs);
buf->writebyte(':');
}
Initializer *iz = value.tdata()[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
buf->writebyte(']');
}
/********************************** ExpInitializer ************************************/
ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
: Initializer(loc)
{
this->exp = exp;
}
Initializer *ExpInitializer::syntaxCopy()
{
return new ExpInitializer(loc, exp->syntaxCopy());
}
bool arrayHasNonConstPointers(Expressions *elems);
bool hasNonConstPointers(Expression *e)
{
if (e->op == TOKnull)
return false;
if (e->op == TOKstructliteral)
{
StructLiteralExp *se = (StructLiteralExp *)e;
return arrayHasNonConstPointers(se->elements);
}
if (e->op == TOKarrayliteral)
{
if (!e->type->nextOf()->hasPointers())
return false;
ArrayLiteralExp *ae = (ArrayLiteralExp *)e;
return arrayHasNonConstPointers(ae->elements);
}
if (e->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e;
if (ae->type->nextOf()->hasPointers() &&
arrayHasNonConstPointers(ae->values))
return true;
if (((TypeAArray *)ae->type)->index->hasPointers())
return arrayHasNonConstPointers(ae->keys);
return false;
}
if (e->type->ty== Tpointer && e->type->nextOf()->ty != Tfunction)
{
#if IN_LLVM
// address of a global is OK
if (e->op == TOKaddress || e->op == TOKcast)
return false;
if (e->op == TOKadd || e->op == TOKmin) {
BinExp *be = (BinExp*)e;
if (be->e1->type->ty == Tpointer || be->e2->type->ty == Tpointer)
return false;
}
#else
if (e->op == TOKsymoff) // address of a global is OK
return false;
#endif
if (e->op == TOKint64) // cast(void *)int is OK
return false;
if (e->op == TOKstring) // "abc".ptr is OK
return false;
return true;
}
return false;
}
bool arrayHasNonConstPointers(Expressions *elems)
{
for (size_t i = 0; i < elems->dim; i++)
{
if (!elems->tdata()[i])
continue;
if (hasNonConstPointers(elems->tdata()[i]))
return true;
}
return false;
}
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
{
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
int wantOptimize = needInterpret ? WANTinterpret|WANTvalue : WANTvalue;
int olderrors = global.errors;
exp = exp->optimize(wantOptimize);
if (!global.gag && olderrors != global.errors)
return this; // Failed, suppress duplicate error messages
if (exp->op == TOKtype)
error("initializer must be an expression, not '%s'", exp->toChars());
// Make sure all pointers are constants
if (needInterpret && hasNonConstPointers(exp))
{
exp->error("cannot use non-constant CTFE pointer in an initializer '%s'", exp->toChars());
return this;
}
Type *tb = t->toBasetype();
/* Look for case of initializing a static array with a too-short
* string literal, such as:
* char[5] foo = "abc";
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
{ StringExp *se = (StringExp *)exp;
if (!se->committed && se->type->ty == Tsarray &&
((TypeSArray *)se->type)->dim->toInteger() <
((TypeSArray *)t)->dim->toInteger())
{
exp = se->castTo(sc, t);
goto L1;
}
}
// Look for the case of statically initializing an array
// with a single member.
if (tb->ty == Tsarray &&
!tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) &&
exp->implicitConvTo(tb->nextOf())
)
{
t = tb->nextOf();
}
exp = exp->implicitCastTo(sc, t);
L1:
exp = exp->optimize(wantOptimize);
//printf("-ExpInitializer::semantic(): "); exp->print();
return this;
}
Type *ExpInitializer::inferType(Scope *sc)
{
//printf("ExpInitializer::inferType() %s\n", toChars());
if (exp->op == TOKfunction && ((FuncExp *)exp)->td)
{
exp->error("cannot infer type from ambiguous function literal %s", exp->toChars());
return Type::terror;
}
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
// Give error for overloaded function addresses
if (exp->op == TOKsymoff)
{ SymOffExp *se = (SymOffExp *)exp;
if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
}
// Give error for overloaded function addresses
if (exp->op == TOKdelegate)
{ DelegateExp *se = (DelegateExp *)exp;
if (
se->func->isFuncDeclaration() &&
!se->func->isFuncDeclaration()->isUnique())
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
}
Type *t = exp->type;
if (!t)
t = Initializer::inferType(sc);
return t;
}
Expression *ExpInitializer::toExpression()
{
return exp;
}
void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
exp->toCBuffer(buf, hgs);
}

149
dmd2/init.h Normal file
View File

@@ -0,0 +1,149 @@
// 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 INIT_H
#define INIT_H
#include "root.h"
#include "mars.h"
#include "arraytypes.h"
struct Identifier;
struct Expression;
struct Scope;
struct Type;
struct dt_t;
struct AggregateDeclaration;
struct VoidInitializer;
struct StructInitializer;
struct ArrayInitializer;
struct ExpInitializer;
struct HdrGenState;
#if IN_LLVM
namespace llvm {
class StructType;
}
#endif
struct Initializer : Object
{
Loc loc;
Initializer(Loc loc);
virtual Initializer *syntaxCopy();
// needInterpret is WANTinterpret if must be a manifest constant, 0 if not.
virtual Initializer *semantic(Scope *sc, Type *t, int needInterpret);
virtual Type *inferType(Scope *sc);
virtual Expression *toExpression() = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
char *toChars();
static Initializers *arraySyntaxCopy(Initializers *ai);
#if IN_DMD
virtual dt_t *toDt();
#endif
virtual VoidInitializer *isVoidInitializer() { return NULL; }
virtual StructInitializer *isStructInitializer() { return NULL; }
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
virtual ExpInitializer *isExpInitializer() { return NULL; }
};
struct VoidInitializer : Initializer
{
Type *type; // type that this will initialize to
VoidInitializer(Loc loc);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
#endif
virtual VoidInitializer *isVoidInitializer() { return this; }
};
struct StructInitializer : Initializer
{
Identifiers field; // of Identifier *'s
Initializers value; // parallel array of Initializer *'s
VarDeclarations vars; // parallel array of VarDeclaration *'s
AggregateDeclaration *ad; // which aggregate this is for
StructInitializer(Loc loc);
Initializer *syntaxCopy();
void addInit(Identifier *field, Initializer *value);
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
#endif
StructInitializer *isStructInitializer() { return this; }
#if IN_LLVM
llvm::StructType *ltype;
#endif
};
struct ArrayInitializer : Initializer
{
Expressions index; // indices
Initializers value; // of Initializer *'s
unsigned dim; // length of array being initialized
Type *type; // type that array will be used to initialize
int sem; // !=0 if semantic() is run
ArrayInitializer(Loc loc);
Initializer *syntaxCopy();
void addInit(Expression *index, Initializer *value);
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
int isAssociativeArray();
Type *inferType(Scope *sc);
Expression *toExpression();
Expression *toAssocArrayLiteral();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
dt_t *toDtBit(); // for bit arrays
#endif
ArrayInitializer *isArrayInitializer() { return this; }
};
struct ExpInitializer : Initializer
{
Expression *exp;
ExpInitializer(Loc loc, Expression *exp);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Type *inferType(Scope *sc);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
dt_t *toDt();
#endif
virtual ExpInitializer *isExpInitializer() { return this; }
};
#endif

1831
dmd2/inline.c Normal file

File diff suppressed because it is too large Load Diff

6586
dmd2/interpret.c Normal file

File diff suppressed because it is too large Load Diff

1105
dmd2/intrange.c Normal file

File diff suppressed because it is too large Load Diff

149
dmd2/intrange.h Normal file
View File

@@ -0,0 +1,149 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by KennyTM
// 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_SXNUM_H
#define DMD_SXNUM_H
#include "mars.h" // for uinteger_t
struct Type;
struct Expression;
/**
This class represents a "sign-extended number", i.e. a 65-bit number, which can
represent all built-in integer types in D. This class is mainly used for
performing value-range propagation only, therefore all arithmetic are done with
saturation, not wrapping as usual.
*/
struct SignExtendedNumber
{
/// The lower 64-bit of the number.
uinteger_t value;
/// The sign (i.e. the most significant bit) of the number.
bool negative;
/// Create an uninitialized sign-extended number.
SignExtendedNumber() {}
/// Create a sign-extended number from an unsigned 64-bit number.
SignExtendedNumber(uinteger_t value_)
: value(value_), negative(false) {}
/// Create a sign-extended number from the lower 64-bit and the sign bit.
SignExtendedNumber(uinteger_t value_, bool negative_)
: value(value_), negative(negative_) {}
/// Create a sign-extended number from a signed 64-bit number.
static SignExtendedNumber fromInteger(uinteger_t value_);
/// Get the minimum or maximum value of a sign-extended number.
static SignExtendedNumber extreme(bool minimum);
static SignExtendedNumber max();
static SignExtendedNumber min() { return SignExtendedNumber(0, true); }
/// Check if the sign-extended number is minimum or zero.
bool isMinimum() const { return negative && value == 0; }
/// Compare two sign-extended number.
bool operator==(const SignExtendedNumber&) const;
bool operator!=(const SignExtendedNumber& a) const { return !(*this == a); }
bool operator<(const SignExtendedNumber&) const;
bool operator>(const SignExtendedNumber& a) const { return a < *this; }
bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
/// Compute the saturated negation of a sign-extended number.
SignExtendedNumber operator-() const;
/// Compute the saturated sum of two sign-extended number.
SignExtendedNumber operator+(const SignExtendedNumber&) const;
/// Compute the saturated difference of two sign-extended number.
SignExtendedNumber operator-(const SignExtendedNumber& a) const;
/// Compute the saturated product of two sign-extended number.
SignExtendedNumber operator*(const SignExtendedNumber&) const;
/// Compute the saturated quotient of two sign-extended number.
SignExtendedNumber operator/(const SignExtendedNumber&) const;
/// Compute the saturated modulus of two sign-extended number.
SignExtendedNumber operator%(const SignExtendedNumber&) const;
/// Increase the sign-extended number by 1 (saturated).
SignExtendedNumber& operator++();
/// Compute the saturated shifts of two sign-extended number.
SignExtendedNumber operator<<(const SignExtendedNumber&) const;
SignExtendedNumber operator>>(const SignExtendedNumber&) const;
};
/**
This class represents a range of integers, denoted by its lower and upper bounds
(inclusive).
*/
struct IntRange
{
SignExtendedNumber imin, imax;
/// Create an uninitialized range.
IntRange() {}
/// Create a range consisting of a single number.
IntRange(const SignExtendedNumber& a)
: imin(a), imax(a) {}
/// Create a range with the lower and upper bounds.
IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
: imin(lower), imax(upper) {}
/// Create the tightest range containing all valid integers in the specified
/// type.
static IntRange fromType(Type *type);
/// Create the tightest range containing all valid integers in the type with
/// a forced signedness.
static IntRange fromType(Type *type, bool isUnsigned);
/// Create the tightest range containing all specified numbers.
static IntRange fromNumbers2(const SignExtendedNumber numbers[2]);
static IntRange fromNumbers4(const SignExtendedNumber numbers[4]);
/// Create the widest range possible.
static IntRange widest();
/// Cast the integer range to a signed type with the given size mask.
IntRange& castSigned(uinteger_t mask);
/// Cast the integer range to an unsigned type with the given size mask.
IntRange& castUnsigned(uinteger_t mask);
/// Cast the integer range to the dchar type.
IntRange& castDchar();
/// Cast the integer range to a specific type.
IntRange& cast(Type *type);
/// Cast the integer range to a specific type, forcing it to be unsigned.
IntRange& castUnsigned(Type *type);
/// Check if this range contains another range.
bool contains(const IntRange& a) const;
/// Check if this range contains 0.
bool containsZero() const;
/// Compute the range of the negated absolute values of the original range.
IntRange absNeg() const;
/// Compute the union of two ranges.
IntRange unionWith(const IntRange& other) const;
void unionOrAssign(const IntRange& other, bool& union_);
/// Dump the content of the integer range to the console.
const IntRange& dump(const char* funcName, Expression *e) const;
/// Split the range into two nonnegative- and negative-only subintervals.
void splitBySign(IntRange& negRange, bool& hasNegRange,
IntRange& nonNegRange, bool& hasNonNegRange) const;
};
#endif

195
dmd2/irstate.c Normal file
View File

@@ -0,0 +1,195 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include <stdio.h>
#include "mars.h"
#include "mtype.h"
#include "declaration.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;
#if DMDV2
varsInScope = irs->varsInScope;
#endif
}
else
{
m = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
#if DMDV2
varsInScope = NULL;
#endif
}
}
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;
varsInScope = irs->varsInScope;
}
else
{
m = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
varsInScope = 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;
varsInScope = 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);
}
/**********************
* Return !=0 if do array bounds checking
*/
int IRState::arrayBoundsCheck()
{
int result = global.params.useArrayBounds;
if (result == 1)
{ // For safe functions only
result = 0;
FuncDeclaration *fd = getFunc();
if (fd)
{ Type *t = fd->type;
if (t->ty == Tfunction && ((TypeFunction *)t)->trust == TRUSTsafe)
result = 1;
}
}
return result;
}

59
dmd2/irstate.h Normal file
View File

@@ -0,0 +1,59 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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 elem;
#include "arraytypes.h"
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;
Dsymbols *deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later
elem *ehidden; // transmit hidden pointer to CallExp::toElem()
Symbol *startaddress;
VarDeclarations *varsInScope; // variables that are in scope that will need destruction later
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();
int arrayBoundsCheck();
};
#endif /* DMD_CONTEXT_H */

462
dmd2/json.c Normal file
View File

@@ -0,0 +1,462 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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.
// This implements the JSON capability.
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <assert.h>
#include "rmem.h"
#include "root.h"
#include "mars.h"
#include "dsymbol.h"
#include "macro.h"
#include "template.h"
#include "lexer.h"
#include "aggregate.h"
#include "declaration.h"
#include "enum.h"
#include "id.h"
#include "module.h"
#include "scope.h"
#include "hdrgen.h"
#include "json.h"
#include "mtype.h"
#include "attrib.h"
#include "cond.h"
const char Pname[] = "name";
const char Pkind[] = "kind";
const char Pfile[] = "file";
const char Pline[] = "line";
const char Ptype[] = "type";
const char Pcomment[] = "comment";
const char Pmembers[] = "members";
const char Pprotection[] = "protection";
const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
void JsonRemoveComma(OutBuffer *buf);
void json_generate(Modules *modules)
{ OutBuffer buf;
buf.writestring("[\n");
for (size_t i = 0; i < modules->dim; i++)
{ Module *m = modules->tdata()[i];
if (global.params.verbose)
printf("json gen %s\n", m->toChars());
m->toJsonBuffer(&buf);
buf.writestring(",\n");
}
JsonRemoveComma(&buf);
buf.writestring("]\n");
// Write buf to file
char *arg = global.params.xfilename;
if (!arg || !*arg)
{ // Generate lib file name from first obj name
char *n = global.params.objfiles->tdata()[0];
n = FileName::name(n);
FileName *fn = FileName::forceExt(n, global.json_ext);
arg = fn->toChars();
}
else if (arg[0] == '-' && arg[1] == 0)
{ // Write to stdout; assume it succeeds
int n = fwrite(buf.data, 1, buf.offset, stdout);
assert(n == buf.offset); // keep gcc happy about return values
return;
}
// if (!FileName::absolute(arg))
// arg = FileName::combine(dir, arg);
FileName *jsonfilename = FileName::defaultExt(arg, global.json_ext);
File *jsonfile = new File(jsonfilename);
assert(jsonfile);
jsonfile->setbuffer(buf.data, buf.offset);
jsonfile->ref = 1;
char *pt = FileName::path(jsonfile->toChars());
if (*pt)
FileName::ensurePathExists(pt);
mem.free(pt);
jsonfile->writev();
}
/*********************************
* Encode string into buf, and wrap it in double quotes.
*/
void JsonString(OutBuffer *buf, const char *s)
{
buf->writeByte('\"');
for (; *s; s++)
{
unsigned char c = (unsigned char) *s;
switch (c)
{
case '\n':
buf->writestring("\\n");
break;
case '\r':
buf->writestring("\\r");
break;
case '\t':
buf->writestring("\\t");
break;
case '\"':
buf->writestring("\\\"");
break;
case '\\':
buf->writestring("\\\\");
break;
case '/':
buf->writestring("\\/");
break;
case '\b':
buf->writestring("\\b");
break;
case '\f':
buf->writestring("\\f");
break;
default:
if (c < 0x20)
buf->printf("\\u%04x", c);
else
// Note that UTF-8 chars pass through here just fine
buf->writeByte(c);
break;
}
}
buf->writeByte('\"');
}
void JsonProperty(OutBuffer *buf, const char *name, const char *value)
{
JsonString(buf, name);
buf->writestring(" : ");
JsonString(buf, value);
buf->writestring(",\n");
}
void JsonProperty(OutBuffer *buf, const char *name, int value)
{
JsonString(buf, name);
buf->writestring(" : ");
buf->printf("%d", value);
buf->writestring(",\n");
}
void JsonRemoveComma(OutBuffer *buf)
{
if (buf->offset >= 2 &&
buf->data[buf->offset - 2] == ',' &&
buf->data[buf->offset - 1] == '\n')
buf->offset -= 2;
}
void Dsymbol::toJsonBuffer(OutBuffer *buf)
{
}
void Module::toJsonBuffer(OutBuffer *buf)
{
buf->writestring("{\n");
if (md)
JsonProperty(buf, Pname, md->toChars());
JsonProperty(buf, Pkind, kind());
JsonProperty(buf, Pfile, srcfile->toChars());
if (comment)
JsonProperty(buf, Pcomment, (const char *)comment);
JsonString(buf, Pmembers);
buf->writestring(" : [\n");
size_t offset = buf->offset;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
if (offset != buf->offset)
{ buf->writestring(",\n");
offset = buf->offset;
}
s->toJsonBuffer(buf);
}
JsonRemoveComma(buf);
buf->writestring("]\n");
buf->writestring("}\n");
}
void AttribDeclaration::toJsonBuffer(OutBuffer *buf)
{
//printf("AttribDeclaration::toJsonBuffer()\n");
Dsymbols *d = include(NULL, NULL);
if (d)
{
size_t offset = buf->offset;
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
//printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars());
if (offset != buf->offset)
{ buf->writestring(",\n");
offset = buf->offset;
}
s->toJsonBuffer(buf);
}
JsonRemoveComma(buf);
}
}
void ConditionalDeclaration::toJsonBuffer(OutBuffer *buf)
{
//printf("ConditionalDeclaration::toJsonBuffer()\n");
if (condition->inc)
{
AttribDeclaration::toJsonBuffer(buf);
}
}
void InvariantDeclaration::toJsonBuffer(OutBuffer *buf) { }
void DtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
void StaticCtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
void StaticDtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
void ClassInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
void ModuleInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
void TypeInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
void UnitTestDeclaration::toJsonBuffer(OutBuffer *buf) { }
#if DMDV2
void PostBlitDeclaration::toJsonBuffer(OutBuffer *buf) { }
#endif
void Declaration::toJsonBuffer(OutBuffer *buf)
{
//printf("Declaration::toJsonBuffer()\n");
buf->writestring("{\n");
JsonProperty(buf, Pname, toChars());
JsonProperty(buf, Pkind, kind());
if (prot())
JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
if (type)
JsonProperty(buf, Ptype, type->toChars());
if (comment)
JsonProperty(buf, Pcomment, (const char *)comment);
if (loc.linnum)
JsonProperty(buf, Pline, loc.linnum);
TypedefDeclaration *td = isTypedefDeclaration();
if (td)
{
JsonProperty(buf, "base", td->basetype->toChars());
}
JsonRemoveComma(buf);
buf->writestring("}\n");
}
void AggregateDeclaration::toJsonBuffer(OutBuffer *buf)
{
//printf("AggregateDeclaration::toJsonBuffer()\n");
buf->writestring("{\n");
JsonProperty(buf, Pname, toChars());
JsonProperty(buf, Pkind, kind());
if (prot())
JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
if (comment)
JsonProperty(buf, Pcomment, (const char *)comment);
if (loc.linnum)
JsonProperty(buf, Pline, loc.linnum);
ClassDeclaration *cd = isClassDeclaration();
if (cd)
{
if (cd->baseClass)
{
JsonProperty(buf, "base", cd->baseClass->toChars());
}
if (cd->interfaces_dim)
{
JsonString(buf, "interfaces");
buf->writestring(" : [\n");
size_t offset = buf->offset;
for (size_t i = 0; i < cd->interfaces_dim; i++)
{ BaseClass *b = cd->interfaces[i];
if (offset != buf->offset)
{ buf->writestring(",\n");
offset = buf->offset;
}
JsonString(buf, b->base->toChars());
}
JsonRemoveComma(buf);
buf->writestring("],\n");
}
}
if (members)
{
JsonString(buf, Pmembers);
buf->writestring(" : [\n");
size_t offset = buf->offset;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
if (offset != buf->offset)
{ buf->writestring(",\n");
offset = buf->offset;
}
s->toJsonBuffer(buf);
}
JsonRemoveComma(buf);
buf->writestring("]\n");
}
JsonRemoveComma(buf);
buf->writestring("}\n");
}
void TemplateDeclaration::toJsonBuffer(OutBuffer *buf)
{
//printf("TemplateDeclaration::toJsonBuffer()\n");
buf->writestring("{\n");
JsonProperty(buf, Pname, toChars());
JsonProperty(buf, Pkind, kind());
if (prot())
JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
if (comment)
JsonProperty(buf, Pcomment, (const char *)comment);
if (loc.linnum)
JsonProperty(buf, Pline, loc.linnum);
JsonString(buf, Pmembers);
buf->writestring(" : [\n");
size_t offset = buf->offset;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
if (offset != buf->offset)
{ buf->writestring(",\n");
offset = buf->offset;
}
s->toJsonBuffer(buf);
}
JsonRemoveComma(buf);
buf->writestring("]\n");
buf->writestring("}\n");
}
void EnumDeclaration::toJsonBuffer(OutBuffer *buf)
{
//printf("EnumDeclaration::toJsonBuffer()\n");
if (isAnonymous())
{
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
s->toJsonBuffer(buf);
buf->writestring(",\n");
}
JsonRemoveComma(buf);
}
return;
}
buf->writestring("{\n");
JsonProperty(buf, Pname, toChars());
JsonProperty(buf, Pkind, kind());
if (prot())
JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
if (comment)
JsonProperty(buf, Pcomment, (const char *)comment);
if (loc.linnum)
JsonProperty(buf, Pline, loc.linnum);
if (memtype)
JsonProperty(buf, "base", memtype->toChars());
if (members)
{
JsonString(buf, Pmembers);
buf->writestring(" : [\n");
size_t offset = buf->offset;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
if (offset != buf->offset)
{ buf->writestring(",\n");
offset = buf->offset;
}
s->toJsonBuffer(buf);
}
JsonRemoveComma(buf);
buf->writestring("]\n");
}
JsonRemoveComma(buf);
buf->writestring("}\n");
}
void EnumMember::toJsonBuffer(OutBuffer *buf)
{
//printf("EnumMember::toJsonBuffer()\n");
buf->writestring("{\n");
JsonProperty(buf, Pname, toChars());
JsonProperty(buf, Pkind, kind());
if (prot())
JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
if (comment)
JsonProperty(buf, Pcomment, (const char *)comment);
if (loc.linnum)
JsonProperty(buf, Pline, loc.linnum);
JsonRemoveComma(buf);
buf->writestring("}\n");
}

24
dmd2/json.h Normal file
View File

@@ -0,0 +1,24 @@
// 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_JSON_H
#define DMD_JSON_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "arraytypes.h"
void json_generate(Modules *);
#endif /* DMD_JSON_H */

3216
dmd2/lexer.c Normal file

File diff suppressed because it is too large Load Diff

321
dmd2/lexer.h Normal file
View File

@@ -0,0 +1,321 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 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,
TOKpreplusplus, TOKpreminusminus,
// 106
// 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,
TOKerror,
// 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,
// 152
// 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
TOKargTypes,
TOKref,
TOKmacro,
#if DMDV2
TOKtraits,
TOKoverloadset,
TOKpure,
TOKnothrow,
TOKtls,
TOKgshared,
TOKline,
TOKfile,
TOKshared,
TOKat,
TOKpow,
TOKpowass,
TOKgoesto,
TOKvector,
#endif
// LDC specific
#if IN_LLVM
TOKgep,
#endif
TOKMAX
};
#define TOKwild TOKinout
#define BASIC_TYPES \
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 BASIC_TYPES_X(t) \
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 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 verror(Loc loc, const char *format, va_list ap);
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 */

54
dmd2/lib.h Normal file
View File

@@ -0,0 +1,54 @@
// 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;
};
#include "arraytypes.h"
typedef ArrayBase<ObjModule> ObjModules;
typedef ArrayBase<ObjSymbol> ObjSymbols;
struct Library
{
File *libfile;
ObjModules objmodules; // ObjModule[]
ObjSymbols 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 */

449
dmd2/macro.c Normal file
View File

@@ -0,0 +1,449 @@
// 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.
/* Simple macro text processor.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <assert.h>
#include "rmem.h"
#include "root.h"
#include "macro.h"
#define isidstart(c) (isalpha(c) || (c) == '_')
#define isidchar(c) (isalnum(c) || (c) == '_')
unsigned char *memdup(unsigned char *p, size_t len)
{
return (unsigned char *)memcpy(mem.malloc(len), p, len);
}
Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
{
next = NULL;
#if 1
this->name = name;
this->namelen = namelen;
this->text = text;
this->textlen = textlen;
#else
this->name = name;
this->namelen = namelen;
this->text = text;
this->textlen = textlen;
#endif
inuse = 0;
}
Macro *Macro::search(unsigned char *name, size_t namelen)
{ Macro *table;
//printf("Macro::search(%.*s)\n", namelen, name);
for (table = this; table; table = table->next)
{
if (table->namelen == namelen &&
memcmp(table->name, name, namelen) == 0)
{
//printf("\tfound %d\n", table->textlen);
break;
}
}
return table;
}
Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
{
//printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text);
Macro *table;
//assert(ptable);
for (table = *ptable; table; table = table->next)
{
if (table->namelen == namelen &&
memcmp(table->name, name, namelen) == 0)
{
table->text = text;
table->textlen = textlen;
return table;
}
}
table = new Macro(name, namelen, text, textlen);
table->next = *ptable;
*ptable = table;
return table;
}
/**********************************************************
* Given buffer p[0..end], extract argument marg[0..marglen].
* Params:
* n 0: get entire argument
* 1..9: get nth argument
* -1: get 2nd through end
*/
unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsigned *pmarglen, int n)
{
/* Scan forward for matching right parenthesis.
* Nest parentheses.
* Skip over $( and $)
* Skip over "..." and '...' strings inside HTML tags.
* Skip over <!-- ... --> comments.
* Skip over previous macro insertions
* Set marglen.
*/
unsigned parens = 1;
unsigned char instring = 0;
unsigned incomment = 0;
unsigned intag = 0;
unsigned inexp = 0;
unsigned argn = 0;
unsigned v = 0;
Largstart:
#if 1
// Skip first space, if any, to find the start of the macro argument
if (v < end && isspace(p[v]))
v++;
#else
// Skip past spaces to find the start of the macro argument
for (; v < end && isspace(p[v]); v++)
;
#endif
*pmarg = p + v;
for (; v < end; v++)
{ unsigned char c = p[v];
switch (c)
{
case ',':
if (!inexp && !instring && !incomment && parens == 1)
{
argn++;
if (argn == 1 && n == -1)
{ v++;
goto Largstart;
}
if (argn == n)
break;
if (argn + 1 == n)
{ v++;
goto Largstart;
}
}
continue;
case '(':
if (!inexp && !instring && !incomment)
parens++;
continue;
case ')':
if (!inexp && !instring && !incomment && --parens == 0)
{
break;
}
continue;
case '"':
case '\'':
if (!inexp && !incomment && intag)
{
if (c == instring)
instring = 0;
else if (!instring)
instring = c;
}
continue;
case '<':
if (!inexp && !instring && !incomment)
{
if (v + 6 < end &&
p[v + 1] == '!' &&
p[v + 2] == '-' &&
p[v + 3] == '-')
{
incomment = 1;
v += 3;
}
else if (v + 2 < end &&
isalpha(p[v + 1]))
intag = 1;
}
continue;
case '>':
if (!inexp)
intag = 0;
continue;
case '-':
if (!inexp &&
!instring &&
incomment &&
v + 2 < end &&
p[v + 1] == '-' &&
p[v + 2] == '>')
{
incomment = 0;
v += 2;
}
continue;
case 0xFF:
if (v + 1 < end)
{
if (p[v + 1] == '{')
inexp++;
else if (p[v + 1] == '}')
inexp--;
}
continue;
default:
continue;
}
break;
}
if (argn == 0 && n == -1)
*pmarg = p + v;
*pmarglen = p + v - *pmarg;
//printf("extractArg%d('%.*s') = '%.*s'\n", n, end, p, *pmarglen, *pmarg);
return v;
}
/*****************************************************
* Expand macro in place in buf.
* Only look at the text in buf from start to end.
*/
void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
unsigned char *arg, unsigned arglen)
{
#if 0
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
printf("Buf is: '%.*s'\n", *pend - start, buf->data + start);
#endif
static int nest;
if (nest > 100) // limit recursive expansion
return;
nest++;
unsigned end = *pend;
assert(start <= end);
assert(end <= buf->offset);
/* First pass - replace $0
*/
arg = memdup(arg, arglen);
for (unsigned u = start; u + 1 < end; )
{
unsigned char *p = buf->data; // buf->data is not loop invariant
/* Look for $0, but not $$0, and replace it with arg.
*/
if (p[u] == '$' && (isdigit(p[u + 1]) || p[u + 1] == '+'))
{
if (u > start && p[u - 1] == '$')
{ // Don't expand $$0, but replace it with $0
buf->remove(u - 1, 1);
end--;
u += 1; // now u is one past the closing '1'
continue;
}
unsigned char c = p[u + 1];
int n = (c == '+') ? -1 : c - '0';
unsigned char *marg;
unsigned marglen;
extractArgN(arg, arglen, &marg, &marglen, n);
if (marglen == 0)
{ // Just remove macro invocation
//printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg);
buf->remove(u, 2);
end -= 2;
}
else if (c == '+')
{
// Replace '$+' with 'arg'
//printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg);
buf->remove(u, 2);
buf->insert(u, marg, marglen);
end += marglen - 2;
// Scan replaced text for further expansion
unsigned mend = u + marglen;
expand(buf, u, &mend, NULL, 0);
end += mend - (u + marglen);
u = mend;
}
else
{
// Replace '$1' with '\xFF{arg\xFF}'
//printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg);
buf->data[u] = 0xFF;
buf->data[u + 1] = '{';
buf->insert(u + 2, marg, marglen);
buf->insert(u + 2 + marglen, "\xFF}", 2);
end += -2 + 2 + marglen + 2;
// Scan replaced text for further expansion
unsigned mend = u + 2 + marglen;
expand(buf, u + 2, &mend, NULL, 0);
end += mend - (u + 2 + marglen);
u = mend;
}
//printf("u = %d, end = %d\n", u, end);
//printf("#%.*s#\n", end, &buf->data[0]);
continue;
}
u++;
}
/* Second pass - replace other macros
*/
for (unsigned u = start; u + 4 < end; )
{
unsigned char *p = buf->data; // buf->data is not loop invariant
/* A valid start of macro expansion is $(c, where c is
* an id start character, and not $$(c.
*/
if (p[u] == '$' && p[u + 1] == '(' && isidstart(p[u + 2]))
{
//printf("\tfound macro start '%c'\n", p[u + 2]);
unsigned char *name = p + u + 2;
unsigned namelen = 0;
unsigned char *marg;
unsigned marglen;
unsigned v;
/* Scan forward to find end of macro name and
* beginning of macro argument (marg).
*/
for (v = u + 2; v < end; v++)
{ unsigned char c = p[v];
if (!isidchar(c))
{ // We've gone past the end of the macro name.
namelen = v - (u + 2);
break;
}
}
v += extractArgN(p + v, end - v, &marg, &marglen, 0);
assert(v <= end);
if (v < end)
{ // v is on the closing ')'
if (u > start && p[u - 1] == '$')
{ // Don't expand $$(NAME), but replace it with $(NAME)
buf->remove(u - 1, 1);
end--;
u = v; // now u is one past the closing ')'
continue;
}
Macro *m = search(name, namelen);
if (m)
{
#if 0
if (m->textlen && m->text[0] == ' ')
{ m->text++;
m->textlen--;
}
#endif
if (m->inuse && marglen == 0)
{ // Remove macro invocation
buf->remove(u, v + 1 - u);
end -= v + 1 - u;
}
else if (m->inuse && arglen == marglen && memcmp(arg, marg, arglen) == 0)
{ // Recursive expansion; just leave in place
}
else
{
//printf("\tmacro '%.*s'(%.*s) = '%.*s'\n", m->namelen, m->name, marglen, marg, m->textlen, m->text);
#if 1
marg = memdup(marg, marglen);
// Insert replacement text
buf->spread(v + 1, 2 + m->textlen + 2);
buf->data[v + 1] = 0xFF;
buf->data[v + 2] = '{';
memcpy(buf->data + v + 3, m->text, m->textlen);
buf->data[v + 3 + m->textlen] = 0xFF;
buf->data[v + 3 + m->textlen + 1] = '}';
end += 2 + m->textlen + 2;
// Scan replaced text for further expansion
m->inuse++;
unsigned mend = v + 1 + 2+m->textlen+2;
expand(buf, v + 1, &mend, marg, marglen);
end += mend - (v + 1 + 2+m->textlen+2);
m->inuse--;
buf->remove(u, v + 1 - u);
end -= v + 1 - u;
u += mend - (v + 1);
#else
// Insert replacement text
buf->insert(v + 1, m->text, m->textlen);
end += m->textlen;
// Scan replaced text for further expansion
m->inuse++;
unsigned mend = v + 1 + m->textlen;
expand(buf, v + 1, &mend, marg, marglen);
end += mend - (v + 1 + m->textlen);
m->inuse--;
buf->remove(u, v + 1 - u);
end -= v + 1 - u;
u += mend - (v + 1);
#endif
mem.free(marg);
//printf("u = %d, end = %d\n", u, end);
//printf("#%.*s#\n", end - u, &buf->data[u]);
continue;
}
}
else
{
// Replace $(NAME) with nothing
buf->remove(u, v + 1 - u);
end -= (v + 1 - u);
continue;
}
}
}
u++;
}
mem.free(arg);
*pend = end;
nest--;
}

45
dmd2/macro.h Normal file
View File

@@ -0,0 +1,45 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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_MACRO_H
#define DMD_MACRO_H 1
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "root.h"
struct Macro
{
private:
Macro *next; // next in list
unsigned char *name; // macro name
size_t namelen; // length of macro name
unsigned char *text; // macro replacement text
size_t textlen; // length of replacement text
int inuse; // macro is in use (don't expand)
Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
Macro *search(unsigned char *name, size_t namelen);
public:
static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
void expand(OutBuffer *buf, unsigned start, unsigned *pend,
unsigned char *arg, unsigned arglen);
};
#endif

303
dmd2/mangle.c Normal file
View File

@@ -0,0 +1,303 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 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_OPENBSD || 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 && 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;
#if IN_LLVM
case LINKintrinsic:
#endif
case LINKc:
case LINKwindows:
case LINKpascal:
return ident->toChars();
case LINKcpp:
#if CPP_MANGLE
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 ||
#if !MODULEINFO_IS_STRUCT
this == Module::moduleinfo ||
#endif
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
)
parent = NULL;
char *id = Dsymbol::mangle();
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
{
OutBuffer buf;
#if 0
printf("TemplateInstance::mangle() %p %s", this, toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
char *id = ident ? ident->toChars() : toChars();
if (!tempdecl)
error("is not defined");
else
{
Dsymbol *par = isnested || isTemplateMixin() ? parent : tempdecl->parent;
if (par)
{
char *p = par->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;
}

1605
dmd2/mars.c Normal file

File diff suppressed because it is too large Load Diff

503
dmd2/mars.h Normal file
View File

@@ -0,0 +1,503 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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
__clang__ Clang 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
__OpenBSD__ OpenBSD
__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_OPENBSD Covers 32 and 64 bit OpenBSD
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, OpenBSD 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>
#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 DEBUG
#define UNITTEST 1
#endif
void unittests();
#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
#define SARRAYVALUE DMDV2 // static arrays are value types
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
// Set if C++ mangling is done by the front end
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS))
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and
* TARGET_SOLARIS, which are
* set on the command line via the compiler makefile.
*/
#if _WIN32
#ifndef TARGET_WINDOS
#define TARGET_WINDOS 1 // Windows dmd generates Windows targets
#endif
#ifndef OMFOBJ
#define OMFOBJ TARGET_WINDOS
#endif
#endif
#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
#ifndef ELFOBJ
#define ELFOBJ 1
#endif
#endif
#if TARGET_OSX
#ifndef MACHOBJ
#define MACHOBJ 1
#endif
#endif
struct OutBuffer;
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct ArrayBase;
typedef ArrayBase<struct Identifier> Identifiers;
typedef ArrayBase<char> Strings;
#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,
OSHaiku,
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 alwaysframe; // always emit standard stack frame
char map; // generate linker .map file
bool isLE; // generate little endian code
bool is64bit; // generate 64 bit 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
ubyte warnings; // enable warnings
ubyte Dversion; // D version number
bool ignoreUnsupportedPragmas; // rather than error on them
bool enforcePropertySyntax;
char *argv0; // program name
Strings *imppath; // array of char*'s of where to look for import modules
Strings *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
Strings *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
bool doXGeneration; // write JSON file
char *xfilename; // write JSON file to xfilename
unsigned debuglevel; // debug level
Strings *debugids; // debug identifiers
unsigned versionlevel; // version level
Strings *versionids; // version identifiers
bool dump_source;
Strings *defaultlibnames; // default libraries for non-debug builds
Strings *debuglibnames; // default libraries for debug builds
char *moduleDepsFile; // filename for deps output
OutBuffer *moduleDeps; // contents to be written to deps file
// 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
Strings *objfiles;
Strings *linkswitches;
Strings *libfiles;
char *deffile;
char *resfile;
char *exefile;
char *mapfile;
#if IN_LLVM
// LDC stuff
OUTPUTFLAG output_ll;
OUTPUTFLAG output_bc;
OUTPUTFLAG output_s;
OUTPUTFLAG output_o;
bool llvmAnnotate;
bool useInlineAsm;
bool verbose_cg;
bool useAvailableExternally;
// 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 *dll_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 *json_ext; // for JSON files
const char *map_ext; // for .map files
const char *copyright;
const char *written;
Strings *path; // Array of char*'s which form the import lookup path
Strings *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 warnings; // number of warnings reported so far
unsigned gag; // !=0 means gag reporting of errors & warnings
unsigned gaggedErrors; // number of errors reported while gagged
// Start gagging. Return the current number of gagged errors
unsigned startGagging();
/* End gagging, restoring the old gagged state.
* Return true if errors occured while gagged.
*/
bool endGagging(unsigned oldGagged);
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
};
typedef uint64_t StorageClass;
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
void errorSupplemental(Loc loc, const char *format, ...);
void verror(Loc loc, const char *format, va_list);
void vwarning(Loc loc, const char *format, va_list);
void verrorSupplemental(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();
const char *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 stderr
#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
const char *importHint(const char *s);
#endif /* DMD_MARS_H */

1365
dmd2/module.c Normal file

File diff suppressed because it is too large Load Diff

232
dmd2/module.h Normal file
View File

@@ -0,0 +1,232 @@
// 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 LLVMContext;
class Module;
class GlobalVariable;
class StructType;
}
#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(Identifiers *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 Modules amodules; // array of all modules
static Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them
static unsigned dprogress; // progress resolving the deferred list
static void init();
static AggregateDeclaration *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 .obj file
File *hdrfile; // 'header' file
File *symfile; // output symbol file
File *docfile; // output documentation 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 semanticRun; // 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
Dsymbols *decldefs; // top level declarations for this Module
Modules aimports; // all imported modules
ModuleInfoDeclaration *vmoduleinfo;
unsigned debuglevel; // debug level
Strings *debugids; // debug identifiers
Strings *debugidsNot; // forward referenced debug identifiers
unsigned versionlevel; // version level
Strings *versionids; // version identifiers
Strings *versionidsNot; // forward referenced version identifiers
Macro *macrotable; // document comment macros
Escape *escapetable; // document comment escapes
bool safe; // TRUE if module is marked as 'safe'
size_t nameoffset; // offset of module name from start of ModuleInfo
size_t namelen; // length of module name in characters
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, Identifiers *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
const char *kind();
#if !IN_LLVM
void setDocfile(); // set docfile member
#endif
void read(Loc loc); // read file
#if IN_LLVM
void parse(bool gen_docs = false); // syntactic parse
#elif IN_GCC
void parse(bool dump_source = false); // syntactic parse
#else
void parse(); // syntactic parse
#endif
void importAll(Scope *sc);
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
void genhdrfile(); // generate D import file
// void gensymfile();
void gendocfile();
int needModuleInfo();
Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *symtabInsert(Dsymbol *s);
void deleteObjFile();
void addDeferredSemantic(Dsymbol *s);
static void runDeferredSemantic();
static void clearCache();
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 *ssharedctor; // module shared constructor
Symbol *sshareddtor; // module shared destructor
Symbol *stest; // module unit test
Symbol *sfilename; // symbol for filename
Symbol *massert; // module assert function
Symbol *toModuleAssert(); // get module assert function
Symbol *munittest; // module unittest failure function
Symbol *toModuleUnittest(); // get module unittest failure function
Symbol *marray; // module array bounds function
Symbol *toModuleArray(); // get module array bounds function
static Symbol *gencritsec();
elem *toEfilename();
Symbol *toSymbol();
#endif
void genmoduleinfo();
#if IN_LLVM
// LDC
llvm::Module* genLLVMModule(llvm::LLVMContext& context, Ir* sir);
void buildTargetFiles(bool singleObj);
File* buildFilePath(const char* forcename, const char* path, const char* ext);
Module *isModule() { return this; }
llvm::GlobalVariable* moduleInfoSymbol();
bool llvmForceLogging;
llvm::GlobalVariable* moduleInfoVar;
llvm::StructType* moduleInfoType;
// array ops emitted in this module already
AA *arrayfuncs;
bool isRoot;
#endif
};
struct ModuleDeclaration
{
Identifier *id;
Identifiers *packages; // array of Identifier's representing packages
bool safe;
ModuleDeclaration(Identifiers *packages, Identifier *id, bool safe);
char *toChars();
};
#endif /* DMD_MODULE_H */

9323
dmd2/mtype.c Normal file

File diff suppressed because it is too large Load Diff

1067
dmd2/mtype.h Normal file

File diff suppressed because it is too large Load Diff

1612
dmd2/opover.c Normal file

File diff suppressed because it is too large Load Diff

1219
dmd2/optimize.c Normal file

File diff suppressed because it is too large Load Diff

6709
dmd2/parse.c Normal file

File diff suppressed because it is too large Load Diff

187
dmd2/parse.h Normal file
View File

@@ -0,0 +1,187 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 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_PARSE_H
#define DMD_PARSE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "arraytypes.h"
#include "lexer.h"
#include "enum.h"
struct Type;
struct TypeQualified;
struct Expression;
struct Declaration;
struct Statement;
struct Import;
struct Initializer;
struct FuncDeclaration;
struct CtorDeclaration;
struct PostBlitDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct SharedStaticCtorDeclaration;
struct SharedStaticDtorDeclaration;
struct ConditionalDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct DeleteDeclaration;
struct Condition;
struct Module;
struct ModuleDeclaration;
struct TemplateDeclaration;
struct TemplateInstance;
struct StaticAssert;
/************************************
* These control how parseStatement() works.
*/
enum ParseStatementFlags
{
PSsemi = 1, // empty ';' statements are allowed, but deprecated
PSscope = 2, // start a new scope
PScurly = 4, // { } statement is required
PScurlyscope = 8, // { } starts a new scope
PSsemi_ok = 0x10, // empty ';' are really ok
};
struct Parser : Lexer
{
ModuleDeclaration *md;
enum LINK linkage;
Loc endloc; // set to location of last right curly
int inBrackets; // inside [] of array index or slice
Loc lookingForElse; // location of lonely if looking for an else
Parser(Module *module, unsigned char *base, unsigned length, int doDocComment);
Dsymbols *parseModule();
Dsymbols *parseDeclDefs(int once);
Dsymbols *parseAutoDeclarations(StorageClass storageClass, unsigned char *comment);
Dsymbols *parseBlock();
void composeStorageClass(StorageClass stc);
StorageClass parseAttribute();
StorageClass parsePostfix();
Expression *parseConstraint();
TemplateDeclaration *parseTemplateDeclaration(int ismixin);
TemplateParameters *parseTemplateParameterList(int flag = 0);
Dsymbol *parseMixin();
Objects *parseTemplateArgumentList();
Objects *parseTemplateArgumentList2();
Objects *parseTemplateArgument();
StaticAssert *parseStaticAssert();
TypeQualified *parseTypeof();
Type *parseVector();
enum LINK parseLinkage();
Condition *parseDebugCondition();
Condition *parseVersionCondition();
Condition *parseStaticIfCondition();
Dsymbol *parseCtor();
PostBlitDeclaration *parsePostBlit();
DtorDeclaration *parseDtor();
StaticCtorDeclaration *parseStaticCtor();
StaticDtorDeclaration *parseStaticDtor();
SharedStaticCtorDeclaration *parseSharedStaticCtor();
SharedStaticDtorDeclaration *parseSharedStaticDtor();
InvariantDeclaration *parseInvariant();
UnitTestDeclaration *parseUnitTest();
NewDeclaration *parseNew();
DeleteDeclaration *parseDelete();
Parameters *parseParameters(int *pvarargs, TemplateParameters **tpl = NULL);
EnumDeclaration *parseEnum();
Dsymbol *parseAggregate();
BaseClasses *parseBaseClasses();
Import *parseImport(Dsymbols *decldefs, int isstatic);
Type *parseType(Identifier **pident = NULL, TemplateParameters **tpl = NULL);
Type *parseBasicType();
Type *parseBasicType2(Type *t);
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int* pdisable = NULL);
Dsymbols *parseDeclarations(StorageClass storage_class, unsigned char *comment);
void parseContracts(FuncDeclaration *f);
void checkDanglingElse(Loc elseloc);
Statement *parseStatement(int flags);
Initializer *parseInitializer();
Expression *parseDefaultInitExp();
void check(Loc loc, enum TOK value);
void check(enum TOK value);
void check(enum TOK value, const char *string);
void checkParens(enum TOK value, Expression *e);
int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
int isBasicType(Token **pt);
int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
int isParameters(Token **pt);
int isExpression(Token **pt);
int isTemplateInstance(Token *t, Token **pt);
int skipParens(Token *t, Token **pt);
int skipAttributes(Token *t, Token **pt);
Expression *parseExpression();
Expression *parsePrimaryExp();
Expression *parseUnaryExp();
Expression *parsePostExp(Expression *e);
Expression *parseMulExp();
Expression *parseAddExp();
Expression *parseShiftExp();
#if DMDV1
Expression *parseRelExp();
Expression *parseEqualExp();
#endif
Expression *parseCmpExp();
Expression *parseAndExp();
Expression *parseXorExp();
Expression *parseOrExp();
Expression *parseAndAndExp();
Expression *parseOrOrExp();
Expression *parseCondExp();
Expression *parseAssignExp();
Expressions *parseArguments();
Expression *parseNewExp(Expression *thisexp);
void addComment(Dsymbol *s, unsigned char *blockComment);
};
// Operator precedence - greater values are higher precedence
enum PREC
{
PREC_zero,
PREC_expr,
PREC_assign,
PREC_cond,
PREC_oror,
PREC_andand,
PREC_or,
PREC_xor,
PREC_and,
PREC_equal,
PREC_rel,
PREC_shift,
PREC_add,
PREC_mul,
PREC_pow,
PREC_unary,
PREC_primary,
};
extern enum PREC precedence[TOKMAX];
void initPrecedence();
#endif /* DMD_PARSE_H */

24
dmd2/readme.txt Normal file
View File

@@ -0,0 +1,24 @@
The D Programming Language
Compiler Front End Source
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
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.
-Walter Bright

188
dmd2/root/aav.c Normal file
View File

@@ -0,0 +1,188 @@
/**
* Implementation of associative arrays.
*
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "aav.h"
static const size_t prime_list[] = {
31UL,
97UL, 389UL,
1543UL, 6151UL,
24593UL, 98317UL,
393241UL, 1572869UL,
6291469UL, 25165843UL,
100663319UL, 402653189UL,
1610612741UL, 4294967291UL,
};
struct aaA
{
aaA *next;
Key key;
Value value;
};
struct AA
{
aaA* *b;
size_t b_length;
size_t nodes; // total number of aaA nodes
aaA* binit[4]; // initial value of b[]
};
static const AA bbinit = { NULL, };
/****************************************************
* Determine number of entries in associative array.
*/
size_t _aaLen(AA* aa)
{
return aa ? aa->nodes : 0;
}
/*************************************************
* Get pointer to value in associative array indexed by key.
* Add entry for key if it is not already there.
*/
Value* _aaGet(AA** paa, Key key)
{
//printf("paa = %p\n", paa);
if (!*paa)
{ AA *a = new AA();
*a = bbinit;
a->b = a->binit;
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
*paa = a;
assert((*paa)->b_length == 4);
}
//printf("paa = %p, *paa = %p\n", paa, *paa);
assert((*paa)->b_length);
size_t i = (size_t)key % (*paa)->b_length;
aaA** pe = &(*paa)->b[i];
aaA *e;
while ((e = *pe) != NULL)
{
if (key == e->key)
return &e->value;
pe = &e->next;
}
// Not found, create new elem
//printf("create new one\n");
e = new aaA();
e->next = NULL;
e->key = key;
e->value = NULL;
*pe = e;
size_t nodes = ++(*paa)->nodes;
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
if (nodes > (*paa)->b_length * 4)
{
//printf("rehash\n");
_aaRehash(paa);
}
return &e->value;
}
/*************************************************
* Get value in associative array indexed by key.
* Returns NULL if it is not already there.
*/
Value _aaGetRvalue(AA* aa, Key key)
{
//printf("_aaGetRvalue(key = %p)\n", key);
if (!aa)
return NULL;
size_t len = aa->b_length;
if (len)
{
size_t i = (size_t)key % len;
aaA* e = aa->b[i];
while (e)
{
if (key == e->key)
return e->value;
e = e->next;
}
}
return NULL; // not found
}
/********************************************
* Rehash an array.
*/
void _aaRehash(AA** paa)
{
//printf("Rehash\n");
if (*paa)
{
AA newb = bbinit;
AA *aa = *paa;
size_t len = _aaLen(*paa);
if (len)
{ size_t i;
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
{
if (len <= prime_list[i])
break;
}
len = prime_list[i];
newb.b = new aaA*[len];
memset(newb.b, 0, len * sizeof(aaA*));
newb.b_length = len;
for (size_t k = 0; k < aa->b_length; k++)
{ aaA *e = aa->b[k];
while (e)
{ aaA* enext = e->next;
size_t j = (size_t)e->key % len;
e->next = newb.b[j];
newb.b[j] = e;
e = enext;
}
}
if (aa->b != aa->binit)
delete[] aa->b;
newb.nodes = aa->nodes;
}
**paa = newb;
}
}
#if UNITTEST
void unittest_aa()
{
AA* aa = NULL;
Value v = _aaGetRvalue(aa, NULL);
assert(!v);
Value *pv = _aaGet(&aa, NULL);
assert(pv);
*pv = (void *)3;
v = _aaGetRvalue(aa, NULL);
assert(v == (void *)3);
}
#endif

11
dmd2/root/aav.h Normal file
View File

@@ -0,0 +1,11 @@
typedef void* Value;
typedef void* Key;
struct AA;
size_t _aaLen(AA* aa);
Value* _aaGet(AA** aa, Key key);
Value _aaGetRvalue(AA* aa, Key key);
void _aaRehash(AA** paa);

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

@@ -0,0 +1,257 @@
// Copyright (c) 1999-2010 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 <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 = SMALLARRAYCAP ? &smallarray[0] : NULL;
dim = 0;
allocdim = SMALLARRAYCAP;
}
Array::~Array()
{
if (data != &smallarray[0])
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: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries);
if (allocdim - dim < nentries)
{
if (allocdim == 0)
{ // Not properly initialized, someone memset it to zero
if (nentries <= SMALLARRAYCAP)
{ allocdim = SMALLARRAYCAP;
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
}
else
{ allocdim = nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data));
}
}
else if (allocdim == SMALLARRAYCAP)
{
allocdim = dim + nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data));
memcpy(data, &smallarray[0], dim * sizeof(*data));
}
else
{ 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)
{
if (allocdim >= SMALLARRAYCAP)
{
if (dim <= SMALLARRAYCAP)
{
memcpy(&smallarray[0], data, dim * sizeof(*data));
mem.free(data);
}
else
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)
{
if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
dim--;
}
char *Array::toChars()
{
unsigned len;
unsigned u;
char **buf;
char *str;
char *p;
buf = (char **)malloc(dim * sizeof(char *));
assert(buf);
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;
free(buf);
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;
}

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

@@ -0,0 +1,325 @@
#define _MT 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#include <errno.h>
#include <process.h>
#include "root.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 *)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()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
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)
{
free(aw);
}
unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
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
}
#elif linux // Posix
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include "root.h"
void *startthread(void *arg);
void err_abort(int status, const char *msg)
{
fprintf(stderr, "fatal error = %d, %s\n", status, msg);
exit(EXIT_FAILURE);
}
struct FileData
{
File *file;
int result;
pthread_mutex_t mutex;
pthread_cond_t cond;
int value;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)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);
FileData *f = &files[filesdim];
f->file = file;
int status = pthread_mutex_init(&f->mutex, NULL);
if (status != 0)
err_abort(status, "init mutex");
status = pthread_cond_init(&f->cond, NULL);
if (status != 0)
err_abort(status, "init cond");
filesdim++;
}
void AsyncRead::start()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
pthread_t thread_id;
int status = pthread_create(&thread_id,
NULL,
&startthread,
this);
if (status != 0)
err_abort(status, "create thread");
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
// Wait for the event
int status = pthread_mutex_lock(&f->mutex);
if (status != 0)
err_abort(status, "lock mutex");
while (f->value == 0)
{
status = pthread_cond_wait(&f->cond, &f->mutex);
if (status != 0)
err_abort(status, "wait on condition");
}
status = pthread_mutex_unlock(&f->mutex);
if (status != 0)
err_abort(status, "unlock mutex");
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
//printf("AsyncRead::dispose()\n");
for (int i = 0; i < aw->filesdim; i++)
{
FileData *f = &aw->files[i];
int status = pthread_cond_destroy(&f->cond);
if (status != 0)
err_abort(status, "cond destroy");
status = pthread_mutex_destroy(&f->mutex);
if (status != 0)
err_abort(status, "mutex destroy");
}
free(aw);
}
void *startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
size_t dim = aw->filesdim;
for (size_t i = 0; i < dim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
// Set event
int status = pthread_mutex_lock(&f->mutex);
if (status != 0)
err_abort(status, "lock mutex");
f->value = 1;
status = pthread_cond_signal(&f->cond);
if (status != 0)
err_abort(status, "signal condition");
status = pthread_mutex_unlock(&f->mutex);
if (status != 0)
err_abort(status, "unlock mutex");
}
return NULL; // end thread
}
#else
#include <stdio.h>
#include <errno.h>
#include "root.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 *)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)
{
free(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 LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
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 LITTLE_ENDIAN
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 LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
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 LITTLE_ENDIAN
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-2011 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((unsigned char)c); }
static int isUpper(dchar c) { return isupper((unsigned char)c); }
static int isLower(dchar c) { return islower((unsigned char)c); }
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower((unsigned char)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

499
dmd2/root/dmgcmem.c Normal file
View File

@@ -0,0 +1,499 @@
// Copyright (c) 2000-2011 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 <string.h>
#include <assert.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#include <unistd.h>
#include <pthread.h>
#endif
#include "rmem.h"
#include "gc/gc.h"
//#include "printf.h"
/* This implementation of the storage allocator uses the Digital Mars gc.
*/
Mem mem;
//static int nuncollectable;
extern "C"
{
void gc_init();
GC *gc_get();
}
void Mem::init()
{
gc_init();
}
char *Mem::strdup(const char *s)
{
return gc_get()->strdup(s);
}
void *Mem::malloc(size_t size)
{
if (gc) // if cached allocator
{
// PRINTF("Using cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
// GC::file = NULL;
// GC::line = 0;
return ((GC *)gc)->malloc(size);
}
if (this == &mem) // don't cache global mem
{
// PRINTF("Using global gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
// GC::file = NULL;
// GC::line = 0;
return gc_get()->malloc(size);
}
// PRINTF("Generating cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
gc = gc_get();
return gc->malloc(size);
}
void *Mem::malloc_uncollectable(size_t size)
{ void *p;
p = ::malloc(size);
if (!p)
error();
addroots((char *)p, (char *)p + size);
#if 0
++nuncollectable;
WPRINTF(L"malloc_uncollectable(%u) = %x, n=%d\n", size, p, nuncollectable);
#endif
return p;
}
void *Mem::calloc(size_t size, size_t n)
{
return gc_get()->calloc(size, n);
}
void *Mem::realloc(void *p, size_t size)
{
return gc_get()->realloc(p, size);
}
void Mem::free(void *p)
{
gc_get()->free(p);
}
void Mem::free_uncollectable(void *p)
{
if (p)
{ removeroots((char *)p);
::free(p);
#if 0
--nuncollectable;
WPRINTF(L"free_uncollectable(%x) n=%d\n", p, nuncollectable);
#endif
#if 0
gc_get()->fullcollect();
GCStats stats;
getStats(&stats);
WPRINTF(L"poolsize = %x, usedsize = %x, freelistsize = %x\n",
stats.poolsize, stats.usedsize, stats.freelistsize);
#endif
}
}
void *Mem::mallocdup(void *o, size_t size)
{
return gc_get()->mallocdup(o, size);
}
void Mem::check(void *p)
{
if (gc)
gc->check(p);
else
gc_get()->check(p);
}
void Mem::error()
{
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
assert(0);
#endif
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
gc_get()->fullcollect();
#if 0
{
GCStats stats;
gc_get()->getStats(&stats);
WPRINTF(L"Thread %x ", Thread::getId());
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
}
#endif
}
void Mem::fullcollectNoStack()
{
gc_get()->fullcollectNoStack();
#if 0
{
GCStats stats;
gc_get()->getStats(&stats);
WPRINTF(L"Thread %x ", Thread::getId());
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
}
#endif
}
void Mem::mark(void *pointer)
{
(void) pointer; // for VC /W4 compatibility
}
void Mem::addroots(char* pStart, char* pEnd)
{
gc_get()->addRange(pStart, pEnd);
}
void Mem::removeroots(char* pStart)
{
gc_get()->removeRange(pStart);
}
void Mem::setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData)
{
(void)pClientData;
gc_get()->setFinalizer(pObj, pFn);
}
void Mem::setStackBottom(void *stackbottom)
{
gc_get()->setStackBottom(stackbottom);
}
GC *Mem::getThreadGC()
{
return gc_get();
}
/* =================================================== */
#if 1
void * operator new(size_t m_size)
{
//PRINTF("Call to global operator new(%d), file = '%s', line = %d\n", m_size, GC::file ? GC::file : "(null)", GC::line);
GC::file = NULL;
GC::line = 0;
return mem.malloc(m_size);
}
void operator delete(void *p)
{
//WPRINTF(L"Call to global operator delete\n");
mem.free(p);
}
void* operator new[](size_t size)
{
return operator new(size);
}
void operator delete[](void *pv)
{
operator delete(pv);
}
#endif
void * Mem::operator new(size_t m_size)
{ void *p;
p = gc_get()->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
mem.error();
return p;
}
void * Mem::operator new(size_t m_size, Mem *mem)
{ void *p;
p = mem->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
::mem.error();
return p;
}
void * Mem::operator new(size_t m_size, GC *gc)
{ void *p;
// if (!gc)
// WPRINTF(L"gc is NULL\n");
p = gc->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
::mem.error();
return p;
}
void Mem::operator delete(void *p)
{
// printf("Mem::operator delete(%p)\n", p);
gc_get()->free(p);
}
/* ============================================================ */
/* The following section of code exists to find the right
* garbage collector for this thread. There is one independent instance
* of the collector per thread.
*/
/* ===================== linux ================================ */
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#include <pthread.h>
#define LOG 0 // log thread creation / destruction
extern "C"
{
// Key identifying the thread-specific data
static pthread_key_t gc_key;
/* "Once" variable ensuring that the key for gc_alloc will be allocated
* exactly once.
*/
static pthread_once_t gc_alloc_key_once = PTHREAD_ONCE_INIT;
/* Forward functions */
static void gc_alloc_key();
static void gc_alloc_destroy_gc(void * accu);
void gc_init()
{
#if LOG
WPRINTF(L"Thread %lx: gc_init()\n", pthread_self());
#endif
pthread_once(&gc_alloc_key_once, gc_alloc_key);
#if LOG
WPRINTF(L"Thread %lx: gc_init() return\n", pthread_self());
#endif
}
GC *gc_get()
{
GC *gc;
// Get the thread-specific data associated with the key
gc = (GC *) pthread_getspecific(gc_key);
// It's initially NULL, meaning that we must allocate the buffer first.
if (gc == NULL)
{
GC_LOG();
gc = new GC();
gc->init();
// Store the buffer pointer in the thread-specific data.
pthread_setspecific(gc_key, (void *) gc);
#if LOG
WPRINTF(L"Thread %lx: allocating gc at %x\n", pthread_self(), gc);
#endif
}
return gc;
}
// Function to allocate the key for gc_alloc thread-specific data.
static void gc_alloc_key()
{
pthread_key_create(&gc_key, gc_alloc_destroy_gc);
#if LOG
WPRINTF(L"Thread %lx: allocated gc key %d\n", pthread_self(), gc_key);
#endif
}
// Function to free the buffer when the thread exits.
// Called only when the thread-specific data is not NULL.
static void gc_alloc_destroy_gc(void *gc)
{
#if LOG
WPRINTF(L"Thread %x: freeing gc at %x\n", pthread_self(), gc);
#endif
delete (GC *)gc;
}
}
#endif
/* ===================== win32 ================================ */
#if !defined(linux) && defined(_WIN32)
#if 1 // single threaded version
extern "C"
{
static GC *gc;
void gc_init()
{
if (!gc)
{ gc = (GC *)::malloc(sizeof(GC));
gc->init();
}
}
GC *gc_get()
{
return gc;
}
}
#else // multi threaded version
#include "mutex.h"
#include "thread.h"
/* This is the win32 version. It suffers from the bug that
* when the thread exits the data structure is not cleared,
* but the memory pool it points to is free'd.
* Thus, if a new thread comes along with the same thread id,
* the data will look initialized, but will point to garbage.
*
* What needs to happen is when a thread exits, the associated
* GC_context data struct is cleared.
*/
struct GC_context
{
ThreadId threadid; // identifier of current thread
GC *gc;
};
Mutex gc_mutex;
static GC_context array[64];
// Array of pointers to GC_context objects, one per threadid
GC_context *gccontext = array;
unsigned gccontext_allocdim = 64;
unsigned gccontext_dim;
ThreadId gc_cache_ti;
GC_context *gc_cache_cc;
extern "C" void gc_init()
{
}
extern "C" GC *gc_get()
{
/* This works by creating an array of GC_context's, one
* for each thread. We match up by thread id.
*/
ThreadId ti;
GC_context *cc;
//PRINTF("gc_get()\n");
ti = Thread::getId();
gc_mutex.acquire();
// Used cached version if we can
if (ti == gc_cache_ti)
{
cc = gc_cache_cc;
//exception(L"getGC_context(): cache x%x", ti);
}
else
{
// This does a linear search through gccontext[].
// A hash table might be faster if there are more
// than a dozen threads.
GC_context *ccp;
GC_context *ccptop = &gccontext[gccontext_dim];
for (ccp = gccontext; ccp < ccptop; ccp++)
{
cc = ccp;
if (cc->threadid == ti)
{
WPRINTF(L"getGC_context(): existing x%x", ti);
goto Lret;
}
}
// Do not allocate with garbage collector, as this must reside
// global to all threads.
assert(gccontext_dim < gccontext_allocdim);
cc = ccp;
memset(cc, 0, sizeof(*cc));
cc->threadid = ti;
cc->gc = new GC();
cc->gc->init();
gccontext_dim++;
WPRINTF(L"getGC_context(): new x%x\n", ti);
Lret:
// Cache for next time
gc_cache_ti = ti;
gc_cache_cc = cc;
}
gc_mutex.release();
return cc->gc;
}
#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__ || __OpenBSD__ || __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];
const 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

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

@@ -0,0 +1,796 @@
// Copyright (c) 1999-2011 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);
}
long double Port::fmodl(long double x, long double y)
{
return ::fmodl(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);
}
long double Port::fmodl(long double x, long double y)
{
return ::fmodl(x, y);
}
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
{
unsigned _int64 number = 0;
int c;
int error;
#ifndef ULLONG_MAX
#define ULLONG_MAX ((unsigned _int64)~0I64)
#endif
while (isspace((unsigned char)*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__ || __OpenBSD__ || __HAIKU__
#include <math.h>
#if linux
#include <bits/nan.h>
#include <bits/mathdef.h>
#endif
#if __FreeBSD__ && __i386__
#include <ieeefp.h>
#endif
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <float.h>
#include <assert.h>
static double zero = 0;
double Port::nan = copysign(NAN, 1.0);
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()
{
assert(!signbit(Port::nan));
#if __FreeBSD__ && __i386__
// 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];
// FreeBSD defaults to double precision. Switch to extended precision.
fpsetprec(FP_PE);
#endif
}
#ifndef __HAIKU__
#endif
int Port::isNan(double r)
{
#if __APPLE__
return __inline_isnan(r);
#elif defined __HAIKU__ || __OpenBSD__
return isnan(r);
#else
#undef isnan
return ::isnan(r);
#endif
}
int Port::isNan(long double r)
{
#if __APPLE__
return __inline_isnan(r);
#elif defined __HAIKU__ || __OpenBSD__
return isnan(r);
#else
#undef isnan
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);
}
#if !defined __HAIKU__
#endif
int Port::isInfinity(double r)
{
#if __APPLE__
return fpclassify(r) == FP_INFINITE;
#elif defined __HAIKU__ || __OpenBSD__
return isinf(r);
#else
#undef isinf
return ::isinf(r);
#endif
}
#undef signbit
int Port::Signbit(double r)
{
union { double d; long long ll; } u;
u.d = r;
return u.ll < 0;
}
double Port::floor(double d)
{
return ::floor(d);
}
double Port::pow(double x, double y)
{
return ::pow(x, y);
}
long double Port::fmodl(long double x, long double y)
{
#if __FreeBSD__ || __OpenBSD__
return ::fmod(x, y); // hack for now, fix later
#else
return ::fmodl(x, y);
#endif
}
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)
{
#if __OpenBSD__
assert(0);
#else
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
#endif
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

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

@@ -0,0 +1,81 @@
// 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 !defined __HAIKU__ || __OpenBSD__
#elif __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 long double fmodl(long double x, long 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

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

@@ -0,0 +1,290 @@
// Copyright (C) 1990-1998 by Symantec
// Copyright (C) 2000-2011 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>
#include <assert.h>
#if _WIN32
#include <tchar.h>
#include <io.h>
#endif
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include <sys/stat.h>
#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;
char **ap = n->argv;
ap = (char **) realloc(ap,n->argvmax * sizeof(char *));
if (!ap)
{ if (n->argv)
free(n->argv);
memset(n, 0, sizeof(*n));
return 1;
}
n->argv = ap;
}
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;
}
if (n.argvmax == 0)
{
n.argvmax = 1;
n.argv = (char **) calloc(n.argvmax, sizeof(char *));
if (!n.argv)
return 1;
}
else
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;
}

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

@@ -0,0 +1,155 @@
/* Copyright (c) 2000 Digital Mars */
/* All Rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __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
{
void *psave = p;
p = ::realloc(psave, size);
if (!p)
{ free(psave);
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 Mem::setStackBottom(void *bottom)
{
}
void Mem::addroots(char* pStart, char* pEnd)
{
}
/* =================================================== */
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-2011 by Digital Mars
// 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 */

2095
dmd2/root/root.c Normal file

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,417 @@
// Copyright (c) 1999-2011 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 ROOT_H
#define ROOT_H
#include <stdlib.h>
#include <stdarg.h>
#ifdef DEBUG
#include <assert.h>
#endif
#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;
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct ArrayBase;
typedef ArrayBase<struct File> Files;
typedef ArrayBase<char> Strings;
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 Strings *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(Strings *path, const char *name, int cwd);
static char *safeSearchPath(Strings *path, const char *name);
static int exists(const char *name);
static void ensurePathExists(const char *path);
static char *canonicalName(const char *name);
};
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 Files *match(char *);
static Files *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();
char *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;
void **data;
private:
unsigned allocdim;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
public:
Array();
~Array();
//Array(const 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();
};
template <typename TYPE>
struct ArrayBase : Array
{
TYPE **tdata()
{
return (TYPE **)data;
}
TYPE*& operator[] (size_t index)
{
#ifdef DEBUG
assert(index < dim);
#endif
return ((TYPE **)data)[index];
}
void insert(size_t index, TYPE *v)
{
Array::insert(index, (void *)v);
}
void insert(size_t index, ArrayBase *a)
{
Array::insert(index, (Array *)a);
}
void append(ArrayBase *a)
{
Array::append((Array *)a);
}
void push(TYPE *a)
{
Array::push((void *)a);
}
ArrayBase *copy()
{
return (ArrayBase *)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

257
dmd2/root/speller.c Normal file
View File

@@ -0,0 +1,257 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#if __sun&&__SVR4
#include <alloca.h>
#endif
#include "speller.h"
const char idchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
/**************************************************
* Looks for correct spelling.
* Currently only looks a 'distance' of one from the seed[].
* This does an exhaustive search, so can potentially be very slow.
* Input:
* seed wrongly spelled word
* fp search function
* fparg argument to search function
* charset character set
* Returns:
* NULL no correct spellings found
* void* value returned by fp() for first possible correct spelling
*/
void *spellerY(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg,
const char *charset, size_t index)
{
if (!seedlen)
return NULL;
assert(seed[seedlen] == 0);
char tmp[30];
char *buf;
if (seedlen <= sizeof(tmp) - 2)
buf = tmp;
else
{
buf = (char *)alloca(seedlen + 2); // leave space for extra char
if (!buf)
return NULL; // no matches
}
memcpy(buf, seed, index);
/* Delete at seed[index] */
if (index < seedlen)
{
memcpy(buf + index, seed + index + 1, seedlen - index);
assert(buf[seedlen - 1] == 0);
void *p = (*fp)(fparg, buf);
if (p)
return p;
}
if (charset && *charset)
{
/* Substitutions */
if (index < seedlen)
{
memcpy(buf, seed, seedlen + 1);
for (const char *s = charset; *s; s++)
{
buf[index] = *s;
//printf("sub buf = '%s'\n", buf);
void *p = (*fp)(fparg, buf);
if (p)
return p;
}
assert(buf[seedlen] == 0);
}
/* Insertions */
memcpy (buf + index + 1, seed + index, seedlen + 1 - index);
for (const char *s = charset; *s; s++)
{
buf[index] = *s;
//printf("ins buf = '%s'\n", buf);
void *p = (*fp)(fparg, buf);
if (p)
return p;
}
assert(buf[seedlen + 1] == 0);
}
return NULL; // didn't find any corrections
}
void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg,
const char *charset, int flag)
{
if (!seedlen)
return NULL;
char tmp[30];
char *buf;
if (seedlen <= sizeof(tmp) - 2)
buf = tmp;
else
{
buf = (char *)alloca(seedlen + 2); // leave space for extra char
if (!buf)
return NULL; // no matches
}
/* Deletions */
memcpy(buf, seed + 1, seedlen);
for (size_t i = 0; i < seedlen; i++)
{
//printf("del buf = '%s'\n", buf);
void *p;
if (flag)
p = spellerY(buf, seedlen - 1, fp, fparg, charset, i);
else
p = (*fp)(fparg, buf);
if (p)
return p;
buf[i] = seed[i];
}
/* Transpositions */
if (!flag)
{
memcpy(buf, seed, seedlen + 1);
for (size_t i = 0; i + 1 < seedlen; i++)
{
// swap [i] and [i + 1]
buf[i] = seed[i + 1];
buf[i + 1] = seed[i];
//printf("tra buf = '%s'\n", buf);
void *p = (*fp)(fparg, buf);
if (p)
return p;
buf[i] = seed[i];
}
}
if (charset && *charset)
{
/* Substitutions */
memcpy(buf, seed, seedlen + 1);
for (size_t i = 0; i < seedlen; i++)
{
for (const char *s = charset; *s; s++)
{
buf[i] = *s;
//printf("sub buf = '%s'\n", buf);
void *p;
if (flag)
p = spellerY(buf, seedlen, fp, fparg, charset, i + 1);
else
p = (*fp)(fparg, buf);
if (p)
return p;
}
buf[i] = seed[i];
}
/* Insertions */
memcpy(buf + 1, seed, seedlen + 1);
for (size_t i = 0; i <= seedlen; i++) // yes, do seedlen+1 iterations
{
for (const char *s = charset; *s; s++)
{
buf[i] = *s;
//printf("ins buf = '%s'\n", buf);
void *p;
if (flag)
p = spellerY(buf, seedlen + 1, fp, fparg, charset, i + 1);
else
p = (*fp)(fparg, buf);
if (p)
return p;
}
buf[i] = seed[i]; // going past end of seed[] is ok, as we hit the 0
}
}
return NULL; // didn't find any corrections
}
void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset)
{
size_t seedlen = strlen(seed);
for (int distance = 0; distance < 2; distance++)
{ void *p = spellerX(seed, seedlen, fp, fparg, charset, distance);
if (p)
return p;
// if (seedlen > 10)
// break;
}
return NULL; // didn't find it
}
#if UNITTEST
#include <stdio.h>
#include <string.h>
#include <assert.h>
void *speller_test(void *fparg, const char *s)
{
//printf("speller_test(%s, %s)\n", fparg, s);
if (strcmp((char *)fparg, s) == 0)
return fparg;
return NULL;
}
void unittest_speller()
{
static const char *cases[][3] =
{
{ "hello", "hell", "y" },
{ "hello", "hel", "y" },
{ "hello", "ello", "y" },
{ "hello", "llo", "y" },
{ "hello", "hellox", "y" },
{ "hello", "helloxy", "y" },
{ "hello", "xhello", "y" },
{ "hello", "xyhello", "y" },
{ "hello", "ehllo", "y" },
{ "hello", "helol", "y" },
{ "hello", "abcd", "n" },
//{ "ehllo", "helol", "y" },
{ "hello", "helxxlo", "y" },
{ "hello", "ehlxxlo", "n" },
{ "hello", "heaao", "y" },
{ "_123456789_123456789_123456789_123456789", "_123456789_123456789_123456789_12345678", "y" },
};
//printf("unittest_speller()\n");
const void *p = speller("hello", &speller_test, (void *)"hell", idchars);
assert(p != NULL);
for (int i = 0; i < sizeof(cases)/sizeof(cases[0]); i++)
{
//printf("case [%d]\n", i);
void *p = speller(cases[i][0], &speller_test, (void *)cases[i][1], idchars);
if (p)
assert(cases[i][2][0] == 'y');
else
assert(cases[i][2][0] == 'n');
}
//printf("unittest_speller() success\n");
}
#endif

7
dmd2/root/speller.h Normal file
View File

@@ -0,0 +1,7 @@
typedef void *(fp_speller_t)(void *, const char *);
extern const char idchars[];
void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset);

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

@@ -0,0 +1,139 @@
// Copyright (c) 1999-2011 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"
void StringTable::init(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-2011 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
{
void **table;
unsigned count;
unsigned tabledim;
void init(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

403
dmd2/scope.c Normal file
View File

@@ -0,0 +1,403 @@
// Copyright (c) 1999-2010 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 "speller.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"
#include "lexer.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->mustsemantic = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->ignoreTemplates = 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->mustsemantic = enclosing->mustsemantic;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->ignoreTemplates = enclosing->ignoreTemplates;
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->symtabInsert(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);
}
}
/************************************************
* Given the failed search attempt, try to find
* one with a close spelling.
*/
void *scope_search_fp(void *arg, const char *seed)
{
//printf("scope_search_fp('%s')\n", seed);
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return NULL;
StringValue *sv = Lexer::stringtable.lookup(seed, len);
if (!sv)
return NULL;
Identifier *id = (Identifier *)sv->ptrvalue;
assert(id);
Scope *sc = (Scope *)arg;
Module::clearCache();
Dsymbol *s = sc->search(0, id, NULL);
return s;
}
Dsymbol *Scope::search_correct(Identifier *ident)
{
if (global.gag)
return NULL; // don't do it for speculative compiles; too time consuming
return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars);
}

Some files were not shown because too many files have changed in this diff Show More