mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-13 07:31:49 +01:00
LDC 2 compiles again.
This commit is contained in:
849
dmd2/access.c
849
dmd2/access.c
@@ -1,424 +1,425 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "enum.h"
|
||||
#include "aggregate.h"
|
||||
#include "init.h"
|
||||
#include "attrib.h"
|
||||
#include "scope.h"
|
||||
#include "id.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "expression.h"
|
||||
#include "module.h"
|
||||
|
||||
#define LOG 0
|
||||
|
||||
/* Code to do access checks
|
||||
*/
|
||||
|
||||
int hasPackageAccess(Scope *sc, Dsymbol *s);
|
||||
|
||||
/****************************************
|
||||
* Return PROT access for Dsymbol smember in this declaration.
|
||||
*/
|
||||
|
||||
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
return PROTpublic;
|
||||
}
|
||||
|
||||
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
if (smember->toParent() == this)
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
else if (smember->isDeclaration()->isStatic())
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
if (smember->toParent() == this)
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
else
|
||||
{
|
||||
enum PROT access;
|
||||
int i;
|
||||
|
||||
if (smember->isDeclaration()->isStatic())
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
|
||||
for (i = 0; i < baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
|
||||
|
||||
access = b->base->getAccess(smember);
|
||||
switch (access)
|
||||
{
|
||||
case PROTnone:
|
||||
break;
|
||||
|
||||
case PROTprivate:
|
||||
access = PROTnone; // private members of base class not accessible
|
||||
break;
|
||||
|
||||
case PROTpackage:
|
||||
case PROTprotected:
|
||||
case PROTpublic:
|
||||
case PROTexport:
|
||||
// If access is to be tightened
|
||||
if (b->protection < access)
|
||||
access = b->protection;
|
||||
|
||||
// Pick path with loosest access
|
||||
if (access > access_ret)
|
||||
access_ret = access;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LOG
|
||||
printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
|
||||
toChars(), smember->toChars(), access_ret);
|
||||
#endif
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Helper function for ClassDeclaration::accessCheck()
|
||||
* Returns:
|
||||
* 0 no access
|
||||
* 1 access
|
||||
*/
|
||||
|
||||
static int accessCheckX(
|
||||
Dsymbol *smember,
|
||||
Dsymbol *sfunc,
|
||||
AggregateDeclaration *dthis,
|
||||
AggregateDeclaration *cdscope)
|
||||
{
|
||||
assert(dthis);
|
||||
|
||||
#if 0
|
||||
printf("accessCheckX for %s.%s in function %s() in scope %s\n",
|
||||
dthis->toChars(), smember->toChars(),
|
||||
sfunc ? sfunc->toChars() : "NULL",
|
||||
cdscope ? cdscope->toChars() : "NULL");
|
||||
#endif
|
||||
if (dthis->hasPrivateAccess(sfunc) ||
|
||||
dthis->isFriendOf(cdscope))
|
||||
{
|
||||
if (smember->toParent() == dthis)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
ClassDeclaration *cdthis = dthis->isClassDeclaration();
|
||||
if (cdthis)
|
||||
{
|
||||
for (int i = 0; i < cdthis->baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
|
||||
enum PROT access;
|
||||
|
||||
access = b->base->getAccess(smember);
|
||||
if (access >= PROTprotected ||
|
||||
accessCheckX(smember, sfunc, b->base, cdscope)
|
||||
)
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (smember->toParent() != dthis)
|
||||
{
|
||||
ClassDeclaration *cdthis = dthis->isClassDeclaration();
|
||||
if (cdthis)
|
||||
{
|
||||
for (int i = 0; i < cdthis->baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
|
||||
|
||||
if (accessCheckX(smember, sfunc, b->base, cdscope))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Do access check for member of this class, this class being the
|
||||
* type of the 'this' pointer used to access smember.
|
||||
*/
|
||||
|
||||
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
|
||||
{
|
||||
int result;
|
||||
|
||||
FuncDeclaration *f = sc->func;
|
||||
AggregateDeclaration *cdscope = sc->getStructClassScope();
|
||||
enum PROT access;
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
|
||||
toChars(), smember->toChars(),
|
||||
f ? f->toChars() : NULL,
|
||||
cdscope ? cdscope->toChars() : NULL);
|
||||
#endif
|
||||
|
||||
Dsymbol *smemberparent = smember->toParent();
|
||||
if (!smemberparent || !smemberparent->isAggregateDeclaration())
|
||||
{
|
||||
#if LOG
|
||||
printf("not an aggregate member\n");
|
||||
#endif
|
||||
return; // then it is accessible
|
||||
}
|
||||
|
||||
// BUG: should enable this check
|
||||
//assert(smember->parent->isBaseOf(this, NULL));
|
||||
|
||||
if (smemberparent == this)
|
||||
{ enum PROT access = smember->prot();
|
||||
|
||||
result = access >= PROTpublic ||
|
||||
hasPrivateAccess(f) ||
|
||||
isFriendOf(cdscope) ||
|
||||
(access == PROTpackage && hasPackageAccess(sc, this));
|
||||
#if LOG
|
||||
printf("result1 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else if ((access = this->getAccess(smember)) >= PROTpublic)
|
||||
{
|
||||
result = 1;
|
||||
#if LOG
|
||||
printf("result2 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else if (access == PROTpackage && hasPackageAccess(sc, this))
|
||||
{
|
||||
result = 1;
|
||||
#if LOG
|
||||
printf("result3 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
result = accessCheckX(smember, f, this, cdscope);
|
||||
#if LOG
|
||||
printf("result4 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
error(loc, "member %s is not accessible", smember->toChars());
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if this is the same or friend of cd.
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
|
||||
{
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
|
||||
#endif
|
||||
if (this == cd)
|
||||
return 1;
|
||||
|
||||
// Friends if both are in the same module
|
||||
//if (toParent() == cd->toParent())
|
||||
if (cd && getModule() == cd->getModule())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tin same module\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LOG
|
||||
printf("\tnot friend\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if scope sc has package level access to s.
|
||||
*/
|
||||
|
||||
int hasPackageAccess(Scope *sc, Dsymbol *s)
|
||||
{
|
||||
#if LOG
|
||||
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
|
||||
#endif
|
||||
|
||||
for (; s; s = s->parent)
|
||||
{
|
||||
if (s->isPackage() && !s->isModule())
|
||||
break;
|
||||
}
|
||||
#if LOG
|
||||
if (s)
|
||||
printf("\tthis is in package '%s'\n", s->toChars());
|
||||
#endif
|
||||
|
||||
if (s && s == sc->module->parent)
|
||||
{
|
||||
#if LOG
|
||||
printf("\ts is in same package as sc\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if LOG
|
||||
printf("\tno package access\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Determine if smember has access to private members of this declaration.
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
|
||||
{
|
||||
if (smember)
|
||||
{ AggregateDeclaration *cd = NULL;
|
||||
Dsymbol *smemberparent = smember->toParent();
|
||||
if (smemberparent)
|
||||
cd = smemberparent->isAggregateDeclaration();
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
|
||||
if (this == cd) // smember is a member of this class
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 1\n");
|
||||
#endif
|
||||
return 1; // so we get private access
|
||||
}
|
||||
|
||||
// If both are members of the same module, grant access
|
||||
while (1)
|
||||
{ Dsymbol *sp = smember->toParent();
|
||||
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
|
||||
smember = sp;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!cd && toParent() == smember->toParent())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 2\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
if (!cd && getModule() == smember->getModule())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 3\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#if LOG
|
||||
printf("\tno\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Check access to d for expression e.d
|
||||
*/
|
||||
|
||||
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
|
||||
{
|
||||
#if LOG
|
||||
if (e)
|
||||
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
|
||||
printf("\te->type = %s\n", e->type->toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("accessCheck(%s)\n", d->toChars());
|
||||
}
|
||||
#endif
|
||||
if (!e)
|
||||
{
|
||||
if (d->prot() == PROTprivate && d->getModule() != sc->module ||
|
||||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
|
||||
|
||||
error(loc, "%s %s.%s is not accessible from %s",
|
||||
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
|
||||
}
|
||||
else if (e->type->ty == Tclass)
|
||||
{ // Do access check
|
||||
ClassDeclaration *cd;
|
||||
|
||||
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
|
||||
#if 1
|
||||
if (e->op == TOKsuper)
|
||||
{ ClassDeclaration *cd2;
|
||||
|
||||
cd2 = sc->func->toParent()->isClassDeclaration();
|
||||
if (cd2)
|
||||
cd = cd2;
|
||||
}
|
||||
#endif
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
else if (e->type->ty == Tstruct)
|
||||
{ // Do access check
|
||||
StructDeclaration *cd;
|
||||
|
||||
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#include "enum.h"
|
||||
#include "aggregate.h"
|
||||
#include "init.h"
|
||||
#include "attrib.h"
|
||||
#include "scope.h"
|
||||
#include "id.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "expression.h"
|
||||
#include "module.h"
|
||||
|
||||
#define LOG 0
|
||||
|
||||
/* Code to do access checks
|
||||
*/
|
||||
|
||||
int hasPackageAccess(Scope *sc, Dsymbol *s);
|
||||
|
||||
/****************************************
|
||||
* Return PROT access for Dsymbol smember in this declaration.
|
||||
*/
|
||||
|
||||
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
return PROTpublic;
|
||||
}
|
||||
|
||||
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
if (smember->toParent() == this)
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
else if (smember->isDeclaration()->isStatic())
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
if (smember->toParent() == this)
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
else
|
||||
{
|
||||
enum PROT access;
|
||||
int i;
|
||||
|
||||
if (smember->isDeclaration()->isStatic())
|
||||
{
|
||||
access_ret = smember->prot();
|
||||
}
|
||||
|
||||
for (i = 0; i < baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
|
||||
|
||||
access = b->base->getAccess(smember);
|
||||
switch (access)
|
||||
{
|
||||
case PROTnone:
|
||||
break;
|
||||
|
||||
case PROTprivate:
|
||||
access = PROTnone; // private members of base class not accessible
|
||||
break;
|
||||
|
||||
case PROTpackage:
|
||||
case PROTprotected:
|
||||
case PROTpublic:
|
||||
case PROTexport:
|
||||
// If access is to be tightened
|
||||
if (b->protection < access)
|
||||
access = b->protection;
|
||||
|
||||
// Pick path with loosest access
|
||||
if (access > access_ret)
|
||||
access_ret = access;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LOG
|
||||
printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
|
||||
toChars(), smember->toChars(), access_ret);
|
||||
#endif
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Helper function for ClassDeclaration::accessCheck()
|
||||
* Returns:
|
||||
* 0 no access
|
||||
* 1 access
|
||||
*/
|
||||
|
||||
static int accessCheckX(
|
||||
Dsymbol *smember,
|
||||
Dsymbol *sfunc,
|
||||
AggregateDeclaration *dthis,
|
||||
AggregateDeclaration *cdscope)
|
||||
{
|
||||
assert(dthis);
|
||||
|
||||
#if 0
|
||||
printf("accessCheckX for %s.%s in function %s() in scope %s\n",
|
||||
dthis->toChars(), smember->toChars(),
|
||||
sfunc ? sfunc->toChars() : "NULL",
|
||||
cdscope ? cdscope->toChars() : "NULL");
|
||||
#endif
|
||||
if (dthis->hasPrivateAccess(sfunc) ||
|
||||
dthis->isFriendOf(cdscope))
|
||||
{
|
||||
if (smember->toParent() == dthis)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
ClassDeclaration *cdthis = dthis->isClassDeclaration();
|
||||
if (cdthis)
|
||||
{
|
||||
for (int i = 0; i < cdthis->baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
|
||||
enum PROT access;
|
||||
|
||||
access = b->base->getAccess(smember);
|
||||
if (access >= PROTprotected ||
|
||||
accessCheckX(smember, sfunc, b->base, cdscope)
|
||||
)
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (smember->toParent() != dthis)
|
||||
{
|
||||
ClassDeclaration *cdthis = dthis->isClassDeclaration();
|
||||
if (cdthis)
|
||||
{
|
||||
for (int i = 0; i < cdthis->baseclasses.dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
|
||||
|
||||
if (accessCheckX(smember, sfunc, b->base, cdscope))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Do access check for member of this class, this class being the
|
||||
* type of the 'this' pointer used to access smember.
|
||||
*/
|
||||
|
||||
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
|
||||
{
|
||||
int result;
|
||||
|
||||
FuncDeclaration *f = sc->func;
|
||||
AggregateDeclaration *cdscope = sc->getStructClassScope();
|
||||
enum PROT access;
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
|
||||
toChars(), smember->toChars(),
|
||||
f ? f->toChars() : NULL,
|
||||
cdscope ? cdscope->toChars() : NULL);
|
||||
#endif
|
||||
|
||||
Dsymbol *smemberparent = smember->toParent();
|
||||
if (!smemberparent || !smemberparent->isAggregateDeclaration())
|
||||
{
|
||||
#if LOG
|
||||
printf("not an aggregate member\n");
|
||||
#endif
|
||||
return; // then it is accessible
|
||||
}
|
||||
|
||||
// BUG: should enable this check
|
||||
//assert(smember->parent->isBaseOf(this, NULL));
|
||||
|
||||
if (smemberparent == this)
|
||||
{ enum PROT access = smember->prot();
|
||||
|
||||
result = access >= PROTpublic ||
|
||||
hasPrivateAccess(f) ||
|
||||
isFriendOf(cdscope) ||
|
||||
(access == PROTpackage && hasPackageAccess(sc, this));
|
||||
#if LOG
|
||||
printf("result1 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else if ((access = this->getAccess(smember)) >= PROTpublic)
|
||||
{
|
||||
result = 1;
|
||||
#if LOG
|
||||
printf("result2 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else if (access == PROTpackage && hasPackageAccess(sc, this))
|
||||
{
|
||||
result = 1;
|
||||
#if LOG
|
||||
printf("result3 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
result = accessCheckX(smember, f, this, cdscope);
|
||||
#if LOG
|
||||
printf("result4 = %d\n", result);
|
||||
#endif
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
error(loc, "member %s is not accessible", smember->toChars());
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if this is the same or friend of cd.
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
|
||||
{
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
|
||||
#endif
|
||||
if (this == cd)
|
||||
return 1;
|
||||
|
||||
// Friends if both are in the same module
|
||||
//if (toParent() == cd->toParent())
|
||||
if (cd && getModule() == cd->getModule())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tin same module\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LOG
|
||||
printf("\tnot friend\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if scope sc has package level access to s.
|
||||
*/
|
||||
|
||||
int hasPackageAccess(Scope *sc, Dsymbol *s)
|
||||
{
|
||||
#if LOG
|
||||
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
|
||||
#endif
|
||||
|
||||
for (; s; s = s->parent)
|
||||
{
|
||||
if (s->isPackage() && !s->isModule())
|
||||
break;
|
||||
}
|
||||
#if LOG
|
||||
if (s)
|
||||
printf("\tthis is in package '%s'\n", s->toChars());
|
||||
#endif
|
||||
|
||||
if (s && s == sc->module->parent)
|
||||
{
|
||||
#if LOG
|
||||
printf("\ts is in same package as sc\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if LOG
|
||||
printf("\tno package access\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Determine if smember has access to private members of this declaration.
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
|
||||
{
|
||||
if (smember)
|
||||
{ AggregateDeclaration *cd = NULL;
|
||||
Dsymbol *smemberparent = smember->toParent();
|
||||
if (smemberparent)
|
||||
cd = smemberparent->isAggregateDeclaration();
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
|
||||
toChars(), smember->toChars());
|
||||
#endif
|
||||
|
||||
if (this == cd) // smember is a member of this class
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 1\n");
|
||||
#endif
|
||||
return 1; // so we get private access
|
||||
}
|
||||
|
||||
// If both are members of the same module, grant access
|
||||
while (1)
|
||||
{ Dsymbol *sp = smember->toParent();
|
||||
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
|
||||
smember = sp;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!cd && toParent() == smember->toParent())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 2\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
if (!cd && getModule() == smember->getModule())
|
||||
{
|
||||
#if LOG
|
||||
printf("\tyes 3\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#if LOG
|
||||
printf("\tno\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Check access to d for expression e.d
|
||||
*/
|
||||
|
||||
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
|
||||
{
|
||||
#if LOG
|
||||
if (e)
|
||||
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
|
||||
printf("\te->type = %s\n", e->type->toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("accessCheck(%s)\n", d->toChars());
|
||||
}
|
||||
#endif
|
||||
if (!e)
|
||||
{
|
||||
if (d->getModule() != sc->module)
|
||||
if (d->prot() == PROTprivate ||
|
||||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
|
||||
|
||||
error(loc, "%s %s.%s is not accessible from %s",
|
||||
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
|
||||
}
|
||||
else if (e->type->ty == Tclass)
|
||||
{ // Do access check
|
||||
ClassDeclaration *cd;
|
||||
|
||||
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
|
||||
#if 1
|
||||
if (e->op == TOKsuper)
|
||||
{ ClassDeclaration *cd2;
|
||||
|
||||
cd2 = sc->func->toParent()->isClassDeclaration();
|
||||
if (cd2)
|
||||
cd = cd2;
|
||||
}
|
||||
#endif
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
else if (e->type->ty == Tstruct)
|
||||
{ // Do access check
|
||||
StructDeclaration *cd;
|
||||
|
||||
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
}
|
||||
|
||||
612
dmd2/aggregate.h
612
dmd2/aggregate.h
@@ -1,292 +1,320 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_AGGREGATE_H
|
||||
#define DMD_AGGREGATE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct TypeFunction;
|
||||
struct Expression;
|
||||
struct FuncDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct DeleteDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct dt_t;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
class Type;
|
||||
class Value;
|
||||
class Constant;
|
||||
class ConstantStruct;
|
||||
class GlobalVariable;
|
||||
}
|
||||
|
||||
struct AggregateDeclaration : ScopeDsymbol
|
||||
{
|
||||
Type *type;
|
||||
unsigned storage_class;
|
||||
enum PROT protection;
|
||||
Type *handle; // 'this' type
|
||||
unsigned structsize; // size of struct
|
||||
unsigned alignsize; // size of struct for alignment purposes
|
||||
unsigned structalign; // struct member alignment in effect
|
||||
int hasUnions; // set if aggregate has overlapping fields
|
||||
Array fields; // VarDeclaration fields
|
||||
unsigned sizeok; // set when structsize contains valid data
|
||||
// 0: no size
|
||||
// 1: size is correct
|
||||
// 2: cannot determine size; fwd referenced
|
||||
int isdeprecated; // !=0 if deprecated
|
||||
Scope *scope; // !=NULL means context to use
|
||||
|
||||
// Special member functions
|
||||
InvariantDeclaration *inv; // invariant
|
||||
NewDeclaration *aggNew; // allocator
|
||||
DeleteDeclaration *aggDelete; // deallocator
|
||||
|
||||
#if DMDV2
|
||||
CtorDeclaration *ctor;
|
||||
CtorDeclaration *defaultCtor; // default constructor
|
||||
#endif
|
||||
|
||||
FuncDeclarations dtors; // Array of destructors
|
||||
FuncDeclaration *dtor; // aggregate destructor
|
||||
|
||||
#ifdef IN_GCC
|
||||
Array methods; // flat list of all methods for debug information
|
||||
#endif
|
||||
|
||||
AggregateDeclaration(Loc loc, Identifier *id);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
unsigned size(Loc loc);
|
||||
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
||||
Type *getType();
|
||||
void addField(Scope *sc, VarDeclaration *v);
|
||||
int isDeprecated(); // is aggregate deprecated?
|
||||
FuncDeclaration *buildDtor(Scope *sc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
// For access checking
|
||||
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
int isFriendOf(AggregateDeclaration *cd);
|
||||
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
|
||||
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
|
||||
|
||||
enum PROT prot();
|
||||
|
||||
// Back end
|
||||
Symbol *stag; // tag symbol for debug data
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
|
||||
AggregateDeclaration *isAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct AnonymousAggregateDeclaration : AggregateDeclaration
|
||||
{
|
||||
AnonymousAggregateDeclaration()
|
||||
: AggregateDeclaration(0, NULL)
|
||||
{
|
||||
}
|
||||
|
||||
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct StructDeclaration : AggregateDeclaration
|
||||
{
|
||||
int zeroInit; // !=0 if initialize with 0 fill
|
||||
#if DMDV2
|
||||
int hasIdentityAssign; // !=0 if has identity opAssign
|
||||
FuncDeclaration *cpctor; // generated copy-constructor, if any
|
||||
|
||||
FuncDeclarations postblits; // Array of postblit functions
|
||||
FuncDeclaration *postblit; // aggregate postblit
|
||||
#endif
|
||||
|
||||
StructDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
char *mangle();
|
||||
const char *kind();
|
||||
int needOpAssign();
|
||||
FuncDeclaration *buildOpAssign(Scope *sc);
|
||||
FuncDeclaration *buildPostBlit(Scope *sc);
|
||||
FuncDeclaration *buildCpCtor(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDt(dt_t **pdt);
|
||||
void toDebug(); // to symbolic debug info
|
||||
|
||||
StructDeclaration *isStructDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct UnionDeclaration : StructDeclaration
|
||||
{
|
||||
UnionDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
const char *kind();
|
||||
|
||||
UnionDeclaration *isUnionDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct BaseClass
|
||||
{
|
||||
Type *type; // (before semantic processing)
|
||||
enum PROT protection; // protection for the base interface
|
||||
|
||||
ClassDeclaration *base;
|
||||
int offset; // 'this' pointer offset
|
||||
Array vtbl; // for interfaces: Array of FuncDeclaration's
|
||||
// making up the vtbl[]
|
||||
|
||||
int baseInterfaces_dim;
|
||||
BaseClass *baseInterfaces; // if BaseClass is an interface, these
|
||||
// are a copy of the InterfaceDeclaration::interfaces
|
||||
|
||||
BaseClass();
|
||||
BaseClass(Type *type, enum PROT protection);
|
||||
|
||||
int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
|
||||
void copyBaseInterfaces(BaseClasses *);
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
#define CLASSINFO_SIZE (0x3C+16) // value of ClassInfo.size
|
||||
#else
|
||||
#define CLASSINFO_SIZE (0x3C+12) // value of ClassInfo.size
|
||||
#endif
|
||||
|
||||
struct ClassDeclaration : AggregateDeclaration
|
||||
{
|
||||
static ClassDeclaration *object;
|
||||
static ClassDeclaration *classinfo;
|
||||
|
||||
ClassDeclaration *baseClass; // NULL only if this is Object
|
||||
FuncDeclaration *staticCtor;
|
||||
FuncDeclaration *staticDtor;
|
||||
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
|
||||
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
|
||||
|
||||
BaseClasses baseclasses; // Array of BaseClass's; first is super,
|
||||
// rest are Interface's
|
||||
|
||||
int interfaces_dim;
|
||||
BaseClass **interfaces; // interfaces[interfaces_dim] for this class
|
||||
// (does not include baseClass)
|
||||
|
||||
BaseClasses *vtblInterfaces; // array of base interfaces that have
|
||||
// their own vtbl[]
|
||||
|
||||
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
|
||||
int com; // !=0 if this is a COM class (meaning
|
||||
// it derives from IUnknown)
|
||||
int isauto; // !=0 if this is an auto class
|
||||
int isabstract; // !=0 if abstract class
|
||||
|
||||
int isnested; // !=0 if is nested
|
||||
VarDeclaration *vthis; // 'this' parameter if this class is nested
|
||||
|
||||
int inuse; // to prevent recursive attempts
|
||||
|
||||
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isBaseOf2(ClassDeclaration *cd);
|
||||
|
||||
#define OFFSET_RUNTIME 0x76543210
|
||||
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#if DMDV2
|
||||
int isFuncHidden(FuncDeclaration *fd);
|
||||
#endif
|
||||
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
|
||||
void interfaceSemantic(Scope *sc);
|
||||
int isNested();
|
||||
int isCOMclass();
|
||||
virtual int isCOMinterface();
|
||||
#if DMDV2
|
||||
virtual int isCPPinterface();
|
||||
#endif
|
||||
int isAbstract();
|
||||
virtual int vtblOffset();
|
||||
const char *kind();
|
||||
char *mangle();
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
|
||||
void addLocalClass(ClassDeclarations *);
|
||||
|
||||
// Back end
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
unsigned baseVtblOffset(BaseClass *bc);
|
||||
Symbol *toSymbol();
|
||||
Symbol *toVtblSymbol();
|
||||
void toDt(dt_t **pdt);
|
||||
void toDt2(dt_t **pdt, ClassDeclaration *cd);
|
||||
|
||||
Symbol *vtblsym;
|
||||
|
||||
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
||||
};
|
||||
|
||||
struct InterfaceDeclaration : ClassDeclaration
|
||||
{
|
||||
#if DMDV2
|
||||
int cpp; // !=0 if this is a C++ interface
|
||||
#endif
|
||||
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
int isBaseOf(BaseClass *bc, int *poffset);
|
||||
const char *kind();
|
||||
int vtblOffset();
|
||||
#if DMDV2
|
||||
int isCPPinterface();
|
||||
#endif
|
||||
virtual int isCOMinterface();
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
Symbol *toSymbol();
|
||||
|
||||
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
|
||||
};
|
||||
|
||||
#endif /* DMD_AGGREGATE_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_AGGREGATE_H
|
||||
#define DMD_AGGREGATE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
#if IN_LLVM
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#endif
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct TypeFunction;
|
||||
struct Expression;
|
||||
struct FuncDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct DeleteDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct dt_t;
|
||||
|
||||
#if IN_LLVM
|
||||
namespace llvm
|
||||
{
|
||||
class Type;
|
||||
class Value;
|
||||
class Constant;
|
||||
class ConstantStruct;
|
||||
class GlobalVariable;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct AggregateDeclaration : ScopeDsymbol
|
||||
{
|
||||
Type *type;
|
||||
unsigned storage_class;
|
||||
enum PROT protection;
|
||||
Type *handle; // 'this' type
|
||||
unsigned structsize; // size of struct
|
||||
unsigned alignsize; // size of struct for alignment purposes
|
||||
unsigned structalign; // struct member alignment in effect
|
||||
int hasUnions; // set if aggregate has overlapping fields
|
||||
Array fields; // VarDeclaration fields
|
||||
unsigned sizeok; // set when structsize contains valid data
|
||||
// 0: no size
|
||||
// 1: size is correct
|
||||
// 2: cannot determine size; fwd referenced
|
||||
int isdeprecated; // !=0 if deprecated
|
||||
Scope *scope; // !=NULL means context to use
|
||||
|
||||
int isnested; // !=0 if is nested
|
||||
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
|
||||
|
||||
// Special member functions
|
||||
InvariantDeclaration *inv; // invariant
|
||||
NewDeclaration *aggNew; // allocator
|
||||
DeleteDeclaration *aggDelete; // deallocator
|
||||
|
||||
#if DMDV2
|
||||
//CtorDeclaration *ctor;
|
||||
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
|
||||
CtorDeclaration *defaultCtor; // default constructor
|
||||
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
|
||||
#endif
|
||||
|
||||
FuncDeclarations dtors; // Array of destructors
|
||||
FuncDeclaration *dtor; // aggregate destructor
|
||||
|
||||
#ifdef IN_GCC
|
||||
Array methods; // flat list of all methods for debug information
|
||||
#endif
|
||||
|
||||
AggregateDeclaration(Loc loc, Identifier *id);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
unsigned size(Loc loc);
|
||||
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
||||
Type *getType();
|
||||
void addField(Scope *sc, VarDeclaration *v);
|
||||
int isDeprecated(); // is aggregate deprecated?
|
||||
FuncDeclaration *buildDtor(Scope *sc);
|
||||
int isNested();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
// For access checking
|
||||
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
int isFriendOf(AggregateDeclaration *cd);
|
||||
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
|
||||
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
|
||||
|
||||
enum PROT prot();
|
||||
|
||||
#if IN_DMD
|
||||
// Back end
|
||||
Symbol *stag; // tag symbol for debug data
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
#endif
|
||||
|
||||
AggregateDeclaration *isAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct AnonymousAggregateDeclaration : AggregateDeclaration
|
||||
{
|
||||
AnonymousAggregateDeclaration()
|
||||
: AggregateDeclaration(0, NULL)
|
||||
{
|
||||
}
|
||||
|
||||
AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct StructDeclaration : AggregateDeclaration
|
||||
{
|
||||
int zeroInit; // !=0 if initialize with 0 fill
|
||||
#if DMDV2
|
||||
int hasIdentityAssign; // !=0 if has identity opAssign
|
||||
FuncDeclaration *cpctor; // generated copy-constructor, if any
|
||||
|
||||
FuncDeclarations postblits; // Array of postblit functions
|
||||
FuncDeclaration *postblit; // aggregate postblit
|
||||
#endif
|
||||
|
||||
StructDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
char *mangle();
|
||||
const char *kind();
|
||||
int needOpAssign();
|
||||
FuncDeclaration *buildOpAssign(Scope *sc);
|
||||
FuncDeclaration *buildPostBlit(Scope *sc);
|
||||
FuncDeclaration *buildCpCtor(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDt(dt_t **pdt);
|
||||
void toDebug(); // to symbolic debug info
|
||||
#endif
|
||||
|
||||
StructDeclaration *isStructDeclaration() { return this; }
|
||||
|
||||
#if IN_LLVM
|
||||
void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct UnionDeclaration : StructDeclaration
|
||||
{
|
||||
UnionDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
const char *kind();
|
||||
|
||||
UnionDeclaration *isUnionDeclaration() { return this; }
|
||||
};
|
||||
|
||||
// warning: two classes with the same base class share the same
|
||||
// BaseClass instance.
|
||||
struct BaseClass
|
||||
{
|
||||
Type *type; // (before semantic processing)
|
||||
enum PROT protection; // protection for the base interface
|
||||
|
||||
ClassDeclaration *base;
|
||||
int offset; // 'this' pointer offset
|
||||
Array vtbl; // for interfaces: Array of FuncDeclaration's
|
||||
// making up the vtbl[]
|
||||
|
||||
int baseInterfaces_dim;
|
||||
BaseClass *baseInterfaces; // if BaseClass is an interface, these
|
||||
// are a copy of the InterfaceDeclaration::interfaces
|
||||
|
||||
BaseClass();
|
||||
BaseClass(Type *type, enum PROT protection);
|
||||
|
||||
int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
|
||||
void copyBaseInterfaces(BaseClasses *);
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size
|
||||
#else
|
||||
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
|
||||
#endif
|
||||
|
||||
struct ClassDeclaration : AggregateDeclaration
|
||||
{
|
||||
static ClassDeclaration *object;
|
||||
static ClassDeclaration *classinfo;
|
||||
|
||||
ClassDeclaration *baseClass; // NULL only if this is Object
|
||||
FuncDeclaration *staticCtor;
|
||||
FuncDeclaration *staticDtor;
|
||||
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
|
||||
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
|
||||
|
||||
BaseClasses baseclasses; // Array of BaseClass's; first is super,
|
||||
// rest are Interface's
|
||||
|
||||
int interfaces_dim;
|
||||
BaseClass **interfaces; // interfaces[interfaces_dim] for this class
|
||||
// (does not include baseClass)
|
||||
|
||||
BaseClasses *vtblInterfaces; // array of base interfaces that have
|
||||
// their own vtbl[]
|
||||
|
||||
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
|
||||
int com; // !=0 if this is a COM class (meaning
|
||||
// it derives from IUnknown)
|
||||
int isauto; // !=0 if this is an auto class
|
||||
int isabstract; // !=0 if abstract class
|
||||
|
||||
int inuse; // to prevent recursive attempts
|
||||
|
||||
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isBaseOf2(ClassDeclaration *cd);
|
||||
|
||||
#define OFFSET_RUNTIME 0x76543210
|
||||
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#if DMDV2
|
||||
int isFuncHidden(FuncDeclaration *fd);
|
||||
#endif
|
||||
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
|
||||
void interfaceSemantic(Scope *sc);
|
||||
int isCOMclass();
|
||||
virtual int isCOMinterface();
|
||||
#if DMDV2
|
||||
virtual int isCPPinterface();
|
||||
#endif
|
||||
int isAbstract();
|
||||
virtual int vtblOffset();
|
||||
const char *kind();
|
||||
char *mangle();
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||
|
||||
void addLocalClass(ClassDeclarations *);
|
||||
|
||||
#if IN_DMD
|
||||
// Back end
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
unsigned baseVtblOffset(BaseClass *bc);
|
||||
Symbol *toSymbol();
|
||||
Symbol *toVtblSymbol();
|
||||
void toDt(dt_t **pdt);
|
||||
void toDt2(dt_t **pdt, ClassDeclaration *cd);
|
||||
|
||||
Symbol *vtblsym;
|
||||
#endif
|
||||
|
||||
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
||||
|
||||
#if IN_LLVM
|
||||
virtual void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct InterfaceDeclaration : ClassDeclaration
|
||||
{
|
||||
#if DMDV2
|
||||
int cpp; // !=0 if this is a C++ interface
|
||||
#endif
|
||||
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
int isBaseOf(BaseClass *bc, int *poffset);
|
||||
const char *kind();
|
||||
int vtblOffset();
|
||||
#if DMDV2
|
||||
int isCPPinterface();
|
||||
#endif
|
||||
virtual int isCOMinterface();
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
Symbol *toSymbol();
|
||||
#endif
|
||||
|
||||
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
|
||||
|
||||
#if IN_LLVM
|
||||
void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* DMD_AGGREGATE_H */
|
||||
|
||||
72
dmd2/aliasthis.c
Normal file
72
dmd2/aliasthis.c
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2009-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "identifier.h"
|
||||
#include "aliasthis.h"
|
||||
#include "scope.h"
|
||||
#include "aggregate.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
#if DMDV2
|
||||
|
||||
|
||||
AliasThis::AliasThis(Loc loc, Identifier *ident)
|
||||
: Dsymbol(NULL) // it's anonymous (no identifier)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->ident = ident;
|
||||
}
|
||||
|
||||
Dsymbol *AliasThis::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(!s);
|
||||
/* Since there is no semantic information stored here,
|
||||
* we don't need to copy it.
|
||||
*/
|
||||
return this;
|
||||
}
|
||||
|
||||
void AliasThis::semantic(Scope *sc)
|
||||
{
|
||||
Dsymbol *parent = sc->parent;
|
||||
if (parent)
|
||||
parent = parent->pastMixin();
|
||||
AggregateDeclaration *ad = NULL;
|
||||
if (parent)
|
||||
ad = parent->isAggregateDeclaration();
|
||||
if (ad)
|
||||
{
|
||||
if (ad->aliasthis)
|
||||
error("there can be only one alias this");
|
||||
assert(ad->members);
|
||||
Dsymbol *s = ad->search(loc, ident, 0);
|
||||
ad->aliasthis = s;
|
||||
}
|
||||
else
|
||||
error("alias this can only appear in struct or class declaration, not %s", parent ? parent->toChars() : "nowhere");
|
||||
}
|
||||
|
||||
const char *AliasThis::kind()
|
||||
{
|
||||
return "alias this";
|
||||
}
|
||||
|
||||
void AliasThis::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("alias ");
|
||||
buf->writestring(ident->toChars());
|
||||
buf->writestring(" this;\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
41
dmd2/aliasthis.h
Normal file
41
dmd2/aliasthis.h
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2009-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_ALIASTHIS_H
|
||||
#define DMD_ALIASTHIS_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "mars.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
#if DMDV2
|
||||
|
||||
struct AliasThis : Dsymbol
|
||||
{
|
||||
// alias Identifier this;
|
||||
Identifier *ident;
|
||||
|
||||
AliasThis(Loc loc, Identifier *ident);
|
||||
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
const char *kind();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
AliasThis *isAliasThis() { return this; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
999
dmd2/arrayop.c
999
dmd2/arrayop.c
@@ -1,494 +1,505 @@
|
||||
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32 || IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#else
|
||||
#include "../root/mem.h"
|
||||
#endif
|
||||
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "scope.h"
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
#include "init.h"
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct the array operation expression.
|
||||
*/
|
||||
|
||||
Expression *BinExp::arrayOp(Scope *sc)
|
||||
{
|
||||
Expressions *arguments = new Expressions();
|
||||
|
||||
/* The expression to generate an array operation for is mangled
|
||||
* into a name to use as the array operation function name.
|
||||
* Mangle in the operands and operators in RPN order, and type.
|
||||
*/
|
||||
OutBuffer buf;
|
||||
buf.writestring("_array");
|
||||
buildArrayIdent(&buf, arguments);
|
||||
buf.writeByte('_');
|
||||
|
||||
/* Append deco of array element type
|
||||
*/
|
||||
#if DMDV2
|
||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
|
||||
#else
|
||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
|
||||
#endif
|
||||
|
||||
size_t namelen = buf.offset;
|
||||
buf.writeByte(0);
|
||||
char *name = (char *)buf.extractData();
|
||||
|
||||
/* Look up name in hash table
|
||||
*/
|
||||
StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
|
||||
FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
|
||||
if (!fd)
|
||||
{
|
||||
// /* Some of the array op functions are written as library functions,
|
||||
// * presumably to optimize them with special CPU vector instructions.
|
||||
// * List those library functions here, in alpha order.
|
||||
// */
|
||||
// static const char *libArrayopFuncs[] =
|
||||
// {
|
||||
// "_arrayExpSliceAddass_a",
|
||||
// "_arrayExpSliceAddass_d", // T[]+=T
|
||||
// "_arrayExpSliceAddass_f", // T[]+=T
|
||||
// "_arrayExpSliceAddass_g",
|
||||
// "_arrayExpSliceAddass_h",
|
||||
// "_arrayExpSliceAddass_i",
|
||||
// "_arrayExpSliceAddass_k",
|
||||
// "_arrayExpSliceAddass_s",
|
||||
// "_arrayExpSliceAddass_t",
|
||||
// "_arrayExpSliceAddass_u",
|
||||
// "_arrayExpSliceAddass_w",
|
||||
//
|
||||
// "_arrayExpSliceDivass_d", // T[]/=T
|
||||
// "_arrayExpSliceDivass_f", // T[]/=T
|
||||
//
|
||||
// "_arrayExpSliceMinSliceAssign_a",
|
||||
// "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
|
||||
// "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
|
||||
// "_arrayExpSliceMinSliceAssign_g",
|
||||
// "_arrayExpSliceMinSliceAssign_h",
|
||||
// "_arrayExpSliceMinSliceAssign_i",
|
||||
// "_arrayExpSliceMinSliceAssign_k",
|
||||
// "_arrayExpSliceMinSliceAssign_s",
|
||||
// "_arrayExpSliceMinSliceAssign_t",
|
||||
// "_arrayExpSliceMinSliceAssign_u",
|
||||
// "_arrayExpSliceMinSliceAssign_w",
|
||||
//
|
||||
// "_arrayExpSliceMinass_a",
|
||||
// "_arrayExpSliceMinass_d", // T[]-=T
|
||||
// "_arrayExpSliceMinass_f", // T[]-=T
|
||||
// "_arrayExpSliceMinass_g",
|
||||
// "_arrayExpSliceMinass_h",
|
||||
// "_arrayExpSliceMinass_i",
|
||||
// "_arrayExpSliceMinass_k",
|
||||
// "_arrayExpSliceMinass_s",
|
||||
// "_arrayExpSliceMinass_t",
|
||||
// "_arrayExpSliceMinass_u",
|
||||
// "_arrayExpSliceMinass_w",
|
||||
//
|
||||
// "_arrayExpSliceMulass_d", // T[]*=T
|
||||
// "_arrayExpSliceMulass_f", // T[]*=T
|
||||
// "_arrayExpSliceMulass_i",
|
||||
// "_arrayExpSliceMulass_k",
|
||||
// "_arrayExpSliceMulass_s",
|
||||
// "_arrayExpSliceMulass_t",
|
||||
// "_arrayExpSliceMulass_u",
|
||||
// "_arrayExpSliceMulass_w",
|
||||
//
|
||||
// "_arraySliceExpAddSliceAssign_a",
|
||||
// "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
|
||||
// "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
|
||||
// "_arraySliceExpAddSliceAssign_g",
|
||||
// "_arraySliceExpAddSliceAssign_h",
|
||||
// "_arraySliceExpAddSliceAssign_i",
|
||||
// "_arraySliceExpAddSliceAssign_k",
|
||||
// "_arraySliceExpAddSliceAssign_s",
|
||||
// "_arraySliceExpAddSliceAssign_t",
|
||||
// "_arraySliceExpAddSliceAssign_u",
|
||||
// "_arraySliceExpAddSliceAssign_w",
|
||||
//
|
||||
// "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
|
||||
// "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
|
||||
//
|
||||
// "_arraySliceExpMinSliceAssign_a",
|
||||
// "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
|
||||
// "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
|
||||
// "_arraySliceExpMinSliceAssign_g",
|
||||
// "_arraySliceExpMinSliceAssign_h",
|
||||
// "_arraySliceExpMinSliceAssign_i",
|
||||
// "_arraySliceExpMinSliceAssign_k",
|
||||
// "_arraySliceExpMinSliceAssign_s",
|
||||
// "_arraySliceExpMinSliceAssign_t",
|
||||
// "_arraySliceExpMinSliceAssign_u",
|
||||
// "_arraySliceExpMinSliceAssign_w",
|
||||
//
|
||||
// "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
|
||||
// "_arraySliceExpMulSliceAddass_f",
|
||||
// "_arraySliceExpMulSliceAddass_r",
|
||||
//
|
||||
// "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
|
||||
// "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
|
||||
// "_arraySliceExpMulSliceAssign_i",
|
||||
// "_arraySliceExpMulSliceAssign_k",
|
||||
// "_arraySliceExpMulSliceAssign_s",
|
||||
// "_arraySliceExpMulSliceAssign_t",
|
||||
// "_arraySliceExpMulSliceAssign_u",
|
||||
// "_arraySliceExpMulSliceAssign_w",
|
||||
//
|
||||
// "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
|
||||
// "_arraySliceExpMulSliceMinass_f",
|
||||
// "_arraySliceExpMulSliceMinass_r",
|
||||
//
|
||||
// "_arraySliceSliceAddSliceAssign_a",
|
||||
// "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
|
||||
// "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
|
||||
// "_arraySliceSliceAddSliceAssign_g",
|
||||
// "_arraySliceSliceAddSliceAssign_h",
|
||||
// "_arraySliceSliceAddSliceAssign_i",
|
||||
// "_arraySliceSliceAddSliceAssign_k",
|
||||
// "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
|
||||
// "_arraySliceSliceAddSliceAssign_s",
|
||||
// "_arraySliceSliceAddSliceAssign_t",
|
||||
// "_arraySliceSliceAddSliceAssign_u",
|
||||
// "_arraySliceSliceAddSliceAssign_w",
|
||||
//
|
||||
// "_arraySliceSliceAddass_a",
|
||||
// "_arraySliceSliceAddass_d", // T[]+=T[]
|
||||
// "_arraySliceSliceAddass_f", // T[]+=T[]
|
||||
// "_arraySliceSliceAddass_g",
|
||||
// "_arraySliceSliceAddass_h",
|
||||
// "_arraySliceSliceAddass_i",
|
||||
// "_arraySliceSliceAddass_k",
|
||||
// "_arraySliceSliceAddass_s",
|
||||
// "_arraySliceSliceAddass_t",
|
||||
// "_arraySliceSliceAddass_u",
|
||||
// "_arraySliceSliceAddass_w",
|
||||
//
|
||||
// "_arraySliceSliceMinSliceAssign_a",
|
||||
// "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
|
||||
// "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
|
||||
// "_arraySliceSliceMinSliceAssign_g",
|
||||
// "_arraySliceSliceMinSliceAssign_h",
|
||||
// "_arraySliceSliceMinSliceAssign_i",
|
||||
// "_arraySliceSliceMinSliceAssign_k",
|
||||
// "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
|
||||
// "_arraySliceSliceMinSliceAssign_s",
|
||||
// "_arraySliceSliceMinSliceAssign_t",
|
||||
// "_arraySliceSliceMinSliceAssign_u",
|
||||
// "_arraySliceSliceMinSliceAssign_w",
|
||||
//
|
||||
// "_arraySliceSliceMinass_a",
|
||||
// "_arraySliceSliceMinass_d", // T[]-=T[]
|
||||
// "_arraySliceSliceMinass_f", // T[]-=T[]
|
||||
// "_arraySliceSliceMinass_g",
|
||||
// "_arraySliceSliceMinass_h",
|
||||
// "_arraySliceSliceMinass_i",
|
||||
// "_arraySliceSliceMinass_k",
|
||||
// "_arraySliceSliceMinass_s",
|
||||
// "_arraySliceSliceMinass_t",
|
||||
// "_arraySliceSliceMinass_u",
|
||||
// "_arraySliceSliceMinass_w",
|
||||
//
|
||||
// "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
|
||||
// "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
|
||||
// "_arraySliceSliceMulSliceAssign_i",
|
||||
// "_arraySliceSliceMulSliceAssign_k",
|
||||
// "_arraySliceSliceMulSliceAssign_s",
|
||||
// "_arraySliceSliceMulSliceAssign_t",
|
||||
// "_arraySliceSliceMulSliceAssign_u",
|
||||
// "_arraySliceSliceMulSliceAssign_w",
|
||||
//
|
||||
// "_arraySliceSliceMulass_d", // T[]*=T[]
|
||||
// "_arraySliceSliceMulass_f", // T[]*=T[]
|
||||
// "_arraySliceSliceMulass_i",
|
||||
// "_arraySliceSliceMulass_k",
|
||||
// "_arraySliceSliceMulass_s",
|
||||
// "_arraySliceSliceMulass_t",
|
||||
// "_arraySliceSliceMulass_u",
|
||||
// "_arraySliceSliceMulass_w",
|
||||
// };
|
||||
//
|
||||
// int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
|
||||
// if (i == -1)
|
||||
// {
|
||||
// #ifdef DEBUG // Make sure our array is alphabetized
|
||||
// for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
|
||||
// {
|
||||
// if (strcmp(name, libArrayopFuncs[i]) == 0)
|
||||
// assert(0);
|
||||
// }
|
||||
// #endif
|
||||
|
||||
/* Not in library, so generate it.
|
||||
* Construct the function body:
|
||||
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
|
||||
* loopbody;
|
||||
* return p;
|
||||
*/
|
||||
|
||||
Arguments *fparams = new Arguments();
|
||||
Expression *loopbody = buildArrayLoop(fparams);
|
||||
Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
|
||||
#if DMDV1
|
||||
// for (size_t i = 0; i < p.length; i++)
|
||||
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
|
||||
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
|
||||
Statement *s1 = new ForStatement(0,
|
||||
new DeclarationStatement(0, d),
|
||||
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
|
||||
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
|
||||
new ExpStatement(0, loopbody));
|
||||
#else
|
||||
// foreach (i; 0 .. p.length)
|
||||
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
|
||||
new Argument(0, NULL, Id::p, NULL),
|
||||
new IntegerExp(0, 0, Type::tint32),
|
||||
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
|
||||
new ExpStatement(0, loopbody));
|
||||
#endif
|
||||
Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
|
||||
//printf("s2: %s\n", s2->toChars());
|
||||
Statement *fbody = new CompoundStatement(0, s1, s2);
|
||||
|
||||
/* Construct the function
|
||||
*/
|
||||
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
|
||||
//printf("ftype: %s\n", ftype->toChars());
|
||||
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
|
||||
fd->fbody = fbody;
|
||||
fd->protection = PROTprotected;
|
||||
fd->linkage = LINKd;
|
||||
|
||||
// special attention for array ops
|
||||
fd->isArrayOp = true;
|
||||
|
||||
sc->module->members->push(fd);
|
||||
|
||||
sc = sc->push();
|
||||
sc->parent = sc->module;
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
fd->semantic(sc);
|
||||
sc->pop();
|
||||
// }
|
||||
// else
|
||||
// { /* In library, refer to it.
|
||||
// */
|
||||
// // FIXME
|
||||
// fd = FuncDeclaration::genCfunc(NULL, type, name);
|
||||
// }
|
||||
sv->ptrvalue = fd; // cache symbol in hash table
|
||||
}
|
||||
|
||||
/* Call the function fd(arguments)
|
||||
*/
|
||||
Expression *ec = new VarExp(0, fd);
|
||||
Expression *e = new CallExp(loc, ec, arguments);
|
||||
e->type = type;
|
||||
return e;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Construct the identifier for the array operation function,
|
||||
* and build the argument list to pass to it.
|
||||
*/
|
||||
|
||||
void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
buf->writestring("Exp");
|
||||
arguments->shift(this);
|
||||
}
|
||||
|
||||
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
buf->writestring("Slice");
|
||||
arguments->shift(this);
|
||||
}
|
||||
|
||||
void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
/* Evaluate assign expressions right to left
|
||||
*/
|
||||
e2->buildArrayIdent(buf, arguments);
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
buf->writestring("Assign");
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
|
||||
{ \
|
||||
/* Evaluate assign expressions right to left \
|
||||
*/ \
|
||||
e2->buildArrayIdent(buf, arguments); \
|
||||
e1->buildArrayIdent(buf, arguments); \
|
||||
buf->writestring(#Str); \
|
||||
buf->writestring("ass"); \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
buf->writestring("Neg");
|
||||
}
|
||||
|
||||
void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
buf->writestring("Com");
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
|
||||
{ \
|
||||
/* Evaluate assign expressions left to right \
|
||||
*/ \
|
||||
e1->buildArrayIdent(buf, arguments); \
|
||||
e2->buildArrayIdent(buf, arguments); \
|
||||
buf->writestring(#Str); \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
/******************************************
|
||||
* Construct the inner loop for the array operation function,
|
||||
* and build the parameter list.
|
||||
*/
|
||||
|
||||
Expression *Expression::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("c", fparams->dim);
|
||||
Argument *param = new Argument(0, type, id, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *e = new IdentifierExp(0, id);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *SliceExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("p", fparams->dim);
|
||||
Argument *param = new Argument(STCconst, type, id, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *e = new IdentifierExp(0, id);
|
||||
Expressions *arguments = new Expressions();
|
||||
Expression *index = new IdentifierExp(0, Id::p);
|
||||
arguments->push(index);
|
||||
e = new ArrayExp(0, e, arguments);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *AssignExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
/* Evaluate assign expressions right to left
|
||||
*/
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams);
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Argument *param = (Argument *)fparams->data[0];
|
||||
param->storageClass = 0;
|
||||
Expression *e = new AssignExp(0, ex1, ex2);
|
||||
return e;
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \
|
||||
{ \
|
||||
/* Evaluate assign expressions right to left \
|
||||
*/ \
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams); \
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams); \
|
||||
Argument *param = (Argument *)fparams->data[0]; \
|
||||
param->storageClass = 0; \
|
||||
Expression *e = new Str##AssignExp(0, ex1, ex2); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
Expression *NegExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Expression *e = new NegExp(0, ex1);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *ComExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Expression *e = new ComExp(0, ex1);
|
||||
return e;
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \
|
||||
{ \
|
||||
/* Evaluate assign expressions left to right \
|
||||
*/ \
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams); \
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams); \
|
||||
Expression *e = new Str##Exp(0, ex1, ex2); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
|
||||
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "rmem.h"
|
||||
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "scope.h"
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
#include "init.h"
|
||||
|
||||
#if IN_DMD
|
||||
extern int binary(const char *p , const char **tab, int high);
|
||||
|
||||
/**************************************
|
||||
* Hash table of array op functions already generated or known about.
|
||||
*/
|
||||
|
||||
StringTable arrayfuncs;
|
||||
#endif
|
||||
|
||||
/***********************************
|
||||
* Construct the array operation expression.
|
||||
*/
|
||||
|
||||
Expression *BinExp::arrayOp(Scope *sc)
|
||||
{
|
||||
Expressions *arguments = new Expressions();
|
||||
|
||||
/* The expression to generate an array operation for is mangled
|
||||
* into a name to use as the array operation function name.
|
||||
* Mangle in the operands and operators in RPN order, and type.
|
||||
*/
|
||||
OutBuffer buf;
|
||||
buf.writestring("_array");
|
||||
buildArrayIdent(&buf, arguments);
|
||||
buf.writeByte('_');
|
||||
|
||||
/* Append deco of array element type
|
||||
*/
|
||||
#if DMDV2
|
||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
|
||||
#else
|
||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
|
||||
#endif
|
||||
|
||||
size_t namelen = buf.offset;
|
||||
buf.writeByte(0);
|
||||
char *name = (char *)buf.extractData();
|
||||
|
||||
/* Look up name in hash table
|
||||
*/
|
||||
#if IN_LLVM
|
||||
StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
|
||||
#else
|
||||
StringValue *sv = arrayfuncs.update(name, namelen);
|
||||
#endif
|
||||
FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
|
||||
if (!fd)
|
||||
{
|
||||
#if IN_DMD
|
||||
/* Some of the array op functions are written as library functions,
|
||||
* presumably to optimize them with special CPU vector instructions.
|
||||
* List those library functions here, in alpha order.
|
||||
*/
|
||||
static const char *libArrayopFuncs[] =
|
||||
{
|
||||
"_arrayExpSliceAddass_a",
|
||||
"_arrayExpSliceAddass_d", // T[]+=T
|
||||
"_arrayExpSliceAddass_f", // T[]+=T
|
||||
"_arrayExpSliceAddass_g",
|
||||
"_arrayExpSliceAddass_h",
|
||||
"_arrayExpSliceAddass_i",
|
||||
"_arrayExpSliceAddass_k",
|
||||
"_arrayExpSliceAddass_s",
|
||||
"_arrayExpSliceAddass_t",
|
||||
"_arrayExpSliceAddass_u",
|
||||
"_arrayExpSliceAddass_w",
|
||||
|
||||
"_arrayExpSliceDivass_d", // T[]/=T
|
||||
"_arrayExpSliceDivass_f", // T[]/=T
|
||||
|
||||
"_arrayExpSliceMinSliceAssign_a",
|
||||
"_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
|
||||
"_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
|
||||
"_arrayExpSliceMinSliceAssign_g",
|
||||
"_arrayExpSliceMinSliceAssign_h",
|
||||
"_arrayExpSliceMinSliceAssign_i",
|
||||
"_arrayExpSliceMinSliceAssign_k",
|
||||
"_arrayExpSliceMinSliceAssign_s",
|
||||
"_arrayExpSliceMinSliceAssign_t",
|
||||
"_arrayExpSliceMinSliceAssign_u",
|
||||
"_arrayExpSliceMinSliceAssign_w",
|
||||
|
||||
"_arrayExpSliceMinass_a",
|
||||
"_arrayExpSliceMinass_d", // T[]-=T
|
||||
"_arrayExpSliceMinass_f", // T[]-=T
|
||||
"_arrayExpSliceMinass_g",
|
||||
"_arrayExpSliceMinass_h",
|
||||
"_arrayExpSliceMinass_i",
|
||||
"_arrayExpSliceMinass_k",
|
||||
"_arrayExpSliceMinass_s",
|
||||
"_arrayExpSliceMinass_t",
|
||||
"_arrayExpSliceMinass_u",
|
||||
"_arrayExpSliceMinass_w",
|
||||
|
||||
"_arrayExpSliceMulass_d", // T[]*=T
|
||||
"_arrayExpSliceMulass_f", // T[]*=T
|
||||
"_arrayExpSliceMulass_i",
|
||||
"_arrayExpSliceMulass_k",
|
||||
"_arrayExpSliceMulass_s",
|
||||
"_arrayExpSliceMulass_t",
|
||||
"_arrayExpSliceMulass_u",
|
||||
"_arrayExpSliceMulass_w",
|
||||
|
||||
"_arraySliceExpAddSliceAssign_a",
|
||||
"_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
|
||||
"_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
|
||||
"_arraySliceExpAddSliceAssign_g",
|
||||
"_arraySliceExpAddSliceAssign_h",
|
||||
"_arraySliceExpAddSliceAssign_i",
|
||||
"_arraySliceExpAddSliceAssign_k",
|
||||
"_arraySliceExpAddSliceAssign_s",
|
||||
"_arraySliceExpAddSliceAssign_t",
|
||||
"_arraySliceExpAddSliceAssign_u",
|
||||
"_arraySliceExpAddSliceAssign_w",
|
||||
|
||||
"_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
|
||||
"_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
|
||||
|
||||
"_arraySliceExpMinSliceAssign_a",
|
||||
"_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
|
||||
"_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
|
||||
"_arraySliceExpMinSliceAssign_g",
|
||||
"_arraySliceExpMinSliceAssign_h",
|
||||
"_arraySliceExpMinSliceAssign_i",
|
||||
"_arraySliceExpMinSliceAssign_k",
|
||||
"_arraySliceExpMinSliceAssign_s",
|
||||
"_arraySliceExpMinSliceAssign_t",
|
||||
"_arraySliceExpMinSliceAssign_u",
|
||||
"_arraySliceExpMinSliceAssign_w",
|
||||
|
||||
"_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
|
||||
"_arraySliceExpMulSliceAddass_f",
|
||||
"_arraySliceExpMulSliceAddass_r",
|
||||
|
||||
"_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
|
||||
"_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
|
||||
"_arraySliceExpMulSliceAssign_i",
|
||||
"_arraySliceExpMulSliceAssign_k",
|
||||
"_arraySliceExpMulSliceAssign_s",
|
||||
"_arraySliceExpMulSliceAssign_t",
|
||||
"_arraySliceExpMulSliceAssign_u",
|
||||
"_arraySliceExpMulSliceAssign_w",
|
||||
|
||||
"_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
|
||||
"_arraySliceExpMulSliceMinass_f",
|
||||
"_arraySliceExpMulSliceMinass_r",
|
||||
|
||||
"_arraySliceSliceAddSliceAssign_a",
|
||||
"_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
|
||||
"_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
|
||||
"_arraySliceSliceAddSliceAssign_g",
|
||||
"_arraySliceSliceAddSliceAssign_h",
|
||||
"_arraySliceSliceAddSliceAssign_i",
|
||||
"_arraySliceSliceAddSliceAssign_k",
|
||||
"_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
|
||||
"_arraySliceSliceAddSliceAssign_s",
|
||||
"_arraySliceSliceAddSliceAssign_t",
|
||||
"_arraySliceSliceAddSliceAssign_u",
|
||||
"_arraySliceSliceAddSliceAssign_w",
|
||||
|
||||
"_arraySliceSliceAddass_a",
|
||||
"_arraySliceSliceAddass_d", // T[]+=T[]
|
||||
"_arraySliceSliceAddass_f", // T[]+=T[]
|
||||
"_arraySliceSliceAddass_g",
|
||||
"_arraySliceSliceAddass_h",
|
||||
"_arraySliceSliceAddass_i",
|
||||
"_arraySliceSliceAddass_k",
|
||||
"_arraySliceSliceAddass_s",
|
||||
"_arraySliceSliceAddass_t",
|
||||
"_arraySliceSliceAddass_u",
|
||||
"_arraySliceSliceAddass_w",
|
||||
|
||||
"_arraySliceSliceMinSliceAssign_a",
|
||||
"_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
|
||||
"_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
|
||||
"_arraySliceSliceMinSliceAssign_g",
|
||||
"_arraySliceSliceMinSliceAssign_h",
|
||||
"_arraySliceSliceMinSliceAssign_i",
|
||||
"_arraySliceSliceMinSliceAssign_k",
|
||||
"_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
|
||||
"_arraySliceSliceMinSliceAssign_s",
|
||||
"_arraySliceSliceMinSliceAssign_t",
|
||||
"_arraySliceSliceMinSliceAssign_u",
|
||||
"_arraySliceSliceMinSliceAssign_w",
|
||||
|
||||
"_arraySliceSliceMinass_a",
|
||||
"_arraySliceSliceMinass_d", // T[]-=T[]
|
||||
"_arraySliceSliceMinass_f", // T[]-=T[]
|
||||
"_arraySliceSliceMinass_g",
|
||||
"_arraySliceSliceMinass_h",
|
||||
"_arraySliceSliceMinass_i",
|
||||
"_arraySliceSliceMinass_k",
|
||||
"_arraySliceSliceMinass_s",
|
||||
"_arraySliceSliceMinass_t",
|
||||
"_arraySliceSliceMinass_u",
|
||||
"_arraySliceSliceMinass_w",
|
||||
|
||||
"_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
|
||||
"_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
|
||||
"_arraySliceSliceMulSliceAssign_i",
|
||||
"_arraySliceSliceMulSliceAssign_k",
|
||||
"_arraySliceSliceMulSliceAssign_s",
|
||||
"_arraySliceSliceMulSliceAssign_t",
|
||||
"_arraySliceSliceMulSliceAssign_u",
|
||||
"_arraySliceSliceMulSliceAssign_w",
|
||||
|
||||
"_arraySliceSliceMulass_d", // T[]*=T[]
|
||||
"_arraySliceSliceMulass_f", // T[]*=T[]
|
||||
"_arraySliceSliceMulass_i",
|
||||
"_arraySliceSliceMulass_k",
|
||||
"_arraySliceSliceMulass_s",
|
||||
"_arraySliceSliceMulass_t",
|
||||
"_arraySliceSliceMulass_u",
|
||||
"_arraySliceSliceMulass_w",
|
||||
};
|
||||
|
||||
int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
|
||||
if (i == -1)
|
||||
{
|
||||
#ifdef DEBUG // Make sure our array is alphabetized
|
||||
for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
|
||||
{
|
||||
if (strcmp(name, libArrayopFuncs[i]) == 0)
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* Not in library, so generate it.
|
||||
* Construct the function body:
|
||||
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
|
||||
* loopbody;
|
||||
* return p;
|
||||
*/
|
||||
|
||||
Arguments *fparams = new Arguments();
|
||||
Expression *loopbody = buildArrayLoop(fparams);
|
||||
Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
|
||||
#if DMDV1
|
||||
// for (size_t i = 0; i < p.length; i++)
|
||||
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
|
||||
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
|
||||
Statement *s1 = new ForStatement(0,
|
||||
new DeclarationStatement(0, d),
|
||||
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
|
||||
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
|
||||
new ExpStatement(0, loopbody));
|
||||
#else
|
||||
// foreach (i; 0 .. p.length)
|
||||
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
|
||||
new Argument(0, NULL, Id::p, NULL),
|
||||
new IntegerExp(0, 0, Type::tint32),
|
||||
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
|
||||
new ExpStatement(0, loopbody));
|
||||
#endif
|
||||
Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
|
||||
//printf("s2: %s\n", s2->toChars());
|
||||
Statement *fbody = new CompoundStatement(0, s1, s2);
|
||||
|
||||
/* Construct the function
|
||||
*/
|
||||
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
|
||||
//printf("ftype: %s\n", ftype->toChars());
|
||||
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
|
||||
fd->fbody = fbody;
|
||||
fd->protection = PROTpublic;
|
||||
fd->linkage = LINKd;
|
||||
|
||||
// special attention for array ops
|
||||
fd->isArrayOp = true;
|
||||
|
||||
sc->module->importedFrom->members->push(fd);
|
||||
|
||||
sc = sc->push();
|
||||
sc->parent = sc->module->importedFrom;
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKc;
|
||||
fd->semantic(sc);
|
||||
sc->pop();
|
||||
#if IN_DMD
|
||||
}
|
||||
else
|
||||
{ /* In library, refer to it.
|
||||
*/
|
||||
fd = FuncDeclaration::genCfunc(type, name);
|
||||
}
|
||||
#endif
|
||||
sv->ptrvalue = fd; // cache symbol in hash table
|
||||
}
|
||||
|
||||
/* Call the function fd(arguments)
|
||||
*/
|
||||
Expression *ec = new VarExp(0, fd);
|
||||
Expression *e = new CallExp(loc, ec, arguments);
|
||||
e->type = type;
|
||||
return e;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Construct the identifier for the array operation function,
|
||||
* and build the argument list to pass to it.
|
||||
*/
|
||||
|
||||
void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
buf->writestring("Exp");
|
||||
arguments->shift(this);
|
||||
}
|
||||
|
||||
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
buf->writestring("Slice");
|
||||
arguments->shift(this);
|
||||
}
|
||||
|
||||
void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
/* Evaluate assign expressions right to left
|
||||
*/
|
||||
e2->buildArrayIdent(buf, arguments);
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
buf->writestring("Assign");
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
|
||||
{ \
|
||||
/* Evaluate assign expressions right to left \
|
||||
*/ \
|
||||
e2->buildArrayIdent(buf, arguments); \
|
||||
e1->buildArrayIdent(buf, arguments); \
|
||||
buf->writestring(#Str); \
|
||||
buf->writestring("ass"); \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
buf->writestring("Neg");
|
||||
}
|
||||
|
||||
void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
buf->writestring("Com");
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
|
||||
{ \
|
||||
/* Evaluate assign expressions left to right \
|
||||
*/ \
|
||||
e1->buildArrayIdent(buf, arguments); \
|
||||
e2->buildArrayIdent(buf, arguments); \
|
||||
buf->writestring(#Str); \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
/******************************************
|
||||
* Construct the inner loop for the array operation function,
|
||||
* and build the parameter list.
|
||||
*/
|
||||
|
||||
Expression *Expression::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("c", fparams->dim);
|
||||
Argument *param = new Argument(0, type, id, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *e = new IdentifierExp(0, id);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *SliceExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("p", fparams->dim);
|
||||
Argument *param = new Argument(STCconst, type, id, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *e = new IdentifierExp(0, id);
|
||||
Expressions *arguments = new Expressions();
|
||||
Expression *index = new IdentifierExp(0, Id::p);
|
||||
arguments->push(index);
|
||||
e = new ArrayExp(0, e, arguments);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *AssignExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
/* Evaluate assign expressions right to left
|
||||
*/
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams);
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Argument *param = (Argument *)fparams->data[0];
|
||||
param->storageClass = 0;
|
||||
Expression *e = new AssignExp(0, ex1, ex2);
|
||||
return e;
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \
|
||||
{ \
|
||||
/* Evaluate assign expressions right to left \
|
||||
*/ \
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams); \
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams); \
|
||||
Argument *param = (Argument *)fparams->data[0]; \
|
||||
param->storageClass = 0; \
|
||||
Expression *e = new Str##AssignExp(0, ex1, ex2); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
Expression *NegExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Expression *e = new NegExp(0, ex1);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *ComExp::buildArrayLoop(Arguments *fparams)
|
||||
{
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Expression *e = new ComExp(0, ex1);
|
||||
return e;
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \
|
||||
{ \
|
||||
/* Evaluate assign expressions left to right \
|
||||
*/ \
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams); \
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams); \
|
||||
Expression *e = new Str##Exp(0, ex1, ex2); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
|
||||
#undef X
|
||||
|
||||
|
||||
|
||||
3036
dmd2/attrib.c
3036
dmd2/attrib.c
File diff suppressed because it is too large
Load Diff
@@ -50,8 +50,14 @@ struct AttribDeclaration : Dsymbol
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
AttribDeclaration *isAttribDeclaration() { return this; }
|
||||
|
||||
virtual void toObjFile(int multiobj); // compile to .obj file
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
int cvMember(unsigned char *p);
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
virtual void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct StorageClassDeclaration: AttribDeclaration
|
||||
@@ -62,6 +68,8 @@ struct StorageClassDeclaration: AttribDeclaration
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
static void stcToCBuffer(OutBuffer *buf, int stc);
|
||||
};
|
||||
|
||||
struct LinkDeclaration : AttribDeclaration
|
||||
@@ -107,9 +115,6 @@ struct AnonDeclaration : AttribDeclaration
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
|
||||
// LDC
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
};
|
||||
|
||||
struct PragmaDeclaration : AttribDeclaration
|
||||
@@ -122,7 +127,14 @@ struct PragmaDeclaration : AttribDeclaration
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ConditionalDeclaration : AttribDeclaration
|
||||
|
||||
42
dmd2/backendlicense.txt
Normal file
42
dmd2/backendlicense.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
The Software is not generally available software. It has not undergone
|
||||
testing and may contain errors. The Software was not designed to operate
|
||||
after December 31, 1999. It may be incomplete and it may not function
|
||||
properly. No support or maintenance is provided with this Software. Do
|
||||
not install or distribute the Software if
|
||||
you are not accustomed to using or distributing experimental software.
|
||||
Do not use this software for life critical applications, or applications
|
||||
that could cause significant harm or property damage.
|
||||
|
||||
Digital Mars licenses the Software to you on an "AS IS" basis, without
|
||||
warranty of any kind. DIGITAL MARS AND SYMANTEC HEREBY EXPRESSLY DISCLAIM
|
||||
ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY,
|
||||
NONINFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. You are solely
|
||||
responsible for determining the appropriateness of using this Software and
|
||||
assume all risks associated with the use of this Software, including but not
|
||||
limited to the risks of program errors, damage
|
||||
to or loss of data, programs or equipment, unavailability or interruption of
|
||||
operations and third party claims. You agree to defend, indemnify and hold
|
||||
Digital Mars and Symantec, its subsidiaries, affiliates, directors, officers,
|
||||
employees and agents harmless from all claims or demands made against them
|
||||
(and any related losses, damages, expenses
|
||||
and costs) arising out of your use of the Software. DIGITAL MARS AND SYMANTEC
|
||||
WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, INCIDENTAL, OR
|
||||
INDIRECT DAMAGES OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING
|
||||
LOST PROFITS OR SAVINGS), EVEN IF DIGITAL MARS OR SYMANTEC HAS BEEN ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
Digital Mars and Symantec will not be liable for the loss of, or damage to,
|
||||
your records or data, the records or
|
||||
data of any third party, or any damages claimed by you based on a third party
|
||||
claim.
|
||||
|
||||
If you send any messages to Digital Mars, on either the Digital Mars
|
||||
newsgroups, the Digital Mars mailing list, or via email, you agree not
|
||||
to make any claims of intellectual
|
||||
property rights over the contents of those messages.
|
||||
|
||||
The Software is copyrighted and comes with a single user license,
|
||||
and may not be redistributed. If you wish to obtain a redistribution license,
|
||||
please contact Digital Mars.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -23,12 +23,15 @@
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
|
||||
#if DMDV2
|
||||
|
||||
/**********************************
|
||||
* Determine if function is a builtin one.
|
||||
* Determine if function is a builtin one that we can
|
||||
* evaluate at compile time.
|
||||
*/
|
||||
enum BUILTIN FuncDeclaration::isBuiltin()
|
||||
{
|
||||
static const char FeZe[] = "FeZe"; // real function(real)
|
||||
static const char FeZe[] = "FNaNbeZe"; // pure nothrow real function(real)
|
||||
|
||||
//printf("FuncDeclaration::isBuiltin() %s\n", toChars());
|
||||
if (builtin == BUILTINunknown)
|
||||
@@ -36,10 +39,12 @@ enum BUILTIN FuncDeclaration::isBuiltin()
|
||||
builtin = BUILTINnot;
|
||||
if (parent && parent->isModule())
|
||||
{
|
||||
// If it's in the std.math package
|
||||
if (parent->ident == Id::math &&
|
||||
parent->parent && parent->parent->ident == Id::std &&
|
||||
!parent->parent->parent)
|
||||
{
|
||||
//printf("deco = %s\n", type->deco);
|
||||
if (strcmp(type->deco, FeZe) == 0)
|
||||
{
|
||||
if (ident == Id::sin)
|
||||
@@ -54,6 +59,13 @@ enum BUILTIN FuncDeclaration::isBuiltin()
|
||||
builtin = BUILTINfabs;
|
||||
//printf("builtin = %d\n", builtin);
|
||||
}
|
||||
// if float or double versions
|
||||
else if (strcmp(type->deco, "FNaNbdZd") == 0 ||
|
||||
strcmp(type->deco, "FNaNbfZf") == 0)
|
||||
{
|
||||
if (ident == Id::_sqrt)
|
||||
builtin = BUILTINsqrt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,28 +87,30 @@ Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments)
|
||||
{
|
||||
case BUILTINsin:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, sinl(arg0->toReal()), Type::tfloat80);
|
||||
e = new RealExp(0, sinl(arg0->toReal()), arg0->type);
|
||||
break;
|
||||
|
||||
case BUILTINcos:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, cosl(arg0->toReal()), Type::tfloat80);
|
||||
e = new RealExp(0, cosl(arg0->toReal()), arg0->type);
|
||||
break;
|
||||
|
||||
case BUILTINtan:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, tanl(arg0->toReal()), Type::tfloat80);
|
||||
e = new RealExp(0, tanl(arg0->toReal()), arg0->type);
|
||||
break;
|
||||
|
||||
case BUILTINsqrt:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, sqrtl(arg0->toReal()), Type::tfloat80);
|
||||
e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type);
|
||||
break;
|
||||
|
||||
case BUILTINfabs:
|
||||
if (arg0->op == TOKfloat64)
|
||||
e = new RealExp(0, fabsl(arg0->toReal()), Type::tfloat80);
|
||||
e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
3484
dmd2/cast.c
3484
dmd2/cast.c
File diff suppressed because it is too large
Load Diff
2854
dmd2/class.c
2854
dmd2/class.c
File diff suppressed because it is too large
Load Diff
880
dmd2/clone.c
880
dmd2/clone.c
@@ -1,437 +1,443 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "init.h"
|
||||
|
||||
|
||||
/*******************************************
|
||||
* We need an opAssign for the struct if
|
||||
* it has a destructor or a postblit.
|
||||
* We need to generate one if a user-specified one does not exist.
|
||||
*/
|
||||
|
||||
int StructDeclaration::needOpAssign()
|
||||
{
|
||||
#define X 0
|
||||
if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
|
||||
if (hasIdentityAssign)
|
||||
goto Ldontneed;
|
||||
|
||||
if (dtor || postblit)
|
||||
goto Lneed;
|
||||
|
||||
/* If any of the fields need an opAssign, then we
|
||||
* need it too.
|
||||
*/
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
Type *tv = v->type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->needOpAssign())
|
||||
goto Lneed;
|
||||
}
|
||||
}
|
||||
Ldontneed:
|
||||
if (X) printf("\tdontneed\n");
|
||||
return 0;
|
||||
|
||||
Lneed:
|
||||
if (X) printf("\tneed\n");
|
||||
return 1;
|
||||
#undef X
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Build opAssign for struct.
|
||||
* S* opAssign(S s) { ... }
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
||||
{
|
||||
if (!needOpAssign())
|
||||
return NULL;
|
||||
|
||||
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
|
||||
FuncDeclaration *fop = NULL;
|
||||
|
||||
Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
|
||||
Arguments *fparams = new Arguments;
|
||||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
|
||||
#if STRUCTTHISREF
|
||||
((TypeFunction *)ftype)->isref = 1;
|
||||
#endif
|
||||
|
||||
fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
|
||||
|
||||
Expression *e = NULL;
|
||||
if (postblit)
|
||||
{ /* Swap:
|
||||
* tmp = *this; *this = s; tmp.dtor();
|
||||
*/
|
||||
//printf("\tswap copy\n");
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
VarDeclaration *tmp;
|
||||
AssignExp *ec = NULL;
|
||||
if (dtor)
|
||||
{
|
||||
tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
|
||||
tmp->noauto = 1;
|
||||
e = new DeclarationExp(0, tmp);
|
||||
ec = new AssignExp(0,
|
||||
new VarExp(0, tmp),
|
||||
#if STRUCTTHISREF
|
||||
new ThisExp(0)
|
||||
#else
|
||||
new PtrExp(0, new ThisExp(0))
|
||||
#endif
|
||||
);
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
ec = new AssignExp(0,
|
||||
#if STRUCTTHISREF
|
||||
new ThisExp(0),
|
||||
#else
|
||||
new PtrExp(0, new ThisExp(0)),
|
||||
#endif
|
||||
new IdentifierExp(0, Id::p));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
if (dtor)
|
||||
{
|
||||
/* Instead of running the destructor on s, run it
|
||||
* on tmp. This avoids needing to copy tmp back in to s.
|
||||
*/
|
||||
Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
|
||||
ec = new CallExp(0, ec);
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Do memberwise copy
|
||||
*/
|
||||
//printf("\tmemberwise copy\n");
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
// this.v = s.v;
|
||||
AssignExp *ec = new AssignExp(0,
|
||||
new DotVarExp(0, new ThisExp(0), v, 0),
|
||||
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
Statement *s1 = new ExpStatement(0, e);
|
||||
|
||||
/* Add:
|
||||
* return this;
|
||||
*/
|
||||
e = new ThisExp(0);
|
||||
Statement *s2 = new ReturnStatement(0, e);
|
||||
|
||||
fop->fbody = new CompoundStatement(0, s1, s2);
|
||||
|
||||
members->push(fop);
|
||||
fop->addMember(sc, this, 1);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
|
||||
fop->semantic(sc);
|
||||
|
||||
sc->pop();
|
||||
|
||||
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
|
||||
return fop;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Build copy constructor for struct.
|
||||
* Copy constructors are compiler generated only, and are only
|
||||
* callable from the compiler. They are not user accessible.
|
||||
* A copy constructor is:
|
||||
* void cpctpr(ref S s)
|
||||
* {
|
||||
* *this = s;
|
||||
* this.postBlit();
|
||||
* }
|
||||
* This is done so:
|
||||
* - postBlit() never sees uninitialized data
|
||||
* - memcpy can be much more efficient than memberwise copy
|
||||
* - no fields are overlooked
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
|
||||
FuncDeclaration *fcp = NULL;
|
||||
|
||||
/* Copy constructor is only necessary if there is a postblit function,
|
||||
* otherwise the code generator will just do a bit copy.
|
||||
*/
|
||||
if (postblit)
|
||||
{
|
||||
//printf("generating cpctor\n");
|
||||
|
||||
Argument *param = new Argument(STCref, type, Id::p, NULL);
|
||||
Arguments *fparams = new Arguments;
|
||||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
|
||||
|
||||
// Build *this = p;
|
||||
Expression *e = new ThisExp(0);
|
||||
#if !STRUCTTHISREF
|
||||
e = new PtrExp(0, e);
|
||||
#endif
|
||||
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
|
||||
ea->op = TOKblit;
|
||||
Statement *s = new ExpStatement(0, ea);
|
||||
|
||||
// Build postBlit();
|
||||
e = new VarExp(0, postblit, 0);
|
||||
e = new CallExp(0, e);
|
||||
|
||||
s = new CompoundStatement(0, s, new ExpStatement(0, e));
|
||||
fcp->fbody = s;
|
||||
|
||||
members->push(fcp);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
|
||||
fcp->semantic(sc);
|
||||
|
||||
sc->pop();
|
||||
}
|
||||
|
||||
return fcp;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Create inclusive postblit for struct by aggregating
|
||||
* all the postblits in postblits[] with the postblits for
|
||||
* all the members.
|
||||
* Note the close similarity with AggregateDeclaration::buildDtor(),
|
||||
* and the ordering changes (runs forward instead of backwards).
|
||||
*/
|
||||
|
||||
#if DMDV2
|
||||
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
|
||||
Expression *e = NULL;
|
||||
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
Type *tv = v->type->toBasetype();
|
||||
size_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->postblit)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 1)
|
||||
{ // this.v.dtor()
|
||||
ex = new DotVarExp(0, ex, sd->postblit, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Typeinfo.postblit(cast(void*)&this.v);
|
||||
Expression *ea = new AddrExp(0, ex);
|
||||
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
|
||||
|
||||
Expression *et = v->type->getTypeInfo(sc);
|
||||
et = new DotIdExp(0, et, Id::postblit);
|
||||
|
||||
ex = new CallExp(0, et, ea);
|
||||
}
|
||||
e = Expression::combine(e, ex); // combine in forward order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our own "postblit" which executes e
|
||||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldPostBlit()\n");
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
dtors.push(dd);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
}
|
||||
|
||||
switch (postblits.dim)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return (FuncDeclaration *)postblits.data[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < postblits.dim; i++)
|
||||
{ FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(e, ex);
|
||||
}
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************
|
||||
* Create inclusive destructor for struct/class by aggregating
|
||||
* all the destructors in dtors[] with the destructors for
|
||||
* all the members.
|
||||
* Note the close similarity with StructDeclaration::buildPostBlit(),
|
||||
* and the ordering changes (runs backward instead of forwards).
|
||||
*/
|
||||
|
||||
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
{
|
||||
//printf("AggregateDeclaration::buildDtor() %s\n", toChars());
|
||||
Expression *e = NULL;
|
||||
|
||||
#if DMDV2
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
Type *tv = v->type->toBasetype();
|
||||
size_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 1)
|
||||
{ // this.v.dtor()
|
||||
ex = new DotVarExp(0, ex, sd->dtor, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Typeinfo.destroy(cast(void*)&this.v);
|
||||
Expression *ea = new AddrExp(0, ex);
|
||||
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
|
||||
|
||||
Expression *et = v->type->getTypeInfo(sc);
|
||||
et = new DotIdExp(0, et, Id::destroy);
|
||||
|
||||
ex = new CallExp(0, et, ea);
|
||||
}
|
||||
e = Expression::combine(ex, e); // combine in reverse order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our own "destructor" which executes e
|
||||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldDtor()\n");
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
dtors.shift(dd);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (dtors.dim)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return (FuncDeclaration *)dtors.data[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < dtors.dim; i++)
|
||||
{ FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(ex, e);
|
||||
}
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
#include "expression.h"
|
||||
#include "statement.h"
|
||||
#include "init.h"
|
||||
|
||||
|
||||
/*******************************************
|
||||
* We need an opAssign for the struct if
|
||||
* it has a destructor or a postblit.
|
||||
* We need to generate one if a user-specified one does not exist.
|
||||
*/
|
||||
|
||||
int StructDeclaration::needOpAssign()
|
||||
{
|
||||
#define X 0
|
||||
if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
|
||||
if (hasIdentityAssign)
|
||||
goto Ldontneed;
|
||||
|
||||
if (dtor || postblit)
|
||||
goto Lneed;
|
||||
|
||||
/* If any of the fields need an opAssign, then we
|
||||
* need it too.
|
||||
*/
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->needOpAssign())
|
||||
goto Lneed;
|
||||
}
|
||||
}
|
||||
Ldontneed:
|
||||
if (X) printf("\tdontneed\n");
|
||||
return 0;
|
||||
|
||||
Lneed:
|
||||
if (X) printf("\tneed\n");
|
||||
return 1;
|
||||
#undef X
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Build opAssign for struct.
|
||||
* S* opAssign(S s) { ... }
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
||||
{
|
||||
if (!needOpAssign())
|
||||
return NULL;
|
||||
|
||||
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
|
||||
FuncDeclaration *fop = NULL;
|
||||
|
||||
Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
|
||||
Arguments *fparams = new Arguments;
|
||||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
|
||||
#if STRUCTTHISREF
|
||||
((TypeFunction *)ftype)->isref = 1;
|
||||
#endif
|
||||
|
||||
fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
|
||||
|
||||
Expression *e = NULL;
|
||||
if (postblit)
|
||||
{ /* Swap:
|
||||
* tmp = *this; *this = s; tmp.dtor();
|
||||
*/
|
||||
//printf("\tswap copy\n");
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
VarDeclaration *tmp;
|
||||
AssignExp *ec = NULL;
|
||||
if (dtor)
|
||||
{
|
||||
tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
|
||||
tmp->noauto = 1;
|
||||
e = new DeclarationExp(0, tmp);
|
||||
ec = new AssignExp(0,
|
||||
new VarExp(0, tmp),
|
||||
#if STRUCTTHISREF
|
||||
new ThisExp(0)
|
||||
#else
|
||||
new PtrExp(0, new ThisExp(0))
|
||||
#endif
|
||||
);
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
ec = new AssignExp(0,
|
||||
#if STRUCTTHISREF
|
||||
new ThisExp(0),
|
||||
#else
|
||||
new PtrExp(0, new ThisExp(0)),
|
||||
#endif
|
||||
new IdentifierExp(0, Id::p));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
if (dtor)
|
||||
{
|
||||
/* Instead of running the destructor on s, run it
|
||||
* on tmp. This avoids needing to copy tmp back in to s.
|
||||
*/
|
||||
Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
|
||||
ec = new CallExp(0, ec);
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Do memberwise copy
|
||||
*/
|
||||
//printf("\tmemberwise copy\n");
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
// this.v = s.v;
|
||||
AssignExp *ec = new AssignExp(0,
|
||||
new DotVarExp(0, new ThisExp(0), v, 0),
|
||||
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
|
||||
ec->op = TOKblit;
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
Statement *s1 = new ExpStatement(0, e);
|
||||
|
||||
/* Add:
|
||||
* return this;
|
||||
*/
|
||||
e = new ThisExp(0);
|
||||
Statement *s2 = new ReturnStatement(0, e);
|
||||
|
||||
fop->fbody = new CompoundStatement(0, s1, s2);
|
||||
|
||||
members->push(fop);
|
||||
fop->addMember(sc, this, 1);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
|
||||
fop->semantic(sc);
|
||||
|
||||
sc->pop();
|
||||
|
||||
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
|
||||
return fop;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Build copy constructor for struct.
|
||||
* Copy constructors are compiler generated only, and are only
|
||||
* callable from the compiler. They are not user accessible.
|
||||
* A copy constructor is:
|
||||
* void cpctpr(ref S s)
|
||||
* {
|
||||
* *this = s;
|
||||
* this.postBlit();
|
||||
* }
|
||||
* This is done so:
|
||||
* - postBlit() never sees uninitialized data
|
||||
* - memcpy can be much more efficient than memberwise copy
|
||||
* - no fields are overlooked
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
|
||||
FuncDeclaration *fcp = NULL;
|
||||
|
||||
/* Copy constructor is only necessary if there is a postblit function,
|
||||
* otherwise the code generator will just do a bit copy.
|
||||
*/
|
||||
if (postblit)
|
||||
{
|
||||
//printf("generating cpctor\n");
|
||||
|
||||
Argument *param = new Argument(STCref, type, Id::p, NULL);
|
||||
Arguments *fparams = new Arguments;
|
||||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
|
||||
|
||||
// Build *this = p;
|
||||
Expression *e = new ThisExp(0);
|
||||
#if !STRUCTTHISREF
|
||||
e = new PtrExp(0, e);
|
||||
#endif
|
||||
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
|
||||
ea->op = TOKblit;
|
||||
Statement *s = new ExpStatement(0, ea);
|
||||
|
||||
// Build postBlit();
|
||||
e = new VarExp(0, postblit, 0);
|
||||
e = new CallExp(0, e);
|
||||
|
||||
s = new CompoundStatement(0, s, new ExpStatement(0, e));
|
||||
fcp->fbody = s;
|
||||
|
||||
members->push(fcp);
|
||||
|
||||
sc = sc->push();
|
||||
sc->stc = 0;
|
||||
sc->linkage = LINKd;
|
||||
|
||||
fcp->semantic(sc);
|
||||
|
||||
sc->pop();
|
||||
}
|
||||
|
||||
return fcp;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Create inclusive postblit for struct by aggregating
|
||||
* all the postblits in postblits[] with the postblits for
|
||||
* all the members.
|
||||
* Note the close similarity with AggregateDeclaration::buildDtor(),
|
||||
* and the ordering changes (runs forward instead of backwards).
|
||||
*/
|
||||
|
||||
#if DMDV2
|
||||
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
|
||||
Expression *e = NULL;
|
||||
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
size_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->postblit)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 1)
|
||||
{ // this.v.postblit()
|
||||
ex = new DotVarExp(0, ex, sd->postblit, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Typeinfo.postblit(cast(void*)&this.v);
|
||||
Expression *ea = new AddrExp(0, ex);
|
||||
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
|
||||
|
||||
Expression *et = v->type->getTypeInfo(sc);
|
||||
et = new DotIdExp(0, et, Id::postblit);
|
||||
|
||||
ex = new CallExp(0, et, ea);
|
||||
}
|
||||
e = Expression::combine(e, ex); // combine in forward order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our own "postblit" which executes e
|
||||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldPostBlit()\n");
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
postblits.shift(dd);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
}
|
||||
|
||||
switch (postblits.dim)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return (FuncDeclaration *)postblits.data[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < postblits.dim; i++)
|
||||
{ FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(e, ex);
|
||||
}
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************
|
||||
* Create inclusive destructor for struct/class by aggregating
|
||||
* all the destructors in dtors[] with the destructors for
|
||||
* all the members.
|
||||
* Note the close similarity with StructDeclaration::buildPostBlit(),
|
||||
* and the ordering changes (runs backward instead of forwards).
|
||||
*/
|
||||
|
||||
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
{
|
||||
//printf("AggregateDeclaration::buildDtor() %s\n", toChars());
|
||||
Expression *e = NULL;
|
||||
|
||||
#if DMDV2
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)fields.data[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
size_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 1)
|
||||
{ // this.v.dtor()
|
||||
ex = new DotVarExp(0, ex, sd->dtor, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Typeinfo.destroy(cast(void*)&this.v);
|
||||
Expression *ea = new AddrExp(0, ex);
|
||||
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
|
||||
|
||||
Expression *et = v->type->getTypeInfo(sc);
|
||||
et = new DotIdExp(0, et, Id::destroy);
|
||||
|
||||
ex = new CallExp(0, et, ea);
|
||||
}
|
||||
e = Expression::combine(ex, e); // combine in reverse order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our own "destructor" which executes e
|
||||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldDtor()\n");
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
dtors.shift(dd);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (dtors.dim)
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return (FuncDeclaration *)dtors.data[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < dtors.dim; i++)
|
||||
{ FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(ex, e);
|
||||
}
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
796
dmd2/cond.c
796
dmd2/cond.c
@@ -1,391 +1,405 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "identifier.h"
|
||||
#include "expression.h"
|
||||
#include "cond.h"
|
||||
#include "module.h"
|
||||
#include "template.h"
|
||||
#include "lexer.h"
|
||||
#ifdef _DH
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#endif
|
||||
|
||||
int findCondition(Array *ids, Identifier *ident)
|
||||
{
|
||||
if (ids)
|
||||
{
|
||||
for (int i = 0; i < ids->dim; i++)
|
||||
{
|
||||
const char *id = (const char *)ids->data[i];
|
||||
|
||||
if (strcmp(id, ident->toChars()) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
Condition::Condition(Loc loc)
|
||||
{
|
||||
this->loc = loc;
|
||||
inc = 0;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: Condition(0)
|
||||
{
|
||||
this->mod = mod;
|
||||
this->level = level;
|
||||
this->ident = ident;
|
||||
}
|
||||
|
||||
Condition *DVCondition::syntaxCopy()
|
||||
{
|
||||
return this; // don't need to copy
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void DebugCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.debuglevel = level;
|
||||
}
|
||||
|
||||
void DebugCondition::addGlobalIdent(const char *ident)
|
||||
{
|
||||
if (!global.params.debugids)
|
||||
global.params.debugids = new Array();
|
||||
global.params.debugids->push((void *)ident);
|
||||
}
|
||||
|
||||
|
||||
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->debugids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.debugids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{ if (!mod->debugidsNot)
|
||||
mod->debugidsNot = new Array();
|
||||
mod->debugidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("debug (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("debug (%u)", level);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void VersionCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.versionlevel = level;
|
||||
}
|
||||
|
||||
void VersionCondition::checkPredefined(Loc loc, const char *ident)
|
||||
{
|
||||
static const char* reserved[] =
|
||||
{
|
||||
"DigitalMars", "LLVM", "LDC", "LLVM64",
|
||||
"X86", "X86_64", "PPC", "PPC64",
|
||||
"Windows", "Win32", "Win64",
|
||||
"linux", "darwin", "Posix",
|
||||
"LittleEndian", "BigEndian",
|
||||
"all",
|
||||
"none",
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
|
||||
{
|
||||
if (strcmp(ident, reserved[i]) == 0)
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (ident[0] == 'D' && ident[1] == '_')
|
||||
goto Lerror;
|
||||
|
||||
return;
|
||||
|
||||
Lerror:
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addGlobalIdent(const char *ident)
|
||||
{
|
||||
checkPredefined(0, ident);
|
||||
addPredefinedGlobalIdent(ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addPredefinedGlobalIdent(const char *ident)
|
||||
{
|
||||
if (!global.params.versionids)
|
||||
global.params.versionids = new Array();
|
||||
global.params.versionids->push((void *)ident);
|
||||
}
|
||||
|
||||
|
||||
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
|
||||
//if (ident) printf("\tident = '%s'\n", ident->toChars());
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->versionids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.versionids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{
|
||||
if (!mod->versionidsNot)
|
||||
mod->versionidsNot = new Array();
|
||||
mod->versionidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("version (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("version (%u)", level);
|
||||
}
|
||||
|
||||
|
||||
/**************************** StaticIfCondition *******************************/
|
||||
|
||||
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
}
|
||||
|
||||
Condition *StaticIfCondition::syntaxCopy()
|
||||
{
|
||||
return new StaticIfCondition(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
#if 0
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
||||
if (s)
|
||||
{
|
||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||
}
|
||||
#endif
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "static if conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc = sc->push(sc->scopesym);
|
||||
sc->sd = s; // s gets any addMember()
|
||||
sc->flags |= SCOPEstaticif;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc->pop();
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
else if (e->isBool(FALSE))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("static if(");
|
||||
exp->toCBuffer(buf, hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
/**************************** IftypeCondition *******************************/
|
||||
|
||||
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->targ = targ;
|
||||
this->id = id;
|
||||
this->tok = tok;
|
||||
this->tspec = tspec;
|
||||
}
|
||||
|
||||
Condition *IftypeCondition::syntaxCopy()
|
||||
{
|
||||
return new IftypeCondition(loc,
|
||||
targ->syntaxCopy(),
|
||||
id,
|
||||
tok,
|
||||
tspec ? tspec->syntaxCopy() : NULL);
|
||||
}
|
||||
|
||||
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
||||
{
|
||||
//printf("IftypeCondition::include()\n");
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "iftype conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
unsigned errors = global.errors;
|
||||
global.gag++; // suppress printing of error messages
|
||||
targ = targ->semantic(loc, sc);
|
||||
global.gag--;
|
||||
if (errors != global.errors) // if any errors happened
|
||||
{ inc = 2; // then condition is false
|
||||
global.errors = errors;
|
||||
}
|
||||
else if (id && tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec.
|
||||
* If TRUE, declare id as an alias for the specialized type.
|
||||
*/
|
||||
|
||||
MATCH m;
|
||||
TemplateTypeParameter tp(loc, id, NULL, NULL);
|
||||
|
||||
TemplateParameters parameters;
|
||||
parameters.setDim(1);
|
||||
parameters.data[0] = (void *)&tp;
|
||||
|
||||
Objects dedtypes;
|
||||
dedtypes.setDim(1);
|
||||
|
||||
m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes);
|
||||
if (m == MATCHnomatch ||
|
||||
(m != MATCHexact && tok == TOKequal))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
inc = 1;
|
||||
Type *tded = (Type *)dedtypes.data[0];
|
||||
if (!tded)
|
||||
tded = targ;
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
}
|
||||
}
|
||||
else if (id)
|
||||
{
|
||||
/* Declare id as an alias for type targ. Evaluate to TRUE
|
||||
*/
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, targ);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
inc = 1;
|
||||
}
|
||||
else if (tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec
|
||||
*/
|
||||
tspec = tspec->semantic(loc, sc);
|
||||
//printf("targ = %s\n", targ->toChars());
|
||||
//printf("tspec = %s\n", tspec->toChars());
|
||||
if (tok == TOKcolon)
|
||||
{ if (targ->implicitConvTo(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
else /* == */
|
||||
{ if (targ->equals(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
inc = 1;
|
||||
//printf("inc = %d\n", inc);
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("iftype(");
|
||||
targ->toCBuffer(buf, id, hgs);
|
||||
if (tspec)
|
||||
{
|
||||
if (tok == TOKcolon)
|
||||
buf->writestring(" : ");
|
||||
else
|
||||
buf->writestring(" == ");
|
||||
tspec->toCBuffer(buf, NULL, hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "identifier.h"
|
||||
#include "expression.h"
|
||||
#include "cond.h"
|
||||
#include "module.h"
|
||||
#include "template.h"
|
||||
#include "lexer.h"
|
||||
#ifdef _DH
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#endif
|
||||
|
||||
int findCondition(Array *ids, Identifier *ident)
|
||||
{
|
||||
if (ids)
|
||||
{
|
||||
for (int i = 0; i < ids->dim; i++)
|
||||
{
|
||||
const char *id = (const char *)ids->data[i];
|
||||
|
||||
if (strcmp(id, ident->toChars()) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
Condition::Condition(Loc loc)
|
||||
{
|
||||
this->loc = loc;
|
||||
inc = 0;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: Condition(0)
|
||||
{
|
||||
this->mod = mod;
|
||||
this->level = level;
|
||||
this->ident = ident;
|
||||
}
|
||||
|
||||
Condition *DVCondition::syntaxCopy()
|
||||
{
|
||||
return this; // don't need to copy
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void DebugCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.debuglevel = level;
|
||||
}
|
||||
|
||||
void DebugCondition::addGlobalIdent(const char *ident)
|
||||
{
|
||||
if (!global.params.debugids)
|
||||
global.params.debugids = new Array();
|
||||
global.params.debugids->push((void *)ident);
|
||||
}
|
||||
|
||||
|
||||
DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->debugids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.debugids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{ if (!mod->debugidsNot)
|
||||
mod->debugidsNot = new Array();
|
||||
mod->debugidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("debug (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("debug (%u)", level);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
void VersionCondition::setGlobalLevel(unsigned level)
|
||||
{
|
||||
global.params.versionlevel = level;
|
||||
}
|
||||
|
||||
void VersionCondition::checkPredefined(Loc loc, const char *ident)
|
||||
{
|
||||
static const char* reserved[] =
|
||||
{
|
||||
"DigitalMars", "X86", "X86_64",
|
||||
"Windows", "Win32", "Win64",
|
||||
"linux",
|
||||
#if DMDV2
|
||||
/* Although Posix is predefined by D1, disallowing its
|
||||
* redefinition breaks makefiles and older builds.
|
||||
*/
|
||||
"Posix",
|
||||
"D_NET",
|
||||
#endif
|
||||
"OSX", "FreeBSD",
|
||||
"Solaris",
|
||||
"LittleEndian", "BigEndian",
|
||||
"all",
|
||||
"none",
|
||||
|
||||
// LDC
|
||||
"LLVM", "LDC", "LLVM64",
|
||||
"PPC", "PPC64",
|
||||
"darwin","solaris","freebsd"
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
|
||||
{
|
||||
if (strcmp(ident, reserved[i]) == 0)
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (ident[0] == 'D' && ident[1] == '_')
|
||||
goto Lerror;
|
||||
|
||||
return;
|
||||
|
||||
Lerror:
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addGlobalIdent(const char *ident)
|
||||
{
|
||||
checkPredefined(0, ident);
|
||||
addPredefinedGlobalIdent(ident);
|
||||
}
|
||||
|
||||
void VersionCondition::addPredefinedGlobalIdent(const char *ident)
|
||||
{
|
||||
if (!global.params.versionids)
|
||||
global.params.versionids = new Array();
|
||||
global.params.versionids->push((void *)ident);
|
||||
}
|
||||
|
||||
|
||||
VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
: DVCondition(mod, level, ident)
|
||||
{
|
||||
}
|
||||
|
||||
int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
|
||||
//if (ident) printf("\tident = '%s'\n", ident->toChars());
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->versionids, ident))
|
||||
inc = 1;
|
||||
else if (findCondition(global.params.versionids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
{
|
||||
if (!mod->versionidsNot)
|
||||
mod->versionidsNot = new Array();
|
||||
mod->versionidsNot->push(ident->toChars());
|
||||
}
|
||||
}
|
||||
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
|
||||
inc = 1;
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (ident)
|
||||
buf->printf("version (%s)", ident->toChars());
|
||||
else
|
||||
buf->printf("version (%u)", level);
|
||||
}
|
||||
|
||||
|
||||
/**************************** StaticIfCondition *******************************/
|
||||
|
||||
StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
}
|
||||
|
||||
Condition *StaticIfCondition::syntaxCopy()
|
||||
{
|
||||
return new StaticIfCondition(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
#if 0
|
||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
||||
if (s)
|
||||
{
|
||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||
}
|
||||
#endif
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "static if conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc = sc->push(sc->scopesym);
|
||||
sc->sd = s; // s gets any addMember()
|
||||
sc->flags |= SCOPEstaticif;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc->pop();
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
else if (e->isBool(FALSE))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("static if(");
|
||||
exp->toCBuffer(buf, hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
/**************************** IftypeCondition *******************************/
|
||||
|
||||
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
|
||||
: Condition(loc)
|
||||
{
|
||||
this->targ = targ;
|
||||
this->id = id;
|
||||
this->tok = tok;
|
||||
this->tspec = tspec;
|
||||
}
|
||||
|
||||
Condition *IftypeCondition::syntaxCopy()
|
||||
{
|
||||
return new IftypeCondition(loc,
|
||||
targ->syntaxCopy(),
|
||||
id,
|
||||
tok,
|
||||
tspec ? tspec->syntaxCopy() : NULL);
|
||||
}
|
||||
|
||||
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
|
||||
{
|
||||
//printf("IftypeCondition::include()\n");
|
||||
if (inc == 0)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
error(loc, "iftype conditional cannot be at global scope");
|
||||
inc = 2;
|
||||
return 0;
|
||||
}
|
||||
Type *t = targ->trySemantic(loc, sc);
|
||||
if (t)
|
||||
targ = t;
|
||||
else
|
||||
inc = 2; // condition is false
|
||||
|
||||
if (!t)
|
||||
{
|
||||
}
|
||||
else if (id && tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec.
|
||||
* If TRUE, declare id as an alias for the specialized type.
|
||||
*/
|
||||
|
||||
MATCH m;
|
||||
TemplateTypeParameter tp(loc, id, NULL, NULL);
|
||||
|
||||
TemplateParameters parameters;
|
||||
parameters.setDim(1);
|
||||
parameters.data[0] = (void *)&tp;
|
||||
|
||||
Objects dedtypes;
|
||||
dedtypes.setDim(1);
|
||||
|
||||
m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes);
|
||||
if (m == MATCHnomatch ||
|
||||
(m != MATCHexact && tok == TOKequal))
|
||||
inc = 2;
|
||||
else
|
||||
{
|
||||
inc = 1;
|
||||
Type *tded = (Type *)dedtypes.data[0];
|
||||
if (!tded)
|
||||
tded = targ;
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
}
|
||||
}
|
||||
else if (id)
|
||||
{
|
||||
/* Declare id as an alias for type targ. Evaluate to TRUE
|
||||
*/
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, targ);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
if (sd)
|
||||
s->addMember(sc, sd, 1);
|
||||
inc = 1;
|
||||
}
|
||||
else if (tspec)
|
||||
{
|
||||
/* Evaluate to TRUE if targ matches tspec
|
||||
*/
|
||||
tspec = tspec->semantic(loc, sc);
|
||||
//printf("targ = %s\n", targ->toChars());
|
||||
//printf("tspec = %s\n", tspec->toChars());
|
||||
if (tok == TOKcolon)
|
||||
{ if (targ->implicitConvTo(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
else /* == */
|
||||
{ if (targ->equals(tspec))
|
||||
inc = 1;
|
||||
else
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
inc = 1;
|
||||
//printf("inc = %d\n", inc);
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
|
||||
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("iftype(");
|
||||
targ->toCBuffer(buf, id, hgs);
|
||||
if (tspec)
|
||||
{
|
||||
if (tok == TOKcolon)
|
||||
buf->writestring(" : ");
|
||||
else
|
||||
buf->writestring(" == ");
|
||||
tspec->toCBuffer(buf, NULL, hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
|
||||
|
||||
3202
dmd2/constfold.c
3202
dmd2/constfold.c
File diff suppressed because it is too large
Load Diff
381
dmd2/cppmangle.c
Normal file
381
dmd2/cppmangle.c
Normal file
@@ -0,0 +1,381 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "dsymbol.h"
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#include "init.h"
|
||||
#include "expression.h"
|
||||
#include "attrib.h"
|
||||
#include "declaration.h"
|
||||
#include "template.h"
|
||||
#include "id.h"
|
||||
#include "enum.h"
|
||||
#include "import.h"
|
||||
#include "aggregate.h"
|
||||
|
||||
#if DMDV2
|
||||
|
||||
/* Do mangling for C++ linkage.
|
||||
* Follows Itanium C++ ABI 1.86
|
||||
* No attempt is made to support mangling of templates, operator
|
||||
* overloading, or special functions.
|
||||
*
|
||||
* So why don't we use the C++ ABI for D name mangling?
|
||||
* Because D supports a lot of things (like modules) that the C++
|
||||
* ABI has no concept of. These affect every D mangled name,
|
||||
* so nothing would be compatible anyway.
|
||||
*/
|
||||
|
||||
struct CppMangleState
|
||||
{
|
||||
static Array components;
|
||||
|
||||
int substitute(OutBuffer *buf, void *p);
|
||||
};
|
||||
|
||||
Array CppMangleState::components;
|
||||
|
||||
|
||||
void writeBase36(OutBuffer *buf, unsigned i)
|
||||
{
|
||||
if (i >= 36)
|
||||
{
|
||||
writeBase36(buf, i / 36);
|
||||
i %= 36;
|
||||
}
|
||||
if (i < 10)
|
||||
buf->writeByte(i + '0');
|
||||
else if (i < 36)
|
||||
buf->writeByte(i - 10 + 'A');
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int CppMangleState::substitute(OutBuffer *buf, void *p)
|
||||
{
|
||||
for (size_t i = 0; i < components.dim; i++)
|
||||
{
|
||||
if (p == components.data[i])
|
||||
{
|
||||
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
|
||||
*/
|
||||
buf->writeByte('S');
|
||||
if (i)
|
||||
writeBase36(buf, i - 1);
|
||||
buf->writeByte('_');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
components.push(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void source_name(OutBuffer *buf, Dsymbol *s)
|
||||
{
|
||||
char *name = s->ident->toChars();
|
||||
buf->printf("%d%s", strlen(name), name);
|
||||
}
|
||||
|
||||
void prefix_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
|
||||
{
|
||||
if (!cms->substitute(buf, s))
|
||||
{
|
||||
Dsymbol *p = s->toParent();
|
||||
if (p && !p->isModule())
|
||||
{
|
||||
prefix_name(buf, cms, p);
|
||||
}
|
||||
source_name(buf, s);
|
||||
}
|
||||
}
|
||||
|
||||
void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
|
||||
{
|
||||
Dsymbol *p = s->toParent();
|
||||
if (p && !p->isModule())
|
||||
{
|
||||
buf->writeByte('N');
|
||||
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd->isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
prefix_name(buf, cms, p);
|
||||
source_name(buf, s);
|
||||
|
||||
buf->writeByte('E');
|
||||
}
|
||||
else
|
||||
source_name(buf, s);
|
||||
}
|
||||
|
||||
|
||||
char *cpp_mangle(Dsymbol *s)
|
||||
{
|
||||
/*
|
||||
* <mangled-name> ::= _Z <encoding>
|
||||
* <encoding> ::= <function name> <bare-function-type>
|
||||
* ::= <data name>
|
||||
* ::= <special-name>
|
||||
*/
|
||||
|
||||
CppMangleState cms;
|
||||
memset(&cms, 0, sizeof(cms));
|
||||
cms.components.setDim(0);
|
||||
|
||||
OutBuffer buf;
|
||||
#if MACHOBJ
|
||||
buf.writestring("__Z");
|
||||
#else
|
||||
buf.writestring("_Z");
|
||||
#endif
|
||||
|
||||
cpp_mangle_name(&buf, &cms, s);
|
||||
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{ // add <bare-function-type>
|
||||
TypeFunction *tf = (TypeFunction *)fd->type;
|
||||
assert(tf->ty == Tfunction);
|
||||
Argument::argsCppMangle(&buf, &cms, tf->parameters, tf->varargs);
|
||||
}
|
||||
buf.writeByte(0);
|
||||
return (char *)buf.extractData();
|
||||
}
|
||||
|
||||
/* ============= Type Encodings ============================================= */
|
||||
|
||||
void Type::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
/* Make this the 'vendor extended type' when there is no
|
||||
* C++ analog.
|
||||
* u <source-name>
|
||||
*/
|
||||
if (!cms->substitute(buf, this))
|
||||
{ assert(deco);
|
||||
buf->printf("u%d%s", strlen(deco), deco);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{ char c;
|
||||
char p = 0;
|
||||
|
||||
/* ABI spec says:
|
||||
* v void
|
||||
* w wchar_t
|
||||
* b bool
|
||||
* c char
|
||||
* a signed char
|
||||
* h unsigned char
|
||||
* s short
|
||||
* t unsigned short
|
||||
* i int
|
||||
* j unsigned int
|
||||
* l long
|
||||
* m unsigned long
|
||||
* x long long, __int64
|
||||
* y unsigned long long, __int64
|
||||
* n __int128
|
||||
* o unsigned __int128
|
||||
* f float
|
||||
* d double
|
||||
* e long double, __float80
|
||||
* g __float128
|
||||
* z ellipsis
|
||||
* u <source-name> # vendor extended type
|
||||
*/
|
||||
|
||||
switch (ty)
|
||||
{
|
||||
case Tvoid: c = 'v'; break;
|
||||
case Tint8: c = 'a'; break;
|
||||
case Tuns8: c = 'h'; break;
|
||||
case Tint16: c = 's'; break;
|
||||
case Tuns16: c = 't'; break;
|
||||
case Tint32: c = 'i'; break;
|
||||
case Tuns32: c = 'j'; break;
|
||||
case Tfloat32: c = 'f'; break;
|
||||
case Tint64: c = 'x'; break;
|
||||
case Tuns64: c = 'y'; break;
|
||||
case Tfloat64: c = 'd'; break;
|
||||
case Tfloat80: c = 'e'; break;
|
||||
case Tbool: c = 'b'; break;
|
||||
case Tchar: c = 'c'; break;
|
||||
case Twchar: c = 't'; break;
|
||||
case Tdchar: c = 'w'; break;
|
||||
|
||||
case Timaginary32: p = 'G'; c = 'f'; break;
|
||||
case Timaginary64: p = 'G'; c = 'd'; break;
|
||||
case Timaginary80: p = 'G'; c = 'e'; break;
|
||||
case Tcomplex32: p = 'C'; c = 'f'; break;
|
||||
case Tcomplex64: p = 'C'; c = 'd'; break;
|
||||
case Tcomplex80: p = 'C'; c = 'e'; break;
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
if (cms->substitute(buf, this))
|
||||
return;
|
||||
buf->writeByte(p);
|
||||
}
|
||||
buf->writeByte(c);
|
||||
}
|
||||
|
||||
|
||||
void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->printf("A%ju_", dim ? dim->toInteger() : 0);
|
||||
next->toCppMangle(buf, cms);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->writeByte('P');
|
||||
next->toCppMangle(buf, cms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->writeByte('R');
|
||||
next->toCppMangle(buf, cms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{ /*
|
||||
* <function-type> ::= F [Y] <bare-function-type> E
|
||||
* <bare-function-type> ::= <signature type>+
|
||||
* # types are possible return type, then parameter types
|
||||
*/
|
||||
|
||||
/* ABI says:
|
||||
"The type of a non-static member function is considered to be different,
|
||||
for the purposes of substitution, from the type of a namespace-scope or
|
||||
static member function whose type appears similar. The types of two
|
||||
non-static member functions are considered to be different, for the
|
||||
purposes of substitution, if the functions are members of different
|
||||
classes. In other words, for the purposes of substitution, the class of
|
||||
which the function is a member is considered part of the type of
|
||||
function."
|
||||
|
||||
BUG: Right now, types of functions are never merged, so our simplistic
|
||||
component matcher always finds them to be different.
|
||||
We should use Type::equals on these, and use different
|
||||
TypeFunctions for non-static member functions, and non-static
|
||||
member functions of different classes.
|
||||
*/
|
||||
if (!cms->substitute(buf, this))
|
||||
{
|
||||
buf->writeByte('F');
|
||||
if (linkage == LINKc)
|
||||
buf->writeByte('Y');
|
||||
next->toCppMangle(buf, cms);
|
||||
Argument::argsCppMangle(buf, cms, parameters, varargs);
|
||||
buf->writeByte('E');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
}
|
||||
|
||||
|
||||
void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
}
|
||||
|
||||
|
||||
void TypeTypedef::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->writeByte('P');
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Argument::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs)
|
||||
{ int n = 0;
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Argument *arg = (Argument *)arguments->data[i];
|
||||
Type *t = arg->type;
|
||||
if (arg->storageClass & (STCout | STCref))
|
||||
t = t->referenceTo();
|
||||
else if (arg->storageClass & STClazy)
|
||||
{ // Mangle as delegate
|
||||
Type *td = new TypeFunction(NULL, t, 0, LINKd);
|
||||
td = new TypeDelegate(td);
|
||||
t = t->merge();
|
||||
}
|
||||
if (t->ty == Tsarray)
|
||||
{ // Mangle static arrays as pointers
|
||||
t = t->pointerTo();
|
||||
}
|
||||
t->toCppMangle(buf, cms);
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (varargs)
|
||||
buf->writestring("z");
|
||||
else if (!n)
|
||||
buf->writeByte('v'); // encode ( ) arguments
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
3376
dmd2/declaration.c
3376
dmd2/declaration.c
File diff suppressed because it is too large
Load Diff
1828
dmd2/declaration.h
1828
dmd2/declaration.h
File diff suppressed because it is too large
Load Diff
4047
dmd2/doc.c
4047
dmd2/doc.c
File diff suppressed because it is too large
Load Diff
2431
dmd2/dsymbol.c
2431
dmd2/dsymbol.c
File diff suppressed because it is too large
Load Diff
678
dmd2/dsymbol.h
678
dmd2/dsymbol.h
@@ -1,326 +1,352 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_DSYMBOL_H
|
||||
#define DMD_DSYMBOL_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "arraytypes.h"
|
||||
|
||||
// llvm
|
||||
#include "../ir/irsymbol.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Scope;
|
||||
struct DsymbolTable;
|
||||
struct Declaration;
|
||||
struct TupleDeclaration;
|
||||
struct TypedefDeclaration;
|
||||
struct AliasDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct EnumDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct StructDeclaration;
|
||||
struct UnionDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct FuncAliasDeclaration;
|
||||
struct FuncLiteralDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct PostBlitDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct StaticCtorDeclaration;
|
||||
struct StaticDtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct UnitTestDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct AttribDeclaration;
|
||||
struct Symbol;
|
||||
struct Package;
|
||||
struct Module;
|
||||
struct Import;
|
||||
struct Type;
|
||||
struct TypeTuple;
|
||||
struct WithStatement;
|
||||
struct LabelDsymbol;
|
||||
struct TemplateDeclaration;
|
||||
struct TemplateInstance;
|
||||
struct TemplateMixin;
|
||||
struct EnumMember;
|
||||
struct ScopeDsymbol;
|
||||
struct WithScopeSymbol;
|
||||
struct ArrayScopeSymbol;
|
||||
struct StaticStructInitDeclaration;
|
||||
struct Expression;
|
||||
struct DeleteDeclaration;
|
||||
struct HdrGenState;
|
||||
struct OverloadSet;
|
||||
struct TypeInfoDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
|
||||
#if IN_GCC
|
||||
union tree_node;
|
||||
typedef union tree_node TYPE;
|
||||
#else
|
||||
struct TYPE;
|
||||
#endif
|
||||
|
||||
// llvm
|
||||
#if IN_LLVM
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum PROT
|
||||
{
|
||||
PROTundefined,
|
||||
PROTnone, // no access
|
||||
PROTprivate,
|
||||
PROTpackage,
|
||||
PROTprotected,
|
||||
PROTpublic,
|
||||
PROTexport,
|
||||
};
|
||||
|
||||
|
||||
struct Dsymbol : Object
|
||||
{
|
||||
Identifier *ident;
|
||||
Identifier *c_ident;
|
||||
Dsymbol *parent;
|
||||
Symbol *csym; // symbol for code generator
|
||||
Symbol *isym; // import version of csym
|
||||
unsigned char *comment; // documentation comment for this Dsymbol
|
||||
Loc loc; // where defined
|
||||
|
||||
Dsymbol();
|
||||
Dsymbol(Identifier *);
|
||||
char *toChars();
|
||||
char *toPrettyChars();
|
||||
char *locToChars();
|
||||
int equals(Object *o);
|
||||
int isAnonymous();
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void error(const char *format, ...);
|
||||
void checkDeprecated(Loc loc, Scope *sc);
|
||||
Module *getModule();
|
||||
Module *getCompilationModule(); // possibly different for templates
|
||||
Dsymbol *pastMixin();
|
||||
Dsymbol *toParent();
|
||||
Dsymbol *toParent2();
|
||||
TemplateInstance *inTemplateInstance();
|
||||
|
||||
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
||||
|
||||
static Array *arraySyntaxCopy(Array *a);
|
||||
|
||||
virtual const char *kind();
|
||||
virtual Dsymbol *toAlias(); // resolve real symbol
|
||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
virtual void semantic(Scope *sc);
|
||||
virtual void semantic2(Scope *sc);
|
||||
virtual void semantic3(Scope *sc);
|
||||
virtual void inlineScan();
|
||||
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
|
||||
virtual int overloadInsert(Dsymbol *s);
|
||||
#ifdef _DH
|
||||
char *toHChars();
|
||||
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#endif
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual void toDocBuffer(OutBuffer *buf);
|
||||
virtual unsigned size(Loc loc);
|
||||
virtual int isforwardRef();
|
||||
virtual void defineRef(Dsymbol *s);
|
||||
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
|
||||
virtual ClassDeclaration *isClassMember(); // are we a member of a class?
|
||||
virtual int isExport(); // is Dsymbol exported?
|
||||
virtual int isImportedSymbol(); // is Dsymbol imported?
|
||||
virtual int isDeprecated(); // is Dsymbol deprecated?
|
||||
virtual int isOverloadable();
|
||||
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
||||
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
||||
virtual Type *getType(); // is this a type?
|
||||
virtual char *mangle();
|
||||
virtual int needThis(); // need a 'this' pointer?
|
||||
virtual enum PROT prot();
|
||||
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
virtual int oneMember(Dsymbol **ps);
|
||||
static int oneMembers(Array *members, Dsymbol **ps);
|
||||
virtual int hasPointers();
|
||||
virtual void addLocalClass(ClassDeclarations *) { }
|
||||
virtual void checkCtorConstInit() { }
|
||||
|
||||
virtual void addComment(unsigned char *comment);
|
||||
virtual void emitComment(Scope *sc);
|
||||
void emitDitto(Scope *sc);
|
||||
|
||||
// Backend
|
||||
|
||||
virtual Symbol *toSymbol(); // to backend symbol
|
||||
virtual void toObjFile(int multiobj); // compile to .obj file
|
||||
virtual int cvMember(unsigned char *p); // emit cv debug info for member
|
||||
|
||||
Symbol *toImport(); // to backend import symbol
|
||||
static Symbol *toImport(Symbol *s); // to backend import symbol
|
||||
|
||||
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
|
||||
|
||||
// Eliminate need for dynamic_cast
|
||||
virtual Package *isPackage() { return NULL; }
|
||||
virtual Module *isModule() { return NULL; }
|
||||
virtual EnumMember *isEnumMember() { return NULL; }
|
||||
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
|
||||
virtual TemplateInstance *isTemplateInstance() { return NULL; }
|
||||
virtual TemplateMixin *isTemplateMixin() { return NULL; }
|
||||
virtual Declaration *isDeclaration() { return NULL; }
|
||||
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
|
||||
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
|
||||
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
|
||||
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
|
||||
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
|
||||
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
|
||||
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
|
||||
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
|
||||
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
|
||||
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
|
||||
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
|
||||
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
|
||||
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
|
||||
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
|
||||
virtual NewDeclaration *isNewDeclaration() { return NULL; }
|
||||
virtual VarDeclaration *isVarDeclaration() { return NULL; }
|
||||
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
|
||||
virtual StructDeclaration *isStructDeclaration() { return NULL; }
|
||||
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
|
||||
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
|
||||
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
|
||||
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
|
||||
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
|
||||
virtual Import *isImport() { return NULL; }
|
||||
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
|
||||
#ifdef _DH
|
||||
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
|
||||
#endif
|
||||
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
|
||||
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
|
||||
virtual OverloadSet *isOverloadSet() { return NULL; }
|
||||
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
|
||||
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
|
||||
|
||||
// llvm stuff
|
||||
int llvmInternal;
|
||||
|
||||
IrDsymbol ir;
|
||||
};
|
||||
|
||||
// Dsymbol that generates a scope
|
||||
|
||||
struct ScopeDsymbol : Dsymbol
|
||||
{
|
||||
Array *members; // all Dsymbol's in this scope
|
||||
DsymbolTable *symtab; // members[] sorted into table
|
||||
|
||||
Array *imports; // imported ScopeDsymbol's
|
||||
unsigned char *prots; // array of PROT, one for each import
|
||||
|
||||
ScopeDsymbol();
|
||||
ScopeDsymbol(Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void importScope(ScopeDsymbol *s, enum PROT protection);
|
||||
int isforwardRef();
|
||||
void defineRef(Dsymbol *s);
|
||||
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
|
||||
Dsymbol *nameCollision(Dsymbol *s);
|
||||
const char *kind();
|
||||
FuncDeclaration *findGetMembers();
|
||||
|
||||
void emitMemberComments(Scope *sc);
|
||||
|
||||
static size_t dim(Array *members);
|
||||
static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
|
||||
|
||||
ScopeDsymbol *isScopeDsymbol() { return this; }
|
||||
};
|
||||
|
||||
// With statement scope
|
||||
|
||||
struct WithScopeSymbol : ScopeDsymbol
|
||||
{
|
||||
WithStatement *withstate;
|
||||
|
||||
WithScopeSymbol(WithStatement *withstate);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
WithScopeSymbol *isWithScopeSymbol() { return this; }
|
||||
};
|
||||
|
||||
// Array Index/Slice scope
|
||||
|
||||
struct ArrayScopeSymbol : ScopeDsymbol
|
||||
{
|
||||
Expression *exp; // IndexExp or SliceExp
|
||||
TypeTuple *type; // for tuple[length]
|
||||
TupleDeclaration *td; // for tuples of objects
|
||||
Scope *sc;
|
||||
|
||||
ArrayScopeSymbol(Scope *sc, Expression *e);
|
||||
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
|
||||
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
|
||||
};
|
||||
|
||||
// Overload Sets
|
||||
|
||||
struct OverloadSet : Dsymbol
|
||||
{
|
||||
Dsymbols a; // array of Dsymbols
|
||||
|
||||
OverloadSet();
|
||||
void push(Dsymbol *s);
|
||||
OverloadSet *isOverloadSet() { return this; }
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
// Table of Dsymbol's
|
||||
|
||||
struct DsymbolTable : Object
|
||||
{
|
||||
StringTable *tab;
|
||||
|
||||
DsymbolTable();
|
||||
~DsymbolTable();
|
||||
|
||||
// Look up Identifier. Return Dsymbol if found, NULL if not.
|
||||
Dsymbol *lookup(Identifier *ident);
|
||||
|
||||
// Insert Dsymbol in table. Return NULL if already there.
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
|
||||
Dsymbol *update(Dsymbol *s);
|
||||
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
|
||||
};
|
||||
|
||||
#endif /* DMD_DSYMBOL_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_DSYMBOL_H
|
||||
#define DMD_DSYMBOL_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "arraytypes.h"
|
||||
|
||||
#if IN_LLVM
|
||||
#include "../ir/irdsymbol.h"
|
||||
#endif
|
||||
|
||||
struct Identifier;
|
||||
struct Scope;
|
||||
struct DsymbolTable;
|
||||
struct Declaration;
|
||||
struct ThisDeclaration;
|
||||
struct TupleDeclaration;
|
||||
struct TypedefDeclaration;
|
||||
struct AliasDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct EnumDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct StructDeclaration;
|
||||
struct UnionDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct FuncAliasDeclaration;
|
||||
struct FuncLiteralDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct PostBlitDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct StaticCtorDeclaration;
|
||||
struct StaticDtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct UnitTestDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct AttribDeclaration;
|
||||
#if IN_DMD
|
||||
struct Symbol;
|
||||
#endif
|
||||
struct Package;
|
||||
struct Module;
|
||||
struct Import;
|
||||
struct Type;
|
||||
struct TypeTuple;
|
||||
struct WithStatement;
|
||||
struct LabelDsymbol;
|
||||
struct TemplateDeclaration;
|
||||
struct TemplateInstance;
|
||||
struct TemplateMixin;
|
||||
struct EnumMember;
|
||||
struct ScopeDsymbol;
|
||||
struct WithScopeSymbol;
|
||||
struct ArrayScopeSymbol;
|
||||
struct StaticStructInitDeclaration;
|
||||
struct Expression;
|
||||
struct DeleteDeclaration;
|
||||
struct HdrGenState;
|
||||
struct OverloadSet;
|
||||
#if IN_LLVM
|
||||
struct TypeInfoDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
#endif
|
||||
|
||||
#if IN_DMD
|
||||
struct Symbol;
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
union tree_node;
|
||||
typedef union tree_node TYPE;
|
||||
#else
|
||||
struct TYPE;
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
class Ir;
|
||||
class IrSymbol;
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
#endif
|
||||
#if IN_DMD
|
||||
// Back end
|
||||
struct Classsym;
|
||||
#endif
|
||||
|
||||
enum PROT
|
||||
{
|
||||
PROTundefined,
|
||||
PROTnone, // no access
|
||||
PROTprivate,
|
||||
PROTpackage,
|
||||
PROTprotected,
|
||||
PROTpublic,
|
||||
PROTexport,
|
||||
};
|
||||
|
||||
|
||||
struct Dsymbol : Object
|
||||
{
|
||||
Identifier *ident;
|
||||
Identifier *c_ident;
|
||||
Dsymbol *parent;
|
||||
#if IN_DMD
|
||||
Symbol *csym; // symbol for code generator
|
||||
Symbol *isym; // import version of csym
|
||||
#endif
|
||||
unsigned char *comment; // documentation comment for this Dsymbol
|
||||
Loc loc; // where defined
|
||||
|
||||
Dsymbol();
|
||||
Dsymbol(Identifier *);
|
||||
char *toChars();
|
||||
char *toPrettyChars();
|
||||
char *locToChars();
|
||||
int equals(Object *o);
|
||||
int isAnonymous();
|
||||
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
|
||||
void error(const char *format, ...) IS_PRINTF(2);
|
||||
void checkDeprecated(Loc loc, Scope *sc);
|
||||
Module *getModule(); // module where declared
|
||||
Module *getCompilationModule(); // possibly different for templates
|
||||
Dsymbol *pastMixin();
|
||||
Dsymbol *toParent();
|
||||
Dsymbol *toParent2();
|
||||
TemplateInstance *inTemplateInstance();
|
||||
|
||||
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
||||
|
||||
static Array *arraySyntaxCopy(Array *a);
|
||||
|
||||
virtual const char *kind();
|
||||
virtual Dsymbol *toAlias(); // resolve real symbol
|
||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
virtual void semantic(Scope *sc);
|
||||
virtual void semantic2(Scope *sc);
|
||||
virtual void semantic3(Scope *sc);
|
||||
virtual void inlineScan();
|
||||
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
|
||||
virtual int overloadInsert(Dsymbol *s);
|
||||
#ifdef _DH
|
||||
char *toHChars();
|
||||
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#endif
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual void toDocBuffer(OutBuffer *buf);
|
||||
virtual unsigned size(Loc loc);
|
||||
virtual int isforwardRef();
|
||||
virtual void defineRef(Dsymbol *s);
|
||||
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
|
||||
virtual ClassDeclaration *isClassMember(); // are we a member of a class?
|
||||
virtual int isExport(); // is Dsymbol exported?
|
||||
virtual int isImportedSymbol(); // is Dsymbol imported?
|
||||
virtual int isDeprecated(); // is Dsymbol deprecated?
|
||||
virtual int isOverloadable();
|
||||
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
||||
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
||||
virtual Type *getType(); // is this a type?
|
||||
virtual char *mangle();
|
||||
virtual int needThis(); // need a 'this' pointer?
|
||||
virtual enum PROT prot();
|
||||
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
virtual int oneMember(Dsymbol **ps);
|
||||
static int oneMembers(Array *members, Dsymbol **ps);
|
||||
virtual int hasPointers();
|
||||
virtual void addLocalClass(ClassDeclarations *) { }
|
||||
virtual void checkCtorConstInit() { }
|
||||
|
||||
virtual void addComment(unsigned char *comment);
|
||||
virtual void emitComment(Scope *sc);
|
||||
void emitDitto(Scope *sc);
|
||||
|
||||
#if IN_DMD
|
||||
// Backend
|
||||
|
||||
virtual Symbol *toSymbol(); // to backend symbol
|
||||
virtual void toObjFile(int multiobj); // compile to .obj file
|
||||
virtual int cvMember(unsigned char *p); // emit cv debug info for member
|
||||
|
||||
Symbol *toImport(); // to backend import symbol
|
||||
static Symbol *toImport(Symbol *s); // to backend import symbol
|
||||
|
||||
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
|
||||
#endif
|
||||
|
||||
// Eliminate need for dynamic_cast
|
||||
virtual Package *isPackage() { return NULL; }
|
||||
virtual Module *isModule() { return NULL; }
|
||||
virtual EnumMember *isEnumMember() { return NULL; }
|
||||
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
|
||||
virtual TemplateInstance *isTemplateInstance() { return NULL; }
|
||||
virtual TemplateMixin *isTemplateMixin() { return NULL; }
|
||||
virtual Declaration *isDeclaration() { return NULL; }
|
||||
virtual ThisDeclaration *isThisDeclaration() { return NULL; }
|
||||
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
|
||||
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
|
||||
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
|
||||
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
|
||||
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
|
||||
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
|
||||
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
|
||||
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
|
||||
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
|
||||
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
|
||||
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
|
||||
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
|
||||
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
|
||||
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
|
||||
virtual NewDeclaration *isNewDeclaration() { return NULL; }
|
||||
virtual VarDeclaration *isVarDeclaration() { return NULL; }
|
||||
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
|
||||
virtual StructDeclaration *isStructDeclaration() { return NULL; }
|
||||
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
|
||||
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
|
||||
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
|
||||
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
|
||||
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
|
||||
virtual Import *isImport() { return NULL; }
|
||||
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
|
||||
#ifdef _DH
|
||||
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
|
||||
#endif
|
||||
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
|
||||
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
|
||||
virtual OverloadSet *isOverloadSet() { return NULL; }
|
||||
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
|
||||
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
|
||||
|
||||
#if IN_LLVM
|
||||
/// Codegen traversal
|
||||
virtual void codegen(Ir* ir);
|
||||
|
||||
// llvm stuff
|
||||
int llvmInternal;
|
||||
|
||||
IrDsymbol ir;
|
||||
IrSymbol* irsym;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Dsymbol that generates a scope
|
||||
|
||||
struct ScopeDsymbol : Dsymbol
|
||||
{
|
||||
Array *members; // all Dsymbol's in this scope
|
||||
DsymbolTable *symtab; // members[] sorted into table
|
||||
|
||||
Array *imports; // imported ScopeDsymbol's
|
||||
unsigned char *prots; // array of PROT, one for each import
|
||||
|
||||
ScopeDsymbol();
|
||||
ScopeDsymbol(Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void importScope(ScopeDsymbol *s, enum PROT protection);
|
||||
int isforwardRef();
|
||||
void defineRef(Dsymbol *s);
|
||||
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
|
||||
Dsymbol *nameCollision(Dsymbol *s);
|
||||
const char *kind();
|
||||
FuncDeclaration *findGetMembers();
|
||||
|
||||
void emitMemberComments(Scope *sc);
|
||||
|
||||
static size_t dim(Array *members);
|
||||
static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
|
||||
|
||||
ScopeDsymbol *isScopeDsymbol() { return this; }
|
||||
};
|
||||
|
||||
// With statement scope
|
||||
|
||||
struct WithScopeSymbol : ScopeDsymbol
|
||||
{
|
||||
WithStatement *withstate;
|
||||
|
||||
WithScopeSymbol(WithStatement *withstate);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
WithScopeSymbol *isWithScopeSymbol() { return this; }
|
||||
};
|
||||
|
||||
// Array Index/Slice scope
|
||||
|
||||
struct ArrayScopeSymbol : ScopeDsymbol
|
||||
{
|
||||
Expression *exp; // IndexExp or SliceExp
|
||||
TypeTuple *type; // for tuple[length]
|
||||
TupleDeclaration *td; // for tuples of objects
|
||||
Scope *sc;
|
||||
|
||||
ArrayScopeSymbol(Scope *sc, Expression *e);
|
||||
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
|
||||
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
|
||||
};
|
||||
|
||||
// Overload Sets
|
||||
|
||||
struct OverloadSet : Dsymbol
|
||||
{
|
||||
Dsymbols a; // array of Dsymbols
|
||||
|
||||
OverloadSet();
|
||||
void push(Dsymbol *s);
|
||||
OverloadSet *isOverloadSet() { return this; }
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
// Table of Dsymbol's
|
||||
|
||||
struct DsymbolTable : Object
|
||||
{
|
||||
StringTable *tab;
|
||||
|
||||
DsymbolTable();
|
||||
~DsymbolTable();
|
||||
|
||||
// Look up Identifier. Return Dsymbol if found, NULL if not.
|
||||
Dsymbol *lookup(Identifier *ident);
|
||||
|
||||
// Insert Dsymbol in table. Return NULL if already there.
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
|
||||
Dsymbol *update(Dsymbol *s);
|
||||
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
|
||||
};
|
||||
|
||||
#endif /* DMD_DSYMBOL_H */
|
||||
|
||||
@@ -52,7 +52,7 @@ void Expression::dump(int i)
|
||||
void IntegerExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %lld type=%s\n", this, (intmax_t)value, type_print(type));
|
||||
printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
|
||||
}
|
||||
|
||||
void IdentifierExp::dump(int i)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
@@ -30,7 +30,9 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
|
||||
maxval = NULL;
|
||||
minval = NULL;
|
||||
defaultval = NULL;
|
||||
#if IN_DMD
|
||||
sinit = NULL;
|
||||
#endif
|
||||
scope = NULL;
|
||||
isdeprecated = 0;
|
||||
}
|
||||
|
||||
186
dmd2/enum.h
186
dmd2/enum.h
@@ -1,90 +1,96 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_ENUM_H
|
||||
#define DMD_ENUM_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct Expression;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
|
||||
struct EnumDeclaration : ScopeDsymbol
|
||||
{ /* enum ident : memtype { ... }
|
||||
*/
|
||||
Type *type; // the TypeEnum
|
||||
Type *memtype; // type of the members
|
||||
|
||||
#if DMDV1
|
||||
integer_t maxval;
|
||||
integer_t minval;
|
||||
integer_t defaultval; // default initializer
|
||||
#else
|
||||
Expression *maxval;
|
||||
Expression *minval;
|
||||
Expression *defaultval; // default initializer
|
||||
|
||||
Scope *scope; // !=NULL means context to use
|
||||
#endif
|
||||
int isdeprecated;
|
||||
|
||||
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Type *getType();
|
||||
const char *kind();
|
||||
#if DMDV2
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#endif
|
||||
int isDeprecated(); // is Dsymbol deprecated?
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
EnumDeclaration *isEnumDeclaration() { return this; }
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
int cvMember(unsigned char *p);
|
||||
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
};
|
||||
|
||||
|
||||
struct EnumMember : Dsymbol
|
||||
{
|
||||
Expression *value;
|
||||
Type *type;
|
||||
|
||||
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
EnumMember *isEnumMember() { return this; }
|
||||
};
|
||||
|
||||
#endif /* DMD_ENUM_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_ENUM_H
|
||||
#define DMD_ENUM_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct Expression;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
|
||||
struct EnumDeclaration : ScopeDsymbol
|
||||
{ /* enum ident : memtype { ... }
|
||||
*/
|
||||
Type *type; // the TypeEnum
|
||||
Type *memtype; // type of the members
|
||||
|
||||
#if DMDV1
|
||||
dinteger_t maxval;
|
||||
dinteger_t minval;
|
||||
dinteger_t defaultval; // default initializer
|
||||
#else
|
||||
Expression *maxval;
|
||||
Expression *minval;
|
||||
Expression *defaultval; // default initializer
|
||||
|
||||
Scope *scope; // !=NULL means context to use
|
||||
#endif
|
||||
int isdeprecated;
|
||||
|
||||
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Type *getType();
|
||||
const char *kind();
|
||||
#if DMDV2
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#endif
|
||||
int isDeprecated(); // is Dsymbol deprecated?
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
EnumDeclaration *isEnumDeclaration() { return this; }
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
int cvMember(unsigned char *p);
|
||||
|
||||
Symbol *sinit;
|
||||
Symbol *toInitializer();
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct EnumMember : Dsymbol
|
||||
{
|
||||
Expression *value;
|
||||
Type *type;
|
||||
|
||||
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
EnumMember *isEnumMember() { return this; }
|
||||
};
|
||||
|
||||
#endif /* DMD_ENUM_H */
|
||||
|
||||
19883
dmd2/expression.c
19883
dmd2/expression.c
File diff suppressed because it is too large
Load Diff
3592
dmd2/expression.h
3592
dmd2/expression.h
File diff suppressed because it is too large
Load Diff
6427
dmd2/func.c
6427
dmd2/func.c
File diff suppressed because it is too large
Load Diff
@@ -24,17 +24,7 @@
|
||||
#include <complex.h>
|
||||
#endif
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#else
|
||||
#if _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#elif POSIX
|
||||
#include "../root/mem.h"
|
||||
#else
|
||||
#error "fix this"
|
||||
#endif
|
||||
#endif
|
||||
#include "rmem.h"
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
|
||||
12
dmd2/html.c
12
dmd2/html.c
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -107,10 +107,10 @@ void Html::extractCode(OutBuffer *buf)
|
||||
{ // Comments start with <!--
|
||||
scanComment();
|
||||
}
|
||||
else if(p[1] == '!' && isCDATAStart())
|
||||
{
|
||||
scanCDATA();
|
||||
}
|
||||
else if(p[1] == '!' && isCDATAStart())
|
||||
{
|
||||
scanCDATA();
|
||||
}
|
||||
else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
|
||||
skipTag();
|
||||
else if (istagstart(*skipWhite(p + 1)))
|
||||
@@ -550,6 +550,7 @@ void Html::scanCDATA()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Convert an HTML character entity into a character.
|
||||
* Forms are:
|
||||
@@ -716,3 +717,4 @@ static int isLineSeparator(const unsigned char* p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
@@ -27,7 +26,7 @@ struct Html
|
||||
|
||||
Html(const char *sourcename, unsigned char *base, unsigned length);
|
||||
|
||||
void error(const char *format, ...);
|
||||
void error(const char *format, ...) IS_PRINTF(2);
|
||||
void extractCode(OutBuffer *buf);
|
||||
void skipTag();
|
||||
void skipString();
|
||||
|
||||
463
dmd2/id.c
Normal file
463
dmd2/id.c
Normal file
@@ -0,0 +1,463 @@
|
||||
// File generated by idgen.c
|
||||
#include "id.h"
|
||||
#include "identifier.h"
|
||||
#include "lexer.h"
|
||||
Identifier *Id::IUnknown;
|
||||
Identifier *Id::Object;
|
||||
Identifier *Id::object;
|
||||
Identifier *Id::max;
|
||||
Identifier *Id::min;
|
||||
Identifier *Id::This;
|
||||
Identifier *Id::ctor;
|
||||
Identifier *Id::dtor;
|
||||
Identifier *Id::cpctor;
|
||||
Identifier *Id::_postblit;
|
||||
Identifier *Id::classInvariant;
|
||||
Identifier *Id::unitTest;
|
||||
Identifier *Id::init;
|
||||
Identifier *Id::size;
|
||||
Identifier *Id::__sizeof;
|
||||
Identifier *Id::alignof;
|
||||
Identifier *Id::mangleof;
|
||||
Identifier *Id::stringof;
|
||||
Identifier *Id::tupleof;
|
||||
Identifier *Id::length;
|
||||
Identifier *Id::remove;
|
||||
Identifier *Id::ptr;
|
||||
Identifier *Id::funcptr;
|
||||
Identifier *Id::dollar;
|
||||
Identifier *Id::offset;
|
||||
Identifier *Id::offsetof;
|
||||
Identifier *Id::ModuleInfo;
|
||||
Identifier *Id::ClassInfo;
|
||||
Identifier *Id::classinfo;
|
||||
Identifier *Id::typeinfo;
|
||||
Identifier *Id::outer;
|
||||
Identifier *Id::Exception;
|
||||
Identifier *Id::Throwable;
|
||||
Identifier *Id::withSym;
|
||||
Identifier *Id::result;
|
||||
Identifier *Id::returnLabel;
|
||||
Identifier *Id::delegate;
|
||||
Identifier *Id::line;
|
||||
Identifier *Id::empty;
|
||||
Identifier *Id::p;
|
||||
Identifier *Id::coverage;
|
||||
Identifier *Id::__vptr;
|
||||
Identifier *Id::__monitor;
|
||||
Identifier *Id::system;
|
||||
Identifier *Id::TypeInfo;
|
||||
Identifier *Id::TypeInfo_Class;
|
||||
Identifier *Id::TypeInfo_Interface;
|
||||
Identifier *Id::TypeInfo_Struct;
|
||||
Identifier *Id::TypeInfo_Enum;
|
||||
Identifier *Id::TypeInfo_Typedef;
|
||||
Identifier *Id::TypeInfo_Pointer;
|
||||
Identifier *Id::TypeInfo_Array;
|
||||
Identifier *Id::TypeInfo_StaticArray;
|
||||
Identifier *Id::TypeInfo_AssociativeArray;
|
||||
Identifier *Id::TypeInfo_Function;
|
||||
Identifier *Id::TypeInfo_Delegate;
|
||||
Identifier *Id::TypeInfo_Tuple;
|
||||
Identifier *Id::TypeInfo_Const;
|
||||
Identifier *Id::TypeInfo_Invariant;
|
||||
Identifier *Id::TypeInfo_Shared;
|
||||
Identifier *Id::elements;
|
||||
Identifier *Id::_arguments_typeinfo;
|
||||
Identifier *Id::_arguments;
|
||||
Identifier *Id::_argptr;
|
||||
Identifier *Id::_match;
|
||||
Identifier *Id::destroy;
|
||||
Identifier *Id::postblit;
|
||||
Identifier *Id::LINE;
|
||||
Identifier *Id::FILE;
|
||||
Identifier *Id::DATE;
|
||||
Identifier *Id::TIME;
|
||||
Identifier *Id::TIMESTAMP;
|
||||
Identifier *Id::VENDOR;
|
||||
Identifier *Id::VERSIONX;
|
||||
Identifier *Id::EOFX;
|
||||
Identifier *Id::nan;
|
||||
Identifier *Id::infinity;
|
||||
Identifier *Id::dig;
|
||||
Identifier *Id::epsilon;
|
||||
Identifier *Id::mant_dig;
|
||||
Identifier *Id::max_10_exp;
|
||||
Identifier *Id::max_exp;
|
||||
Identifier *Id::min_10_exp;
|
||||
Identifier *Id::min_exp;
|
||||
Identifier *Id::re;
|
||||
Identifier *Id::im;
|
||||
Identifier *Id::C;
|
||||
Identifier *Id::D;
|
||||
Identifier *Id::Windows;
|
||||
Identifier *Id::Pascal;
|
||||
Identifier *Id::System;
|
||||
Identifier *Id::exit;
|
||||
Identifier *Id::success;
|
||||
Identifier *Id::failure;
|
||||
Identifier *Id::keys;
|
||||
Identifier *Id::values;
|
||||
Identifier *Id::rehash;
|
||||
Identifier *Id::sort;
|
||||
Identifier *Id::reverse;
|
||||
Identifier *Id::dup;
|
||||
Identifier *Id::idup;
|
||||
Identifier *Id::___out;
|
||||
Identifier *Id::___in;
|
||||
Identifier *Id::__int;
|
||||
Identifier *Id::__dollar;
|
||||
Identifier *Id::__LOCAL_SIZE;
|
||||
Identifier *Id::uadd;
|
||||
Identifier *Id::neg;
|
||||
Identifier *Id::com;
|
||||
Identifier *Id::add;
|
||||
Identifier *Id::add_r;
|
||||
Identifier *Id::sub;
|
||||
Identifier *Id::sub_r;
|
||||
Identifier *Id::mul;
|
||||
Identifier *Id::mul_r;
|
||||
Identifier *Id::div;
|
||||
Identifier *Id::div_r;
|
||||
Identifier *Id::mod;
|
||||
Identifier *Id::mod_r;
|
||||
Identifier *Id::eq;
|
||||
Identifier *Id::cmp;
|
||||
Identifier *Id::iand;
|
||||
Identifier *Id::iand_r;
|
||||
Identifier *Id::ior;
|
||||
Identifier *Id::ior_r;
|
||||
Identifier *Id::ixor;
|
||||
Identifier *Id::ixor_r;
|
||||
Identifier *Id::shl;
|
||||
Identifier *Id::shl_r;
|
||||
Identifier *Id::shr;
|
||||
Identifier *Id::shr_r;
|
||||
Identifier *Id::ushr;
|
||||
Identifier *Id::ushr_r;
|
||||
Identifier *Id::cat;
|
||||
Identifier *Id::cat_r;
|
||||
Identifier *Id::assign;
|
||||
Identifier *Id::addass;
|
||||
Identifier *Id::subass;
|
||||
Identifier *Id::mulass;
|
||||
Identifier *Id::divass;
|
||||
Identifier *Id::modass;
|
||||
Identifier *Id::andass;
|
||||
Identifier *Id::orass;
|
||||
Identifier *Id::xorass;
|
||||
Identifier *Id::shlass;
|
||||
Identifier *Id::shrass;
|
||||
Identifier *Id::ushrass;
|
||||
Identifier *Id::catass;
|
||||
Identifier *Id::postinc;
|
||||
Identifier *Id::postdec;
|
||||
Identifier *Id::index;
|
||||
Identifier *Id::indexass;
|
||||
Identifier *Id::slice;
|
||||
Identifier *Id::sliceass;
|
||||
Identifier *Id::call;
|
||||
Identifier *Id::cast;
|
||||
Identifier *Id::match;
|
||||
Identifier *Id::next;
|
||||
Identifier *Id::opIn;
|
||||
Identifier *Id::opIn_r;
|
||||
Identifier *Id::opStar;
|
||||
Identifier *Id::opDot;
|
||||
Identifier *Id::opImplicitCast;
|
||||
Identifier *Id::classNew;
|
||||
Identifier *Id::classDelete;
|
||||
Identifier *Id::apply;
|
||||
Identifier *Id::applyReverse;
|
||||
Identifier *Id::Fempty;
|
||||
Identifier *Id::Fhead;
|
||||
Identifier *Id::Ftoe;
|
||||
Identifier *Id::Fnext;
|
||||
Identifier *Id::Fretreat;
|
||||
Identifier *Id::adDup;
|
||||
Identifier *Id::adReverse;
|
||||
Identifier *Id::aaLen;
|
||||
Identifier *Id::aaKeys;
|
||||
Identifier *Id::aaValues;
|
||||
Identifier *Id::aaRehash;
|
||||
Identifier *Id::GNU_asm;
|
||||
Identifier *Id::lib;
|
||||
Identifier *Id::msg;
|
||||
Identifier *Id::startaddress;
|
||||
Identifier *Id::intrinsic;
|
||||
Identifier *Id::va_intrinsic;
|
||||
Identifier *Id::no_typeinfo;
|
||||
Identifier *Id::no_moduleinfo;
|
||||
Identifier *Id::Alloca;
|
||||
Identifier *Id::vastart;
|
||||
Identifier *Id::vacopy;
|
||||
Identifier *Id::vaend;
|
||||
Identifier *Id::vaarg;
|
||||
Identifier *Id::ldc;
|
||||
Identifier *Id::allow_inline;
|
||||
Identifier *Id::llvm_inline_asm;
|
||||
Identifier *Id::tohash;
|
||||
Identifier *Id::tostring;
|
||||
Identifier *Id::getmembers;
|
||||
Identifier *Id::main;
|
||||
Identifier *Id::WinMain;
|
||||
Identifier *Id::DllMain;
|
||||
Identifier *Id::tls_get_addr;
|
||||
Identifier *Id::std;
|
||||
Identifier *Id::math;
|
||||
Identifier *Id::sin;
|
||||
Identifier *Id::cos;
|
||||
Identifier *Id::tan;
|
||||
Identifier *Id::_sqrt;
|
||||
Identifier *Id::fabs;
|
||||
Identifier *Id::isAbstractClass;
|
||||
Identifier *Id::isArithmetic;
|
||||
Identifier *Id::isAssociativeArray;
|
||||
Identifier *Id::isFinalClass;
|
||||
Identifier *Id::isFloating;
|
||||
Identifier *Id::isIntegral;
|
||||
Identifier *Id::isScalar;
|
||||
Identifier *Id::isStaticArray;
|
||||
Identifier *Id::isUnsigned;
|
||||
Identifier *Id::isVirtualFunction;
|
||||
Identifier *Id::isAbstractFunction;
|
||||
Identifier *Id::isFinalFunction;
|
||||
Identifier *Id::hasMember;
|
||||
Identifier *Id::getMember;
|
||||
Identifier *Id::getVirtualFunctions;
|
||||
Identifier *Id::classInstanceSize;
|
||||
Identifier *Id::allMembers;
|
||||
Identifier *Id::derivedMembers;
|
||||
Identifier *Id::isSame;
|
||||
Identifier *Id::compiles;
|
||||
void Id::initialize()
|
||||
{
|
||||
IUnknown = Lexer::idPool("IUnknown");
|
||||
Object = Lexer::idPool("Object");
|
||||
object = Lexer::idPool("object");
|
||||
max = Lexer::idPool("max");
|
||||
min = Lexer::idPool("min");
|
||||
This = Lexer::idPool("this");
|
||||
ctor = Lexer::idPool("__ctor");
|
||||
dtor = Lexer::idPool("__dtor");
|
||||
cpctor = Lexer::idPool("__cpctor");
|
||||
_postblit = Lexer::idPool("__postblit");
|
||||
classInvariant = Lexer::idPool("__invariant");
|
||||
unitTest = Lexer::idPool("__unitTest");
|
||||
init = Lexer::idPool("init");
|
||||
size = Lexer::idPool("size");
|
||||
__sizeof = Lexer::idPool("sizeof");
|
||||
alignof = Lexer::idPool("alignof");
|
||||
mangleof = Lexer::idPool("mangleof");
|
||||
stringof = Lexer::idPool("stringof");
|
||||
tupleof = Lexer::idPool("tupleof");
|
||||
length = Lexer::idPool("length");
|
||||
remove = Lexer::idPool("remove");
|
||||
ptr = Lexer::idPool("ptr");
|
||||
funcptr = Lexer::idPool("funcptr");
|
||||
dollar = Lexer::idPool("__dollar");
|
||||
offset = Lexer::idPool("offset");
|
||||
offsetof = Lexer::idPool("offsetof");
|
||||
ModuleInfo = Lexer::idPool("ModuleInfo");
|
||||
ClassInfo = Lexer::idPool("ClassInfo");
|
||||
classinfo = Lexer::idPool("classinfo");
|
||||
typeinfo = Lexer::idPool("typeinfo");
|
||||
outer = Lexer::idPool("outer");
|
||||
Exception = Lexer::idPool("Exception");
|
||||
Throwable = Lexer::idPool("Throwable");
|
||||
withSym = Lexer::idPool("__withSym");
|
||||
result = Lexer::idPool("__result");
|
||||
returnLabel = Lexer::idPool("__returnLabel");
|
||||
delegate = Lexer::idPool("delegate");
|
||||
line = Lexer::idPool("line");
|
||||
empty = Lexer::idPool("");
|
||||
p = Lexer::idPool("p");
|
||||
coverage = Lexer::idPool("__coverage");
|
||||
__vptr = Lexer::idPool("__vptr");
|
||||
__monitor = Lexer::idPool("__monitor");
|
||||
system = Lexer::idPool("system");
|
||||
TypeInfo = Lexer::idPool("TypeInfo");
|
||||
TypeInfo_Class = Lexer::idPool("TypeInfo_Class");
|
||||
TypeInfo_Interface = Lexer::idPool("TypeInfo_Interface");
|
||||
TypeInfo_Struct = Lexer::idPool("TypeInfo_Struct");
|
||||
TypeInfo_Enum = Lexer::idPool("TypeInfo_Enum");
|
||||
TypeInfo_Typedef = Lexer::idPool("TypeInfo_Typedef");
|
||||
TypeInfo_Pointer = Lexer::idPool("TypeInfo_Pointer");
|
||||
TypeInfo_Array = Lexer::idPool("TypeInfo_Array");
|
||||
TypeInfo_StaticArray = Lexer::idPool("TypeInfo_StaticArray");
|
||||
TypeInfo_AssociativeArray = Lexer::idPool("TypeInfo_AssociativeArray");
|
||||
TypeInfo_Function = Lexer::idPool("TypeInfo_Function");
|
||||
TypeInfo_Delegate = Lexer::idPool("TypeInfo_Delegate");
|
||||
TypeInfo_Tuple = Lexer::idPool("TypeInfo_Tuple");
|
||||
TypeInfo_Const = Lexer::idPool("TypeInfo_Const");
|
||||
TypeInfo_Invariant = Lexer::idPool("TypeInfo_Invariant");
|
||||
TypeInfo_Shared = Lexer::idPool("TypeInfo_Shared");
|
||||
elements = Lexer::idPool("elements");
|
||||
_arguments_typeinfo = Lexer::idPool("_arguments_typeinfo");
|
||||
_arguments = Lexer::idPool("_arguments");
|
||||
_argptr = Lexer::idPool("_argptr");
|
||||
_match = Lexer::idPool("_match");
|
||||
destroy = Lexer::idPool("destroy");
|
||||
postblit = Lexer::idPool("postblit");
|
||||
LINE = Lexer::idPool("__LINE__");
|
||||
FILE = Lexer::idPool("__FILE__");
|
||||
DATE = Lexer::idPool("__DATE__");
|
||||
TIME = Lexer::idPool("__TIME__");
|
||||
TIMESTAMP = Lexer::idPool("__TIMESTAMP__");
|
||||
VENDOR = Lexer::idPool("__VENDOR__");
|
||||
VERSIONX = Lexer::idPool("__VERSION__");
|
||||
EOFX = Lexer::idPool("__EOF__");
|
||||
nan = Lexer::idPool("nan");
|
||||
infinity = Lexer::idPool("infinity");
|
||||
dig = Lexer::idPool("dig");
|
||||
epsilon = Lexer::idPool("epsilon");
|
||||
mant_dig = Lexer::idPool("mant_dig");
|
||||
max_10_exp = Lexer::idPool("max_10_exp");
|
||||
max_exp = Lexer::idPool("max_exp");
|
||||
min_10_exp = Lexer::idPool("min_10_exp");
|
||||
min_exp = Lexer::idPool("min_exp");
|
||||
re = Lexer::idPool("re");
|
||||
im = Lexer::idPool("im");
|
||||
C = Lexer::idPool("C");
|
||||
D = Lexer::idPool("D");
|
||||
Windows = Lexer::idPool("Windows");
|
||||
Pascal = Lexer::idPool("Pascal");
|
||||
System = Lexer::idPool("System");
|
||||
exit = Lexer::idPool("exit");
|
||||
success = Lexer::idPool("success");
|
||||
failure = Lexer::idPool("failure");
|
||||
keys = Lexer::idPool("keys");
|
||||
values = Lexer::idPool("values");
|
||||
rehash = Lexer::idPool("rehash");
|
||||
sort = Lexer::idPool("sort");
|
||||
reverse = Lexer::idPool("reverse");
|
||||
dup = Lexer::idPool("dup");
|
||||
idup = Lexer::idPool("idup");
|
||||
___out = Lexer::idPool("out");
|
||||
___in = Lexer::idPool("in");
|
||||
__int = Lexer::idPool("int");
|
||||
__dollar = Lexer::idPool("$");
|
||||
__LOCAL_SIZE = Lexer::idPool("__LOCAL_SIZE");
|
||||
uadd = Lexer::idPool("opPos");
|
||||
neg = Lexer::idPool("opNeg");
|
||||
com = Lexer::idPool("opCom");
|
||||
add = Lexer::idPool("opAdd");
|
||||
add_r = Lexer::idPool("opAdd_r");
|
||||
sub = Lexer::idPool("opSub");
|
||||
sub_r = Lexer::idPool("opSub_r");
|
||||
mul = Lexer::idPool("opMul");
|
||||
mul_r = Lexer::idPool("opMul_r");
|
||||
div = Lexer::idPool("opDiv");
|
||||
div_r = Lexer::idPool("opDiv_r");
|
||||
mod = Lexer::idPool("opMod");
|
||||
mod_r = Lexer::idPool("opMod_r");
|
||||
eq = Lexer::idPool("opEquals");
|
||||
cmp = Lexer::idPool("opCmp");
|
||||
iand = Lexer::idPool("opAnd");
|
||||
iand_r = Lexer::idPool("opAnd_r");
|
||||
ior = Lexer::idPool("opOr");
|
||||
ior_r = Lexer::idPool("opOr_r");
|
||||
ixor = Lexer::idPool("opXor");
|
||||
ixor_r = Lexer::idPool("opXor_r");
|
||||
shl = Lexer::idPool("opShl");
|
||||
shl_r = Lexer::idPool("opShl_r");
|
||||
shr = Lexer::idPool("opShr");
|
||||
shr_r = Lexer::idPool("opShr_r");
|
||||
ushr = Lexer::idPool("opUShr");
|
||||
ushr_r = Lexer::idPool("opUShr_r");
|
||||
cat = Lexer::idPool("opCat");
|
||||
cat_r = Lexer::idPool("opCat_r");
|
||||
assign = Lexer::idPool("opAssign");
|
||||
addass = Lexer::idPool("opAddAssign");
|
||||
subass = Lexer::idPool("opSubAssign");
|
||||
mulass = Lexer::idPool("opMulAssign");
|
||||
divass = Lexer::idPool("opDivAssign");
|
||||
modass = Lexer::idPool("opModAssign");
|
||||
andass = Lexer::idPool("opAndAssign");
|
||||
orass = Lexer::idPool("opOrAssign");
|
||||
xorass = Lexer::idPool("opXorAssign");
|
||||
shlass = Lexer::idPool("opShlAssign");
|
||||
shrass = Lexer::idPool("opShrAssign");
|
||||
ushrass = Lexer::idPool("opUShrAssign");
|
||||
catass = Lexer::idPool("opCatAssign");
|
||||
postinc = Lexer::idPool("opPostInc");
|
||||
postdec = Lexer::idPool("opPostDec");
|
||||
index = Lexer::idPool("opIndex");
|
||||
indexass = Lexer::idPool("opIndexAssign");
|
||||
slice = Lexer::idPool("opSlice");
|
||||
sliceass = Lexer::idPool("opSliceAssign");
|
||||
call = Lexer::idPool("opCall");
|
||||
cast = Lexer::idPool("opCast");
|
||||
match = Lexer::idPool("opMatch");
|
||||
next = Lexer::idPool("opNext");
|
||||
opIn = Lexer::idPool("opIn");
|
||||
opIn_r = Lexer::idPool("opIn_r");
|
||||
opStar = Lexer::idPool("opStar");
|
||||
opDot = Lexer::idPool("opDot");
|
||||
opImplicitCast = Lexer::idPool("opImplicitCast");
|
||||
classNew = Lexer::idPool("new");
|
||||
classDelete = Lexer::idPool("delete");
|
||||
apply = Lexer::idPool("opApply");
|
||||
applyReverse = Lexer::idPool("opApplyReverse");
|
||||
Fempty = Lexer::idPool("empty");
|
||||
Fhead = Lexer::idPool("front");
|
||||
Ftoe = Lexer::idPool("back");
|
||||
Fnext = Lexer::idPool("popFront");
|
||||
Fretreat = Lexer::idPool("popBack");
|
||||
adDup = Lexer::idPool("_adDupT");
|
||||
adReverse = Lexer::idPool("_adReverse");
|
||||
aaLen = Lexer::idPool("_aaLen");
|
||||
aaKeys = Lexer::idPool("_aaKeys");
|
||||
aaValues = Lexer::idPool("_aaValues");
|
||||
aaRehash = Lexer::idPool("_aaRehash");
|
||||
GNU_asm = Lexer::idPool("GNU_asm");
|
||||
lib = Lexer::idPool("lib");
|
||||
msg = Lexer::idPool("msg");
|
||||
startaddress = Lexer::idPool("startaddress");
|
||||
intrinsic = Lexer::idPool("intrinsic");
|
||||
va_intrinsic = Lexer::idPool("va_intrinsic");
|
||||
no_typeinfo = Lexer::idPool("no_typeinfo");
|
||||
no_moduleinfo = Lexer::idPool("no_moduleinfo");
|
||||
Alloca = Lexer::idPool("alloca");
|
||||
vastart = Lexer::idPool("va_start");
|
||||
vacopy = Lexer::idPool("va_copy");
|
||||
vaend = Lexer::idPool("va_end");
|
||||
vaarg = Lexer::idPool("va_arg");
|
||||
ldc = Lexer::idPool("ldc");
|
||||
allow_inline = Lexer::idPool("allow_inline");
|
||||
llvm_inline_asm = Lexer::idPool("llvm_inline_asm");
|
||||
tohash = Lexer::idPool("toHash");
|
||||
tostring = Lexer::idPool("toString");
|
||||
getmembers = Lexer::idPool("getMembers");
|
||||
main = Lexer::idPool("main");
|
||||
WinMain = Lexer::idPool("WinMain");
|
||||
DllMain = Lexer::idPool("DllMain");
|
||||
tls_get_addr = Lexer::idPool("___tls_get_addr");
|
||||
std = Lexer::idPool("std");
|
||||
math = Lexer::idPool("math");
|
||||
sin = Lexer::idPool("sin");
|
||||
cos = Lexer::idPool("cos");
|
||||
tan = Lexer::idPool("tan");
|
||||
_sqrt = Lexer::idPool("sqrt");
|
||||
fabs = Lexer::idPool("fabs");
|
||||
isAbstractClass = Lexer::idPool("isAbstractClass");
|
||||
isArithmetic = Lexer::idPool("isArithmetic");
|
||||
isAssociativeArray = Lexer::idPool("isAssociativeArray");
|
||||
isFinalClass = Lexer::idPool("isFinalClass");
|
||||
isFloating = Lexer::idPool("isFloating");
|
||||
isIntegral = Lexer::idPool("isIntegral");
|
||||
isScalar = Lexer::idPool("isScalar");
|
||||
isStaticArray = Lexer::idPool("isStaticArray");
|
||||
isUnsigned = Lexer::idPool("isUnsigned");
|
||||
isVirtualFunction = Lexer::idPool("isVirtualFunction");
|
||||
isAbstractFunction = Lexer::idPool("isAbstractFunction");
|
||||
isFinalFunction = Lexer::idPool("isFinalFunction");
|
||||
hasMember = Lexer::idPool("hasMember");
|
||||
getMember = Lexer::idPool("getMember");
|
||||
getVirtualFunctions = Lexer::idPool("getVirtualFunctions");
|
||||
classInstanceSize = Lexer::idPool("classInstanceSize");
|
||||
allMembers = Lexer::idPool("allMembers");
|
||||
derivedMembers = Lexer::idPool("derivedMembers");
|
||||
isSame = Lexer::idPool("isSame");
|
||||
compiles = Lexer::idPool("compiles");
|
||||
}
|
||||
237
dmd2/id.h
Normal file
237
dmd2/id.h
Normal file
@@ -0,0 +1,237 @@
|
||||
// File generated by idgen.c
|
||||
#ifndef DMD_ID_H
|
||||
#define DMD_ID_H 1
|
||||
struct Identifier;
|
||||
struct Id
|
||||
{
|
||||
static Identifier *IUnknown;
|
||||
static Identifier *Object;
|
||||
static Identifier *object;
|
||||
static Identifier *max;
|
||||
static Identifier *min;
|
||||
static Identifier *This;
|
||||
static Identifier *ctor;
|
||||
static Identifier *dtor;
|
||||
static Identifier *cpctor;
|
||||
static Identifier *_postblit;
|
||||
static Identifier *classInvariant;
|
||||
static Identifier *unitTest;
|
||||
static Identifier *init;
|
||||
static Identifier *size;
|
||||
static Identifier *__sizeof;
|
||||
static Identifier *alignof;
|
||||
static Identifier *mangleof;
|
||||
static Identifier *stringof;
|
||||
static Identifier *tupleof;
|
||||
static Identifier *length;
|
||||
static Identifier *remove;
|
||||
static Identifier *ptr;
|
||||
static Identifier *funcptr;
|
||||
static Identifier *dollar;
|
||||
static Identifier *offset;
|
||||
static Identifier *offsetof;
|
||||
static Identifier *ModuleInfo;
|
||||
static Identifier *ClassInfo;
|
||||
static Identifier *classinfo;
|
||||
static Identifier *typeinfo;
|
||||
static Identifier *outer;
|
||||
static Identifier *Exception;
|
||||
static Identifier *Throwable;
|
||||
static Identifier *withSym;
|
||||
static Identifier *result;
|
||||
static Identifier *returnLabel;
|
||||
static Identifier *delegate;
|
||||
static Identifier *line;
|
||||
static Identifier *empty;
|
||||
static Identifier *p;
|
||||
static Identifier *coverage;
|
||||
static Identifier *__vptr;
|
||||
static Identifier *__monitor;
|
||||
static Identifier *system;
|
||||
static Identifier *TypeInfo;
|
||||
static Identifier *TypeInfo_Class;
|
||||
static Identifier *TypeInfo_Interface;
|
||||
static Identifier *TypeInfo_Struct;
|
||||
static Identifier *TypeInfo_Enum;
|
||||
static Identifier *TypeInfo_Typedef;
|
||||
static Identifier *TypeInfo_Pointer;
|
||||
static Identifier *TypeInfo_Array;
|
||||
static Identifier *TypeInfo_StaticArray;
|
||||
static Identifier *TypeInfo_AssociativeArray;
|
||||
static Identifier *TypeInfo_Function;
|
||||
static Identifier *TypeInfo_Delegate;
|
||||
static Identifier *TypeInfo_Tuple;
|
||||
static Identifier *TypeInfo_Const;
|
||||
static Identifier *TypeInfo_Invariant;
|
||||
static Identifier *TypeInfo_Shared;
|
||||
static Identifier *elements;
|
||||
static Identifier *_arguments_typeinfo;
|
||||
static Identifier *_arguments;
|
||||
static Identifier *_argptr;
|
||||
static Identifier *_match;
|
||||
static Identifier *destroy;
|
||||
static Identifier *postblit;
|
||||
static Identifier *LINE;
|
||||
static Identifier *FILE;
|
||||
static Identifier *DATE;
|
||||
static Identifier *TIME;
|
||||
static Identifier *TIMESTAMP;
|
||||
static Identifier *VENDOR;
|
||||
static Identifier *VERSIONX;
|
||||
static Identifier *EOFX;
|
||||
static Identifier *nan;
|
||||
static Identifier *infinity;
|
||||
static Identifier *dig;
|
||||
static Identifier *epsilon;
|
||||
static Identifier *mant_dig;
|
||||
static Identifier *max_10_exp;
|
||||
static Identifier *max_exp;
|
||||
static Identifier *min_10_exp;
|
||||
static Identifier *min_exp;
|
||||
static Identifier *re;
|
||||
static Identifier *im;
|
||||
static Identifier *C;
|
||||
static Identifier *D;
|
||||
static Identifier *Windows;
|
||||
static Identifier *Pascal;
|
||||
static Identifier *System;
|
||||
static Identifier *exit;
|
||||
static Identifier *success;
|
||||
static Identifier *failure;
|
||||
static Identifier *keys;
|
||||
static Identifier *values;
|
||||
static Identifier *rehash;
|
||||
static Identifier *sort;
|
||||
static Identifier *reverse;
|
||||
static Identifier *dup;
|
||||
static Identifier *idup;
|
||||
static Identifier *___out;
|
||||
static Identifier *___in;
|
||||
static Identifier *__int;
|
||||
static Identifier *__dollar;
|
||||
static Identifier *__LOCAL_SIZE;
|
||||
static Identifier *uadd;
|
||||
static Identifier *neg;
|
||||
static Identifier *com;
|
||||
static Identifier *add;
|
||||
static Identifier *add_r;
|
||||
static Identifier *sub;
|
||||
static Identifier *sub_r;
|
||||
static Identifier *mul;
|
||||
static Identifier *mul_r;
|
||||
static Identifier *div;
|
||||
static Identifier *div_r;
|
||||
static Identifier *mod;
|
||||
static Identifier *mod_r;
|
||||
static Identifier *eq;
|
||||
static Identifier *cmp;
|
||||
static Identifier *iand;
|
||||
static Identifier *iand_r;
|
||||
static Identifier *ior;
|
||||
static Identifier *ior_r;
|
||||
static Identifier *ixor;
|
||||
static Identifier *ixor_r;
|
||||
static Identifier *shl;
|
||||
static Identifier *shl_r;
|
||||
static Identifier *shr;
|
||||
static Identifier *shr_r;
|
||||
static Identifier *ushr;
|
||||
static Identifier *ushr_r;
|
||||
static Identifier *cat;
|
||||
static Identifier *cat_r;
|
||||
static Identifier *assign;
|
||||
static Identifier *addass;
|
||||
static Identifier *subass;
|
||||
static Identifier *mulass;
|
||||
static Identifier *divass;
|
||||
static Identifier *modass;
|
||||
static Identifier *andass;
|
||||
static Identifier *orass;
|
||||
static Identifier *xorass;
|
||||
static Identifier *shlass;
|
||||
static Identifier *shrass;
|
||||
static Identifier *ushrass;
|
||||
static Identifier *catass;
|
||||
static Identifier *postinc;
|
||||
static Identifier *postdec;
|
||||
static Identifier *index;
|
||||
static Identifier *indexass;
|
||||
static Identifier *slice;
|
||||
static Identifier *sliceass;
|
||||
static Identifier *call;
|
||||
static Identifier *cast;
|
||||
static Identifier *match;
|
||||
static Identifier *next;
|
||||
static Identifier *opIn;
|
||||
static Identifier *opIn_r;
|
||||
static Identifier *opStar;
|
||||
static Identifier *opDot;
|
||||
static Identifier *opImplicitCast;
|
||||
static Identifier *classNew;
|
||||
static Identifier *classDelete;
|
||||
static Identifier *apply;
|
||||
static Identifier *applyReverse;
|
||||
static Identifier *Fempty;
|
||||
static Identifier *Fhead;
|
||||
static Identifier *Ftoe;
|
||||
static Identifier *Fnext;
|
||||
static Identifier *Fretreat;
|
||||
static Identifier *adDup;
|
||||
static Identifier *adReverse;
|
||||
static Identifier *aaLen;
|
||||
static Identifier *aaKeys;
|
||||
static Identifier *aaValues;
|
||||
static Identifier *aaRehash;
|
||||
static Identifier *GNU_asm;
|
||||
static Identifier *lib;
|
||||
static Identifier *msg;
|
||||
static Identifier *startaddress;
|
||||
static Identifier *intrinsic;
|
||||
static Identifier *va_intrinsic;
|
||||
static Identifier *no_typeinfo;
|
||||
static Identifier *no_moduleinfo;
|
||||
static Identifier *Alloca;
|
||||
static Identifier *vastart;
|
||||
static Identifier *vacopy;
|
||||
static Identifier *vaend;
|
||||
static Identifier *vaarg;
|
||||
static Identifier *ldc;
|
||||
static Identifier *allow_inline;
|
||||
static Identifier *llvm_inline_asm;
|
||||
static Identifier *tohash;
|
||||
static Identifier *tostring;
|
||||
static Identifier *getmembers;
|
||||
static Identifier *main;
|
||||
static Identifier *WinMain;
|
||||
static Identifier *DllMain;
|
||||
static Identifier *tls_get_addr;
|
||||
static Identifier *std;
|
||||
static Identifier *math;
|
||||
static Identifier *sin;
|
||||
static Identifier *cos;
|
||||
static Identifier *tan;
|
||||
static Identifier *_sqrt;
|
||||
static Identifier *fabs;
|
||||
static Identifier *isAbstractClass;
|
||||
static Identifier *isArithmetic;
|
||||
static Identifier *isAssociativeArray;
|
||||
static Identifier *isFinalClass;
|
||||
static Identifier *isFloating;
|
||||
static Identifier *isIntegral;
|
||||
static Identifier *isScalar;
|
||||
static Identifier *isStaticArray;
|
||||
static Identifier *isUnsigned;
|
||||
static Identifier *isVirtualFunction;
|
||||
static Identifier *isAbstractFunction;
|
||||
static Identifier *isFinalFunction;
|
||||
static Identifier *hasMember;
|
||||
static Identifier *getMember;
|
||||
static Identifier *getVirtualFunctions;
|
||||
static Identifier *classInstanceSize;
|
||||
static Identifier *allMembers;
|
||||
static Identifier *derivedMembers;
|
||||
static Identifier *isSame;
|
||||
static Identifier *compiles;
|
||||
static void initialize();
|
||||
};
|
||||
#endif
|
||||
@@ -1,101 +1,102 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "identifier.h"
|
||||
#include "mars.h"
|
||||
#include "lexer.h"
|
||||
#include "id.h"
|
||||
|
||||
Identifier::Identifier(const char *string, int value)
|
||||
{
|
||||
//printf("Identifier('%s', %d)\n", string, value);
|
||||
this->string = string;
|
||||
this->value = value;
|
||||
this->len = strlen(string);
|
||||
}
|
||||
|
||||
hash_t Identifier::hashCode()
|
||||
{
|
||||
return String::calcHash(string);
|
||||
}
|
||||
|
||||
int Identifier::equals(Object *o)
|
||||
{
|
||||
return this == o || memcmp(string,o->toChars(),len+1) == 0;
|
||||
}
|
||||
|
||||
int Identifier::compare(Object *o)
|
||||
{
|
||||
return memcmp(string, o->toChars(), len + 1);
|
||||
}
|
||||
|
||||
char *Identifier::toChars()
|
||||
{
|
||||
return (char *)string;
|
||||
}
|
||||
|
||||
const char *Identifier::toHChars2()
|
||||
{
|
||||
const char *p = NULL;
|
||||
|
||||
if (this == Id::ctor) p = "this";
|
||||
else if (this == Id::dtor) p = "~this";
|
||||
else if (this == Id::classInvariant) p = "invariant";
|
||||
else if (this == Id::unitTest) p = "unittest";
|
||||
else if (this == Id::dollar) p = "$";
|
||||
else if (this == Id::withSym) p = "with";
|
||||
else if (this == Id::result) p = "result";
|
||||
else if (this == Id::returnLabel) p = "return";
|
||||
else
|
||||
{ p = toChars();
|
||||
if (*p == '_')
|
||||
{
|
||||
if (memcmp(p, "_staticCtor", 11) == 0)
|
||||
p = "static this";
|
||||
else if (memcmp(p, "_staticDtor", 11) == 0)
|
||||
p = "static ~this";
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Identifier::print()
|
||||
{
|
||||
fprintf(stdmsg, "%s",string);
|
||||
}
|
||||
|
||||
int Identifier::dyncast()
|
||||
{
|
||||
return DYNCAST_IDENTIFIER;
|
||||
}
|
||||
|
||||
|
||||
Identifier *Identifier::generateId(const char *prefix)
|
||||
{
|
||||
static size_t i;
|
||||
|
||||
return generateId(prefix, ++i);
|
||||
}
|
||||
|
||||
Identifier *Identifier::generateId(const char *prefix, size_t i)
|
||||
{ OutBuffer buf;
|
||||
|
||||
buf.writestring(prefix);
|
||||
buf.printf("%"PRIuSIZE, i);
|
||||
|
||||
char *id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
return Lexer::idPool(id);
|
||||
}
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "identifier.h"
|
||||
#include "mars.h"
|
||||
#include "lexer.h"
|
||||
#include "id.h"
|
||||
|
||||
Identifier::Identifier(const char *string, int value)
|
||||
{
|
||||
//printf("Identifier('%s', %d)\n", string, value);
|
||||
this->string = string;
|
||||
this->value = value;
|
||||
this->len = strlen(string);
|
||||
}
|
||||
|
||||
hash_t Identifier::hashCode()
|
||||
{
|
||||
return String::calcHash(string);
|
||||
}
|
||||
|
||||
int Identifier::equals(Object *o)
|
||||
{
|
||||
return this == o || memcmp(string,o->toChars(),len+1) == 0;
|
||||
}
|
||||
|
||||
int Identifier::compare(Object *o)
|
||||
{
|
||||
return memcmp(string, o->toChars(), len + 1);
|
||||
}
|
||||
|
||||
char *Identifier::toChars()
|
||||
{
|
||||
return (char *)string;
|
||||
}
|
||||
|
||||
const char *Identifier::toHChars2()
|
||||
{
|
||||
const char *p = NULL;
|
||||
|
||||
if (this == Id::ctor) p = "this";
|
||||
else if (this == Id::dtor) p = "~this";
|
||||
else if (this == Id::classInvariant) p = "invariant";
|
||||
else if (this == Id::unitTest) p = "unittest";
|
||||
else if (this == Id::dollar) p = "$";
|
||||
else if (this == Id::withSym) p = "with";
|
||||
else if (this == Id::result) p = "result";
|
||||
else if (this == Id::returnLabel) p = "return";
|
||||
else
|
||||
{ p = toChars();
|
||||
if (*p == '_')
|
||||
{
|
||||
if (memcmp(p, "_staticCtor", 11) == 0)
|
||||
p = "static this";
|
||||
else if (memcmp(p, "_staticDtor", 11) == 0)
|
||||
p = "static ~this";
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Identifier::print()
|
||||
{
|
||||
fprintf(stdmsg, "%s",string);
|
||||
}
|
||||
|
||||
int Identifier::dyncast()
|
||||
{
|
||||
return DYNCAST_IDENTIFIER;
|
||||
}
|
||||
|
||||
// BUG: these are redundant with Lexer::uniqueId()
|
||||
|
||||
Identifier *Identifier::generateId(const char *prefix)
|
||||
{
|
||||
static size_t i;
|
||||
|
||||
return generateId(prefix, ++i);
|
||||
}
|
||||
|
||||
Identifier *Identifier::generateId(const char *prefix, size_t i)
|
||||
{ OutBuffer buf;
|
||||
|
||||
buf.writestring(prefix);
|
||||
buf.printf("%zu", i);
|
||||
|
||||
char *id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
return Lexer::idPool(id);
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#if IN_LLVM
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Identifier : Object
|
||||
{
|
||||
|
||||
BIN
dmd2/idgen
Executable file
BIN
dmd2/idgen
Executable file
Binary file not shown.
742
dmd2/idgen.c
742
dmd2/idgen.c
@@ -1,363 +1,379 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
// Program to generate string files in d data structures.
|
||||
// Saves much tedious typing, and eliminates typo problems.
|
||||
// Generates:
|
||||
// id.h
|
||||
// id.c
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct Msgtable
|
||||
{
|
||||
const char *ident; // name to use in DMD source
|
||||
const char *name; // name in D executable
|
||||
};
|
||||
|
||||
Msgtable msgtable[] =
|
||||
{
|
||||
{ "IUnknown" },
|
||||
{ "Object" },
|
||||
{ "object" },
|
||||
{ "max" },
|
||||
{ "min" },
|
||||
{ "This", "this" },
|
||||
{ "ctor", "__ctor" },
|
||||
{ "dtor", "__dtor" },
|
||||
{ "cpctor", "__cpctor" },
|
||||
{ "_postblit", "__postblit" },
|
||||
{ "classInvariant", "__invariant" },
|
||||
{ "unitTest", "__unitTest" },
|
||||
{ "init" },
|
||||
{ "size" },
|
||||
{ "__sizeof", "sizeof" },
|
||||
{ "alignof" },
|
||||
{ "mangleof" },
|
||||
{ "stringof" },
|
||||
{ "tupleof" },
|
||||
{ "length" },
|
||||
{ "remove" },
|
||||
{ "ptr" },
|
||||
{ "funcptr" },
|
||||
{ "dollar", "__dollar" },
|
||||
{ "offset" },
|
||||
{ "offsetof" },
|
||||
{ "ModuleInfo" },
|
||||
{ "ClassInfo" },
|
||||
{ "classinfo" },
|
||||
{ "typeinfo" },
|
||||
{ "outer" },
|
||||
{ "Exception" },
|
||||
{ "withSym", "__withSym" },
|
||||
{ "result", "__result" },
|
||||
{ "returnLabel", "__returnLabel" },
|
||||
{ "delegate" },
|
||||
{ "line" },
|
||||
{ "empty", "" },
|
||||
{ "p" },
|
||||
{ "coverage", "__coverage" },
|
||||
{ "__vptr" },
|
||||
{ "__monitor" },
|
||||
{ "system" },
|
||||
|
||||
{ "TypeInfo" },
|
||||
{ "TypeInfo_Class" },
|
||||
{ "TypeInfo_Interface" },
|
||||
{ "TypeInfo_Struct" },
|
||||
{ "TypeInfo_Enum" },
|
||||
{ "TypeInfo_Typedef" },
|
||||
{ "TypeInfo_Pointer" },
|
||||
{ "TypeInfo_Array" },
|
||||
{ "TypeInfo_StaticArray" },
|
||||
{ "TypeInfo_AssociativeArray" },
|
||||
{ "TypeInfo_Function" },
|
||||
{ "TypeInfo_Delegate" },
|
||||
{ "TypeInfo_Tuple" },
|
||||
{ "TypeInfo_Const" },
|
||||
{ "TypeInfo_Invariant" },
|
||||
{ "elements" },
|
||||
{ "_arguments_typeinfo" },
|
||||
{ "_arguments" },
|
||||
{ "_argptr" },
|
||||
{ "_match" },
|
||||
{ "destroy" },
|
||||
{ "postblit" },
|
||||
|
||||
{ "LINE", "__LINE__" },
|
||||
{ "FILE", "__FILE__" },
|
||||
{ "DATE", "__DATE__" },
|
||||
{ "TIME", "__TIME__" },
|
||||
{ "TIMESTAMP", "__TIMESTAMP__" },
|
||||
{ "VENDOR", "__VENDOR__" },
|
||||
{ "VERSIONX", "__VERSION__" },
|
||||
{ "EOFX", "__EOF__" },
|
||||
|
||||
{ "nan" },
|
||||
{ "infinity" },
|
||||
{ "dig" },
|
||||
{ "epsilon" },
|
||||
{ "mant_dig" },
|
||||
{ "max_10_exp" },
|
||||
{ "max_exp" },
|
||||
{ "min_10_exp" },
|
||||
{ "min_exp" },
|
||||
{ "re" },
|
||||
{ "im" },
|
||||
|
||||
{ "C" },
|
||||
{ "D" },
|
||||
{ "Windows" },
|
||||
{ "Pascal" },
|
||||
{ "System" },
|
||||
|
||||
{ "exit" },
|
||||
{ "success" },
|
||||
{ "failure" },
|
||||
|
||||
{ "keys" },
|
||||
{ "values" },
|
||||
{ "rehash" },
|
||||
|
||||
{ "sort" },
|
||||
{ "reverse" },
|
||||
{ "dup" },
|
||||
{ "idup" },
|
||||
|
||||
// For inline assembler
|
||||
{ "___out", "out" },
|
||||
{ "___in", "in" },
|
||||
{ "__int", "int" },
|
||||
{ "__dollar", "$" },
|
||||
{ "__LOCAL_SIZE" },
|
||||
|
||||
// For operator overloads
|
||||
{ "uadd", "opPos" },
|
||||
{ "neg", "opNeg" },
|
||||
{ "com", "opCom" },
|
||||
{ "add", "opAdd" },
|
||||
{ "add_r", "opAdd_r" },
|
||||
{ "sub", "opSub" },
|
||||
{ "sub_r", "opSub_r" },
|
||||
{ "mul", "opMul" },
|
||||
{ "mul_r", "opMul_r" },
|
||||
{ "div", "opDiv" },
|
||||
{ "div_r", "opDiv_r" },
|
||||
{ "mod", "opMod" },
|
||||
{ "mod_r", "opMod_r" },
|
||||
{ "eq", "opEquals" },
|
||||
{ "cmp", "opCmp" },
|
||||
{ "iand", "opAnd" },
|
||||
{ "iand_r", "opAnd_r" },
|
||||
{ "ior", "opOr" },
|
||||
{ "ior_r", "opOr_r" },
|
||||
{ "ixor", "opXor" },
|
||||
{ "ixor_r", "opXor_r" },
|
||||
{ "shl", "opShl" },
|
||||
{ "shl_r", "opShl_r" },
|
||||
{ "shr", "opShr" },
|
||||
{ "shr_r", "opShr_r" },
|
||||
{ "ushr", "opUShr" },
|
||||
{ "ushr_r", "opUShr_r" },
|
||||
{ "cat", "opCat" },
|
||||
{ "cat_r", "opCat_r" },
|
||||
{ "assign", "opAssign" },
|
||||
{ "addass", "opAddAssign" },
|
||||
{ "subass", "opSubAssign" },
|
||||
{ "mulass", "opMulAssign" },
|
||||
{ "divass", "opDivAssign" },
|
||||
{ "modass", "opModAssign" },
|
||||
{ "andass", "opAndAssign" },
|
||||
{ "orass", "opOrAssign" },
|
||||
{ "xorass", "opXorAssign" },
|
||||
{ "shlass", "opShlAssign" },
|
||||
{ "shrass", "opShrAssign" },
|
||||
{ "ushrass", "opUShrAssign" },
|
||||
{ "catass", "opCatAssign" },
|
||||
{ "postinc", "opPostInc" },
|
||||
{ "postdec", "opPostDec" },
|
||||
{ "index", "opIndex" },
|
||||
{ "indexass", "opIndexAssign" },
|
||||
{ "slice", "opSlice" },
|
||||
{ "sliceass", "opSliceAssign" },
|
||||
{ "call", "opCall" },
|
||||
{ "cast", "opCast" },
|
||||
{ "match", "opMatch" },
|
||||
{ "next", "opNext" },
|
||||
{ "opIn" },
|
||||
{ "opIn_r" },
|
||||
{ "opStar" },
|
||||
{ "opDot" },
|
||||
{ "opImplicitCast" },
|
||||
|
||||
{ "classNew", "new" },
|
||||
{ "classDelete", "delete" },
|
||||
|
||||
// For foreach
|
||||
{ "apply", "opApply" },
|
||||
{ "applyReverse", "opApplyReverse" },
|
||||
|
||||
{ "Fempty", "empty" },
|
||||
{ "Fhead", "head" },
|
||||
{ "Ftoe", "toe" },
|
||||
{ "Fnext", "next" },
|
||||
{ "Fretreat", "retreat" },
|
||||
|
||||
{ "adDup", "_adDupT" },
|
||||
{ "adReverse", "_adReverse" },
|
||||
|
||||
// For internal functions
|
||||
{ "aaLen", "_aaLen" },
|
||||
{ "aaKeys", "_aaKeys" },
|
||||
{ "aaValues", "_aaValues" },
|
||||
{ "aaRehash", "_aaRehash" },
|
||||
|
||||
// For pragma's
|
||||
{ "GNU_asm" },
|
||||
{ "lib" },
|
||||
{ "msg" },
|
||||
{ "startaddress" },
|
||||
|
||||
// LDC pragma's
|
||||
{ "intrinsic" },
|
||||
{ "va_intrinsic" },
|
||||
{ "no_typeinfo" },
|
||||
{ "no_moduleinfo" },
|
||||
{ "Alloca", "alloca" },
|
||||
{ "vastart", "va_start" },
|
||||
{ "vacopy", "va_copy" },
|
||||
{ "vaend", "va_end" },
|
||||
{ "vaarg", "va_arg" },
|
||||
{ "ldc" },
|
||||
{ "allow_inline" },
|
||||
|
||||
// For special functions
|
||||
{ "tohash", "toHash" },
|
||||
{ "tostring", "toString" },
|
||||
{ "getmembers", "getMembers" },
|
||||
|
||||
// Special functions
|
||||
//{ "alloca" },
|
||||
{ "main" },
|
||||
{ "WinMain" },
|
||||
{ "DllMain" },
|
||||
|
||||
// Builtin functions
|
||||
{ "std" },
|
||||
{ "math" },
|
||||
{ "sin" },
|
||||
{ "cos" },
|
||||
{ "tan" },
|
||||
{ "_sqrt", "sqrt" },
|
||||
{ "fabs" },
|
||||
|
||||
// Traits
|
||||
{ "isAbstractClass" },
|
||||
{ "isArithmetic" },
|
||||
{ "isAssociativeArray" },
|
||||
{ "isFinalClass" },
|
||||
{ "isFloating" },
|
||||
{ "isIntegral" },
|
||||
{ "isScalar" },
|
||||
{ "isStaticArray" },
|
||||
{ "isUnsigned" },
|
||||
{ "isVirtualFunction" },
|
||||
{ "isAbstractFunction" },
|
||||
{ "isFinalFunction" },
|
||||
{ "hasMember" },
|
||||
{ "getMember" },
|
||||
{ "getVirtualFunctions" },
|
||||
{ "classInstanceSize" },
|
||||
{ "allMembers" },
|
||||
{ "derivedMembers" },
|
||||
{ "isSame" },
|
||||
{ "compiles" },
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned i;
|
||||
|
||||
{
|
||||
fp = fopen("id.h","w");
|
||||
if (!fp)
|
||||
{ printf("can't open id.h\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(fp, "// File generated by idgen.c\n");
|
||||
#if __DMC__
|
||||
fprintf(fp, "#pragma once\n");
|
||||
#endif
|
||||
fprintf(fp, "#ifndef DMD_ID_H\n");
|
||||
fprintf(fp, "#define DMD_ID_H 1\n");
|
||||
fprintf(fp, "struct Identifier;\n");
|
||||
fprintf(fp, "struct Id\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
|
||||
fprintf(fp," static Identifier *%s;\n", id);
|
||||
}
|
||||
|
||||
fprintf(fp, " static void initialize();\n");
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
{
|
||||
fp = fopen("id.c","w");
|
||||
if (!fp)
|
||||
{ printf("can't open id.c\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(fp, "// File generated by idgen.c\n");
|
||||
fprintf(fp, "#include \"id.h\"\n");
|
||||
fprintf(fp, "#include \"identifier.h\"\n");
|
||||
fprintf(fp, "#include \"lexer.h\"\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
const char *p = msgtable[i].name;
|
||||
|
||||
if (!p)
|
||||
p = id;
|
||||
fprintf(fp,"Identifier *Id::%s;\n", id);
|
||||
}
|
||||
|
||||
fprintf(fp, "void Id::initialize()\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
const char *p = msgtable[i].name;
|
||||
|
||||
if (!p)
|
||||
p = id;
|
||||
fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p);
|
||||
}
|
||||
|
||||
fprintf(fp, "}\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
// Program to generate string files in d data structures.
|
||||
// Saves much tedious typing, and eliminates typo problems.
|
||||
// Generates:
|
||||
// id.h
|
||||
// id.c
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct Msgtable
|
||||
{
|
||||
const char *ident; // name to use in DMD source
|
||||
const char *name; // name in D executable
|
||||
};
|
||||
|
||||
Msgtable msgtable[] =
|
||||
{
|
||||
{ "IUnknown" },
|
||||
{ "Object" },
|
||||
{ "object" },
|
||||
{ "max" },
|
||||
{ "min" },
|
||||
{ "This", "this" },
|
||||
{ "ctor", "__ctor" },
|
||||
{ "dtor", "__dtor" },
|
||||
{ "cpctor", "__cpctor" },
|
||||
{ "_postblit", "__postblit" },
|
||||
{ "classInvariant", "__invariant" },
|
||||
{ "unitTest", "__unitTest" },
|
||||
{ "init" },
|
||||
{ "size" },
|
||||
{ "__sizeof", "sizeof" },
|
||||
{ "alignof" },
|
||||
{ "mangleof" },
|
||||
{ "stringof" },
|
||||
{ "tupleof" },
|
||||
{ "length" },
|
||||
{ "remove" },
|
||||
{ "ptr" },
|
||||
{ "funcptr" },
|
||||
{ "dollar", "__dollar" },
|
||||
{ "offset" },
|
||||
{ "offsetof" },
|
||||
{ "ModuleInfo" },
|
||||
{ "ClassInfo" },
|
||||
{ "classinfo" },
|
||||
{ "typeinfo" },
|
||||
{ "outer" },
|
||||
{ "Exception" },
|
||||
{ "Throwable" },
|
||||
{ "withSym", "__withSym" },
|
||||
{ "result", "__result" },
|
||||
{ "returnLabel", "__returnLabel" },
|
||||
{ "delegate" },
|
||||
{ "line" },
|
||||
{ "empty", "" },
|
||||
{ "p" },
|
||||
{ "coverage", "__coverage" },
|
||||
{ "__vptr" },
|
||||
{ "__monitor" },
|
||||
{ "system" },
|
||||
|
||||
{ "TypeInfo" },
|
||||
{ "TypeInfo_Class" },
|
||||
{ "TypeInfo_Interface" },
|
||||
{ "TypeInfo_Struct" },
|
||||
{ "TypeInfo_Enum" },
|
||||
{ "TypeInfo_Typedef" },
|
||||
{ "TypeInfo_Pointer" },
|
||||
{ "TypeInfo_Array" },
|
||||
{ "TypeInfo_StaticArray" },
|
||||
{ "TypeInfo_AssociativeArray" },
|
||||
{ "TypeInfo_Function" },
|
||||
{ "TypeInfo_Delegate" },
|
||||
{ "TypeInfo_Tuple" },
|
||||
{ "TypeInfo_Const" },
|
||||
{ "TypeInfo_Invariant" },
|
||||
{ "TypeInfo_Shared" },
|
||||
{ "elements" },
|
||||
{ "_arguments_typeinfo" },
|
||||
{ "_arguments" },
|
||||
{ "_argptr" },
|
||||
{ "_match" },
|
||||
{ "destroy" },
|
||||
{ "postblit" },
|
||||
|
||||
{ "LINE", "__LINE__" },
|
||||
{ "FILE", "__FILE__" },
|
||||
{ "DATE", "__DATE__" },
|
||||
{ "TIME", "__TIME__" },
|
||||
{ "TIMESTAMP", "__TIMESTAMP__" },
|
||||
{ "VENDOR", "__VENDOR__" },
|
||||
{ "VERSIONX", "__VERSION__" },
|
||||
{ "EOFX", "__EOF__" },
|
||||
|
||||
{ "nan" },
|
||||
{ "infinity" },
|
||||
{ "dig" },
|
||||
{ "epsilon" },
|
||||
{ "mant_dig" },
|
||||
{ "max_10_exp" },
|
||||
{ "max_exp" },
|
||||
{ "min_10_exp" },
|
||||
{ "min_exp" },
|
||||
{ "re" },
|
||||
{ "im" },
|
||||
|
||||
{ "C" },
|
||||
{ "D" },
|
||||
{ "Windows" },
|
||||
{ "Pascal" },
|
||||
{ "System" },
|
||||
|
||||
{ "exit" },
|
||||
{ "success" },
|
||||
{ "failure" },
|
||||
|
||||
{ "keys" },
|
||||
{ "values" },
|
||||
{ "rehash" },
|
||||
|
||||
{ "sort" },
|
||||
{ "reverse" },
|
||||
{ "dup" },
|
||||
{ "idup" },
|
||||
|
||||
// For inline assembler
|
||||
{ "___out", "out" },
|
||||
{ "___in", "in" },
|
||||
{ "__int", "int" },
|
||||
{ "__dollar", "$" },
|
||||
{ "__LOCAL_SIZE" },
|
||||
|
||||
// For operator overloads
|
||||
{ "uadd", "opPos" },
|
||||
{ "neg", "opNeg" },
|
||||
{ "com", "opCom" },
|
||||
{ "add", "opAdd" },
|
||||
{ "add_r", "opAdd_r" },
|
||||
{ "sub", "opSub" },
|
||||
{ "sub_r", "opSub_r" },
|
||||
{ "mul", "opMul" },
|
||||
{ "mul_r", "opMul_r" },
|
||||
{ "div", "opDiv" },
|
||||
{ "div_r", "opDiv_r" },
|
||||
{ "mod", "opMod" },
|
||||
{ "mod_r", "opMod_r" },
|
||||
{ "eq", "opEquals" },
|
||||
{ "cmp", "opCmp" },
|
||||
{ "iand", "opAnd" },
|
||||
{ "iand_r", "opAnd_r" },
|
||||
{ "ior", "opOr" },
|
||||
{ "ior_r", "opOr_r" },
|
||||
{ "ixor", "opXor" },
|
||||
{ "ixor_r", "opXor_r" },
|
||||
{ "shl", "opShl" },
|
||||
{ "shl_r", "opShl_r" },
|
||||
{ "shr", "opShr" },
|
||||
{ "shr_r", "opShr_r" },
|
||||
{ "ushr", "opUShr" },
|
||||
{ "ushr_r", "opUShr_r" },
|
||||
{ "cat", "opCat" },
|
||||
{ "cat_r", "opCat_r" },
|
||||
{ "assign", "opAssign" },
|
||||
{ "addass", "opAddAssign" },
|
||||
{ "subass", "opSubAssign" },
|
||||
{ "mulass", "opMulAssign" },
|
||||
{ "divass", "opDivAssign" },
|
||||
{ "modass", "opModAssign" },
|
||||
{ "andass", "opAndAssign" },
|
||||
{ "orass", "opOrAssign" },
|
||||
{ "xorass", "opXorAssign" },
|
||||
{ "shlass", "opShlAssign" },
|
||||
{ "shrass", "opShrAssign" },
|
||||
{ "ushrass", "opUShrAssign" },
|
||||
{ "catass", "opCatAssign" },
|
||||
{ "postinc", "opPostInc" },
|
||||
{ "postdec", "opPostDec" },
|
||||
{ "index", "opIndex" },
|
||||
{ "indexass", "opIndexAssign" },
|
||||
{ "slice", "opSlice" },
|
||||
{ "sliceass", "opSliceAssign" },
|
||||
{ "call", "opCall" },
|
||||
{ "cast", "opCast" },
|
||||
{ "match", "opMatch" },
|
||||
{ "next", "opNext" },
|
||||
{ "opIn" },
|
||||
{ "opIn_r" },
|
||||
{ "opStar" },
|
||||
{ "opDot" },
|
||||
{ "opImplicitCast" },
|
||||
|
||||
{ "classNew", "new" },
|
||||
{ "classDelete", "delete" },
|
||||
|
||||
// For foreach
|
||||
{ "apply", "opApply" },
|
||||
{ "applyReverse", "opApplyReverse" },
|
||||
|
||||
#if 1
|
||||
{ "Fempty", "empty" },
|
||||
{ "Fhead", "front" },
|
||||
{ "Ftoe", "back" },
|
||||
{ "Fnext", "popFront" },
|
||||
{ "Fretreat", "popBack" },
|
||||
#else
|
||||
{ "Fempty", "empty" },
|
||||
{ "Fhead", "head" },
|
||||
{ "Ftoe", "toe" },
|
||||
{ "Fnext", "next" },
|
||||
{ "Fretreat", "retreat" },
|
||||
#endif
|
||||
|
||||
{ "adDup", "_adDupT" },
|
||||
{ "adReverse", "_adReverse" },
|
||||
|
||||
// For internal functions
|
||||
{ "aaLen", "_aaLen" },
|
||||
{ "aaKeys", "_aaKeys" },
|
||||
{ "aaValues", "_aaValues" },
|
||||
{ "aaRehash", "_aaRehash" },
|
||||
|
||||
// For pragma's
|
||||
{ "GNU_asm" },
|
||||
{ "lib" },
|
||||
{ "msg" },
|
||||
{ "startaddress" },
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC pragma's
|
||||
{ "intrinsic" },
|
||||
{ "va_intrinsic" },
|
||||
{ "no_typeinfo" },
|
||||
{ "no_moduleinfo" },
|
||||
{ "Alloca", "alloca" },
|
||||
{ "vastart", "va_start" },
|
||||
{ "vacopy", "va_copy" },
|
||||
{ "vaend", "va_end" },
|
||||
{ "vaarg", "va_arg" },
|
||||
{ "ldc" },
|
||||
{ "allow_inline" },
|
||||
{ "llvm_inline_asm" },
|
||||
#endif
|
||||
|
||||
// For special functions
|
||||
{ "tohash", "toHash" },
|
||||
{ "tostring", "toString" },
|
||||
{ "getmembers", "getMembers" },
|
||||
|
||||
// Special functions
|
||||
#if IN_DMD
|
||||
{ "alloca" },
|
||||
#endif
|
||||
{ "main" },
|
||||
{ "WinMain" },
|
||||
{ "DllMain" },
|
||||
{ "tls_get_addr", "___tls_get_addr" },
|
||||
|
||||
// Builtin functions
|
||||
{ "std" },
|
||||
{ "math" },
|
||||
{ "sin" },
|
||||
{ "cos" },
|
||||
{ "tan" },
|
||||
{ "_sqrt", "sqrt" },
|
||||
{ "fabs" },
|
||||
|
||||
// Traits
|
||||
{ "isAbstractClass" },
|
||||
{ "isArithmetic" },
|
||||
{ "isAssociativeArray" },
|
||||
{ "isFinalClass" },
|
||||
{ "isFloating" },
|
||||
{ "isIntegral" },
|
||||
{ "isScalar" },
|
||||
{ "isStaticArray" },
|
||||
{ "isUnsigned" },
|
||||
{ "isVirtualFunction" },
|
||||
{ "isAbstractFunction" },
|
||||
{ "isFinalFunction" },
|
||||
{ "hasMember" },
|
||||
{ "getMember" },
|
||||
{ "getVirtualFunctions" },
|
||||
{ "classInstanceSize" },
|
||||
{ "allMembers" },
|
||||
{ "derivedMembers" },
|
||||
{ "isSame" },
|
||||
{ "compiles" },
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned i;
|
||||
|
||||
{
|
||||
fp = fopen("id.h","w");
|
||||
if (!fp)
|
||||
{ printf("can't open id.h\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(fp, "// File generated by idgen.c\n");
|
||||
#if __DMC__
|
||||
fprintf(fp, "#pragma once\n");
|
||||
#endif
|
||||
fprintf(fp, "#ifndef DMD_ID_H\n");
|
||||
fprintf(fp, "#define DMD_ID_H 1\n");
|
||||
fprintf(fp, "struct Identifier;\n");
|
||||
fprintf(fp, "struct Id\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
|
||||
fprintf(fp," static Identifier *%s;\n", id);
|
||||
}
|
||||
|
||||
fprintf(fp, " static void initialize();\n");
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
{
|
||||
fp = fopen("id.c","w");
|
||||
if (!fp)
|
||||
{ printf("can't open id.c\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(fp, "// File generated by idgen.c\n");
|
||||
fprintf(fp, "#include \"id.h\"\n");
|
||||
fprintf(fp, "#include \"identifier.h\"\n");
|
||||
fprintf(fp, "#include \"lexer.h\"\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
const char *p = msgtable[i].name;
|
||||
|
||||
if (!p)
|
||||
p = id;
|
||||
fprintf(fp,"Identifier *Id::%s;\n", id);
|
||||
}
|
||||
|
||||
fprintf(fp, "void Id::initialize()\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
|
||||
{ const char *id = msgtable[i].ident;
|
||||
const char *p = msgtable[i].name;
|
||||
|
||||
if (!p)
|
||||
p = id;
|
||||
fprintf(fp," %s = Lexer::idPool(\"%s\");\n", id, p);
|
||||
}
|
||||
|
||||
fprintf(fp, "}\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
BIN
dmd2/impcnvgen
Executable file
BIN
dmd2/impcnvgen
Executable file
Binary file not shown.
182
dmd2/impcnvtab.c
Normal file
182
dmd2/impcnvtab.c
Normal file
@@ -0,0 +1,182 @@
|
||||
// This file is generated by impcnvgen.c
|
||||
#include "mtype.h"
|
||||
unsigned char Type::impcnvResult[TMAX][TMAX] =
|
||||
{
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
};
|
||||
unsigned char Type::impcnvType1[TMAX][TMAX] =
|
||||
{
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,22,23,24,36,19,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,22,23,24,36,20,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,22,23,24,36,21,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,22,23,24,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,23,23,24,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,25,25,25,25,25,25,25,25,25,26,27,25,26,27,25,26,27,36,25,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,26,26,26,26,26,26,26,26,26,26,27,26,26,27,26,26,27,36,26,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,36,27,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,32,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
};
|
||||
unsigned char Type::impcnvType2[TMAX][TMAX] =
|
||||
{
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
};
|
||||
unsigned char Type::impcnvWarn[TMAX][TMAX] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
635
dmd2/import.c
635
dmd2/import.c
@@ -1,262 +1,373 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
#include "import.h"
|
||||
#include "identifier.h"
|
||||
#include "module.h"
|
||||
#include "scope.h"
|
||||
#include "hdrgen.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "id.h"
|
||||
|
||||
/********************************* Import ****************************/
|
||||
|
||||
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
|
||||
int isstatic)
|
||||
: Dsymbol(id)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->packages = packages;
|
||||
this->id = id;
|
||||
this->aliasId = aliasId;
|
||||
this->isstatic = isstatic;
|
||||
protection = PROTundefined;
|
||||
pkg = NULL;
|
||||
mod = NULL;
|
||||
|
||||
if (aliasId)
|
||||
this->ident = aliasId;
|
||||
// Kludge to change Import identifier to first package
|
||||
else if (packages && packages->dim)
|
||||
this->ident = (Identifier *)packages->data[0];
|
||||
}
|
||||
|
||||
void Import::addAlias(Identifier *name, Identifier *alias)
|
||||
{
|
||||
if (isstatic)
|
||||
error("cannot have an import bind list");
|
||||
|
||||
if (!aliasId)
|
||||
this->ident = NULL; // make it an anonymous import
|
||||
|
||||
names.push(name);
|
||||
aliases.push(alias);
|
||||
}
|
||||
|
||||
const char *Import::kind()
|
||||
{
|
||||
return isstatic ? (char *)"static import" : (char *)"import";
|
||||
}
|
||||
|
||||
enum PROT Import::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
|
||||
Dsymbol *Import::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(!s);
|
||||
|
||||
Import *si;
|
||||
|
||||
si = new Import(loc, packages, id, aliasId, isstatic);
|
||||
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
|
||||
}
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
void Import::load(Scope *sc)
|
||||
{
|
||||
DsymbolTable *dst;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("Import::load('%s')\n", toChars());
|
||||
|
||||
// See if existing module
|
||||
dst = Package::resolve(packages, NULL, &pkg);
|
||||
|
||||
s = dst->lookup(id);
|
||||
if (s)
|
||||
{
|
||||
if (s->isModule())
|
||||
mod = (Module *)s;
|
||||
else
|
||||
error("package and module have the same name");
|
||||
}
|
||||
|
||||
if (!mod)
|
||||
{
|
||||
// Load module
|
||||
mod = Module::load(loc, packages, id);
|
||||
dst->insert(id, mod); // id may be different from mod->ident,
|
||||
// if so then insert alias
|
||||
if (!mod->importedFrom)
|
||||
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
||||
}
|
||||
if (!pkg)
|
||||
pkg = mod;
|
||||
mod->semantic();
|
||||
|
||||
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
|
||||
|
||||
void Import::semantic(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic('%s')\n", toChars());
|
||||
|
||||
load(sc);
|
||||
|
||||
if (mod)
|
||||
{
|
||||
#if 0
|
||||
if (mod->loc.linnum != 0)
|
||||
{ /* If the line number is not 0, then this is not
|
||||
* a 'root' module, i.e. it was not specified on the command line.
|
||||
*/
|
||||
mod->importedFrom = sc->module->importedFrom;
|
||||
assert(mod->importedFrom);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Default to private importing
|
||||
*/
|
||||
protection = sc->protection;
|
||||
if (!sc->explicitProtection)
|
||||
protection = PROTprivate;
|
||||
|
||||
if (!isstatic && !aliasId && !names.dim)
|
||||
{
|
||||
sc->scopesym->importScope(mod, protection);
|
||||
}
|
||||
|
||||
// Modules need a list of each imported module
|
||||
sc->module->aimports.push(mod);
|
||||
|
||||
if (mod->needmoduleinfo)
|
||||
sc->module->needmoduleinfo = 1;
|
||||
|
||||
sc = sc->push(mod);
|
||||
for (size_t i = 0; i < aliasdecls.dim; i++)
|
||||
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
|
||||
|
||||
//printf("\tImport alias semantic('%s')\n", s->toChars());
|
||||
if (!mod->search(loc, (Identifier *)names.data[i], 0))
|
||||
error("%s not found", ((Identifier *)names.data[i])->toChars());
|
||||
|
||||
ad->semantic(sc);
|
||||
ad->protection = protection;
|
||||
}
|
||||
sc = sc->pop();
|
||||
}
|
||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
|
||||
void Import::semantic2(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic2('%s')\n", toChars());
|
||||
mod->semantic2();
|
||||
if (mod->needmoduleinfo)
|
||||
sc->module->needmoduleinfo = 1;
|
||||
}
|
||||
|
||||
Dsymbol *Import::toAlias()
|
||||
{
|
||||
if (aliasId)
|
||||
return mod;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* Add import to sd's symbol table.
|
||||
*/
|
||||
|
||||
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (names.dim == 0)
|
||||
return Dsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
if (aliasId)
|
||||
result = Dsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
/* Instead of adding the import to sd's symbol table,
|
||||
* add each of the alias=name pairs
|
||||
*/
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
Identifier *name = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[i];
|
||||
|
||||
if (!alias)
|
||||
alias = name;
|
||||
|
||||
TypeIdentifier *tname = new TypeIdentifier(loc, name);
|
||||
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
|
||||
result |= ad->addMember(sc, sd, memnum);
|
||||
|
||||
aliasdecls.push(ad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
|
||||
|
||||
if (!pkg)
|
||||
load(NULL);
|
||||
|
||||
// Forward it to the package/module
|
||||
return pkg->search(loc, ident, flags);
|
||||
}
|
||||
|
||||
int Import::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
// Allow multiple imports of the same name
|
||||
return s->isImport() != NULL;
|
||||
}
|
||||
|
||||
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (hgs->hdrgen && id == Id::object)
|
||||
return; // object is imported by default
|
||||
|
||||
if (isstatic)
|
||||
buf->writestring("static ");
|
||||
buf->writestring("import ");
|
||||
if (aliasId)
|
||||
{
|
||||
buf->printf("%s = ", aliasId->toChars());
|
||||
}
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
|
||||
buf->printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
buf->printf("%s;", id->toChars());
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
#include "import.h"
|
||||
#include "identifier.h"
|
||||
#include "module.h"
|
||||
#include "scope.h"
|
||||
#include "hdrgen.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "id.h"
|
||||
|
||||
/********************************* Import ****************************/
|
||||
|
||||
Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
|
||||
int isstatic)
|
||||
: Dsymbol(id)
|
||||
{
|
||||
assert(id);
|
||||
this->loc = loc;
|
||||
this->packages = packages;
|
||||
this->id = id;
|
||||
this->aliasId = aliasId;
|
||||
this->isstatic = isstatic;
|
||||
#if IN_LLVM
|
||||
protection = PROTundefined;
|
||||
#endif
|
||||
pkg = NULL;
|
||||
mod = NULL;
|
||||
|
||||
if (aliasId)
|
||||
this->ident = aliasId;
|
||||
// Kludge to change Import identifier to first package
|
||||
else if (packages && packages->dim)
|
||||
this->ident = (Identifier *)packages->data[0];
|
||||
}
|
||||
|
||||
void Import::addAlias(Identifier *name, Identifier *alias)
|
||||
{
|
||||
if (isstatic)
|
||||
error("cannot have an import bind list");
|
||||
|
||||
if (!aliasId)
|
||||
this->ident = NULL; // make it an anonymous import
|
||||
|
||||
names.push(name);
|
||||
aliases.push(alias);
|
||||
}
|
||||
|
||||
const char *Import::kind()
|
||||
{
|
||||
return isstatic ? (char *)"static import" : (char *)"import";
|
||||
}
|
||||
|
||||
#if IN_LLVM
|
||||
enum PROT Import::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
#endif
|
||||
|
||||
Dsymbol *Import::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(!s);
|
||||
|
||||
Import *si;
|
||||
|
||||
si = new Import(loc, packages, id, aliasId, isstatic);
|
||||
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
|
||||
}
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
void Import::load(Scope *sc)
|
||||
{
|
||||
DsymbolTable *dst;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("Import::load('%s')\n", toChars());
|
||||
|
||||
// See if existing module
|
||||
dst = Package::resolve(packages, NULL, &pkg);
|
||||
|
||||
s = dst->lookup(id);
|
||||
if (s)
|
||||
{
|
||||
if (s->isModule())
|
||||
mod = (Module *)s;
|
||||
else
|
||||
error("package and module have the same name");
|
||||
}
|
||||
|
||||
if (!mod)
|
||||
{
|
||||
// Load module
|
||||
mod = Module::load(loc, packages, id);
|
||||
dst->insert(id, mod); // id may be different from mod->ident,
|
||||
// if so then insert alias
|
||||
if (!mod->importedFrom)
|
||||
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
||||
}
|
||||
if (!pkg)
|
||||
pkg = mod;
|
||||
|
||||
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
|
||||
#if IN_LLVM
|
||||
char* escapePath(char* fname, char* buffer, int bufLen) {
|
||||
char* res = buffer;
|
||||
bufLen -= 2; // for \0 and an occasional escape char
|
||||
int dst = 0;
|
||||
for (; dst < bufLen && *fname; ++dst, ++fname) {
|
||||
switch (*fname) {
|
||||
case '(':
|
||||
case ')':
|
||||
case '\\':
|
||||
buffer[dst++] = '\\';
|
||||
// fall through
|
||||
|
||||
default:
|
||||
buffer[dst] = *fname;
|
||||
}
|
||||
}
|
||||
buffer[dst] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Import::semantic(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic('%s')\n", toChars());
|
||||
|
||||
load(sc);
|
||||
|
||||
if (mod)
|
||||
{
|
||||
#if 0
|
||||
if (mod->loc.linnum != 0)
|
||||
{ /* If the line number is not 0, then this is not
|
||||
* a 'root' module, i.e. it was not specified on the command line.
|
||||
*/
|
||||
mod->importedFrom = sc->module->importedFrom;
|
||||
assert(mod->importedFrom);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Modules need a list of each imported module
|
||||
//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
|
||||
sc->module->aimports.push(mod);
|
||||
|
||||
mod->semantic();
|
||||
|
||||
if (!isstatic && !aliasId && !names.dim)
|
||||
{
|
||||
/* Default to private importing
|
||||
*/
|
||||
enum PROT prot = sc->protection;
|
||||
if (!sc->explicitProtection)
|
||||
prot = PROTprivate;
|
||||
sc->scopesym->importScope(mod, prot);
|
||||
}
|
||||
|
||||
if (mod->needmoduleinfo)
|
||||
sc->module->needmoduleinfo = 1;
|
||||
|
||||
sc = sc->push(mod);
|
||||
for (size_t i = 0; i < aliasdecls.dim; i++)
|
||||
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
|
||||
|
||||
//printf("\tImport alias semantic('%s')\n", s->toChars());
|
||||
if (!mod->search(loc, (Identifier *)names.data[i], 0))
|
||||
error("%s not found", ((Identifier *)names.data[i])->toChars());
|
||||
|
||||
ad->importprot = protection;
|
||||
ad->semantic(sc);
|
||||
}
|
||||
sc = sc->pop();
|
||||
}
|
||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
|
||||
|
||||
if (global.params.moduleDeps != NULL) {
|
||||
char fnameBuf[262]; // MAX_PATH+2
|
||||
|
||||
OutBuffer *const ob = global.params.moduleDeps;
|
||||
ob->printf("%s (%s) : ",
|
||||
sc->module->toPrettyChars(),
|
||||
escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
|
||||
);
|
||||
|
||||
char* protStr = "";
|
||||
switch (sc->protection) {
|
||||
case PROTpublic: protStr = "public"; break;
|
||||
case PROTprivate: protStr = "private"; break;
|
||||
case PROTpackage: protStr = "package"; break;
|
||||
default: break;
|
||||
}
|
||||
ob->writestring(protStr);
|
||||
if (isstatic) {
|
||||
ob->writestring(" static");
|
||||
}
|
||||
ob->writestring(" : ");
|
||||
|
||||
if (this->packages) {
|
||||
for (size_t i = 0; i < this->packages->dim; i++) {
|
||||
Identifier *pid = (Identifier *)this->packages->data[i];
|
||||
ob->printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
|
||||
ob->printf("%s (%s)",
|
||||
this->id->toChars(),
|
||||
mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???"
|
||||
);
|
||||
|
||||
if (aliasId) {
|
||||
ob->printf(" -> %s", aliasId->toChars());
|
||||
} else {
|
||||
if (names.dim > 0) {
|
||||
ob->writestring(" : ");
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
if (i > 0) {
|
||||
ob->writebyte(',');
|
||||
}
|
||||
|
||||
Identifier *name = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[i];
|
||||
|
||||
if (!alias) {
|
||||
ob->printf("%s", name->toChars());
|
||||
alias = name;
|
||||
} else {
|
||||
ob->printf("%s=%s", alias->toChars(), name->toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ob->writenl();
|
||||
}
|
||||
}
|
||||
|
||||
void Import::semantic2(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic2('%s')\n", toChars());
|
||||
mod->semantic2();
|
||||
if (mod->needmoduleinfo)
|
||||
sc->module->needmoduleinfo = 1;
|
||||
}
|
||||
|
||||
Dsymbol *Import::toAlias()
|
||||
{
|
||||
if (aliasId)
|
||||
return mod;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* Add import to sd's symbol table.
|
||||
*/
|
||||
|
||||
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (names.dim == 0)
|
||||
return Dsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
if (aliasId)
|
||||
result = Dsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
/* Instead of adding the import to sd's symbol table,
|
||||
* add each of the alias=name pairs
|
||||
*/
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
Identifier *name = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[i];
|
||||
|
||||
if (!alias)
|
||||
alias = name;
|
||||
|
||||
TypeIdentifier *tname = new TypeIdentifier(loc, name);
|
||||
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
|
||||
result |= ad->addMember(sc, sd, memnum);
|
||||
|
||||
aliasdecls.push(ad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
|
||||
|
||||
if (!pkg)
|
||||
{ load(NULL);
|
||||
mod->semantic();
|
||||
}
|
||||
|
||||
// Forward it to the package/module
|
||||
return pkg->search(loc, ident, flags);
|
||||
}
|
||||
|
||||
int Import::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
// Allow multiple imports of the same name
|
||||
return s->isImport() != NULL;
|
||||
}
|
||||
|
||||
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (hgs->hdrgen && id == Id::object)
|
||||
return; // object is imported by default
|
||||
|
||||
if (isstatic)
|
||||
buf->writestring("static ");
|
||||
buf->writestring("import ");
|
||||
if (aliasId)
|
||||
{
|
||||
buf->printf("%s = ", aliasId->toChars());
|
||||
}
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
|
||||
buf->printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
buf->printf("%s", id->toChars());
|
||||
if (names.dim > 0) {
|
||||
buf->writebyte(':');
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
if (i > 0) {
|
||||
buf->writebyte(',');
|
||||
}
|
||||
|
||||
Identifier *name = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[i];
|
||||
|
||||
if (!alias) {
|
||||
buf->printf("%s", name->toChars());
|
||||
alias = name;
|
||||
} else {
|
||||
buf->printf("%s=%s", alias->toChars(), name->toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
buf->writebyte(';');
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
|
||||
616
dmd2/inifile.c
616
dmd2/inifile.c
@@ -1,300 +1,316 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "mem.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#define LOG 0
|
||||
|
||||
char *skipspace(const char *p);
|
||||
|
||||
#if __GNUC__
|
||||
char *strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
#endif /* unix */
|
||||
|
||||
/*****************************
|
||||
* Read and analyze .ini file.
|
||||
* Input:
|
||||
* argv0 program name (argv[0])
|
||||
* inifile .ini file name
|
||||
*/
|
||||
|
||||
void inifile(char *argv0x, const char *inifilex)
|
||||
{
|
||||
char *argv0 = (char *)argv0x;
|
||||
char *inifile = (char *)inifilex; // do const-correct later
|
||||
char *path; // need path for @P macro
|
||||
char *filename;
|
||||
OutBuffer buf;
|
||||
int i;
|
||||
int k;
|
||||
int envsection = 0;
|
||||
|
||||
#if LOG
|
||||
printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
|
||||
#endif
|
||||
if (FileName::absolute(inifile))
|
||||
{
|
||||
filename = inifile;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for inifile in the following sequence of places:
|
||||
* o current directory
|
||||
* o home directory
|
||||
* o directory off of argv0
|
||||
* o /etc/
|
||||
*/
|
||||
if (FileName::exists(inifile))
|
||||
{
|
||||
filename = inifile;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = FileName::combine(getenv("HOME"), inifile);
|
||||
if (!FileName::exists(filename))
|
||||
{
|
||||
filename = FileName::replaceName(argv0, inifile);
|
||||
if (!FileName::exists(filename))
|
||||
{
|
||||
#if POSIX
|
||||
|
||||
#if 0
|
||||
#if __GLIBC__ // This fix by Thomas Kuehne
|
||||
/* argv0 might be a symbolic link,
|
||||
* so try again looking past it to the real path
|
||||
*/
|
||||
char* real_argv0 = realpath(argv0, NULL);
|
||||
if (real_argv0)
|
||||
{
|
||||
filename = FileName::replaceName(real_argv0, inifile);
|
||||
free(real_argv0);
|
||||
if (FileName::exists(filename))
|
||||
goto Ldone;
|
||||
}
|
||||
#else
|
||||
#error use of glibc non-standard extension realpath(char*, NULL)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// old way; problem is that argv0 might not be on the PATH at all
|
||||
// and some other instance might be found
|
||||
|
||||
// Search PATH for argv0
|
||||
const char *p = getenv("PATH");
|
||||
Array *paths = FileName::splitPath(p);
|
||||
filename = FileName::searchPath(paths, argv0, 0);
|
||||
if (!filename)
|
||||
goto Letc; // argv0 not found on path
|
||||
filename = FileName::replaceName(filename, inifile);
|
||||
if (FileName::exists(filename))
|
||||
goto Ldone;
|
||||
#endif
|
||||
|
||||
// Search /etc/ for inifile
|
||||
Letc:
|
||||
filename = FileName::combine((char *)"/etc/", inifile);
|
||||
|
||||
Ldone:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
path = FileName::path(filename);
|
||||
#if LOG
|
||||
printf("\tpath = '%s', filename = '%s'\n", path, filename);
|
||||
#endif
|
||||
|
||||
File file(filename);
|
||||
|
||||
if (file.read())
|
||||
return; // error reading file
|
||||
|
||||
// Parse into lines
|
||||
int eof = 0;
|
||||
for (i = 0; i < file.len && !eof; i++)
|
||||
{
|
||||
int linestart = i;
|
||||
|
||||
for (; i < file.len; i++)
|
||||
{
|
||||
switch (file.buffer[i])
|
||||
{
|
||||
case '\r':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
// Skip if it was preceded by '\r'
|
||||
if (i && file.buffer[i - 1] == '\r')
|
||||
goto Lskip;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 0x1A:
|
||||
eof = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The line is file.buffer[linestart..i]
|
||||
char *line;
|
||||
int len;
|
||||
char *p;
|
||||
char *pn;
|
||||
|
||||
line = (char *)&file.buffer[linestart];
|
||||
len = i - linestart;
|
||||
|
||||
buf.reset();
|
||||
|
||||
// First, expand the macros.
|
||||
// Macros are bracketed by % characters.
|
||||
|
||||
for (k = 0; k < len; k++)
|
||||
{
|
||||
if (line[k] == '%')
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = k + 1; j < len; j++)
|
||||
{
|
||||
if (line[j] == '%')
|
||||
{
|
||||
if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
|
||||
{
|
||||
// %@P% is special meaning the path to the .ini file
|
||||
p = path;
|
||||
if (!*p)
|
||||
p = (char *)".";
|
||||
}
|
||||
else
|
||||
{ int len = j - k;
|
||||
char tmp[10]; // big enough most of the time
|
||||
|
||||
if (len <= sizeof(tmp))
|
||||
p = tmp;
|
||||
else
|
||||
p = (char *)alloca(len);
|
||||
len--;
|
||||
memcpy(p, &line[k + 1], len);
|
||||
p[len] = 0;
|
||||
strupr(p);
|
||||
p = getenv(p);
|
||||
if (!p)
|
||||
p = (char *)"";
|
||||
}
|
||||
buf.writestring(p);
|
||||
k = j;
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.writeByte(line[k]);
|
||||
L1:
|
||||
;
|
||||
}
|
||||
|
||||
// Remove trailing spaces
|
||||
while (buf.offset && isspace(buf.data[buf.offset - 1]))
|
||||
buf.offset--;
|
||||
|
||||
p = buf.toChars();
|
||||
|
||||
// The expanded line is in p.
|
||||
// Now parse it for meaning.
|
||||
|
||||
p = skipspace(p);
|
||||
switch (*p)
|
||||
{
|
||||
case ';': // comment
|
||||
case 0: // blank
|
||||
break;
|
||||
|
||||
case '[': // look for [Environment]
|
||||
p = skipspace(p + 1);
|
||||
for (pn = p; isalnum(*pn); pn++)
|
||||
;
|
||||
if (pn - p == 11 &&
|
||||
memicmp(p, "Environment", 11) == 0 &&
|
||||
*skipspace(pn) == ']'
|
||||
)
|
||||
envsection = 1;
|
||||
else
|
||||
envsection = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (envsection)
|
||||
{
|
||||
pn = p;
|
||||
|
||||
// Convert name to upper case;
|
||||
// remove spaces bracketing =
|
||||
for (p = pn; *p; p++)
|
||||
{ if (islower(*p))
|
||||
*p &= ~0x20;
|
||||
else if (isspace(*p))
|
||||
memmove(p, p + 1, strlen(p));
|
||||
else if (*p == '=')
|
||||
{
|
||||
p++;
|
||||
while (isspace(*p))
|
||||
memmove(p, p + 1, strlen(p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
putenv(strdup(pn));
|
||||
#if LOG
|
||||
printf("\tputenv('%s')\n", pn);
|
||||
//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Lskip:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
* Skip spaces.
|
||||
*/
|
||||
|
||||
char *skipspace(const char *p)
|
||||
{
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
return (char *)p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some portions copyright (c) 1994-1995 by Symantec
|
||||
* Copyright (c) 1999-2009 by Digital Mars
|
||||
* All Rights Reserved
|
||||
* http://www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This source file is made available for personal use
|
||||
* only. The license is in /dmd/src/dmd/backendlicense.txt
|
||||
* For any other uses, please contact Digital Mars.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if __APPLE__
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
#if __FreeBSD__ || __sun&&__SVR4
|
||||
// for PATH_MAX
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#if __sun&&__SVR4
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#define LOG 0
|
||||
|
||||
char *skipspace(const char *p);
|
||||
|
||||
#if __GNUC__
|
||||
char *strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
#endif /* unix */
|
||||
|
||||
/*****************************
|
||||
* Read and analyze .ini file.
|
||||
* Input:
|
||||
* argv0 program name (argv[0])
|
||||
* inifile .ini file name
|
||||
*/
|
||||
|
||||
void inifile(const char *argv0x, const char *inifilex)
|
||||
{
|
||||
char *argv0 = (char *)argv0x;
|
||||
char *inifile = (char *)inifilex; // do const-correct later
|
||||
char *path; // need path for @P macro
|
||||
char *filename;
|
||||
OutBuffer buf;
|
||||
int i;
|
||||
int k;
|
||||
int envsection = 0;
|
||||
|
||||
#if LOG
|
||||
printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
|
||||
#endif
|
||||
if (FileName::absolute(inifile))
|
||||
{
|
||||
filename = inifile;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for inifile in the following sequence of places:
|
||||
* o current directory
|
||||
* o home directory
|
||||
* o directory off of argv0
|
||||
* o /etc/
|
||||
*/
|
||||
if (FileName::exists(inifile))
|
||||
{
|
||||
filename = inifile;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = FileName::combine(getenv("HOME"), inifile);
|
||||
if (!FileName::exists(filename))
|
||||
{
|
||||
filename = (char *)FileName::replaceName(argv0, inifile);
|
||||
if (!FileName::exists(filename))
|
||||
{
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
|
||||
#if __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 // This fix by Thomas Kuehne
|
||||
/* argv0 might be a symbolic link,
|
||||
* so try again looking past it to the real path
|
||||
*/
|
||||
#if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
|
||||
char resolved_name[PATH_MAX + 1];
|
||||
char* real_argv0 = realpath(argv0, resolved_name);
|
||||
#else
|
||||
char* real_argv0 = realpath(argv0, NULL);
|
||||
#endif
|
||||
//printf("argv0 = %s, real_argv0 = %p\n", argv0, real_argv0);
|
||||
if (real_argv0)
|
||||
{
|
||||
filename = (char *)FileName::replaceName(real_argv0, inifile);
|
||||
#if !(__APPLE__ || __FreeBSD__ || __sun&&__SVR4)
|
||||
free(real_argv0);
|
||||
#endif
|
||||
if (FileName::exists(filename))
|
||||
goto Ldone;
|
||||
}
|
||||
#else
|
||||
#error use of glibc non-standard extension realpath(char*, NULL)
|
||||
#endif
|
||||
if (1){
|
||||
// Search PATH for argv0
|
||||
const char *p = getenv("PATH");
|
||||
Array *paths = FileName::splitPath(p);
|
||||
filename = FileName::searchPath(paths, argv0, 0);
|
||||
if (!filename)
|
||||
goto Letc; // argv0 not found on path
|
||||
filename = (char *)FileName::replaceName(filename, inifile);
|
||||
if (FileName::exists(filename))
|
||||
goto Ldone;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Search /etc/ for inifile
|
||||
Letc:
|
||||
filename = FileName::combine((char *)"/etc/", inifile);
|
||||
|
||||
Ldone:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
path = FileName::path(filename);
|
||||
#if LOG
|
||||
printf("\tpath = '%s', filename = '%s'\n", path, filename);
|
||||
#endif
|
||||
|
||||
File file(filename);
|
||||
|
||||
if (file.read())
|
||||
return; // error reading file
|
||||
|
||||
// Parse into lines
|
||||
int eof = 0;
|
||||
for (i = 0; i < file.len && !eof; i++)
|
||||
{
|
||||
int linestart = i;
|
||||
|
||||
for (; i < file.len; i++)
|
||||
{
|
||||
switch (file.buffer[i])
|
||||
{
|
||||
case '\r':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
// Skip if it was preceded by '\r'
|
||||
if (i && file.buffer[i - 1] == '\r')
|
||||
goto Lskip;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 0x1A:
|
||||
eof = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The line is file.buffer[linestart..i]
|
||||
char *line;
|
||||
int len;
|
||||
char *p;
|
||||
char *pn;
|
||||
|
||||
line = (char *)&file.buffer[linestart];
|
||||
len = i - linestart;
|
||||
|
||||
buf.reset();
|
||||
|
||||
// First, expand the macros.
|
||||
// Macros are bracketed by % characters.
|
||||
|
||||
for (k = 0; k < len; k++)
|
||||
{
|
||||
if (line[k] == '%')
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = k + 1; j < len; j++)
|
||||
{
|
||||
if (line[j] == '%')
|
||||
{
|
||||
if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
|
||||
{
|
||||
// %@P% is special meaning the path to the .ini file
|
||||
p = path;
|
||||
if (!*p)
|
||||
p = (char *)".";
|
||||
}
|
||||
else
|
||||
{ int len = j - k;
|
||||
char tmp[10]; // big enough most of the time
|
||||
|
||||
if (len <= sizeof(tmp))
|
||||
p = tmp;
|
||||
else
|
||||
p = (char *)alloca(len);
|
||||
len--;
|
||||
memcpy(p, &line[k + 1], len);
|
||||
p[len] = 0;
|
||||
strupr(p);
|
||||
p = getenv(p);
|
||||
if (!p)
|
||||
p = (char *)"";
|
||||
}
|
||||
buf.writestring(p);
|
||||
k = j;
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.writeByte(line[k]);
|
||||
L1:
|
||||
;
|
||||
}
|
||||
|
||||
// Remove trailing spaces
|
||||
while (buf.offset && isspace(buf.data[buf.offset - 1]))
|
||||
buf.offset--;
|
||||
|
||||
p = buf.toChars();
|
||||
|
||||
// The expanded line is in p.
|
||||
// Now parse it for meaning.
|
||||
|
||||
p = skipspace(p);
|
||||
switch (*p)
|
||||
{
|
||||
case ';': // comment
|
||||
case 0: // blank
|
||||
break;
|
||||
|
||||
case '[': // look for [Environment]
|
||||
p = skipspace(p + 1);
|
||||
for (pn = p; isalnum(*pn); pn++)
|
||||
;
|
||||
if (pn - p == 11 &&
|
||||
memicmp(p, "Environment", 11) == 0 &&
|
||||
*skipspace(pn) == ']'
|
||||
)
|
||||
envsection = 1;
|
||||
else
|
||||
envsection = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (envsection)
|
||||
{
|
||||
pn = p;
|
||||
|
||||
// Convert name to upper case;
|
||||
// remove spaces bracketing =
|
||||
for (p = pn; *p; p++)
|
||||
{ if (islower(*p))
|
||||
*p &= ~0x20;
|
||||
else if (isspace(*p))
|
||||
memmove(p, p + 1, strlen(p));
|
||||
else if (*p == '=')
|
||||
{
|
||||
p++;
|
||||
while (isspace(*p))
|
||||
memmove(p, p + 1, strlen(p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
putenv(strdup(pn));
|
||||
#if LOG
|
||||
printf("\tputenv('%s')\n", pn);
|
||||
//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Lskip:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
* Skip spaces.
|
||||
*/
|
||||
|
||||
char *skipspace(const char *p)
|
||||
{
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
return (char *)p;
|
||||
}
|
||||
|
||||
|
||||
1197
dmd2/init.c
1197
dmd2/init.c
File diff suppressed because it is too large
Load Diff
13
dmd2/init.h
13
dmd2/init.h
@@ -26,7 +26,6 @@ struct VoidInitializer;
|
||||
struct StructInitializer;
|
||||
struct ArrayInitializer;
|
||||
struct ExpInitializer;
|
||||
struct StructInitializer;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
@@ -45,7 +44,9 @@ struct Initializer : Object
|
||||
|
||||
static Initializers *arraySyntaxCopy(Initializers *ai);
|
||||
|
||||
#if IN_DMD
|
||||
virtual dt_t *toDt();
|
||||
#endif
|
||||
|
||||
virtual VoidInitializer *isVoidInitializer() { return NULL; }
|
||||
virtual StructInitializer *isStructInitializer() { return NULL; }
|
||||
@@ -63,7 +64,9 @@ struct VoidInitializer : Initializer
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
dt_t *toDt();
|
||||
#endif
|
||||
|
||||
virtual VoidInitializer *isVoidInitializer() { return this; }
|
||||
};
|
||||
@@ -83,9 +86,11 @@ struct StructInitializer : Initializer
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
dt_t *toDt();
|
||||
#endif
|
||||
|
||||
StructInitializer *isStructInitializer() { return this; }
|
||||
StructInitializer *isStructInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct ArrayInitializer : Initializer
|
||||
@@ -105,8 +110,10 @@ struct ArrayInitializer : Initializer
|
||||
Initializer *toAssocArrayInitializer();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
dt_t *toDt();
|
||||
dt_t *toDtBit(); // for bit arrays
|
||||
#endif
|
||||
|
||||
ArrayInitializer *isArrayInitializer() { return this; }
|
||||
};
|
||||
@@ -122,7 +129,9 @@ struct ExpInitializer : Initializer
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
dt_t *toDt();
|
||||
#endif
|
||||
|
||||
virtual ExpInitializer *isExpInitializer() { return this; }
|
||||
};
|
||||
|
||||
2944
dmd2/inline.c
2944
dmd2/inline.c
File diff suppressed because it is too large
Load Diff
120
dmd2/interpret.c
120
dmd2/interpret.c
@@ -12,7 +12,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mem.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#include "statement.h"
|
||||
#include "expression.h"
|
||||
@@ -69,7 +69,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
else if (ident == Id::aaValues)
|
||||
return interpret_aaValues(istate, arguments);
|
||||
|
||||
if (cantInterpret || semanticRun == 1)
|
||||
if (cantInterpret || semanticRun == 3)
|
||||
return NULL;
|
||||
|
||||
if (needThis() || isNested() || !fbody)
|
||||
@@ -77,13 +77,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (semanticRun == 0 && scope)
|
||||
if (semanticRun < 3 && scope)
|
||||
{
|
||||
semantic3(scope);
|
||||
if (global.errors) // if errors compiling this function
|
||||
return NULL;
|
||||
if (global.errors) // if errors compiling this function
|
||||
return NULL;
|
||||
}
|
||||
if (semanticRun < 2)
|
||||
if (semanticRun < 4)
|
||||
return NULL;
|
||||
|
||||
Type *tb = type->toBasetype();
|
||||
@@ -987,7 +987,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
|
||||
{
|
||||
Expression *e = EXP_CANT_INTERPRET;
|
||||
VarDeclaration *v = d->isVarDeclaration();
|
||||
#if IN_LLVM
|
||||
StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration();
|
||||
#else
|
||||
SymbolDeclaration *s = d->isSymbolDeclaration();
|
||||
#endif
|
||||
if (v)
|
||||
{
|
||||
#if DMDV2
|
||||
@@ -1512,6 +1516,80 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Assignment to struct member of the form:
|
||||
* v.var = e2
|
||||
*/
|
||||
else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1;
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
|
||||
if (v->isDataseg())
|
||||
return EXP_CANT_INTERPRET;
|
||||
if (fp && !v->value)
|
||||
{ error("variable %s is used before initialization", v->toChars());
|
||||
return e;
|
||||
}
|
||||
if (v->value == NULL && v->init->isVoidInitializer())
|
||||
{ /* Since a void initializer initializes to undefined
|
||||
* values, it is valid here to use the default initializer.
|
||||
* No attempt is made to determine if someone actually relies
|
||||
* on the void value - to do that we'd need a VoidExp.
|
||||
* That's probably a good enhancement idea.
|
||||
*/
|
||||
v->value = v->type->defaultInit();
|
||||
}
|
||||
Expression *vie = v->value;
|
||||
if (vie->op == TOKvar)
|
||||
{
|
||||
Declaration *d = ((VarExp *)vie)->var;
|
||||
vie = getVarExp(e1->loc, istate, d);
|
||||
}
|
||||
if (vie->op != TOKstructliteral)
|
||||
return EXP_CANT_INTERPRET;
|
||||
StructLiteralExp *se = (StructLiteralExp *)vie;
|
||||
VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
|
||||
if (!vf)
|
||||
return EXP_CANT_INTERPRET;
|
||||
int fieldi = se->getFieldIndex(type, vf->offset);
|
||||
if (fieldi == -1)
|
||||
return EXP_CANT_INTERPRET;
|
||||
Expression *ev = se->getField(type, vf->offset);
|
||||
if (fp)
|
||||
e2 = (*fp)(type, ev, e2);
|
||||
else
|
||||
e2 = Cast(type, type, e2);
|
||||
if (e2 == EXP_CANT_INTERPRET)
|
||||
return e2;
|
||||
|
||||
if (!v->isParameter())
|
||||
{
|
||||
for (size_t i = 0; 1; i++)
|
||||
{
|
||||
if (i == istate->vars.dim)
|
||||
{ istate->vars.push(v);
|
||||
break;
|
||||
}
|
||||
if (v == (VarDeclaration *)istate->vars.data[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create new struct literal reflecting updated fieldi
|
||||
*/
|
||||
Expressions *expsx = new Expressions();
|
||||
expsx->setDim(se->elements->dim);
|
||||
for (size_t j = 0; j < expsx->dim; j++)
|
||||
{
|
||||
if (j == fieldi)
|
||||
expsx->data[j] = (void *)e2;
|
||||
else
|
||||
expsx->data[j] = se->elements->data[j];
|
||||
}
|
||||
v->value = new StructLiteralExp(se->loc, se->sd, expsx);
|
||||
v->value->type = se->type;
|
||||
|
||||
e = Cast(type, type, post ? ev : e2);
|
||||
}
|
||||
/* Assignment to struct member of the form:
|
||||
* *(symoffexp) = e2
|
||||
*/
|
||||
@@ -2159,21 +2237,29 @@ Expression *PtrExp::interpret(InterState *istate)
|
||||
Expression *DotVarExp::interpret(InterState *istate)
|
||||
{ Expression *e = EXP_CANT_INTERPRET;
|
||||
|
||||
#if LOG
|
||||
printf("DotVarExp::interpret() %s\n", toChars());
|
||||
#endif
|
||||
|
||||
Expression *ex = e1->interpret(istate);
|
||||
|
||||
// Constant fold structliteral.member
|
||||
if (ex != EXP_CANT_INTERPRET && ex->op == TOKstructliteral)
|
||||
{ StructLiteralExp *se = (StructLiteralExp *)ex;
|
||||
|
||||
VarDeclaration* v;
|
||||
if (v = var->isVarDeclaration())
|
||||
{
|
||||
e = se->getField(type, v->offset);
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
if (ex != EXP_CANT_INTERPRET)
|
||||
{
|
||||
if (ex->op == TOKstructliteral)
|
||||
{ StructLiteralExp *se = (StructLiteralExp *)ex;
|
||||
VarDeclaration *v = var->isVarDeclaration();
|
||||
if (v)
|
||||
{ e = se->getField(type, v->offset);
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LOG
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
|
||||
#endif
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
164
dmd2/irstate.c
Normal file
164
dmd2/irstate.c
Normal file
@@ -0,0 +1,164 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "irstate.h"
|
||||
|
||||
IRState::IRState(IRState *irs, Statement *s)
|
||||
{
|
||||
prev = irs;
|
||||
statement = s;
|
||||
symbol = NULL;
|
||||
breakBlock = NULL;
|
||||
contBlock = NULL;
|
||||
switchBlock = NULL;
|
||||
defaultBlock = NULL;
|
||||
ident = NULL;
|
||||
ehidden = NULL;
|
||||
startaddress = NULL;
|
||||
if (irs)
|
||||
{
|
||||
m = irs->m;
|
||||
shidden = irs->shidden;
|
||||
sclosure = irs->sclosure;
|
||||
sthis = irs->sthis;
|
||||
blx = irs->blx;
|
||||
deferToObj = irs->deferToObj;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = NULL;
|
||||
shidden = NULL;
|
||||
sclosure = NULL;
|
||||
sthis = NULL;
|
||||
blx = NULL;
|
||||
deferToObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IRState::IRState(IRState *irs, Dsymbol *s)
|
||||
{
|
||||
prev = irs;
|
||||
statement = NULL;
|
||||
symbol = s;
|
||||
breakBlock = NULL;
|
||||
contBlock = NULL;
|
||||
switchBlock = NULL;
|
||||
defaultBlock = NULL;
|
||||
ident = NULL;
|
||||
ehidden = NULL;
|
||||
startaddress = NULL;
|
||||
if (irs)
|
||||
{
|
||||
m = irs->m;
|
||||
shidden = irs->shidden;
|
||||
sclosure = irs->sclosure;
|
||||
sthis = irs->sthis;
|
||||
blx = irs->blx;
|
||||
deferToObj = irs->deferToObj;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = NULL;
|
||||
shidden = NULL;
|
||||
sclosure = NULL;
|
||||
sthis = NULL;
|
||||
blx = NULL;
|
||||
deferToObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IRState::IRState(Module *m, Dsymbol *s)
|
||||
{
|
||||
prev = NULL;
|
||||
statement = NULL;
|
||||
this->m = m;
|
||||
symbol = s;
|
||||
breakBlock = NULL;
|
||||
contBlock = NULL;
|
||||
switchBlock = NULL;
|
||||
defaultBlock = NULL;
|
||||
ident = NULL;
|
||||
ehidden = NULL;
|
||||
shidden = NULL;
|
||||
sclosure = NULL;
|
||||
sthis = NULL;
|
||||
blx = NULL;
|
||||
deferToObj = NULL;
|
||||
startaddress = NULL;
|
||||
}
|
||||
|
||||
block *IRState::getBreakBlock(Identifier *ident)
|
||||
{
|
||||
IRState *bc;
|
||||
|
||||
for (bc = this; bc; bc = bc->prev)
|
||||
{
|
||||
if (ident)
|
||||
{
|
||||
if (bc->prev && bc->prev->ident == ident)
|
||||
return bc->breakBlock;
|
||||
}
|
||||
else if (bc->breakBlock)
|
||||
return bc->breakBlock;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block *IRState::getContBlock(Identifier *ident)
|
||||
{
|
||||
IRState *bc;
|
||||
|
||||
for (bc = this; bc; bc = bc->prev)
|
||||
{
|
||||
if (ident)
|
||||
{
|
||||
if (bc->prev && bc->prev->ident == ident)
|
||||
return bc->contBlock;
|
||||
}
|
||||
else if (bc->contBlock)
|
||||
return bc->contBlock;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block *IRState::getSwitchBlock()
|
||||
{
|
||||
IRState *bc;
|
||||
|
||||
for (bc = this; bc; bc = bc->prev)
|
||||
{
|
||||
if (bc->switchBlock)
|
||||
return bc->switchBlock;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block *IRState::getDefaultBlock()
|
||||
{
|
||||
IRState *bc;
|
||||
|
||||
for (bc = this; bc; bc = bc->prev)
|
||||
{
|
||||
if (bc->defaultBlock)
|
||||
return bc->defaultBlock;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FuncDeclaration *IRState::getFunc()
|
||||
{
|
||||
IRState *bc;
|
||||
|
||||
for (bc = this; bc->prev; bc = bc->prev)
|
||||
{
|
||||
}
|
||||
return (FuncDeclaration *)(bc->symbol);
|
||||
}
|
||||
|
||||
|
||||
57
dmd2/irstate.h
Normal file
57
dmd2/irstate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
#ifndef DMD_CONTEXT_H
|
||||
#define DMD_CONTEXT_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct block;
|
||||
struct Dsymbol;
|
||||
struct Identifier;
|
||||
struct Symbol;
|
||||
struct FuncDeclaration;
|
||||
struct Blockx;
|
||||
struct Array;
|
||||
struct elem;
|
||||
|
||||
struct IRState
|
||||
{
|
||||
IRState *prev;
|
||||
Statement *statement;
|
||||
Module *m; // module
|
||||
Dsymbol *symbol;
|
||||
Identifier *ident;
|
||||
Symbol *shidden; // hidden parameter to function
|
||||
Symbol *sthis; // 'this' parameter to function (member and nested)
|
||||
Symbol *sclosure; // pointer to closure instance
|
||||
Blockx *blx;
|
||||
Array *deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later
|
||||
elem *ehidden; // transmit hidden pointer to CallExp::toElem()
|
||||
Symbol *startaddress;
|
||||
|
||||
block *breakBlock;
|
||||
block *contBlock;
|
||||
block *switchBlock;
|
||||
block *defaultBlock;
|
||||
|
||||
IRState(IRState *irs, Statement *s);
|
||||
IRState(IRState *irs, Dsymbol *s);
|
||||
IRState(Module *m, Dsymbol *s);
|
||||
|
||||
block *getBreakBlock(Identifier *ident);
|
||||
block *getContBlock(Identifier *ident);
|
||||
block *getSwitchBlock();
|
||||
block *getDefaultBlock();
|
||||
FuncDeclaration *getFunc();
|
||||
};
|
||||
|
||||
#endif /* DMD_CONTEXT_H */
|
||||
6217
dmd2/lexer.c
6217
dmd2/lexer.c
File diff suppressed because it is too large
Load Diff
616
dmd2/lexer.h
616
dmd2/lexer.h
@@ -1,307 +1,309 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_LEXER_H
|
||||
#define DMD_LEXER_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
|
||||
struct StringTable;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
|
||||
/* Tokens:
|
||||
( )
|
||||
[ ]
|
||||
{ }
|
||||
< > <= >= == != === !==
|
||||
<< >> <<= >>= >>> >>>=
|
||||
+ - += -=
|
||||
* / % *= /= %=
|
||||
& | ^ &= |= ^=
|
||||
= ! ~
|
||||
++ --
|
||||
. -> : ,
|
||||
? && ||
|
||||
*/
|
||||
|
||||
enum TOK
|
||||
{
|
||||
TOKreserved,
|
||||
|
||||
// Other
|
||||
TOKlparen, TOKrparen,
|
||||
TOKlbracket, TOKrbracket,
|
||||
TOKlcurly, TOKrcurly,
|
||||
TOKcolon, TOKneg,
|
||||
TOKsemicolon, TOKdotdotdot,
|
||||
TOKeof, TOKcast,
|
||||
TOKnull, TOKassert,
|
||||
TOKtrue, TOKfalse,
|
||||
TOKarray, TOKcall,
|
||||
TOKaddress, TOKtypedot,
|
||||
TOKtype, TOKthrow,
|
||||
TOKnew, TOKdelete,
|
||||
TOKstar, TOKsymoff,
|
||||
TOKvar, TOKdotvar,
|
||||
TOKdotti, TOKdotexp,
|
||||
TOKdottype, TOKslice,
|
||||
TOKarraylength, TOKversion,
|
||||
TOKmodule, TOKdollar,
|
||||
TOKtemplate, TOKdottd,
|
||||
TOKdeclaration, TOKtypeof,
|
||||
TOKpragma, TOKdsymbol,
|
||||
TOKtypeid, TOKuadd,
|
||||
TOKremove,
|
||||
TOKnewanonclass, TOKcomment,
|
||||
TOKarrayliteral, TOKassocarrayliteral,
|
||||
TOKstructliteral,
|
||||
|
||||
// Operators
|
||||
TOKlt, TOKgt,
|
||||
TOKle, TOKge,
|
||||
TOKequal, TOKnotequal,
|
||||
TOKidentity, TOKnotidentity,
|
||||
TOKindex, TOKis,
|
||||
TOKtobool,
|
||||
|
||||
// 60
|
||||
// NCEG floating point compares
|
||||
// !<>= <> <>= !> !>= !< !<= !<>
|
||||
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
|
||||
|
||||
TOKshl, TOKshr,
|
||||
TOKshlass, TOKshrass,
|
||||
TOKushr, TOKushrass,
|
||||
TOKcat, TOKcatass, // ~ ~=
|
||||
TOKadd, TOKmin, TOKaddass, TOKminass,
|
||||
TOKmul, TOKdiv, TOKmod,
|
||||
TOKmulass, TOKdivass, TOKmodass,
|
||||
TOKand, TOKor, TOKxor,
|
||||
TOKandass, TOKorass, TOKxorass,
|
||||
TOKassign, TOKnot, TOKtilde,
|
||||
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
|
||||
TOKdot, TOKarrow, TOKcomma,
|
||||
TOKquestion, TOKandand, TOKoror,
|
||||
|
||||
// 104
|
||||
// Numeric literals
|
||||
TOKint32v, TOKuns32v,
|
||||
TOKint64v, TOKuns64v,
|
||||
TOKfloat32v, TOKfloat64v, TOKfloat80v,
|
||||
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
|
||||
|
||||
// Char constants
|
||||
TOKcharv, TOKwcharv, TOKdcharv,
|
||||
|
||||
// Leaf operators
|
||||
TOKidentifier, TOKstring,
|
||||
TOKthis, TOKsuper,
|
||||
TOKhalt, TOKtuple,
|
||||
|
||||
// Basic types
|
||||
TOKvoid,
|
||||
TOKint8, TOKuns8,
|
||||
TOKint16, TOKuns16,
|
||||
TOKint32, TOKuns32,
|
||||
TOKint64, TOKuns64,
|
||||
TOKfloat32, TOKfloat64, TOKfloat80,
|
||||
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
||||
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
||||
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
|
||||
TOKcent, TOKucent,
|
||||
|
||||
// Aggregates
|
||||
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
|
||||
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
|
||||
TOKmixin,
|
||||
|
||||
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
|
||||
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
|
||||
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
|
||||
TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
|
||||
|
||||
// Statements
|
||||
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
|
||||
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
|
||||
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
|
||||
TOKasm, TOKforeach, TOKforeach_reverse,
|
||||
TOKscope,
|
||||
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
|
||||
|
||||
// Contracts
|
||||
TOKbody, TOKinvariant,
|
||||
|
||||
// Testing
|
||||
TOKunittest,
|
||||
|
||||
// Added after 1.0
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
TOKtraits,
|
||||
TOKoverloadset,
|
||||
TOKpure,
|
||||
TOKnothrow,
|
||||
TOKtls,
|
||||
TOKline,
|
||||
TOKfile,
|
||||
TOKshared,
|
||||
#endif
|
||||
|
||||
// LDC specific
|
||||
#if IN_LLVM
|
||||
TOKgep,
|
||||
#endif
|
||||
|
||||
TOKMAX
|
||||
};
|
||||
|
||||
#define CASE_BASIC_TYPES \
|
||||
case TOKwchar: case TOKdchar: \
|
||||
case TOKbit: case TOKbool: case TOKchar: \
|
||||
case TOKint8: case TOKuns8: \
|
||||
case TOKint16: case TOKuns16: \
|
||||
case TOKint32: case TOKuns32: \
|
||||
case TOKint64: case TOKuns64: \
|
||||
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
|
||||
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
|
||||
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
|
||||
case TOKvoid
|
||||
|
||||
#define CASE_BASIC_TYPES_X(t) \
|
||||
case TOKvoid: t = Type::tvoid; goto LabelX; \
|
||||
case TOKint8: t = Type::tint8; goto LabelX; \
|
||||
case TOKuns8: t = Type::tuns8; goto LabelX; \
|
||||
case TOKint16: t = Type::tint16; goto LabelX; \
|
||||
case TOKuns16: t = Type::tuns16; goto LabelX; \
|
||||
case TOKint32: t = Type::tint32; goto LabelX; \
|
||||
case TOKuns32: t = Type::tuns32; goto LabelX; \
|
||||
case TOKint64: t = Type::tint64; goto LabelX; \
|
||||
case TOKuns64: t = Type::tuns64; goto LabelX; \
|
||||
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
|
||||
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
|
||||
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
|
||||
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
|
||||
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
|
||||
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
|
||||
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
|
||||
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
|
||||
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
|
||||
case TOKbit: t = Type::tbit; goto LabelX; \
|
||||
case TOKbool: t = Type::tbool; goto LabelX; \
|
||||
case TOKchar: t = Type::tchar; goto LabelX; \
|
||||
case TOKwchar: t = Type::twchar; goto LabelX; \
|
||||
case TOKdchar: t = Type::tdchar; goto LabelX; \
|
||||
LabelX
|
||||
|
||||
struct Token
|
||||
{
|
||||
Token *next;
|
||||
unsigned char *ptr; // pointer to first character of this token within buffer
|
||||
enum TOK value;
|
||||
unsigned char *blockComment; // doc comment string prior to this token
|
||||
unsigned char *lineComment; // doc comment for previous token
|
||||
union
|
||||
{
|
||||
// Integers
|
||||
d_int32 int32value;
|
||||
d_uns32 uns32value;
|
||||
d_int64 int64value;
|
||||
d_uns64 uns64value;
|
||||
|
||||
// Floats
|
||||
#ifdef IN_GCC
|
||||
// real_t float80value; // can't use this in a union!
|
||||
#else
|
||||
d_float80 float80value;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{ unsigned char *ustring; // UTF8 string
|
||||
unsigned len;
|
||||
unsigned char postfix; // 'c', 'w', 'd'
|
||||
};
|
||||
|
||||
Identifier *ident;
|
||||
};
|
||||
#ifdef IN_GCC
|
||||
real_t float80value; // can't use this in a union!
|
||||
#endif
|
||||
|
||||
static const char *tochars[TOKMAX];
|
||||
static void *operator new(size_t sz);
|
||||
|
||||
int isKeyword();
|
||||
void print();
|
||||
const char *toChars();
|
||||
static const char *toChars(enum TOK);
|
||||
};
|
||||
|
||||
struct Lexer
|
||||
{
|
||||
static StringTable stringtable;
|
||||
static OutBuffer stringbuffer;
|
||||
static Token *freelist;
|
||||
|
||||
Loc loc; // for error messages
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
Token token;
|
||||
Module *mod;
|
||||
int doDocComment; // collect doc comment information
|
||||
int anyToken; // !=0 means seen at least one token
|
||||
int commentToken; // !=0 means comments are TOKcomment's
|
||||
|
||||
Lexer(Module *mod,
|
||||
unsigned char *base, unsigned begoffset, unsigned endoffset,
|
||||
int doDocComment, int commentToken);
|
||||
|
||||
static void initKeywords();
|
||||
static Identifier *idPool(const char *s);
|
||||
static Identifier *uniqueId(const char *s);
|
||||
static Identifier *uniqueId(const char *s, int num);
|
||||
|
||||
TOK nextToken();
|
||||
TOK peekNext();
|
||||
void scan(Token *t);
|
||||
Token *peek(Token *t);
|
||||
Token *peekPastParen(Token *t);
|
||||
unsigned escapeSequence();
|
||||
TOK wysiwygStringConstant(Token *t, int tc);
|
||||
TOK hexStringConstant(Token *t);
|
||||
#if DMDV2
|
||||
TOK delimitedStringConstant(Token *t);
|
||||
TOK tokenStringConstant(Token *t);
|
||||
#endif
|
||||
TOK escapeStringConstant(Token *t, int wide);
|
||||
TOK charConstant(Token *t, int wide);
|
||||
void stringPostfix(Token *t);
|
||||
unsigned wchar(unsigned u);
|
||||
TOK number(Token *t);
|
||||
TOK inreal(Token *t);
|
||||
void error(const char *format, ...);
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void pragma();
|
||||
unsigned decodeUTF();
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_LEXER_H
|
||||
#define DMD_LEXER_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
|
||||
struct StringTable;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
|
||||
/* Tokens:
|
||||
( )
|
||||
[ ]
|
||||
{ }
|
||||
< > <= >= == != === !==
|
||||
<< >> <<= >>= >>> >>>=
|
||||
+ - += -=
|
||||
* / % *= /= %=
|
||||
& | ^ &= |= ^=
|
||||
= ! ~
|
||||
++ --
|
||||
. -> : ,
|
||||
? && ||
|
||||
*/
|
||||
|
||||
enum TOK
|
||||
{
|
||||
TOKreserved,
|
||||
|
||||
// Other
|
||||
TOKlparen, TOKrparen,
|
||||
TOKlbracket, TOKrbracket,
|
||||
TOKlcurly, TOKrcurly,
|
||||
TOKcolon, TOKneg,
|
||||
TOKsemicolon, TOKdotdotdot,
|
||||
TOKeof, TOKcast,
|
||||
TOKnull, TOKassert,
|
||||
TOKtrue, TOKfalse,
|
||||
TOKarray, TOKcall,
|
||||
TOKaddress,
|
||||
TOKtype, TOKthrow,
|
||||
TOKnew, TOKdelete,
|
||||
TOKstar, TOKsymoff,
|
||||
TOKvar, TOKdotvar,
|
||||
TOKdotti, TOKdotexp,
|
||||
TOKdottype, TOKslice,
|
||||
TOKarraylength, TOKversion,
|
||||
TOKmodule, TOKdollar,
|
||||
TOKtemplate, TOKdottd,
|
||||
TOKdeclaration, TOKtypeof,
|
||||
TOKpragma, TOKdsymbol,
|
||||
TOKtypeid, TOKuadd,
|
||||
TOKremove,
|
||||
TOKnewanonclass, TOKcomment,
|
||||
TOKarrayliteral, TOKassocarrayliteral,
|
||||
TOKstructliteral,
|
||||
|
||||
// Operators
|
||||
TOKlt, TOKgt,
|
||||
TOKle, TOKge,
|
||||
TOKequal, TOKnotequal,
|
||||
TOKidentity, TOKnotidentity,
|
||||
TOKindex, TOKis,
|
||||
TOKtobool,
|
||||
|
||||
// 60
|
||||
// NCEG floating point compares
|
||||
// !<>= <> <>= !> !>= !< !<= !<>
|
||||
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
|
||||
|
||||
TOKshl, TOKshr,
|
||||
TOKshlass, TOKshrass,
|
||||
TOKushr, TOKushrass,
|
||||
TOKcat, TOKcatass, // ~ ~=
|
||||
TOKadd, TOKmin, TOKaddass, TOKminass,
|
||||
TOKmul, TOKdiv, TOKmod,
|
||||
TOKmulass, TOKdivass, TOKmodass,
|
||||
TOKand, TOKor, TOKxor,
|
||||
TOKandass, TOKorass, TOKxorass,
|
||||
TOKassign, TOKnot, TOKtilde,
|
||||
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
|
||||
TOKdot, TOKarrow, TOKcomma,
|
||||
TOKquestion, TOKandand, TOKoror,
|
||||
|
||||
// 104
|
||||
// Numeric literals
|
||||
TOKint32v, TOKuns32v,
|
||||
TOKint64v, TOKuns64v,
|
||||
TOKfloat32v, TOKfloat64v, TOKfloat80v,
|
||||
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
|
||||
|
||||
// Char constants
|
||||
TOKcharv, TOKwcharv, TOKdcharv,
|
||||
|
||||
// Leaf operators
|
||||
TOKidentifier, TOKstring,
|
||||
TOKthis, TOKsuper,
|
||||
TOKhalt, TOKtuple,
|
||||
|
||||
// Basic types
|
||||
TOKvoid,
|
||||
TOKint8, TOKuns8,
|
||||
TOKint16, TOKuns16,
|
||||
TOKint32, TOKuns32,
|
||||
TOKint64, TOKuns64,
|
||||
TOKfloat32, TOKfloat64, TOKfloat80,
|
||||
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
||||
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
||||
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
|
||||
TOKcent, TOKucent,
|
||||
|
||||
// Aggregates
|
||||
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
|
||||
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
|
||||
TOKmixin,
|
||||
|
||||
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
|
||||
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
|
||||
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
|
||||
TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
|
||||
|
||||
// Statements
|
||||
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
|
||||
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
|
||||
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
|
||||
TOKasm, TOKforeach, TOKforeach_reverse,
|
||||
TOKscope,
|
||||
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
|
||||
|
||||
// Contracts
|
||||
TOKbody, TOKinvariant,
|
||||
|
||||
// Testing
|
||||
TOKunittest,
|
||||
|
||||
// Added after 1.0
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
TOKtraits,
|
||||
TOKoverloadset,
|
||||
TOKpure,
|
||||
TOKnothrow,
|
||||
TOKtls,
|
||||
TOKgshared,
|
||||
TOKline,
|
||||
TOKfile,
|
||||
TOKshared,
|
||||
#endif
|
||||
|
||||
// LDC specific
|
||||
#if IN_LLVM
|
||||
TOKgep,
|
||||
#endif
|
||||
|
||||
TOKMAX
|
||||
};
|
||||
|
||||
#define CASE_BASIC_TYPES \
|
||||
case TOKwchar: case TOKdchar: \
|
||||
case TOKbit: case TOKbool: case TOKchar: \
|
||||
case TOKint8: case TOKuns8: \
|
||||
case TOKint16: case TOKuns16: \
|
||||
case TOKint32: case TOKuns32: \
|
||||
case TOKint64: case TOKuns64: \
|
||||
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
|
||||
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
|
||||
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
|
||||
case TOKvoid
|
||||
|
||||
#define CASE_BASIC_TYPES_X(t) \
|
||||
case TOKvoid: t = Type::tvoid; goto LabelX; \
|
||||
case TOKint8: t = Type::tint8; goto LabelX; \
|
||||
case TOKuns8: t = Type::tuns8; goto LabelX; \
|
||||
case TOKint16: t = Type::tint16; goto LabelX; \
|
||||
case TOKuns16: t = Type::tuns16; goto LabelX; \
|
||||
case TOKint32: t = Type::tint32; goto LabelX; \
|
||||
case TOKuns32: t = Type::tuns32; goto LabelX; \
|
||||
case TOKint64: t = Type::tint64; goto LabelX; \
|
||||
case TOKuns64: t = Type::tuns64; goto LabelX; \
|
||||
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
|
||||
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
|
||||
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
|
||||
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
|
||||
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
|
||||
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
|
||||
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
|
||||
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
|
||||
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
|
||||
case TOKbit: t = Type::tbit; goto LabelX; \
|
||||
case TOKbool: t = Type::tbool; goto LabelX; \
|
||||
case TOKchar: t = Type::tchar; goto LabelX; \
|
||||
case TOKwchar: t = Type::twchar; goto LabelX; \
|
||||
case TOKdchar: t = Type::tdchar; goto LabelX; \
|
||||
LabelX
|
||||
|
||||
struct Token
|
||||
{
|
||||
Token *next;
|
||||
unsigned char *ptr; // pointer to first character of this token within buffer
|
||||
enum TOK value;
|
||||
unsigned char *blockComment; // doc comment string prior to this token
|
||||
unsigned char *lineComment; // doc comment for previous token
|
||||
union
|
||||
{
|
||||
// Integers
|
||||
d_int32 int32value;
|
||||
d_uns32 uns32value;
|
||||
d_int64 int64value;
|
||||
d_uns64 uns64value;
|
||||
|
||||
// Floats
|
||||
#ifdef IN_GCC
|
||||
// real_t float80value; // can't use this in a union!
|
||||
#else
|
||||
d_float80 float80value;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{ unsigned char *ustring; // UTF8 string
|
||||
unsigned len;
|
||||
unsigned char postfix; // 'c', 'w', 'd'
|
||||
};
|
||||
|
||||
Identifier *ident;
|
||||
};
|
||||
#ifdef IN_GCC
|
||||
real_t float80value; // can't use this in a union!
|
||||
#endif
|
||||
|
||||
static const char *tochars[TOKMAX];
|
||||
static void *operator new(size_t sz);
|
||||
|
||||
int isKeyword();
|
||||
void print();
|
||||
const char *toChars();
|
||||
static const char *toChars(enum TOK);
|
||||
};
|
||||
|
||||
struct Lexer
|
||||
{
|
||||
static StringTable stringtable;
|
||||
static OutBuffer stringbuffer;
|
||||
static Token *freelist;
|
||||
|
||||
Loc loc; // for error messages
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
Token token;
|
||||
Module *mod;
|
||||
int doDocComment; // collect doc comment information
|
||||
int anyToken; // !=0 means seen at least one token
|
||||
int commentToken; // !=0 means comments are TOKcomment's
|
||||
|
||||
Lexer(Module *mod,
|
||||
unsigned char *base, unsigned begoffset, unsigned endoffset,
|
||||
int doDocComment, int commentToken);
|
||||
|
||||
static void initKeywords();
|
||||
static Identifier *idPool(const char *s);
|
||||
static Identifier *uniqueId(const char *s);
|
||||
static Identifier *uniqueId(const char *s, int num);
|
||||
|
||||
TOK nextToken();
|
||||
TOK peekNext();
|
||||
TOK peekNext2();
|
||||
void scan(Token *t);
|
||||
Token *peek(Token *t);
|
||||
Token *peekPastParen(Token *t);
|
||||
unsigned escapeSequence();
|
||||
TOK wysiwygStringConstant(Token *t, int tc);
|
||||
TOK hexStringConstant(Token *t);
|
||||
#if DMDV2
|
||||
TOK delimitedStringConstant(Token *t);
|
||||
TOK tokenStringConstant(Token *t);
|
||||
#endif
|
||||
TOK escapeStringConstant(Token *t, int wide);
|
||||
TOK charConstant(Token *t, int wide);
|
||||
void stringPostfix(Token *t);
|
||||
unsigned wchar(unsigned u);
|
||||
TOK number(Token *t);
|
||||
TOK inreal(Token *t);
|
||||
void error(const char *format, ...) IS_PRINTF(2);
|
||||
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
|
||||
void pragma();
|
||||
unsigned decodeUTF();
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
|
||||
49
dmd2/lib.h
Normal file
49
dmd2/lib.h
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_LIB_H
|
||||
#define DMD_LIB_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct ObjModule;
|
||||
|
||||
struct ObjSymbol
|
||||
{
|
||||
char *name;
|
||||
ObjModule *om;
|
||||
};
|
||||
|
||||
struct Library
|
||||
{
|
||||
File *libfile;
|
||||
Array objmodules; // ObjModule[]
|
||||
Array objsymbols; // ObjSymbol[]
|
||||
|
||||
StringTable tab;
|
||||
|
||||
Library();
|
||||
void setFilename(char *dir, char *filename);
|
||||
void addObject(const char *module_name, void *buf, size_t buflen);
|
||||
void addLibrary(void *buf, size_t buflen);
|
||||
void write();
|
||||
|
||||
private:
|
||||
void addSymbol(ObjModule *om, char *name, int pickAny = 0);
|
||||
void scanObjModule(ObjModule *om);
|
||||
unsigned short numDictPages(unsigned padding);
|
||||
int FillDict(unsigned char *bucketsP, unsigned short uNumPages);
|
||||
void WriteLibToBuffer(OutBuffer *libbuf);
|
||||
};
|
||||
|
||||
#endif /* DMD_LIB_H */
|
||||
|
||||
14
dmd2/macro.c
14
dmd2/macro.c
@@ -16,19 +16,9 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#else
|
||||
#if _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#elif POSIX
|
||||
#include "../root/mem.h"
|
||||
#else
|
||||
#error "fix this"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "rmem.h"
|
||||
#include "root.h"
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
#define isidstart(c) (isalpha(c) || (c) == '_')
|
||||
|
||||
589
dmd2/mangle.c
589
dmd2/mangle.c
@@ -1,291 +1,298 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "mtype.h"
|
||||
#include "attrib.h"
|
||||
#include "template.h"
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
|
||||
#if TARGET_LINUX
|
||||
char *cpp_mangle(Dsymbol *s);
|
||||
#endif
|
||||
|
||||
char *mangle(Declaration *sthis)
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("::mangle(%s)\n", sthis->toChars());
|
||||
s = sthis;
|
||||
do
|
||||
{
|
||||
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
|
||||
if (s->ident)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (s != sthis && fd)
|
||||
{
|
||||
id = mangle(fd);
|
||||
buf.prependstring(id);
|
||||
goto L1;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = s->ident->toChars();
|
||||
int len = strlen(id);
|
||||
char tmp[sizeof(len) * 3 + 1];
|
||||
buf.prependstring(id);
|
||||
sprintf(tmp, "%d", len);
|
||||
buf.prependstring(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
buf.prependstring("0");
|
||||
s = s->parent;
|
||||
} while (s);
|
||||
|
||||
// buf.prependstring("_D");
|
||||
L1:
|
||||
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
|
||||
//printf("sthis->type = %s\n", sthis->type->toChars());
|
||||
FuncDeclaration *fd = sthis->isFuncDeclaration();
|
||||
if (fd && (fd->needThis() || fd->isNested()))
|
||||
buf.writeByte(Type::needThisPrefix());
|
||||
if (sthis->type->deco)
|
||||
buf.writestring(sthis->type->deco);
|
||||
else
|
||||
{ assert(fd->inferRetType);
|
||||
}
|
||||
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
return id;
|
||||
}
|
||||
|
||||
char *Declaration::mangle()
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
int len = strlen(result);
|
||||
|
||||
assert(len > 0);
|
||||
//printf("mangle: '%s' => '%s'\n", toChars(), result);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
assert(result[i] == '_' ||
|
||||
result[i] == '@' ||
|
||||
isalnum(result[i]) || result[i] & 0x80);
|
||||
}
|
||||
}
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
|
||||
if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
|
||||
{
|
||||
// If it's not a D declaration, no mangling
|
||||
switch (linkage)
|
||||
{
|
||||
case LINKd:
|
||||
break;
|
||||
|
||||
// LDC
|
||||
case LINKintrinsic:
|
||||
|
||||
case LINKc:
|
||||
case LINKwindows:
|
||||
case LINKpascal:
|
||||
return ident->toChars();
|
||||
|
||||
case LINKcpp:
|
||||
#if TARGET_LINUX
|
||||
return cpp_mangle(this);
|
||||
#else
|
||||
// Windows C++ mangling is done by C++ back end
|
||||
return ident->toChars();
|
||||
#endif
|
||||
|
||||
case LINKdefault:
|
||||
error("forward declaration");
|
||||
return ident->toChars();
|
||||
|
||||
default:
|
||||
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
char *p = ::mangle(this);
|
||||
OutBuffer buf;
|
||||
buf.writestring("_D");
|
||||
buf.writestring(p);
|
||||
p = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *FuncDeclaration::mangle()
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
assert(strlen(result) > 0);
|
||||
}
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
if (isMain())
|
||||
return (char *)"_Dmain";
|
||||
|
||||
if (isWinMain() || isDllMain())
|
||||
return ident->toChars();
|
||||
|
||||
assert(this);
|
||||
return Declaration::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *StructDeclaration::mangle()
|
||||
{
|
||||
//printf("StructDeclaration::mangle() '%s'\n", toChars());
|
||||
return Dsymbol::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *TypedefDeclaration::mangle()
|
||||
{
|
||||
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
|
||||
return Dsymbol::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *ClassDeclaration::mangle()
|
||||
{
|
||||
Dsymbol *parentsave = parent;
|
||||
|
||||
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
|
||||
|
||||
/* These are reserved to the compiler, so keep simple
|
||||
* names for them.
|
||||
*/
|
||||
if (ident == Id::Exception)
|
||||
{ if (parent->ident == Id::object)
|
||||
parent = NULL;
|
||||
}
|
||||
else if (ident == Id::TypeInfo ||
|
||||
// ident == Id::Exception ||
|
||||
ident == Id::TypeInfo_Struct ||
|
||||
ident == Id::TypeInfo_Class ||
|
||||
ident == Id::TypeInfo_Typedef ||
|
||||
ident == Id::TypeInfo_Tuple ||
|
||||
this == object ||
|
||||
this == classinfo ||
|
||||
this == Module::moduleinfo ||
|
||||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
|
||||
)
|
||||
parent = NULL;
|
||||
|
||||
char *id = Dsymbol::mangle();
|
||||
parent = parentsave;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
char *TemplateInstance::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateInstance::mangle() %s", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (tempdecl->parent)
|
||||
{
|
||||
char *p = tempdecl->parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
char *TemplateMixin::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateMixin::mangle() %s", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
char *p = parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
char *Dsymbol::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("Dsymbol::mangle() '%s'", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
char *p = parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "init.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "mtype.h"
|
||||
#include "attrib.h"
|
||||
#include "template.h"
|
||||
#include "id.h"
|
||||
#include "module.h"
|
||||
|
||||
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
|
||||
char *cpp_mangle(Dsymbol *s);
|
||||
#endif
|
||||
|
||||
char *mangle(Declaration *sthis)
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
Dsymbol *s;
|
||||
|
||||
//printf("::mangle(%s)\n", sthis->toChars());
|
||||
s = sthis;
|
||||
do
|
||||
{
|
||||
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
|
||||
if (s->ident)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (s != sthis && fd)
|
||||
{
|
||||
id = mangle(fd);
|
||||
buf.prependstring(id);
|
||||
goto L1;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = s->ident->toChars();
|
||||
int len = strlen(id);
|
||||
char tmp[sizeof(len) * 3 + 1];
|
||||
buf.prependstring(id);
|
||||
sprintf(tmp, "%d", len);
|
||||
buf.prependstring(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
buf.prependstring("0");
|
||||
s = s->parent;
|
||||
} while (s);
|
||||
|
||||
// buf.prependstring("_D");
|
||||
L1:
|
||||
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
|
||||
//printf("sthis->type = %s\n", sthis->type->toChars());
|
||||
FuncDeclaration *fd = sthis->isFuncDeclaration();
|
||||
if (fd && (fd->needThis() || fd->isNested()))
|
||||
buf.writeByte(Type::needThisPrefix());
|
||||
if (sthis->type->deco)
|
||||
buf.writestring(sthis->type->deco);
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!fd->inferRetType)
|
||||
printf("%s\n", fd->toChars());
|
||||
#endif
|
||||
assert(fd->inferRetType);
|
||||
}
|
||||
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
return id;
|
||||
}
|
||||
|
||||
char *Declaration::mangle()
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
int len = strlen(result);
|
||||
|
||||
assert(len > 0);
|
||||
//printf("mangle: '%s' => '%s'\n", toChars(), result);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
assert(result[i] == '_' ||
|
||||
result[i] == '@' ||
|
||||
isalnum(result[i]) || result[i] & 0x80);
|
||||
}
|
||||
}
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
|
||||
if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
|
||||
{
|
||||
// If it's not a D declaration, no mangling
|
||||
switch (linkage)
|
||||
{
|
||||
case LINKd:
|
||||
break;
|
||||
|
||||
// LDC
|
||||
case LINKintrinsic:
|
||||
|
||||
case LINKc:
|
||||
case LINKwindows:
|
||||
case LINKpascal:
|
||||
return ident->toChars();
|
||||
|
||||
case LINKcpp:
|
||||
#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
|
||||
return cpp_mangle(this);
|
||||
#else
|
||||
// Windows C++ mangling is done by C++ back end
|
||||
return ident->toChars();
|
||||
#endif
|
||||
|
||||
case LINKdefault:
|
||||
error("forward declaration");
|
||||
return ident->toChars();
|
||||
|
||||
default:
|
||||
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
char *p = ::mangle(this);
|
||||
OutBuffer buf;
|
||||
buf.writestring("_D");
|
||||
buf.writestring(p);
|
||||
p = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *FuncDeclaration::mangle()
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
assert(strlen(result) > 0);
|
||||
}
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
if (isMain())
|
||||
return (char *)"_Dmain";
|
||||
|
||||
if (isWinMain() || isDllMain() || ident == Id::tls_get_addr)
|
||||
return ident->toChars();
|
||||
|
||||
assert(this);
|
||||
return Declaration::mangle();
|
||||
}
|
||||
|
||||
char *StructDeclaration::mangle()
|
||||
{
|
||||
//printf("StructDeclaration::mangle() '%s'\n", toChars());
|
||||
return Dsymbol::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *TypedefDeclaration::mangle()
|
||||
{
|
||||
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
|
||||
return Dsymbol::mangle();
|
||||
}
|
||||
|
||||
|
||||
char *ClassDeclaration::mangle()
|
||||
{
|
||||
Dsymbol *parentsave = parent;
|
||||
|
||||
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
|
||||
|
||||
/* These are reserved to the compiler, so keep simple
|
||||
* names for them.
|
||||
*/
|
||||
if (ident == Id::Exception)
|
||||
{ if (parent->ident == Id::object)
|
||||
parent = NULL;
|
||||
}
|
||||
else if (ident == Id::TypeInfo ||
|
||||
// ident == Id::Exception ||
|
||||
ident == Id::TypeInfo_Struct ||
|
||||
ident == Id::TypeInfo_Class ||
|
||||
ident == Id::TypeInfo_Typedef ||
|
||||
ident == Id::TypeInfo_Tuple ||
|
||||
this == object ||
|
||||
this == classinfo ||
|
||||
this == Module::moduleinfo ||
|
||||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
|
||||
)
|
||||
parent = NULL;
|
||||
|
||||
char *id = Dsymbol::mangle();
|
||||
parent = parentsave;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
char *TemplateInstance::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateInstance::mangle() %s", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (!tempdecl)
|
||||
error("is not defined");
|
||||
else if (tempdecl->parent)
|
||||
{
|
||||
char *p = tempdecl->parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%zu%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if IN_LLVM
|
||||
char *TemplateMixin::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateMixin::mangle() %s", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
char *p = parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%zu%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *Dsymbol::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("Dsymbol::mangle() '%s'", toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
char *p = parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%zu%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
630
dmd2/mars.c
630
dmd2/mars.c
@@ -1,278 +1,352 @@
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
|
||||
#if __DMC__
|
||||
#include <dos.h>
|
||||
#endif
|
||||
|
||||
#if POSIX
|
||||
#include <errno.h>
|
||||
#elif _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "root.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
#include "mtype.h"
|
||||
#include "id.h"
|
||||
#include "cond.h"
|
||||
#include "expression.h"
|
||||
#include "lexer.h"
|
||||
|
||||
#include "revisions.h"
|
||||
|
||||
Global global;
|
||||
|
||||
Global::Global()
|
||||
{
|
||||
mars_ext = "d";
|
||||
sym_ext = "d";
|
||||
hdr_ext = "di";
|
||||
doc_ext = "html";
|
||||
ddoc_ext = "ddoc";
|
||||
|
||||
// LDC
|
||||
ll_ext = "ll";
|
||||
bc_ext = "bc";
|
||||
s_ext = "s";
|
||||
obj_ext = "o";
|
||||
#if _WIN32
|
||||
obj_ext_alt = "obj";
|
||||
#endif
|
||||
|
||||
copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v2.021";
|
||||
ldc_version = LDC_REV;
|
||||
llvm_version = LLVM_REV_STR;
|
||||
global.structalign = 8;
|
||||
|
||||
// This should only be used as a global, so the other fields are
|
||||
// automatically initialized to zero when the program is loaded.
|
||||
// In particular, DO NOT zero-initialize .params here (like DMD
|
||||
// does) because command-line options initialize some of those
|
||||
// fields to non-zero defaults, and do so from constructors that
|
||||
// may run before this one.
|
||||
}
|
||||
|
||||
char *Loc::toChars() const
|
||||
{
|
||||
OutBuffer buf;
|
||||
|
||||
if (filename)
|
||||
{
|
||||
buf.printf("%s", filename);
|
||||
}
|
||||
|
||||
if (linnum)
|
||||
buf.printf("(%d)", linnum);
|
||||
buf.writeByte(0);
|
||||
return (char *)buf.extractData();
|
||||
}
|
||||
|
||||
Loc::Loc(Module *mod, unsigned linnum)
|
||||
{
|
||||
this->linnum = linnum;
|
||||
this->filename = mod ? mod->srcfile->toChars() : NULL;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Print error message and exit.
|
||||
*/
|
||||
|
||||
void error(Loc loc, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
verror(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void verror(Loc loc, const char *format, va_list ap)
|
||||
{
|
||||
if (!global.gag)
|
||||
{
|
||||
char *p = loc.toChars();
|
||||
|
||||
if (*p)
|
||||
fprintf(stdmsg, "%s: ", p);
|
||||
mem.free(p);
|
||||
|
||||
fprintf(stdmsg, "Error: ");
|
||||
vfprintf(stdmsg, format, ap);
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
}
|
||||
global.errors++;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Call this after printing out fatal error messages to clean up and exit
|
||||
* the compiler.
|
||||
*/
|
||||
|
||||
void fatal()
|
||||
{
|
||||
#if 0
|
||||
halt();
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Try to stop forgetting to remove the breakpoints from
|
||||
* release builds.
|
||||
*/
|
||||
void halt()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*(char*)0=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Parse and append contents of environment variable envvar
|
||||
* to argc and argv[].
|
||||
* The string is separated into arguments, processing \ and ".
|
||||
*/
|
||||
|
||||
void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
|
||||
{
|
||||
char *env;
|
||||
char *p;
|
||||
Array *argv;
|
||||
int argc;
|
||||
|
||||
int wildcard; // do wildcard expansion
|
||||
int instring;
|
||||
int slash;
|
||||
char c;
|
||||
int j;
|
||||
|
||||
env = getenv(envvar);
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
env = mem.strdup(env); // create our own writable copy
|
||||
|
||||
argc = *pargc;
|
||||
argv = new Array();
|
||||
argv->setDim(argc);
|
||||
|
||||
int argc_left = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
|
||||
// HACK: set flag to indicate we saw '-run' here
|
||||
global.params.run = true;
|
||||
// Don't eat -run yet so the program arguments don't get changed
|
||||
argc_left = argc - i;
|
||||
argc = i;
|
||||
*pargv = &(*pargv)[i];
|
||||
argv->setDim(i);
|
||||
break;
|
||||
} else {
|
||||
argv->data[i] = (void *)(*pargv)[i];
|
||||
}
|
||||
}
|
||||
// HACK to stop required values from command line being drawn from DFLAGS
|
||||
argv->push((char*)"");
|
||||
argc++;
|
||||
|
||||
j = 1; // leave argv[0] alone
|
||||
while (1)
|
||||
{
|
||||
wildcard = 1;
|
||||
switch (*env)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
env++;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
goto Ldone;
|
||||
|
||||
case '"':
|
||||
wildcard = 0;
|
||||
default:
|
||||
argv->push(env); // append
|
||||
//argv->insert(j, env); // insert at position j
|
||||
j++;
|
||||
argc++;
|
||||
p = env;
|
||||
slash = 0;
|
||||
instring = 0;
|
||||
c = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c = *env++;
|
||||
switch (c)
|
||||
{
|
||||
case '"':
|
||||
p -= (slash >> 1);
|
||||
if (slash & 1)
|
||||
{ p--;
|
||||
goto Laddc;
|
||||
}
|
||||
instring ^= 1;
|
||||
slash = 0;
|
||||
continue;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (instring)
|
||||
goto Laddc;
|
||||
*p = 0;
|
||||
//if (wildcard)
|
||||
//wildcardexpand(); // not implemented
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
slash++;
|
||||
*p++ = c;
|
||||
continue;
|
||||
|
||||
case 0:
|
||||
*p = 0;
|
||||
//if (wildcard)
|
||||
//wildcardexpand(); // not implemented
|
||||
goto Ldone;
|
||||
|
||||
default:
|
||||
Laddc:
|
||||
slash = 0;
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ldone:
|
||||
assert(argc == argv->dim);
|
||||
argv->reserve(argc_left);
|
||||
for (int i = 0; i < argc_left; i++)
|
||||
argv->data[argc++] = (void *)(*pargv)[i];
|
||||
|
||||
*pargc = argc;
|
||||
*pargv = (char **)argv->data;
|
||||
}
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
|
||||
#if POSIX
|
||||
#include <errno.h>
|
||||
#elif _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "rmem.h"
|
||||
#include "root.h"
|
||||
#if !IN_LLVM
|
||||
#include "async.h"
|
||||
#endif
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
#include "mtype.h"
|
||||
#include "id.h"
|
||||
#include "cond.h"
|
||||
#include "expression.h"
|
||||
#include "lexer.h"
|
||||
#if IN_LLVM
|
||||
#include "gen/revisions.h"
|
||||
#else
|
||||
#include "lib.h"
|
||||
|
||||
#if WINDOWS_SEH
|
||||
#include <windows.h>
|
||||
long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
|
||||
#endif
|
||||
|
||||
|
||||
int response_expand(int *pargc, char ***pargv);
|
||||
void browse(const char *url);
|
||||
void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
|
||||
|
||||
void obj_start(char *srcfile);
|
||||
void obj_end(Library *library, File *objfile);
|
||||
#endif
|
||||
|
||||
Global global;
|
||||
|
||||
Global::Global()
|
||||
{
|
||||
mars_ext = "d";
|
||||
sym_ext = "d";
|
||||
hdr_ext = "di";
|
||||
doc_ext = "html";
|
||||
ddoc_ext = "ddoc";
|
||||
|
||||
#if IN_LLVM
|
||||
ll_ext = "ll";
|
||||
bc_ext = "bc";
|
||||
s_ext = "s";
|
||||
obj_ext = "o";
|
||||
#if _WIN32
|
||||
obj_ext_alt = "obj";
|
||||
#endif
|
||||
#else
|
||||
#if TARGET_WINDOS
|
||||
obj_ext = "obj";
|
||||
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
|
||||
obj_ext = "o";
|
||||
#elif TARGET_NET
|
||||
#else
|
||||
#error "fix this"
|
||||
#endif
|
||||
|
||||
#if TARGET_WINDOS
|
||||
lib_ext = "lib";
|
||||
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
|
||||
lib_ext = "a";
|
||||
#elif TARGET_NET
|
||||
#else
|
||||
#error "fix this"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
copyright = "Copyright (c) 1999-2009 by Digital Mars";
|
||||
written = "written by Walter Bright"
|
||||
#if TARGET_NET
|
||||
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
|
||||
#endif
|
||||
;
|
||||
version = "v2.030";
|
||||
#if IN_LLVM
|
||||
ldc_version = LDC_REV;
|
||||
llvm_version = LLVM_REV_STR;
|
||||
#endif
|
||||
global.structalign = 8;
|
||||
|
||||
// This should only be used as a global, so the other fields are
|
||||
// automatically initialized to zero when the program is loaded.
|
||||
// In particular, DO NOT zero-initialize .params here (like DMD
|
||||
// does) because command-line options initialize some of those
|
||||
// fields to non-zero defaults, and do so from constructors that
|
||||
// may run before this one.
|
||||
}
|
||||
|
||||
char *Loc::toChars()
|
||||
{
|
||||
OutBuffer buf;
|
||||
|
||||
if (filename)
|
||||
{
|
||||
buf.printf("%s", filename);
|
||||
}
|
||||
|
||||
if (linnum)
|
||||
buf.printf("(%d)", linnum);
|
||||
buf.writeByte(0);
|
||||
return (char *)buf.extractData();
|
||||
}
|
||||
|
||||
Loc::Loc(Module *mod, unsigned linnum)
|
||||
{
|
||||
this->linnum = linnum;
|
||||
this->filename = mod ? mod->srcfile->toChars() : NULL;
|
||||
}
|
||||
|
||||
bool Loc::equals(const Loc& loc)
|
||||
{
|
||||
return linnum == loc.linnum && FileName::equals(filename, loc.filename);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Print error message and exit.
|
||||
*/
|
||||
|
||||
void error(Loc loc, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
verror(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void warning(Loc loc, const char *format, ...)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vwarning(loc, format, ap);
|
||||
va_end( ap );
|
||||
}
|
||||
}
|
||||
|
||||
void verror(Loc loc, const char *format, va_list ap)
|
||||
{
|
||||
if (!global.gag)
|
||||
{
|
||||
char *p = loc.toChars();
|
||||
|
||||
if (*p)
|
||||
fprintf(stdmsg, "%s: ", p);
|
||||
mem.free(p);
|
||||
|
||||
fprintf(stdmsg, "Error: ");
|
||||
vfprintf(stdmsg, format, ap);
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
}
|
||||
global.errors++;
|
||||
}
|
||||
|
||||
void vwarning(Loc loc, const char *format, va_list ap)
|
||||
{
|
||||
if (global.params.warnings && !global.gag)
|
||||
{
|
||||
char *p = loc.toChars();
|
||||
|
||||
if (*p)
|
||||
fprintf(stdmsg, "%s: ", p);
|
||||
mem.free(p);
|
||||
|
||||
fprintf(stdmsg, "Warning: ");
|
||||
vfprintf(stdmsg, format, ap);
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Call this after printing out fatal error messages to clean up and exit
|
||||
* the compiler.
|
||||
*/
|
||||
|
||||
void fatal()
|
||||
{
|
||||
#if 0
|
||||
halt();
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Try to stop forgetting to remove the breakpoints from
|
||||
* release builds.
|
||||
*/
|
||||
void halt()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*(char*)0=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Parse and append contents of environment variable envvar
|
||||
* to argc and argv[].
|
||||
* The string is separated into arguments, processing \ and ".
|
||||
*/
|
||||
|
||||
void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
|
||||
{
|
||||
char *env;
|
||||
char *p;
|
||||
Array *argv;
|
||||
int argc;
|
||||
|
||||
int wildcard; // do wildcard expansion
|
||||
int instring;
|
||||
int slash;
|
||||
char c;
|
||||
int j;
|
||||
|
||||
env = getenv(envvar);
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
env = mem.strdup(env); // create our own writable copy
|
||||
|
||||
argc = *pargc;
|
||||
argv = new Array();
|
||||
argv->setDim(argc);
|
||||
|
||||
int argc_left = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
|
||||
// HACK: set flag to indicate we saw '-run' here
|
||||
global.params.run = true;
|
||||
// Don't eat -run yet so the program arguments don't get changed
|
||||
argc_left = argc - i;
|
||||
argc = i;
|
||||
*pargv = &(*pargv)[i];
|
||||
argv->setDim(i);
|
||||
break;
|
||||
} else {
|
||||
argv->data[i] = (void *)(*pargv)[i];
|
||||
}
|
||||
}
|
||||
// HACK to stop required values from command line being drawn from DFLAGS
|
||||
argv->push((char*)"");
|
||||
argc++;
|
||||
|
||||
j = 1; // leave argv[0] alone
|
||||
while (1)
|
||||
{
|
||||
wildcard = 1;
|
||||
switch (*env)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
env++;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
goto Ldone;
|
||||
|
||||
case '"':
|
||||
wildcard = 0;
|
||||
default:
|
||||
argv->push(env); // append
|
||||
//argv->insert(j, env); // insert at position j
|
||||
j++;
|
||||
argc++;
|
||||
p = env;
|
||||
slash = 0;
|
||||
instring = 0;
|
||||
c = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c = *env++;
|
||||
switch (c)
|
||||
{
|
||||
case '"':
|
||||
p -= (slash >> 1);
|
||||
if (slash & 1)
|
||||
{ p--;
|
||||
goto Laddc;
|
||||
}
|
||||
instring ^= 1;
|
||||
slash = 0;
|
||||
continue;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (instring)
|
||||
goto Laddc;
|
||||
*p = 0;
|
||||
//if (wildcard)
|
||||
//wildcardexpand(); // not implemented
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
slash++;
|
||||
*p++ = c;
|
||||
continue;
|
||||
|
||||
case 0:
|
||||
*p = 0;
|
||||
//if (wildcard)
|
||||
//wildcardexpand(); // not implemented
|
||||
goto Ldone;
|
||||
|
||||
default:
|
||||
Laddc:
|
||||
slash = 0;
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ldone:
|
||||
assert(argc == argv->dim);
|
||||
argv->reserve(argc_left);
|
||||
for (int i = 0; i < argc_left; i++)
|
||||
argv->data[argc++] = (void *)(*pargv)[i];
|
||||
|
||||
*pargc = argc;
|
||||
*pargv = (char **)argv->data;
|
||||
}
|
||||
|
||||
811
dmd2/mars.h
811
dmd2/mars.h
@@ -1,353 +1,458 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_MARS_H
|
||||
#define DMD_MARS_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __DMC__
|
||||
#ifdef DEBUG
|
||||
#undef assert
|
||||
#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
/* Changes for the GDC compiler by David Friedman */
|
||||
#endif
|
||||
|
||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
||||
#define STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer
|
||||
|
||||
struct Array;
|
||||
|
||||
// LDC
|
||||
enum ARCH
|
||||
{
|
||||
ARCHinvalid,
|
||||
ARCHx86,
|
||||
ARCHx86_64,
|
||||
ARCHppc,
|
||||
ARCHppc_64,
|
||||
ARCHarm,
|
||||
ARCHthumb
|
||||
};
|
||||
enum OUTPUTFLAG
|
||||
{
|
||||
OUTPUTFLAGno,
|
||||
OUTPUTFLAGdefault, // for the .o default
|
||||
OUTPUTFLAGset // for -output
|
||||
};
|
||||
|
||||
enum OS
|
||||
{
|
||||
OSinvalid,
|
||||
OSLinux,
|
||||
OSWindows,
|
||||
OSMacOSX,
|
||||
OSFreeBSD,
|
||||
OSSolaris,
|
||||
};
|
||||
|
||||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
bool obj; // write object file
|
||||
bool link; // perform link
|
||||
bool verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
#if !IN_LLVM
|
||||
// LDC uses a different mechanism
|
||||
bool optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
#endif
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
bool is64bit; // generate 64 bit code
|
||||
bool isLE; // generate little endian code
|
||||
bool useDeprecated; // allow use of deprecated features
|
||||
bool useAssert; // generate runtime code for assert()'s
|
||||
bool useInvariants; // generate class invariant checks
|
||||
bool useIn; // generate precondition checks
|
||||
bool useOut; // generate postcondition checks
|
||||
bool useArrayBounds; // generate array bounds checks
|
||||
bool useSwitchError; // check for switches without a default
|
||||
bool useUnitTests; // generate unittest code
|
||||
bool useInline; // inline expand functions
|
||||
bool warnings; // enable warnings
|
||||
bool safe; // enforce safe memory model
|
||||
char Dversion; // D version number
|
||||
|
||||
char *argv0; // program name
|
||||
Array *imppath; // array of char*'s of where to look for import modules
|
||||
Array *fileImppath; // array of char*'s of where to look for file import modules
|
||||
char *objdir; // .obj file output directory
|
||||
char *objname; // .obj file output name
|
||||
|
||||
bool doDocComments; // process embedded documentation comments
|
||||
char *docdir; // write documentation file to docdir directory
|
||||
char *docname; // write documentation file to docname
|
||||
Array *ddocfiles; // macro include files for Ddoc
|
||||
|
||||
bool doHdrGeneration; // process embedded documentation comments
|
||||
char *hdrdir; // write 'header' file to docdir directory
|
||||
char *hdrname; // write 'header' file to docname
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
|
||||
bool dump_source;
|
||||
|
||||
Array *defaultlibnames; // default libraries for non-debug builds
|
||||
Array *debuglibnames; // default libraries for debug builds
|
||||
|
||||
char *xmlname; // filename for XML output
|
||||
|
||||
// Hidden debug switches
|
||||
bool debuga;
|
||||
bool debugb;
|
||||
bool debugc;
|
||||
bool debugf;
|
||||
bool debugr;
|
||||
bool debugw;
|
||||
bool debugx;
|
||||
bool debugy;
|
||||
|
||||
bool run; // run resulting executable
|
||||
|
||||
// Linker stuff
|
||||
Array *objfiles;
|
||||
Array *linkswitches;
|
||||
Array *libfiles;
|
||||
char *deffile;
|
||||
char *resfile;
|
||||
char *exefile;
|
||||
|
||||
// LDC stuff
|
||||
OUTPUTFLAG output_ll;
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
OUTPUTFLAG output_o;
|
||||
bool llvmAnnotate;
|
||||
bool useInlineAsm;
|
||||
|
||||
// target stuff
|
||||
const char* llvmArch;
|
||||
const char *targetTriple;
|
||||
const char *dataLayout;
|
||||
};
|
||||
|
||||
struct Global
|
||||
{
|
||||
char *mars_ext;
|
||||
char *sym_ext;
|
||||
char *obj_ext;
|
||||
#if _WIN32
|
||||
char *obj_ext_alt;
|
||||
#endif
|
||||
char *ll_ext;
|
||||
char *bc_ext;
|
||||
char *s_ext;
|
||||
char *doc_ext; // for Ddoc generated files
|
||||
char *ddoc_ext; // for Ddoc macro include files
|
||||
char *hdr_ext; // for D 'header' import files
|
||||
char *copyright;
|
||||
char *written;
|
||||
Array *path; // Array of char*'s which form the import lookup path
|
||||
Array *filePath; // Array of char*'s which form the file import lookup path
|
||||
int structalign;
|
||||
char *version;
|
||||
char *ldc_version;
|
||||
char *llvm_version;
|
||||
|
||||
Param params;
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors
|
||||
|
||||
Global();
|
||||
};
|
||||
|
||||
extern Global global;
|
||||
|
||||
/* Set if Windows Structured Exception Handling C extensions are supported.
|
||||
* Apparently, VC has dropped support for these?
|
||||
*/
|
||||
#define WINDOWS_SEH (_WIN32 && __DMC__)
|
||||
|
||||
|
||||
#if __GNUC__
|
||||
//#define memicmp strncasecmp
|
||||
//#define stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
#ifdef __DMC__
|
||||
typedef _Complex long double complex_t;
|
||||
#else
|
||||
#ifndef IN_GCC
|
||||
#include "complex_t.h"
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Be careful not to care about sign when using integer_t
|
||||
typedef uint64_t integer_t;
|
||||
|
||||
// Signed and unsigned variants
|
||||
typedef int64_t sinteger_t;
|
||||
typedef uint64_t uinteger_t;
|
||||
|
||||
typedef int8_t d_int8;
|
||||
typedef uint8_t d_uns8;
|
||||
typedef int16_t d_int16;
|
||||
typedef uint16_t d_uns16;
|
||||
typedef int32_t d_int32;
|
||||
typedef uint32_t d_uns32;
|
||||
typedef int64_t d_int64;
|
||||
typedef uint64_t d_uns64;
|
||||
|
||||
typedef float d_float32;
|
||||
typedef double d_float64;
|
||||
typedef long double d_float80;
|
||||
|
||||
typedef d_uns8 d_char;
|
||||
typedef d_uns16 d_wchar;
|
||||
typedef d_uns32 d_dchar;
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
#else
|
||||
typedef long double real_t;
|
||||
#endif
|
||||
|
||||
// Modify OutBuffer::writewchar to write the correct size of wchar
|
||||
#if _WIN32
|
||||
#define writewchar writeword
|
||||
#else
|
||||
// This needs a configuration test...
|
||||
#define writewchar write4
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-complex_t.h"
|
||||
#endif
|
||||
|
||||
// taken from GDC
|
||||
// for handling printf incompatibilities
|
||||
#if __MSVCRT__
|
||||
#define PRIuSIZE "Iu"
|
||||
#define PRIxSIZE "Ix"
|
||||
#elif __MINGW32__
|
||||
#define PRIuSIZE "u"
|
||||
#define PRIxSIZE "x"
|
||||
#else
|
||||
#define PRIuSIZE "zu"
|
||||
#define PRIxSIZE "zx"
|
||||
#endif
|
||||
|
||||
struct Module;
|
||||
|
||||
//typedef unsigned Loc; // file location
|
||||
struct Loc
|
||||
{
|
||||
char *filename;
|
||||
unsigned linnum;
|
||||
|
||||
Loc()
|
||||
{
|
||||
linnum = 0;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(int x)
|
||||
{
|
||||
linnum = x;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(Module *mod, unsigned linnum);
|
||||
|
||||
char *toChars() const;
|
||||
};
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||
// in interface vtbl[]'s
|
||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||
// in the inheritance graph multiple
|
||||
// times, only one is used
|
||||
|
||||
enum LINK
|
||||
{
|
||||
LINKdefault,
|
||||
LINKd,
|
||||
LINKc,
|
||||
LINKcpp,
|
||||
LINKwindows,
|
||||
LINKpascal,
|
||||
|
||||
// LDC
|
||||
LINKintrinsic,
|
||||
};
|
||||
|
||||
enum DYNCAST
|
||||
{
|
||||
DYNCAST_OBJECT,
|
||||
DYNCAST_EXPRESSION,
|
||||
DYNCAST_DSYMBOL,
|
||||
DYNCAST_TYPE,
|
||||
DYNCAST_IDENTIFIER,
|
||||
DYNCAST_TUPLE,
|
||||
};
|
||||
|
||||
enum MATCH
|
||||
{
|
||||
MATCHnomatch, // no match
|
||||
MATCHconvert, // match with conversions
|
||||
#if DMDV2
|
||||
MATCHconst, // match with conversion to const
|
||||
#endif
|
||||
MATCHexact // exact match
|
||||
};
|
||||
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void verror(Loc loc, const char *format, va_list);
|
||||
void fatal();
|
||||
void err_nomem();
|
||||
void inifile(char *argv0, const char *inifile);
|
||||
void halt();
|
||||
|
||||
/*** Where to send error messages ***/
|
||||
#if IN_GCC || IN_LLVM
|
||||
#define stdmsg stderr
|
||||
#else
|
||||
#define stdmsg stdout
|
||||
#endif
|
||||
|
||||
#endif /* DMD_MARS_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_MARS_H
|
||||
#define DMD_MARS_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*
|
||||
It is very important to use version control macros correctly - the
|
||||
idea is that host and target are independent. If these are done
|
||||
correctly, cross compilers can be built.
|
||||
The host compiler and host operating system are also different,
|
||||
and are predefined by the host compiler. The ones used in
|
||||
dmd are:
|
||||
|
||||
Macros defined by the compiler, not the code:
|
||||
|
||||
Compiler:
|
||||
__DMC__ Digital Mars compiler
|
||||
_MSC_VER Microsoft compiler
|
||||
__GNUC__ Gnu compiler
|
||||
|
||||
Host operating system:
|
||||
_WIN32 Microsoft NT, Windows 95, Windows 98, Win32s,
|
||||
Windows 2000, Win XP, Vista
|
||||
_WIN64 Windows for AMD64
|
||||
linux Linux
|
||||
__APPLE__ Mac OSX
|
||||
__FreeBSD__ FreeBSD
|
||||
__sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary)
|
||||
|
||||
For the target systems, there are the target operating system and
|
||||
the target object file format:
|
||||
|
||||
Target operating system:
|
||||
TARGET_WINDOS Covers 32 bit windows and 64 bit windows
|
||||
TARGET_LINUX Covers 32 and 64 bit linux
|
||||
TARGET_OSX Covers 32 and 64 bit Mac OSX
|
||||
TARGET_FREEBSD Covers 32 and 64 bit FreeBSD
|
||||
TARGET_SOLARIS Covers 32 and 64 bit Solaris
|
||||
TARGET_NET Covers .Net
|
||||
|
||||
It is expected that the compiler for each platform will be able
|
||||
to generate 32 and 64 bit code from the same compiler binary.
|
||||
|
||||
Target object module format:
|
||||
OMFOBJ Intel Object Module Format, used on Windows
|
||||
ELFOBJ Elf Object Module Format, used on linux, FreeBSD and Solaris
|
||||
MACHOBJ Mach-O Object Module Format, used on Mac OSX
|
||||
|
||||
There are currently no macros for byte endianness order.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __DMC__
|
||||
#ifdef DEBUG
|
||||
#undef assert
|
||||
#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IS_PRINTF
|
||||
# ifdef __GNUC__
|
||||
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
|
||||
# else
|
||||
# define IS_PRINTF(FMTARG)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
/* Changes for the GDC compiler by David Friedman */
|
||||
#endif
|
||||
|
||||
#define DMDV1 0
|
||||
#define DMDV2 1 // Version 2.0 features
|
||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
||||
#define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer
|
||||
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
|
||||
|
||||
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and
|
||||
* TARGET_SOLARIS, which are
|
||||
* set on the command line via the compiler makefile.
|
||||
*/
|
||||
|
||||
#if _WIN32
|
||||
#define TARGET_WINDOS 1 // Windows dmd generates Windows targets
|
||||
#define OMFOBJ 1
|
||||
#endif
|
||||
|
||||
#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
|
||||
#ifndef ELFOBJ
|
||||
#define ELFOBJ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TARGET_OSX
|
||||
#ifndef MACHOBJ
|
||||
#define MACHOBJ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
struct Array;
|
||||
struct OutBuffer;
|
||||
|
||||
#if IN_LLVM
|
||||
enum ARCH
|
||||
{
|
||||
ARCHinvalid,
|
||||
ARCHx86,
|
||||
ARCHx86_64,
|
||||
ARCHppc,
|
||||
ARCHppc_64,
|
||||
ARCHarm,
|
||||
ARCHthumb
|
||||
};
|
||||
enum OUTPUTFLAG
|
||||
{
|
||||
OUTPUTFLAGno,
|
||||
OUTPUTFLAGdefault, // for the .o default
|
||||
OUTPUTFLAGset // for -output
|
||||
};
|
||||
|
||||
enum OS
|
||||
{
|
||||
OSinvalid,
|
||||
OSLinux,
|
||||
OSWindows,
|
||||
OSMacOSX,
|
||||
OSFreeBSD,
|
||||
OSSolaris,
|
||||
};
|
||||
|
||||
typedef unsigned char ubyte;
|
||||
#endif
|
||||
|
||||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
bool obj; // write object file
|
||||
bool link; // perform link
|
||||
bool verbose; // verbose compile
|
||||
bool vtls; // identify thread local variables
|
||||
ubyte symdebug; // insert debug symbolic information
|
||||
#if !IN_LLVM
|
||||
// LDC uses a different mechanism
|
||||
bool optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
#endif
|
||||
ARCH cpu; // target CPU
|
||||
OS os;
|
||||
bool is64bit; // generate X86_64 bit code
|
||||
bool isLE; // generate little endian code
|
||||
bool useDeprecated; // allow use of deprecated features
|
||||
bool useAssert; // generate runtime code for assert()'s
|
||||
bool useInvariants; // generate class invariant checks
|
||||
bool useIn; // generate precondition checks
|
||||
bool useOut; // generate postcondition checks
|
||||
bool useArrayBounds; // generate array bounds checks
|
||||
bool useSwitchError; // check for switches without a default
|
||||
bool useUnitTests; // generate unittest code
|
||||
bool useInline; // inline expand functions
|
||||
bool warnings; // enable warnings
|
||||
ubyte Dversion; // D version number
|
||||
char safe; // enforce safe memory model
|
||||
|
||||
char *argv0; // program name
|
||||
Array *imppath; // array of char*'s of where to look for import modules
|
||||
Array *fileImppath; // array of char*'s of where to look for file import modules
|
||||
char *objdir; // .obj file output directory
|
||||
char *objname; // .obj file output name
|
||||
|
||||
bool doDocComments; // process embedded documentation comments
|
||||
char *docdir; // write documentation file to docdir directory
|
||||
char *docname; // write documentation file to docname
|
||||
Array *ddocfiles; // macro include files for Ddoc
|
||||
|
||||
bool doHdrGeneration; // process embedded documentation comments
|
||||
char *hdrdir; // write 'header' file to docdir directory
|
||||
char *hdrname; // write 'header' file to docname
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
|
||||
bool dump_source;
|
||||
|
||||
Array *defaultlibnames; // default libraries for non-debug builds
|
||||
Array *debuglibnames; // default libraries for debug builds
|
||||
|
||||
const char *xmlname; // filename for XML output
|
||||
|
||||
OutBuffer *moduleDeps; // buffer and filename for emitting module deps
|
||||
char *moduleDepsFile;
|
||||
|
||||
// Hidden debug switches
|
||||
bool debuga;
|
||||
bool debugb;
|
||||
bool debugc;
|
||||
bool debugf;
|
||||
bool debugr;
|
||||
bool debugw;
|
||||
bool debugx;
|
||||
bool debugy;
|
||||
|
||||
bool run; // run resulting executable
|
||||
|
||||
// Linker stuff
|
||||
Array *objfiles;
|
||||
Array *linkswitches;
|
||||
Array *libfiles;
|
||||
char *deffile;
|
||||
char *resfile;
|
||||
char *exefile;
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC stuff
|
||||
OUTPUTFLAG output_ll;
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
OUTPUTFLAG output_o;
|
||||
bool llvmAnnotate;
|
||||
bool useInlineAsm;
|
||||
bool verbose_cg;
|
||||
|
||||
// target stuff
|
||||
const char* llvmArch;
|
||||
const char *targetTriple;
|
||||
const char *dataLayout;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Global
|
||||
{
|
||||
const char *mars_ext;
|
||||
const char *sym_ext;
|
||||
const char *obj_ext;
|
||||
#if IN_LLVM
|
||||
#if _WIN32
|
||||
char *obj_ext_alt;
|
||||
#endif
|
||||
char *ll_ext;
|
||||
char *bc_ext;
|
||||
char *s_ext;
|
||||
#endif
|
||||
const char *lib_ext;
|
||||
const char *doc_ext; // for Ddoc generated files
|
||||
const char *ddoc_ext; // for Ddoc macro include files
|
||||
const char *hdr_ext; // for D 'header' import files
|
||||
const char *copyright;
|
||||
const char *written;
|
||||
Array *path; // Array of char*'s which form the import lookup path
|
||||
Array *filePath; // Array of char*'s which form the file import lookup path
|
||||
int structalign;
|
||||
const char *version;
|
||||
#if IN_LLVM
|
||||
char *ldc_version;
|
||||
char *llvm_version;
|
||||
#endif
|
||||
|
||||
Param params;
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors
|
||||
|
||||
Global();
|
||||
};
|
||||
|
||||
extern Global global;
|
||||
|
||||
/* Set if Windows Structured Exception Handling C extensions are supported.
|
||||
* Apparently, VC has dropped support for these?
|
||||
*/
|
||||
#define WINDOWS_SEH (_WIN32 && __DMC__)
|
||||
|
||||
|
||||
#ifdef __DMC__
|
||||
typedef _Complex long double complex_t;
|
||||
#else
|
||||
#ifndef IN_GCC
|
||||
#include "complex_t.h"
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Be careful not to care about sign when using dinteger_t
|
||||
//typedef uint64_t integer_t;
|
||||
typedef uint64_t dinteger_t; // use this instead of integer_t to
|
||||
// avoid conflicts with system #include's
|
||||
|
||||
// Signed and unsigned variants
|
||||
typedef int64_t sinteger_t;
|
||||
typedef uint64_t uinteger_t;
|
||||
|
||||
typedef int8_t d_int8;
|
||||
typedef uint8_t d_uns8;
|
||||
typedef int16_t d_int16;
|
||||
typedef uint16_t d_uns16;
|
||||
typedef int32_t d_int32;
|
||||
typedef uint32_t d_uns32;
|
||||
typedef int64_t d_int64;
|
||||
typedef uint64_t d_uns64;
|
||||
|
||||
typedef float d_float32;
|
||||
typedef double d_float64;
|
||||
typedef long double d_float80;
|
||||
|
||||
typedef d_uns8 d_char;
|
||||
typedef d_uns16 d_wchar;
|
||||
typedef d_uns32 d_dchar;
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
#else
|
||||
typedef long double real_t;
|
||||
#endif
|
||||
|
||||
// Modify OutBuffer::writewchar to write the correct size of wchar
|
||||
#if _WIN32
|
||||
#define writewchar writeword
|
||||
#else
|
||||
// This needs a configuration test...
|
||||
#define writewchar write4
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-complex_t.h"
|
||||
#endif
|
||||
|
||||
struct Module;
|
||||
|
||||
//typedef unsigned Loc; // file location
|
||||
struct Loc
|
||||
{
|
||||
const char *filename;
|
||||
unsigned linnum;
|
||||
|
||||
Loc()
|
||||
{
|
||||
linnum = 0;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(int x)
|
||||
{
|
||||
linnum = x;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(Module *mod, unsigned linnum);
|
||||
|
||||
char *toChars();
|
||||
bool equals(const Loc& loc);
|
||||
};
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||
// in interface vtbl[]'s
|
||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||
// in the inheritance graph multiple
|
||||
// times, only one is used
|
||||
|
||||
enum LINK
|
||||
{
|
||||
LINKdefault,
|
||||
LINKd,
|
||||
LINKc,
|
||||
LINKcpp,
|
||||
LINKwindows,
|
||||
LINKpascal,
|
||||
|
||||
#if IN_LLVM
|
||||
LINKintrinsic,
|
||||
#endif
|
||||
};
|
||||
|
||||
enum DYNCAST
|
||||
{
|
||||
DYNCAST_OBJECT,
|
||||
DYNCAST_EXPRESSION,
|
||||
DYNCAST_DSYMBOL,
|
||||
DYNCAST_TYPE,
|
||||
DYNCAST_IDENTIFIER,
|
||||
DYNCAST_TUPLE,
|
||||
};
|
||||
|
||||
enum MATCH
|
||||
{
|
||||
MATCHnomatch, // no match
|
||||
MATCHconvert, // match with conversions
|
||||
#if DMDV2
|
||||
MATCHconst, // match with conversion to const
|
||||
#endif
|
||||
MATCHexact // exact match
|
||||
};
|
||||
|
||||
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
|
||||
void vwarning(Loc loc, const char *format, va_list);
|
||||
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
|
||||
void verror(Loc loc, const char *format, va_list);
|
||||
void fatal();
|
||||
void err_nomem();
|
||||
#if IN_LLVM
|
||||
void inifile(char *argv0, const char *inifile);
|
||||
#else
|
||||
int runLINK();
|
||||
void deleteExeFile();
|
||||
int runProgram();
|
||||
void inifile(const char *argv0, const char *inifile);
|
||||
#endif
|
||||
void halt();
|
||||
#if !IN_LLVM
|
||||
void util_progress();
|
||||
#endif
|
||||
|
||||
/*** Where to send error messages ***/
|
||||
#if IN_GCC || IN_LLVM
|
||||
#define stdmsg stderr
|
||||
#else
|
||||
#define stdmsg stdout
|
||||
#endif
|
||||
|
||||
#if !IN_LLVM
|
||||
struct Dsymbol;
|
||||
struct Library;
|
||||
struct File;
|
||||
void obj_start(char *srcfile);
|
||||
void obj_end(Library *library, File *objfile);
|
||||
void obj_append(Dsymbol *s);
|
||||
void obj_write_deferred(Library *library);
|
||||
#endif
|
||||
|
||||
#endif /* DMD_MARS_H */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include "mem.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#if USE_BOEHM_GC
|
||||
// I needed to perfix the dir after upgrading to gc 7.0
|
||||
|
||||
2155
dmd2/module.c
2155
dmd2/module.c
File diff suppressed because it is too large
Load Diff
409
dmd2/module.h
409
dmd2/module.h
@@ -1,197 +1,212 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_MODULE_H
|
||||
#define DMD_MODULE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct ModuleInfoDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct ModuleDeclaration;
|
||||
struct Macro;
|
||||
struct Escape;
|
||||
struct VarDeclaration;
|
||||
struct Library;
|
||||
|
||||
// Back end
|
||||
#if IN_LLVM
|
||||
struct DValue;
|
||||
typedef DValue elem;
|
||||
#else
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node elem;
|
||||
#else
|
||||
struct elem;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Package : ScopeDsymbol
|
||||
{
|
||||
Package(Identifier *ident);
|
||||
const char *kind();
|
||||
|
||||
static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
|
||||
|
||||
Package *isPackage() { return this; }
|
||||
|
||||
virtual void semantic(Scope *sc) { }
|
||||
};
|
||||
|
||||
struct Module : Package
|
||||
{
|
||||
static Module *rootModule;
|
||||
static DsymbolTable *modules; // symbol table of all modules
|
||||
static Array amodules; // array of all modules
|
||||
static Array deferred; // deferred Dsymbol's needing semantic() run on them
|
||||
static unsigned dprogress; // progress resolving the deferred list
|
||||
static void init();
|
||||
|
||||
static ClassDeclaration *moduleinfo;
|
||||
|
||||
|
||||
const char *arg; // original argument name
|
||||
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
||||
File *srcfile; // input source file
|
||||
|
||||
File *objfile; // output object file
|
||||
File *docfile; // output doc file
|
||||
File *hdrfile; // output hdr file
|
||||
|
||||
unsigned errors; // if any errors in file
|
||||
unsigned numlines; // number of lines in source file
|
||||
int isHtml; // if it is an HTML file
|
||||
int isDocFile; // if it is a documentation input file, not D source
|
||||
int needmoduleinfo;
|
||||
#ifdef IN_GCC
|
||||
int strictlyneedmoduleinfo;
|
||||
#endif
|
||||
|
||||
int insearch;
|
||||
Identifier *searchCacheIdent;
|
||||
Dsymbol *searchCacheSymbol; // cached value of search
|
||||
int searchCacheFlags; // cached flags
|
||||
|
||||
int semanticstarted; // has semantic() been started?
|
||||
int semanticdone; // has semantic() been done?
|
||||
int root; // != 0 if this is a 'root' module,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
Module *importedFrom; // module from command line we're imported from,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
|
||||
Array *decldefs; // top level declarations for this Module
|
||||
|
||||
Array aimports; // all imported modules
|
||||
|
||||
ModuleInfoDeclaration *vmoduleinfo;
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
Array *debugidsNot; // forward referenced debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
Array *versionidsNot; // forward referenced version identifiers
|
||||
|
||||
Macro *macrotable; // document comment macros
|
||||
struct Escape *escapetable; // document comment escapes
|
||||
|
||||
int doDocComment; // enable generating doc comments for this module
|
||||
int doHdrGen; // enable generating header file for this module
|
||||
|
||||
bool safe;
|
||||
|
||||
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
|
||||
~Module();
|
||||
|
||||
static Module *load(Loc loc, Array *packages, Identifier *ident);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
void read(Loc loc); // read file
|
||||
#if IN_GCC
|
||||
void parse(bool dump_source = false); // syntactic parse
|
||||
#else
|
||||
void parse(); // syntactic parse
|
||||
#endif
|
||||
void semantic(Scope* unused_sc = NULL); // semantic analysis
|
||||
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
|
||||
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
|
||||
void inlineScan(); // scan for functions to inline
|
||||
#ifdef _DH
|
||||
void genhdrfile(); // generate D import file
|
||||
#endif
|
||||
void genobjfile(int multiobj);
|
||||
// void gensymfile();
|
||||
void gendocfile();
|
||||
int needModuleInfo();
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void deleteObjFile();
|
||||
void addDeferredSemantic(Dsymbol *s);
|
||||
void runDeferredSemantic();
|
||||
|
||||
// Back end
|
||||
|
||||
int doppelganger; // sub-module
|
||||
Symbol *cov; // private uint[] __coverage;
|
||||
unsigned *covb; // bit array of valid code line numbers
|
||||
|
||||
Symbol *sictor; // module order independent constructor
|
||||
Symbol *sctor; // module constructor
|
||||
Symbol *sdtor; // module destructor
|
||||
Symbol *stest; // module unit test
|
||||
|
||||
Symbol *sfilename; // symbol for filename
|
||||
|
||||
Symbol *massert; // module assert function
|
||||
Symbol *toModuleAssert(); // get module assert function
|
||||
|
||||
Symbol *marray; // module array bounds function
|
||||
Symbol *toModuleArray(); // get module array bounds function
|
||||
|
||||
|
||||
static Symbol *gencritsec();
|
||||
elem *toEfilename();
|
||||
elem *toEmodulename();
|
||||
|
||||
Symbol *toSymbol();
|
||||
void genmoduleinfo();
|
||||
|
||||
// LDC
|
||||
void buildTargetFiles();
|
||||
File* buildFilePath(char* forcename, const char* path, const char* ext);
|
||||
Module *isModule() { return this; }
|
||||
|
||||
bool llvmForceLogging;
|
||||
|
||||
// array ops emitted in this module already
|
||||
StringTable arrayfuncs;
|
||||
};
|
||||
|
||||
|
||||
struct ModuleDeclaration
|
||||
{
|
||||
Identifier *id;
|
||||
Array *packages; // array of Identifier's representing packages
|
||||
bool safe;
|
||||
|
||||
ModuleDeclaration(Array *packages, Identifier *id, bool safe);
|
||||
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
#endif /* DMD_MODULE_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_MODULE_H
|
||||
#define DMD_MODULE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct ModuleInfoDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct ModuleDeclaration;
|
||||
struct Macro;
|
||||
struct Escape;
|
||||
struct VarDeclaration;
|
||||
struct Library;
|
||||
|
||||
// Back end
|
||||
#if IN_LLVM
|
||||
class Ir;
|
||||
struct DValue;
|
||||
typedef DValue elem;
|
||||
namespace llvm { class Module; }
|
||||
#else
|
||||
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node elem;
|
||||
#else
|
||||
struct elem;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Package : ScopeDsymbol
|
||||
{
|
||||
Package(Identifier *ident);
|
||||
const char *kind();
|
||||
|
||||
static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
|
||||
|
||||
Package *isPackage() { return this; }
|
||||
|
||||
virtual void semantic(Scope *sc) { }
|
||||
};
|
||||
|
||||
struct Module : Package
|
||||
{
|
||||
static Module *rootModule;
|
||||
static DsymbolTable *modules; // symbol table of all modules
|
||||
static Array amodules; // array of all modules
|
||||
static Array deferred; // deferred Dsymbol's needing semantic() run on them
|
||||
static unsigned dprogress; // progress resolving the deferred list
|
||||
static void init();
|
||||
|
||||
static ClassDeclaration *moduleinfo;
|
||||
|
||||
|
||||
const char *arg; // original argument name
|
||||
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
||||
File *srcfile; // input source file
|
||||
|
||||
File *objfile; // output object file
|
||||
File *docfile; // output doc file
|
||||
File *hdrfile; // output hdr file
|
||||
|
||||
unsigned errors; // if any errors in file
|
||||
unsigned numlines; // number of lines in source file
|
||||
int isHtml; // if it is an HTML file
|
||||
int isDocFile; // if it is a documentation input file, not D source
|
||||
int needmoduleinfo;
|
||||
#ifdef IN_GCC
|
||||
int strictlyneedmoduleinfo;
|
||||
#endif
|
||||
|
||||
int selfimports; // 0: don't know, 1: does not, 2: does
|
||||
int selfImports(); // returns !=0 if module imports itself
|
||||
|
||||
int insearch;
|
||||
Identifier *searchCacheIdent;
|
||||
Dsymbol *searchCacheSymbol; // cached value of search
|
||||
int searchCacheFlags; // cached flags
|
||||
|
||||
int semanticstarted; // has semantic() been started?
|
||||
int semanticdone; // has semantic() been done?
|
||||
int root; // != 0 if this is a 'root' module,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
Module *importedFrom; // module from command line we're imported from,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
|
||||
Array *decldefs; // top level declarations for this Module
|
||||
|
||||
Array aimports; // all imported modules
|
||||
|
||||
ModuleInfoDeclaration *vmoduleinfo;
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
Array *debugidsNot; // forward referenced debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
Array *versionidsNot; // forward referenced version identifiers
|
||||
|
||||
Macro *macrotable; // document comment macros
|
||||
Escape *escapetable; // document comment escapes
|
||||
bool safe; // TRUE if module is marked as 'safe'
|
||||
|
||||
int doDocComment; // enable generating doc comments for this module
|
||||
int doHdrGen; // enable generating header file for this module
|
||||
|
||||
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
|
||||
~Module();
|
||||
|
||||
static Module *load(Loc loc, Array *packages, Identifier *ident);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
#if !IN_LLVM
|
||||
void setDocfile(); // set docfile member
|
||||
#endif
|
||||
void read(Loc loc); // read file
|
||||
#if IN_GCC
|
||||
void parse(bool dump_source = false); // syntactic parse
|
||||
#else
|
||||
void parse(); // syntactic parse
|
||||
#endif
|
||||
void semantic(Scope* unused_sc = NULL); // semantic analysis
|
||||
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
|
||||
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
|
||||
void inlineScan(); // scan for functions to inline
|
||||
#if !IN_LLVM
|
||||
void setHdrfile(); // set hdrfile member
|
||||
#endif
|
||||
#ifdef _DH
|
||||
void genhdrfile(); // generate D import file
|
||||
#endif
|
||||
// void gensymfile();
|
||||
void gendocfile();
|
||||
int needModuleInfo();
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void deleteObjFile();
|
||||
void addDeferredSemantic(Dsymbol *s);
|
||||
void runDeferredSemantic();
|
||||
int imports(Module *m);
|
||||
|
||||
// Back end
|
||||
#if IN_DMD
|
||||
int doppelganger; // sub-module
|
||||
Symbol *cov; // private uint[] __coverage;
|
||||
unsigned *covb; // bit array of valid code line numbers
|
||||
|
||||
Symbol *sictor; // module order independent constructor
|
||||
Symbol *sctor; // module constructor
|
||||
Symbol *sdtor; // module destructor
|
||||
Symbol *stest; // module unit test
|
||||
|
||||
Symbol *sfilename; // symbol for filename
|
||||
|
||||
Symbol *massert; // module assert function
|
||||
Symbol *toModuleAssert(); // get module assert function
|
||||
|
||||
Symbol *marray; // module array bounds function
|
||||
Symbol *toModuleArray(); // get module array bounds function
|
||||
|
||||
|
||||
static Symbol *gencritsec();
|
||||
elem *toEfilename();
|
||||
elem *toEmodulename();
|
||||
|
||||
Symbol *toSymbol();
|
||||
#endif
|
||||
void genmoduleinfo();
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC
|
||||
llvm::Module* genLLVMModule(Ir* sir);
|
||||
void buildTargetFiles();
|
||||
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
||||
Module *isModule() { return this; }
|
||||
|
||||
bool llvmForceLogging;
|
||||
|
||||
// array ops emitted in this module already
|
||||
StringTable arrayfuncs;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct ModuleDeclaration
|
||||
{
|
||||
Identifier *id;
|
||||
Array *packages; // array of Identifier's representing packages
|
||||
bool safe;
|
||||
|
||||
ModuleDeclaration(Array *packages, Identifier *id, bool safe);
|
||||
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
#endif /* DMD_MODULE_H */
|
||||
|
||||
1294
dmd2/mtype.c
1294
dmd2/mtype.c
File diff suppressed because it is too large
Load Diff
1705
dmd2/mtype.h
1705
dmd2/mtype.h
File diff suppressed because it is too large
Load Diff
61
dmd2/objfile.h
Normal file
61
dmd2/objfile.h
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
|
||||
#ifndef OBJFILE_H
|
||||
#define OBJFILE_H
|
||||
|
||||
#include "root.h"
|
||||
|
||||
typedef void *SymHandle;
|
||||
typedef unsigned SegOffset;
|
||||
|
||||
enum ObjFormat
|
||||
{
|
||||
NTCOFF,
|
||||
ELF
|
||||
};
|
||||
|
||||
struct ObjFile : File
|
||||
{
|
||||
ObjFile(FileName *);
|
||||
~ObjFile();
|
||||
|
||||
ObjFile *init(ObjFormat);
|
||||
|
||||
void comment(const char *); // insert comment into object file
|
||||
void modulename(const char *); // set module name
|
||||
void library(const char *); // add default library
|
||||
void startaddress(SegHandle seg, SegOffset offset); // set start address
|
||||
|
||||
// Segments
|
||||
enum SegHandle
|
||||
{ code = 1,
|
||||
data, bss
|
||||
};
|
||||
|
||||
SymHandle defineSym(const char *name, SegHandle seg, SegOffset offset);
|
||||
SymHandle externSym(const char *name);
|
||||
|
||||
SegOffset write(SegHandle seg, const void *data, unsigned nbytes);
|
||||
SegOffset writestring(SegHandle seg, char *string);
|
||||
SegOffset write8(SegHandle seg, unsigned b);
|
||||
SegOffset write16(SegHandle seg, unsigned w);
|
||||
SegOffset write32(SegHandle seg, unsigned long v);
|
||||
SegOffset write64(SegHandle seg, unsigned long long v);
|
||||
SegOffset fill0(SegHandle seg, unsigned nbytes);
|
||||
SegOffset align(SegHandle seg, unsigned size);
|
||||
SegOffset writefixup(SegHandle seg, SymHandle sym, unsigned value, int selfrelative);
|
||||
|
||||
// Non-binding hint as to how big seg will grow
|
||||
void reserve(SegHandle seg, SegOffset size);
|
||||
|
||||
// Set actual size
|
||||
void setSize(SegHandle seg, SegOffset size);
|
||||
|
||||
// Get/set offset for subsequent writes
|
||||
void setOffset(SegHandle seg, SegOffset offset);
|
||||
SegOffset getOffset(SegHandle seg);
|
||||
|
||||
SegHandle createSeg(const char *name);
|
||||
};
|
||||
|
||||
#endif
|
||||
1536
dmd2/opover.c
1536
dmd2/opover.c
File diff suppressed because it is too large
Load Diff
1862
dmd2/optimize.c
1862
dmd2/optimize.c
File diff suppressed because it is too large
Load Diff
11645
dmd2/parse.c
11645
dmd2/parse.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -70,6 +70,7 @@ struct Parser : Lexer
|
||||
Array *parseDeclDefs(int once);
|
||||
Array *parseAutoDeclarations(unsigned storageClass, unsigned char *comment);
|
||||
Array *parseBlock();
|
||||
void composeStorageClass(unsigned stc);
|
||||
Expression *parseConstraint();
|
||||
TemplateDeclaration *parseTemplateDeclaration();
|
||||
TemplateParameters *parseTemplateParameterList(int flag = 0);
|
||||
@@ -83,7 +84,7 @@ struct Parser : Lexer
|
||||
Condition *parseDebugCondition();
|
||||
Condition *parseVersionCondition();
|
||||
Condition *parseStaticIfCondition();
|
||||
FuncDeclaration *parseCtor();
|
||||
Dsymbol *parseCtor();
|
||||
PostBlitDeclaration *parsePostBlit();
|
||||
DtorDeclaration *parseDtor();
|
||||
StaticCtorDeclaration *parseStaticCtor();
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
|
||||
The D Programming Language
|
||||
Compiler Front End Source
|
||||
Copyright (c) 1999-2002, by Digital Mars
|
||||
www.digitalmars.com
|
||||
Copyright (c) 1999-2009, by Digital Mars
|
||||
http://www.digitalmars.com
|
||||
All Rights Reserved
|
||||
|
||||
|
||||
This is the source code to the front end Digital Mars D compiler.
|
||||
It covers the lexical analysis, parsing, and semantic analysis
|
||||
of the D Programming Language defined in the documents at
|
||||
www.digitalmars.com/d/
|
||||
|
||||
The optimizer, code generator, and object file generator are not part
|
||||
of this source, hence the source does not currently constitute a complete,
|
||||
compilable program. However, many people have expressed a strong interested
|
||||
in producing a D compiler with the GNU compiler sources. This release should
|
||||
enable that.
|
||||
http://www.digitalmars.com/d/
|
||||
|
||||
These sources are free, they are redistributable and modifiable
|
||||
under the terms of the GNU General Public License (attached as gpl.txt),
|
||||
or the Artistic License (attached as artistic.txt).
|
||||
|
||||
The optimizer and code generator sources are
|
||||
covered under a separate license, backendlicense.txt.
|
||||
|
||||
It does not apply to anything else distributed by Digital Mars,
|
||||
including D compiler executables.
|
||||
|
||||
|
||||
224
dmd2/root/array.c
Normal file
224
dmd2/root/array.c
Normal file
@@ -0,0 +1,224 @@
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if (defined (__SVR4) && defined (__sun))
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#if _MSC_VER || __MINGW32__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
#include "gdc_alloca.h"
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#include "port.h"
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
/********************************* Array ****************************/
|
||||
|
||||
Array::Array()
|
||||
{
|
||||
data = NULL;
|
||||
dim = 0;
|
||||
allocdim = 0;
|
||||
}
|
||||
|
||||
Array::~Array()
|
||||
{
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void Array::mark()
|
||||
{ unsigned u;
|
||||
|
||||
mem.mark(data);
|
||||
for (u = 0; u < dim; u++)
|
||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||
}
|
||||
|
||||
void Array::reserve(unsigned nentries)
|
||||
{
|
||||
//printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
|
||||
if (allocdim - dim < nentries)
|
||||
{
|
||||
allocdim = dim + nentries;
|
||||
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
|
||||
void Array::setDim(unsigned newdim)
|
||||
{
|
||||
if (dim < newdim)
|
||||
{
|
||||
reserve(newdim - dim);
|
||||
}
|
||||
dim = newdim;
|
||||
}
|
||||
|
||||
void Array::fixDim()
|
||||
{
|
||||
if (dim != allocdim)
|
||||
{ data = (void **)mem.realloc(data, dim * sizeof(*data));
|
||||
allocdim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
void Array::push(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
data[dim++] = ptr;
|
||||
}
|
||||
|
||||
void *Array::pop()
|
||||
{
|
||||
return data[--dim];
|
||||
}
|
||||
|
||||
void Array::shift(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + 1, data, dim * sizeof(*data));
|
||||
data[0] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void Array::insert(unsigned index, void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||
data[index] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
|
||||
void Array::insert(unsigned index, Array *a)
|
||||
{
|
||||
if (a)
|
||||
{ unsigned d;
|
||||
|
||||
d = a->dim;
|
||||
reserve(d);
|
||||
if (dim != index)
|
||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||
memcpy(data + index, a->data, d * sizeof(*data));
|
||||
dim += d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Append array a to this array.
|
||||
*/
|
||||
|
||||
void Array::append(Array *a)
|
||||
{
|
||||
insert(dim, a);
|
||||
}
|
||||
|
||||
void Array::remove(unsigned i)
|
||||
{
|
||||
memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
char *Array::toChars()
|
||||
{
|
||||
unsigned len;
|
||||
unsigned u;
|
||||
char **buf;
|
||||
char *str;
|
||||
char *p;
|
||||
|
||||
buf = (char **)alloca(dim * sizeof(char *));
|
||||
len = 2;
|
||||
for (u = 0; u < dim; u++)
|
||||
{
|
||||
buf[u] = ((Object *)data[u])->toChars();
|
||||
len += strlen(buf[u]) + 1;
|
||||
}
|
||||
str = (char *)mem.malloc(len);
|
||||
|
||||
str[0] = '[';
|
||||
p = str + 1;
|
||||
for (u = 0; u < dim; u++)
|
||||
{
|
||||
if (u)
|
||||
*p++ = ',';
|
||||
len = strlen(buf[u]);
|
||||
memcpy(p,buf[u],len);
|
||||
p += len;
|
||||
}
|
||||
*p++ = ']';
|
||||
*p = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
void Array::zero()
|
||||
{
|
||||
memset(data,0,dim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
void *Array::tos()
|
||||
{
|
||||
return dim ? data[dim - 1] : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
#if _WIN32
|
||||
__cdecl
|
||||
#endif
|
||||
Array_sort_compare(const void *x, const void *y)
|
||||
{
|
||||
Object *ox = *(Object **)x;
|
||||
Object *oy = *(Object **)y;
|
||||
|
||||
return ox->compare(oy);
|
||||
}
|
||||
|
||||
void Array::sort()
|
||||
{
|
||||
if (dim)
|
||||
{
|
||||
qsort(data, dim, sizeof(Object *), Array_sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
Array *Array::copy()
|
||||
{
|
||||
Array *a = new Array();
|
||||
|
||||
a->setDim(dim);
|
||||
memcpy(a->data, data, dim * sizeof(void *));
|
||||
return a;
|
||||
}
|
||||
|
||||
177
dmd2/root/async.c
Normal file
177
dmd2/root/async.c
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
#define _MT 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <process.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
static unsigned __stdcall startthread(void *p);
|
||||
|
||||
struct FileData
|
||||
{
|
||||
File *file;
|
||||
int result;
|
||||
HANDLE event;
|
||||
};
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
|
||||
HANDLE hThread;
|
||||
|
||||
size_t filesdim;
|
||||
size_t filesmax;
|
||||
FileData files[1];
|
||||
};
|
||||
|
||||
|
||||
AsyncRead *AsyncRead::create(size_t nfiles)
|
||||
{
|
||||
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
|
||||
(nfiles - 1) * sizeof(FileData));
|
||||
aw->filesmax = nfiles;
|
||||
return aw;
|
||||
}
|
||||
|
||||
void AsyncRead::addFile(File *file)
|
||||
{
|
||||
//printf("addFile(file = %p)\n", file);
|
||||
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
||||
assert(filesdim < filesmax);
|
||||
files[filesdim].file = file;
|
||||
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
ResetEvent(files[filesdim].event);
|
||||
filesdim++;
|
||||
}
|
||||
|
||||
void AsyncRead::start()
|
||||
{
|
||||
unsigned threadaddr;
|
||||
hThread = (HANDLE) _beginthreadex(NULL,
|
||||
0,
|
||||
&startthread,
|
||||
this,
|
||||
0,
|
||||
(unsigned *)&threadaddr);
|
||||
|
||||
if (hThread)
|
||||
{
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
int AsyncRead::read(size_t i)
|
||||
{
|
||||
FileData *f = &files[i];
|
||||
WaitForSingleObject(f->event, INFINITE);
|
||||
Sleep(0); // give up time slice
|
||||
return f->result;
|
||||
}
|
||||
|
||||
void AsyncRead::dispose(AsyncRead *aw)
|
||||
{
|
||||
delete aw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned __stdcall startthread(void *p)
|
||||
{
|
||||
AsyncRead *aw = (AsyncRead *)p;
|
||||
|
||||
for (size_t i = 0; i < aw->filesdim; i++)
|
||||
{ FileData *f = &aw->files[i];
|
||||
|
||||
f->result = f->file->read();
|
||||
SetEvent(f->event);
|
||||
}
|
||||
_endthreadex(EXIT_SUCCESS);
|
||||
return EXIT_SUCCESS; // if skidding
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
struct FileData
|
||||
{
|
||||
File *file;
|
||||
int result;
|
||||
//HANDLE event;
|
||||
};
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
|
||||
//HANDLE hThread;
|
||||
|
||||
size_t filesdim;
|
||||
size_t filesmax;
|
||||
FileData files[1];
|
||||
};
|
||||
|
||||
|
||||
AsyncRead *AsyncRead::create(size_t nfiles)
|
||||
{
|
||||
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
|
||||
(nfiles - 1) * sizeof(FileData));
|
||||
aw->filesmax = nfiles;
|
||||
return aw;
|
||||
}
|
||||
|
||||
void AsyncRead::addFile(File *file)
|
||||
{
|
||||
//printf("addFile(file = %p)\n", file);
|
||||
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
||||
assert(filesdim < filesmax);
|
||||
files[filesdim].file = file;
|
||||
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
//ResetEvent(files[filesdim].event);
|
||||
filesdim++;
|
||||
}
|
||||
|
||||
void AsyncRead::start()
|
||||
{
|
||||
}
|
||||
|
||||
int AsyncRead::read(size_t i)
|
||||
{
|
||||
FileData *f = &files[i];
|
||||
f->result = f->file->read();
|
||||
return f->result;
|
||||
}
|
||||
|
||||
void AsyncRead::dispose(AsyncRead *aw)
|
||||
{
|
||||
delete aw;
|
||||
}
|
||||
|
||||
#endif
|
||||
33
dmd2/root/async.h
Normal file
33
dmd2/root/async.h
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
// Copyright (c) 2009-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef ASYNC_H
|
||||
#define ASYNC_H
|
||||
|
||||
#if __DMC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
/*******************
|
||||
* Simple interface to read files asynchronously in another
|
||||
* thread.
|
||||
*/
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
482
dmd2/root/dchar.c
Normal file
482
dmd2/root/dchar.c
Normal file
@@ -0,0 +1,482 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dchar.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#if M_UNICODE
|
||||
|
||||
// Converts a char string to Unicode
|
||||
|
||||
dchar *Dchar::dup(char *p)
|
||||
{
|
||||
dchar *s;
|
||||
size_t len;
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
len = strlen(p);
|
||||
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
s[i] = (dchar)(p[i] & 0xFF);
|
||||
}
|
||||
s[len] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
dchar *Dchar::memchr(dchar *p, int c, int count)
|
||||
{
|
||||
int u;
|
||||
|
||||
for (u = 0; u < count; u++)
|
||||
{
|
||||
if (p[u] == c)
|
||||
return p + u;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if _WIN32 && __DMC__
|
||||
__declspec(naked)
|
||||
unsigned Dchar::calcHash(const dchar *str, unsigned len)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov ECX,4[ESP]
|
||||
mov EDX,8[ESP]
|
||||
xor EAX,EAX
|
||||
test EDX,EDX
|
||||
je L92
|
||||
|
||||
LC8: cmp EDX,1
|
||||
je L98
|
||||
cmp EDX,2
|
||||
je LAE
|
||||
|
||||
add EAX,[ECX]
|
||||
// imul EAX,EAX,025h
|
||||
lea EAX,[EAX][EAX*8]
|
||||
add ECX,4
|
||||
sub EDX,2
|
||||
jmp LC8
|
||||
|
||||
L98: mov DX,[ECX]
|
||||
and EDX,0FFFFh
|
||||
add EAX,EDX
|
||||
ret
|
||||
|
||||
LAE: add EAX,[ECX]
|
||||
L92: ret
|
||||
}
|
||||
}
|
||||
#else
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash += *(const uint16_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash += *(const uint32_t *)str;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash += *(const uint32_t *)str;
|
||||
hash *= 37;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash += *(const uint16_t *)str | 0x20;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash += *(const uint32_t *)str | 0x200020;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash += *(const uint32_t *)str | 0x200020;
|
||||
hash *= 37;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif MCBS
|
||||
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
hash += *(const uint16_t *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
hash += (*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
hash += *(const uint32_t *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif UTF8
|
||||
|
||||
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
|
||||
|
||||
char Dchar::mblen[256] =
|
||||
{
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
|
||||
};
|
||||
|
||||
dchar *Dchar::dec(dchar *pstart, dchar *p)
|
||||
{
|
||||
while ((p[-1] & 0xC0) == 0x80)
|
||||
p--;
|
||||
return p;
|
||||
}
|
||||
|
||||
int Dchar::get(dchar *p)
|
||||
{
|
||||
unsigned c;
|
||||
unsigned char *q = (unsigned char *)p;
|
||||
|
||||
c = q[0];
|
||||
switch (mblen[c])
|
||||
{
|
||||
case 2:
|
||||
c = ((c - 0xC0) << 6) |
|
||||
(q[1] - 0x80);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
c = ((c - 0xE0) << 12) |
|
||||
((q[1] - 0x80) << 6) |
|
||||
(q[2] - 0x80);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
c = ((c - 0xF0) << 18) |
|
||||
((q[1] - 0x80) << 12) |
|
||||
((q[2] - 0x80) << 6) |
|
||||
(q[3] - 0x80);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
c = ((c - 0xF8) << 24) |
|
||||
((q[1] - 0x80) << 18) |
|
||||
((q[2] - 0x80) << 12) |
|
||||
((q[3] - 0x80) << 6) |
|
||||
(q[4] - 0x80);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
c = ((c - 0xFC) << 30) |
|
||||
((q[1] - 0x80) << 24) |
|
||||
((q[2] - 0x80) << 18) |
|
||||
((q[3] - 0x80) << 12) |
|
||||
((q[4] - 0x80) << 6) |
|
||||
(q[5] - 0x80);
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
dchar *Dchar::put(dchar *p, unsigned c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
*p++ = c;
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
p[0] = 0xC0 + (c >> 6);
|
||||
p[1] = 0x80 + (c & 0x3F);
|
||||
p += 2;
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
p[0] = 0xE0 + (c >> 12);
|
||||
p[1] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[2] = 0x80 + (c & 0x3F);
|
||||
p += 3;
|
||||
}
|
||||
else if (c <= 0x1FFFFF)
|
||||
{
|
||||
p[0] = 0xF0 + (c >> 18);
|
||||
p[1] = 0x80 + ((c >> 12) & 0x3F);
|
||||
p[2] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[3] = 0x80 + (c & 0x3F);
|
||||
p += 4;
|
||||
}
|
||||
else if (c <= 0x3FFFFFF)
|
||||
{
|
||||
p[0] = 0xF8 + (c >> 24);
|
||||
p[1] = 0x80 + ((c >> 18) & 0x3F);
|
||||
p[2] = 0x80 + ((c >> 12) & 0x3F);
|
||||
p[3] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[4] = 0x80 + (c & 0x3F);
|
||||
p += 5;
|
||||
}
|
||||
else if (c <= 0x7FFFFFFF)
|
||||
{
|
||||
p[0] = 0xFC + (c >> 30);
|
||||
p[1] = 0x80 + ((c >> 24) & 0x3F);
|
||||
p[2] = 0x80 + ((c >> 18) & 0x3F);
|
||||
p[3] = 0x80 + ((c >> 12) & 0x3F);
|
||||
p[4] = 0x80 + ((c >> 6) & 0x3F);
|
||||
p[5] = 0x80 + (c & 0x3F);
|
||||
p += 6;
|
||||
}
|
||||
else
|
||||
assert(0); // not a UCS-4 character
|
||||
return p;
|
||||
}
|
||||
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint16_t *)str;
|
||||
#else
|
||||
hash += str[0] * 256 + str[1];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += (*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2];
|
||||
#else
|
||||
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint32_t *)str;
|
||||
#else
|
||||
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
||||
#endif
|
||||
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // ascii
|
||||
|
||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint16_t *)str;
|
||||
#else
|
||||
hash += str[0] * 256 + str[1];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += (*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2];
|
||||
#else
|
||||
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
||||
#endif
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
#if __I86__
|
||||
hash += *(const uint32_t *)str;
|
||||
#else
|
||||
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
||||
#endif
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(const uint8_t *)str | 0x20;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
hash += *(const uint16_t *)str | 0x2020;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
hash += ((*(const uint16_t *)str << 8) +
|
||||
((const uint8_t *)str)[2]) | 0x202020;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
hash += *(const uint32_t *)str | 0x20202020;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
// Print out values to hardcode into Dchar::mblen[]
|
||||
int c;
|
||||
int s;
|
||||
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
s = 1;
|
||||
if (c >= 0xC0 && c <= 0xDF)
|
||||
s = 2;
|
||||
if (c >= 0xE0 && c <= 0xEF)
|
||||
s = 3;
|
||||
if (c >= 0xF0 && c <= 0xF7)
|
||||
s = 4;
|
||||
if (c >= 0xF8 && c <= 0xFB)
|
||||
s = 5;
|
||||
if (c >= 0xFC && c <= 0xFD)
|
||||
s = 6;
|
||||
|
||||
printf("%d", s);
|
||||
if ((c & 15) == 15)
|
||||
printf(",\n");
|
||||
else
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
194
dmd2/root/dchar.h
Normal file
194
dmd2/root/dchar.h
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
|
||||
#ifndef DCHAR_H
|
||||
#define DCHAR_H
|
||||
|
||||
#if __GNUC__ && !_WIN32
|
||||
#include "gnuc.h"
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
// Disable useless warnings about unreferenced functions
|
||||
#pragma warning (disable : 4514)
|
||||
#endif
|
||||
|
||||
//#include "root.h"
|
||||
typedef size_t hash_t;
|
||||
|
||||
#undef TEXT
|
||||
|
||||
// NOTE: All functions accepting pointer arguments must not be NULL
|
||||
|
||||
#if M_UNICODE
|
||||
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
typedef wchar_t dchar;
|
||||
#define TEXT(x) L##x
|
||||
|
||||
#define Dchar_mbmax 1
|
||||
|
||||
struct Dchar
|
||||
{
|
||||
static dchar *inc(dchar *p) { return p + 1; }
|
||||
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
|
||||
static int len(const dchar *p) { return wcslen(p); }
|
||||
static dchar get(dchar *p) { return *p; }
|
||||
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
|
||||
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
|
||||
static int cmp(dchar *s1, dchar *s2)
|
||||
{
|
||||
#if __DMC__
|
||||
if (!*s1 && !*s2) // wcscmp is broken
|
||||
return 0;
|
||||
#endif
|
||||
return wcscmp(s1, s2);
|
||||
#if 0
|
||||
return (*s1 == *s2)
|
||||
? wcscmp(s1, s2)
|
||||
: ((int)*s1 - (int)*s2);
|
||||
#endif
|
||||
}
|
||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
|
||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||
static int isAlpha(dchar c) { return iswalpha(c); }
|
||||
static int isUpper(dchar c) { return iswupper(c); }
|
||||
static int isLower(dchar c) { return iswlower(c); }
|
||||
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
||||
static int isLocaleLower(dchar c) { return isLower(c); }
|
||||
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
|
||||
static int toLower(dchar *p) { return toLower(*p); }
|
||||
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
|
||||
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
|
||||
static dchar *dup(char *p);
|
||||
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
|
||||
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
|
||||
static dchar *memchr(dchar *p, int c, int count);
|
||||
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
|
||||
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
|
||||
static hash_t calcHash(const dchar *str, size_t len);
|
||||
|
||||
// Case insensitive versions
|
||||
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
|
||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
|
||||
static hash_t icalcHash(const dchar *str, size_t len);
|
||||
};
|
||||
|
||||
#elif MCBS
|
||||
|
||||
#include <limits.h>
|
||||
#include <mbstring.h>
|
||||
|
||||
typedef char dchar;
|
||||
#define TEXT(x) x
|
||||
|
||||
#define Dchar_mbmax MB_LEN_MAX
|
||||
|
||||
#elif UTF8
|
||||
|
||||
typedef char dchar;
|
||||
#define TEXT(x) x
|
||||
|
||||
#define Dchar_mbmax 6
|
||||
|
||||
struct Dchar
|
||||
{
|
||||
static char mblen[256];
|
||||
|
||||
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
|
||||
static dchar *dec(dchar *pstart, dchar *p);
|
||||
static int len(const dchar *p) { return strlen(p); }
|
||||
static int get(dchar *p);
|
||||
static int getprev(dchar *pstart, dchar *p)
|
||||
{ return *dec(pstart, p) & 0xFF; }
|
||||
static dchar *put(dchar *p, unsigned c);
|
||||
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
|
||||
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
|
||||
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
|
||||
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
||||
static int isLocaleLower(dchar c) { return isLower(c); }
|
||||
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
|
||||
static int toLower(dchar *p) { return toLower(*p); }
|
||||
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
|
||||
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
||||
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
||||
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
||||
static dchar *memchr(dchar *p, int c, int count)
|
||||
{ return (dchar *)::memchr(p, c, count); }
|
||||
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
||||
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
||||
static hash_t calcHash(const dchar *str, size_t len);
|
||||
|
||||
// Case insensitive versions
|
||||
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
|
||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
typedef char dchar;
|
||||
#define TEXT(x) x
|
||||
|
||||
#define Dchar_mbmax 1
|
||||
|
||||
struct Dchar
|
||||
{
|
||||
static dchar *inc(dchar *p) { return p + 1; }
|
||||
static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
|
||||
static int len(const dchar *p) { return strlen(p); }
|
||||
static int get(dchar *p) { return *p & 0xFF; }
|
||||
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
|
||||
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
|
||||
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||
#ifndef GCC_SAFE_DMD
|
||||
static int isAlpha(dchar c) { return isalpha(c); }
|
||||
static int isUpper(dchar c) { return isupper(c); }
|
||||
static int isLower(dchar c) { return islower(c); }
|
||||
static int isLocaleUpper(dchar c) { return isupper(c); }
|
||||
static int isLocaleLower(dchar c) { return islower(c); }
|
||||
static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
|
||||
static int toLower(dchar *p) { return toLower(*p); }
|
||||
static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
|
||||
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
||||
#endif
|
||||
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
||||
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
||||
static dchar *memchr(dchar *p, int c, int count)
|
||||
{ return (dchar *)::memchr(p, c, count); }
|
||||
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
||||
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
||||
static hash_t calcHash(const dchar *str, size_t len);
|
||||
|
||||
// Case insensitive versions
|
||||
#ifdef __GNUC__
|
||||
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
|
||||
#else
|
||||
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
|
||||
#endif
|
||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
|
||||
static hash_t icalcHash(const dchar *str, size_t len);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
55
dmd2/root/gnuc.c
Normal file
55
dmd2/root/gnuc.c
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
// Put functions in here missing from gnu C
|
||||
|
||||
#include "gnuc.h"
|
||||
|
||||
int memicmp(const char *s1, const char *s2, int n)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{ char c1 = s1[i];
|
||||
char c2 = s2[i];
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
if ('A' <= c1 && c1 <= 'Z')
|
||||
c1 += 'a' - 'A';
|
||||
if ('A' <= c2 && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (;;)
|
||||
{ char c1 = *s1;
|
||||
char c2 = *s2;
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
if ('A' <= c1 && c1 <= 'Z')
|
||||
c1 += 'a' - 'A';
|
||||
if ('A' <= c2 && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
if (!c1)
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
8
dmd2/root/gnuc.h
Normal file
8
dmd2/root/gnuc.h
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#ifndef _GNUC_H
|
||||
#define _GNUC_H 1
|
||||
|
||||
int memicmp(const char *s1, const char *s2, int n);
|
||||
int stricmp(const char *s1, const char *s2);
|
||||
|
||||
#endif
|
||||
63
dmd2/root/lstring.c
Normal file
63
dmd2/root/lstring.c
Normal file
@@ -0,0 +1,63 @@
|
||||
// lstring.c
|
||||
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dchar.h"
|
||||
#include "rmem.h"
|
||||
#include "lstring.h"
|
||||
|
||||
#ifdef _MSC_VER // prevent compiler internal crash
|
||||
Lstring Lstring::zero;
|
||||
#else
|
||||
Lstring Lstring::zero = LSTRING_EMPTY();
|
||||
#endif
|
||||
|
||||
Lstring *Lstring::ctor(const dchar *p, unsigned length)
|
||||
{
|
||||
Lstring *s;
|
||||
|
||||
s = alloc(length);
|
||||
memcpy(s->string, p, length * sizeof(dchar));
|
||||
return s;
|
||||
}
|
||||
|
||||
Lstring *Lstring::alloc(unsigned length)
|
||||
{
|
||||
Lstring *s;
|
||||
|
||||
s = (Lstring *)mem.malloc(size(length));
|
||||
s->length = length;
|
||||
s->string[length] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
Lstring *Lstring::append(const Lstring *s)
|
||||
{
|
||||
Lstring *t;
|
||||
|
||||
if (!s->length)
|
||||
return this;
|
||||
t = alloc(length + s->length);
|
||||
memcpy(t->string, string, length * sizeof(dchar));
|
||||
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
|
||||
return t;
|
||||
}
|
||||
|
||||
Lstring *Lstring::substring(int start, int end)
|
||||
{
|
||||
Lstring *t;
|
||||
|
||||
if (start == end)
|
||||
return &zero;
|
||||
t = alloc(end - start);
|
||||
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
|
||||
return t;
|
||||
}
|
||||
72
dmd2/root/lstring.h
Normal file
72
dmd2/root/lstring.h
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
// lstring.h
|
||||
// length-prefixed strings
|
||||
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef LSTRING_H
|
||||
#define LSTRING_H 1
|
||||
|
||||
#include "dchar.h"
|
||||
|
||||
struct Lstring
|
||||
{
|
||||
unsigned length;
|
||||
|
||||
// Disable warning about nonstandard extension
|
||||
#pragma warning (disable : 4200)
|
||||
dchar string[];
|
||||
|
||||
static Lstring zero; // 0 length string
|
||||
|
||||
// No constructors because we want to be able to statically
|
||||
// initialize Lstring's, and Lstrings are of variable size.
|
||||
|
||||
#if M_UNICODE
|
||||
#define LSTRING(p,length) { length, L##p }
|
||||
#else
|
||||
#define LSTRING(p,length) { length, p }
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
#define LSTRING_EMPTY() { 0 }
|
||||
#else
|
||||
#define LSTRING_EMPTY() LSTRING("", 0)
|
||||
#endif
|
||||
|
||||
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
|
||||
static Lstring *ctor(const dchar *p, unsigned length);
|
||||
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
|
||||
static Lstring *alloc(unsigned length);
|
||||
Lstring *clone();
|
||||
|
||||
unsigned len() { return length; }
|
||||
|
||||
dchar *toDchars() { return string; }
|
||||
|
||||
hash_t hash() { return Dchar::calcHash(string, length); }
|
||||
hash_t ihash() { return Dchar::icalcHash(string, length); }
|
||||
|
||||
static int cmp(const Lstring *s1, const Lstring *s2)
|
||||
{
|
||||
int c = s2->length - s1->length;
|
||||
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
|
||||
}
|
||||
|
||||
static int icmp(const Lstring *s1, const Lstring *s2)
|
||||
{
|
||||
int c = s2->length - s1->length;
|
||||
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
|
||||
}
|
||||
|
||||
Lstring *append(const Lstring *s);
|
||||
Lstring *substring(int start, int end);
|
||||
};
|
||||
|
||||
#endif
|
||||
100
dmd2/root/man.c
Normal file
100
dmd2/root/man.c
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 2008-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#pragma comment(lib,"shell32.lib")
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if linux || __FreeBSD__ || __sun&&__SVR4
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
pid_t childpid;
|
||||
const char *args[3];
|
||||
|
||||
char *browser = getenv("BROWSER");
|
||||
if (browser)
|
||||
browser = strdup(browser);
|
||||
else
|
||||
browser = "x-www-browser";
|
||||
|
||||
args[0] = browser;
|
||||
args[1] = url;
|
||||
args[2] = NULL;
|
||||
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
execvp(args[0], (char**)args);
|
||||
perror(args[0]); // failed to execute
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if __APPLE__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void browse(const char *url)
|
||||
{
|
||||
pid_t childpid;
|
||||
const char *args[5];
|
||||
|
||||
char *browser = getenv("BROWSER");
|
||||
if (browser)
|
||||
{ browser = strdup(browser);
|
||||
args[0] = browser;
|
||||
args[1] = url;
|
||||
args[2] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
|
||||
args[0] = "open";
|
||||
args[1] = "-a";
|
||||
args[2] = "/Applications/Safari.app";
|
||||
args[3] = url;
|
||||
args[4] = NULL;
|
||||
}
|
||||
|
||||
childpid = fork();
|
||||
if (childpid == 0)
|
||||
{
|
||||
execvp(args[0], (char**)args);
|
||||
perror(args[0]); // failed to execute
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
759
dmd2/root/port.c
Normal file
759
dmd2/root/port.c
Normal file
@@ -0,0 +1,759 @@
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
#include "port.h"
|
||||
#if __DMC__
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <fp.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = INFINITY;
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
long double Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return ::isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return ::isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::isfinite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::fpclassify(r) == FP_INFINITE);
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return ::signbit(r);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
return ::strupr(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
// Disable useless warnings about unreferenced functions
|
||||
#pragma warning (disable : 4514)
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits> // for std::numeric_limits
|
||||
|
||||
static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
|
||||
//static unsigned long nanarray[2] = {0,0x7FF80000 };
|
||||
double Port::nan = (*(double *)nanarray);
|
||||
|
||||
//static unsigned long infinityarray[2] = {0,0x7FF00000 };
|
||||
static double zero = 0;
|
||||
double Port::infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
long double Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
Port::infinity = std::numeric_limits<long double>::infinity();
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return ::_isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return ::_isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* MSVC doesn't have 80 bit long doubles
|
||||
*/
|
||||
return isSignallingNan((double) r);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::_finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&(r))[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
if (y == 0)
|
||||
return 1; // even if x is NAN
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
unsigned _int64 number = 0;
|
||||
int c;
|
||||
int error;
|
||||
#define ULLONG_MAX ((unsigned _int64)~0I64)
|
||||
|
||||
while (isspace(*p)) /* skip leading white space */
|
||||
p++;
|
||||
if (*p == '+')
|
||||
p++;
|
||||
switch (base)
|
||||
{ case 0:
|
||||
base = 10; /* assume decimal base */
|
||||
if (*p == '0')
|
||||
{ base = 8; /* could be octal */
|
||||
p++;
|
||||
switch (*p)
|
||||
{ case 'x':
|
||||
case 'X':
|
||||
base = 16; /* hex */
|
||||
p++;
|
||||
break;
|
||||
#if BINARY
|
||||
case 'b':
|
||||
case 'B':
|
||||
base = 2; /* binary */
|
||||
p++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16: /* skip over '0x' and '0X' */
|
||||
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
|
||||
p += 2;
|
||||
break;
|
||||
#if BINARY
|
||||
case 2: /* skip over '0b' and '0B' */
|
||||
if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
|
||||
p += 2;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
error = 0;
|
||||
for (;;)
|
||||
{ c = *p;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c = (c & ~0x20) - ('A' - 10);
|
||||
else /* unrecognized character */
|
||||
break;
|
||||
if (c >= base) /* not in number base */
|
||||
break;
|
||||
if ((ULLONG_MAX - c) / base < number)
|
||||
error = 1;
|
||||
number = number * base + c;
|
||||
p++;
|
||||
}
|
||||
if (pend)
|
||||
*pend = (char *)p;
|
||||
if (error)
|
||||
{ number = ULLONG_MAX;
|
||||
errno = ERANGE;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64toa(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64tow(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{ double d;
|
||||
|
||||
if ((__int64) ull < 0)
|
||||
{
|
||||
// MSVC doesn't implement the conversion
|
||||
d = (double) (__int64)(ull - 0x8000000000000000i64);
|
||||
d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
|
||||
}
|
||||
else
|
||||
d = (double)(__int64)ull;
|
||||
return d;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
return ::strupr(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__
|
||||
|
||||
#include <math.h>
|
||||
#if linux
|
||||
#include <bits/nan.h>
|
||||
#include <bits/mathdef.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
long double Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile long double foo;
|
||||
foo = NAN;
|
||||
if (signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
|
||||
#if __FreeBSD__
|
||||
// LDBL_MAX comes out as infinity. Fix.
|
||||
static unsigned char x[sizeof(long double)] =
|
||||
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
|
||||
Port::ldbl_max = *(long double *)&x[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#undef isinf
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return fpclassify(r) == FP_INFINITE;
|
||||
#else
|
||||
return ::isinf(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if __sun&&__SVR4
|
||||
|
||||
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <ieeefp.h>
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
long double Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile long double foo;
|
||||
foo = NAN;
|
||||
if (signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return isinf(r);
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
|
||||
#include <math.h>
|
||||
#include <bits/nan.h>
|
||||
#include <bits/mathdef.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
long double Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
#include "d-gcc-real.h"
|
||||
extern "C" bool real_isnan (const real_t *);
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
Port::infinity = real_t::getinfinity();
|
||||
Port::nan = real_t::getnan(real_t::LongDouble);
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return real_isnan(&r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#undef isinf
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return ::isinf(r);
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
78
dmd2/root/port.h
Normal file
78
dmd2/root/port.h
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
|
||||
// Portable wrapper around compiler/system specific things.
|
||||
// The idea is to minimize #ifdef's in the app code.
|
||||
|
||||
#ifndef TYPEDEFS
|
||||
#define TYPEDEFS
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#if _MSC_VER
|
||||
typedef __int64 longlong;
|
||||
typedef unsigned __int64 ulonglong;
|
||||
|
||||
// According to VC 8.0 docs, long double is the same as double
|
||||
#define strtold strtod
|
||||
#define strtof strtod
|
||||
|
||||
#else
|
||||
typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef double d_time;
|
||||
|
||||
struct Port
|
||||
{
|
||||
static double nan;
|
||||
static double infinity;
|
||||
static double dbl_max;
|
||||
static double dbl_min;
|
||||
static long double ldbl_max;
|
||||
|
||||
#if __GNUC__
|
||||
// These conflict with macros in math.h, should rename them
|
||||
#undef isnan
|
||||
#undef isfinite
|
||||
#undef isinfinity
|
||||
#undef signbit
|
||||
#endif
|
||||
static int isNan(double);
|
||||
static int isNan(long double);
|
||||
|
||||
static int isSignallingNan(double);
|
||||
static int isSignallingNan(long double);
|
||||
|
||||
static int isFinite(double);
|
||||
static int isInfinity(double);
|
||||
static int Signbit(double);
|
||||
|
||||
static double floor(double);
|
||||
static double pow(double x, double y);
|
||||
|
||||
static ulonglong strtoull(const char *p, char **pend, int base);
|
||||
|
||||
static char *ull_to_string(char *buffer, ulonglong ull);
|
||||
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
|
||||
|
||||
// Convert ulonglong to double
|
||||
static double ull_to_double(ulonglong ull);
|
||||
|
||||
// Get locale-dependent list separator
|
||||
static const char *list_separator();
|
||||
static const wchar_t *wlist_separator();
|
||||
|
||||
static char *strupr(char *);
|
||||
};
|
||||
|
||||
#endif
|
||||
278
dmd2/root/response.c
Normal file
278
dmd2/root/response.c
Normal file
@@ -0,0 +1,278 @@
|
||||
// Copyright (C) 1990-1998 by Symantec
|
||||
// Copyright (C) 2000-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// http://www.digitalmars.com
|
||||
// Written by Walter Bright
|
||||
/*
|
||||
* This source file is made available for personal use
|
||||
* only. The license is in /dmd/src/dmd/backendlicense.txt
|
||||
* For any other uses, please contact Digital Mars.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !__DMC__
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <tchar.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
/*********************************
|
||||
* #include <stdlib.h>
|
||||
* int response_expand(int *pargc,char ***pargv);
|
||||
*
|
||||
* Expand any response files in command line.
|
||||
* Response files are arguments that look like:
|
||||
* @NAME
|
||||
* The name is first searched for in the environment. If it is not
|
||||
* there, it is searched for as a file name.
|
||||
* Arguments are separated by spaces, tabs, or newlines. These can be
|
||||
* imbedded within arguments by enclosing the argument in '' or "".
|
||||
* Recursively expands nested response files.
|
||||
*
|
||||
* To use, put the line:
|
||||
* response_expand(&argc,&argv);
|
||||
* as the first executable statement in main(int argc, char **argv).
|
||||
* argc and argv are adjusted to be the new command line arguments
|
||||
* after response file expansion.
|
||||
*
|
||||
* Digital Mars's MAKE program can be notified that a program can accept
|
||||
* long command lines via environment variables by preceding the rule
|
||||
* line for the program with a *.
|
||||
*
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure (argc, argv unchanged)
|
||||
*/
|
||||
|
||||
struct Narg
|
||||
{
|
||||
int argc; /* arg count */
|
||||
int argvmax; /* dimension of nargv[] */
|
||||
char **argv;
|
||||
};
|
||||
|
||||
static int addargp(struct Narg *n, char *p)
|
||||
{
|
||||
/* The 2 is to always allow room for a NULL argp at the end */
|
||||
if (n->argc + 2 >= n->argvmax)
|
||||
{
|
||||
n->argvmax = n->argc + 2;
|
||||
n->argv = (char **) realloc(n->argv,n->argvmax * sizeof(char *));
|
||||
if (!n->argv)
|
||||
return 1;
|
||||
}
|
||||
n->argv[n->argc++] = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int response_expand(int *pargc, char ***pargv)
|
||||
{
|
||||
struct Narg n;
|
||||
int i;
|
||||
char *cp;
|
||||
int recurse = 0;
|
||||
|
||||
n.argc = 0;
|
||||
n.argvmax = 0; /* dimension of n.argv[] */
|
||||
n.argv = NULL;
|
||||
for(i=0; i<*pargc; ++i)
|
||||
{
|
||||
cp = (*pargv)[i];
|
||||
if (*cp == '@')
|
||||
{
|
||||
char *buffer;
|
||||
char *bufend;
|
||||
char *p;
|
||||
|
||||
cp++;
|
||||
p = getenv(cp);
|
||||
if (p)
|
||||
{
|
||||
buffer = strdup(p);
|
||||
if (!buffer)
|
||||
goto noexpand;
|
||||
bufend = buffer + strlen(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
long length;
|
||||
int fd;
|
||||
int nread;
|
||||
size_t len;
|
||||
|
||||
#if __DMC__
|
||||
length = filesize(cp);
|
||||
#else
|
||||
struct stat statbuf;
|
||||
if (stat(cp, &statbuf))
|
||||
goto noexpand;
|
||||
length = statbuf.st_size;
|
||||
#endif
|
||||
if (length & 0xF0000000) /* error or file too big */
|
||||
goto noexpand;
|
||||
len = length;
|
||||
buffer = (char *)malloc(len + 1);
|
||||
if (!buffer)
|
||||
goto noexpand;
|
||||
bufend = &buffer[len];
|
||||
/* Read file into buffer */
|
||||
#if _WIN32
|
||||
fd = open(cp,O_RDONLY|O_BINARY);
|
||||
#else
|
||||
fd = open(cp,O_RDONLY);
|
||||
#endif
|
||||
if (fd == -1)
|
||||
goto noexpand;
|
||||
nread = read(fd,buffer,len);
|
||||
close(fd);
|
||||
|
||||
if (nread != len)
|
||||
goto noexpand;
|
||||
}
|
||||
|
||||
// The logic of this should match that in setargv()
|
||||
|
||||
for (p = buffer; p < bufend; p++)
|
||||
{
|
||||
char *d;
|
||||
char c,lastc;
|
||||
unsigned char instring;
|
||||
int num_slashes,non_slashes;
|
||||
|
||||
switch (*p)
|
||||
{
|
||||
case 26: /* ^Z marks end of file */
|
||||
goto L2;
|
||||
|
||||
case 0xD:
|
||||
case 0:
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
continue; // scan to start of argument
|
||||
|
||||
case '@':
|
||||
recurse = 1;
|
||||
default: /* start of new argument */
|
||||
if (addargp(&n,p))
|
||||
goto noexpand;
|
||||
instring = 0;
|
||||
c = 0;
|
||||
num_slashes = 0;
|
||||
for (d = p; 1; p++)
|
||||
{
|
||||
lastc = c;
|
||||
if (p >= bufend)
|
||||
goto Lend;
|
||||
c = *p;
|
||||
switch (c)
|
||||
{
|
||||
case '"':
|
||||
/*
|
||||
Yes this looks strange,but this is so that we are
|
||||
MS Compatible, tests have shown that:
|
||||
\\\\"foo bar" gets passed as \\foo bar
|
||||
\\\\foo gets passed as \\\\foo
|
||||
\\\"foo gets passed as \"foo
|
||||
and \"foo gets passed as "foo in VC!
|
||||
*/
|
||||
non_slashes = num_slashes % 2;
|
||||
num_slashes = num_slashes / 2;
|
||||
for (; num_slashes > 0; num_slashes--)
|
||||
{
|
||||
d--;
|
||||
*d = '\0';
|
||||
}
|
||||
|
||||
if (non_slashes)
|
||||
{
|
||||
*(d-1) = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
instring ^= 1;
|
||||
}
|
||||
break;
|
||||
case 26:
|
||||
Lend:
|
||||
*d = 0; // terminate argument
|
||||
goto L2;
|
||||
|
||||
case 0xD: // CR
|
||||
c = lastc;
|
||||
continue; // ignore
|
||||
|
||||
case '@':
|
||||
recurse = 1;
|
||||
goto Ladd;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (!instring)
|
||||
{
|
||||
case '\n':
|
||||
case 0:
|
||||
*d = 0; // terminate argument
|
||||
goto Lnextarg;
|
||||
}
|
||||
default:
|
||||
Ladd:
|
||||
if (c == '\\')
|
||||
num_slashes++;
|
||||
else
|
||||
num_slashes = 0;
|
||||
*d++ = c;
|
||||
break;
|
||||
}
|
||||
#ifdef _MBCS
|
||||
if (_istlead (c)) {
|
||||
*d++ = *++p;
|
||||
if (*(d - 1) == '\0') {
|
||||
d--;
|
||||
goto Lnextarg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
Lnextarg:
|
||||
;
|
||||
}
|
||||
L2:
|
||||
;
|
||||
}
|
||||
else if (addargp(&n,(*pargv)[i]))
|
||||
goto noexpand;
|
||||
}
|
||||
n.argv[n.argc] = NULL;
|
||||
if (recurse)
|
||||
{
|
||||
/* Recursively expand @filename */
|
||||
if (response_expand(&n.argc,&n.argv))
|
||||
goto noexpand;
|
||||
}
|
||||
*pargc = n.argc;
|
||||
*pargv = n.argv;
|
||||
return 0; /* success */
|
||||
|
||||
noexpand: /* error */
|
||||
free(n.argv);
|
||||
/* BUG: any file buffers are not free'd */
|
||||
return 1;
|
||||
}
|
||||
143
dmd2/root/rmem.c
Normal file
143
dmd2/root/rmem.c
Normal file
@@ -0,0 +1,143 @@
|
||||
|
||||
/* Copyright (c) 2000 Digital Mars */
|
||||
/* All Rights Reserved */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
|
||||
#include "../root/rmem.h"
|
||||
#else
|
||||
#include "rmem.h"
|
||||
#endif
|
||||
|
||||
/* This implementation of the storage allocator uses the standard C allocation package.
|
||||
*/
|
||||
|
||||
Mem mem;
|
||||
|
||||
void Mem::init()
|
||||
{
|
||||
}
|
||||
|
||||
char *Mem::strdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (s)
|
||||
{
|
||||
p = ::strdup(s);
|
||||
if (p)
|
||||
return p;
|
||||
error();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *Mem::malloc(size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::calloc(size_t size, size_t n)
|
||||
{ void *p;
|
||||
|
||||
if (!size || !n)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::calloc(size, n);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::realloc(void *p, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
{ if (p)
|
||||
{ ::free(p);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
else if (!p)
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
else
|
||||
{
|
||||
p = ::realloc(p, size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::free(void *p)
|
||||
{
|
||||
if (p)
|
||||
::free(p);
|
||||
}
|
||||
|
||||
void *Mem::mallocdup(void *o, size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
else
|
||||
memcpy(p,o,size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::error()
|
||||
{
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void Mem::fullcollect()
|
||||
{
|
||||
}
|
||||
|
||||
void Mem::mark(void *pointer)
|
||||
{
|
||||
(void) pointer; // necessary for VC /W4
|
||||
}
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
void *p = malloc(m_size);
|
||||
if (p)
|
||||
return p;
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
return p;
|
||||
}
|
||||
|
||||
void operator delete(void *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
51
dmd2/root/rmem.h
Normal file
51
dmd2/root/rmem.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2000-2001 by Chromium Communications
|
||||
// All Rights Reserved
|
||||
|
||||
#ifndef ROOT_MEM_H
|
||||
#define ROOT_MEM_H
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
|
||||
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
|
||||
|
||||
struct GC; // thread specific allocator
|
||||
|
||||
struct Mem
|
||||
{
|
||||
GC *gc; // pointer to our thread specific allocator
|
||||
Mem() { gc = NULL; }
|
||||
|
||||
void init();
|
||||
|
||||
// Derive from Mem to get these storage allocators instead of global new/delete
|
||||
void * operator new(size_t m_size);
|
||||
void * operator new(size_t m_size, Mem *mem);
|
||||
void * operator new(size_t m_size, GC *gc);
|
||||
void operator delete(void *p);
|
||||
|
||||
void * operator new[](size_t m_size);
|
||||
void operator delete[](void *p);
|
||||
|
||||
char *strdup(const char *s);
|
||||
void *malloc(size_t size);
|
||||
void *malloc_uncollectable(size_t size);
|
||||
void *calloc(size_t size, size_t n);
|
||||
void *realloc(void *p, size_t size);
|
||||
void free(void *p);
|
||||
void free_uncollectable(void *p);
|
||||
void *mallocdup(void *o, size_t size);
|
||||
void error();
|
||||
void check(void *p); // validate pointer
|
||||
void fullcollect(); // do full garbage collection
|
||||
void fullcollectNoStack(); // do full garbage collection, no scan stack
|
||||
void mark(void *pointer);
|
||||
void addroots(char* pStart, char* pEnd);
|
||||
void removeroots(char* pStart);
|
||||
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
|
||||
void setStackBottom(void *bottom);
|
||||
GC *getThreadGC(); // get apartment allocator for this thread
|
||||
};
|
||||
|
||||
extern Mem mem;
|
||||
|
||||
#endif /* ROOT_MEM_H */
|
||||
1948
dmd2/root/root.c
Normal file
1948
dmd2/root/root.c
Normal file
File diff suppressed because it is too large
Load Diff
359
dmd2/root/root.h
Normal file
359
dmd2/root/root.h
Normal file
@@ -0,0 +1,359 @@
|
||||
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef ROOT_H
|
||||
#define ROOT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if __DMC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
typedef size_t hash_t;
|
||||
|
||||
#include "dchar.h"
|
||||
|
||||
char *wchar2ascii(wchar_t *);
|
||||
int wcharIsAscii(wchar_t *);
|
||||
char *wchar2ascii(wchar_t *, unsigned len);
|
||||
int wcharIsAscii(wchar_t *, unsigned len);
|
||||
|
||||
int bstrcmp(unsigned char *s1, unsigned char *s2);
|
||||
char *bstr2str(unsigned char *b);
|
||||
void error(const char *format, ...);
|
||||
void error(const wchar_t *format, ...);
|
||||
void warning(const char *format, ...);
|
||||
|
||||
#ifndef TYPEDEFS
|
||||
#define TYPEDEFS
|
||||
|
||||
#if _MSC_VER
|
||||
#include <float.h> // for _isnan
|
||||
#include <malloc.h> // for alloca
|
||||
// According to VC 8.0 docs, long double is the same as double
|
||||
#define strtold strtod
|
||||
#define strtof strtod
|
||||
#define isnan _isnan
|
||||
|
||||
typedef __int64 longlong;
|
||||
typedef unsigned __int64 ulonglong;
|
||||
#else
|
||||
typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
longlong randomx();
|
||||
|
||||
/*
|
||||
* Root of our class library.
|
||||
*/
|
||||
|
||||
struct OutBuffer;
|
||||
struct Array;
|
||||
|
||||
struct Object
|
||||
{
|
||||
Object() { }
|
||||
virtual ~Object() { }
|
||||
|
||||
virtual int equals(Object *o);
|
||||
|
||||
/**
|
||||
* Returns a hash code, useful for things like building hash tables of Objects.
|
||||
*/
|
||||
virtual hash_t hashCode();
|
||||
|
||||
/**
|
||||
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||
* Useful for sorting Objects.
|
||||
*/
|
||||
virtual int compare(Object *obj);
|
||||
|
||||
/**
|
||||
* Pretty-print an Object. Useful for debugging the old-fashioned way.
|
||||
*/
|
||||
virtual void print();
|
||||
|
||||
virtual char *toChars();
|
||||
virtual dchar *toDchars();
|
||||
virtual void toBuffer(OutBuffer *buf);
|
||||
|
||||
/**
|
||||
* Used as a replacement for dynamic_cast. Returns a unique number
|
||||
* defined by the library user. For Object, the return value is 0.
|
||||
*/
|
||||
virtual int dyncast();
|
||||
|
||||
/**
|
||||
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
|
||||
*/
|
||||
/*virtual*/ // not used, disable for now
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct String : Object
|
||||
{
|
||||
int ref; // != 0 if this is a reference to someone else's string
|
||||
char *str; // the string itself
|
||||
|
||||
String(char *str, int ref = 1);
|
||||
|
||||
~String();
|
||||
|
||||
static hash_t calcHash(const char *str, size_t len);
|
||||
static hash_t calcHash(const char *str);
|
||||
hash_t hashCode();
|
||||
unsigned len();
|
||||
int equals(Object *obj);
|
||||
int compare(Object *obj);
|
||||
char *toChars();
|
||||
void print();
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct FileName : String
|
||||
{
|
||||
FileName(char *str, int ref);
|
||||
FileName(char *path, char *name);
|
||||
hash_t hashCode();
|
||||
int equals(Object *obj);
|
||||
static int equals(const char *name1, const char *name2);
|
||||
int compare(Object *obj);
|
||||
static int compare(const char *name1, const char *name2);
|
||||
static int absolute(const char *name);
|
||||
static char *ext(const char *);
|
||||
char *ext();
|
||||
static char *removeExt(const char *str);
|
||||
static char *name(const char *);
|
||||
char *name();
|
||||
static char *path(const char *);
|
||||
static const char *replaceName(const char *path, const char *name);
|
||||
|
||||
static char *combine(const char *path, const char *name);
|
||||
static Array *splitPath(const char *path);
|
||||
static FileName *defaultExt(const char *name, const char *ext);
|
||||
static FileName *forceExt(const char *name, const char *ext);
|
||||
int equalsExt(const char *ext);
|
||||
|
||||
void CopyTo(FileName *to);
|
||||
static char *searchPath(Array *path, const char *name, int cwd);
|
||||
static int exists(const char *name);
|
||||
static void ensurePathExists(const char *path);
|
||||
};
|
||||
|
||||
struct File : Object
|
||||
{
|
||||
int ref; // != 0 if this is a reference to someone else's buffer
|
||||
unsigned char *buffer; // data for our file
|
||||
unsigned len; // amount of data in buffer[]
|
||||
void *touchtime; // system time to use for file
|
||||
|
||||
FileName *name; // name of our file
|
||||
|
||||
File(char *);
|
||||
File(FileName *);
|
||||
~File();
|
||||
|
||||
void mark();
|
||||
|
||||
char *toChars();
|
||||
|
||||
/* Read file, return !=0 if error
|
||||
*/
|
||||
|
||||
int read();
|
||||
|
||||
/* Write file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void readv();
|
||||
|
||||
/* Read file, return !=0 if error
|
||||
*/
|
||||
|
||||
int mmread();
|
||||
|
||||
/* Write file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void mmreadv();
|
||||
|
||||
/* Write file, return !=0 if error
|
||||
*/
|
||||
|
||||
int write();
|
||||
|
||||
/* Write file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void writev();
|
||||
|
||||
/* Return !=0 if file exists.
|
||||
* 0: file doesn't exist
|
||||
* 1: normal file
|
||||
* 2: directory
|
||||
*/
|
||||
|
||||
/* Append to file, return !=0 if error
|
||||
*/
|
||||
|
||||
int append();
|
||||
|
||||
/* Append to file, either succeed or fail
|
||||
* with error message & exit.
|
||||
*/
|
||||
|
||||
void appendv();
|
||||
|
||||
/* Return !=0 if file exists.
|
||||
* 0: file doesn't exist
|
||||
* 1: normal file
|
||||
* 2: directory
|
||||
*/
|
||||
|
||||
int exists();
|
||||
|
||||
/* Given wildcard filespec, return an array of
|
||||
* matching File's.
|
||||
*/
|
||||
|
||||
static Array *match(char *);
|
||||
static Array *match(FileName *);
|
||||
|
||||
// Compare file times.
|
||||
// Return <0 this < f
|
||||
// =0 this == f
|
||||
// >0 this > f
|
||||
int compareTime(File *f);
|
||||
|
||||
// Read system file statistics
|
||||
void stat();
|
||||
|
||||
/* Set buffer
|
||||
*/
|
||||
|
||||
void setbuffer(void *buffer, unsigned len)
|
||||
{
|
||||
this->buffer = (unsigned char *)buffer;
|
||||
this->len = len;
|
||||
}
|
||||
|
||||
void checkoffset(size_t offset, size_t nbytes);
|
||||
|
||||
void remove(); // delete file
|
||||
};
|
||||
|
||||
struct OutBuffer : Object
|
||||
{
|
||||
unsigned char *data;
|
||||
unsigned offset;
|
||||
unsigned size;
|
||||
|
||||
OutBuffer();
|
||||
~OutBuffer();
|
||||
void *extractData();
|
||||
void mark();
|
||||
|
||||
void reserve(unsigned nbytes);
|
||||
void setsize(unsigned size);
|
||||
void reset();
|
||||
void write(const void *data, unsigned nbytes);
|
||||
void writebstring(unsigned char *string);
|
||||
void writestring(const char *string);
|
||||
void writedstring(const char *string);
|
||||
void writedstring(const wchar_t *string);
|
||||
void prependstring(const char *string);
|
||||
void writenl(); // write newline
|
||||
void writeByte(unsigned b);
|
||||
void writebyte(unsigned b) { writeByte(b); }
|
||||
void writeUTF8(unsigned b);
|
||||
void writedchar(unsigned b);
|
||||
void prependbyte(unsigned b);
|
||||
void writeword(unsigned w);
|
||||
void writeUTF16(unsigned w);
|
||||
void write4(unsigned w);
|
||||
void write(OutBuffer *buf);
|
||||
void write(Object *obj);
|
||||
void fill0(unsigned nbytes);
|
||||
void align(unsigned size);
|
||||
void vprintf(const char *format, va_list args);
|
||||
void printf(const char *format, ...);
|
||||
#if M_UNICODE
|
||||
void vprintf(const unsigned short *format, va_list args);
|
||||
void printf(const unsigned short *format, ...);
|
||||
#endif
|
||||
void bracket(char left, char right);
|
||||
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
|
||||
void spread(unsigned offset, unsigned nbytes);
|
||||
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
|
||||
void remove(unsigned offset, unsigned nbytes);
|
||||
char *toChars();
|
||||
char *extractString();
|
||||
};
|
||||
|
||||
struct Array : Object
|
||||
{
|
||||
unsigned dim;
|
||||
unsigned allocdim;
|
||||
void **data;
|
||||
|
||||
Array();
|
||||
~Array();
|
||||
void mark();
|
||||
char *toChars();
|
||||
|
||||
void reserve(unsigned nentries);
|
||||
void setDim(unsigned newdim);
|
||||
void fixDim();
|
||||
void push(void *ptr);
|
||||
void *pop();
|
||||
void shift(void *ptr);
|
||||
void insert(unsigned index, void *ptr);
|
||||
void insert(unsigned index, Array *a);
|
||||
void append(Array *a);
|
||||
void remove(unsigned i);
|
||||
void zero();
|
||||
void *tos();
|
||||
void sort();
|
||||
Array *copy();
|
||||
};
|
||||
|
||||
struct Bits : Object
|
||||
{
|
||||
unsigned bitdim;
|
||||
unsigned allocdim;
|
||||
unsigned *data;
|
||||
|
||||
Bits();
|
||||
~Bits();
|
||||
void mark();
|
||||
|
||||
void resize(unsigned bitdim);
|
||||
|
||||
void set(unsigned bitnum);
|
||||
void clear(unsigned bitnum);
|
||||
int test(unsigned bitnum);
|
||||
|
||||
void set();
|
||||
void clear();
|
||||
void copy(Bits *from);
|
||||
Bits *clone();
|
||||
|
||||
void sub(Bits *b);
|
||||
};
|
||||
|
||||
#endif
|
||||
139
dmd2/root/stringtable.c
Normal file
139
dmd2/root/stringtable.c
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
#include "dchar.h"
|
||||
#include "lstring.h"
|
||||
#include "stringtable.h"
|
||||
|
||||
StringTable::StringTable(unsigned size)
|
||||
{
|
||||
table = (void **)mem.calloc(size, sizeof(void *));
|
||||
tabledim = size;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
StringTable::~StringTable()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
// Zero out dangling pointers to help garbage collector.
|
||||
// Should zero out StringEntry's too.
|
||||
for (i = 0; i < count; i++)
|
||||
table[i] = NULL;
|
||||
|
||||
mem.free(table);
|
||||
table = NULL;
|
||||
}
|
||||
|
||||
struct StringEntry
|
||||
{
|
||||
StringEntry *left;
|
||||
StringEntry *right;
|
||||
hash_t hash;
|
||||
|
||||
StringValue value;
|
||||
|
||||
static StringEntry *alloc(const dchar *s, unsigned len);
|
||||
};
|
||||
|
||||
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
|
||||
{
|
||||
StringEntry *se;
|
||||
|
||||
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
|
||||
se->value.lstring.length = len;
|
||||
se->hash = Dchar::calcHash(s,len);
|
||||
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
|
||||
return se;
|
||||
}
|
||||
|
||||
void **StringTable::search(const dchar *s, unsigned len)
|
||||
{
|
||||
hash_t hash;
|
||||
unsigned u;
|
||||
int cmp;
|
||||
StringEntry **se;
|
||||
|
||||
//printf("StringTable::search(%p,%d)\n",s,len);
|
||||
hash = Dchar::calcHash(s,len);
|
||||
u = hash % tabledim;
|
||||
se = (StringEntry **)&table[u];
|
||||
//printf("\thash = %d, u = %d\n",hash,u);
|
||||
while (*se)
|
||||
{
|
||||
cmp = (*se)->hash - hash;
|
||||
if (cmp == 0)
|
||||
{
|
||||
cmp = (*se)->value.lstring.len() - len;
|
||||
if (cmp == 0)
|
||||
{
|
||||
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
|
||||
if (cmp == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmp < 0)
|
||||
se = &(*se)->left;
|
||||
else
|
||||
se = &(*se)->right;
|
||||
}
|
||||
//printf("\treturn %p, %p\n",se, (*se));
|
||||
return (void **)se;
|
||||
}
|
||||
|
||||
StringValue *StringTable::lookup(const dchar *s, unsigned len)
|
||||
{ StringEntry *se;
|
||||
|
||||
se = *(StringEntry **)search(s,len);
|
||||
if (se)
|
||||
return &se->value;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringValue *StringTable::update(const dchar *s, unsigned len)
|
||||
{ StringEntry **pse;
|
||||
StringEntry *se;
|
||||
|
||||
pse = (StringEntry **)search(s,len);
|
||||
se = *pse;
|
||||
if (!se) // not in table: so create new entry
|
||||
{
|
||||
se = StringEntry::alloc(s, len);
|
||||
*pse = se;
|
||||
}
|
||||
return &se->value;
|
||||
}
|
||||
|
||||
StringValue *StringTable::insert(const dchar *s, unsigned len)
|
||||
{ StringEntry **pse;
|
||||
StringEntry *se;
|
||||
|
||||
pse = (StringEntry **)search(s,len);
|
||||
se = *pse;
|
||||
if (se)
|
||||
return NULL; // error: already in table
|
||||
else
|
||||
{
|
||||
se = StringEntry::alloc(s, len);
|
||||
*pse = se;
|
||||
}
|
||||
return &se->value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
48
dmd2/root/stringtable.h
Normal file
48
dmd2/root/stringtable.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
|
||||
#ifndef STRINGTABLE_H
|
||||
#define STRINGTABLE_H
|
||||
|
||||
#if __SC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "lstring.h"
|
||||
|
||||
struct StringValue
|
||||
{
|
||||
union
|
||||
{ int intvalue;
|
||||
void *ptrvalue;
|
||||
dchar *string;
|
||||
};
|
||||
Lstring lstring;
|
||||
};
|
||||
|
||||
struct StringTable : Object
|
||||
{
|
||||
void **table;
|
||||
unsigned count;
|
||||
unsigned tabledim;
|
||||
|
||||
StringTable(unsigned size = 37);
|
||||
~StringTable();
|
||||
|
||||
StringValue *lookup(const dchar *s, unsigned len);
|
||||
StringValue *insert(const dchar *s, unsigned len);
|
||||
StringValue *update(const dchar *s, unsigned len);
|
||||
|
||||
private:
|
||||
void **search(const dchar *s, unsigned len);
|
||||
};
|
||||
|
||||
#endif
|
||||
725
dmd2/scope.c
725
dmd2/scope.c
@@ -1,364 +1,361 @@
|
||||
|
||||
// Copyright (c) 1999-2005 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "init.h"
|
||||
#include "identifier.h"
|
||||
#include "attrib.h"
|
||||
#include "dsymbol.h"
|
||||
#include "scope.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
|
||||
Scope *Scope::freelist = NULL;
|
||||
|
||||
void *Scope::operator new(size_t size)
|
||||
{
|
||||
if (freelist)
|
||||
{
|
||||
Scope *s = freelist;
|
||||
freelist = s->enclosing;
|
||||
//printf("freelist %p\n", s);
|
||||
assert(s->flags & SCOPEfree);
|
||||
s->flags &= ~SCOPEfree;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *p = ::operator new(size);
|
||||
//printf("new %p\n", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
Scope::Scope()
|
||||
{ // Create root scope
|
||||
|
||||
//printf("Scope::Scope() %p\n", this);
|
||||
this->module = NULL;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->enclosing = NULL;
|
||||
this->parent = NULL;
|
||||
this->sw = NULL;
|
||||
this->tf = NULL;
|
||||
this->tfOfTry = NULL;
|
||||
this->tinst = NULL;
|
||||
this->sbreak = NULL;
|
||||
this->scontinue = NULL;
|
||||
this->fes = NULL;
|
||||
this->structalign = global.structalign;
|
||||
this->func = NULL;
|
||||
this->slabel = NULL;
|
||||
this->linkage = LINKd;
|
||||
this->protection = PROTpublic;
|
||||
this->explicitProtection = 0;
|
||||
this->stc = 0;
|
||||
this->offset = 0;
|
||||
this->inunion = 0;
|
||||
this->incontract = 0;
|
||||
this->nofree = 0;
|
||||
this->noctor = 0;
|
||||
this->noaccesscheck = 0;
|
||||
this->intypeof = 0;
|
||||
this->parameterSpecialization = 0;
|
||||
this->callSuper = 0;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = NULL;
|
||||
}
|
||||
|
||||
Scope::Scope(Scope *enclosing)
|
||||
{
|
||||
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
|
||||
assert(!(enclosing->flags & SCOPEfree));
|
||||
this->module = enclosing->module;
|
||||
this->func = enclosing->func;
|
||||
this->parent = enclosing->parent;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->sw = enclosing->sw;
|
||||
this->tf = enclosing->tf;
|
||||
this->tfOfTry = enclosing->tfOfTry;
|
||||
this->tinst = enclosing->tinst;
|
||||
this->sbreak = enclosing->sbreak;
|
||||
this->scontinue = enclosing->scontinue;
|
||||
this->fes = enclosing->fes;
|
||||
this->structalign = enclosing->structalign;
|
||||
this->enclosing = enclosing;
|
||||
#ifdef DEBUG
|
||||
if (enclosing->enclosing)
|
||||
assert(!(enclosing->enclosing->flags & SCOPEfree));
|
||||
if (this == enclosing->enclosing)
|
||||
{
|
||||
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
|
||||
}
|
||||
assert(this != enclosing->enclosing);
|
||||
#endif
|
||||
this->slabel = NULL;
|
||||
this->linkage = enclosing->linkage;
|
||||
this->protection = enclosing->protection;
|
||||
this->explicitProtection = enclosing->explicitProtection;
|
||||
this->stc = enclosing->stc;
|
||||
this->offset = 0;
|
||||
this->inunion = enclosing->inunion;
|
||||
this->incontract = enclosing->incontract;
|
||||
this->nofree = 0;
|
||||
this->noctor = enclosing->noctor;
|
||||
this->noaccesscheck = enclosing->noaccesscheck;
|
||||
this->intypeof = enclosing->intypeof;
|
||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||
this->callSuper = enclosing->callSuper;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = enclosing->docbuf;
|
||||
assert(this != enclosing);
|
||||
}
|
||||
|
||||
Scope *Scope::createGlobal(Module *module)
|
||||
{
|
||||
Scope *sc;
|
||||
|
||||
sc = new Scope();
|
||||
sc->module = module;
|
||||
sc->scopesym = new ScopeDsymbol();
|
||||
sc->scopesym->symtab = new DsymbolTable();
|
||||
|
||||
// Add top level package as member of this global scope
|
||||
Dsymbol *m = module;
|
||||
while (m->parent)
|
||||
m = m->parent;
|
||||
m->addMember(NULL, sc->scopesym, 1);
|
||||
m->parent = NULL; // got changed by addMember()
|
||||
|
||||
// Create the module scope underneath the global scope
|
||||
sc = sc->push(module);
|
||||
sc->parent = module;
|
||||
return sc;
|
||||
}
|
||||
|
||||
Scope *Scope::push()
|
||||
{
|
||||
//printf("Scope::push()\n");
|
||||
Scope *s = new Scope(this);
|
||||
assert(this != s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Scope *Scope::push(ScopeDsymbol *ss)
|
||||
{
|
||||
//printf("Scope::push(%s)\n", ss->toChars());
|
||||
Scope *s = push();
|
||||
s->scopesym = ss;
|
||||
return s;
|
||||
}
|
||||
|
||||
Scope *Scope::pop()
|
||||
{
|
||||
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
|
||||
Scope *enc = enclosing;
|
||||
|
||||
if (enclosing)
|
||||
enclosing->callSuper |= callSuper;
|
||||
|
||||
if (!nofree)
|
||||
{ enclosing = freelist;
|
||||
freelist = this;
|
||||
flags |= SCOPEfree;
|
||||
}
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
{
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
// regarding when and how constructors can appear.
|
||||
// It merges the results of two paths.
|
||||
// The two paths are callSuper and cs; the result is merged into callSuper.
|
||||
|
||||
if (cs != callSuper)
|
||||
{ int a;
|
||||
int b;
|
||||
|
||||
callSuper |= cs & (CSXany_ctor | CSXlabel);
|
||||
if (cs & CSXreturn)
|
||||
{
|
||||
}
|
||||
else if (callSuper & CSXreturn)
|
||||
{
|
||||
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
|
||||
}
|
||||
else
|
||||
{
|
||||
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
|
||||
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
|
||||
if (a != b)
|
||||
error(loc, "one path skips constructor");
|
||||
callSuper |= cs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
{ Dsymbol *s;
|
||||
Scope *sc;
|
||||
|
||||
//printf("Scope::search(%p, '%s')\n", this, ident->toChars());
|
||||
if (ident == Id::empty)
|
||||
{
|
||||
// Look for module scope
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
assert(sc != sc->enclosing);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
s = sc->scopesym->isModule();
|
||||
if (s)
|
||||
{
|
||||
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
|
||||
if (pscopesym)
|
||||
*pscopesym = sc->scopesym;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
assert(sc != sc->enclosing);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
|
||||
s = sc->scopesym->search(loc, ident, 0);
|
||||
if (s)
|
||||
{
|
||||
if ((global.params.warnings ||
|
||||
global.params.Dversion > 1) &&
|
||||
ident == Id::length &&
|
||||
sc->scopesym->isArrayScopeSymbol() &&
|
||||
sc->enclosing &&
|
||||
sc->enclosing->search(loc, ident, NULL))
|
||||
{
|
||||
// WTF ?
|
||||
if (global.params.warnings)
|
||||
fprintf(stdmsg, "warning - ");
|
||||
error(s->loc, "array 'length' hides other 'length' name in outer scope");
|
||||
}
|
||||
|
||||
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
|
||||
if (pscopesym)
|
||||
*pscopesym = sc->scopesym;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dsymbol *Scope::insert(Dsymbol *s)
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
//printf("\tsc = %p\n", sc);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
|
||||
if (!sc->scopesym->symtab)
|
||||
sc->scopesym->symtab = new DsymbolTable();
|
||||
return sc->scopesym->symtab->insert(s);
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Search enclosing scopes for ClassDeclaration.
|
||||
*/
|
||||
|
||||
ClassDeclaration *Scope::getClassScope()
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
|
||||
if (sc->scopesym)
|
||||
{
|
||||
cd = sc->scopesym->isClassDeclaration();
|
||||
if (cd)
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Search enclosing scopes for ClassDeclaration.
|
||||
*/
|
||||
|
||||
AggregateDeclaration *Scope::getStructClassScope()
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
AggregateDeclaration *ad;
|
||||
|
||||
if (sc->scopesym)
|
||||
{
|
||||
ad = sc->scopesym->isClassDeclaration();
|
||||
if (ad)
|
||||
return ad;
|
||||
else
|
||||
{ ad = sc->scopesym->isStructDeclaration();
|
||||
if (ad)
|
||||
return ad;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* For TemplateDeclarations, we need to remember the Scope
|
||||
* where it was declared. So mark the Scope as not
|
||||
* to be free'd.
|
||||
*/
|
||||
|
||||
void Scope::setNoFree()
|
||||
{ Scope *sc;
|
||||
//int i = 0;
|
||||
|
||||
//printf("Scope::setNoFree(this = %p)\n", this);
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
//printf("\tsc = %p\n", sc);
|
||||
sc->nofree = 1;
|
||||
|
||||
assert(!(flags & SCOPEfree));
|
||||
//assert(sc != sc->enclosing);
|
||||
//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
|
||||
//if (++i == 10)
|
||||
//assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (c) 1999-2005 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "init.h"
|
||||
#include "identifier.h"
|
||||
#include "attrib.h"
|
||||
#include "dsymbol.h"
|
||||
#include "scope.h"
|
||||
#include "declaration.h"
|
||||
#include "aggregate.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
|
||||
Scope *Scope::freelist = NULL;
|
||||
|
||||
void *Scope::operator new(size_t size)
|
||||
{
|
||||
if (freelist)
|
||||
{
|
||||
Scope *s = freelist;
|
||||
freelist = s->enclosing;
|
||||
//printf("freelist %p\n", s);
|
||||
assert(s->flags & SCOPEfree);
|
||||
s->flags &= ~SCOPEfree;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *p = ::operator new(size);
|
||||
//printf("new %p\n", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
Scope::Scope()
|
||||
{ // Create root scope
|
||||
|
||||
//printf("Scope::Scope() %p\n", this);
|
||||
this->module = NULL;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->enclosing = NULL;
|
||||
this->parent = NULL;
|
||||
this->sw = NULL;
|
||||
this->enclosingFinally = NULL;
|
||||
this->enclosingScopeExit = NULL;
|
||||
this->tinst = NULL;
|
||||
this->sbreak = NULL;
|
||||
this->scontinue = NULL;
|
||||
this->fes = NULL;
|
||||
this->structalign = global.structalign;
|
||||
this->func = NULL;
|
||||
this->slabel = NULL;
|
||||
this->linkage = LINKd;
|
||||
this->protection = PROTpublic;
|
||||
this->explicitProtection = 0;
|
||||
this->stc = 0;
|
||||
this->offset = 0;
|
||||
this->inunion = 0;
|
||||
this->incontract = 0;
|
||||
this->nofree = 0;
|
||||
this->noctor = 0;
|
||||
this->noaccesscheck = 0;
|
||||
this->intypeof = 0;
|
||||
this->parameterSpecialization = 0;
|
||||
this->callSuper = 0;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = NULL;
|
||||
}
|
||||
|
||||
Scope::Scope(Scope *enclosing)
|
||||
{
|
||||
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
|
||||
assert(!(enclosing->flags & SCOPEfree));
|
||||
this->module = enclosing->module;
|
||||
this->func = enclosing->func;
|
||||
this->parent = enclosing->parent;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->sw = enclosing->sw;
|
||||
this->enclosingFinally = enclosing->enclosingFinally;
|
||||
this->enclosingScopeExit = enclosing->enclosingScopeExit;
|
||||
this->tinst = enclosing->tinst;
|
||||
this->sbreak = enclosing->sbreak;
|
||||
this->scontinue = enclosing->scontinue;
|
||||
this->fes = enclosing->fes;
|
||||
this->structalign = enclosing->structalign;
|
||||
this->enclosing = enclosing;
|
||||
#ifdef DEBUG
|
||||
if (enclosing->enclosing)
|
||||
assert(!(enclosing->enclosing->flags & SCOPEfree));
|
||||
if (this == enclosing->enclosing)
|
||||
{
|
||||
printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
|
||||
}
|
||||
assert(this != enclosing->enclosing);
|
||||
#endif
|
||||
this->slabel = NULL;
|
||||
this->linkage = enclosing->linkage;
|
||||
this->protection = enclosing->protection;
|
||||
this->explicitProtection = enclosing->explicitProtection;
|
||||
this->stc = enclosing->stc;
|
||||
this->offset = 0;
|
||||
this->inunion = enclosing->inunion;
|
||||
this->incontract = enclosing->incontract;
|
||||
this->nofree = 0;
|
||||
this->noctor = enclosing->noctor;
|
||||
this->noaccesscheck = enclosing->noaccesscheck;
|
||||
this->intypeof = enclosing->intypeof;
|
||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||
this->callSuper = enclosing->callSuper;
|
||||
this->flags = 0;
|
||||
this->anonAgg = NULL;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = enclosing->docbuf;
|
||||
assert(this != enclosing);
|
||||
}
|
||||
|
||||
Scope *Scope::createGlobal(Module *module)
|
||||
{
|
||||
Scope *sc;
|
||||
|
||||
sc = new Scope();
|
||||
sc->module = module;
|
||||
sc->scopesym = new ScopeDsymbol();
|
||||
sc->scopesym->symtab = new DsymbolTable();
|
||||
|
||||
// Add top level package as member of this global scope
|
||||
Dsymbol *m = module;
|
||||
while (m->parent)
|
||||
m = m->parent;
|
||||
m->addMember(NULL, sc->scopesym, 1);
|
||||
m->parent = NULL; // got changed by addMember()
|
||||
|
||||
// Create the module scope underneath the global scope
|
||||
sc = sc->push(module);
|
||||
sc->parent = module;
|
||||
return sc;
|
||||
}
|
||||
|
||||
Scope *Scope::push()
|
||||
{
|
||||
//printf("Scope::push()\n");
|
||||
Scope *s = new Scope(this);
|
||||
assert(this != s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Scope *Scope::push(ScopeDsymbol *ss)
|
||||
{
|
||||
//printf("Scope::push(%s)\n", ss->toChars());
|
||||
Scope *s = push();
|
||||
s->scopesym = ss;
|
||||
return s;
|
||||
}
|
||||
|
||||
Scope *Scope::pop()
|
||||
{
|
||||
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
|
||||
Scope *enc = enclosing;
|
||||
|
||||
if (enclosing)
|
||||
enclosing->callSuper |= callSuper;
|
||||
|
||||
if (!nofree)
|
||||
{ enclosing = freelist;
|
||||
freelist = this;
|
||||
flags |= SCOPEfree;
|
||||
}
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
{
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
// regarding when and how constructors can appear.
|
||||
// It merges the results of two paths.
|
||||
// The two paths are callSuper and cs; the result is merged into callSuper.
|
||||
|
||||
if (cs != callSuper)
|
||||
{ int a;
|
||||
int b;
|
||||
|
||||
callSuper |= cs & (CSXany_ctor | CSXlabel);
|
||||
if (cs & CSXreturn)
|
||||
{
|
||||
}
|
||||
else if (callSuper & CSXreturn)
|
||||
{
|
||||
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
|
||||
}
|
||||
else
|
||||
{
|
||||
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
|
||||
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
|
||||
if (a != b)
|
||||
error(loc, "one path skips constructor");
|
||||
callSuper |= cs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
{ Dsymbol *s;
|
||||
Scope *sc;
|
||||
|
||||
//printf("Scope::search(%p, '%s')\n", this, ident->toChars());
|
||||
if (ident == Id::empty)
|
||||
{
|
||||
// Look for module scope
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
assert(sc != sc->enclosing);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
s = sc->scopesym->isModule();
|
||||
if (s)
|
||||
{
|
||||
//printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
|
||||
if (pscopesym)
|
||||
*pscopesym = sc->scopesym;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
assert(sc != sc->enclosing);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
|
||||
s = sc->scopesym->search(loc, ident, 0);
|
||||
if (s)
|
||||
{
|
||||
if ((global.params.warnings ||
|
||||
global.params.Dversion > 1) &&
|
||||
ident == Id::length &&
|
||||
sc->scopesym->isArrayScopeSymbol() &&
|
||||
sc->enclosing &&
|
||||
sc->enclosing->search(loc, ident, NULL))
|
||||
{
|
||||
warning(s->loc, "array 'length' hides other 'length' name in outer scope");
|
||||
}
|
||||
|
||||
//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
|
||||
if (pscopesym)
|
||||
*pscopesym = sc->scopesym;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dsymbol *Scope::insert(Dsymbol *s)
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
//printf("\tsc = %p\n", sc);
|
||||
if (sc->scopesym)
|
||||
{
|
||||
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
|
||||
if (!sc->scopesym->symtab)
|
||||
sc->scopesym->symtab = new DsymbolTable();
|
||||
return sc->scopesym->symtab->insert(s);
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Search enclosing scopes for ClassDeclaration.
|
||||
*/
|
||||
|
||||
ClassDeclaration *Scope::getClassScope()
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
|
||||
if (sc->scopesym)
|
||||
{
|
||||
cd = sc->scopesym->isClassDeclaration();
|
||||
if (cd)
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Search enclosing scopes for ClassDeclaration.
|
||||
*/
|
||||
|
||||
AggregateDeclaration *Scope::getStructClassScope()
|
||||
{ Scope *sc;
|
||||
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
AggregateDeclaration *ad;
|
||||
|
||||
if (sc->scopesym)
|
||||
{
|
||||
ad = sc->scopesym->isClassDeclaration();
|
||||
if (ad)
|
||||
return ad;
|
||||
else
|
||||
{ ad = sc->scopesym->isStructDeclaration();
|
||||
if (ad)
|
||||
return ad;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* For TemplateDeclarations, we need to remember the Scope
|
||||
* where it was declared. So mark the Scope as not
|
||||
* to be free'd.
|
||||
*/
|
||||
|
||||
void Scope::setNoFree()
|
||||
{ Scope *sc;
|
||||
//int i = 0;
|
||||
|
||||
//printf("Scope::setNoFree(this = %p)\n", this);
|
||||
for (sc = this; sc; sc = sc->enclosing)
|
||||
{
|
||||
//printf("\tsc = %p\n", sc);
|
||||
sc->nofree = 1;
|
||||
|
||||
assert(!(flags & SCOPEfree));
|
||||
//assert(sc != sc->enclosing);
|
||||
//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
|
||||
//if (++i == 10)
|
||||
//assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
244
dmd2/scope.h
244
dmd2/scope.h
@@ -1,119 +1,125 @@
|
||||
|
||||
// Copyright (c) 1999-2005 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_SCOPE_H
|
||||
#define DMD_SCOPE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct Dsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct Array;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct SwitchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct AnonymousAggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct EnclosingHandler;
|
||||
struct AnonDeclaration;
|
||||
#if __GNUC__
|
||||
#include "dsymbol.h" // PROT
|
||||
#include "mars.h" // LINK
|
||||
#else
|
||||
enum LINK;
|
||||
enum PROT;
|
||||
#endif
|
||||
|
||||
struct Scope
|
||||
{
|
||||
Scope *enclosing; // enclosing Scope
|
||||
|
||||
Module *module; // Root module
|
||||
ScopeDsymbol *scopesym; // current symbol
|
||||
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
|
||||
// sd gets the addMember()
|
||||
FuncDeclaration *func; // function we are in
|
||||
Dsymbol *parent; // parent to use
|
||||
LabelStatement *slabel; // enclosing labelled statement
|
||||
SwitchStatement *sw; // enclosing switch statement
|
||||
TryFinallyStatement *tf; // enclosing try finally statement; set inside its finally block
|
||||
EnclosingHandler *tfOfTry; // enclosing try-finally, volatile or synchronized statement; set inside its try or body block
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Statement *sbreak; // enclosing statement that supports "break"
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||
unsigned offset; // next offset to use in aggregate
|
||||
int inunion; // we're processing members of a union
|
||||
int incontract; // we're inside contract code
|
||||
int nofree; // set if shouldn't free it
|
||||
int noctor; // set if constructor calls aren't allowed
|
||||
int intypeof; // in typeof(exp)
|
||||
int parameterSpecialization; // if in template parameter specialization
|
||||
int noaccesscheck; // don't do access checks
|
||||
|
||||
unsigned callSuper; // primitive flow analysis for constructors
|
||||
#define CSXthis_ctor 1 // called this()
|
||||
#define CSXsuper_ctor 2 // called super()
|
||||
#define CSXthis 4 // referenced this
|
||||
#define CSXsuper 8 // referenced super
|
||||
#define CSXlabel 0x10 // seen a label
|
||||
#define CSXreturn 0x20 // seen a return statement
|
||||
#define CSXany_ctor 0x40 // either this() or super() was called
|
||||
|
||||
unsigned structalign; // alignment for struct members
|
||||
enum LINK linkage; // linkage for external functions
|
||||
|
||||
enum PROT protection; // protection for class members
|
||||
int explicitProtection; // set if in an explicit protection attribute
|
||||
|
||||
unsigned stc; // storage class
|
||||
|
||||
unsigned flags;
|
||||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||
OutBuffer *docbuf; // buffer for documentation output
|
||||
|
||||
static Scope *freelist;
|
||||
static void *operator new(size_t sz);
|
||||
static Scope *createGlobal(Module *module);
|
||||
|
||||
Scope();
|
||||
Scope(Module *module);
|
||||
Scope(Scope *enclosing);
|
||||
|
||||
Scope *push();
|
||||
Scope *push(ScopeDsymbol *ss);
|
||||
Scope *pop();
|
||||
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
ClassDeclaration *getClassScope();
|
||||
AggregateDeclaration *getStructClassScope();
|
||||
void setNoFree();
|
||||
};
|
||||
|
||||
#endif /* DMD_SCOPE_H */
|
||||
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_SCOPE_H
|
||||
#define DMD_SCOPE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
struct Dsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct Array;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct SwitchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct AnonymousAggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct TemplateInstance;
|
||||
|
||||
#if IN_LLVM
|
||||
struct EnclosingHandler;
|
||||
struct AnonDeclaration;
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
// Requires a full definition for PROT and LINK
|
||||
#include "dsymbol.h" // PROT
|
||||
#include "mars.h" // LINK
|
||||
#else
|
||||
enum LINK;
|
||||
enum PROT;
|
||||
#endif
|
||||
|
||||
struct Scope
|
||||
{
|
||||
Scope *enclosing; // enclosing Scope
|
||||
|
||||
Module *module; // Root module
|
||||
ScopeDsymbol *scopesym; // current symbol
|
||||
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
|
||||
// sd gets the addMember()
|
||||
FuncDeclaration *func; // function we are in
|
||||
Dsymbol *parent; // parent to use
|
||||
LabelStatement *slabel; // enclosing labelled statement
|
||||
SwitchStatement *sw; // enclosing switch statement
|
||||
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
|
||||
Statement *sbreak; // enclosing statement that supports "break"
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||
unsigned offset; // next offset to use in aggregate
|
||||
int inunion; // we're processing members of a union
|
||||
int incontract; // we're inside contract code
|
||||
int nofree; // set if shouldn't free it
|
||||
int noctor; // set if constructor calls aren't allowed
|
||||
int intypeof; // in typeof(exp)
|
||||
int parameterSpecialization; // if in template parameter specialization
|
||||
int noaccesscheck; // don't do access checks
|
||||
|
||||
unsigned callSuper; // primitive flow analysis for constructors
|
||||
#define CSXthis_ctor 1 // called this()
|
||||
#define CSXsuper_ctor 2 // called super()
|
||||
#define CSXthis 4 // referenced this
|
||||
#define CSXsuper 8 // referenced super
|
||||
#define CSXlabel 0x10 // seen a label
|
||||
#define CSXreturn 0x20 // seen a return statement
|
||||
#define CSXany_ctor 0x40 // either this() or super() was called
|
||||
|
||||
unsigned structalign; // alignment for struct members
|
||||
enum LINK linkage; // linkage for external functions
|
||||
|
||||
enum PROT protection; // protection for class members
|
||||
int explicitProtection; // set if in an explicit protection attribute
|
||||
|
||||
unsigned stc; // storage class
|
||||
|
||||
unsigned flags;
|
||||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||
OutBuffer *docbuf; // buffer for documentation output
|
||||
|
||||
static Scope *freelist;
|
||||
static void *operator new(size_t sz);
|
||||
static Scope *createGlobal(Module *module);
|
||||
|
||||
Scope();
|
||||
Scope(Module *module);
|
||||
Scope(Scope *enclosing);
|
||||
|
||||
Scope *push();
|
||||
Scope *push(ScopeDsymbol *ss);
|
||||
Scope *pop();
|
||||
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
ClassDeclaration *getClassScope();
|
||||
AggregateDeclaration *getStructClassScope();
|
||||
void setNoFree();
|
||||
};
|
||||
|
||||
#endif /* DMD_SCOPE_H */
|
||||
|
||||
8762
dmd2/statement.c
8762
dmd2/statement.c
File diff suppressed because it is too large
Load Diff
1854
dmd2/statement.h
1854
dmd2/statement.h
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
||||
#include "scope.h"
|
||||
#include "template.h"
|
||||
|
||||
|
||||
/********************************* AttribDeclaration ****************************/
|
||||
|
||||
StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
|
||||
@@ -47,6 +48,10 @@ void StaticAssert::semantic(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
#include "scope.h"
|
||||
#include "template.h"
|
||||
#include "declaration.h"
|
||||
|
||||
void StaticAssert::semantic2(Scope *sc)
|
||||
{
|
||||
Expression *e;
|
||||
@@ -67,11 +72,12 @@ void StaticAssert::semantic2(Scope *sc)
|
||||
error("%s", buf.toChars());
|
||||
}
|
||||
else
|
||||
error("is false");
|
||||
if(sc->tinst)
|
||||
error("(%s) is false", exp->toChars());
|
||||
if(sc->tinst)
|
||||
sc->tinst->printInstantiationTrace();
|
||||
if (!global.gag)
|
||||
fatal();
|
||||
if (!global.gag) {
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
else if (!e->isBool(TRUE))
|
||||
{
|
||||
|
||||
137
dmd2/struct.c
137
dmd2/struct.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
#include "statement.h"
|
||||
#include "template.h"
|
||||
|
||||
/********************************* AggregateDeclaration ****************************/
|
||||
|
||||
@@ -41,13 +42,20 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
aggNew = NULL;
|
||||
aggDelete = NULL;
|
||||
|
||||
#if IN_DMD
|
||||
stag = NULL;
|
||||
sinit = NULL;
|
||||
#endif
|
||||
scope = NULL;
|
||||
dtor = NULL;
|
||||
isnested = 0;
|
||||
vthis = NULL;
|
||||
|
||||
#if DMDV2
|
||||
ctor = NULL;
|
||||
defaultCtor = NULL;
|
||||
aliasthis = NULL;
|
||||
#endif
|
||||
dtor = NULL;
|
||||
}
|
||||
|
||||
enum PROT AggregateDeclaration::prot()
|
||||
@@ -132,31 +140,21 @@ int AggregateDeclaration::isDeprecated()
|
||||
* Align sizes of 0, as we may not know array sizes yet.
|
||||
*/
|
||||
|
||||
void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset)
|
||||
void AggregateDeclaration::alignmember(
|
||||
unsigned salign, // struct alignment that is in effect
|
||||
unsigned size, // alignment requirement of field
|
||||
unsigned *poffset)
|
||||
{
|
||||
//printf("salign = %d, size = %d, offset = %d\n",salign,size,*poffset);
|
||||
//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
|
||||
if (salign > 1)
|
||||
{ int sa;
|
||||
|
||||
switch (size)
|
||||
{ case 1:
|
||||
break;
|
||||
case 2:
|
||||
case_2:
|
||||
*poffset = (*poffset + 1) & ~1; // align to word
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
if (salign == 2)
|
||||
goto case_2;
|
||||
*poffset = (*poffset + 3) & ~3; // align to dword
|
||||
break;
|
||||
default:
|
||||
*poffset = (*poffset + size - 1) & ~(size - 1);
|
||||
break;
|
||||
}
|
||||
{
|
||||
assert(size != 3);
|
||||
int sa = size;
|
||||
if (sa == 0 || salign < sa)
|
||||
sa = salign;
|
||||
*poffset = (*poffset + sa - 1) & ~(sa - 1);
|
||||
}
|
||||
//printf("result = %d\n",*poffset);
|
||||
//printf("result = %d\n",offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,13 +169,18 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
||||
|
||||
// Check for forward referenced types which will fail the size() call
|
||||
Type *t = v->type->toBasetype();
|
||||
if (v->storage_class & STCref)
|
||||
{ // References are the size of a pointer
|
||||
t = Type::tvoidptr;
|
||||
}
|
||||
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
|
||||
{ TypeStruct *ts = (TypeStruct *)t;
|
||||
|
||||
#if DMDV2
|
||||
if (ts->sym == this)
|
||||
{
|
||||
error("cannot have field %s with same struct type", v->toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ts->sym->sizeok != 1)
|
||||
{
|
||||
@@ -191,9 +194,9 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
||||
return;
|
||||
}
|
||||
|
||||
memsize = v->type->size(loc);
|
||||
memalignsize = v->type->alignsize();
|
||||
xalign = v->type->memalign(sc->structalign);
|
||||
memsize = t->size(loc);
|
||||
memalignsize = t->alignsize();
|
||||
xalign = t->memalign(sc->structalign);
|
||||
alignmember(xalign, memalignsize, &sc->offset);
|
||||
v->offset = sc->offset;
|
||||
sc->offset += memsize;
|
||||
@@ -211,15 +214,28 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* Returns !=0 if there's an extra member which is the 'this'
|
||||
* pointer to the enclosing context (enclosing aggregate or function)
|
||||
*/
|
||||
|
||||
int AggregateDeclaration::isNested()
|
||||
{
|
||||
return isnested;
|
||||
}
|
||||
|
||||
|
||||
/********************************* StructDeclaration ****************************/
|
||||
|
||||
StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
||||
: AggregateDeclaration(loc, id)
|
||||
{
|
||||
zeroInit = 0; // assume false until we do semantic processing
|
||||
#if DMDV2
|
||||
hasIdentityAssign = 0;
|
||||
cpctor = NULL;
|
||||
postblit = NULL;
|
||||
#endif
|
||||
|
||||
// For forward references
|
||||
type = new TypeStruct(this);
|
||||
@@ -277,24 +293,64 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
assert(!isAnonymous());
|
||||
if (sc->stc & STCabstract)
|
||||
error("structs, unions cannot be abstract");
|
||||
if (storage_class & STCinvariant)
|
||||
#if DMDV2
|
||||
if (storage_class & STCimmutable)
|
||||
type = type->invariantOf();
|
||||
else if (storage_class & STCconst)
|
||||
type = type->constOf();
|
||||
else if (storage_class & STCshared)
|
||||
type = type->sharedOf();
|
||||
#endif
|
||||
|
||||
if (sizeok == 0) // if not already done the addMember step
|
||||
{
|
||||
int hasfunctions = 0;
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
|
||||
s->addMember(sc, this, 1);
|
||||
if (s->isFuncDeclaration())
|
||||
hasfunctions = 1;
|
||||
}
|
||||
|
||||
// If nested struct, add in hidden 'this' pointer to outer scope
|
||||
if (hasfunctions && !(storage_class & STCstatic))
|
||||
{ Dsymbol *s = toParent2();
|
||||
if (s)
|
||||
{
|
||||
AggregateDeclaration *ad = s->isAggregateDeclaration();
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
|
||||
TemplateInstance *ti;
|
||||
if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
|
||||
{ isnested = 1;
|
||||
Type *t;
|
||||
if (ad)
|
||||
t = ad->handle;
|
||||
else if (fd)
|
||||
{ AggregateDeclaration *ad = fd->isMember2();
|
||||
if (ad)
|
||||
t = ad->handle;
|
||||
else
|
||||
t = Type::tvoidptr;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
if (t->ty == Tstruct)
|
||||
t = Type::tvoidptr; // t should not be a ref type
|
||||
assert(!vthis);
|
||||
vthis = new ThisDeclaration(loc, t);
|
||||
//vthis->storage_class |= STCref;
|
||||
members->push(vthis);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sizeok = 0;
|
||||
sc2 = sc->push(this);
|
||||
sc2->stc &= storage_class & (STCconst | STCinvariant);
|
||||
sc2->stc &= storage_class & STC_TYPECTOR;
|
||||
sc2->parent = this;
|
||||
if (isUnionDeclaration())
|
||||
sc2->inunion = 1;
|
||||
@@ -314,6 +370,14 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Type *t;
|
||||
if (s->isDeclaration() &&
|
||||
(t = s->isDeclaration()->type) != NULL &&
|
||||
t->toBasetype()->ty == Tstruct)
|
||||
{ StructDeclaration *sd = (StructDeclaration *)t->toDsymbol(sc);
|
||||
if (sd->isnested)
|
||||
error("inner struct %s cannot be a field", sd->toChars());
|
||||
}
|
||||
}
|
||||
|
||||
/* The TypeInfo_Struct is expecting an opEquals and opCmp with
|
||||
@@ -349,9 +413,9 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
Dsymbol *s = search_function(this, id);
|
||||
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
|
||||
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
|
||||
if (!fd)
|
||||
{ fd = fdx->overloadExactMatch(tfeq);
|
||||
{ fd = fdx->overloadExactMatch(tfeq, getModule());
|
||||
if (fd)
|
||||
{ // Create the thunk, fdptr
|
||||
FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
|
||||
@@ -373,11 +437,12 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
id = Id::cmp;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
dtor = buildDtor(sc2);
|
||||
postblit = buildPostBlit(sc2);
|
||||
cpctor = buildCpCtor(sc2);
|
||||
buildOpAssign(sc2);
|
||||
#endif
|
||||
|
||||
sc2->pop();
|
||||
|
||||
@@ -429,7 +494,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!vd->type->isZeroInit())
|
||||
if (!vd->type->isZeroInit(loc))
|
||||
{
|
||||
zeroInit = 0;
|
||||
break;
|
||||
@@ -440,7 +505,9 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
/* Look for special member functions.
|
||||
*/
|
||||
ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
|
||||
#if DMDV2
|
||||
ctor = search(0, Id::ctor, 0);
|
||||
#endif
|
||||
inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0);
|
||||
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
|
||||
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
|
||||
|
||||
9553
dmd2/template.c
9553
dmd2/template.c
File diff suppressed because it is too large
Load Diff
744
dmd2/template.h
744
dmd2/template.h
@@ -1,363 +1,381 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_TEMPLATE_H
|
||||
#define DMD_TEMPLATE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "root.h"
|
||||
#include "arraytypes.h"
|
||||
#include "dsymbol.h"
|
||||
#include "mtype.h"
|
||||
|
||||
|
||||
struct OutBuffer;
|
||||
struct Identifier;
|
||||
struct TemplateInstance;
|
||||
struct TemplateParameter;
|
||||
struct TemplateTypeParameter;
|
||||
struct TemplateThisParameter;
|
||||
struct TemplateValueParameter;
|
||||
struct TemplateAliasParameter;
|
||||
struct TemplateTupleParameter;
|
||||
struct Type;
|
||||
struct TypeTypeof;
|
||||
struct Scope;
|
||||
struct Expression;
|
||||
struct AliasDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct HdrGenState;
|
||||
enum MATCH;
|
||||
|
||||
struct Tuple : Object
|
||||
{
|
||||
Objects objects;
|
||||
|
||||
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
|
||||
};
|
||||
|
||||
|
||||
struct TemplateDeclaration : ScopeDsymbol
|
||||
{
|
||||
TemplateParameters *parameters; // array of TemplateParameter's
|
||||
|
||||
TemplateParameters *origParameters; // originals for Ddoc
|
||||
|
||||
Expression *constraint;
|
||||
|
||||
Array instances; // array of TemplateInstance's
|
||||
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
TemplateDeclaration *overroot; // first in overnext list
|
||||
|
||||
Scope *scope;
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
||||
Expression *constraint, Array *decldefs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
char *toChars();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
// void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
|
||||
MATCH leastAsSpecialized(TemplateDeclaration *td2);
|
||||
|
||||
MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
|
||||
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
|
||||
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
|
||||
|
||||
TemplateDeclaration *isTemplateDeclaration() { return this; }
|
||||
|
||||
TemplateTupleParameter *isVariadic();
|
||||
int isOverloadable();
|
||||
|
||||
// LDC
|
||||
std::string intrinsicName;
|
||||
};
|
||||
|
||||
struct TemplateParameter
|
||||
{
|
||||
/* For type-parameter:
|
||||
* template Foo(ident) // specType is set to NULL
|
||||
* template Foo(ident : specType)
|
||||
* For value-parameter:
|
||||
* template Foo(valType ident) // specValue is set to NULL
|
||||
* template Foo(valType ident : specValue)
|
||||
* For alias-parameter:
|
||||
* template Foo(alias ident)
|
||||
* For this-parameter:
|
||||
* template Foo(this ident)
|
||||
*/
|
||||
|
||||
Loc loc;
|
||||
Identifier *ident;
|
||||
|
||||
Declaration *sparam;
|
||||
|
||||
TemplateParameter(Loc loc, Identifier *ident);
|
||||
|
||||
virtual TemplateTypeParameter *isTemplateTypeParameter();
|
||||
virtual TemplateValueParameter *isTemplateValueParameter();
|
||||
virtual TemplateAliasParameter *isTemplateAliasParameter();
|
||||
virtual TemplateThisParameter *isTemplateThisParameter();
|
||||
virtual TemplateTupleParameter *isTemplateTupleParameter();
|
||||
|
||||
virtual TemplateParameter *syntaxCopy() = 0;
|
||||
virtual void declareParameter(Scope *sc) = 0;
|
||||
virtual void semantic(Scope *) = 0;
|
||||
virtual void print(Object *oarg, Object *oded) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
virtual Object *specialization() = 0;
|
||||
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
|
||||
|
||||
/* If TemplateParameter's match as far as overloading goes.
|
||||
*/
|
||||
virtual int overloadMatch(TemplateParameter *) = 0;
|
||||
|
||||
/* Match actual argument against parameter.
|
||||
*/
|
||||
virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
|
||||
|
||||
/* Create dummy argument based on parameter.
|
||||
*/
|
||||
virtual void *dummyArg() = 0;
|
||||
};
|
||||
|
||||
struct TemplateTypeParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident : specType = defaultType
|
||||
*/
|
||||
Type *specType; // type parameter: if !=NULL, this is the type specialization
|
||||
Type *defaultType;
|
||||
|
||||
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
||||
|
||||
TemplateTypeParameter *isTemplateTypeParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct TemplateThisParameter : TemplateTypeParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* this ident : specType = defaultType
|
||||
*/
|
||||
Type *specType; // type parameter: if !=NULL, this is the type specialization
|
||||
Type *defaultType;
|
||||
|
||||
TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
||||
|
||||
TemplateThisParameter *isTemplateThisParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TemplateValueParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* valType ident : specValue = defaultValue
|
||||
*/
|
||||
|
||||
Type *valType;
|
||||
Expression *specValue;
|
||||
Expression *defaultValue;
|
||||
|
||||
static Expression *edummy;
|
||||
|
||||
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
|
||||
|
||||
TemplateValueParameter *isTemplateValueParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateAliasParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* specType ident : specAlias = defaultAlias
|
||||
*/
|
||||
|
||||
Type *specType;
|
||||
Object *specAlias;
|
||||
Object *defaultAlias;
|
||||
|
||||
static Dsymbol *sdummy;
|
||||
|
||||
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
|
||||
|
||||
TemplateAliasParameter *isTemplateAliasParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateTupleParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident ...
|
||||
*/
|
||||
|
||||
TemplateTupleParameter(Loc loc, Identifier *ident);
|
||||
|
||||
TemplateTupleParameter *isTemplateTupleParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateInstance : ScopeDsymbol
|
||||
{
|
||||
/* Given:
|
||||
* foo!(args) =>
|
||||
* name = foo
|
||||
* tiargs = args
|
||||
*/
|
||||
Identifier *name;
|
||||
//Array idents;
|
||||
Objects *tiargs; // Array of Types/Expressions of template
|
||||
// instance arguments [int*, char, 10*10]
|
||||
|
||||
Objects tdtypes; // Array of Types/Expressions corresponding
|
||||
// to TemplateDeclaration.parameters
|
||||
// [int, char, 100]
|
||||
|
||||
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
|
||||
TemplateInstance *inst; // refer to existing instance
|
||||
ScopeDsymbol *argsym; // argument symbol table
|
||||
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
||||
// sole member
|
||||
WithScopeSymbol *withsym; // if a member of a with statement
|
||||
int semanticdone; // has semantic() been done?
|
||||
int semantictiargsdone; // has semanticTiargs() been done?
|
||||
int nest; // for recursion detection
|
||||
int havetempdecl; // 1 if used second constructor
|
||||
Dsymbol *isnested; // if referencing local symbols, this is the context
|
||||
int errors; // 1 if compiled with errors
|
||||
#ifdef IN_GCC
|
||||
/* On some targets, it is necessary to know whether a symbol
|
||||
will be emitted in the output or not before the symbol
|
||||
is used. This can be different from getModule(). */
|
||||
Module * objFileModule;
|
||||
#endif
|
||||
|
||||
TemplateInstance(Loc loc, Identifier *temp_id);
|
||||
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
|
||||
static Objects *arraySyntaxCopy(Objects *objs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Dsymbol *toAlias(); // resolve real symbol
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
|
||||
// Internal
|
||||
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
|
||||
void semanticTiargs(Scope *sc);
|
||||
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
|
||||
TemplateDeclaration *findBestMatch(Scope *sc);
|
||||
void declareParameters(Scope *sc);
|
||||
int isNested(Objects *tiargs);
|
||||
Identifier *genIdent();
|
||||
|
||||
TemplateInstance *isTemplateInstance() { return this; }
|
||||
AliasDeclaration *isAliasDeclaration();
|
||||
|
||||
// LDC
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Module* tmodule; // module from outermost enclosing template instantiation
|
||||
void printInstantiationTrace();
|
||||
};
|
||||
|
||||
struct TemplateMixin : TemplateInstance
|
||||
{
|
||||
Array *idents;
|
||||
Type *tqual;
|
||||
|
||||
Scope *scope; // for forward referencing
|
||||
|
||||
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
int hasPointers();
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
|
||||
TemplateMixin *isTemplateMixin() { return this; }
|
||||
};
|
||||
|
||||
Expression *isExpression(Object *o);
|
||||
Dsymbol *isDsymbol(Object *o);
|
||||
Type *isType(Object *o);
|
||||
Tuple *isTuple(Object *o);
|
||||
Type *getType(Object *o);
|
||||
Dsymbol *getDsymbol(Object *o);
|
||||
|
||||
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
|
||||
|
||||
#endif /* DMD_TEMPLATE_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef DMD_TEMPLATE_H
|
||||
#define DMD_TEMPLATE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
#if IN_LLVM
|
||||
#include <string>
|
||||
#endif
|
||||
#include "root.h"
|
||||
#include "arraytypes.h"
|
||||
#include "dsymbol.h"
|
||||
#if IN_LLVM
|
||||
#include "mtype.h"
|
||||
#endif
|
||||
|
||||
struct OutBuffer;
|
||||
struct Identifier;
|
||||
struct TemplateInstance;
|
||||
struct TemplateParameter;
|
||||
struct TemplateTypeParameter;
|
||||
struct TemplateThisParameter;
|
||||
struct TemplateValueParameter;
|
||||
struct TemplateAliasParameter;
|
||||
struct TemplateTupleParameter;
|
||||
struct Type;
|
||||
struct TypeTypeof;
|
||||
struct Scope;
|
||||
struct Expression;
|
||||
struct AliasDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct HdrGenState;
|
||||
enum MATCH;
|
||||
|
||||
struct Tuple : Object
|
||||
{
|
||||
Objects objects;
|
||||
|
||||
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
|
||||
};
|
||||
|
||||
|
||||
struct TemplateDeclaration : ScopeDsymbol
|
||||
{
|
||||
TemplateParameters *parameters; // array of TemplateParameter's
|
||||
|
||||
TemplateParameters *origParameters; // originals for Ddoc
|
||||
Expression *constraint;
|
||||
Array instances; // array of TemplateInstance's
|
||||
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
TemplateDeclaration *overroot; // first in overnext list
|
||||
|
||||
Scope *scope;
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
int literal; // this template declaration is a literal
|
||||
|
||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
||||
Expression *constraint, Array *decldefs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
char *toChars();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
// void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
|
||||
MATCH leastAsSpecialized(TemplateDeclaration *td2);
|
||||
|
||||
MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
|
||||
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
|
||||
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
|
||||
|
||||
TemplateDeclaration *isTemplateDeclaration() { return this; }
|
||||
|
||||
TemplateTupleParameter *isVariadic();
|
||||
int isOverloadable();
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC
|
||||
std::string intrinsicName;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TemplateParameter
|
||||
{
|
||||
/* For type-parameter:
|
||||
* template Foo(ident) // specType is set to NULL
|
||||
* template Foo(ident : specType)
|
||||
* For value-parameter:
|
||||
* template Foo(valType ident) // specValue is set to NULL
|
||||
* template Foo(valType ident : specValue)
|
||||
* For alias-parameter:
|
||||
* template Foo(alias ident)
|
||||
* For this-parameter:
|
||||
* template Foo(this ident)
|
||||
*/
|
||||
|
||||
Loc loc;
|
||||
Identifier *ident;
|
||||
|
||||
Declaration *sparam;
|
||||
|
||||
TemplateParameter(Loc loc, Identifier *ident);
|
||||
|
||||
virtual TemplateTypeParameter *isTemplateTypeParameter();
|
||||
virtual TemplateValueParameter *isTemplateValueParameter();
|
||||
virtual TemplateAliasParameter *isTemplateAliasParameter();
|
||||
#if DMDV2
|
||||
virtual TemplateThisParameter *isTemplateThisParameter();
|
||||
#endif
|
||||
virtual TemplateTupleParameter *isTemplateTupleParameter();
|
||||
|
||||
virtual TemplateParameter *syntaxCopy() = 0;
|
||||
virtual void declareParameter(Scope *sc) = 0;
|
||||
virtual void semantic(Scope *) = 0;
|
||||
virtual void print(Object *oarg, Object *oded) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
virtual Object *specialization() = 0;
|
||||
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
|
||||
|
||||
/* If TemplateParameter's match as far as overloading goes.
|
||||
*/
|
||||
virtual int overloadMatch(TemplateParameter *) = 0;
|
||||
|
||||
/* Match actual argument against parameter.
|
||||
*/
|
||||
virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
|
||||
|
||||
/* Create dummy argument based on parameter.
|
||||
*/
|
||||
virtual void *dummyArg() = 0;
|
||||
};
|
||||
|
||||
struct TemplateTypeParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident : specType = defaultType
|
||||
*/
|
||||
Type *specType; // type parameter: if !=NULL, this is the type specialization
|
||||
Type *defaultType;
|
||||
|
||||
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
||||
|
||||
TemplateTypeParameter *isTemplateTypeParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct TemplateThisParameter : TemplateTypeParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* this ident : specType = defaultType
|
||||
*/
|
||||
Type *specType; // type parameter: if !=NULL, this is the type specialization
|
||||
Type *defaultType;
|
||||
|
||||
TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
||||
|
||||
TemplateThisParameter *isTemplateThisParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TemplateValueParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* valType ident : specValue = defaultValue
|
||||
*/
|
||||
|
||||
Type *valType;
|
||||
Expression *specValue;
|
||||
Expression *defaultValue;
|
||||
|
||||
static Expression *edummy;
|
||||
|
||||
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
|
||||
|
||||
TemplateValueParameter *isTemplateValueParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateAliasParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* specType ident : specAlias = defaultAlias
|
||||
*/
|
||||
|
||||
Type *specType;
|
||||
Object *specAlias;
|
||||
Object *defaultAlias;
|
||||
|
||||
static Dsymbol *sdummy;
|
||||
|
||||
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
|
||||
|
||||
TemplateAliasParameter *isTemplateAliasParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateTupleParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident ...
|
||||
*/
|
||||
|
||||
TemplateTupleParameter(Loc loc, Identifier *ident);
|
||||
|
||||
TemplateTupleParameter *isTemplateTupleParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateInstance : ScopeDsymbol
|
||||
{
|
||||
/* Given:
|
||||
* foo!(args) =>
|
||||
* name = foo
|
||||
* tiargs = args
|
||||
*/
|
||||
Identifier *name;
|
||||
//Array idents;
|
||||
Objects *tiargs; // Array of Types/Expressions of template
|
||||
// instance arguments [int*, char, 10*10]
|
||||
|
||||
Objects tdtypes; // Array of Types/Expressions corresponding
|
||||
// to TemplateDeclaration.parameters
|
||||
// [int, char, 100]
|
||||
|
||||
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
|
||||
TemplateInstance *inst; // refer to existing instance
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
ScopeDsymbol *argsym; // argument symbol table
|
||||
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
||||
// sole member
|
||||
WithScopeSymbol *withsym; // if a member of a with statement
|
||||
int semanticdone; // has semantic() been done?
|
||||
int semantictiargsdone; // has semanticTiargs() been done?
|
||||
int nest; // for recursion detection
|
||||
int havetempdecl; // 1 if used second constructor
|
||||
Dsymbol *isnested; // if referencing local symbols, this is the context
|
||||
int errors; // 1 if compiled with errors
|
||||
#ifdef IN_GCC
|
||||
/* On some targets, it is necessary to know whether a symbol
|
||||
will be emitted in the output or not before the symbol
|
||||
is used. This can be different from getModule(). */
|
||||
Module * objFileModule;
|
||||
#endif
|
||||
|
||||
TemplateInstance(Loc loc, Identifier *temp_id);
|
||||
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
|
||||
static Objects *arraySyntaxCopy(Objects *objs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Dsymbol *toAlias(); // resolve real symbol
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
void printInstantiationTrace();
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
#endif
|
||||
|
||||
// Internal
|
||||
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
|
||||
void semanticTiargs(Scope *sc);
|
||||
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
|
||||
TemplateDeclaration *findBestMatch(Scope *sc);
|
||||
void declareParameters(Scope *sc);
|
||||
int hasNestedArgs(Objects *tiargs);
|
||||
Identifier *genIdent();
|
||||
|
||||
TemplateInstance *isTemplateInstance() { return this; }
|
||||
AliasDeclaration *isAliasDeclaration();
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC
|
||||
Module* tmodule; // module from outermost enclosing template instantiation
|
||||
Module* emittedInModule; // which module this template instance has been emitted in
|
||||
|
||||
void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TemplateMixin : TemplateInstance
|
||||
{
|
||||
Array *idents;
|
||||
Type *tqual;
|
||||
|
||||
Scope *scope; // for forward referencing
|
||||
|
||||
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps);
|
||||
int hasPointers();
|
||||
char *toChars();
|
||||
char *mangle();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
#endif
|
||||
|
||||
TemplateMixin *isTemplateMixin() { return this; }
|
||||
|
||||
#if IN_LLVM
|
||||
void codegen(Ir*);
|
||||
#endif
|
||||
};
|
||||
|
||||
Expression *isExpression(Object *o);
|
||||
Dsymbol *isDsymbol(Object *o);
|
||||
Type *isType(Object *o);
|
||||
Tuple *isTuple(Object *o);
|
||||
Type *getType(Object *o);
|
||||
Dsymbol *getDsymbol(Object *o);
|
||||
|
||||
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
|
||||
|
||||
#endif /* DMD_TEMPLATE_H */
|
||||
|
||||
@@ -41,5 +41,6 @@
|
||||
#include "id.h"
|
||||
#include "cond.h"
|
||||
#include "version.h"
|
||||
#include "lib.h"
|
||||
|
||||
#endif /* DMD_TOTAL_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -12,25 +12,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
|
||||
#if IN_GCC
|
||||
// Issues with using -include total.h (defines integer_t) and then complex.h fails...
|
||||
#undef integer_t
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
|
||||
#if IN_GCC || IN_LLVM
|
||||
#include "mem.h"
|
||||
#elif _WIN32
|
||||
#include "..\root\mem.h"
|
||||
#elif linux
|
||||
#include "../root/mem.h"
|
||||
#endif
|
||||
#include "rmem.h"
|
||||
|
||||
//#include "port.h"
|
||||
#include "mtype.h"
|
||||
@@ -53,6 +37,8 @@
|
||||
|
||||
#define LOGSEMANTIC 0
|
||||
|
||||
#if DMDV2
|
||||
|
||||
/************************************************
|
||||
* Delegate to be passed to overloadApply() that looks
|
||||
* for virtual functions.
|
||||
@@ -197,7 +183,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
e = isExpression(o);
|
||||
Dsymbol *s = isDsymbol(o);
|
||||
if (t)
|
||||
e = new TypeDotIdExp(loc, t, id);
|
||||
e = typeDotIdExp(loc, t, id);
|
||||
else if (e)
|
||||
e = new DotIdExp(loc, e, id);
|
||||
else if (s)
|
||||
@@ -212,13 +198,10 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
if (ident == Id::hasMember)
|
||||
{ /* Take any errors as meaning it wasn't found
|
||||
*/
|
||||
unsigned errors = global.errors;
|
||||
global.gag++;
|
||||
e = e->semantic(sc);
|
||||
global.gag--;
|
||||
if (errors != global.errors)
|
||||
{ if (global.gag == 0)
|
||||
global.errors = errors;
|
||||
e = e->trySemantic(sc);
|
||||
if (!e)
|
||||
{ if (global.gag)
|
||||
global.errors++;
|
||||
goto Lfalse;
|
||||
}
|
||||
else
|
||||
@@ -255,7 +238,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
Pvirtuals p;
|
||||
p.exps = exps;
|
||||
p.e1 = e;
|
||||
overloadApply(f, fpvirtuals, &p);
|
||||
overloadApply(f->getModule(), f, fpvirtuals, &p);
|
||||
|
||||
TupleExp *tup = new TupleExp(loc, exps);
|
||||
return tup->semantic(sc);
|
||||
@@ -340,16 +323,15 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Object *o = (Object *)args->data[i];
|
||||
Type *t;
|
||||
Expression *e;
|
||||
Dsymbol *s;
|
||||
|
||||
unsigned errors = global.errors;
|
||||
global.gag++;
|
||||
|
||||
t = isType(o);
|
||||
Type *t = isType(o);
|
||||
if (t)
|
||||
{ t->resolve(loc, sc, &e, &t, &s);
|
||||
{ Dsymbol *s;
|
||||
t->resolve(loc, sc, &e, &t, &s);
|
||||
if (t)
|
||||
t->semantic(loc, sc);
|
||||
else if (e)
|
||||
@@ -438,3 +420,4 @@ Ltrue:
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1422,8 +1422,13 @@ bool hasUnalignedFields(Type* t)
|
||||
{
|
||||
t = t->toBasetype();
|
||||
if (t->ty == Tsarray) {
|
||||
#if DMDV2
|
||||
assert(t->nextOf()->size() % t->nextOf()->alignsize() == 0);
|
||||
return hasUnalignedFields(t->nextOf());
|
||||
#else
|
||||
assert(t->next->size() % t->next->alignsize() == 0);
|
||||
return hasUnalignedFields(t->next);
|
||||
#endif
|
||||
} else if (t->ty != Tstruct)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -434,7 +434,11 @@ void TypeInfoEnumDeclaration::llvmDefine()
|
||||
else
|
||||
{
|
||||
const LLType* memty = DtoType(sd->memtype);
|
||||
#if DMDV2
|
||||
LLConstant* C = llvm::ConstantInt::get(memty, sd->defaultval->toInteger(), !sd->memtype->isunsigned());
|
||||
#else
|
||||
LLConstant* C = llvm::ConstantInt::get(memty, sd->defaultval, !sd->memtype->isunsigned());
|
||||
#endif
|
||||
b.push_void_array(C, sd->memtype, sd);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,11 @@ LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
|
||||
"don't implement any interfaces");
|
||||
|
||||
VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
|
||||
#if DMDV2
|
||||
const llvm::Type* InterfaceTy = DtoType(idx->type->nextOf());
|
||||
#else
|
||||
const llvm::Type* InterfaceTy = DtoType(idx->type->next);
|
||||
#endif
|
||||
|
||||
// create Interface[N]
|
||||
const llvm::ArrayType* array_type = llvm::ArrayType::get(InterfaceTy,n);
|
||||
@@ -328,7 +332,11 @@ llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instan
|
||||
|
||||
// start with the interface info
|
||||
VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
|
||||
#if DMDV2
|
||||
Type* first = interfaces_idx->type->nextOf()->pointerTo();
|
||||
#else
|
||||
Type* first = interfaces_idx->type->next->pointerTo();
|
||||
#endif
|
||||
|
||||
// index into the interfaces array
|
||||
llvm::Constant* idxs[2] = {
|
||||
|
||||
@@ -171,7 +171,11 @@ void IrTypeClass::addBaseClassData(
|
||||
ArrayIter<BaseClass> it2(*base->vtblInterfaces);
|
||||
|
||||
VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
|
||||
#if DMDV2
|
||||
Type* first = interfaces_idx->type->nextOf()->pointerTo();
|
||||
#else
|
||||
Type* first = interfaces_idx->type->next->pointerTo();
|
||||
#endif
|
||||
|
||||
// align offset
|
||||
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);
|
||||
|
||||
Reference in New Issue
Block a user