[svn r134] Merged the DMD 1.024 frontend.

Added std.base64.
This commit is contained in:
Tomas Lindquist Olsen
2007-12-28 23:52:40 +01:00
parent 5eb88f9e80
commit 4428e47a66
14 changed files with 381 additions and 49 deletions

View File

@@ -29,6 +29,7 @@ Declaration::Declaration(Identifier *id)
: Dsymbol(id)
{
type = NULL;
originalType = NULL;
storage_class = STCundefined;
protection = PROTundefined;
linkage = LINKdefault;
@@ -622,9 +623,13 @@ void VarDeclaration::semantic(Scope *sc)
* declarations.
*/
storage_class &= ~STCauto;
originalType = type;
}
else
{ if (!originalType)
originalType = type;
type = type->semantic(loc, sc);
}
type->checkDeprecated(loc, sc);
linkage = sc->linkage;

View File

@@ -91,6 +91,7 @@ int overloadApply(FuncDeclaration *fstart,
struct Declaration : Dsymbol
{
Type *type;
Type *originalType; // before semantic analysis
unsigned storage_class;
enum PROT protection;
enum LINK linkage;
@@ -114,6 +115,7 @@ struct Declaration : Dsymbol
int isFinal() { return storage_class & STCfinal; }
int isAbstract() { return storage_class & STCabstract; }
int isConst() { return storage_class & STCconst; }
int isInvariant() { return 0; }
int isAuto() { return storage_class & STCauto; }
int isScope() { return storage_class & (STCscope | STCauto); }
int isSynchronized() { return storage_class & STCsynchronized; }

View File

@@ -269,7 +269,6 @@ void Module::gendocfile()
}
buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars());
if (isDocFile)
{
size_t commentlen = strlen((char *)comment);
@@ -283,7 +282,6 @@ void Module::gendocfile()
}
else
{
dc->writeSections(sc, this, sc->docbuf);
emitMemberComments(sc);
}
@@ -654,6 +652,10 @@ void prefix(OutBuffer *buf, Dsymbol *s)
buf->writestring("static ");
if (d->isConst())
buf->writestring("const ");
#if V2
if (d->isInvariant())
buf->writestring("invariant ");
#endif
if (d->isFinal())
buf->writestring("final ");
if (d->isSynchronized())
@@ -663,7 +665,7 @@ void prefix(OutBuffer *buf, Dsymbol *s)
void Declaration::toDocBuffer(OutBuffer *buf)
{
//printf("Declaration::toDocbuffer() %s\n", toChars());
//printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType);
if (ident)
{
prefix(buf, this);
@@ -671,7 +673,12 @@ void Declaration::toDocBuffer(OutBuffer *buf)
if (type)
{ HdrGenState hgs;
hgs.ddoc = 1;
type->toCBuffer(buf, ident, &hgs);
if (originalType)
{ //originalType->print();
originalType->toCBuffer(buf, ident, &hgs);
}
else
type->toCBuffer(buf, ident, &hgs);
}
else
buf->writestring(ident->toChars());
@@ -723,10 +730,11 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
td->onemember == this)
{ HdrGenState hgs;
unsigned o = buf->offset;
TypeFunction *tf = (TypeFunction *)type;
hgs.ddoc = 1;
prefix(buf, td);
type->next->toCBuffer(buf, NULL, &hgs);
tf->next->toCBuffer(buf, NULL, &hgs);
buf->writeByte(' ');
buf->writestring(ident->toChars());
buf->writeByte('(');
@@ -738,7 +746,6 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
tp->toCBuffer(buf, &hgs);
}
buf->writeByte(')');
TypeFunction *tf = (TypeFunction *)type;
Argument::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs);
buf->writestring(";\n");

View File

