mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merge dmd-1.074 into ldc.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -51,6 +51,13 @@ namespace llvm
|
||||
}
|
||||
#endif
|
||||
|
||||
enum Sizeok
|
||||
{
|
||||
SIZEOKnone, // size of aggregate is not computed yet
|
||||
SIZEOKdone, // size of aggregate is set correctly
|
||||
SIZEOKfwd, // error in computing size of aggregate
|
||||
};
|
||||
|
||||
struct AggregateDeclaration : ScopeDsymbol
|
||||
{
|
||||
Type *type;
|
||||
@@ -62,10 +69,7 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
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
|
||||
enum Sizeok sizeok; // set when structsize contains valid data
|
||||
int isdeprecated; // !=0 if deprecated
|
||||
|
||||
#if DMDV2
|
||||
@@ -89,7 +93,8 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
FuncDeclaration *dtor; // aggregate destructor
|
||||
|
||||
#ifdef IN_GCC
|
||||
Array methods; // flat list of all methods for debug information
|
||||
Expressions *attributes; // GCC decl/type attributes
|
||||
FuncDeclarations methods; // flat list of all methods for debug information
|
||||
#endif
|
||||
|
||||
AggregateDeclaration(Loc loc, Identifier *id);
|
||||
@@ -98,8 +103,10 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
void inlineScan();
|
||||
unsigned size(Loc loc);
|
||||
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
||||
static unsigned placeField(unsigned *nextoffset,
|
||||
unsigned memsize, unsigned memalignsize, unsigned memalign,
|
||||
unsigned *paggsize, unsigned *paggalignsize, bool isunion);
|
||||
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?
|
||||
@@ -163,14 +170,19 @@ struct StructDeclaration : AggregateDeclaration
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
char *mangle();
|
||||
const char *kind();
|
||||
void finalizeSize(Scope *sc);
|
||||
#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);
|
||||
|
||||
@@ -222,7 +234,8 @@ struct BaseClass
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size
|
||||
#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
|
||||
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
|
||||
|
||||
333
dmd/attrib.c
333
dmd/attrib.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -54,6 +54,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
|
||||
return decl;
|
||||
}
|
||||
|
||||
int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||
{
|
||||
Dsymbols *d = include(NULL, NULL);
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
if (s)
|
||||
{
|
||||
if (s->apply(fp, param))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
int m = 0;
|
||||
@@ -61,8 +79,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
//printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
|
||||
m |= s->addMember(sc, sd, m | memnum);
|
||||
}
|
||||
@@ -92,8 +110,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
|
||||
newsc->explicitProtection = explicitProtection;
|
||||
newsc->structalign = structalign;
|
||||
}
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
{ Dsymbol *s = decl->tdata()[i];
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{ Dsymbol *s = (*decl)[i];
|
||||
|
||||
s->setScope(newsc); // yes, the only difference from semanticNewSc()
|
||||
}
|
||||
@@ -127,8 +145,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc,
|
||||
newsc->explicitProtection = explicitProtection;
|
||||
newsc->structalign = structalign;
|
||||
}
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
{ Dsymbol *s = decl->tdata()[i];
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{ Dsymbol *s = (*decl)[i];
|
||||
|
||||
s->semantic(newsc);
|
||||
}
|
||||
@@ -149,7 +167,7 @@ void AttribDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{
|
||||
Dsymbol *s = d->tdata()[i];
|
||||
Dsymbol *s = (*d)[i];
|
||||
|
||||
s->semantic(sc);
|
||||
}
|
||||
@@ -163,7 +181,7 @@ void AttribDeclaration::semantic2(Scope *sc)
|
||||
if (d)
|
||||
{
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->semantic2(sc);
|
||||
}
|
||||
}
|
||||
@@ -176,7 +194,7 @@ void AttribDeclaration::semantic3(Scope *sc)
|
||||
if (d)
|
||||
{
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->semantic3(sc);
|
||||
}
|
||||
}
|
||||
@@ -188,8 +206,8 @@ void AttribDeclaration::inlineScan()
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
//printf("AttribDeclaration::inlineScan %s\n", s->toChars());
|
||||
s->inlineScan();
|
||||
}
|
||||
@@ -205,8 +223,8 @@ void AttribDeclaration::addComment(unsigned char *comment)
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
//printf("AttribDeclaration::addComment %s\n", s->toChars());
|
||||
s->addComment(comment);
|
||||
}
|
||||
@@ -230,8 +248,8 @@ void AttribDeclaration::emitComment(Scope *sc)
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
//printf("AttribDeclaration::emitComment %s\n", s->toChars());
|
||||
s->emitComment(sc);
|
||||
}
|
||||
@@ -246,32 +264,27 @@ void AttribDeclaration::toObjFile(int multiobj)
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->toObjFile(multiobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AttribDeclaration::cvMember(unsigned char *p)
|
||||
#endif
|
||||
|
||||
void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||
{
|
||||
int nwritten = 0;
|
||||
int n;
|
||||
Dsymbols *d = include(NULL, NULL);
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
n = s->cvMember(p);
|
||||
if (p)
|
||||
p += n;
|
||||
nwritten += n;
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->setFieldOffset(ad, poffset, isunion);
|
||||
}
|
||||
}
|
||||
return nwritten;
|
||||
}
|
||||
#endif
|
||||
|
||||
int AttribDeclaration::hasPointers()
|
||||
{
|
||||
@@ -281,7 +294,7 @@ int AttribDeclaration::hasPointers()
|
||||
{
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{
|
||||
Dsymbol *s = d->tdata()[i];
|
||||
Dsymbol *s = (*d)[i];
|
||||
if (s->hasPointers())
|
||||
return 1;
|
||||
}
|
||||
@@ -323,8 +336,8 @@ void AttribDeclaration::checkCtorConstInit()
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->checkCtorConstInit();
|
||||
}
|
||||
}
|
||||
@@ -339,8 +352,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
|
||||
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->addLocalClass(aclasses);
|
||||
}
|
||||
}
|
||||
@@ -354,15 +367,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
if (decl->dim == 0)
|
||||
buf->writestring("{}");
|
||||
else if (decl->dim == 1)
|
||||
(decl->tdata()[0])->toCBuffer(buf, hgs);
|
||||
((*decl)[0])->toCBuffer(buf, hgs);
|
||||
else
|
||||
{
|
||||
buf->writenl();
|
||||
buf->writeByte('{');
|
||||
buf->writenl();
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = decl->tdata()[i];
|
||||
Dsymbol *s = (*decl)[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
@@ -467,6 +480,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
|
||||
{ STCout, TOKout },
|
||||
{ STCin, TOKin },
|
||||
#if DMDV2
|
||||
{ STCmanifest, TOKenum },
|
||||
{ STCimmutable, TOKimmutable },
|
||||
{ STCshared, TOKshared },
|
||||
{ STCnothrow, TOKnothrow },
|
||||
@@ -474,10 +488,11 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
|
||||
{ STCref, TOKref },
|
||||
{ STCtls, TOKtls },
|
||||
{ STCgshared, TOKgshared },
|
||||
{ STCproperty, TOKat },
|
||||
{ STCsafe, TOKat },
|
||||
{ STCtrusted, TOKat },
|
||||
{ STCdisable, TOKat },
|
||||
{ STCproperty, TOKat, Id::property },
|
||||
{ STCsafe, TOKat, Id::safe },
|
||||
{ STCtrusted, TOKat, Id::trusted },
|
||||
{ STCsystem, TOKat, Id::system },
|
||||
{ STCdisable, TOKat, Id::disable },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -488,20 +503,9 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
|
||||
enum TOK tok = table[i].tok;
|
||||
#if DMDV2
|
||||
if (tok == TOKat)
|
||||
{ Identifier *id;
|
||||
|
||||
if (stc & STCproperty)
|
||||
id = Id::property;
|
||||
else if (stc & STCsafe)
|
||||
id = Id::safe;
|
||||
else if (stc & STCtrusted)
|
||||
id = Id::trusted;
|
||||
else if (stc & STCdisable)
|
||||
id = Id::disable;
|
||||
else
|
||||
assert(0);
|
||||
{
|
||||
buf->writeByte('@');
|
||||
buf->writestring(id->toChars());
|
||||
buf->writestring(table[i].id->toChars());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -560,9 +564,9 @@ void LinkDeclaration::semantic3(Scope *sc)
|
||||
{ enum LINK linkage_save = sc->linkage;
|
||||
|
||||
sc->linkage = linkage;
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = decl->tdata()[i];
|
||||
Dsymbol *s = (*decl)[i];
|
||||
|
||||
s->semantic3(sc);
|
||||
}
|
||||
@@ -738,6 +742,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
|
||||
: AttribDeclaration(decl)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->alignment = 0;
|
||||
this->isunion = isunion;
|
||||
this->sem = 0;
|
||||
}
|
||||
@@ -755,21 +760,6 @@ void AnonDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
|
||||
|
||||
if (sem == 1)
|
||||
{ //printf("already completed\n");
|
||||
scope = NULL;
|
||||
return; // semantic() already completed
|
||||
}
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
scx = scope;
|
||||
scope = NULL;
|
||||
}
|
||||
|
||||
unsigned dprogress_save = Module::dprogress;
|
||||
|
||||
assert(sc->parent);
|
||||
|
||||
Dsymbol *parent = sc->parent->pastMixin();
|
||||
@@ -781,106 +771,85 @@ void AnonDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
}
|
||||
|
||||
alignment = sc->structalign;
|
||||
if (decl)
|
||||
{
|
||||
AnonymousAggregateDeclaration aad;
|
||||
int adisunion;
|
||||
|
||||
if (sc->anonAgg)
|
||||
{ ad = sc->anonAgg;
|
||||
adisunion = sc->inunion;
|
||||
}
|
||||
else
|
||||
adisunion = ad->isUnionDeclaration() != NULL;
|
||||
|
||||
// printf("\tsc->anonAgg = %p\n", sc->anonAgg);
|
||||
// printf("\tad = %p\n", ad);
|
||||
// printf("\taad = %p\n", &aad);
|
||||
|
||||
sc = sc->push();
|
||||
sc->anonAgg = &aad;
|
||||
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
|
||||
sc->inunion = isunion;
|
||||
sc->offset = 0;
|
||||
sc->flags = 0;
|
||||
aad.structalign = sc->structalign;
|
||||
aad.parent = ad;
|
||||
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = decl->tdata()[i];
|
||||
|
||||
Dsymbol *s = (*decl)[i];
|
||||
s->semantic(sc);
|
||||
if (isunion)
|
||||
sc->offset = 0;
|
||||
if (aad.sizeok == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
sc = sc->pop();
|
||||
}
|
||||
}
|
||||
|
||||
// If failed due to forward references, unwind and try again later
|
||||
if (aad.sizeok == 2)
|
||||
|
||||
void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||
{
|
||||
//printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
|
||||
|
||||
if (decl)
|
||||
{
|
||||
/* This works by treating an AnonDeclaration as an aggregate 'member',
|
||||
* so in order to place that member we need to compute the member's
|
||||
* size and alignment.
|
||||
*/
|
||||
|
||||
size_t fieldstart = ad->fields.dim;
|
||||
|
||||
/* Hackishly hijack ad's structsize and alignsize fields
|
||||
* for use in our fake anon aggregate member.
|
||||
*/
|
||||
unsigned savestructsize = ad->structsize;
|
||||
unsigned savealignsize = ad->alignsize;
|
||||
ad->structsize = 0;
|
||||
ad->alignsize = 0;
|
||||
|
||||
unsigned offset = 0;
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
ad->sizeok = 2;
|
||||
//printf("\tsetting ad->sizeok %p to 2\n", ad);
|
||||
if (!sc->anonAgg)
|
||||
{
|
||||
scope = scx ? scx : new Scope(*sc);
|
||||
scope->setNoFree();
|
||||
scope->module->addDeferredSemantic(this);
|
||||
}
|
||||
Module::dprogress = dprogress_save;
|
||||
//printf("\tforward reference %p\n", this);
|
||||
return;
|
||||
Dsymbol *s = (*decl)[i];
|
||||
|
||||
s->setFieldOffset(ad, &offset, this->isunion);
|
||||
if (this->isunion)
|
||||
offset = 0;
|
||||
}
|
||||
if (sem == 0)
|
||||
{ Module::dprogress++;
|
||||
sem = 1;
|
||||
//printf("\tcompleted %p\n", this);
|
||||
}
|
||||
else
|
||||
;//printf("\talready completed %p\n", this);
|
||||
|
||||
unsigned anonstructsize = ad->structsize;
|
||||
unsigned anonalignsize = ad->alignsize;
|
||||
ad->structsize = savestructsize;
|
||||
ad->alignsize = savealignsize;
|
||||
|
||||
// 0 sized structs are set to 1 byte
|
||||
if (aad.structsize == 0)
|
||||
if (anonstructsize == 0)
|
||||
{
|
||||
aad.structsize = 1;
|
||||
aad.alignsize = 1;
|
||||
anonstructsize = 1;
|
||||
anonalignsize = 1;
|
||||
}
|
||||
|
||||
// Align size of anonymous aggregate
|
||||
//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
|
||||
ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
|
||||
//ad->structsize = sc->offset;
|
||||
//printf("sc->offset = %d\n", sc->offset);
|
||||
/* Given the anon 'member's size and alignment,
|
||||
* go ahead and place it.
|
||||
*/
|
||||
unsigned anonoffset = AggregateDeclaration::placeField(
|
||||
poffset,
|
||||
anonstructsize, anonalignsize, alignment,
|
||||
&ad->structsize, &ad->alignsize,
|
||||
isunion);
|
||||
|
||||
// Add members of aad to ad
|
||||
//printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars());
|
||||
for (unsigned i = 0; i < aad.fields.dim; i++)
|
||||
// Add to the anon fields the base offset of this anonymous aggregate
|
||||
//printf("anon fields, anonoffset = %d\n", anonoffset);
|
||||
for (size_t i = fieldstart; i < ad->fields.dim; i++)
|
||||
{
|
||||
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
|
||||
|
||||
v->offset += sc->offset;
|
||||
ad->fields.push(v);
|
||||
VarDeclaration *v = ad->fields[i];
|
||||
//printf("\t[%d] %s %d\n", i, v->toChars(), v->offset);
|
||||
v->offset += anonoffset;
|
||||
}
|
||||
|
||||
// Add size of aad to ad
|
||||
if (adisunion)
|
||||
{
|
||||
if (aad.structsize > ad->structsize)
|
||||
ad->structsize = aad.structsize;
|
||||
sc->offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ad->structsize = sc->offset + aad.structsize;
|
||||
sc->offset = ad->structsize;
|
||||
}
|
||||
|
||||
if (ad->alignsize < aad.alignsize)
|
||||
ad->alignsize = aad.alignsize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,9 +860,9 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring("\n{\n");
|
||||
if (decl)
|
||||
{
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = decl->tdata()[i];
|
||||
Dsymbol *s = (*decl)[i];
|
||||
|
||||
//buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
@@ -953,10 +922,10 @@ void PragmaDeclaration::setScope(Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression *e = args->tdata()[0];
|
||||
Expression *e = (*args)[0];
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
args->tdata()[0] = e;
|
||||
(*args)[0] = e;
|
||||
StringExp* se = e->toString();
|
||||
if (!se)
|
||||
{
|
||||
@@ -991,7 +960,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < args->dim; i++)
|
||||
{
|
||||
Expression *e = args->tdata()[i];
|
||||
Expression *e = (*args)[i];
|
||||
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
@@ -1013,11 +982,11 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
error("string expected for library name");
|
||||
else
|
||||
{
|
||||
Expression *e = args->tdata()[0];
|
||||
Expression *e = (*args)[0];
|
||||
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
args->tdata()[0] = e;
|
||||
(*args)[0] = e;
|
||||
if (e->op == TOKerror)
|
||||
goto Lnodecl;
|
||||
StringExp *se = e->toString();
|
||||
@@ -1045,7 +1014,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
Declaration *d = NULL;
|
||||
StringExp *s = NULL;
|
||||
|
||||
e = (Expression *)args->data[0];
|
||||
e = (*args)[0];
|
||||
e = e->semantic(sc);
|
||||
if (e->op == TOKvar)
|
||||
{
|
||||
@@ -1056,14 +1025,14 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
if (!d)
|
||||
error("first argument of GNU_asm must be a function or variable declaration");
|
||||
|
||||
e = args->tdata()[1];
|
||||
e = (*args)[1];
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue);
|
||||
e = e->toString();
|
||||
if (e && ((StringExp *)e)->sz == 1)
|
||||
s = ((StringExp *)e);
|
||||
else
|
||||
error("second argument of GNU_asm must be a char string");
|
||||
error("second argument of GNU_asm must be a character string");
|
||||
|
||||
if (d && s)
|
||||
d->c_ident = Lexer::idPool((char*) s->string);
|
||||
@@ -1078,10 +1047,10 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
error("function name expected for start address");
|
||||
else
|
||||
{
|
||||
Expression *e = (Expression *)args->data[0];
|
||||
Expression *e = (*args)[0];
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
args->data[0] = (void *)e;
|
||||
(*args)[0] = e;
|
||||
Dsymbol *sa = getDsymbol(e);
|
||||
if (!sa || !sa->isFuncDeclaration())
|
||||
error("function name expected for start address, not '%s'", e->toChars());
|
||||
@@ -1111,11 +1080,13 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < args->dim; i++)
|
||||
{
|
||||
#if IN_LLVM
|
||||
// ignore errors in ignored pragmas.
|
||||
global.gag++;
|
||||
unsigned errors_save = global.errors;
|
||||
#endif
|
||||
|
||||
Expression *e = (Expression *)args->data[i];
|
||||
Expression *e = (*args)[i];
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (i == 0)
|
||||
@@ -1124,9 +1095,11 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
printf(",");
|
||||
printf("%s", e->toChars());
|
||||
|
||||
#if IN_LLVM
|
||||
// restore error state.
|
||||
global.gag--;
|
||||
global.errors = errors_save;
|
||||
#endif
|
||||
}
|
||||
if (args->dim)
|
||||
printf(")");
|
||||
@@ -1141,9 +1114,9 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
Ldecl:
|
||||
if (decl)
|
||||
{
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = decl->tdata()[i];
|
||||
Dsymbol *s = (*decl)[i];
|
||||
|
||||
s->semantic(sc);
|
||||
|
||||
@@ -1180,7 +1153,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
|
||||
{
|
||||
assert(args && args->dim == 1);
|
||||
|
||||
Expression *e = (Expression *)args->data[0];
|
||||
Expression *e = (*args)[0];
|
||||
|
||||
assert(e->op == TOKstring);
|
||||
|
||||
@@ -1208,7 +1181,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
|
||||
else if (ident == Id::startaddress)
|
||||
{
|
||||
assert(args && args->dim == 1);
|
||||
Expression *e = (Expression *)args->data[0];
|
||||
Expression *e = (*args)[0];
|
||||
Dsymbol *sa = getDsymbol(e);
|
||||
FuncDeclaration *f = sa->isFuncDeclaration();
|
||||
assert(f);
|
||||
@@ -1285,8 +1258,8 @@ void ConditionalDeclaration::emitComment(Scope *sc)
|
||||
* a template, then include(NULL, NULL) will fail.
|
||||
*/
|
||||
Dsymbols *d = decl ? decl : elsedecl;
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
s->emitComment(sc);
|
||||
}
|
||||
}
|
||||
@@ -1308,9 +1281,9 @@ void ConditionalDeclaration::setScope(Scope *sc)
|
||||
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{
|
||||
Dsymbol *s = d->tdata()[i];
|
||||
Dsymbol *s = (*d)[i];
|
||||
|
||||
s->setScope(sc);
|
||||
}
|
||||
@@ -1324,9 +1297,9 @@ void ConditionalDeclaration::importAll(Scope *sc)
|
||||
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{
|
||||
Dsymbol *s = d->tdata()[i];
|
||||
Dsymbol *s = (*d)[i];
|
||||
|
||||
s->importAll(sc);
|
||||
}
|
||||
@@ -1349,10 +1322,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment)
|
||||
{
|
||||
if (d)
|
||||
{
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = d->tdata()[i];
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
//printf("ConditionalDeclaration::addComment %s\n", s->toChars());
|
||||
s->addComment(comment);
|
||||
}
|
||||
@@ -1372,9 +1343,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writenl();
|
||||
if (decl)
|
||||
{
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = decl->tdata()[i];
|
||||
Dsymbol *s = (*decl)[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
@@ -1388,9 +1359,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writenl();
|
||||
buf->writeByte('{');
|
||||
buf->writenl();
|
||||
for (unsigned i = 0; i < elsedecl->dim; i++)
|
||||
for (size_t i = 0; i < elsedecl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = elsedecl->tdata()[i];
|
||||
Dsymbol *s = (*elsedecl)[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
@@ -1474,9 +1445,9 @@ void StaticIfDeclaration::semantic(Scope *sc)
|
||||
addisdone = 1;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{
|
||||
Dsymbol *s = d->tdata()[i];
|
||||
Dsymbol *s = (*d)[i];
|
||||
|
||||
s->semantic(sc);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -33,6 +33,7 @@ struct AttribDeclaration : Dsymbol
|
||||
|
||||
AttribDeclaration(Dsymbols *decl);
|
||||
virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
||||
int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void setScopeNewSc(Scope *sc,
|
||||
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
|
||||
@@ -48,6 +49,7 @@ struct AttribDeclaration : Dsymbol
|
||||
void emitComment(Scope *sc);
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
int hasPointers();
|
||||
bool hasStaticCtorOrDtor();
|
||||
void checkCtorConstInit();
|
||||
@@ -58,7 +60,6 @@ struct AttribDeclaration : Dsymbol
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
int cvMember(unsigned char *p);
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -119,12 +120,14 @@ struct AlignDeclaration : AttribDeclaration
|
||||
|
||||
struct AnonDeclaration : AttribDeclaration
|
||||
{
|
||||
int isunion;
|
||||
bool isunion;
|
||||
unsigned alignment;
|
||||
int sem; // 1 if successful semantic()
|
||||
|
||||
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
@@ -1166,17 +1166,16 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
Expression *DelegateExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
Type *tb;
|
||||
#if 0
|
||||
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
|
||||
toChars(), type->toChars(), t->toChars());
|
||||
#endif
|
||||
Expression *e = this;
|
||||
static char msg[] = "cannot form delegate due to covariant return type";
|
||||
|
||||
tb = t->toBasetype();
|
||||
Expression *e = this;
|
||||
Type *tb = t->toBasetype();
|
||||
type = type->toBasetype();
|
||||
if (tb != type)
|
||||
if (tb != type || hasOverloads)
|
||||
{
|
||||
// Look for delegates to functions where the functions are overloaded.
|
||||
FuncDeclaration *f;
|
||||
|
||||
112
dmd/class.c
112
dmd/class.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -228,9 +228,9 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
|
||||
cd->baseclasses->setDim(this->baseclasses->dim);
|
||||
for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
||||
{
|
||||
BaseClass *b = (BaseClass *)this->baseclasses->data[i];
|
||||
BaseClass *b = this->baseclasses->tdata()[i];
|
||||
BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
|
||||
cd->baseclasses->data[i] = b2;
|
||||
cd->baseclasses->tdata()[i] = b2;
|
||||
}
|
||||
|
||||
ScopeDsymbol::syntaxCopy(cd);
|
||||
@@ -264,7 +264,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
}
|
||||
if (symtab)
|
||||
{ if (sizeok == 1 || !scope)
|
||||
{ if (sizeok == SIZEOKdone || !scope)
|
||||
{ //printf("\tsemantic for '%s' is already completed\n", toChars());
|
||||
return; // semantic() already completed
|
||||
}
|
||||
@@ -290,7 +290,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
|
||||
// Expand any tuples in baseclasses[]
|
||||
for (size_t i = 0; i < baseclasses->dim; )
|
||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
{ BaseClass *b = baseclasses->tdata()[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
Type *tb = b->type->toBasetype();
|
||||
|
||||
@@ -315,11 +315,12 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
BaseClass *b;
|
||||
Type *tb;
|
||||
|
||||
b = (BaseClass *)baseclasses->data[0];
|
||||
b = baseclasses->tdata()[0];
|
||||
//b->type = b->type->semantic(loc, sc);
|
||||
tb = b->type->toBasetype();
|
||||
if (tb->ty != Tclass)
|
||||
{ error("base type must be class or interface, not %s", b->type->toChars());
|
||||
{ if (b->type != Type::terror)
|
||||
error("base type must be class or interface, not %s", b->type->toChars());
|
||||
baseclasses->remove(0);
|
||||
}
|
||||
else
|
||||
@@ -331,7 +332,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
if (!isDeprecated())
|
||||
{
|
||||
// Deriving from deprecated class makes this one deprecated too
|
||||
isdeprecated = 1;
|
||||
isdeprecated = true;
|
||||
|
||||
tc->checkDeprecated(loc, sc);
|
||||
}
|
||||
@@ -350,12 +351,12 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
goto L7;
|
||||
}
|
||||
}
|
||||
if (!tc->sym->symtab || tc->sym->sizeok == 0)
|
||||
if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
|
||||
{ // Try to resolve forward reference
|
||||
if (/*sc->mustsemantic &&*/ tc->sym->scope)
|
||||
tc->sym->semantic(NULL);
|
||||
}
|
||||
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
|
||||
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
|
||||
{
|
||||
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
|
||||
//error("forward reference of base class %s", baseClass->toChars());
|
||||
@@ -384,7 +385,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
BaseClass *b;
|
||||
Type *tb;
|
||||
|
||||
b = (BaseClass *)baseclasses->data[i];
|
||||
b = baseclasses->tdata()[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
tb = b->type->toBasetype();
|
||||
if (tb->ty == Tclass)
|
||||
@@ -392,7 +393,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
else
|
||||
tc = NULL;
|
||||
if (!tc || !tc->sym->isInterfaceDeclaration())
|
||||
{
|
||||
{ if (b->type != Type::terror)
|
||||
error("base type must be interface, not %s", b->type->toChars());
|
||||
baseclasses->remove(i);
|
||||
continue;
|
||||
@@ -404,7 +405,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
if (!isDeprecated())
|
||||
{
|
||||
// Deriving from deprecated class makes this one deprecated too
|
||||
isdeprecated = 1;
|
||||
isdeprecated = true;
|
||||
|
||||
tc->checkDeprecated(loc, sc);
|
||||
}
|
||||
@@ -413,7 +414,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
// Check for duplicate interfaces
|
||||
for (size_t j = (baseClass ? 1 : 0); j < i; j++)
|
||||
{
|
||||
BaseClass *b2 = (BaseClass *)baseclasses->data[j];
|
||||
BaseClass *b2 = baseclasses->tdata()[j];
|
||||
if (b2->base == tc->sym)
|
||||
error("inherits from duplicate interface %s", b2->base->toChars());
|
||||
}
|
||||
@@ -467,7 +468,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
interfaces_dim = baseclasses->dim;
|
||||
interfaces = (BaseClass **)baseclasses->data;
|
||||
interfaces = baseclasses->tdata();
|
||||
|
||||
|
||||
if (baseClass)
|
||||
@@ -480,7 +481,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
|
||||
// Copy vtbl[] from base class
|
||||
vtbl.setDim(baseClass->vtbl.dim);
|
||||
memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
|
||||
memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
|
||||
|
||||
// Inherit properties from base class
|
||||
com = baseClass->isCOMclass();
|
||||
@@ -503,7 +504,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->addMember(sc, this, 1);
|
||||
}
|
||||
|
||||
@@ -606,17 +607,20 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
structsize = sc->offset;
|
||||
Scope scsave = *sc;
|
||||
size_t members_dim = members->dim;
|
||||
sizeok = 0;
|
||||
sizeok = SIZEOKnone;
|
||||
|
||||
/* Set scope so if there are forward references, we still might be able to
|
||||
* resolve individual members like enums.
|
||||
*/
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
/* There are problems doing this in the general case because
|
||||
* Scope keeps track of things like 'offset'
|
||||
*/
|
||||
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
||||
if (s->isEnumDeclaration() ||
|
||||
(s->isAggregateDeclaration() && s->ident) ||
|
||||
s->isTemplateMixin() ||
|
||||
s->isAliasDeclaration())
|
||||
{
|
||||
//printf("setScope %s %s\n", s->kind(), s->toChars());
|
||||
s->setScope(sc);
|
||||
@@ -624,13 +628,35 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->semantic(sc);
|
||||
}
|
||||
|
||||
if (sizeok == 2)
|
||||
{ // semantic() failed because of forward references.
|
||||
// Set the offsets of the fields and determine the size of the class
|
||||
|
||||
unsigned offset = structsize;
|
||||
bool isunion = isUnionDeclaration() != NULL;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->setFieldOffset(this, &offset, false);
|
||||
}
|
||||
sc->offset = structsize;
|
||||
|
||||
if (global.gag && global.gaggedErrors != errors)
|
||||
{ // The type is no good, yet the error messages were gagged.
|
||||
type = Type::terror;
|
||||
}
|
||||
|
||||
if (sizeok == 2) // failed due to forward references
|
||||
{ // semantic() failed due to forward references
|
||||
// Unwind what we did, and defer it for later
|
||||
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{ Dsymbol *s = fields[i];
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd)
|
||||
vd->offset = 0;
|
||||
}
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
alignsize = 0;
|
||||
@@ -650,7 +676,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
|
||||
//printf("\tsemantic('%s') successful\n", toChars());
|
||||
|
||||
structsize = sc->offset;
|
||||
//members->print();
|
||||
|
||||
/* Look for special member functions.
|
||||
@@ -683,7 +708,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
members->push(ctor);
|
||||
ctor->addMember(sc, this, 1);
|
||||
*sc = scsave; // why? What about sc->nofree?
|
||||
sc->offset = structsize;
|
||||
ctor->semantic(sc);
|
||||
this->ctor = ctor;
|
||||
defaultCtor = ctor;
|
||||
@@ -699,9 +723,10 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
#endif
|
||||
|
||||
// Allocate instance of each new interface
|
||||
sc->offset = structsize;
|
||||
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
||||
{
|
||||
BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
|
||||
BaseClass *b = (*vtblInterfaces)[i];
|
||||
unsigned thissize = PTRSIZE;
|
||||
|
||||
alignmember(structalign, thissize, &sc->offset);
|
||||
@@ -720,7 +745,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
alignsize = thissize;
|
||||
}
|
||||
structsize = sc->offset;
|
||||
sizeok = 1;
|
||||
sizeok = SIZEOKdone;
|
||||
Module::dprogress++;
|
||||
|
||||
dtor = buildDtor(sc);
|
||||
@@ -731,7 +756,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
// Fill in base class vtbl[]s
|
||||
for (i = 0; i < vtblInterfaces->dim; i++)
|
||||
{
|
||||
BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
|
||||
BaseClass *b = vtblInterfaces->tdata()[i];
|
||||
|
||||
//b->fillVtbl(this, &b->vtbl, 1);
|
||||
}
|
||||
@@ -750,7 +775,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
}
|
||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||
{
|
||||
BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
BaseClass *b = baseclasses->tdata()[i];
|
||||
|
||||
if (i)
|
||||
buf->writeByte(',');
|
||||
@@ -764,7 +789,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writenl();
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
@@ -799,7 +824,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
|
||||
return 0;
|
||||
//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
|
||||
for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cd->baseclasses->data[i];
|
||||
{ BaseClass *b = cd->baseclasses->tdata()[i];
|
||||
|
||||
if (b->base == this || isBaseOf2(b->base))
|
||||
return 1;
|
||||
@@ -845,7 +870,7 @@ int ClassDeclaration::isBaseInfoComplete()
|
||||
if (!baseClass)
|
||||
return ident == Id::Object;
|
||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
{ BaseClass *b = baseclasses->tdata()[i];
|
||||
if (!b->base || !b->base->isBaseInfoComplete())
|
||||
return 0;
|
||||
}
|
||||
@@ -860,7 +885,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
if (scope && !symtab)
|
||||
{ Scope *sc = scope;
|
||||
sc->mustsemantic++;
|
||||
// If speculatively gagged, ungag now.
|
||||
unsigned oldgag = global.gag;
|
||||
if (global.isSpeculativeGagging())
|
||||
global.gag = 0;
|
||||
semantic(sc);
|
||||
global.gag = oldgag;
|
||||
sc->mustsemantic--;
|
||||
}
|
||||
|
||||
@@ -878,7 +908,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
|
||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||
{
|
||||
BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
BaseClass *b = baseclasses->tdata()[i];
|
||||
|
||||
if (b->base)
|
||||
{
|
||||
@@ -1178,12 +1208,12 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
|
||||
if (sc->stc & STCdeprecated)
|
||||
{
|
||||
isdeprecated = 1;
|
||||
isdeprecated = true;
|
||||
}
|
||||
|
||||
// Expand any tuples in baseclasses[]
|
||||
for (size_t i = 0; i < baseclasses->dim; )
|
||||
{ BaseClass *b = (BaseClass *)baseclasses->data[0];
|
||||
{ BaseClass *b = (*baseclasses)[0];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
Type *tb = b->type->toBasetype();
|
||||
|
||||
@@ -1208,7 +1238,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
BaseClass *b;
|
||||
Type *tb;
|
||||
|
||||
b = (BaseClass *)baseclasses->data[i];
|
||||
b = baseclasses->tdata()[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
tb = b->type->toBasetype();
|
||||
if (tb->ty == Tclass)
|
||||
@@ -1216,7 +1246,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
else
|
||||
tc = NULL;
|
||||
if (!tc || !tc->sym->isInterfaceDeclaration())
|
||||
{
|
||||
{ if (b->type != Type::terror)
|
||||
error("base type must be interface, not %s", b->type->toChars());
|
||||
baseclasses->remove(i);
|
||||
continue;
|
||||
@@ -1226,7 +1256,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
// Check for duplicate interfaces
|
||||
for (size_t j = 0; j < i; j++)
|
||||
{
|
||||
BaseClass *b2 = (BaseClass *)baseclasses->data[j];
|
||||
BaseClass *b2 = baseclasses->tdata()[j];
|
||||
if (b2->base == tc->sym)
|
||||
error("inherits from duplicate interface %s", b2->base->toChars());
|
||||
}
|
||||
@@ -1311,10 +1341,10 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
sc->explicitProtection = 0;
|
||||
structalign = sc->structalign;
|
||||
sc->offset = PTRSIZE * 2;
|
||||
structsize = sc->offset;
|
||||
inuse++;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->semantic(sc);
|
||||
}
|
||||
inuse--;
|
||||
@@ -1408,7 +1438,7 @@ int InterfaceDeclaration::isBaseInfoComplete()
|
||||
{
|
||||
assert(!baseClass);
|
||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
{ BaseClass *b = baseclasses->tdata()[i];
|
||||
if (!b->base || !b->base->isBaseInfoComplete ())
|
||||
return 0;
|
||||
}
|
||||
|
||||
22
dmd/cond.c
22
dmd/cond.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -225,6 +225,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
this->nest = 0;
|
||||
}
|
||||
|
||||
Condition *StaticIfCondition::syntaxCopy()
|
||||
@@ -235,7 +236,7 @@ Condition *StaticIfCondition::syntaxCopy()
|
||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
#if 0
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc);
|
||||
if (s)
|
||||
{
|
||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||
@@ -243,6 +244,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
#endif
|
||||
if (inc == 0)
|
||||
{
|
||||
if (exp->op == TOKerror || nest > 100)
|
||||
{
|
||||
error(loc, (nest > 1000) ? "unresolvable circular static if expression"
|
||||
: "error evaluating static if expression");
|
||||
if (!global.gag)
|
||||
inc = 2; // so we don't see the error message again
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "static if conditional cannot be at global scope");
|
||||
@@ -250,13 +260,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
++nest;
|
||||
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))
|
||||
--nest;
|
||||
if (e->op == TOKerror)
|
||||
{ exp = e;
|
||||
inc = 0;
|
||||
}
|
||||
else if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
else if (e->isBool(FALSE))
|
||||
inc = 2;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -36,6 +36,7 @@ struct Condition
|
||||
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
|
||||
@@ -59,6 +60,7 @@ struct DebugCondition : DVCondition
|
||||
|
||||
int include(Scope *sc, ScopeDsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
DebugCondition *isDebugCondition() { return this; }
|
||||
};
|
||||
|
||||
struct VersionCondition : DVCondition
|
||||
@@ -77,6 +79,7 @@ struct VersionCondition : DVCondition
|
||||
struct StaticIfCondition : Condition
|
||||
{
|
||||
Expression *exp;
|
||||
int nest; // limit circular dependencies
|
||||
|
||||
StaticIfCondition(Loc loc, Expression *exp);
|
||||
Condition *syntaxCopy();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -530,7 +530,8 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
goto L2;
|
||||
}
|
||||
else
|
||||
{ error("cannot alias an expression %s", e->toChars());
|
||||
{ if (e->op != TOKerror)
|
||||
error("cannot alias an expression %s", e->toChars());
|
||||
t = e->type;
|
||||
}
|
||||
}
|
||||
@@ -543,7 +544,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
ScopeDsymbol::multiplyDefined(0, this, overnext);
|
||||
this->inSemantic = 0;
|
||||
|
||||
if (errors != global.errors)
|
||||
if (global.gag && errors != global.errors)
|
||||
type = savedtype;
|
||||
return;
|
||||
|
||||
@@ -580,7 +581,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
assert(global.errors);
|
||||
s = NULL;
|
||||
}
|
||||
if (errors != global.errors)
|
||||
if (global.gag && errors != global.errors)
|
||||
{
|
||||
type = savedtype;
|
||||
overnext = savedovernext;
|
||||
@@ -728,6 +729,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
|
||||
#if DMDV1
|
||||
nestedref = 0;
|
||||
#endif
|
||||
alignment = 0;
|
||||
ctorinit = 0;
|
||||
aliassym = NULL;
|
||||
onstack = 0;
|
||||
@@ -767,6 +769,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
|
||||
sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
|
||||
sv->storage_class = storage_class;
|
||||
}
|
||||
|
||||
// Syntax copy for header file
|
||||
if (!htype) // Don't overwrite original
|
||||
{ if (type) // Make copy for both old and new instances
|
||||
@@ -955,9 +958,7 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
AggregateDeclaration *aad = sc->anonAgg;
|
||||
if (!aad)
|
||||
aad = parent->isAggregateDeclaration();
|
||||
AggregateDeclaration *aad = parent->isAggregateDeclaration();
|
||||
if (aad)
|
||||
{
|
||||
#if DMDV2
|
||||
@@ -970,7 +971,15 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
aad->addField(sc, this);
|
||||
{
|
||||
storage_class |= STCfield;
|
||||
alignment = sc->structalign;
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor ||
|
||||
tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor)
|
||||
aad->noDefaultCtor = TRUE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
InterfaceDeclaration *id = parent->isInterfaceDeclaration();
|
||||
@@ -1305,6 +1314,31 @@ ExpInitializer *VarDeclaration::getExpInitializer()
|
||||
void VarDeclaration::semantic2(Scope *sc)
|
||||
{
|
||||
//printf("VarDeclaration::semantic2('%s')\n", toChars());
|
||||
// Inside unions, default to void initializers
|
||||
if (!init && sc->inunion && !toParent()->isFuncDeclaration())
|
||||
{
|
||||
AggregateDeclaration *aad = parent->isAggregateDeclaration();
|
||||
if (aad)
|
||||
{
|
||||
if (aad->fields[0] == this)
|
||||
{
|
||||
int hasinit = 0;
|
||||
for (size_t i = 1; i < aad->fields.dim; i++)
|
||||
{
|
||||
if (aad->fields[i]->init &&
|
||||
!aad->fields[i]->init->isVoidInitializer())
|
||||
{
|
||||
hasinit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasinit)
|
||||
init = new ExpInitializer(loc, type->defaultInitLiteral(loc));
|
||||
}
|
||||
else
|
||||
init = new VoidInitializer(loc);
|
||||
}
|
||||
}
|
||||
if (init && !toParent()->isFuncDeclaration())
|
||||
{ inuse++;
|
||||
#if 0
|
||||
@@ -1330,6 +1364,82 @@ void VarDeclaration::semantic3(Scope *sc)
|
||||
Declaration::semantic3(sc);
|
||||
}
|
||||
|
||||
void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||
{
|
||||
//printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars());
|
||||
|
||||
if (aliassym)
|
||||
{ // If this variable was really a tuple, set the offsets for the tuple fields
|
||||
TupleDeclaration *v2 = aliassym->isTupleDeclaration();
|
||||
assert(v2);
|
||||
for (size_t i = 0; i < v2->objects->dim; i++)
|
||||
{ Object *o = (*v2->objects)[i];
|
||||
assert(o->dyncast() == DYNCAST_EXPRESSION);
|
||||
Expression *e = (Expression *)o;
|
||||
assert(e->op == TOKdsymbol);
|
||||
DsymbolExp *se = (DsymbolExp *)e;
|
||||
se->s->setFieldOffset(ad, poffset, isunion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(storage_class & STCfield))
|
||||
return;
|
||||
assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
|
||||
|
||||
/* Fields that are tuples appear both as part of TupleDeclarations and
|
||||
* as members. That means ignore them if they are already a field.
|
||||
*/
|
||||
if (offset)
|
||||
return; // already a field
|
||||
for (size_t i = 0; i < ad->fields.dim; i++)
|
||||
{
|
||||
if (ad->fields[i] == this)
|
||||
return; // already a field
|
||||
}
|
||||
|
||||
// Check for forward referenced types which will fail the size() call
|
||||
Type *t = type->toBasetype();
|
||||
if (storage_class & STCref)
|
||||
{ // References are the size of a pointer
|
||||
t = Type::tvoidptr;
|
||||
}
|
||||
if (t->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)t;
|
||||
#if DMDV2
|
||||
if (ts->sym == ad)
|
||||
{
|
||||
ad->error("cannot have field %s with same struct type", toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope)
|
||||
ts->sym->semantic(NULL);
|
||||
if (ts->sym->sizeok != SIZEOKdone)
|
||||
{
|
||||
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (t->ty == Tident)
|
||||
{
|
||||
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned memsize = t->size(loc); // size of member
|
||||
unsigned memalignsize = t->alignsize(); // size of member for alignment purposes
|
||||
unsigned memalign = t->memalign(alignment); // alignment boundaries
|
||||
|
||||
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign,
|
||||
&ad->structsize, &ad->alignsize, isunion);
|
||||
|
||||
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
|
||||
|
||||
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize);
|
||||
ad->fields.push(this);
|
||||
}
|
||||
|
||||
const char *VarDeclaration::kind()
|
||||
{
|
||||
return "variable";
|
||||
|
||||
@@ -279,6 +279,7 @@ struct VarDeclaration : Declaration
|
||||
#else
|
||||
int nestedref; // referenced by a lexically nested function
|
||||
#endif
|
||||
unsigned short alignment;
|
||||
int ctorinit; // it has been initialized in a ctor
|
||||
int onstack; // 1: it has been allocated on the stack
|
||||
// 2: on stack, run destructor anyway
|
||||
@@ -305,6 +306,7 @@ struct VarDeclaration : Declaration
|
||||
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
void semantic2(Scope *sc);
|
||||
const char *kind();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -795,6 +797,7 @@ struct FuncDeclaration : Declaration
|
||||
int isAbstract();
|
||||
int isCodeseg();
|
||||
int isOverloadable();
|
||||
int hasOverloads();
|
||||
int isPure();
|
||||
int isSafe();
|
||||
int isTrusted();
|
||||
|
||||
@@ -261,6 +261,9 @@ void Module::gendocfile()
|
||||
Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
|
||||
}
|
||||
|
||||
char *srcfilename = srcfile->toChars();
|
||||
Macro::define(¯otable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
|
||||
|
||||
char *docfilename = docfile->toChars();
|
||||
Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -50,6 +50,7 @@ Dsymbol::Dsymbol()
|
||||
this->loc = 0;
|
||||
this->comment = NULL;
|
||||
this->scope = NULL;
|
||||
this->errors = false;
|
||||
#if IN_LLVM
|
||||
this->llvmInternal = LLVMnone;
|
||||
this->irsym = NULL;
|
||||
@@ -69,6 +70,7 @@ Dsymbol::Dsymbol(Identifier *ident)
|
||||
this->loc = 0;
|
||||
this->comment = NULL;
|
||||
this->scope = NULL;
|
||||
this->errors = false;
|
||||
#if IN_LLVM
|
||||
this->llvmInternal = LLVMnone;
|
||||
this->irsym = NULL;
|
||||
@@ -169,6 +171,10 @@ bool Dsymbol::hasStaticCtorOrDtor()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||
{
|
||||
}
|
||||
|
||||
char *Dsymbol::toChars()
|
||||
{
|
||||
return ident ? ident->toChars() : (char *)"__anonymous";
|
||||
@@ -283,6 +289,23 @@ TemplateInstance *Dsymbol::inTemplateInstance()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if this function is a member of a template which has only been
|
||||
// instantiated speculatively, eg from inside is(typeof()).
|
||||
// Return the speculative template instance it is part of,
|
||||
// or NULL if not speculative.
|
||||
TemplateInstance *Dsymbol::isSpeculative()
|
||||
{
|
||||
Dsymbol * par = parent;
|
||||
while (par)
|
||||
{
|
||||
TemplateInstance *ti = par->isTemplateInstance();
|
||||
if (ti && ti->speculative)
|
||||
return ti;
|
||||
par = par->toParent();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Dsymbol::isAnonymous()
|
||||
{
|
||||
return ident ? 0 : 1;
|
||||
@@ -367,11 +390,21 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
|
||||
void *symbol_search_fp(void *arg, const char *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);
|
||||
|
||||
Dsymbol *s = (Dsymbol *)arg;
|
||||
Identifier id(seed, 0);
|
||||
Module::clearCache();
|
||||
s = s->search(0, &id, 4|2);
|
||||
return s;
|
||||
return s->search(0, id, 4|2);
|
||||
}
|
||||
|
||||
Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
||||
@@ -409,7 +442,13 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
|
||||
id = ti->name;
|
||||
sm = s->search(loc, id, 0);
|
||||
if (!sm)
|
||||
{ error("template identifier %s is not a member of %s %s",
|
||||
{
|
||||
sm = s->search_correct(id);
|
||||
if (sm)
|
||||
error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
|
||||
id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
|
||||
else
|
||||
error("template identifier '%s' is not a member of '%s %s'",
|
||||
id->toChars(), s->kind(), s->toChars());
|
||||
return NULL;
|
||||
}
|
||||
@@ -495,6 +534,11 @@ int Dsymbol::isOverloadable()
|
||||
}
|
||||
#endif
|
||||
|
||||
int Dsymbol::hasOverloads()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
|
||||
{
|
||||
return NULL;
|
||||
@@ -518,6 +562,11 @@ int Dsymbol::needThis()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||
{
|
||||
return (*fp)(this, param);
|
||||
}
|
||||
|
||||
int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
//printf("Dsymbol::addMember('%s')\n", toChars());
|
||||
@@ -634,19 +683,16 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
|
||||
|
||||
Module *Dsymbol::getModule()
|
||||
{
|
||||
Module *m;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("Dsymbol::getModule()\n");
|
||||
TemplateDeclaration *td = getFuncTemplateDecl(this);
|
||||
if (td)
|
||||
return td->getModule();
|
||||
|
||||
s = this;
|
||||
Dsymbol *s = this;
|
||||
while (s)
|
||||
{
|
||||
//printf("\ts = '%s'\n", s->toChars());
|
||||
m = s->isModule();
|
||||
//printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
|
||||
Module *m = s->isModule();
|
||||
if (m)
|
||||
return m;
|
||||
s = s->parent;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -128,6 +128,8 @@ enum PASS
|
||||
PASSobj, // toObjFile() run
|
||||
};
|
||||
|
||||
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
|
||||
|
||||
struct Dsymbol : Object
|
||||
{
|
||||
Identifier *ident;
|
||||
@@ -140,6 +142,7 @@ struct Dsymbol : Object
|
||||
unsigned char *comment; // documentation comment for this Dsymbol
|
||||
Loc loc; // where defined
|
||||
Scope *scope; // !=NULL means context to use for semantic()
|
||||
bool errors; // this symbol failed to pass semantic()
|
||||
|
||||
Dsymbol();
|
||||
Dsymbol(Identifier *);
|
||||
@@ -157,6 +160,7 @@ struct Dsymbol : Object
|
||||
Dsymbol *toParent();
|
||||
Dsymbol *toParent2();
|
||||
TemplateInstance *inTemplateInstance();
|
||||
TemplateInstance *isSpeculative();
|
||||
|
||||
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
||||
|
||||
@@ -165,6 +169,7 @@ struct Dsymbol : Object
|
||||
virtual const char *toPrettyChars();
|
||||
virtual const char *kind();
|
||||
virtual Dsymbol *toAlias(); // resolve real symbol
|
||||
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
virtual void setScope(Scope *sc);
|
||||
virtual void importAll(Scope *sc);
|
||||
@@ -193,6 +198,7 @@ struct Dsymbol : Object
|
||||
#if DMDV2
|
||||
virtual int isOverloadable();
|
||||
#endif
|
||||
virtual int hasOverloads();
|
||||
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?
|
||||
@@ -202,6 +208,7 @@ struct Dsymbol : Object
|
||||
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
virtual int oneMember(Dsymbol **ps);
|
||||
static int oneMembers(Dsymbols *members, Dsymbol **ps);
|
||||
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
virtual int hasPointers();
|
||||
virtual bool hasStaticCtorOrDtor();
|
||||
virtual void addLocalClass(ClassDeclarations *) { }
|
||||
|
||||
316
dmd/expression.c
316
dmd/expression.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -345,10 +345,10 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
||||
*/
|
||||
Type *t0 = NULL;
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (Expression *)exps->data[i];
|
||||
{ Expression *e = (*exps)[i];
|
||||
|
||||
if (!e->type)
|
||||
{ error("%s has no value", e->toChars());
|
||||
{ error(e->loc, "%s has no value", e->toChars());
|
||||
e = new ErrorExp();
|
||||
}
|
||||
e = resolveProperties(sc, e);
|
||||
@@ -357,7 +357,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
||||
t0 = e->type;
|
||||
else
|
||||
e = e->implicitCastTo(sc, t0);
|
||||
exps->data[i] = (void *)e;
|
||||
(*exps)[i] = e;
|
||||
}
|
||||
|
||||
if (!t0)
|
||||
@@ -384,11 +384,11 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
||||
Expression *e0;
|
||||
int j0;
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (Expression *)exps->data[i];
|
||||
{ Expression *e = (*exps)[i];
|
||||
|
||||
e = resolveProperties(sc, e);
|
||||
if (!e->type)
|
||||
{ error("%s has no value", e->toChars());
|
||||
{ e->error("%s has no value", e->toChars());
|
||||
e = new ErrorExp();
|
||||
}
|
||||
|
||||
@@ -401,8 +401,9 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
||||
condexp.type = NULL;
|
||||
condexp.e1 = e0;
|
||||
condexp.e2 = e;
|
||||
condexp.loc = e->loc;
|
||||
condexp.semantic(sc);
|
||||
exps->data[j0] = (void *)condexp.e1;
|
||||
(*exps)[j0] = condexp.e1;
|
||||
e = condexp.e2;
|
||||
j0 = i;
|
||||
e0 = e;
|
||||
@@ -414,15 +415,15 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
||||
e0 = e;
|
||||
t0 = e->type;
|
||||
}
|
||||
exps->data[i] = (void *)e;
|
||||
(*exps)[i] = e;
|
||||
}
|
||||
|
||||
if (t0)
|
||||
{
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (Expression *)exps->data[i];
|
||||
{ Expression *e = (*exps)[i];
|
||||
e = e->implicitCastTo(sc, t0);
|
||||
exps->data[i] = (void *)e;
|
||||
(*exps)[i] = e;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -525,23 +526,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check if this function is a member of a template which has only been
|
||||
// instantiated speculatively, eg from inside is(typeof()).
|
||||
// Return the speculative template instance it is part of,
|
||||
// or NULL if not speculative.
|
||||
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd)
|
||||
{
|
||||
Dsymbol * par = fd->parent;
|
||||
while (par)
|
||||
{
|
||||
TemplateInstance *ti = par->isTemplateInstance();
|
||||
if (ti && ti->speculative)
|
||||
return ti;
|
||||
par = par->toParent();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Now that we know the exact type of the function we're calling,
|
||||
* the arguments[] need to be adjusted:
|
||||
@@ -565,7 +549,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
// If inferring return type, and semantic3() needs to be run if not already run
|
||||
if (!tf->next && fd->inferRetType)
|
||||
{
|
||||
TemplateInstance *spec = isSpeculativeFunction(fd);
|
||||
TemplateInstance *spec = fd->isSpeculative();
|
||||
int olderrs = global.errors;
|
||||
fd->semantic3(fd->scope);
|
||||
// Update the template instantiation with the number
|
||||
@@ -583,10 +567,9 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
Expression *arg;
|
||||
|
||||
if (i < nargs)
|
||||
arg = (Expression *)arguments->data[i];
|
||||
arg = (*arguments)[i];
|
||||
else
|
||||
arg = NULL;
|
||||
Type *tb;
|
||||
|
||||
if (i < nparams)
|
||||
{
|
||||
@@ -613,12 +596,13 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
if (tf->varargs == 2 && i + 1 == nparams)
|
||||
{
|
||||
//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
|
||||
if (arg->implicitConvTo(p->type))
|
||||
MATCH m;
|
||||
if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch)
|
||||
{
|
||||
if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()))
|
||||
if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
|
||||
goto L2;
|
||||
else if (nargs != nparams)
|
||||
{ error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
|
||||
{ error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
|
||||
return;
|
||||
}
|
||||
goto L1;
|
||||
@@ -661,9 +645,6 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
Expression *e = new VarExp(loc, v);
|
||||
e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
|
||||
AssignExp *ae = new AssignExp(loc, e, a);
|
||||
#if DMDV2
|
||||
ae->op = TOKconstruct;
|
||||
#endif
|
||||
if (c)
|
||||
c = new CommaExp(loc, c, ae);
|
||||
else
|
||||
@@ -723,7 +704,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
// LDC we don't want this!
|
||||
#if !IN_LLVM
|
||||
// Convert static arrays to pointers
|
||||
tb = arg->type->toBasetype();
|
||||
Type *tb = arg->type->toBasetype();
|
||||
if (tb->ty == Tsarray)
|
||||
{
|
||||
arg = arg->checkToPointer();
|
||||
@@ -732,7 +713,19 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
||||
{
|
||||
arg = callCpCtor(loc, sc, arg);
|
||||
if (arg->op == TOKcall)
|
||||
{
|
||||
/* The struct value returned from the function is transferred
|
||||
* to the function, so the callee should not call the destructor
|
||||
* on it.
|
||||
*/
|
||||
valueNoDtor(arg);
|
||||
}
|
||||
else
|
||||
{ /* Not transferring it, so call the copy constructor
|
||||
*/
|
||||
arg = callCpCtor(loc, sc, arg, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -801,7 +794,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
}
|
||||
|
||||
// Convert static arrays to dynamic arrays
|
||||
tb = arg->type->toBasetype();
|
||||
// BUG: I don't think this is right for D2
|
||||
Type *tb = arg->type->toBasetype();
|
||||
if (tb->ty == Tsarray)
|
||||
{ TypeSArray *ts = (TypeSArray *)tb;
|
||||
Type *ta = ts->next->arrayOf();
|
||||
@@ -2222,6 +2216,7 @@ Lagain:
|
||||
if (em)
|
||||
{
|
||||
e = em->value->copy();
|
||||
e->loc = loc;
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -2234,8 +2229,8 @@ Lagain:
|
||||
v->semantic(v->scope);
|
||||
type = v->type;
|
||||
if (!v->type)
|
||||
{ error("forward reference of %s", v->toChars());
|
||||
type = Type::terror;
|
||||
{ error("forward reference of %s %s", v->kind(), v->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
}
|
||||
if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray)
|
||||
@@ -2245,8 +2240,7 @@ Lagain:
|
||||
if (v->inuse)
|
||||
{
|
||||
error("circular reference to '%s'", v->toChars());
|
||||
type = Type::tint32;
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
ExpInitializer *ei = v->init->isExpInitializer();
|
||||
if (ei)
|
||||
@@ -2282,13 +2276,19 @@ Lagain:
|
||||
{ //printf("'%s' is a function\n", f->toChars());
|
||||
|
||||
if (!f->originalType && f->scope) // semantic not yet run
|
||||
{
|
||||
unsigned oldgag = global.gag;
|
||||
if (global.isSpeculativeGagging() && !f->isSpeculative())
|
||||
global.gag = 0;
|
||||
f->semantic(f->scope);
|
||||
global.gag = oldgag;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
// if inferring return type, sematic3 needs to be run
|
||||
if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
|
||||
{
|
||||
TemplateInstance *spec = isSpeculativeFunction(f);
|
||||
TemplateInstance *spec = f->isSpeculative();
|
||||
int olderrs = global.errors;
|
||||
f->semantic3(f->scope);
|
||||
// Update the template instantiation with the number
|
||||
@@ -2362,10 +2362,10 @@ Lagain:
|
||||
}
|
||||
|
||||
TemplateInstance *ti = s->isTemplateInstance();
|
||||
if (ti && !global.errors)
|
||||
if (ti)
|
||||
{ if (!ti->semanticRun)
|
||||
ti->semantic(sc);
|
||||
s = ti->inst->toAlias();
|
||||
s = ti->toAlias();
|
||||
if (!s->isTemplateInstance())
|
||||
goto Lagain;
|
||||
e = new ScopeExp(loc, ti);
|
||||
@@ -3224,6 +3224,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
|
||||
printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
|
||||
#endif
|
||||
|
||||
if (type)
|
||||
return this;
|
||||
|
||||
// Run semantic() on each element
|
||||
arrayExpressionSemantic(keys, sc);
|
||||
arrayExpressionSemantic(values, sc);
|
||||
@@ -3232,8 +3235,7 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
|
||||
if (keys->dim != values->dim)
|
||||
{
|
||||
error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
|
||||
keys->setDim(0);
|
||||
values->setDim(0);
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
Type *tkey = NULL;
|
||||
@@ -3241,6 +3243,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
|
||||
keys = arrayExpressionToCommonType(sc, keys, &tkey);
|
||||
values = arrayExpressionToCommonType(sc, values, &tvalue);
|
||||
|
||||
if (tkey == Type::terror || tvalue == Type::terror)
|
||||
return new ErrorExp;
|
||||
|
||||
type = new TypeAArray(tvalue, tkey);
|
||||
type = type->semantic(loc, sc);
|
||||
return this;
|
||||
@@ -3629,8 +3634,9 @@ Expression *ScopeExp::semantic(Scope *sc)
|
||||
#endif
|
||||
Lagain:
|
||||
ti = sds->isTemplateInstance();
|
||||
if (ti && !global.errors)
|
||||
if (ti && !ti->errors)
|
||||
{
|
||||
unsigned olderrs = global.errors;
|
||||
if (!ti->semanticRun)
|
||||
ti->semantic(sc);
|
||||
if (ti->inst)
|
||||
@@ -3660,7 +3666,7 @@ Lagain:
|
||||
}
|
||||
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
|
||||
}
|
||||
if (global.errors)
|
||||
if (olderrs != global.errors)
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
@@ -5471,6 +5477,32 @@ void BinExp::incompatibleTypes()
|
||||
|
||||
/************************************************************/
|
||||
|
||||
Expression *BinAssignExp::semantic(Scope *sc)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("BinAssignExp::semantic()\n");
|
||||
if (type)
|
||||
return this;
|
||||
BinExp::semantic(sc);
|
||||
e2 = resolveProperties(sc, e2);
|
||||
|
||||
e = op_overload(sc);
|
||||
if (e)
|
||||
return e;
|
||||
|
||||
e1 = e1->modifiableLvalue(sc, e1);
|
||||
e1->checkScalar();
|
||||
e1->checkNoBool();
|
||||
type = e1->type;
|
||||
typeCombine(sc);
|
||||
e1->checkIntegral();
|
||||
e2 = e2->checkIntegral();
|
||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
||||
return this;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
CompileExp::CompileExp(Loc loc, Expression *e)
|
||||
: UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
|
||||
{
|
||||
@@ -5921,7 +5953,9 @@ Expression *DotIdExp::semantic(Scope *sc)
|
||||
if (tup)
|
||||
{
|
||||
if (eleft)
|
||||
error("cannot have e.tuple");
|
||||
{ error("cannot have e.tuple");
|
||||
return new ErrorExp();
|
||||
}
|
||||
e = new TupleExp(loc, tup);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
@@ -5959,7 +5993,12 @@ Expression *DotIdExp::semantic(Scope *sc)
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
error("undefined identifier %s", toChars());
|
||||
s = ie->sds->search_correct(ident);
|
||||
if (s)
|
||||
error("undefined identifier '%s', did you mean '%s %s'?",
|
||||
ident->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error("undefined identifier '%s'", ident->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
else if (e1->type->ty == Tpointer &&
|
||||
@@ -6239,8 +6278,8 @@ L1:
|
||||
return e;
|
||||
if (e->op == TOKdottd)
|
||||
{
|
||||
if (global.errors)
|
||||
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
|
||||
if (ti->errors)
|
||||
return new ErrorExp();
|
||||
DotTemplateExp *dte = (DotTemplateExp *)e;
|
||||
TemplateDeclaration *td = dte->td;
|
||||
eleft = dte->e1;
|
||||
@@ -6248,8 +6287,8 @@ L1:
|
||||
#if DMDV2
|
||||
if (ti->needsTypeInference(sc))
|
||||
{
|
||||
e = new CallExp(loc, this);
|
||||
return e->semantic(sc);
|
||||
e1 = eleft; // save result of semantic()
|
||||
return this;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -6451,6 +6490,7 @@ DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f)
|
||||
: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
|
||||
{
|
||||
this->func = f;
|
||||
this->hasOverloads = 0;
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
@@ -6828,6 +6868,17 @@ Lagain:
|
||||
arrayExpressionSemantic(arguments, sc);
|
||||
preFunctionParameters(loc, sc, arguments);
|
||||
|
||||
// If there was an error processing any template argument,
|
||||
// return an error without trying to resolve the template.
|
||||
if (targsi && targsi->dim)
|
||||
{
|
||||
for (size_t k = 0; k < targsi->dim; k++)
|
||||
{ Object *o = targsi->tdata()[k];
|
||||
if (isError(o))
|
||||
return new ErrorExp();
|
||||
}
|
||||
}
|
||||
|
||||
if (e1->op == TOKdotvar && t1->ty == Tfunction ||
|
||||
e1->op == TOKdottd)
|
||||
{
|
||||
@@ -7336,11 +7387,24 @@ Expression *AddrExp::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
if (f && f->isNested())
|
||||
if (f)
|
||||
{
|
||||
Expression *e = new DelegateExp(loc, e1, f);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
if (f->isNested())
|
||||
{
|
||||
if (f->isFuncLiteralDeclaration())
|
||||
{
|
||||
if (!f->FuncDeclaration::isNested())
|
||||
{ /* Supply a 'null' for a this pointer if no this is available
|
||||
*/
|
||||
Expression *e = new DelegateExp(loc, new NullExp(loc, Type::tvoidptr), f);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
Expression *e = new DelegateExp(loc, e1, f);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e1->op == TOKarray)
|
||||
@@ -8554,10 +8618,11 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
if (e1->op == TOKarray)
|
||||
{
|
||||
ArrayExp *ae = (ArrayExp *)e1;
|
||||
AggregateDeclaration *ad;
|
||||
AggregateDeclaration *ad = NULL;
|
||||
Identifier *id = Id::index;
|
||||
|
||||
ae->e1 = ae->e1->semantic(sc);
|
||||
ae->e1 = resolveProperties(sc, ae->e1);
|
||||
Type *t1 = ae->e1->type->toBasetype();
|
||||
if (t1->ty == Tstruct)
|
||||
{
|
||||
@@ -8585,7 +8650,9 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
{ Expression *e = new DotIdExp(loc, ae->e1, id);
|
||||
|
||||
if (1 || !global.params.useDeprecated)
|
||||
error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
|
||||
{ error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
|
||||
e = e->semantic(sc);
|
||||
@@ -8601,7 +8668,7 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
if (e1->op == TOKslice)
|
||||
{ Type *t1;
|
||||
SliceExp *ae = (SliceExp *)e1;
|
||||
AggregateDeclaration *ad;
|
||||
AggregateDeclaration *ad = NULL;
|
||||
Identifier *id = Id::index;
|
||||
|
||||
ae->e1 = ae->e1->semantic(sc);
|
||||
@@ -8697,8 +8764,9 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
* check for operator overloading.
|
||||
*/
|
||||
if (t1->ty == Tclass || t1->ty == Tstruct)
|
||||
{
|
||||
if (!e2->type->implicitConvTo(e1->type))
|
||||
{ // Disallow assignment operator overloads for same type
|
||||
if (/*op == TOKassign &&*/ // construction shouldn't be allowed, but OK to avoid breaking existing code
|
||||
!e2->implicitConvTo(e1->type))
|
||||
{
|
||||
Expression *e = op_overload(sc);
|
||||
if (e)
|
||||
@@ -8725,8 +8793,16 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
e1 = e1->modifiableLvalue(sc, e1old);
|
||||
}
|
||||
|
||||
// If it is a array, get the element type. Note that it may be
|
||||
// multi-dimensional.
|
||||
Type *telem = t1;
|
||||
while (telem->ty == Tarray)
|
||||
telem = telem->nextOf();
|
||||
|
||||
// Check for block assignment. If it is of type void[], void[][], etc,
|
||||
// '= null' is the only allowable block assignment (Bug 7493)
|
||||
if (e1->op == TOKslice &&
|
||||
t1->nextOf() &&
|
||||
t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) &&
|
||||
e2->implicitConvTo(t1->nextOf())
|
||||
// !(t1->nextOf()->equals(e2->type->nextOf()))
|
||||
)
|
||||
@@ -8792,7 +8868,7 @@ ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
|
||||
/************************************************************/
|
||||
|
||||
AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8903,7 +8979,7 @@ Expression *AddAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8957,7 +9033,7 @@ Expression *MinAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8981,6 +9057,8 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
e1 = e1->modifiableLvalue(sc, e1);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
|
||||
Type *tb1 = e1->type->toBasetype();
|
||||
Type *tb2 = e2->type->toBasetype();
|
||||
@@ -9039,13 +9117,15 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *MulAssignExp::semantic(Scope *sc)
|
||||
{ Expression *e;
|
||||
|
||||
if (type)
|
||||
return this;
|
||||
BinExp::semantic(sc);
|
||||
e2 = resolveProperties(sc, e2);
|
||||
|
||||
@@ -9117,13 +9197,15 @@ Expression *MulAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *DivAssignExp::semantic(Scope *sc)
|
||||
{ Expression *e;
|
||||
|
||||
if (type)
|
||||
return this;
|
||||
BinExp::semantic(sc);
|
||||
e2 = resolveProperties(sc, e2);
|
||||
|
||||
@@ -9198,12 +9280,14 @@ Expression *DivAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *ModAssignExp::semantic(Scope *sc)
|
||||
{
|
||||
if (type)
|
||||
return this;
|
||||
BinExp::semantic(sc);
|
||||
checkComplexMulAssign();
|
||||
return commonSemanticAssign(sc);
|
||||
@@ -9212,104 +9296,28 @@ Expression *ModAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *ShlAssignExp::semantic(Scope *sc)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("ShlAssignExp::semantic()\n");
|
||||
BinExp::semantic(sc);
|
||||
e2 = resolveProperties(sc, e2);
|
||||
|
||||
e = op_overload(sc);
|
||||
if (e)
|
||||
return e;
|
||||
|
||||
e1 = e1->modifiableLvalue(sc, e1);
|
||||
e1->checkScalar();
|
||||
e1->checkNoBool();
|
||||
type = e1->type;
|
||||
typeCombine(sc);
|
||||
e1->checkIntegral();
|
||||
e2 = e2->checkIntegral();
|
||||
#if !IN_LLVM
|
||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
||||
#else
|
||||
e2 = e2->castTo(sc, e1->type);
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *ShrAssignExp::semantic(Scope *sc)
|
||||
{ Expression *e;
|
||||
|
||||
BinExp::semantic(sc);
|
||||
e2 = resolveProperties(sc, e2);
|
||||
|
||||
e = op_overload(sc);
|
||||
if (e)
|
||||
return e;
|
||||
|
||||
e1 = e1->modifiableLvalue(sc, e1);
|
||||
e1->checkScalar();
|
||||
e1->checkNoBool();
|
||||
type = e1->type;
|
||||
typeCombine(sc);
|
||||
e1->checkIntegral();
|
||||
e2 = e2->checkIntegral();
|
||||
#if !IN_LLVM
|
||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
||||
#else
|
||||
e2 = e2->castTo(sc, e1->type);
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *UshrAssignExp::semantic(Scope *sc)
|
||||
{ Expression *e;
|
||||
|
||||
BinExp::semantic(sc);
|
||||
e2 = resolveProperties(sc, e2);
|
||||
|
||||
e = op_overload(sc);
|
||||
if (e)
|
||||
return e;
|
||||
|
||||
e1 = e1->modifiableLvalue(sc, e1);
|
||||
e1->checkScalar();
|
||||
e1->checkNoBool();
|
||||
type = e1->type;
|
||||
typeCombine(sc);
|
||||
e1->checkIntegral();
|
||||
e2 = e2->checkIntegral();
|
||||
#if !IN_LLVM
|
||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
||||
#else
|
||||
e2 = e2->castTo(sc, e1->type);
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9321,7 +9329,7 @@ Expression *AndAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9333,7 +9341,7 @@ Expression *OrAssignExp::semantic(Scope *sc)
|
||||
/************************************************************/
|
||||
|
||||
XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
|
||||
: BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -932,8 +932,12 @@ struct BinExp : Expression
|
||||
|
||||
struct BinAssignExp : BinExp
|
||||
{
|
||||
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
|
||||
int checkSideEffect(int flag);
|
||||
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, op, size, e1, e2)
|
||||
{
|
||||
}
|
||||
|
||||
Expression *semantic(Scope *sc);
|
||||
};
|
||||
|
||||
/****************************************************************/
|
||||
@@ -1031,6 +1035,7 @@ struct DelegateExp : UnaExp
|
||||
{
|
||||
FuncDeclaration *func;
|
||||
Module* m; // starting point for overload resolution
|
||||
int hasOverloads;
|
||||
|
||||
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
|
||||
Expression *semantic(Scope *sc);
|
||||
@@ -1446,10 +1451,10 @@ struct ConstructExp : AssignExp
|
||||
#endif
|
||||
|
||||
#define ASSIGNEXP(op) \
|
||||
struct op##AssignExp : BinExp \
|
||||
struct op##AssignExp : BinAssignExp \
|
||||
{ \
|
||||
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
|
||||
Expression *semantic(Scope *sc); \
|
||||
S(Expression *semantic(Scope *sc);) \
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
|
||||
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
|
||||
X(Expression *buildArrayLoop(Parameters *fparams);) \
|
||||
@@ -1460,6 +1465,7 @@ struct op##AssignExp : BinExp \
|
||||
};
|
||||
|
||||
#define X(a) a
|
||||
#define S(a) a
|
||||
ASSIGNEXP(Add)
|
||||
ASSIGNEXP(Min)
|
||||
ASSIGNEXP(Mul)
|
||||
@@ -1468,15 +1474,28 @@ ASSIGNEXP(Mod)
|
||||
ASSIGNEXP(And)
|
||||
ASSIGNEXP(Or)
|
||||
ASSIGNEXP(Xor)
|
||||
#undef S
|
||||
|
||||
#if DMDV2
|
||||
#define S(a) a
|
||||
ASSIGNEXP(Pow)
|
||||
#undef S
|
||||
#endif
|
||||
|
||||
#undef X
|
||||
|
||||
#define X(a)
|
||||
#define S(a)
|
||||
|
||||
ASSIGNEXP(Shl)
|
||||
ASSIGNEXP(Shr)
|
||||
ASSIGNEXP(Ushr)
|
||||
#undef S
|
||||
|
||||
#define S(a) a
|
||||
ASSIGNEXP(Cat)
|
||||
|
||||
#undef S
|
||||
#undef X
|
||||
#undef ASSIGNEXP
|
||||
#undef ASSIGNEXP_TOELEM
|
||||
|
||||
38
dmd/func.c
38
dmd/func.c
@@ -1,5 +1,5 @@
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -306,7 +306,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
(pd = toParent2()) != NULL &&
|
||||
(id = pd->isInterfaceDeclaration()) != NULL)
|
||||
{
|
||||
error("template member function not allowed in interface %s", id->toChars());
|
||||
error("template member functions are not allowed in interface %s", id->toChars());
|
||||
}
|
||||
|
||||
cd = parent->isClassDeclaration();
|
||||
@@ -362,6 +362,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
//printf("\tnot virtual\n");
|
||||
goto Ldone;
|
||||
}
|
||||
// Suppress further errors if the return type is an error
|
||||
if (type->nextOf() == Type::terror)
|
||||
goto Ldone;
|
||||
|
||||
/* Find index of existing function in base class's vtbl[] to override
|
||||
* (the index will be the same as in cd's current vtbl[])
|
||||
@@ -407,7 +410,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
break;
|
||||
|
||||
case -2: // can't determine because of fwd refs
|
||||
cd->sizeok = 2; // can't finish due to forward reference
|
||||
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
|
||||
Module::dprogress = dprogress_save;
|
||||
return;
|
||||
|
||||
@@ -488,18 +491,26 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
break;
|
||||
|
||||
case -2:
|
||||
cd->sizeok = 2; // can't finish due to forward reference
|
||||
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
|
||||
Module::dprogress = dprogress_save;
|
||||
return;
|
||||
|
||||
default:
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi];
|
||||
Type *ti = NULL;
|
||||
|
||||
/* Remember which functions this overrides
|
||||
*/
|
||||
foverrides.push(fdv);
|
||||
|
||||
#if DMDV2
|
||||
/* Should we really require 'override' when implementing
|
||||
* an interface function?
|
||||
*/
|
||||
//if (!isOverride())
|
||||
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
|
||||
#endif
|
||||
|
||||
if (fdv->tintro)
|
||||
ti = fdv->tintro;
|
||||
else if (!type->equals(fdv->type))
|
||||
@@ -513,7 +524,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
if (global.endGagging(errors))
|
||||
{
|
||||
// any error in isBaseOf() is a forward reference error, so we bail out
|
||||
cd->sizeok = 2; // can't finish due to forward reference
|
||||
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
|
||||
Module::dprogress = dprogress_save;
|
||||
return;
|
||||
}
|
||||
@@ -524,10 +535,15 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
if (ti)
|
||||
{
|
||||
if (tintro && !tintro->equals(ti))
|
||||
if (tintro)
|
||||
{
|
||||
if (!tintro->nextOf()->equals(ti->nextOf()) &&
|
||||
!tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
|
||||
!ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
|
||||
{
|
||||
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
|
||||
}
|
||||
}
|
||||
tintro = ti;
|
||||
}
|
||||
goto L2;
|
||||
@@ -601,7 +617,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
if (f->varargs)
|
||||
{
|
||||
Lmainerr:
|
||||
error("parameters must be main() or main(char[][] args)");
|
||||
error("parameters must be main() or main(string[] args)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2508,6 +2524,10 @@ int FuncDeclaration::isCodeseg()
|
||||
return TRUE; // functions are always in the code segment
|
||||
}
|
||||
|
||||
int FuncDeclaration::hasOverloads()
|
||||
{
|
||||
return overnext != NULL;
|
||||
}
|
||||
// Determine if function needs
|
||||
// a static frame pointer to its lexically enclosing function
|
||||
|
||||
@@ -3175,7 +3195,7 @@ int StaticCtorDeclaration::addPostInvariant()
|
||||
|
||||
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (hgs->hdrgen)
|
||||
if (hgs->hdrgen && !hgs->tpltMember)
|
||||
{ buf->writestring("static this();");
|
||||
buf->writenl();
|
||||
return;
|
||||
|
||||
@@ -104,15 +104,15 @@ void Html::error(const char *format, ...)
|
||||
{
|
||||
if (!global.gag)
|
||||
{
|
||||
printf("%s(%d) : HTML Error: ", sourcename, linnum);
|
||||
fprintf(stderr, "%s(%d) : HTML Error: ", sourcename, linnum);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vprintf(format, ap);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
global.errors++;
|
||||
|
||||
26
dmd/import.c
26
dmd/import.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -79,7 +79,16 @@ void Import::load(Scope *sc)
|
||||
|
||||
// See if existing module
|
||||
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
|
||||
|
||||
#if TARGET_NET //dot net needs modules and packages with same name
|
||||
#else
|
||||
if (pkg && pkg->isModule())
|
||||
{
|
||||
::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
|
||||
pkg->toChars(), pkg->toPrettyChars(), id->toChars());
|
||||
mod = pkg->isModule(); // Error recovery - treat as import of that module
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Dsymbol *s = dst->lookup(id);
|
||||
if (s)
|
||||
{
|
||||
@@ -89,7 +98,8 @@ void Import::load(Scope *sc)
|
||||
if (s->isModule())
|
||||
mod = (Module *)s;
|
||||
else
|
||||
error("package and module have the same name");
|
||||
::error(loc, "can only import from a module, not from package %s.%s",
|
||||
pkg->toPrettyChars(), id->toChars());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -97,11 +107,14 @@ void Import::load(Scope *sc)
|
||||
{
|
||||
// Load module
|
||||
mod = Module::load(loc, packages, id);
|
||||
if (mod)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -151,7 +164,8 @@ void Import::semantic(Scope *sc)
|
||||
// Load if not already done so
|
||||
if (!mod)
|
||||
{ load(sc);
|
||||
mod->importAll(0);
|
||||
if (mod)
|
||||
mod->importAll(0);
|
||||
}
|
||||
|
||||
if (mod)
|
||||
@@ -200,7 +214,9 @@ void Import::semantic(Scope *sc)
|
||||
}
|
||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
|
||||
if (global.params.moduleDeps != NULL)
|
||||
if (global.params.moduleDeps != NULL &&
|
||||
// object self-imports itself, so skip that (Bugzilla 7547)
|
||||
!(id == Id::object && sc->module->ident == Id::object))
|
||||
{
|
||||
/* The grammar of the file is:
|
||||
* ImportDeclaration
|
||||
|
||||
74
dmd/init.c
74
dmd/init.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
|
||||
a = new Initializers();
|
||||
a->setDim(ai->dim);
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{ Initializer *e = (Initializer *)ai->data[i];
|
||||
{ Initializer *e = (*ai)[i];
|
||||
|
||||
e = e->syntaxCopy();
|
||||
a->data[i] = e;
|
||||
(*a)[i] = e;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
@@ -128,11 +128,11 @@ Initializer *StructInitializer::syntaxCopy()
|
||||
ai->value.setDim(value.dim);
|
||||
for (size_t i = 0; i < field.dim; i++)
|
||||
{
|
||||
ai->field.data[i] = field.data[i];
|
||||
ai->field[i] = field[i];
|
||||
|
||||
Initializer *init = (Initializer *)value.data[i];
|
||||
Initializer *init = value[i];
|
||||
init = init->syntaxCopy();
|
||||
ai->value.data[i] = init;
|
||||
ai->value[i] = init;
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
@@ -189,7 +189,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
s = ad->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
s = ad->search_correct(id);
|
||||
if (s)
|
||||
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
|
||||
id->toChars(), t->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
errors = 1;
|
||||
continue;
|
||||
}
|
||||
@@ -212,8 +217,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
if (s && (v = s->isVarDeclaration()) != NULL)
|
||||
{
|
||||
val = val->semantic(sc, v->type, needInterpret);
|
||||
value.data[i] = (void *)val;
|
||||
vars.data[i] = (void *)v;
|
||||
value[i] = val;
|
||||
vars[i] = v;
|
||||
}
|
||||
else
|
||||
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
|
||||
@@ -273,7 +278,7 @@ Expression *StructInitializer::toExpression()
|
||||
elements->setDim(nfields);
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{
|
||||
elements->data[i] = NULL;
|
||||
(*elements)[i] = NULL;
|
||||
}
|
||||
unsigned fieldi = 0;
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
@@ -305,37 +310,37 @@ Expression *StructInitializer::toExpression()
|
||||
{ error(loc, "too many initializers for '%s'", ad->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
Initializer *iz = value[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
Expression *ex = iz->toExpression();
|
||||
if (!ex)
|
||||
goto Lno;
|
||||
if (elements->data[fieldi])
|
||||
if ((*elements)[fieldi])
|
||||
{ error(loc, "duplicate initializer for field '%s'",
|
||||
((Dsymbol *)ad->fields.data[fieldi])->toChars());
|
||||
ad->fields[fieldi]->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
elements->data[fieldi] = ex;
|
||||
(*elements)[fieldi] = ex;
|
||||
++fieldi;
|
||||
}
|
||||
// Now, fill in any missing elements with default initializers.
|
||||
// We also need to validate any anonymous unions
|
||||
for (size_t i = 0; i < elements->dim; )
|
||||
{
|
||||
VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration();
|
||||
VarDeclaration * vd = ad->fields[i]->isVarDeclaration();
|
||||
int unionSize = ad->numFieldsInUnion(i);
|
||||
if (unionSize == 1)
|
||||
{ // Not a union -- default initialize if missing
|
||||
if (!elements->data[i])
|
||||
elements->data[i] = vd->type->defaultInit();
|
||||
if (!(*elements)[i])
|
||||
(*elements)[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)
|
||||
for (size_t j = i; j < i + unionSize; ++j)
|
||||
{
|
||||
if (!elements->data[j])
|
||||
if (!(*elements)[j])
|
||||
continue;
|
||||
if (found >= 0)
|
||||
{
|
||||
@@ -375,13 +380,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (i > 0)
|
||||
buf->writebyte(',');
|
||||
Identifier *id = (Identifier *)field.data[i];
|
||||
Identifier *id = field[i];
|
||||
if (id)
|
||||
{
|
||||
buf->writestring(id->toChars());
|
||||
buf->writebyte(':');
|
||||
}
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
Initializer *iz = value[i];
|
||||
if (iz)
|
||||
iz->toCBuffer(buf, hgs);
|
||||
}
|
||||
@@ -408,14 +413,14 @@ Initializer *ArrayInitializer::syntaxCopy()
|
||||
ai->index.setDim(index.dim);
|
||||
ai->value.setDim(value.dim);
|
||||
for (size_t i = 0; i < ai->value.dim; i++)
|
||||
{ Expression *e = (Expression *)index.data[i];
|
||||
{ Expression *e = index[i];
|
||||
if (e)
|
||||
e = e->syntaxCopy();
|
||||
ai->index.data[i] = e;
|
||||
ai->index[i] = e;
|
||||
|
||||
Initializer *init = (Initializer *)value.data[i];
|
||||
Initializer *init = value[i];
|
||||
init = init->syntaxCopy();
|
||||
ai->value.data[i] = init;
|
||||
ai->value[i] = init;
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
@@ -532,7 +537,7 @@ Expression *ArrayInitializer::toExpression()
|
||||
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
||||
{
|
||||
if (index[i])
|
||||
j = (index[i])->toInteger();
|
||||
j = index[i]->toInteger();
|
||||
if (j >= edim)
|
||||
edim = j + 1;
|
||||
}
|
||||
@@ -584,6 +589,7 @@ Lno:
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
* If possible, convert array initializer to associative array initializer.
|
||||
*/
|
||||
@@ -601,18 +607,18 @@ Initializer *ArrayInitializer::toAssocArrayInitializer()
|
||||
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
{
|
||||
e = index.tdata()[i];
|
||||
e = index[i];
|
||||
if (!e)
|
||||
goto Lno;
|
||||
keys->tdata()[i] = e;
|
||||
(*keys)[i] = e;
|
||||
|
||||
Initializer *iz = value.tdata()[i];
|
||||
Initializer *iz = value[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
e = iz->toExpression();
|
||||
if (!e)
|
||||
goto Lno;
|
||||
values->tdata()[i] = e;
|
||||
(*values)[i] = e;
|
||||
}
|
||||
e = new AssocArrayLiteralExp(loc, keys, values);
|
||||
return new ExpInitializer(loc, e);
|
||||
@@ -668,13 +674,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (i > 0)
|
||||
buf->writebyte(',');
|
||||
Expression *ex = index.tdata()[i];
|
||||
Expression *ex = index[i];
|
||||
if (ex)
|
||||
{
|
||||
ex->toCBuffer(buf, hgs);
|
||||
buf->writebyte(':');
|
||||
}
|
||||
Initializer *iz = value.tdata()[i];
|
||||
Initializer *iz = value[i];
|
||||
if (iz)
|
||||
iz->toCBuffer(buf, hgs);
|
||||
}
|
||||
@@ -707,7 +713,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
return this; // Failed, suppress duplicate error messages
|
||||
|
||||
if (exp->op == TOKtype)
|
||||
error("initializer must be an expression, not '%s'", exp->toChars());
|
||||
exp->error("initializer must be an expression, not '%s'", exp->toChars());
|
||||
Type *tb = t->toBasetype();
|
||||
|
||||
/* Look for case of initializing a static array with a too-short
|
||||
@@ -767,7 +773,7 @@ Type *ExpInitializer::inferType(Scope *sc)
|
||||
// Give error for overloaded function addresses
|
||||
if (exp->op == TOKdelegate)
|
||||
{ DelegateExp *se = (DelegateExp *)exp;
|
||||
if (
|
||||
if (se->hasOverloads &&
|
||||
se->func->isFuncDeclaration() &&
|
||||
!se->func->isFuncDeclaration()->isUnique())
|
||||
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
|
||||
|
||||
22
dmd/inline.c
22
dmd/inline.c
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -196,6 +196,8 @@ int lambdaInlineCost(Expression *e, void *param)
|
||||
|
||||
int expressionInlineCost(Expression *e, InlineCostState *ics)
|
||||
{
|
||||
//printf("expressionInlineCost()\n");
|
||||
//e->dump(0);
|
||||
ICS2 ics2;
|
||||
ics2.cost = 0;
|
||||
ics2.ics = ics;
|
||||
@@ -340,6 +342,7 @@ struct InlineDoState
|
||||
Dsymbols from; // old Dsymbols
|
||||
Dsymbols to; // parallel array of new Dsymbols
|
||||
Dsymbol *parent; // new parent
|
||||
FuncDeclaration *fd; // function being inlined (old parent)
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -1486,6 +1489,9 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
|
||||
if (
|
||||
!fbody ||
|
||||
ident == Id::ensure || // ensure() has magic properties the inliner loses
|
||||
(ident == Id::require && // require() has magic properties too
|
||||
toParent()->isFuncDeclaration() && // see bug 7699
|
||||
toParent()->isFuncDeclaration()->needThis()) ||
|
||||
!hdrscan &&
|
||||
(
|
||||
#if 0
|
||||
@@ -1600,6 +1606,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
||||
|
||||
memset(&ids, 0, sizeof(ids));
|
||||
ids.parent = iss->fd;
|
||||
ids.fd = this;
|
||||
|
||||
if (ps)
|
||||
as = new Statements();
|
||||
@@ -1786,6 +1793,18 @@ Expression *Expression::inlineCopy(Scope *sc)
|
||||
*/
|
||||
return copy();
|
||||
#else
|
||||
if (op == TOKdelegate)
|
||||
{ DelegateExp *de = (DelegateExp *)this;
|
||||
|
||||
if (de->func->isNested())
|
||||
{ /* See Bugzilla 4820
|
||||
* Defer checking until later if we actually need the 'this' pointer
|
||||
*/
|
||||
Expression *e = de->copy();
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
InlineCostState ics;
|
||||
|
||||
memset(&ics, 0, sizeof(ics));
|
||||
@@ -1802,3 +1821,4 @@ Expression *Expression::inlineCopy(Scope *sc)
|
||||
return e;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
390
dmd/interpret.c
390
dmd/interpret.c
@@ -27,7 +27,6 @@
|
||||
#include "attrib.h" // for AttribDeclaration
|
||||
|
||||
#include "template.h"
|
||||
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd);
|
||||
|
||||
|
||||
#define LOG 0
|
||||
@@ -45,6 +44,10 @@ private:
|
||||
together with the VarDeclaration, and the previous
|
||||
stack address of that variable, so that we can restore it
|
||||
when we leave the stack frame.
|
||||
Note that when a function is forward referenced, the interpreter must
|
||||
run semantic3, and that may start CTFE again with a NULL istate. Thus
|
||||
the stack might not be empty when CTFE begins.
|
||||
|
||||
Ctfe Stack addresses are just 0-based integers, but we save
|
||||
them as 'void *' because ArrayBase can only do pointers.
|
||||
*/
|
||||
@@ -143,7 +146,11 @@ public:
|
||||
}
|
||||
void saveGlobalConstant(VarDeclaration *v, Expression *e)
|
||||
{
|
||||
assert(v->isDataseg() && !v->isCTFE());
|
||||
#if DMDV2
|
||||
assert( v->init && (v->isConst() || v->isImmutable()) && !v->isCTFE());
|
||||
#else
|
||||
assert( v->init && v->isConst() && !v->isCTFE());
|
||||
#endif
|
||||
v->ctfeAdrOnStack = globalValues.dim;
|
||||
globalValues.push(e);
|
||||
}
|
||||
@@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval);
|
||||
bool needToCopyLiteral(Expression *expr);
|
||||
Expression *copyLiteral(Expression *e);
|
||||
Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
|
||||
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2);
|
||||
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2);
|
||||
Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
|
||||
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
|
||||
Expression *scrubReturnValue(Loc loc, Expression *e);
|
||||
@@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression
|
||||
{
|
||||
return value->sd->isClassDeclaration();
|
||||
}
|
||||
VarDeclaration *getFieldAt(int index)
|
||||
{
|
||||
ClassDeclaration *cd = originalClass();
|
||||
size_t fieldsSoFar = 0;
|
||||
while (index - fieldsSoFar >= cd->fields.dim)
|
||||
{ fieldsSoFar += cd->fields.dim;
|
||||
cd = cd->baseClass;
|
||||
}
|
||||
return cd->fields.tdata()[index - fieldsSoFar];
|
||||
}
|
||||
// Return index of the field, or -1 if not found
|
||||
int getFieldIndex(Type *fieldtype, size_t fieldoffset)
|
||||
{
|
||||
@@ -283,6 +300,28 @@ struct ClassReferenceExp : Expression
|
||||
}
|
||||
};
|
||||
|
||||
struct VoidInitExp : Expression
|
||||
{
|
||||
VarDeclaration *var;
|
||||
|
||||
VoidInitExp(VarDeclaration *var, Type *type)
|
||||
: Expression(var->loc, TOKvoid, sizeof(VoidInitExp))
|
||||
{
|
||||
this->var = var;
|
||||
this->type = var->type;
|
||||
}
|
||||
char *toChars()
|
||||
{
|
||||
return (char *)"void";
|
||||
}
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue)
|
||||
{
|
||||
error("CTFE internal error: trying to read uninitialized variable");
|
||||
assert(0);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
};
|
||||
|
||||
// Return index of the field, or -1 if not found
|
||||
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
|
||||
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
|
||||
@@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0)
|
||||
* arguments function arguments
|
||||
* thisarg 'this', if a needThis() function, NULL if not.
|
||||
*
|
||||
* Return result expression if successful, EXP_CANT_INTERPRET if not.
|
||||
* Return result expression if successful, EXP_CANT_INTERPRET if not,
|
||||
* or EXP_VOID_INTERPRET if function returned void.
|
||||
*/
|
||||
|
||||
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
|
||||
@@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
*/
|
||||
int olderrors = global.errors;
|
||||
int oldgag = global.gag;
|
||||
TemplateInstance *spec = isSpeculativeFunction(this);
|
||||
TemplateInstance *spec = isSpeculative();
|
||||
if (global.gag && !spec)
|
||||
global.gag = 0;
|
||||
semantic3(scope);
|
||||
@@ -576,6 +616,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
--evaluatingArgs;
|
||||
if (earg == EXP_CANT_INTERPRET)
|
||||
return earg;
|
||||
/* Struct literals are passed by value, but we don't need to
|
||||
* copy them if they are passed as const
|
||||
*/
|
||||
if (earg->op == TOKstructliteral
|
||||
#if DMDV2
|
||||
&& !(arg->storageClass & (STCconst | STCimmutable))
|
||||
#endif
|
||||
)
|
||||
earg = copyLiteral(earg);
|
||||
}
|
||||
if (earg->op == TOKthrownexception)
|
||||
{
|
||||
@@ -675,6 +724,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
// If fell off the end of a void function, return void
|
||||
if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
|
||||
return EXP_VOID_INTERPRET;
|
||||
|
||||
// If result is void, return void
|
||||
if (e == EXP_VOID_INTERPRET)
|
||||
return e;
|
||||
|
||||
// If it generated an exception, return it
|
||||
if (exceptionOrCantInterpret(e))
|
||||
{
|
||||
@@ -683,6 +737,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
((ThrownExceptionExp *)e)->generateUncaughtError();
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
|
||||
// If we're about to leave CTFE, make sure we don't crash the
|
||||
// compiler by returning a CTFE-internal expression.
|
||||
if (!istate && !evaluatingArgs)
|
||||
{
|
||||
e = scrubReturnValue(loc, e);
|
||||
@@ -896,13 +953,16 @@ uinteger_t resolveArrayLength(Expression *e)
|
||||
}
|
||||
|
||||
// As Equal, but resolves slices before comparing
|
||||
Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
{
|
||||
if (e1->op == TOKslice)
|
||||
e1 = resolveSlice(e1);
|
||||
if (e2->op == TOKslice)
|
||||
e2 = resolveSlice(e2);
|
||||
return Equal(op, type, e1, e2);
|
||||
Expression *e = Equal(op, type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
error(loc, "cannot evaluate %s==%s at compile time", e1->toChars(), e2->toChars());
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
@@ -973,7 +1033,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
return Cat(type, e1, e2);
|
||||
}
|
||||
|
||||
void scrubArray(Loc loc, Expressions *elems);
|
||||
bool scrubArray(Loc loc, Expressions *elems, bool structlit = false);
|
||||
|
||||
/* All results destined for use outside of CTFE need to have their CTFE-specific
|
||||
* features removed.
|
||||
@@ -986,6 +1046,11 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
|
||||
error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if (e->op == TOKvoid)
|
||||
{
|
||||
error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
|
||||
e = new ErrorExp();
|
||||
}
|
||||
if (e->op == TOKslice)
|
||||
{
|
||||
e = resolveSlice(e);
|
||||
@@ -994,7 +1059,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
|
||||
{
|
||||
StructLiteralExp *se = (StructLiteralExp *)e;
|
||||
se->ownedByCtfe = false;
|
||||
scrubArray(loc, se->elements);
|
||||
if (!scrubArray(loc, se->elements, true))
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if (e->op == TOKstring)
|
||||
{
|
||||
@@ -1003,29 +1069,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
|
||||
if (e->op == TOKarrayliteral)
|
||||
{
|
||||
((ArrayLiteralExp *)e)->ownedByCtfe = false;
|
||||
scrubArray(loc, ((ArrayLiteralExp *)e)->elements);
|
||||
if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements))
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if (e->op == TOKassocarrayliteral)
|
||||
{
|
||||
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
|
||||
aae->ownedByCtfe = false;
|
||||
scrubArray(loc, aae->keys);
|
||||
scrubArray(loc, aae->values);
|
||||
if (!scrubArray(loc, aae->keys))
|
||||
return EXP_CANT_INTERPRET;
|
||||
if (!scrubArray(loc, aae->values))
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
// Scrub all members of an array
|
||||
void scrubArray(Loc loc, Expressions *elems)
|
||||
// Scrub all members of an array. Return false if error
|
||||
bool scrubArray(Loc loc, Expressions *elems, bool structlit)
|
||||
{
|
||||
for (size_t i = 0; i < elems->dim; i++)
|
||||
{
|
||||
Expression *m = elems->tdata()[i];
|
||||
if (!m)
|
||||
continue;
|
||||
m = scrubReturnValue(loc, m);
|
||||
if (m && m->op == TOKvoid && structlit)
|
||||
m = NULL;
|
||||
if (m)
|
||||
m = scrubReturnValue(loc, m);
|
||||
if (m == EXP_CANT_INTERPRET)
|
||||
return false;
|
||||
elems->tdata()[i] = m;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1360,7 +1435,7 @@ Expression *SwitchStatement::interpret(InterState *istate)
|
||||
Expression * caseExp = cs->exp->interpret(istate);
|
||||
if (exceptionOrCantInterpret(caseExp))
|
||||
return caseExp;
|
||||
e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp);
|
||||
e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp);
|
||||
if (exceptionOrCantInterpret(e))
|
||||
return e;
|
||||
if (e->isBool(TRUE))
|
||||
@@ -1475,25 +1550,25 @@ Expression *TryCatchStatement::interpret(InterState *istate)
|
||||
ThrownExceptionExp *ex = (ThrownExceptionExp *)e;
|
||||
Type *extype = ex->thrown->originalClass()->type;
|
||||
// Search for an appropriate catch clause.
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{
|
||||
#if DMDV1
|
||||
Catch *ca = (Catch *)catches->data[i];
|
||||
Catch *ca = (Catch *)catches->data[i];
|
||||
#else
|
||||
Catch *ca = catches->tdata()[i];
|
||||
Catch *ca = catches->tdata()[i];
|
||||
#endif
|
||||
Type *catype = ca->type;
|
||||
Type *catype = ca->type;
|
||||
|
||||
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
|
||||
{ // Execute the handler
|
||||
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
|
||||
{ // Execute the handler
|
||||
if (ca->var)
|
||||
{
|
||||
ctfeStack.push(ca->var);
|
||||
ca->var->setValue(ex->thrown);
|
||||
}
|
||||
return ca->handler->interpret(istate);
|
||||
}
|
||||
return ca->handler ? ca->handler->interpret(istate) : NULL;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -1734,6 +1809,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
}
|
||||
Type *pointee = ((TypePointer *)type)->next;
|
||||
Expression *val = getVarExp(loc, istate, var, goal);
|
||||
if (val == EXP_CANT_INTERPRET)
|
||||
return val;
|
||||
if (val->type->ty == Tarray || val->type->ty == Tsarray)
|
||||
{
|
||||
// Check for unsupported type painting operations
|
||||
@@ -1907,10 +1984,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
||||
if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception)
|
||||
{
|
||||
e = copyLiteral(e);
|
||||
if (v->isDataseg())
|
||||
ctfeStack.saveGlobalConstant(v, e);
|
||||
else
|
||||
v->setValueWithoutChecking(e);
|
||||
ctfeStack.saveGlobalConstant(v, e);
|
||||
}
|
||||
}
|
||||
else if (v->isCTFE() && !v->hasValue())
|
||||
@@ -1919,11 +1993,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
||||
{
|
||||
if (v->init->isVoidInitializer())
|
||||
{
|
||||
error(loc, "variable %s is used before initialization", v->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
// var should have been initialized when it was created
|
||||
error(loc, "CTFE internal error - trying to access uninitialized var");
|
||||
assert(0);
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = v->init->toExpression();
|
||||
e = e->interpret(istate);
|
||||
}
|
||||
e = v->init->toExpression();
|
||||
e = e->interpret(istate);
|
||||
}
|
||||
else
|
||||
e = v->type->defaultInitLiteral(loc);
|
||||
@@ -1939,7 +2018,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
else if (!e)
|
||||
error(loc, "variable %s is used before initialization", v->toChars());
|
||||
{
|
||||
assert(0);
|
||||
assert(v->init && v->init->isVoidInitializer());
|
||||
e = v->type->voidInitLiteral(v);
|
||||
}
|
||||
else if (exceptionOrCantInterpret(e))
|
||||
return e;
|
||||
else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex)
|
||||
@@ -1958,6 +2041,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
||||
|| e->op == TOKassocarrayliteral || e->op == TOKslice
|
||||
|| e->type->toBasetype()->ty == Tpointer)
|
||||
return e; // it's already an Lvalue
|
||||
else if (e->op == TOKvoid)
|
||||
{
|
||||
VoidInitExp *ve = (VoidInitExp *)e;
|
||||
error(loc, "cannot read uninitialized variable %s in ctfe", v->toPrettyChars());
|
||||
errorSupplemental(ve->var->loc, "%s was uninitialized and used before set", ve->var->toChars());
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
else
|
||||
e = e->interpret(istate, goal);
|
||||
}
|
||||
@@ -1971,10 +2061,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
||||
if (s->dsym->toInitializer() == s->sym)
|
||||
{
|
||||
#endif
|
||||
e = s->dsym->type->defaultInitLiteral();
|
||||
e = s->dsym->type->defaultInitLiteral(loc);
|
||||
e = e->semantic(NULL);
|
||||
if (e->op == TOKerror)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
else // Convert NULL to VoidExp
|
||||
e = e->interpret(istate, goal);
|
||||
#if !IN_LLVM
|
||||
}
|
||||
else
|
||||
@@ -2045,7 +2137,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
if (ie)
|
||||
e = ie->exp->interpret(istate);
|
||||
else if (v->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
{
|
||||
e = v->type->voidInitLiteral(v);
|
||||
// There is no AssignExp for void initializers,
|
||||
// so set it here.
|
||||
v->setValue(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Declaration %s is not yet implemented in CTFE", toChars());
|
||||
@@ -2274,7 +2371,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
ekey = resolveSlice(ekey);
|
||||
for (size_t j = i; j < keysx->dim; j++)
|
||||
{ Expression *ekey2 = keysx->tdata()[j];
|
||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2);
|
||||
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, ekey2);
|
||||
if (ex == EXP_CANT_INTERPRET)
|
||||
goto Lerr;
|
||||
if (ex->isBool(TRUE)) // if a match
|
||||
@@ -2448,10 +2545,10 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is
|
||||
if (elemType->ty == Tchar || elemType->ty == Twchar
|
||||
|| elemType->ty == Tdchar)
|
||||
return createBlockDuplicatedStringLiteral(loc, newtype,
|
||||
(unsigned)(elemType->defaultInitLiteral()->toInteger()),
|
||||
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
|
||||
len, elemType->size());
|
||||
return createBlockDuplicatedArrayLiteral(loc, newtype,
|
||||
elemType->defaultInitLiteral(),
|
||||
elemType->defaultInitLiteral(loc),
|
||||
len);
|
||||
}
|
||||
|
||||
@@ -2465,7 +2562,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
|
||||
if (newtype->toBasetype()->ty == Tstruct)
|
||||
{
|
||||
Expression *se = newtype->defaultInitLiteral();
|
||||
Expression *se = newtype->defaultInitLiteral(loc);
|
||||
#if DMDV2
|
||||
if (member)
|
||||
{
|
||||
@@ -2502,7 +2599,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
Dsymbol *s = c->fields.tdata()[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v);
|
||||
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral();
|
||||
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc);
|
||||
if (exceptionOrCantInterpret(m))
|
||||
return m;
|
||||
elems->tdata()[fieldsSoFar+i] = copyLiteral(m);
|
||||
@@ -2672,7 +2769,7 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
|
||||
}
|
||||
if (indx < 0 || indx > len)
|
||||
{
|
||||
error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len);
|
||||
error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
|
||||
@@ -2974,7 +3071,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi
|
||||
for (size_t j = valuesx->dim; j; )
|
||||
{ j--;
|
||||
Expression *ekey = aae->keys->tdata()[j];
|
||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
|
||||
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
|
||||
if (exceptionOrCantInterpret(ex))
|
||||
return ex;
|
||||
if (ex->isBool(TRUE))
|
||||
@@ -3144,7 +3241,7 @@ Expression *copyLiteral(Expression *e)
|
||||
assert(v);
|
||||
// If it is a void assignment, use the default initializer
|
||||
if (!m)
|
||||
m = v->type->defaultInitLiteral(e->loc);
|
||||
m = v->type->voidInitLiteral(v);
|
||||
if (m->op == TOKslice)
|
||||
m = resolveSlice(m);
|
||||
if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray)
|
||||
@@ -3171,7 +3268,8 @@ Expression *copyLiteral(Expression *e)
|
||||
|| e->op == TOKsymoff || e->op == TOKnull
|
||||
|| e->op == TOKvar
|
||||
|| e->op == TOKint64 || e->op == TOKfloat64
|
||||
|| e->op == TOKchar || e->op == TOKcomplex80)
|
||||
|| e->op == TOKchar || e->op == TOKcomplex80
|
||||
|| e->op == TOKvoid)
|
||||
{ // Simple value types
|
||||
Expression *r = e->syntaxCopy();
|
||||
r->type = e->type;
|
||||
@@ -3341,7 +3439,7 @@ void assignInPlace(Expression *dest, Expression *src)
|
||||
assert(o->op == e->op);
|
||||
assignInPlace(o, e);
|
||||
}
|
||||
else if (e->type->ty == Tsarray && o->type->ty == Tsarray)
|
||||
else if (e->type->ty == Tsarray && o->type->ty == Tsarray && e->op != TOKvoid)
|
||||
{
|
||||
assignInPlace(o, e);
|
||||
}
|
||||
@@ -3636,7 +3734,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
Type *elemType= NULL;
|
||||
elemType = ((TypeArray *)t)->next;
|
||||
assert(elemType);
|
||||
Expression *defaultElem = elemType->defaultInitLiteral();
|
||||
Expression *defaultElem = elemType->defaultInitLiteral(loc);
|
||||
|
||||
Expressions *elements = new Expressions();
|
||||
elements->setDim(newlen);
|
||||
@@ -3744,7 +3842,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
// only modifying part of the variable. So we need to make sure
|
||||
// that the parent variable exists.
|
||||
if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
|
||||
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral()));
|
||||
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc)));
|
||||
|
||||
// ---------------------------------------
|
||||
// Deal with reference assignment
|
||||
@@ -3822,7 +3920,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
indx = resolveSlice(indx);
|
||||
|
||||
// Look up this index in it up in the existing AA, to get the next level of AA.
|
||||
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx);
|
||||
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(loc, existingAA, indx);
|
||||
if (exceptionOrCantInterpret(newAA))
|
||||
return newAA;
|
||||
if (!newAA)
|
||||
@@ -3968,14 +4066,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
? (StructLiteralExp *)exx
|
||||
: ((ClassReferenceExp *)exx)->value;
|
||||
int fieldi = exx->op == TOKstructliteral
|
||||
? se->getFieldIndex(member->type, member->offset)
|
||||
: ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset);
|
||||
? findFieldIndexByName(se->sd, member)
|
||||
: ((ClassReferenceExp *)exx)->findFieldIndexByName(member);
|
||||
if (fieldi == -1)
|
||||
{
|
||||
error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
assert(fieldi>=0 && fieldi < se->elements->dim);
|
||||
assert(fieldi >= 0 && fieldi < se->elements->dim);
|
||||
// If it's a union, set all other members of this union to void
|
||||
if (exx->op == TOKstructliteral)
|
||||
{
|
||||
assert(se->sd);
|
||||
int unionStart = se->sd->firstFieldInUnion(fieldi);
|
||||
int unionSize = se->sd->numFieldsInUnion(fieldi);
|
||||
for(int i = unionStart; i < unionStart + unionSize; ++i)
|
||||
{ if (i == fieldi)
|
||||
continue;
|
||||
Expression **el = &se->elements->tdata()[i];
|
||||
if ((*el)->op != TOKvoid)
|
||||
*el = (*el)->type->voidInitLiteral(member);
|
||||
}
|
||||
}
|
||||
|
||||
if (newval->op == TOKstructliteral)
|
||||
assignInPlace(se->elements->tdata()[fieldi], newval);
|
||||
else
|
||||
@@ -4050,6 +4163,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
}
|
||||
aggregate = getAggregateFromPointer(aggregate, &ofs);
|
||||
indexToModify += ofs;
|
||||
if (aggregate->op != TOKslice && aggregate->op != TOKstring &&
|
||||
aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral)
|
||||
{
|
||||
if (indexToModify != 0)
|
||||
{
|
||||
error("pointer index [%lld] lies outside memory block [0..1]", indexToModify);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
// It is equivalent to *aggregate = newval.
|
||||
// Aggregate could be varexp, a dotvar, ...
|
||||
// TODO: we could support this
|
||||
error("indexed assignment of non-array pointers is not yet supported at compile time; use *%s = %s instead",
|
||||
ie->e1->toChars(), e2->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
destarraylen = resolveArrayLength(aggregate);
|
||||
}
|
||||
if (indexToModify >= destarraylen)
|
||||
@@ -4075,7 +4203,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
|
||||
{
|
||||
IndexExp *ix = (IndexExp *)aggregate;
|
||||
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
|
||||
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
|
||||
if (!aggregate)
|
||||
{
|
||||
error("key %s not found in associative array %s",
|
||||
@@ -4177,6 +4305,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
if (isPointer(oldval->type))
|
||||
{ // Slicing a pointer
|
||||
oldval = oldval->interpret(istate, ctfeNeedLvalue);
|
||||
if (exceptionOrCantInterpret(oldval))
|
||||
return oldval;
|
||||
dinteger_t ofs;
|
||||
oldval = getAggregateFromPointer(oldval, &ofs);
|
||||
assignmentToSlicedPointer = true;
|
||||
@@ -4186,7 +4316,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
|
||||
&& oldval->op != TOKslice && oldval->op != TOKnull)
|
||||
{
|
||||
error("CTFE ICE: cannot resolve array length");
|
||||
if (assignmentToSlicedPointer)
|
||||
{
|
||||
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
|
||||
sexp->e1->toChars());
|
||||
}
|
||||
else
|
||||
error("CTFE ICE: cannot resolve array length");
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
uinteger_t dollar = resolveArrayLength(oldval);
|
||||
@@ -4249,7 +4385,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
|
||||
{
|
||||
IndexExp *ix = (IndexExp *)aggregate;
|
||||
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
|
||||
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
|
||||
if (!aggregate)
|
||||
{
|
||||
error("key %s not found in associative array %s",
|
||||
@@ -4273,7 +4409,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
firstIndex = lowerbound + sexpold->lwr->toInteger();
|
||||
if (hi > sexpold->upr->toInteger())
|
||||
{
|
||||
error("slice [%d..%d] exceeds array bounds [0..%jd]",
|
||||
error("slice [%d..%d] exceeds array bounds [0..%lld]",
|
||||
lowerbound, upperbound,
|
||||
sexpold->upr->toInteger() - sexpold->lwr->toInteger());
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -4285,11 +4421,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
|
||||
dinteger_t ofs;
|
||||
aggregate = getAggregateFromPointer(aggregate, &ofs);
|
||||
if (aggregate->op == TOKnull)
|
||||
{
|
||||
error("cannot slice null pointer %s", sexp->e1->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
dinteger_t hi = upperbound + ofs;
|
||||
firstIndex = lowerbound + ofs;
|
||||
if (firstIndex < 0 || hi > dim)
|
||||
{
|
||||
error("slice [%d..%jd] exceeds memory block bounds [0..%jd]",
|
||||
error("slice [lld..%lld] exceeds memory block bounds [0..%lld]",
|
||||
firstIndex, hi, dim);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -4430,9 +4571,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
||||
else
|
||||
{
|
||||
error("%s cannot be evaluated at compile time", toChars());
|
||||
#ifdef DEBUG
|
||||
dump(0);
|
||||
#endif
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
@@ -4812,6 +4950,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
if (!global.gag)
|
||||
showCtfeBackTrace(istate, this, fd);
|
||||
}
|
||||
else if (eresult == EXP_VOID_INTERPRET)
|
||||
;
|
||||
else
|
||||
eresult->loc = loc;
|
||||
return eresult;
|
||||
}
|
||||
|
||||
@@ -4830,7 +4972,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
InterState istateComma;
|
||||
if (!istate && firstComma->e1->op == TOKdeclaration)
|
||||
{
|
||||
assert(ctfeStack.stackPointer() == 0);
|
||||
ctfeStack.startFrame();
|
||||
istate = &istateComma;
|
||||
}
|
||||
@@ -4848,7 +4989,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
ctfeStack.push(v);
|
||||
if (!v->init && !v->getValue())
|
||||
{
|
||||
v->setValue(copyLiteral(v->type->defaultInitLiteral()));
|
||||
v->setValue(copyLiteral(v->type->defaultInitLiteral(loc)));
|
||||
}
|
||||
if (!v->getValue()) {
|
||||
Expression *newval = v->init->toExpression();
|
||||
@@ -4944,7 +5085,7 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
* Return ae[e2] if present, or NULL if not found.
|
||||
* Return EXP_CANT_INTERPRET on error.
|
||||
*/
|
||||
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
|
||||
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
|
||||
{
|
||||
/* Search the keys backwards, in case there are duplicate keys
|
||||
*/
|
||||
@@ -4952,13 +5093,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
|
||||
{
|
||||
i--;
|
||||
Expression *ekey = ae->keys->tdata()[i];
|
||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2);
|
||||
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, e2);
|
||||
if (ex == EXP_CANT_INTERPRET)
|
||||
{
|
||||
error("cannot evaluate %s==%s at compile time",
|
||||
ekey->toChars(), e2->toChars());
|
||||
return ex;
|
||||
}
|
||||
if (ex->isBool(TRUE))
|
||||
{
|
||||
return ae->values->tdata()[i];
|
||||
@@ -5013,23 +5150,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
if (exceptionOrCantInterpret(e2))
|
||||
return e2;
|
||||
dinteger_t indx = e2->toInteger();
|
||||
|
||||
dinteger_t ofs;
|
||||
Expression *agg = getAggregateFromPointer(e1, &ofs);
|
||||
|
||||
if (agg->op == TOKnull)
|
||||
{
|
||||
error("cannot index null pointer %s", this->e1->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
|
||||
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
||||
Type *pointee = ((TypePointer *)agg->type)->next;
|
||||
if ((indx + ofs) < 0 || (indx+ofs) > len)
|
||||
if ( agg->op == TOKarrayliteral || agg->op == TOKstring)
|
||||
{
|
||||
error("pointer index [%jd] exceeds allocated memory block [0..%jd]",
|
||||
indx+ofs, len);
|
||||
return EXP_CANT_INTERPRET;
|
||||
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
||||
Type *pointee = ((TypePointer *)agg->type)->next;
|
||||
if ((indx + ofs) < 0 || (indx+ofs) > len)
|
||||
{
|
||||
error("pointer index [%lld] exceeds allocated memory block [0..%lld]",
|
||||
indx+ofs, len);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
return ctfeIndex(loc, type, agg, indx+ofs);
|
||||
}
|
||||
else
|
||||
{ // Pointer to a non-array variable
|
||||
if ((indx + ofs) != 0)
|
||||
{
|
||||
error("pointer index [%lld] lies outside memory block [0..1]",
|
||||
indx+ofs);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
return agg->interpret(istate);
|
||||
}
|
||||
return ctfeIndex(loc, type, agg, indx+ofs);
|
||||
}
|
||||
e1 = this->e1;
|
||||
if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe))
|
||||
@@ -5070,7 +5221,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
|
||||
if (indx > iup - ilo)
|
||||
{
|
||||
error("index %ju exceeds array length %ju", indx, iup - ilo);
|
||||
error("index %llu exceeds array length %llu", indx, iup - ilo);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
indx += ilo;
|
||||
@@ -5091,7 +5242,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
{
|
||||
if (e2->op == TOKslice)
|
||||
e2 = resolveSlice(e2);
|
||||
e = findKeyInAA((AssocArrayLiteralExp *)e1, e2);
|
||||
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2);
|
||||
if (!e)
|
||||
{
|
||||
error("key %s not found in associative array %s",
|
||||
@@ -5112,6 +5263,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
return e;
|
||||
if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
|
||||
e = e->interpret(istate);
|
||||
if (goal == ctfeNeedRvalue && e->op == TOKvoid)
|
||||
{
|
||||
error("%s is used before initialized", toChars());
|
||||
errorSupplemental(e->loc, "originally uninitialized here");
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
e = paintTypeOntoLiteral(type, e);
|
||||
return e;
|
||||
}
|
||||
@@ -5166,12 +5323,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
error("cannot slice null pointer %s", this->e1->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if (agg->op != TOKarrayliteral && agg->op != TOKstring)
|
||||
{
|
||||
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
|
||||
this->e1->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
|
||||
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
||||
Type *pointee = ((TypePointer *)agg->type)->next;
|
||||
if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr)
|
||||
{
|
||||
error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]",
|
||||
error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]",
|
||||
ilwr+ofs, iupr+ofs, len);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -5235,7 +5398,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
{
|
||||
if (ilwr== 0 && iupr == 0)
|
||||
return e1;
|
||||
e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr);
|
||||
e1->error("slice [%llu..%llu] is out of bounds", ilwr, iupr);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if (e1->op == TOKslice)
|
||||
@@ -5247,7 +5410,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
uinteger_t up1 = se->upr->toInteger();
|
||||
if (ilwr > iupr || iupr > up1 - lo1)
|
||||
{
|
||||
error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]",
|
||||
error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]",
|
||||
ilwr, iupr, lo1, up1);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -5264,7 +5427,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
{
|
||||
if (iupr < ilwr || ilwr < 0 || iupr > dollar)
|
||||
{
|
||||
error("slice [%jd..%jd] exceeds array bounds [0..%jd]",
|
||||
error("slice [%lld..%lld] exceeds array bounds [0..%lld]",
|
||||
ilwr, iupr, dollar);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -5295,7 +5458,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
}
|
||||
if (e1->op == TOKslice)
|
||||
e1 = resolveSlice(e1);
|
||||
e = findKeyInAA((AssocArrayLiteralExp *)e2, e1);
|
||||
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1);
|
||||
if (exceptionOrCantInterpret(e))
|
||||
return e;
|
||||
if (!e)
|
||||
@@ -5354,8 +5517,12 @@ bool isAssocArray(Type *t)
|
||||
if (t->ty != Tstruct)
|
||||
return false;
|
||||
StructDeclaration *sym = ((TypeStruct *)t)->sym;
|
||||
if (sym->ident == Id::AssociativeArray)
|
||||
if (sym->ident == Id::AssociativeArray && sym->parent &&
|
||||
sym->parent->parent &&
|
||||
sym->parent->parent->ident == Id::object)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -5510,9 +5677,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
e->type = type;
|
||||
return e;
|
||||
}
|
||||
error("pointer cast from %s to %s is not supported at compile time",
|
||||
|
||||
// Check if we have a null pointer (eg, inside a struct)
|
||||
e1 = e1->interpret(istate);
|
||||
if (e1->op != TOKnull)
|
||||
{
|
||||
error("pointer cast from %s to %s is not supported at compile time",
|
||||
e1->type->toChars(), to->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
}
|
||||
if (to->ty == Tarray && e1->op == TOKslice)
|
||||
{
|
||||
@@ -5660,7 +5833,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
assert(indx >=0 && indx <= len); // invalid pointer
|
||||
if (indx == len)
|
||||
{
|
||||
error("dereference of pointer %s one past end of memory block limits [0..%jd]",
|
||||
error("dereference of pointer %s one past end of memory block limits [0..%lld]",
|
||||
toChars(), len);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -5705,7 +5878,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
}
|
||||
else if (e->op == TOKaddress)
|
||||
e = ((AddrExp*)e)->e1; // *(&x) ==> x
|
||||
if (e->op == TOKnull)
|
||||
else if (e->op == TOKnull)
|
||||
{
|
||||
error("dereference of null pointer '%s'", e1->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -5794,6 +5967,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
|
||||
e->op == TOKassocarrayliteral || e->op == TOKstring)
|
||||
return e;
|
||||
if (e->op == TOKvoid)
|
||||
{
|
||||
VoidInitExp *ve = (VoidInitExp *)e;
|
||||
error("cannot read uninitialized variable %s in ctfe", toChars());
|
||||
ve->var->error("was uninitialized and used before set");
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if ( isPointer(type) )
|
||||
{
|
||||
return paintTypeOntoLiteral(type, e);
|
||||
@@ -5838,7 +6018,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal)
|
||||
size_t removed = 0;
|
||||
for (size_t j = 0; j < valuesx->dim; ++j)
|
||||
{ Expression *ekey = keysx->tdata()[j];
|
||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
|
||||
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
|
||||
if (exceptionOrCantInterpret(ex))
|
||||
return ex;
|
||||
if (ex->isBool(TRUE))
|
||||
@@ -6017,7 +6197,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
|
||||
else if (str->op == TOKarrayliteral)
|
||||
ale = (ArrayLiteralExp *)str;
|
||||
else
|
||||
{ error("CTFE internal error: cannot foreach %s", str->toChars());
|
||||
{ str->error("CTFE internal error: cannot foreach %s", str->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
Expressions args;
|
||||
@@ -6472,6 +6652,10 @@ bool isCtfeValueValid(Expression *newval)
|
||||
assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe);
|
||||
return true;
|
||||
}
|
||||
if (newval->op == TOKvoid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
newval->error("CTFE internal error: illegal value %s\n", newval->toChars());
|
||||
return false;
|
||||
}
|
||||
@@ -6504,3 +6688,29 @@ void VarDeclaration::setValue(Expression *newval)
|
||||
assert(isCtfeValueValid(newval));
|
||||
ctfeStack.setValue(this, newval);
|
||||
}
|
||||
|
||||
|
||||
Expression *Type::voidInitLiteral(VarDeclaration *var)
|
||||
{
|
||||
return new VoidInitExp(var, this);
|
||||
}
|
||||
|
||||
Expression *TypeSArray::voidInitLiteral(VarDeclaration *var)
|
||||
{
|
||||
return createBlockDuplicatedArrayLiteral(var->loc, this, next->voidInitLiteral(var), dim->toInteger());
|
||||
}
|
||||
|
||||
Expression *TypeStruct::voidInitLiteral(VarDeclaration *var)
|
||||
{
|
||||
Expressions *exps = new Expressions();
|
||||
exps->setDim(sym->fields.dim);
|
||||
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||
{
|
||||
//(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type);
|
||||
(*exps)[i] = sym->fields[i]->type->voidInitLiteral(var);
|
||||
}
|
||||
StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps);
|
||||
se->type = this;
|
||||
se->ownedByCtfe = true;
|
||||
return se;
|
||||
}
|
||||
|
||||
34
dmd/lexer.c
34
dmd/lexer.c
@@ -304,7 +304,7 @@ void Lexer::error(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
verror(loc, format, ap);
|
||||
verror(tokenLoc(), format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
@@ -2870,6 +2870,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
|
||||
return c;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Search actual location of current token
|
||||
* even when infinite look-ahead was done.
|
||||
*/
|
||||
Loc Lexer::tokenLoc()
|
||||
{
|
||||
Loc result = this->loc;
|
||||
Token* last = &token;
|
||||
while (last->next)
|
||||
last = last->next;
|
||||
|
||||
unsigned char* start = token.ptr;
|
||||
unsigned char* stop = last->ptr;
|
||||
|
||||
for (unsigned char* p = start; p < stop; ++p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '\n':
|
||||
result.linnum--;
|
||||
break;
|
||||
case '\r':
|
||||
if (p[1] != '\n')
|
||||
result.linnum--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Create an identifier in the string table.
|
||||
*/
|
||||
|
||||
@@ -312,6 +312,8 @@ struct Lexer
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
|
||||
Loc tokenLoc();
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
|
||||
@@ -72,7 +72,7 @@ Global::Global()
|
||||
|
||||
copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v1.073";
|
||||
version = "v1.074";
|
||||
ldc_version = "LDC trunk";
|
||||
llvm_version = "LLVM 3.0";
|
||||
global.structalign = 8;
|
||||
@@ -102,6 +102,11 @@ bool Global::endGagging(unsigned oldGagged)
|
||||
return anyErrs;
|
||||
}
|
||||
|
||||
bool Global::isSpeculativeGagging()
|
||||
{
|
||||
return gag && gag == speculativeGag;
|
||||
}
|
||||
|
||||
|
||||
char *Loc::toChars() const
|
||||
{
|
||||
|
||||
@@ -347,6 +347,12 @@ struct Global
|
||||
unsigned gag; // !=0 means gag reporting of errors & warnings
|
||||
unsigned gaggedErrors; // number of errors reported while gagged
|
||||
|
||||
/* Gagging can either be speculative (is(typeof()), etc)
|
||||
* or because of forward references
|
||||
*/
|
||||
unsigned speculativeGag; // == gag means gagging is for is(typeof);
|
||||
bool isSpeculativeGagging();
|
||||
|
||||
// Start gagging. Return the current number of gagged errors
|
||||
unsigned startGagging();
|
||||
|
||||
|
||||
45
dmd/module.c
45
dmd/module.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -387,7 +387,9 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
||||
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
|
||||
}
|
||||
|
||||
m->read(loc);
|
||||
if (!m->read(loc))
|
||||
return NULL;
|
||||
|
||||
m->parse();
|
||||
|
||||
#ifdef IN_GCC
|
||||
@@ -397,7 +399,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
||||
return m;
|
||||
}
|
||||
|
||||
void Module::read(Loc loc)
|
||||
bool Module::read(Loc loc)
|
||||
{
|
||||
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
|
||||
if (srcfile->read())
|
||||
@@ -415,9 +417,11 @@ void Module::read(Loc loc)
|
||||
}
|
||||
else
|
||||
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
|
||||
fatal();
|
||||
}
|
||||
fatal();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned readwordLE(unsigned short *p)
|
||||
@@ -684,7 +688,15 @@ void Module::parse()
|
||||
|
||||
if (md)
|
||||
{ this->ident = md->id;
|
||||
dst = Package::resolve(md->packages, &this->parent, NULL);
|
||||
this->safe = md->safe;
|
||||
Package *ppack = NULL;
|
||||
dst = Package::resolve(md->packages, &this->parent, &ppack);
|
||||
if (ppack && ppack->isModule())
|
||||
{
|
||||
error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s",
|
||||
ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars());
|
||||
dst = modules;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -709,7 +721,7 @@ void Module::parse()
|
||||
{
|
||||
Package *pkg = prev->isPackage();
|
||||
assert(pkg);
|
||||
error(loc, "from file %s conflicts with package name %s",
|
||||
error(pkg->loc, "from file %s conflicts with package name %s",
|
||||
srcname, pkg->toChars());
|
||||
}
|
||||
}
|
||||
@@ -1216,19 +1228,24 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
|
||||
else
|
||||
{
|
||||
assert(p->isPackage());
|
||||
#if TARGET_NET //dot net needs modules and packages with same name
|
||||
#else
|
||||
if (p->isModule())
|
||||
{ p->error("module and package have the same name");
|
||||
fatal();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
// It might already be a module, not a package, but that needs
|
||||
// to be checked at a higher level, where a nice error message
|
||||
// can be generated.
|
||||
// dot net needs modules and packages with same name
|
||||
}
|
||||
parent = p;
|
||||
dst = ((Package *)p)->symtab;
|
||||
if (ppkg && !*ppkg)
|
||||
*ppkg = (Package *)p;
|
||||
#if TARGET_NET
|
||||
#else
|
||||
if (p->isModule())
|
||||
{ // Return the module so that a nice error message can be generated
|
||||
if (ppkg)
|
||||
*ppkg = (Package *)p;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (pparent)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -134,10 +134,11 @@ struct Module : Package
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void toJsonBuffer(OutBuffer *buf);
|
||||
const char *kind();
|
||||
void read(Loc loc); // read file
|
||||
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
|
||||
#if IN_LLVM
|
||||
void parse(bool gen_docs = false); // syntactic parse
|
||||
#elif IN_GCC
|
||||
void setDocfile(); // set docfile member
|
||||
void parse(bool dump_source = false); // syntactic parse
|
||||
#else
|
||||
void parse(); // syntactic parse
|
||||
|
||||
75
dmd/mtype.c
75
dmd/mtype.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -1451,7 +1451,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
case Timaginary64: t = tfloat64; goto L2;
|
||||
case Timaginary80: t = tfloat80; goto L2;
|
||||
L2:
|
||||
e = new RealExp(0, 0.0, t);
|
||||
e = new RealExp(e->loc, 0.0, t);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1481,7 +1481,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
case Tfloat32:
|
||||
case Tfloat64:
|
||||
case Tfloat80:
|
||||
e = new RealExp(0, 0.0, this);
|
||||
e = new RealExp(e->loc, 0.0, this);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2645,6 +2645,22 @@ int TypeAArray::checkBoolean()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Expression *TypeAArray::toExpression()
|
||||
{
|
||||
Expression *e = next->toExpression();
|
||||
if (e)
|
||||
{
|
||||
Expression *ei = index->toExpression();
|
||||
if (ei)
|
||||
{
|
||||
Expressions *arguments = new Expressions();
|
||||
arguments->push(ei);
|
||||
return new ArrayExp(0, e, arguments);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int TypeAArray::hasPointers()
|
||||
{
|
||||
return TRUE;
|
||||
@@ -3184,13 +3200,25 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
|
||||
error(loc, "cannot have parameter of type %s", fparam->type->toChars());
|
||||
|
||||
if (fparam->defaultArg)
|
||||
{
|
||||
fparam->defaultArg = fparam->defaultArg->semantic(argsc);
|
||||
fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg);
|
||||
fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type);
|
||||
{ Expression *e = fparam->defaultArg;
|
||||
e = e->semantic(argsc);
|
||||
e = resolveProperties(argsc, e);
|
||||
if (e->op == TOKfunction) // see Bugzilla 4820
|
||||
{ FuncExp *fe = (FuncExp *)e;
|
||||
if (fe->fd)
|
||||
{ // Replace function literal with a function symbol,
|
||||
// since default arg expression must be copied when used
|
||||
// and copying the literal itself is wrong.
|
||||
e = new VarExp(e->loc, fe->fd);
|
||||
e = new AddrExp(e->loc, e);
|
||||
e = e->semantic(argsc);
|
||||
}
|
||||
}
|
||||
e = e->implicitCastTo(argsc, fparam->type);
|
||||
fparam->defaultArg = e;
|
||||
}
|
||||
|
||||
/* If arg turns out to be a tuple, the number of parameters may
|
||||
/* If fparam after semantic() turns out to be a tuple, the number of parameters may
|
||||
* change.
|
||||
*/
|
||||
if (t->ty == Ttuple)
|
||||
@@ -3650,7 +3678,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
|
||||
else
|
||||
{
|
||||
Lerror:
|
||||
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
|
||||
if (id->dyncast() == DYNCAST_DSYMBOL)
|
||||
{ // searchX already handles errors for template instances
|
||||
assert(global.errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
sm = s->search_correct(id);
|
||||
if (sm)
|
||||
error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?",
|
||||
id->toChars(), toChars(), sm->kind(), sm->toChars());
|
||||
else
|
||||
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
|
||||
}
|
||||
*pe = new ErrorExp();
|
||||
}
|
||||
return;
|
||||
@@ -4131,14 +4171,19 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sc->intypeof++;
|
||||
exp = exp->semantic(sc);
|
||||
Scope *sc2 = sc->push();
|
||||
sc2->intypeof++;
|
||||
unsigned oldspecgag = global.speculativeGag;
|
||||
if (global.gag)
|
||||
global.speculativeGag = global.gag;
|
||||
exp = exp->semantic(sc2);
|
||||
global.speculativeGag = oldspecgag;
|
||||
#if DMDV2
|
||||
if (exp->type && exp->type->ty == Tfunction &&
|
||||
((TypeFunction *)exp->type)->isproperty)
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = resolveProperties(sc2, exp);
|
||||
#endif
|
||||
sc->intypeof--;
|
||||
sc2->pop();
|
||||
if (exp->op == TOKtype)
|
||||
{
|
||||
error(loc, "argument %s to typeof is not an expression", exp->toChars());
|
||||
@@ -4959,8 +5004,8 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
|
||||
e = vd->init->toExpression();
|
||||
}
|
||||
else
|
||||
e = vd->type->defaultInitLiteral();
|
||||
structelems->tdata()[j] = e;
|
||||
e = vd->type->defaultInitLiteral(loc);
|
||||
(*structelems)[j] = e;
|
||||
}
|
||||
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
|
||||
// Why doesn't the StructLiteralExp constructor do this, when
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -254,7 +254,8 @@ struct Type : Object
|
||||
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
virtual unsigned memalign(unsigned salign);
|
||||
virtual Expression *defaultInit(Loc loc = 0);
|
||||
virtual Expression *defaultInitLiteral(Loc loc = 0);
|
||||
virtual Expression *defaultInitLiteral(Loc loc);
|
||||
virtual Expression *voidInitLiteral(VarDeclaration *var);
|
||||
virtual int isZeroInit(Loc loc = 0); // if initializer is 0
|
||||
#if IN_DMD
|
||||
virtual dt_t **toDt(dt_t **pdt);
|
||||
@@ -391,6 +392,7 @@ struct TypeSArray : TypeArray
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
Expression *defaultInitLiteral(Loc loc);
|
||||
Expression *voidInitLiteral(VarDeclaration *var);
|
||||
#if IN_DMD
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
dt_t **toDtElem(dt_t **pdt, Expression *e);
|
||||
@@ -451,6 +453,7 @@ struct TypeAArray : TypeArray
|
||||
int isZeroInit(Loc loc);
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Expression *toExpression();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
|
||||
@@ -644,6 +647,7 @@ struct TypeStruct : Type
|
||||
unsigned memalign(unsigned salign);
|
||||
Expression *defaultInit(Loc loc);
|
||||
Expression *defaultInitLiteral(Loc loc);
|
||||
Expression *voidInitLiteral(VarDeclaration *var);
|
||||
int isZeroInit(Loc loc);
|
||||
int checkBoolean();
|
||||
#if IN_DMD
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -129,7 +129,7 @@ Dsymbols *Parser::parseModule()
|
||||
|
||||
decldefs = parseDeclDefs(0);
|
||||
if (token.value != TOKeof)
|
||||
{ error("unrecognized declaration");
|
||||
{ error(loc, "unrecognized declaration");
|
||||
goto Lerr;
|
||||
}
|
||||
return decldefs;
|
||||
@@ -5565,6 +5565,7 @@ void initPrecedence()
|
||||
precedence[TOKtraits] = PREC_primary;
|
||||
precedence[TOKdefault] = PREC_primary;
|
||||
precedence[TOKoverloadset] = PREC_primary;
|
||||
precedence[TOKvoid] = PREC_primary;
|
||||
#endif
|
||||
|
||||
// post
|
||||
|
||||
376
dmd/root/aav.c
376
dmd/root/aav.c
@@ -1,188 +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
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -1,11 +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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
514
dmd/root/array.c
514
dmd/root/array.c
@@ -1,257 +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;
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
650
dmd/root/async.c
650
dmd/root/async.c
@@ -1,325 +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
|
||||
|
||||
#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
|
||||
|
||||
@@ -1,33 +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
|
||||
|
||||
// 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
|
||||
|
||||
964
dmd/root/dchar.c
964
dmd/root/dchar.c
@@ -1,482 +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
|
||||
|
||||
// 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
|
||||
|
||||
388
dmd/root/dchar.h
388
dmd/root/dchar.h
@@ -1,194 +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
|
||||
|
||||
|
||||
// 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) { (void)pstart; 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) { (void)pstart; 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
|
||||
|
||||
|
||||
636
dmd/root/longdouble.c
Normal file
636
dmd/root/longdouble.c
Normal file
@@ -0,0 +1,636 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Rainer Schuetze
|
||||
// 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.
|
||||
|
||||
// 80 bit floating point value implementation for Microsoft compiler
|
||||
|
||||
#if _MSC_VER
|
||||
#include "longdouble.h"
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// implemented in ldfpu.asm for _WIN64
|
||||
int ld_initfpu(int bits, int mask);
|
||||
void ld_expl(longdouble* ld, int exp);
|
||||
longdouble ld_add(longdouble ld1, longdouble ld2);
|
||||
longdouble ld_sub(longdouble ld1, longdouble ld2);
|
||||
longdouble ld_mul(longdouble ld1, longdouble ld2);
|
||||
longdouble ld_div(longdouble ld1, longdouble ld2);
|
||||
longdouble ld_mod(longdouble ld1, longdouble ld2);
|
||||
bool ld_cmpb(longdouble ld1, longdouble ld2);
|
||||
bool ld_cmpbe(longdouble ld1, longdouble ld2);
|
||||
bool ld_cmpa(longdouble ld1, longdouble ld2);
|
||||
bool ld_cmpae(longdouble ld1, longdouble ld2);
|
||||
bool ld_cmpe(longdouble ld1, longdouble ld2);
|
||||
bool ld_cmpne(longdouble ld1, longdouble ld2);
|
||||
longdouble ld_sqrt(longdouble ld1);
|
||||
longdouble ld_sin(longdouble ld1);
|
||||
longdouble ld_cos(longdouble ld1);
|
||||
longdouble ld_tan(longdouble ld1);
|
||||
}
|
||||
|
||||
bool initFPU()
|
||||
{
|
||||
#ifdef _WIN64
|
||||
// int old_cw = ld_initfpu(_RC_NEAR);
|
||||
int old_cw = ld_initfpu(0x300 /*_PC_64 | _RC_NEAR*/, // #defines NOT identical to CPU FPU control word!
|
||||
0xF00 /*_MCW_PC | _MCW_RC*/);
|
||||
#else
|
||||
int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR,
|
||||
_MCW_EM | _MCW_PC | _MCW_RC);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
static bool doInitFPU = initFPU();
|
||||
|
||||
#ifndef _WIN64
|
||||
extern "C"
|
||||
{
|
||||
|
||||
double ld_read(const longdouble* pthis)
|
||||
{
|
||||
double res;
|
||||
__asm
|
||||
{
|
||||
mov eax, pthis
|
||||
fld tbyte ptr [eax]
|
||||
fstp res
|
||||
}
|
||||
return res;
|
||||
}
|
||||
long long ld_readll(const longdouble* pthis)
|
||||
{
|
||||
#if 1
|
||||
return ld_readull(pthis);
|
||||
#elif defined _WIN64
|
||||
return ld_readll(this);
|
||||
#else
|
||||
longdouble* pthis = this;
|
||||
long long res;
|
||||
__asm
|
||||
{
|
||||
mov eax, pthis
|
||||
fld tbyte ptr [eax]
|
||||
fistp qword ptr res
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long long ld_readull(const longdouble* pthis)
|
||||
{
|
||||
#if 1
|
||||
// somehow the FPU does not respect the CHOP mode of the rounding control
|
||||
// in 64-bit mode
|
||||
// so we roll our own conversion (it also allows the usual C wrap-around
|
||||
// instead of the "invalid value" created by the FPU)
|
||||
int expo = pthis->exponent - 0x3fff;
|
||||
unsigned long long u;
|
||||
if(expo < 0 || expo > 127)
|
||||
return 0;
|
||||
if(expo < 64)
|
||||
u = pthis->mantissa >> (63 - expo);
|
||||
else
|
||||
u = pthis->mantissa << (expo - 63);
|
||||
if(pthis->sign)
|
||||
u = ~u + 1;
|
||||
return u;
|
||||
#else
|
||||
longdouble* pthis = this;
|
||||
long long res; // cannot use unsigned, VC will not generate "fistp qword"
|
||||
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
|
||||
__asm
|
||||
{
|
||||
mov eax, pthis
|
||||
fld tbyte ptr [eax]
|
||||
fld tbyte ptr twoPow63
|
||||
fsubp ST(1),ST(0) // move it into signed range
|
||||
|
||||
lea eax, res
|
||||
fistp qword ptr [eax]
|
||||
}
|
||||
res ^= (1LL << 63);
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ld_set(longdouble* pthis, double d)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, pthis
|
||||
fld d
|
||||
fstp tbyte ptr [eax]
|
||||
}
|
||||
}
|
||||
void ld_setll(longdouble* pthis, long long d)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
fild qword ptr d
|
||||
mov eax, pthis
|
||||
fstp tbyte ptr [eax]
|
||||
}
|
||||
}
|
||||
void ld_setull(longdouble* pthis, unsigned long long d)
|
||||
{
|
||||
d ^= (1LL << 63);
|
||||
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
|
||||
__asm
|
||||
{
|
||||
fild qword ptr d
|
||||
fld tbyte ptr twoPow63
|
||||
faddp ST(1),ST(0)
|
||||
mov eax, pthis
|
||||
fstp tbyte ptr [eax]
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
#endif // !_WIN64
|
||||
|
||||
longdouble ldexpl(longdouble ld, int exp)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
ld_expl(&ld, exp);
|
||||
#else
|
||||
__asm
|
||||
{
|
||||
fild dword ptr exp
|
||||
fld tbyte ptr ld
|
||||
fscale // ST(0) = ST(0) * (2**ST(1))
|
||||
fstp ST(1)
|
||||
fstp tbyte ptr ld
|
||||
}
|
||||
#endif
|
||||
return ld;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
longdouble operator+(longdouble ld1, longdouble ld2)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_add(ld1, ld2);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld1
|
||||
fld tbyte ptr ld2
|
||||
fadd
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
longdouble operator-(longdouble ld1, longdouble ld2)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_sub(ld1, ld2);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld1
|
||||
fld tbyte ptr ld2
|
||||
fsub
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
longdouble operator*(longdouble ld1, longdouble ld2)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_mul(ld1, ld2);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld1
|
||||
fld tbyte ptr ld2
|
||||
fmul
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
longdouble operator/(longdouble ld1, longdouble ld2)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_div(ld1, ld2);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld1
|
||||
fld tbyte ptr ld2
|
||||
fdiv
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator< (longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cmpb(x, y);
|
||||
#else
|
||||
short sw;
|
||||
bool res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
fucomip ST(0),ST(1)
|
||||
setb AL
|
||||
setnp AH
|
||||
and AL,AH
|
||||
mov res,AL
|
||||
fstp ST(0)
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
bool operator<=(longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cmpbe(x, y);
|
||||
#else
|
||||
short sw;
|
||||
bool res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
fucomip ST(0),ST(1)
|
||||
setbe AL
|
||||
setnp AH
|
||||
and AL,AH
|
||||
mov res,AL
|
||||
fstp ST(0)
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
bool operator> (longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cmpa(x, y);
|
||||
#else
|
||||
short sw;
|
||||
bool res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
fucomip ST(0),ST(1)
|
||||
seta AL
|
||||
setnp AH
|
||||
and AL,AH
|
||||
mov res,AL
|
||||
fstp ST(0)
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
bool operator>=(longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cmpae(x, y);
|
||||
#else
|
||||
short sw;
|
||||
bool res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
fucomip ST(0),ST(1)
|
||||
setae AL
|
||||
setnp AH
|
||||
and AL,AH
|
||||
mov res,AL
|
||||
fstp ST(0)
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
bool operator==(longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cmpe(x, y);
|
||||
#else
|
||||
short sw;
|
||||
bool res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
fucomip ST(0),ST(1)
|
||||
sete AL
|
||||
setnp AH
|
||||
and AL,AH
|
||||
mov res,AL
|
||||
fstp ST(0)
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
bool operator!=(longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cmpne(x, y);
|
||||
#else
|
||||
short sw;
|
||||
bool res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
fucomip ST(0),ST(1)
|
||||
setne AL
|
||||
setp AH
|
||||
or AL,AH
|
||||
mov res,AL
|
||||
fstp ST(0)
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int _isnan(longdouble ld)
|
||||
{
|
||||
return (ld.exponent == 0x7fff && ld.mantissa != 0);
|
||||
}
|
||||
|
||||
longdouble fabsl(longdouble ld)
|
||||
{
|
||||
ld.sign = 0;
|
||||
return ld;
|
||||
}
|
||||
|
||||
longdouble sqrtl(longdouble ld)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_sqrt(ld);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld;
|
||||
fsqrt;
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
longdouble sinl (longdouble ld)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_sin(ld);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld;
|
||||
fsin; // exact for |x|<=PI/4
|
||||
fstp tbyte ptr res
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
longdouble cosl (longdouble ld)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_cos(ld);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld;
|
||||
fcos; // exact for |x|<=PI/4
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
longdouble tanl (longdouble ld)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_tan(ld);
|
||||
#else
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr ld;
|
||||
fptan;
|
||||
fstp ST(0); // always 1
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
longdouble fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return ld_mod(x, y);
|
||||
#else
|
||||
short sw;
|
||||
longdouble res;
|
||||
__asm
|
||||
{
|
||||
fld tbyte ptr y
|
||||
fld tbyte ptr x // ST = x, ST1 = y
|
||||
FM1: // We don't use fprem1 because for some inexplicable
|
||||
// reason we get -5 when we do _modulo(15, 10)
|
||||
fprem // ST = ST % ST1
|
||||
fstsw word ptr sw
|
||||
fwait
|
||||
mov AH,byte ptr sw+1 // get msb of status word in AH
|
||||
sahf // transfer to flags
|
||||
jp FM1 // continue till ST < ST1
|
||||
fstp ST(1) // leave remainder on stack
|
||||
fstp tbyte ptr res;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 };
|
||||
longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 };
|
||||
|
||||
longdouble ld_zero = { 0, 0, 0 };
|
||||
longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 };
|
||||
longdouble ld_pi = { 0xc90fdaa22168c235ULL, 0x4000, 0 };
|
||||
longdouble ld_log2t = { 0xd49a784bcd1b8afeULL, 0x4000, 0 };
|
||||
longdouble ld_log2e = { 0xb8aa3b295c17f0bcULL, 0x3fff, 0 };
|
||||
longdouble ld_log2 = { 0x9a209a84fbcff799ULL, 0x3ffd, 0 };
|
||||
longdouble ld_ln2 = { 0xb17217f7d1cf79acULL, 0x3ffe, 0 };
|
||||
|
||||
longdouble ld_pi2 = ld_pi*2;
|
||||
longdouble ld_piOver2 = ld_pi*0.5;
|
||||
longdouble ld_piOver4 = ld_pi*0.25;
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
#define LD_TYPE_OTHER 0
|
||||
#define LD_TYPE_ZERO 1
|
||||
#define LD_TYPE_INFINITE 2
|
||||
#define LD_TYPE_SNAN 3
|
||||
#define LD_TYPE_QNAN 4
|
||||
|
||||
int ld_type(longdouble x)
|
||||
{
|
||||
if(x.exponent == 0)
|
||||
return x.mantissa == 0 ? LD_TYPE_ZERO : LD_TYPE_OTHER; // dnormal if not zero
|
||||
if(x.exponent != 0x7fff)
|
||||
return LD_TYPE_OTHER;
|
||||
if(x.mantissa == 0)
|
||||
return LD_TYPE_INFINITE;
|
||||
if(x.mantissa & (1LL << 63))
|
||||
return LD_TYPE_QNAN;
|
||||
return LD_TYPE_SNAN;
|
||||
}
|
||||
|
||||
int ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
// fmt is 'a','A','f' or 'g'
|
||||
if(fmt != 'a' && fmt != 'A')
|
||||
{
|
||||
char format[] = { '%', fmt, 0 };
|
||||
return sprintf(str, format, ld_read(&x));
|
||||
}
|
||||
|
||||
unsigned short exp = x.exponent;
|
||||
unsigned long long mantissa = x.mantissa;
|
||||
|
||||
switch(ld_type(x))
|
||||
{
|
||||
case LD_TYPE_ZERO:
|
||||
return sprintf(str, "0x0.0L");
|
||||
case LD_TYPE_QNAN:
|
||||
case LD_TYPE_SNAN:
|
||||
return sprintf(str, "NAN");
|
||||
case LD_TYPE_INFINITE:
|
||||
return sprintf(str, x.sign ? "-INF" : "INF");
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
if(x.sign)
|
||||
str[len++] = '-';
|
||||
len += sprintf(str + len, mantissa & (1LL << 63) ? "0x1." : "0x0.");
|
||||
mantissa = mantissa << 1;
|
||||
while(mantissa)
|
||||
{
|
||||
int dig = (mantissa >> 60) & 0xf;
|
||||
dig += dig < 10 ? '0' : fmt - 10;
|
||||
str[len++] = dig;
|
||||
mantissa = mantissa << 4;
|
||||
}
|
||||
str[len++] = 'p';
|
||||
if(exp < 0x3fff)
|
||||
{
|
||||
str[len++] = '-';
|
||||
exp = 0x3fff - exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
str[len++] = '+';
|
||||
exp = exp - 0x3fff;
|
||||
}
|
||||
int exppos = len;
|
||||
for(int i = 12; i >= 0; i -= 4)
|
||||
{
|
||||
int dig = (exp >> i) & 0xf;
|
||||
if(dig != 0 || len > exppos || i == 0)
|
||||
str[len++] = dig + (dig < 10 ? '0' : fmt - 10);
|
||||
}
|
||||
str[len] = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
#if UNITTEST
|
||||
static bool unittest()
|
||||
{
|
||||
char buffer[32];
|
||||
ld_sprint(buffer, 'a', ld_pi);
|
||||
assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0);
|
||||
|
||||
longdouble ldb = ldouble(0.4);
|
||||
long long b = ldb;
|
||||
assert(b == 0);
|
||||
|
||||
b = ldouble(0.9);
|
||||
assert(b == 0);
|
||||
|
||||
long long x = 0x12345678abcdef78LL;
|
||||
longdouble ldx = ldouble(x);
|
||||
assert(ldx > 0);
|
||||
long long y = ldx;
|
||||
assert(x == y);
|
||||
|
||||
x = -0x12345678abcdef78LL;
|
||||
ldx = ldouble(x);
|
||||
assert(ldx < 0);
|
||||
y = ldx;
|
||||
assert(x == y);
|
||||
|
||||
unsigned long long u = 0x12345678abcdef78LL;
|
||||
longdouble ldu = ldouble(u);
|
||||
assert(ldu > 0);
|
||||
unsigned long long v = ldu;
|
||||
assert(u == v);
|
||||
|
||||
u = 0xf234567812345678ULL;
|
||||
ldu = ldouble(u);
|
||||
assert(ldu > 0);
|
||||
v = ldu;
|
||||
assert(u == v);
|
||||
|
||||
u = 0xf2345678;
|
||||
ldu = ldouble(u);
|
||||
ldu = ldu * ldu;
|
||||
ldu = sqrt(ldu);
|
||||
v = ldu;
|
||||
assert(u == v);
|
||||
|
||||
u = 0x123456789A;
|
||||
ldu = ldouble(u);
|
||||
ldu = ldu * (1LL << 23);
|
||||
v = ldu;
|
||||
u = u * (1LL << 23);
|
||||
assert(u == v);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool runUnittest = unittest();
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
254
dmd/root/longdouble.h
Normal file
254
dmd/root/longdouble.h
Normal file
@@ -0,0 +1,254 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Rainer Schuetze
|
||||
// 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.
|
||||
|
||||
// 80 bit floating point value implementation for Microsoft compiler
|
||||
|
||||
#ifndef __LONG_DOUBLE_H__
|
||||
#define __LONG_DOUBLE_H__
|
||||
|
||||
#if IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
typedef real_t longdouble;
|
||||
|
||||
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||
inline int ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
if(fmt == 'a' || fmt == 'A')
|
||||
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
|
||||
return x.format(buffer, 46);
|
||||
}
|
||||
|
||||
#elif !_MSC_VER // has native 10 byte doubles
|
||||
#include <stdio.h>
|
||||
typedef long double longdouble;
|
||||
typedef volatile long double volatile_longdouble;
|
||||
|
||||
// also used from within C code, so use a #define rather than a template
|
||||
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||
#define ldouble(x) ((longdouble)(x))
|
||||
|
||||
inline int ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
char sfmt[4] = "%Lg";
|
||||
sfmt[2] = fmt;
|
||||
return sprintf(str, sfmt, x);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
|
||||
struct longdouble;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// implemented in ldfpu.asm for _WIN64
|
||||
double ld_read(const longdouble* ld);
|
||||
long long ld_readll(const longdouble* ld);
|
||||
unsigned long long ld_readull(const longdouble* ld);
|
||||
void ld_set(longdouble* ld, double d);
|
||||
void ld_setll(longdouble* ld, long long d);
|
||||
void ld_setull(longdouble* ld, unsigned long long d);
|
||||
}
|
||||
|
||||
struct longdouble
|
||||
{
|
||||
unsigned long long mantissa;
|
||||
unsigned short exponent:15; // bias 0x3fff
|
||||
unsigned short sign:1;
|
||||
unsigned short fill:16; // for 12 byte alignment
|
||||
|
||||
// no constructor to be able to use this class in a union
|
||||
// use ldouble() to explicitely create a longdouble value
|
||||
|
||||
template<typename T> longdouble& operator=(T x) { set(x); return *this; }
|
||||
|
||||
void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; }
|
||||
|
||||
// we need to list all basic types to avoid ambiguities
|
||||
void set(float d) { ld_set(this, d); }
|
||||
void set(double d) { ld_set(this, d); }
|
||||
void set(long double d) { ld_set(this, d); }
|
||||
|
||||
void set(signed char d) { ld_set(this, d); }
|
||||
void set(short d) { ld_set(this, d); }
|
||||
void set(int d) { ld_set(this, d); }
|
||||
void set(long d) { ld_set(this, d); }
|
||||
void set(long long d) { ld_setll(this, d); }
|
||||
|
||||
void set(unsigned char d) { ld_set(this, d); }
|
||||
void set(unsigned short d) { ld_set(this, d); }
|
||||
void set(unsigned int d) { ld_set(this, d); }
|
||||
void set(unsigned long d) { ld_set(this, d); }
|
||||
void set(unsigned long long d) { ld_setull(this, d); }
|
||||
void set(bool d) { ld_set(this, d); }
|
||||
|
||||
operator float () { return ld_read(this); }
|
||||
operator double () { return ld_read(this); }
|
||||
|
||||
operator signed char () { return ld_read(this); }
|
||||
operator short () { return ld_read(this); }
|
||||
operator int () { return ld_read(this); }
|
||||
operator long () { return ld_read(this); }
|
||||
operator long long () { return ld_readll(this); }
|
||||
|
||||
operator unsigned char () { return ld_read(this); }
|
||||
operator unsigned short () { return ld_read(this); }
|
||||
operator unsigned int () { return ld_read(this); }
|
||||
operator unsigned long () { return ld_read(this); }
|
||||
operator unsigned long long() { return ld_readull(this); }
|
||||
operator bool () { return mantissa != 0 || exponent != 0; } // correct?
|
||||
};
|
||||
|
||||
// some optimizations are avoided by adding volatile to the longdouble
|
||||
// type, but this introduces bad ambiguities when using the class implementation above
|
||||
// as we are going through asm these optimizations won't kick in anyway, so "volatile"
|
||||
// is not required.
|
||||
typedef longdouble volatile_longdouble;
|
||||
|
||||
inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
|
||||
{
|
||||
longdouble d;
|
||||
d.mantissa = mantissa;
|
||||
d.exponent = exp;
|
||||
d.sign = sign;
|
||||
return d;
|
||||
}
|
||||
template<typename T> inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
|
||||
//template<typename T> inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; }
|
||||
|
||||
longdouble operator+(longdouble ld1, longdouble ld2);
|
||||
longdouble operator-(longdouble ld1, longdouble ld2);
|
||||
longdouble operator*(longdouble ld1, longdouble ld2);
|
||||
longdouble operator/(longdouble ld1, longdouble ld2);
|
||||
|
||||
bool operator< (longdouble ld1, longdouble ld2);
|
||||
bool operator<=(longdouble ld1, longdouble ld2);
|
||||
bool operator> (longdouble ld1, longdouble ld2);
|
||||
bool operator>=(longdouble ld1, longdouble ld2);
|
||||
bool operator==(longdouble ld1, longdouble ld2);
|
||||
bool operator!=(longdouble ld1, longdouble ld2);
|
||||
|
||||
inline longdouble operator-(longdouble ld1) { ld1.sign ^= 1; return ld1; }
|
||||
inline longdouble operator+(longdouble ld1) { return ld1; }
|
||||
|
||||
template<typename T> inline longdouble operator+(longdouble ld, T x) { return ld + ldouble(x); }
|
||||
template<typename T> inline longdouble operator-(longdouble ld, T x) { return ld - ldouble(x); }
|
||||
template<typename T> inline longdouble operator*(longdouble ld, T x) { return ld * ldouble(x); }
|
||||
template<typename T> inline longdouble operator/(longdouble ld, T x) { return ld / ldouble(x); }
|
||||
|
||||
template<typename T> inline longdouble operator+(T x, longdouble ld) { return ldouble(x) + ld; }
|
||||
template<typename T> inline longdouble operator-(T x, longdouble ld) { return ldouble(x) - ld; }
|
||||
template<typename T> inline longdouble operator*(T x, longdouble ld) { return ldouble(x) * ld; }
|
||||
template<typename T> inline longdouble operator/(T x, longdouble ld) { return ldouble(x) / ld; }
|
||||
|
||||
template<typename T> inline longdouble& operator+=(longdouble& ld, T x) { return ld = ld + x; }
|
||||
template<typename T> inline longdouble& operator-=(longdouble& ld, T x) { return ld = ld - x; }
|
||||
template<typename T> inline longdouble& operator*=(longdouble& ld, T x) { return ld = ld * x; }
|
||||
template<typename T> inline longdouble& operator/=(longdouble& ld, T x) { return ld = ld / x; }
|
||||
|
||||
template<typename T> inline bool operator< (longdouble ld, T x) { return ld < ldouble(x); }
|
||||
template<typename T> inline bool operator<=(longdouble ld, T x) { return ld <= ldouble(x); }
|
||||
template<typename T> inline bool operator> (longdouble ld, T x) { return ld > ldouble(x); }
|
||||
template<typename T> inline bool operator>=(longdouble ld, T x) { return ld >= ldouble(x); }
|
||||
template<typename T> inline bool operator==(longdouble ld, T x) { return ld == ldouble(x); }
|
||||
template<typename T> inline bool operator!=(longdouble ld, T x) { return ld != ldouble(x); }
|
||||
|
||||
template<typename T> inline bool operator< (T x, longdouble ld) { return ldouble(x) < ld; }
|
||||
template<typename T> inline bool operator<=(T x, longdouble ld) { return ldouble(x) <= ld; }
|
||||
template<typename T> inline bool operator> (T x, longdouble ld) { return ldouble(x) > ld; }
|
||||
template<typename T> inline bool operator>=(T x, longdouble ld) { return ldouble(x) >= ld; }
|
||||
template<typename T> inline bool operator==(T x, longdouble ld) { return ldouble(x) == ld; }
|
||||
template<typename T> inline bool operator!=(T x, longdouble ld) { return ldouble(x) != ld; }
|
||||
|
||||
int _isnan(longdouble ld);
|
||||
|
||||
longdouble fabsl(longdouble ld);
|
||||
longdouble sqrtl(longdouble ld);
|
||||
longdouble sinl (longdouble ld);
|
||||
longdouble cosl (longdouble ld);
|
||||
longdouble tanl (longdouble ld);
|
||||
|
||||
longdouble fmodl(longdouble x, longdouble y);
|
||||
longdouble ldexpl(longdouble ldval, int exp); // see strtold
|
||||
|
||||
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
|
||||
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
|
||||
|
||||
#undef LDBL_DIG
|
||||
#undef LDBL_MAX
|
||||
#undef LDBL_MIN
|
||||
#undef LDBL_EPSILON
|
||||
#undef LDBL_MANT_DIG
|
||||
#undef LDBL_MAX_EXP
|
||||
#undef LDBL_MIN_EXP
|
||||
#undef LDBL_MAX_10_EXP
|
||||
#undef LDBL_MIN_10_EXP
|
||||
|
||||
#define LDBL_DIG 18
|
||||
#define LDBL_MAX ldouble(0xffffffffffffffffULL, 0x7ffe)
|
||||
#define LDBL_MIN ldouble(0x8000000000000000ULL, 1)
|
||||
#define LDBL_EPSILON ldouble(0x8000000000000000ULL, 0x3fff - 63) // allow denormal?
|
||||
#define LDBL_MANT_DIG 64
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define LDBL_MIN_EXP (-16381)
|
||||
#define LDBL_MAX_10_EXP 4932
|
||||
#define LDBL_MIN_10_EXP (-4932)
|
||||
|
||||
extern longdouble ld_zero;
|
||||
extern longdouble ld_one;
|
||||
extern longdouble ld_pi;
|
||||
extern longdouble ld_log2t;
|
||||
extern longdouble ld_log2e;
|
||||
extern longdouble ld_log2;
|
||||
extern longdouble ld_ln2;
|
||||
|
||||
extern longdouble ld_inf;
|
||||
extern longdouble ld_qnan;
|
||||
extern longdouble ld_snan;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// CLASS numeric_limits<longdouble>
|
||||
template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
|
||||
: public _Num_float_base
|
||||
{ // limits for type long double
|
||||
public:
|
||||
typedef longdouble _Ty;
|
||||
|
||||
static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; }
|
||||
static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; }
|
||||
static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; }
|
||||
static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); }
|
||||
static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); }
|
||||
static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; }
|
||||
static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; }
|
||||
static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; }
|
||||
|
||||
_STCONS(int, digits, LDBL_MANT_DIG);
|
||||
_STCONS(int, digits10, LDBL_DIG);
|
||||
_STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
|
||||
_STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
|
||||
_STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
|
||||
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
|
||||
};
|
||||
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
|
||||
|
||||
int ld_sprint(char* str, int fmt, longdouble x);
|
||||
|
||||
#endif // !_MSC_VER
|
||||
|
||||
#endif // __LONG_DOUBLE_H__
|
||||
@@ -1,63 +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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -1,72 +1,74 @@
|
||||
|
||||
// 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
|
||||
|
||||
// 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;
|
||||
|
||||
#ifndef IN_GCC
|
||||
// Disable warning about nonstandard extension
|
||||
#pragma warning (disable : 4200)
|
||||
#endif
|
||||
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
|
||||
|
||||
200
dmd/root/man.c
200
dmd/root/man.c
@@ -1,100 +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
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
|
||||
1451
dmd/root/port.c
1451
dmd/root/port.c
File diff suppressed because it is too large
Load Diff
164
dmd/root/port.h
164
dmd/root/port.h
@@ -1,81 +1,83 @@
|
||||
|
||||
// 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 __OpenBSD__
|
||||
#elif __GNUC__ && !defined __HAIKU__
|
||||
// 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
|
||||
|
||||
// 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.
|
||||
|
||||
#include "longdouble.h"
|
||||
|
||||
#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
|
||||
longdouble strtold(const char *p,char **endp);
|
||||
#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 longdouble ldbl_max;
|
||||
|
||||
#if __OpenBSD__
|
||||
#elif __GNUC__ && !defined __HAIKU__
|
||||
// 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(longdouble);
|
||||
|
||||
static int isSignallingNan(double);
|
||||
static int isSignallingNan(longdouble);
|
||||
|
||||
static int isFinite(double);
|
||||
static int isInfinity(double);
|
||||
static int Signbit(double);
|
||||
|
||||
static double floor(double);
|
||||
static double pow(double x, double y);
|
||||
|
||||
static longdouble fmodl(longdouble x, longdouble 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -8,7 +8,7 @@
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef POSIX
|
||||
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
|
||||
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -35,7 +35,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <iostream>
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#if POSIX
|
||||
@@ -364,21 +364,21 @@ FileName::FileName(char *path, char *name)
|
||||
}
|
||||
|
||||
// Split a path into an Array of paths
|
||||
Strings *FileName::splitPath(const char *path)
|
||||
Strings *FileName::splitPath(const char *path)
|
||||
{
|
||||
char c = 0; // unnecessary initializer is for VC /W4
|
||||
const char *p;
|
||||
OutBuffer buf;
|
||||
Strings *array;
|
||||
Strings *array;
|
||||
|
||||
array = new Strings();
|
||||
array = new Strings();
|
||||
if (path)
|
||||
{
|
||||
p = path;
|
||||
do
|
||||
{ char instring = 0;
|
||||
|
||||
while (isspace((unsigned char)*p)) // skip leading whitespace
|
||||
while (isspace((unsigned char)*p)) // skip leading whitespace
|
||||
p++;
|
||||
buf.reserve(strlen(p) + 1); // guess size of path
|
||||
// LDC remember first character
|
||||
@@ -799,7 +799,7 @@ void FileName::CopyTo(FileName *to)
|
||||
* cwd if !=0, search current directory before searching path
|
||||
*/
|
||||
|
||||
char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||
char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||
{
|
||||
if (absolute(name))
|
||||
{
|
||||
@@ -815,7 +815,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||
|
||||
for (i = 0; i < path->dim; i++)
|
||||
{
|
||||
char *p = path->tdata()[i];
|
||||
char *p = path->tdata()[i];
|
||||
char *n = combine(p, name);
|
||||
|
||||
if (exists(n))
|
||||
@@ -839,7 +839,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||
* !=NULL mem.malloc'd file name
|
||||
*/
|
||||
|
||||
char *FileName::safeSearchPath(Strings *path, const char *name)
|
||||
char *FileName::safeSearchPath(Strings *path, const char *name)
|
||||
{
|
||||
#if _WIN32
|
||||
/* Disallow % / \ : and .. in name characters
|
||||
@@ -876,7 +876,7 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
|
||||
for (i = 0; i < path->dim; i++)
|
||||
{
|
||||
char *cname = NULL;
|
||||
char *cpath = canonicalName(path->tdata()[i]);
|
||||
char *cpath = canonicalName(path->tdata()[i]);
|
||||
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
|
||||
// name, (char *)path->data[i], cpath);
|
||||
if (cpath == NULL)
|
||||
@@ -966,7 +966,7 @@ void FileName::ensurePathExists(const char *path)
|
||||
{
|
||||
//printf("mkdir(%s)\n", path);
|
||||
#if _WIN32
|
||||
if (_mkdir(path))
|
||||
if (_mkdir(path))
|
||||
#endif
|
||||
#if POSIX
|
||||
if (mkdir(path, 0777))
|
||||
@@ -1088,13 +1088,13 @@ int File::read()
|
||||
//printf("File::read('%s')\n",name);
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
{
|
||||
//printf("\topen error, errno = %d\n",errno);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (!ref)
|
||||
::free(buffer);
|
||||
::free(buffer);
|
||||
ref = 0; // we own the buffer now
|
||||
|
||||
//printf("\tfile opened\n");
|
||||
@@ -1104,7 +1104,7 @@ int File::read()
|
||||
goto err2;
|
||||
}
|
||||
size = buf.st_size;
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
if (!buffer)
|
||||
{
|
||||
printf("\tmalloc error, errno = %d\n",errno);
|
||||
@@ -1137,7 +1137,7 @@ int File::read()
|
||||
err2:
|
||||
close(fd);
|
||||
err:
|
||||
::free(buffer);
|
||||
::free(buffer);
|
||||
buffer = NULL;
|
||||
len = 0;
|
||||
|
||||
@@ -1158,11 +1158,11 @@ err1:
|
||||
goto err1;
|
||||
|
||||
if (!ref)
|
||||
::free(buffer);
|
||||
::free(buffer);
|
||||
ref = 0;
|
||||
|
||||
size = GetFileSize(h,NULL);
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
if (!buffer)
|
||||
goto err2;
|
||||
|
||||
@@ -1191,7 +1191,7 @@ err1:
|
||||
err2:
|
||||
CloseHandle(h);
|
||||
err:
|
||||
::free(buffer);
|
||||
::free(buffer);
|
||||
buffer = NULL;
|
||||
len = 0;
|
||||
|
||||
@@ -1454,23 +1454,23 @@ void File::remove()
|
||||
#endif
|
||||
}
|
||||
|
||||
Files *File::match(char *n)
|
||||
Files *File::match(char *n)
|
||||
{
|
||||
return match(new FileName(n, 0));
|
||||
}
|
||||
|
||||
Files *File::match(FileName *n)
|
||||
Files *File::match(FileName *n)
|
||||
{
|
||||
#if POSIX
|
||||
return NULL;
|
||||
#elif _WIN32
|
||||
HANDLE h;
|
||||
WIN32_FIND_DATAA fileinfo;
|
||||
Files *a;
|
||||
Files *a;
|
||||
char *c;
|
||||
char *name;
|
||||
|
||||
a = new Files();
|
||||
a = new Files();
|
||||
c = n->toChars();
|
||||
name = n->name();
|
||||
h = FindFirstFileA(c,&fileinfo);
|
||||
@@ -1540,7 +1540,7 @@ void File::stat()
|
||||
void File::checkoffset(size_t offset, size_t nbytes)
|
||||
{
|
||||
if (offset > len || offset + nbytes > len)
|
||||
error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
|
||||
error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset);
|
||||
}
|
||||
|
||||
char *File::toChars()
|
||||
@@ -1563,11 +1563,11 @@ OutBuffer::~OutBuffer()
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
char *OutBuffer::extractData()
|
||||
char *OutBuffer::extractData()
|
||||
{
|
||||
char *p;
|
||||
char *p;
|
||||
|
||||
p = (char *)data;
|
||||
p = (char *)data;
|
||||
data = NULL;
|
||||
offset = 0;
|
||||
size = 0;
|
||||
@@ -1813,7 +1813,7 @@ void OutBuffer::align(unsigned size)
|
||||
// The compiler shipped with Visual Studio 2005 (and possible
|
||||
// other versions) does not support C99 printf format specfiers
|
||||
// such as %z and %j
|
||||
#if _MSC_VER || __MINGW32__
|
||||
#if 0 && _MSC_VER
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
@@ -1832,7 +1832,7 @@ search_and_replace(S& str, const S& what, const S& replacement)
|
||||
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
|
||||
S tmp = f; \
|
||||
search_and_replace(fmt, S("%z"), S("%l")); \
|
||||
search_and_replace(fmt, S("%j"), S("%i")); \
|
||||
search_and_replace(fmt, S("%j"), S("%l")); \
|
||||
f = tmp.c_str();
|
||||
#else
|
||||
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
|
||||
|
||||
853
dmd/root/root.h
853
dmd/root/root.h
@@ -1,425 +1,428 @@
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef IS_PRINTF
|
||||
# ifdef __GNUC__
|
||||
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
|
||||
# else
|
||||
# define IS_PRINTF(FMTARG)
|
||||
# endif
|
||||
#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, ...) IS_PRINTF(1);
|
||||
void error(const wchar_t *format, ...);
|
||||
void warning(const char *format, ...) IS_PRINTF(1);
|
||||
|
||||
#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, ...) IS_PRINTF(2);
|
||||
#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
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef IS_PRINTF
|
||||
# ifdef __GNUC__
|
||||
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
|
||||
# else
|
||||
# define IS_PRINTF(FMTARG)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef size_t hash_t;
|
||||
|
||||
#include "longdouble.h"
|
||||
#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, ...) IS_PRINTF(1);
|
||||
#if M_UNICODE
|
||||
void error(const dchar *format, ...);
|
||||
#endif
|
||||
void warning(const char *format, ...) IS_PRINTF(1);
|
||||
|
||||
#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
|
||||
longdouble strtold(const char *p,char **endp);
|
||||
#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, ...) IS_PRINTF(2);
|
||||
#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
|
||||
|
||||
@@ -1,139 +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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,48 +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
|
||||
// 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
|
||||
|
||||
@@ -78,7 +78,6 @@ Scope::Scope()
|
||||
this->parameterSpecialization = 0;
|
||||
this->callSuper = 0;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = NULL;
|
||||
@@ -127,7 +126,6 @@ Scope::Scope(Scope *enclosing)
|
||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||
this->callSuper = enclosing->callSuper;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = enclosing->docbuf;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -64,6 +64,10 @@ struct Scope
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||
unsigned offset; // next offset to use in aggregate
|
||||
// This really shouldn't be a part of Scope, because it requires
|
||||
// semantic() to be done in the lexical field order. It should be
|
||||
// set in a pass after semantic() on all fields so they can be
|
||||
// semantic'd in any order.
|
||||
int inunion; // we're processing members of a union
|
||||
int incontract; // we're inside contract code
|
||||
int nofree; // set if shouldn't free it
|
||||
@@ -95,7 +99,6 @@ struct Scope
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||
|
||||
@@ -4,9 +4,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if __sun&&__SVR4
|
||||
#if __sun&&__SVR4 || _MSC_VER
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#if _MSC_VER
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "speller.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -1441,7 +1441,13 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
s =((ScopeExp *)e)->sds;
|
||||
|
||||
if (s)
|
||||
{
|
||||
var = new AliasDeclaration(loc, arg->ident, s);
|
||||
}
|
||||
else if (e->op == TOKtype)
|
||||
{
|
||||
var = new AliasDeclaration(loc, arg->ident, e->type);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg->type = e->type;
|
||||
@@ -3783,6 +3789,8 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
||||
{
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
if (exp->op == TOKerror)
|
||||
goto Lbody;
|
||||
ClassDeclaration *cd = exp->type->isClassHandle();
|
||||
if (!cd)
|
||||
error("can only synchronize on class objects, not '%s'", exp->type->toChars());
|
||||
@@ -3797,6 +3805,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
||||
exp = exp->semantic(sc);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* Rewrite as:
|
||||
* auto tmp = exp;
|
||||
* _d_monitorenter(tmp);
|
||||
@@ -3827,7 +3836,9 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
||||
|
||||
s = new CompoundStatement(loc, cs);
|
||||
return s->semantic(sc);
|
||||
#endif
|
||||
}
|
||||
#if 1
|
||||
else
|
||||
{ /* Generate our own critical section, then rewrite as:
|
||||
* __gshared byte[CriticalSection.sizeof] critsec;
|
||||
@@ -3869,6 +3880,11 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
||||
s = new CompoundStatement(loc, cs);
|
||||
return s->semantic(sc);
|
||||
}
|
||||
#endif
|
||||
Lbody:
|
||||
if (body)
|
||||
body = body->semantic(sc);
|
||||
return this;
|
||||
}
|
||||
|
||||
int SynchronizedStatement::hasBreak()
|
||||
@@ -4141,7 +4157,9 @@ Catch *Catch::syntaxCopy()
|
||||
}
|
||||
|
||||
void Catch::semantic(Scope *sc)
|
||||
{ ScopeDsymbol *sym;
|
||||
{
|
||||
if (type && type->deco)
|
||||
return;
|
||||
|
||||
//printf("Catch::semantic(%s)\n", ident->toChars());
|
||||
|
||||
@@ -4158,7 +4176,7 @@ void Catch::semantic(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
|
||||
sym = new ScopeDsymbol();
|
||||
ScopeDsymbol *sym = new ScopeDsymbol();
|
||||
sym->parent = sc->scopesym;
|
||||
sc = sc->push(sym);
|
||||
|
||||
|
||||
188
dmd/struct.c
188
dmd/struct.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -36,7 +36,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
alignsize = 0; // size of struct for alignment purposes
|
||||
structalign = 0; // struct member alignment in effect
|
||||
hasUnions = 0;
|
||||
sizeok = 0; // size not determined yet
|
||||
sizeok = SIZEOKnone; // size not determined yet
|
||||
isdeprecated = 0;
|
||||
inv = NULL;
|
||||
aggNew = NULL;
|
||||
@@ -123,9 +123,9 @@ unsigned AggregateDeclaration::size(Loc loc)
|
||||
//printf("AggregateDeclaration::size() = %d\n", structsize);
|
||||
if (!members)
|
||||
error(loc, "unknown size");
|
||||
if (sizeok != 1 && scope)
|
||||
if (sizeok != SIZEOKdone && scope)
|
||||
semantic(NULL);
|
||||
if (sizeok != 1)
|
||||
if (sizeok != SIZEOKdone)
|
||||
{ error(loc, "no size yet for forward reference");
|
||||
//*(char*)0=0;
|
||||
}
|
||||
@@ -169,73 +169,41 @@ void AggregateDeclaration::alignmember(
|
||||
//printf("result = %d\n", *poffset);
|
||||
}
|
||||
|
||||
|
||||
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
||||
/****************************************
|
||||
* Place a member (mem) into an aggregate (agg), which can be a struct, union or class
|
||||
* Returns:
|
||||
* offset to place field at
|
||||
*/
|
||||
unsigned AggregateDeclaration::placeField(
|
||||
unsigned *nextoffset, // next location in aggregate
|
||||
unsigned memsize, // size of member
|
||||
unsigned memalignsize, // size of member for alignment purposes
|
||||
unsigned memalign, // alignment in effect for this member
|
||||
unsigned *paggsize, // size of aggregate (updated)
|
||||
unsigned *paggalignsize, // size of aggregate for alignment purposes (updated)
|
||||
bool isunion // the aggregate is a union
|
||||
)
|
||||
{
|
||||
unsigned memsize; // size of member
|
||||
unsigned memalignsize; // size of member for alignment purposes
|
||||
unsigned xalign; // alignment boundaries
|
||||
|
||||
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
|
||||
|
||||
// Check for forward referenced types which will fail the size() call
|
||||
Type *t = v->type->toBasetype();
|
||||
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
|
||||
{ TypeStruct *ts = (TypeStruct *)t;
|
||||
#if DMDV2
|
||||
if (ts->sym == this)
|
||||
{
|
||||
error("cannot have field %s with same struct type", v->toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ts->sym->sizeok != 1 && ts->sym->scope)
|
||||
ts->sym->semantic(NULL);
|
||||
if (ts->sym->sizeok != 1)
|
||||
{
|
||||
sizeok = 2; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (t->ty == Tident)
|
||||
{
|
||||
sizeok = 2; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
|
||||
memsize = v->type->size(loc);
|
||||
memalignsize = v->type->alignsize();
|
||||
xalign = v->type->memalign(sc->structalign);
|
||||
#if 0
|
||||
alignmember(xalign, memalignsize, &sc->offset);
|
||||
v->offset = sc->offset;
|
||||
sc->offset += memsize;
|
||||
if (sc->offset > structsize)
|
||||
structsize = sc->offset;
|
||||
#else
|
||||
unsigned ofs = sc->offset;
|
||||
alignmember(xalign, memalignsize, &ofs);
|
||||
v->offset = ofs;
|
||||
unsigned ofs = *nextoffset;
|
||||
alignmember(memalign, memalignsize, &ofs);
|
||||
unsigned memoffset = ofs;
|
||||
ofs += memsize;
|
||||
if (ofs > structsize)
|
||||
structsize = ofs;
|
||||
if (!isUnionDeclaration())
|
||||
sc->offset = ofs;
|
||||
#endif
|
||||
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16)
|
||||
if (ofs > *paggsize)
|
||||
*paggsize = ofs;
|
||||
if (!isunion)
|
||||
*nextoffset = ofs;
|
||||
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
|
||||
/* Not sure how to handle this */
|
||||
;
|
||||
else if (sc->structalign < memalignsize)
|
||||
memalignsize = sc->structalign;
|
||||
if (alignsize < memalignsize)
|
||||
alignsize = memalignsize;
|
||||
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
|
||||
else if (memalign < memalignsize)
|
||||
memalignsize = memalign;
|
||||
if (*paggalignsize < memalignsize)
|
||||
*paggalignsize = memalignsize;
|
||||
|
||||
v->storage_class |= STCfield;
|
||||
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
|
||||
fields.push(v);
|
||||
return memoffset;
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* If field[indx] is not part of a union, return indx.
|
||||
* Otherwise, return the lowest field index of the union.
|
||||
@@ -330,7 +298,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
|
||||
if (symtab)
|
||||
{ if (sizeok == 1 || !scope)
|
||||
{ if (sizeok == SIZEOKdone || !scope)
|
||||
{ //printf("already completed\n");
|
||||
scope = NULL;
|
||||
return; // semantic() already completed
|
||||
@@ -369,7 +337,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
type = type->constOf();
|
||||
#endif
|
||||
|
||||
if (sizeok == 0) // if not already done the addMember step
|
||||
if (sizeok == SIZEOKnone) // if not already done the addMember step
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
@@ -379,7 +347,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
sizeok = 0;
|
||||
sizeok = SIZEOKnone;
|
||||
sc2 = sc->push(this);
|
||||
sc2->stc = 0;
|
||||
sc2->parent = this;
|
||||
@@ -394,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
* resolve individual members like enums.
|
||||
*/
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
/* There are problems doing this in the general case because
|
||||
* Scope keeps track of things like 'offset'
|
||||
*/
|
||||
@@ -407,8 +375,13 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
// Ungag errors when not speculative
|
||||
unsigned oldgag = global.gag;
|
||||
if (global.isSpeculativeGagging() && !isSpeculative())
|
||||
global.gag = 0;
|
||||
s->semantic(sc2);
|
||||
global.gag = oldgag;
|
||||
#if 0
|
||||
if (sizeok == 2)
|
||||
{ //printf("forward reference\n");
|
||||
@@ -416,6 +389,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
finalizeSize(sc2);
|
||||
|
||||
#if DMDV1
|
||||
/* This doesn't work for DMDV2 because (ref S) and (S) parameter
|
||||
@@ -480,44 +454,14 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
#if DMDV2
|
||||
/* Try to find the opEquals function. Build it if necessary.
|
||||
*/
|
||||
TypeFunction *tfeqptr;
|
||||
{ // bool opEquals(const T*) const;
|
||||
Parameters *parameters = new Parameters;
|
||||
#if STRUCTTHISREF
|
||||
// bool opEquals(ref const T) const;
|
||||
Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL);
|
||||
#else
|
||||
// bool opEquals(const T*) const;
|
||||
Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL);
|
||||
#endif
|
||||
|
||||
parameters->push(param);
|
||||
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
|
||||
tfeqptr->mod = MODconst;
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2);
|
||||
|
||||
Dsymbol *s = search_function(this, Id::eq);
|
||||
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{
|
||||
eq = fdx->overloadExactMatch(tfeqptr);
|
||||
if (!eq)
|
||||
fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars());
|
||||
}
|
||||
|
||||
TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL;
|
||||
// BUG: should also check that td is a function template, not just a template
|
||||
|
||||
if (!eq && !td)
|
||||
eq = buildOpEquals(sc2);
|
||||
}
|
||||
|
||||
dtor = buildDtor(sc2);
|
||||
postblit = buildPostBlit(sc2);
|
||||
cpctor = buildCpCtor(sc2);
|
||||
|
||||
buildOpAssign(sc2);
|
||||
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
|
||||
|
||||
xeq = buildXopEquals(sc2);
|
||||
#endif
|
||||
|
||||
sc2->pop();
|
||||
@@ -525,6 +469,12 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
if (sizeok == 2)
|
||||
{ // semantic() failed because of forward references.
|
||||
// Unwind what we did, and defer it for later
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{ Dsymbol *s = fields[i];
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd)
|
||||
vd->offset = 0;
|
||||
}
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
alignsize = 0;
|
||||
@@ -551,7 +501,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
// aligned properly.
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
|
||||
sizeok = 1;
|
||||
sizeok = SIZEOKdone;
|
||||
Module::dprogress++;
|
||||
|
||||
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
|
||||
@@ -613,6 +563,36 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
return ScopeDsymbol::search(loc, ident, flags);
|
||||
}
|
||||
|
||||
void StructDeclaration::finalizeSize(Scope *sc)
|
||||
{
|
||||
if (sizeok != SIZEOKnone)
|
||||
return;
|
||||
|
||||
// Set the offsets of the fields and determine the size of the struct
|
||||
unsigned offset = 0;
|
||||
bool isunion = isUnionDeclaration() != NULL;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->setFieldOffset(this, &offset, isunion);
|
||||
}
|
||||
if (sizeok == SIZEOKfwd)
|
||||
return;
|
||||
|
||||
// 0 sized struct's are set to 1 byte
|
||||
if (structsize == 0)
|
||||
{
|
||||
structsize = 1;
|
||||
alignsize = 1;
|
||||
}
|
||||
|
||||
// Round struct size up to next alignsize boundary.
|
||||
// This will ensure that arrays of structs will get their internals
|
||||
// aligned properly.
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
|
||||
sizeok = SIZEOKdone;
|
||||
}
|
||||
|
||||
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->printf("%s ", kind());
|
||||
|
||||
271
dmd/template.c
271
dmd/template.c
@@ -202,7 +202,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
||||
{
|
||||
if (sc1->scopesym == ti1)
|
||||
{
|
||||
error("recursive template expansion for template argument %s", t1->toChars());
|
||||
tempdecl->error("recursive template expansion for template argument %s", t1->toChars());
|
||||
return 1; // fake a match
|
||||
}
|
||||
}
|
||||
@@ -381,7 +381,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
|
||||
this->members = decldefs;
|
||||
this->overnext = NULL;
|
||||
this->overroot = NULL;
|
||||
this->semanticRun = 0;
|
||||
this->semanticRun = PASSinit;
|
||||
this->onemember = NULL;
|
||||
|
||||
// Compute in advance for Ddoc's use
|
||||
@@ -438,7 +438,7 @@ void TemplateDeclaration::semantic(Scope *sc)
|
||||
#endif
|
||||
if (semanticRun)
|
||||
return; // semantic() already run
|
||||
semanticRun = 1;
|
||||
semanticRun = PASSsemantic;
|
||||
|
||||
if (sc->func)
|
||||
{
|
||||
@@ -994,12 +994,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
* now form the tuple argument.
|
||||
*/
|
||||
Tuple *t = new Tuple();
|
||||
dedargs->data[parameters->dim - 1] = (void *)t;
|
||||
dedargs->tdata()[parameters->dim - 1] = t;
|
||||
|
||||
tuple_dim = nfargs - (nfparams - 1);
|
||||
t->objects.setDim(tuple_dim);
|
||||
for (size_t i = 0; i < tuple_dim; i++)
|
||||
{ Expression *farg = (Expression *)fargs->data[fptupindex + i];
|
||||
{ Expression *farg = fargs->tdata()[fptupindex + i];
|
||||
|
||||
// Check invalid arguments to detect errors early.
|
||||
if (farg->op == TOKerror || farg->type->ty == Terror)
|
||||
goto Lnomatch;
|
||||
|
||||
t->objects.data[i] = (void *)farg->type;
|
||||
}
|
||||
declareParameter(paramscope, tp, t);
|
||||
@@ -1025,7 +1030,7 @@ L2:
|
||||
{
|
||||
// Match 'ethis' to any TemplateThisParameter's
|
||||
for (size_t i = 0; i < parameters->dim; i++)
|
||||
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||
{ TemplateParameter *tp = parameters->tdata()[i];
|
||||
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
|
||||
if (ttp)
|
||||
{ MATCH m;
|
||||
@@ -1101,7 +1106,13 @@ L2:
|
||||
}
|
||||
}
|
||||
else
|
||||
{ Expression *farg = (Expression *)fargs->data[i];
|
||||
{
|
||||
Expression *farg = fargs->tdata()[i];
|
||||
|
||||
// Check invalid arguments to detect errors early.
|
||||
if (farg->op == TOKerror || farg->type->ty == Terror)
|
||||
goto Lnomatch;
|
||||
|
||||
#if 0
|
||||
printf("\tfarg->type = %s\n", farg->type->toChars());
|
||||
printf("\tfparam->type = %s\n", fparam->type->toChars());
|
||||
@@ -1121,10 +1132,34 @@ L2:
|
||||
argtype = argtype->invariantOf();
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow implicit function literals to delegate conversion
|
||||
*/
|
||||
if (farg->op == TOKfunction)
|
||||
{ FuncExp *fe = (FuncExp *)farg;
|
||||
Type *tp = fparam->type;
|
||||
Expression *e = fe->inferType(tp, 1, parameters);
|
||||
if (!e)
|
||||
goto Lvarargs;
|
||||
farg = e;
|
||||
argtype = farg->type;
|
||||
}
|
||||
|
||||
if (!(fparam->storageClass & STClazy) && argtype->ty == Tvoid)
|
||||
goto Lnomatch;
|
||||
|
||||
/* Remove top const for dynamic array types and pointer types
|
||||
*/
|
||||
if ((argtype->ty == Tarray || argtype->ty == Tpointer) &&
|
||||
!argtype->isMutable() &&
|
||||
(!(fparam->storageClass & STCref) ||
|
||||
(fparam->storageClass & STCauto) && !farg->isLvalue()))
|
||||
{
|
||||
argtype = argtype->mutableOf();
|
||||
}
|
||||
#endif
|
||||
|
||||
MATCH m;
|
||||
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
|
||||
MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
|
||||
//printf("\tdeduceType m = %d\n", m);
|
||||
|
||||
/* If no match, see if there's a conversion to a delegate
|
||||
@@ -1428,7 +1463,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
}
|
||||
printf(" fargs:\n");
|
||||
for (size_t i = 0; i < fargs->dim; i++)
|
||||
{ Expression *arg = (Expression *)fargs->data[i];
|
||||
{ Expression *arg = fargs->tdata()[i];
|
||||
printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
|
||||
//printf("\tty = %d\n", arg->type->ty);
|
||||
}
|
||||
@@ -1499,8 +1534,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
}
|
||||
if (td_ambig)
|
||||
{
|
||||
error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
||||
toChars(),
|
||||
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
||||
kind(), parent->toPrettyChars(), ident->toChars(),
|
||||
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
|
||||
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
|
||||
}
|
||||
@@ -1514,6 +1549,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
fd = ti->toAlias()->isFuncDeclaration();
|
||||
if (!fd)
|
||||
goto Lerror;
|
||||
|
||||
/* As Bugzilla 3682 shows, a template instance can be matched while instantiating
|
||||
* that same template. Thus, the function type can be incomplete. Complete it.
|
||||
*/
|
||||
{ TypeFunction *tf = (TypeFunction *)fd->type;
|
||||
assert(tf->ty == Tfunction);
|
||||
if (tf->next)
|
||||
fd->type = tf->semantic(loc, sc);
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
Lerror:
|
||||
@@ -1530,14 +1575,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
{
|
||||
if (i)
|
||||
bufa.writeByte(',');
|
||||
Object *oarg = (Object *)args->data[i];
|
||||
Object *oarg = args->tdata()[i];
|
||||
ObjectToCBuffer(&bufa, &hgs, oarg);
|
||||
}
|
||||
}
|
||||
|
||||
OutBuffer buf;
|
||||
argExpTypesToCBuffer(&buf, fargs, &hgs);
|
||||
error(loc, "cannot deduce template function from argument types !(%s)(%s)",
|
||||
if (this->overnext)
|
||||
::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)",
|
||||
kind(), parent->toPrettyChars(), ident->toChars(),
|
||||
bufa.toChars(), buf.toChars());
|
||||
else
|
||||
error("cannot deduce template function from argument types !(%s)(%s)",
|
||||
bufa.toChars(), buf.toChars());
|
||||
}
|
||||
return NULL;
|
||||
@@ -1633,7 +1683,7 @@ char *TemplateDeclaration::toChars()
|
||||
int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
|
||||
{
|
||||
for (size_t i = 0; i < parameters->dim; i++)
|
||||
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||
{ TemplateParameter *tp = parameters->tdata()[i];
|
||||
|
||||
if (tp->ident->equals(id))
|
||||
return i;
|
||||
@@ -1662,7 +1712,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
|
||||
* Foo!(int*) // template instantiation
|
||||
* Input:
|
||||
* this = int*
|
||||
* tparam = T
|
||||
* tparam = T*
|
||||
* parameters = [ T:T* ] // Array of TemplateParameter's
|
||||
* Output:
|
||||
* dedtypes = [ int ] // Array of Expression/Type's
|
||||
@@ -1696,7 +1746,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||
Loc loc;
|
||||
if (parameters->dim)
|
||||
{
|
||||
TemplateParameter *tp = (TemplateParameter *)parameters->data[0];
|
||||
TemplateParameter *tp = parameters->tdata()[0];
|
||||
loc = tp->loc;
|
||||
}
|
||||
|
||||
@@ -1708,7 +1758,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||
return deduceType(sc, tparam, parameters, dedtypes);
|
||||
}
|
||||
|
||||
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||
TemplateParameter *tp = parameters->tdata()[i];
|
||||
|
||||
// Found the corresponding parameter tp
|
||||
if (!tp->isTemplateTypeParameter())
|
||||
@@ -2840,14 +2890,14 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
|
||||
//printf("TemplateAliasParameter::matchArg()\n");
|
||||
|
||||
if (i < tiargs->dim)
|
||||
oarg = (Object *)tiargs->data[i];
|
||||
oarg = tiargs->tdata()[i];
|
||||
else
|
||||
{ // Get default argument instead
|
||||
oarg = defaultArg(loc, sc);
|
||||
if (!oarg)
|
||||
{ assert(i < dedtypes->dim);
|
||||
// It might have already been deduced
|
||||
oarg = (Object *)dedtypes->data[i];
|
||||
oarg = dedtypes->tdata()[i];
|
||||
if (!oarg)
|
||||
goto Lnomatch;
|
||||
}
|
||||
@@ -2937,7 +2987,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
|
||||
{
|
||||
s = defaultAlias->toDsymbol(sc);
|
||||
if (!s)
|
||||
error("%s is not a symbol", defaultAlias->toChars());
|
||||
error(Loc(0), "%s is not a symbol", defaultAlias->toChars());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -2986,7 +3036,13 @@ void TemplateValueParameter::declareParameter(Scope *sc)
|
||||
|
||||
void TemplateValueParameter::semantic(Scope *sc)
|
||||
{
|
||||
bool wasSame = (sparam->type == valType);
|
||||
sparam->semantic(sc);
|
||||
if (sparam->type == Type::terror && wasSame)
|
||||
{ // If sparam has a type error, avoid duplicate errors
|
||||
valType = Type::terror;
|
||||
return;
|
||||
}
|
||||
valType = valType->semantic(loc, sc);
|
||||
if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
|
||||
valType->ty != Tident)
|
||||
@@ -3344,13 +3400,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
|
||||
this->tinst = NULL;
|
||||
this->argsym = NULL;
|
||||
this->aliasdecl = NULL;
|
||||
this->semanticRun = 0;
|
||||
this->semanticRun = PASSinit;
|
||||
this->semantictiargsdone = 0;
|
||||
this->withsym = NULL;
|
||||
this->nest = 0;
|
||||
this->havetempdecl = 0;
|
||||
this->isnested = NULL;
|
||||
this->errors = 0;
|
||||
this->speculative = 0;
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -3379,13 +3434,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
|
||||
this->tinst = NULL;
|
||||
this->argsym = NULL;
|
||||
this->aliasdecl = NULL;
|
||||
this->semanticRun = 0;
|
||||
this->semanticRun = PASSinit;
|
||||
this->semantictiargsdone = 1;
|
||||
this->withsym = NULL;
|
||||
this->nest = 0;
|
||||
this->havetempdecl = 1;
|
||||
this->isnested = NULL;
|
||||
this->errors = 0;
|
||||
this->speculative = 0;
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -3463,7 +3517,7 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
// get the enclosing template instance from the scope tinst
|
||||
tinst = sc->tinst;
|
||||
|
||||
if (semanticRun != 0)
|
||||
if (semanticRun != PASSinit)
|
||||
{
|
||||
#if LOG
|
||||
printf("Recursive template expansion\n");
|
||||
@@ -3472,7 +3526,7 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
// inst = this;
|
||||
return;
|
||||
}
|
||||
semanticRun = 1;
|
||||
semanticRun = PASSsemantic;
|
||||
|
||||
// get the enclosing template instance from the scope tinst
|
||||
tinst = sc->tinst;
|
||||
@@ -3579,7 +3633,7 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
#if LOG
|
||||
printf("\tit's a match with instance %p\n", inst);
|
||||
printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun);
|
||||
#endif
|
||||
return;
|
||||
|
||||
@@ -3866,7 +3920,7 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
|
||||
target_symbol_list->remove(target_symbol_list_idx);
|
||||
}
|
||||
semanticRun = 0;
|
||||
semanticRun = PASSinit;
|
||||
inst = NULL;
|
||||
}
|
||||
}
|
||||
@@ -4208,13 +4262,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
|
||||
// Only one template, so we can give better error message
|
||||
error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
|
||||
else
|
||||
error("%s does not match any template declaration", toChars());
|
||||
::error(loc, "%s %s.%s does not match any template declaration",
|
||||
tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars());
|
||||
return NULL;
|
||||
}
|
||||
if (td_ambig)
|
||||
{
|
||||
error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
||||
toChars(),
|
||||
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
||||
td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(),
|
||||
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
|
||||
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
|
||||
}
|
||||
@@ -4275,7 +4330,12 @@ int TemplateInstance::hasNestedArgs(Objects *args)
|
||||
sa = ((VarExp *)ea)->var;
|
||||
goto Lsa;
|
||||
}
|
||||
if (ea->op == TOKfunction)
|
||||
if (ea->op == TOKthis)
|
||||
{
|
||||
sa = ((ThisExp *)ea)->var;
|
||||
goto Lsa;
|
||||
}
|
||||
if (ea->op == TOKfunction)
|
||||
{
|
||||
sa = ((FuncExp *)ea)->fd;
|
||||
goto Lsa;
|
||||
@@ -4472,16 +4532,15 @@ void TemplateInstance::declareParameters(Scope *sc)
|
||||
//printf("TemplateInstance::declareParameters()\n");
|
||||
for (size_t i = 0; i < tdtypes.dim; i++)
|
||||
{
|
||||
TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
|
||||
//Object *o = (Object *)tiargs->data[i];
|
||||
Object *o = (Object *)tdtypes.data[i]; // initializer for tp
|
||||
TemplateParameter *tp = tempdecl->parameters->tdata()[i];
|
||||
//Object *o = tiargs->tdata()[i];
|
||||
Object *o = tdtypes.tdata()[i]; // initializer for tp
|
||||
|
||||
//printf("\ttdtypes[%d] = %p\n", i, o);
|
||||
tempdecl->declareParameter(sc, tp, o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* Determine if template instance is really a template function,
|
||||
* and that template function needs to infer types from the function
|
||||
@@ -4493,6 +4552,7 @@ int TemplateInstance::needsTypeInference(Scope *sc)
|
||||
//printf("TemplateInstance::needsTypeInference() %s\n", toChars());
|
||||
if (!tempdecl)
|
||||
tempdecl = findTemplateDeclaration(sc);
|
||||
int multipleMatches = FALSE;
|
||||
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
|
||||
{
|
||||
/* If any of the overloaded template declarations need inference,
|
||||
@@ -4518,23 +4578,44 @@ int TemplateInstance::needsTypeInference(Scope *sc)
|
||||
/* Determine if the instance arguments, tiargs, are all that is necessary
|
||||
* to instantiate the template.
|
||||
*/
|
||||
TemplateTupleParameter *tp = td->isVariadic();
|
||||
//printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim);
|
||||
TypeFunction *fdtype = (TypeFunction *)fd->type;
|
||||
if (Parameter::dim(fdtype->parameters) &&
|
||||
((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim))
|
||||
return TRUE;
|
||||
if (Parameter::dim(fdtype->parameters))
|
||||
{
|
||||
TemplateParameter *tp = td->isVariadic();
|
||||
if (tp && td->parameters->dim > 1)
|
||||
return TRUE;
|
||||
|
||||
if (tiargs->dim < td->parameters->dim)
|
||||
{ // Can remain tiargs be filled by default arguments?
|
||||
for (size_t i = tiargs->dim; i < td->parameters->dim; i++)
|
||||
{ tp = (*td->parameters)[i];
|
||||
if (TemplateTypeParameter *ttp = tp->isTemplateTypeParameter())
|
||||
{ if (!ttp->defaultType)
|
||||
return TRUE;
|
||||
}
|
||||
else if (TemplateAliasParameter *tap = tp->isTemplateAliasParameter())
|
||||
{ if (!tap->defaultAlias)
|
||||
return TRUE;
|
||||
}
|
||||
else if (TemplateValueParameter *tvp = tp->isTemplateValueParameter())
|
||||
{ if (!tvp->defaultValue)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("false\n");
|
||||
return FALSE;
|
||||
return multipleMatches;
|
||||
}
|
||||
|
||||
void TemplateInstance::semantic2(Scope *sc)
|
||||
{ int i;
|
||||
|
||||
if (semanticRun >= 2)
|
||||
if (semanticRun >= PASSsemantic2)
|
||||
return;
|
||||
semanticRun = 2;
|
||||
semanticRun = PASSsemantic2;
|
||||
#if LOG
|
||||
printf("+TemplateInstance::semantic2('%s')\n", toChars());
|
||||
#endif
|
||||
@@ -4567,9 +4648,9 @@ void TemplateInstance::semantic3(Scope *sc)
|
||||
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
|
||||
#endif
|
||||
//if (toChars()[0] == 'D') *(char*)0=0;
|
||||
if (semanticRun >= 3)
|
||||
if (semanticRun >= PASSsemantic3)
|
||||
return;
|
||||
semanticRun = 3;
|
||||
semanticRun = PASSsemantic3;
|
||||
if (!errors && members)
|
||||
{
|
||||
sc = tempdecl->scope;
|
||||
@@ -4752,9 +4833,24 @@ Dsymbol *TemplateInstance::toAlias()
|
||||
printf("TemplateInstance::toAlias()\n");
|
||||
#endif
|
||||
if (!inst)
|
||||
{ error("cannot resolve forward reference");
|
||||
errors = 1;
|
||||
return this;
|
||||
{
|
||||
// Maybe we can resolve it
|
||||
if (scope)
|
||||
{
|
||||
/* Anything that affects scope->offset must be
|
||||
* done in lexical order. Fwd ref error if it is affected, otherwise allow.
|
||||
*/
|
||||
unsigned offset = scope->offset;
|
||||
Scope *sc = scope;
|
||||
semantic(scope);
|
||||
// if (offset != sc->offset)
|
||||
// inst = NULL; // trigger fwd ref error
|
||||
}
|
||||
if (!inst)
|
||||
{ error("cannot resolve forward reference");
|
||||
errors = 1;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
if (inst != this)
|
||||
@@ -4865,7 +4961,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
|
||||
ti = (TemplateInstance *)ti->syntaxCopy(NULL);
|
||||
id = (Identifier *)ti;
|
||||
}
|
||||
ids->data[i] = id;
|
||||
ids->tdata()[i] = id;
|
||||
}
|
||||
|
||||
tm = new TemplateMixin(loc, ident,
|
||||
@@ -4886,7 +4982,7 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
// This for when a class/struct contains mixin members, and
|
||||
// is done over because of forward references
|
||||
if (parent && toParent()->isAggregateDeclaration())
|
||||
semanticRun = 1; // do over
|
||||
semanticRun = PASSsemantic; // do over
|
||||
else
|
||||
{
|
||||
#if LOG
|
||||
@@ -4896,7 +4992,7 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
if (!semanticRun)
|
||||
semanticRun = 1;
|
||||
semanticRun = PASSsemantic;
|
||||
#if LOG
|
||||
printf("\tdo semantic\n");
|
||||
#endif
|
||||
@@ -4979,10 +5075,10 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
* runDeferred will re-run mixin's semantic outside of the struct's
|
||||
* semantic.
|
||||
*/
|
||||
semanticRun = 0;
|
||||
semanticRun = PASSinit;
|
||||
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
|
||||
if (ad)
|
||||
ad->sizeok = 2;
|
||||
ad->sizeok = SIZEOKfwd;
|
||||
else
|
||||
{
|
||||
// Forward reference
|
||||
@@ -5027,11 +5123,11 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < tiargs->dim; i++)
|
||||
{ Object *o = (Object *)tiargs->data[i];
|
||||
{ Object *o = (*tiargs)[i];
|
||||
Type *ta = isType(o);
|
||||
Expression *ea = isExpression(o);
|
||||
Dsymbol *sa = isDsymbol(o);
|
||||
Object *tmo = (Object *)tm->tiargs->data[i];
|
||||
Object *tmo = (*tm->tiargs)[i];
|
||||
if (ta)
|
||||
{
|
||||
Type *tmta = isType(tmo);
|
||||
@@ -5095,10 +5191,8 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
declareParameters(argscope);
|
||||
|
||||
// Add members to enclosing scope, as well as this scope
|
||||
for (unsigned i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = (Dsymbol *)members->data[i];
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->addMember(argscope, this, i);
|
||||
//sc->insert(s);
|
||||
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
|
||||
@@ -5124,7 +5218,7 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->semantic(sc2);
|
||||
}
|
||||
|
||||
@@ -5166,9 +5260,9 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
|
||||
void TemplateMixin::semantic2(Scope *sc)
|
||||
{
|
||||
if (semanticRun >= 2)
|
||||
if (semanticRun >= PASSsemantic2)
|
||||
return;
|
||||
semanticRun = 2;
|
||||
semanticRun = PASSsemantic2;
|
||||
#if LOG
|
||||
printf("+TemplateMixin::semantic2('%s')\n", toChars());
|
||||
#endif
|
||||
@@ -5179,7 +5273,7 @@ void TemplateMixin::semantic2(Scope *sc)
|
||||
sc = sc->push(this);
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
#if LOG
|
||||
printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
|
||||
#endif
|
||||
@@ -5195,9 +5289,9 @@ void TemplateMixin::semantic2(Scope *sc)
|
||||
|
||||
void TemplateMixin::semantic3(Scope *sc)
|
||||
{
|
||||
if (semanticRun >= 3)
|
||||
if (semanticRun >= PASSsemantic3)
|
||||
return;
|
||||
semanticRun = 3;
|
||||
semanticRun = PASSsemantic3;
|
||||
#if LOG
|
||||
printf("TemplateMixin::semantic3('%s')\n", toChars());
|
||||
#endif
|
||||
@@ -5207,7 +5301,7 @@ void TemplateMixin::semantic3(Scope *sc)
|
||||
sc = sc->push(this);
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
s->semantic3(sc);
|
||||
}
|
||||
sc = sc->pop();
|
||||
@@ -5230,21 +5324,48 @@ int TemplateMixin::oneMember(Dsymbol **ps)
|
||||
return Dsymbol::oneMember(ps);
|
||||
}
|
||||
|
||||
int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||
{
|
||||
if (members)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
if (s)
|
||||
{
|
||||
if (s->apply(fp, param))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TemplateMixin::hasPointers()
|
||||
{
|
||||
//printf("TemplateMixin::hasPointers() %s\n", toChars());
|
||||
|
||||
if (members)
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
//printf(" s = %s %s\n", s->kind(), s->toChars());
|
||||
if (s->hasPointers())
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
return 1;
|
||||
Dsymbol *s = (*members)[i];
|
||||
//printf(" s = %s %s\n", s->kind(), s->toChars());
|
||||
if (s->hasPointers())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||
{
|
||||
if (members)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->setFieldOffset(ad, poffset, isunion);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *TemplateMixin::toChars()
|
||||
@@ -5264,7 +5385,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring("mixin ");
|
||||
|
||||
for (size_t i = 0; i < idents->dim; i++)
|
||||
{ Identifier *id = (Identifier *)idents->data[i];
|
||||
{ Identifier *id = idents->tdata()[i];
|
||||
|
||||
if (i)
|
||||
buf->writeByte('.');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -40,6 +40,7 @@ struct AliasDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct HdrGenState;
|
||||
enum MATCH;
|
||||
enum PASS;
|
||||
|
||||
struct Tuple : Object
|
||||
{
|
||||
@@ -60,7 +61,7 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
TemplateDeclaration *overroot; // first in overnext list
|
||||
|
||||
int semanticRun; // 1 semantic() run
|
||||
enum PASS semanticRun; // 1 semantic() run
|
||||
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
@@ -287,12 +288,11 @@ struct TemplateInstance : ScopeDsymbol
|
||||
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
||||
// sole member
|
||||
WithScopeSymbol *withsym; // if a member of a with statement
|
||||
int semanticRun; // has semantic() been done?
|
||||
enum PASS semanticRun; // has semantic() been done?
|
||||
int semantictiargsdone; // has semanticTiargs() been done?
|
||||
int nest; // for recursion detection
|
||||
int havetempdecl; // 1 if used second constructor
|
||||
Dsymbol *isnested; // if referencing local symbols, this is the context
|
||||
int errors; // 1 if compiled with errors
|
||||
int speculative; // 1 if only instantiated with errors gagged
|
||||
#ifdef IN_GCC
|
||||
/* On some targets, it is necessary to know whether a symbol
|
||||
@@ -356,7 +356,9 @@ struct TemplateMixin : TemplateInstance
|
||||
void inlineScan();
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||
int hasPointers();
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Reference in New Issue
Block a user