/* Compiler implementation of the D programming language
* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* http://www.boost.org/LICENSE_1_0.txt
* https://github.com/D-Programming-Language/dmd/blob/master/src/version.c
*/
#include "root/dsystem.h"
#include "root/root.h"
#include "identifier.h"
#include "dsymbol.h"
#include "cond.h"
#include "version.h"
#include "module.h"
void checkReserved(Loc loc, const char *ident);
/* ================================================== */
/* DebugSymbol's happen for statements like:
* debug = identifier;
* debug = integer;
*/
DebugSymbol::DebugSymbol(Loc loc, Identifier *ident)
: Dsymbol(ident)
{
this->loc = loc;
}
DebugSymbol::DebugSymbol(Loc loc, unsigned level)
: Dsymbol()
{
this->level = level;
this->loc = loc;
}
const char *DebugSymbol::toChars()
{
if (ident)
return ident->toChars();
else
{
OutBuffer buf;
buf.printf("%d", level);
return buf.extractString();
}
}
Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s)
{
assert(!s);
DebugSymbol *ds = new DebugSymbol(loc, ident);
ds->level = level;
return ds;
}
void DebugSymbol::addMember(Scope *, ScopeDsymbol *sds)
{
//printf("DebugSymbol::addMember('%s') %s\n", sds->toChars(), toChars());
Module *m = sds->isModule();
// Do not add the member to the symbol table,
// just make sure subsequent debug declarations work.
if (ident)
{
if (!m)
{
error("declaration must be at module level");
errors = true;
}
else
{
if (findCondition(m->debugidsNot, ident))
{
error("defined after use");
errors = true;
}
if (!m->debugids)
m->debugids = new Strings();
m->debugids->push(ident->toChars());
}
}
else
{
if (!m)
{
error("level declaration must be at module level");
errors = true;
}
else
m->debuglevel = level;
}
}
void DebugSymbol::semantic(Scope *)
{
//printf("DebugSymbol::semantic() %s\n", toChars());
if (semanticRun < PASSsemanticdone)
semanticRun = PASSsemanticdone;
}
const char *DebugSymbol::kind() const
{
return "debug";
}
/* ================================================== */
/* VersionSymbol's happen for statements like:
* version = identifier;
* version = integer;
*/
VersionSymbol::VersionSymbol(Loc loc, Identifier *ident)
: Dsymbol(ident)
{
this->loc = loc;
}
VersionSymbol::VersionSymbol(Loc loc, unsigned level)
: Dsymbol()
{
this->level = level;
this->loc = loc;
}
const char *VersionSymbol::toChars()
{
if (ident)
return ident->toChars();
else
{
OutBuffer buf;
buf.printf("%d", level);
return buf.extractString();
}
}
Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s)
{
assert(!s);
VersionSymbol *ds = ident ? new VersionSymbol(loc, ident)
: new VersionSymbol(loc, level);
return ds;
}
void VersionSymbol::addMember(Scope *, ScopeDsymbol *sds)
{
//printf("VersionSymbol::addMember('%s') %s\n", sds->toChars(), toChars());
Module *m = sds->isModule();
// Do not add the member to the symbol table,
// just make sure subsequent debug declarations work.
if (ident)
{
checkReserved(loc, ident->toChars());
if (!m)
{
error("declaration must be at module level");
errors = true;
}
else
{
if (findCondition(m->versionidsNot, ident))
{
error("defined after use");
errors = true;
}
if (!m->versionids)
m->versionids = new Strings();
m->versionids->push(ident->toChars());
}
}
else
{
if (!m)
{
error("level declaration must be at module level");
errors = true;
}
else
m->versionlevel = level;
}
}
void VersionSymbol::semantic(Scope *)
{
if (semanticRun < PASSsemanticdone)
semanticRun = PASSsemanticdone;
}
const char *VersionSymbol::kind() const
{
return "version";
}