@@ -1270,7 +1270,7 @@ RealExp::RealExp(Loc loc, real_t value, Type *type)
char *RealExp::toChars()
{
static char buffer[sizeof(value) * 3 + 8 + 1 + 1];
char buffer[sizeof(value) * 3 + 8 + 1 + 1];
#ifdef IN_GCC
value.format(buffer, sizeof(buffer));
@@ -1280,7 +1280,7 @@ char *RealExp::toChars()
sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
#endif
assert(strlen(buffer) < sizeof(buffer));
return buffer;
return mem.strdup(buffer);
}
integer_t RealExp::toInteger()
@@ -1484,7 +1484,7 @@ ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
char *ComplexExp::toChars()
{
static char buffer[sizeof(value) * 3 + 8 + 1];
char buffer[sizeof(value) * 3 + 8 + 1];
#ifdef IN_GCC
char buf1[sizeof(value) * 3 + 8 + 1];
@@ -1496,7 +1496,7 @@ char *ComplexExp::toChars()
sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
assert(strlen(buffer) < sizeof(buffer));
#endif
return buffer;
return mem.strdup(buffer);
}
integer_t ComplexExp::toInteger()
@@ -3140,7 +3140,13 @@ Lagain:
if (cd->isInterfaceDeclaration())
error("cannot create instance of interface %s", cd->toChars());
else if (cd->isAbstract())
error("cannot create instance of abstract class %s", cd->toChars());
{ error("cannot create instance of abstract class %s", cd->toChars());
for (int i = 0; i < cd->vtbl.dim; i++)
{ FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
if (fd && fd->isAbstract())
error("function %s is abstract", fd->toChars());
}
}
checkDeprecated(sc, cd);
if (cd->isNested())
{ /* We need a 'this' pointer for the nested class.
@@ -5528,9 +5534,9 @@ Lagain:
TemplateDeclaration *td = dte->td;
assert(td);
if (!arguments)
// Should fix deduce() so it works on NULL argument
// Should fix deduceFunctionTemplate() so it works on NULL argument
arguments = new Expressions();
f = td->deduce(sc, loc, NULL, arguments);
f = td->deduceFunctionTemplate(sc, loc, NULL, arguments);
if (!f)
{ type = Type::terror;
return this;
@@ -5705,7 +5711,7 @@ Lagain:
else if (e1->op == TOKtemplate)
{
TemplateExp *te = (TemplateExp *)e1;
f = te->td->deduce(sc, loc, NULL, arguments);
f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments);
if (!f)
{ type = Type::terror;
return this;

View File

@@ -145,6 +145,9 @@ void FuncDeclaration::semantic(Scope *sc)
if (isAbstract() && !isVirtual())
error("non-virtual functions cannot be abstract");
if (isAbstract() && isFinal())
error("cannot be both final and abstract");
#if 0
if (isAbstract() && fbody)
error("abstract functions cannot have bodies");

View File

@@ -71,7 +71,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2007 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
llvmdc_version = "0.1";
version = "v1.023";
version = "v1.024";
global.structalign = 8;
memset(&params, 0, sizeof(Param));

View File

@@ -87,6 +87,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
vmoduleinfo = NULL;
massert = NULL;
marray = NULL;
sictor = NULL;
sctor = NULL;
sdtor = NULL;
stest = NULL;

View File

@@ -147,6 +147,7 @@ struct Module : Package
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

View File

@@ -2742,38 +2742,50 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
//printf("TypeFunction::semantic() this = %p\n", this);
linkage = sc->linkage;
if (!next)
TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
memcpy(tf, this, sizeof(TypeFunction));
if (parameters)
{ tf->parameters = (Arguments *)parameters->copy();
for (size_t i = 0; i < parameters->dim; i++)
{ Argument *arg = (Argument *)parameters->data[i];
Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
memcpy(cpy, arg, sizeof(Argument));
tf->parameters->data[i] = (void *)cpy;
}
}
tf->linkage = sc->linkage;
if (!tf->next)
{
assert(global.errors);
next = tvoid;
tf->next = tvoid;
}
next = next->semantic(loc,sc);
if (next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", next->toChars());
next = Type::terror;
tf->next = tf->next->semantic(loc,sc);
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
tf->next = Type::terror;
}
if (next->toBasetype()->ty == Tfunction)
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
next = Type::terror;
tf->next = Type::terror;
}
if (next->toBasetype()->ty == Ttuple)
if (tf->next->toBasetype()->ty == Ttuple)
{ error(loc, "functions cannot return a tuple");
next = Type::terror;
tf->next = Type::terror;
}
if (next->isauto() && !(sc->flags & SCOPEctor))
error(loc, "functions cannot return auto %s", next->toChars());
if (tf->next->isauto() && !(sc->flags & SCOPEctor))
error(loc, "functions cannot return auto %s", tf->next->toChars());
if (parameters)
{ size_t dim = Argument::dim(parameters);
if (tf->parameters)
{ size_t dim = Argument::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{ Argument *arg = Argument::getNth(parameters, i);
{ Argument *arg = Argument::getNth(tf->parameters, i);
Type *t;
inuse++;
tf->inuse++;
arg->type = arg->type->semantic(loc,sc);
if (inuse == 1) inuse--;
if (tf->inuse == 1) tf->inuse--;
t = arg->type->toBasetype();
if (arg->storageClass & (STCout | STCref | STClazy))
@@ -2795,27 +2807,27 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
* change.
*/
if (t->ty == Ttuple)
{ dim = Argument::dim(parameters);
{ dim = Argument::dim(tf->parameters);
i--;
}
}
}
deco = merge()->deco;
tf->deco = tf->merge()->deco;
if (inuse)
if (tf->inuse)
{ error(loc, "recursive type");
inuse = 0;
tf->inuse = 0;
return terror;
}
if (varargs == 1 && linkage != LINKd && Argument::dim(parameters) == 0)
if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
error(loc, "variadic functions with non-D linkage must have at least one parameter");
/* Don't return merge(), because arg identifiers and default args
* can be different
* even though the types match
*/
return this;
return tf;
}
/********************************

View File

@@ -729,7 +729,7 @@ static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc lo
FuncDeclaration *fd;
assert(td);
fd = td->deduce(sc, loc, targsi, arguments);
fd = td->deduceFunctionTemplate(sc, loc, targsi, arguments);
if (!fd)
return;
m->anyf = fd;

View File

@@ -647,7 +647,7 @@ int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
* dedargs Expression/Type deduced template arguments
*/
MATCH TemplateDeclaration::deduceMatch(Objects *targsi, Expressions *fargs,
MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
Objects *dedargs)
{
size_t i;
@@ -662,7 +662,7 @@ MATCH TemplateDeclaration::deduceMatch(Objects *targsi, Expressions *fargs,
Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
#if 0
printf("\nTemplateDeclaration::deduceMatch() %s\n", toChars());
printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
for (i = 0; i < fargs->dim; i++)
{ Expression *e = (Expression *)fargs->data[i];
printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
@@ -985,7 +985,7 @@ int TemplateDeclaration::isOverloadable()
* fargs arguments to function
*/
FuncDeclaration *TemplateDeclaration::deduce(Scope *sc, Loc loc,
FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
Objects *targsi, Expressions *fargs)
{
MATCH m_best = MATCHnomatch;
@@ -996,7 +996,7 @@ FuncDeclaration *TemplateDeclaration::deduce(Scope *sc, Loc loc,
FuncDeclaration *fd;
#if 0
printf("TemplateDeclaration::deduce() %s\n", toChars());
printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
printf(" targsi:\n");
if (targsi)
{ for (int i = 0; i < targsi->dim; i++)
@@ -1028,8 +1028,8 @@ FuncDeclaration *TemplateDeclaration::deduce(Scope *sc, Loc loc,
MATCH m;
Objects dedargs;
m = td->deduceMatch(targsi, fargs, &dedargs);
//printf("deduceMatch = %d\n", m);
m = td->deduceFunctionTemplateMatch(targsi, fargs, &dedargs);
//printf("deduceFunctionTemplateMatch = %d\n", m);
if (!m) // if no match
continue;

View File

@@ -71,8 +71,8 @@ struct TemplateDeclaration : ScopeDsymbol
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
int leastAsSpecialized(TemplateDeclaration *td2);
MATCH deduceMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduce(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
MATCH deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
TemplateDeclaration *isTemplateDeclaration() { return this; }

View File

@@ -2,16 +2,18 @@ module phobos;
import
std.array,
std.base64,
std.ctype,
std.format,
std.intrinsic,
std.math,
std.moduleinit,
std.outofmemory,
std.stdarg,
std.stdint,
std.stdio,
std.stdarg,
std.string,
std.traits,
std.uni,
std.utf,

293
lphobos/std/base64.d Normal file
View File

@@ -0,0 +1,293 @@
/**
* Encodes/decodes MIME base64 data.
*
* Macros:
* WIKI=Phobos/StdBase64
* References:
* <a href="http://en.wikipedia.org/wiki/Base64">Wikipedia Base64</a>$(BR)
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>$(BR)
*/
/* base64.d
* Modified from C. Miller's version, his copyright is below.
*/
/*
Copyright (C) 2004 Christopher E. Miller
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
module std.base64;
/**
*/
class Base64Exception: Exception
{
this(char[] msg)
{
super(msg);
}
}
/**
*/
class Base64CharException: Base64Exception
{
this(char[] msg)
{
super(msg);
}
}
const char[] array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* Returns the number of bytes needed to encode a string of length slen.
*/
uint encodeLength(uint slen)
{
uint result;
result = slen / 3;
if(slen % 3)
result++;
return result * 4;
}
/**
* Encodes str[] and places the result in buf[].
* Params:
* str = string to encode
* buf = destination buffer, must be large enough for the result.
* Returns:
* slice into buf[] representing encoded result
*/
char[] encode(char[] str, char[] buf)
in
{
assert(buf.length >= encodeLength(str.length));
}
body
{
if(!str.length)
return buf[0 .. 0];
uint stri;
uint strmax = str.length / 3;
uint strleft = str.length % 3;
uint x;
char* sp, bp;
bp = &buf[0];
sp = &str[0];
for(stri = 0; stri != strmax; stri++)
{
x = (sp[0] << 16) | (sp[1] << 8) | (sp[2]);
sp+= 3;
*bp++ = array[(x & 0b11111100_00000000_00000000) >> 18];
*bp++ = array[(x & 0b00000011_11110000_00000000) >> 12];
*bp++ = array[(x & 0b00000000_00001111_11000000) >> 6];
*bp++ = array[(x & 0b00000000_00000000_00111111)];
}
switch(strleft)
{
case 2:
x = (sp[0] << 16) | (sp[1] << 8);
sp += 2;
*bp++ = array[(x & 0b11111100_00000000_00000000) >> 18];
*bp++ = array[(x & 0b00000011_11110000_00000000) >> 12];
*bp++ = array[(x & 0b00000000_00001111_11000000) >> 6];
*bp++ = '=';
break;
case 1:
x = *sp++ << 16;
*bp++ = array[(x & 0b11111100_00000000_00000000) >> 18];
*bp++ = array[(x & 0b00000011_11110000_00000000) >> 12];
*bp++ = '=';
*bp++ = '=';
break;
case 0:
break;
default:
assert(0);
}
return buf[0 .. (bp - &buf[0])];
}
/**
* Encodes str[] and returns the result.
*/
char[] encode(char[] str)
{
return encode(str, new char[encodeLength(str.length)]);
}
unittest
{
assert(encode("f") == "Zg==");
assert(encode("fo") == "Zm8=");
assert(encode("foo") == "Zm9v");
assert(encode("foos") == "Zm9vcw==");
assert(encode("all your base64 are belong to foo") == "YWxsIHlvdXIgYmFzZTY0IGFyZSBiZWxvbmcgdG8gZm9v");
}
/**
* Returns the number of bytes needed to decode an encoded string of this
* length.
*/
uint decodeLength(uint elen)
{
return elen / 4 * 3;
}
/**
* Decodes str[] and places the result in buf[].
* Params:
* str = string to encode
* buf = destination buffer, must be large enough for the result.
* Returns:
* slice into buf[] representing encoded result
* Errors:
* Throws Base64Exception on invalid base64 encoding in estr[].
* Throws Base64CharException on invalid base64 character in estr[].
*/
char[] decode(char[] estr, char[] buf)
in
{
assert(buf.length + 2 >= decodeLength(estr.length)); //account for '=' padding
}
body
{
void badc(char ch)
{
throw new Base64CharException("Invalid base64 character '" ~ (&ch)[0 .. 1] ~ "'");
}
uint arrayIndex(char ch)
out(result)
{
assert(ch == array[result]);
}
body
{
if(ch >= 'A' && ch <= 'Z')
return ch - 'A';
if(ch >= 'a' && ch <= 'z')
return 'Z' - 'A' + 1 + ch - 'a';
if(ch >= '0' && ch <= '9')
return 'Z' - 'A' + 1 + 'z' - 'a' + 1 + ch - '0';
if(ch == '+')
return 'Z' - 'A' + 1 + 'z' - 'a' + 1 + '9' - '0' + 1;
if(ch == '/')
return 'Z' - 'A' + 1 + 'z' - 'a' + 1 + '9' - '0' + 1 + 1;
badc(ch);
assert(0);
}
if(!estr.length)
return buf[0 .. 0];
if(estr.length % 4)
throw new Base64Exception("Invalid encoded base64 string");
uint estri;
uint estrmax = estr.length / 4;
uint x;
char* sp, bp;
char ch;
sp = &estr[0];
bp = &buf[0];
for(estri = 0; estri != estrmax; estri++)
{
x = arrayIndex(sp[0]) << 18 | arrayIndex(sp[1]) << 12;
sp += 2;
ch = *sp++;
if(ch == '=')
{
if(*sp++ != '=')
badc('=');
*bp++ = cast(char) (x >> 16);
break;
}
x |= arrayIndex(ch) << 6;
ch = *sp++;
if(ch == '=')
{
*bp++ = cast(char) (x >> 16);
*bp++ = cast(char) ((x >> 8) & 0xFF);
break;
}
x |= arrayIndex(ch);
*bp++ = cast(char) (x >> 16);
*bp++ = cast(char) ((x >> 8) & 0xFF);
*bp++ = cast(char) (x & 0xFF);
}
return buf[0 .. (bp - &buf[0])];
}
/**
* Decodes estr[] and returns the result.
* Errors:
* Throws Base64Exception on invalid base64 encoding in estr[].
* Throws Base64CharException on invalid base64 character in estr[].
*/
char[] decode(char[] estr)
{
return decode(estr, new char[decodeLength(estr.length)]);
}
unittest
{
assert(decode(encode("f")) == "f");
assert(decode(encode("fo")) == "fo");
assert(decode(encode("foo")) == "foo");
assert(decode(encode("foos")) == "foos");
assert(decode(encode("all your base64 are belong to foo")) == "all your base64 are belong to foo");
assert(decode(encode("testing some more")) == "testing some more");
assert(decode(encode("asdf jkl;")) == "asdf jkl;");
assert(decode(encode("base64 stuff")) == "base64 stuff");
assert(decode(encode("\1\2\3\4\5\6\7foo\7\6\5\4\3\2\1!")) == "\1\2\3\4\5\6\7foo\7\6\5\4\3\2\1!");
}