diff options
author | Michi Henning <michi@zeroc.com> | 2002-07-05 00:22:17 +0000 |
---|---|---|
committer | Michi Henning <michi@zeroc.com> | 2002-07-05 00:22:17 +0000 |
commit | 451058a0f311fea3784812ad8b5759170de35afd (patch) | |
tree | eb1367904c39bea9e5b18290255e6491581da196 /cpp/src | |
parent | Fixes from Marc review. (diff) | |
download | ice-451058a0f311fea3784812ad8b5759170de35afd.tar.bz2 ice-451058a0f311fea3784812ad8b5759170de35afd.tar.xz ice-451058a0f311fea3784812ad8b5759170de35afd.zip |
Constant definitions for Slice are complete now. (Code generation for C++
only.) I couldn't avoid adding a few #ifdefs because of the different
64-bit integer APIs across Linux and Windows. (#including config.h
wasn't an option because that would have created a circular dependency
between Ice and Slice.)
Added sufficient test cases to convince myself that things actually work as
intended.
Will compile under Windows now, so bear with me if things are broken under
Windows for a few minutes...
Some things that aren't quite right yet:
- No support for universal character names (\uxxxx)
- gcc appears to have a preprocessor bug. For example, preprocessing a file
containing a single '@' character just echos that '@' character to the
output. According to the C++ spec, '@' should be translated to its
universal character name (because it isn't part of the basic C++ source
character set).
- Why is the Slice string type mapped to std::string? Given that we are
supposed to support unicode for everything, shouldn't that be mapped to
std::wstring?
Once Windows compiles OK, I'll start on the Java code generation.
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/IceUtil/OutputUtil.cpp | 36 | ||||
-rw-r--r-- | cpp/src/Slice/CPlusPlusUtil.cpp | 6 | ||||
-rw-r--r-- | cpp/src/Slice/Grammar.y | 127 | ||||
-rw-r--r-- | cpp/src/Slice/GrammarUtil.h | 18 | ||||
-rw-r--r-- | cpp/src/Slice/Parser.cpp | 69 | ||||
-rw-r--r-- | cpp/src/Slice/Scanner.l | 50 | ||||
-rw-r--r-- | cpp/src/slice2cpp/Gen.cpp | 52 |
7 files changed, 214 insertions, 144 deletions
diff --git a/cpp/src/IceUtil/OutputUtil.cpp b/cpp/src/IceUtil/OutputUtil.cpp index 1759f8bec88..553ff6cf775 100644 --- a/cpp/src/IceUtil/OutputUtil.cpp +++ b/cpp/src/IceUtil/OutputUtil.cpp @@ -188,6 +188,42 @@ IceUtil::OutputBase::operator!() const return !_out; } +streamsize +IceUtil::OutputBase::width() const +{ + return _out.width(); +} + +streamsize +IceUtil::OutputBase::width(streamsize newWidth) +{ + return _out.width(newWidth); +} + +ios_base::fmtflags +IceUtil::OutputBase::flags() const +{ + return _out.flags(); +} + +ios_base::fmtflags +IceUtil::OutputBase::flags(ios_base::fmtflags newFlags) +{ + return _out.flags(newFlags); +} + +ostream::char_type +IceUtil::OutputBase::fill() const +{ + return _out.fill(); +} + +ostream::char_type +IceUtil::OutputBase::fill(ostream::char_type newFill) +{ + return _out.fill(newFill); +} + // ---------------------------------------------------------------------- // Output // ---------------------------------------------------------------------- diff --git a/cpp/src/Slice/CPlusPlusUtil.cpp b/cpp/src/Slice/CPlusPlusUtil.cpp index 719a66c8d1e..0c800c87ac4 100644 --- a/cpp/src/Slice/CPlusPlusUtil.cpp +++ b/cpp/src/Slice/CPlusPlusUtil.cpp @@ -146,6 +146,12 @@ Slice::typeToString(const TypePtr& type) { return contained->scoped(); } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + return en->scoped(); + } return "???"; } diff --git a/cpp/src/Slice/Grammar.y b/cpp/src/Slice/Grammar.y index 59142e02d41..be20f5fbd8b 100644 --- a/cpp/src/Slice/Grammar.y +++ b/cpp/src/Slice/Grammar.y @@ -1288,98 +1288,36 @@ local ; // ---------------------------------------------------------------------- -unary_plus_minus -// ---------------------------------------------------------------------- -: '+' -{ - IntegerTokPtr itp = new IntegerTok; - itp->v = 1; - $$ = itp; -} -| '-' -{ - IntegerTokPtr itp = new IntegerTok; - itp->v = -1; - $$ = itp; -} -; - -// ---------------------------------------------------------------------- -numeric_literal +const_initializer // ---------------------------------------------------------------------- : ICE_INTEGER_LITERAL { + BuiltinPtr type = unit->builtin(Builtin::KindLong); + IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1); + ostringstream sstr; + sstr << intVal->v; + SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; + basestring->v = make_pair(type, sstr.str()); + $$ = basestring; } | ICE_FLOATING_POINT_LITERAL { -} -; - -// ---------------------------------------------------------------------- -numeric_initializer -// ---------------------------------------------------------------------- -: unary_plus_minus numeric_initializer -{ - IntegerTokPtr sign = IntegerTokPtr::dynamicCast($1); - IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($2); - if(intVal) - { - if(sign->v == -1) - { - if(intVal->v < 0 && intVal->v == LONG_MIN) - { - string msg = "integer constant `" + intVal->v; - msg += "' is too large in magnitude to convert to a positive number"; - unit->error(msg); - } - intVal->v *= -1; - } - } - else - { - FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($2); - assert(floatVal); - floatVal->v *= sign->v; - } - $$ = $2; -} -| numeric_literal -{ -} -; - -// ---------------------------------------------------------------------- -const_initializer -// ---------------------------------------------------------------------- -: numeric_initializer -{ - TypeStringTokPtr typestring = new TypeStringTok; + BuiltinPtr type = unit->builtin(Builtin::KindDouble); + FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1); ostringstream sstr; - BuiltinPtr type; - IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1); - if(intVal) - { - type = unit->builtin(Builtin::KindLong); - sstr << intVal->v << ends; - } - else - { - FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1); - assert(floatVal); - type = unit->builtin(Builtin::KindDouble); - sstr << floatVal->v << ends; - } - typestring->v = make_pair(type, sstr.str()); - $$ = typestring; + sstr << floatVal->v; + SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; + basestring->v = make_pair(type, sstr.str()); + $$ = basestring; } | scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($1); - TypeStringTokPtr typestring = new TypeStringTok; + SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; ContainedList cl = unit->currentContainer()->lookupContained(scoped->v); if(cl.empty()) { - typestring->v = make_pair(TypePtr(0), scoped->v); + basestring->v = make_pair(TypePtr(0), scoped->v); } else { @@ -1396,37 +1334,33 @@ const_initializer msg += " " + kindOf; unit->error(msg); } - // Hmmm... there appears to be no way to get from an enumerator - // to its parent enumeration (of type EnumPtr). - // We need this to do the type checking on the enumerations. - EnumPtr type; // TODO: fix this - typestring->v = make_pair(type, scoped->v); + basestring->v = make_pair(enumerator, scoped->v); } - $$ = typestring; + $$ = basestring; } | ICE_STRING_LITERAL { BuiltinPtr type = unit->builtin(Builtin::KindString); StringTokPtr literal = StringTokPtr::dynamicCast($1); - TypeStringTokPtr typestring = new TypeStringTok; - typestring->v = make_pair(type, literal->v); - $$ = typestring; + SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; + basestring->v = make_pair(type, literal->v); + $$ = basestring; } | ICE_FALSE { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast($1); - TypeStringTokPtr typestring = new TypeStringTok; - typestring->v = make_pair(type, literal->v); - $$ = typestring; + SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; + basestring->v = make_pair(type, literal->v); + $$ = basestring; } | ICE_TRUE { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast($1); - TypeStringTokPtr typestring = new TypeStringTok; - typestring->v = make_pair(type, literal->v); - $$ = typestring; + SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; + basestring->v = make_pair(type, literal->v); + $$ = basestring; } ; @@ -1437,9 +1371,14 @@ const_def { TypePtr const_type = TypePtr::dynamicCast($2); StringTokPtr ident = StringTokPtr::dynamicCast($3); - TypeStringTokPtr value = TypeStringTokPtr::dynamicCast($5); + SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast($5); $$ = unit->currentContainer()->createConstDef(ident->v, const_type, value->v.first, value->v.second); } +| ICE_CONST type '=' const_initializer +{ + unit->error("missing constant name"); + YYERROR; // Can't continue, jump to next yyerrok +} ; // ---------------------------------------------------------------------- diff --git a/cpp/src/Slice/GrammarUtil.h b/cpp/src/Slice/GrammarUtil.h index bc349184dc0..a3fc29b74d2 100644 --- a/cpp/src/Slice/GrammarUtil.h +++ b/cpp/src/Slice/GrammarUtil.h @@ -27,6 +27,7 @@ class FloatingTok; class ExceptionListTok; class ClassListTok; class EnumeratorListTok; +class SyntaxTreeBaseStringTok; typedef ::IceUtil::Handle<StringTok> StringTokPtr; typedef ::IceUtil::Handle<StringListTok> StringListTokPtr; @@ -38,6 +39,7 @@ typedef ::IceUtil::Handle<FloatingTok> FloatingTokPtr; typedef ::IceUtil::Handle<ExceptionListTok> ExceptionListTokPtr; typedef ::IceUtil::Handle<ClassListTok> ClassListTokPtr; typedef ::IceUtil::Handle<EnumeratorListTok> EnumeratorListTokPtr; +typedef ::IceUtil::Handle<SyntaxTreeBaseStringTok> SyntaxTreeBaseStringTokPtr; // ---------------------------------------------------------------------- // StringTok @@ -96,7 +98,7 @@ class SLICE_API IntegerTok : public GrammarBase public: IntegerTok() { } - long v; + Long v; }; // ---------------------------------------------------------------------- @@ -108,7 +110,7 @@ class SLICE_API FloatingTok : public GrammarBase public: FloatingTok() { } - double v; + Double v; }; // ---------------------------------------------------------------------- @@ -159,6 +161,18 @@ public: EnumeratorList v; }; +// ---------------------------------------------------------------------- +// SyntaxTreeBaseStringTok +// ---------------------------------------------------------------------- + +class SLICE_API SyntaxTreeBaseStringTok : public GrammarBase +{ +public: + + SyntaxTreeBaseStringTok() { } + SyntaxTreeBaseString v; +}; + } #endif diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 75149005e17..b242b354695 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -654,7 +654,7 @@ Slice::Container::createEnumerator(const string& name) ConstDefPtr Slice::Container::createConstDef(const string name, const TypePtr& constType, - const TypePtr& literalType, const string& value) + const SyntaxTreeBasePtr& literalType, const string& value) { // // Check that the constant name is legal @@ -694,7 +694,7 @@ Slice::Container::createConstDef(const string name, const TypePtr& constType, // // Check that the type of the constant is compatible with the type of the initializer // - if(!constTypesAreCompatible(name, constType, literalType)) + if(!constTypesAreCompatible(name, constType, literalType, value)) { return 0; } @@ -1503,7 +1503,8 @@ Slice::Container::legalConstType(const string& name, const TypePtr& constType, b bool Slice::Container::constTypesAreCompatible(const string& name, const TypePtr& constType, - const TypePtr& literalType, + const SyntaxTreeBasePtr& literalType, + const string& value, bool printError) const { BuiltinPtr ct = BuiltinPtr::dynamicCast(constType); @@ -1513,9 +1514,11 @@ Slice::Container::constTypesAreCompatible(const string& name, switch(ct->kind()) { case Builtin::KindBool: - if(lt->kind() == Builtin::KindBool) { - return true; + if(lt->kind() == Builtin::KindBool) + { + return true; + } break; } case Builtin::KindByte: @@ -1524,47 +1527,58 @@ Slice::Container::constTypesAreCompatible(const string& name, case Builtin::KindLong: { if(lt->kind() == Builtin::KindLong) - return true; + { + return true; + } break; } case Builtin::KindFloat: case Builtin::KindDouble: { if(lt->kind() == Builtin::KindDouble) - return true; + { + return true; + } break; } case Builtin::KindString: { if(lt->kind() == Builtin::KindString) - return true; + { + return true; + } break; } } - string msg = "initializer type `" + lt->kindAsString(); + string msg = "initializer of type `" + lt->kindAsString(); msg += "' is incompatible with the type `" + ct->kindAsString() + "' of constant `" + name + "'"; _unit->error(msg); return false; } + if(ct && !lt) { - string msg = "initializer type is incompatible with the type `" + ct->kindAsString(); + string msg = "type of initializer is incompatible with the type `" + ct->kindAsString(); msg += "' of constant `" + name + "'"; _unit->error(msg); return false; } - EnumPtr ep = EnumPtr::dynamicCast(literalType); - if(ep) + + EnumPtr enumP = EnumPtr::dynamicCast(constType); + assert(enumP); + EnumeratorPtr enumeratorP = EnumeratorPtr::dynamicCast(literalType); + if(!enumeratorP) { - // TODO: check that the left-hand enum type and the right-hand enum type are the same + string msg = "type of initializer is incompatible with the type of constant `" + name + "'"; + _unit->error(msg); + return false; } - // TODO: assert here once the enum problem is fixed -- the right-hand type can only be - // a built-in type or an enumeration; Grammar.y makes sure of that. - if(!ep) + EnumeratorList elist = enumP->getEnumerators(); + if(find(elist.begin(), elist.end(), enumeratorP) == elist.end()) { - // TODO: fix this - string msg = "hmmm... can't cast to enumerator!"; + string msg = "enumerator `" + value + "' is not defined in enumeration `" + enumP->scoped() + "'"; _unit->error(msg); + return false; } return true; } @@ -1580,11 +1594,10 @@ Slice::Container::checkRange(const string& name, const TypePtr& constType, const { case Builtin::KindByte: { - // TODO: need to really do all this with 64-bit longs -- what about Windows? - long l = strtol(value.c_str(), 0, 0); - if(l < 0 || l > 255) + Long l = STRTOLL(value.c_str(), 0, 0); + if(l < BYTE_MIN || l > BYTE_MAX) { - string msg = "initializer for constant `" + name + "' out of range for type byte"; + string msg = "initializer `" + value + "' for constant `" + name + "' out of range for type byte"; _unit->error(msg); return false; } @@ -1592,10 +1605,10 @@ Slice::Container::checkRange(const string& name, const TypePtr& constType, const } case Builtin::KindShort: { - long l = strtol(value.c_str(), 0, 0); - if(l < 32768 || l > 32767) + Long l = STRTOLL(value.c_str(), 0, 0); + if(l < INT16_MIN || l > INT16_MAX) { - string msg = "initializer for constant `" + name + "' out of range for type short"; + string msg = "initializer `" + value + "' for constant `" + name + "' out of range for type short"; _unit->error(msg); return false; } @@ -1603,10 +1616,10 @@ Slice::Container::checkRange(const string& name, const TypePtr& constType, const } case Builtin::KindInt: { - long l = strtol(value.c_str(), 0, 0); - if(l < 2147483648 || l > 2147483647) + Long l = STRTOLL(value.c_str(), 0, 0); + if(l < INT32_MIN || l > INT32_MAX) { - string msg = "initializer for constant `" + name + "' out of range for type int"; + string msg = "initializer `" + value + "' for constant `" + name + "' out of range for type int"; _unit->error(msg); return false; } diff --git a/cpp/src/Slice/Scanner.l b/cpp/src/Slice/Scanner.l index 85d7d868d0a..4cb68b02448 100644 --- a/cpp/src/Slice/Scanner.l +++ b/cpp/src/Slice/Scanner.l @@ -10,8 +10,9 @@ // // ********************************************************************** -#include <Slice/GrammarUtil.h> // Before Grammer.h, so that YYSTYPE is defined +#include <Slice/GrammarUtil.h> // Before Grammer.h, so that YYSTYPE is defined #include <Slice/Grammar.h> + #include <stdlib.h> #include <math.h> @@ -38,7 +39,7 @@ void initScanner(); %option noyywrap %option never-interactive -integer_constant (\+|-)?(0[0-7]+)|(0x[[:xdigit:]]+)|([[:digit:]]+) +integer_constant (\+|-)?((0[0-7]+)|(0x[[:xdigit:]]+)|([[:digit:]]+)) fractional_constant ([[:digit:]]*\.[[:digit:]]+)|([[:digit:]]+\.) exponent_part (e|E)(\+|-)?[[:digit:]]+ floating_literal (({fractional_constant}{exponent_part}?)|([[:digit:]]+{exponent_part}))[fF]? @@ -256,26 +257,25 @@ floating_literal (({fractional_constant}{exponent_part}?)|([[:digit:]]+{exponent } case 'x': { - unsigned long ul = 0; - next = static_cast<char>(yyinput()); - if(isxdigit(next)) + Long ull = 0; + while(isxdigit(next = static_cast<char>(yyinput()))) { - ul *= 16; - if(isdigit(next)) + ull *= 16; + if(isdigit(next)) { - ul += next - '0'; + ull += next - '0'; } else if(islower(next)) { - ul += next - 'a'; + ull += next - 'a' + 10; } else { - ul += next - 'A'; + ull += next - 'A' + 10; } } unput(next); - str->v += static_cast<char>(ul); + str->v += static_cast<char>(ull); break; } @@ -301,18 +301,30 @@ floating_literal (({fractional_constant}{exponent_part}?)|([[:digit:]]+{exponent IntegerTokPtr itp = new IntegerTok; *yylvalp = itp; errno = 0; - itp->v = strtol(yytext, 0, 0); -// -// TODO: strtol() is broken under gcc: it returns an error for -2147483648 (but shouldn't) -// - if(errno == ERANGE && (itp->v == LONG_MAX || itp->v == LONG_MIN)) +#if defined(_WIN32) + itp->v = _atoi64(yytext); + if(itp->v == 0) // Poor error reporting for _atoi64(), so we have to do it the hard way... + { + errno = 0; + long l = strtol(yytext, 0, 0); + if(l != 0 || errno != 0) // _atoi64() returned zero even though yytext wasn't all zeros + { + string msg = "integer constant `"; + msg += yytext; + msg += "' out of range"; + unit->error(msg); + } + } +#else + itp->v = strtoll(yytext, 0, 0); + if(errno == ERANGE) { - string msg = "integer constant `"; + string msg = "integer constant `"; msg += yytext; - msg += "' too "; - msg += itp->v == LONG_MAX ? "large (overflow)" : "small (underflow)"; + msg += "' out of range"; unit->error(msg); } +#endif return ICE_INTEGER_LITERAL; } diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 8c133248975..db6643bf6ba 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -932,7 +932,57 @@ void Slice::Gen::TypesVisitor::visitConstDef(const ConstDefPtr& p) { H << sp; - H << nl << "const " << inputTypeToString(p->type()) << " " << p->name() << " = " << p->value() << ";"; + H << nl << "const " << typeToString(p->type()) << " " << p->name() << " = "; + + BuiltinPtr bp = BuiltinPtr::dynamicCast(p->type()); + if(bp && bp->kind() != Builtin::KindString) + { + H << p->value(); + } + else + { + // + // Expand strings into the basic source character set. We can't use isalpha() and the like + // here because they are sensitive to the current locale. + // + static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "_{}[]#()<>%:;,?*+=/^&|~!=,\\\"' \t"; + static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end()); + + H << "\""; // Opening " + + ios_base::fmtflags originalFlags = H.flags(); // Save stream state + streamsize originalWidth = H.width(); + ostream::char_type originalFill = H.fill(); + + const string val = p->value(); + for(string::const_iterator c = val.begin(); c != val.end(); ++c) + { + if(charSet.find(*c) == charSet.end()) + { + unsigned char uc = *c; // char may be signed, so make it positive + H << "\\"; // Print as octal if not in basic source character set + H.flags(ios_base::oct); + H.width(3); + H.fill('0'); + H << static_cast<unsigned>(uc); + } + else + { + H << *c; // Print normally if in basic source character set + } + } + + H.fill(originalFill); // Restore stream state + H.width(originalWidth); + H.flags(originalFlags); + + H << "\""; // Closing " + } + + H << ";"; } void |