summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2004-01-16 22:22:44 +0000
committerMark Spruiell <mes@zeroc.com>2004-01-16 22:22:44 +0000
commit00081d77200a08baac2e62cc2797c7530caacea3 (patch)
tree69a638dc86939389e9c810946a7d0fef20a31cd4 /cpp/src
parentadding ClassDef::isA (diff)
downloadice-00081d77200a08baac2e62cc2797c7530caacea3.tar.bz2
ice-00081d77200a08baac2e62cc2797c7530caacea3.tar.xz
ice-00081d77200a08baac2e62cc2797c7530caacea3.zip
initial check-in
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/FreezeScript/.depend15
-rw-r--r--cpp/src/FreezeScript/AssignVisitor.cpp598
-rw-r--r--cpp/src/FreezeScript/AssignVisitor.h59
-rw-r--r--cpp/src/FreezeScript/Data.cpp2637
-rw-r--r--cpp/src/FreezeScript/Data.h639
-rw-r--r--cpp/src/FreezeScript/Error.cpp193
-rw-r--r--cpp/src/FreezeScript/Error.h73
-rw-r--r--cpp/src/FreezeScript/Exception.cpp62
-rw-r--r--cpp/src/FreezeScript/Exception.h43
-rw-r--r--cpp/src/FreezeScript/Functions.cpp350
-rw-r--r--cpp/src/FreezeScript/Functions.h31
-rw-r--r--cpp/src/FreezeScript/Grammar.y320
-rw-r--r--cpp/src/FreezeScript/GrammarUtil.h141
-rw-r--r--cpp/src/FreezeScript/Makefile57
-rw-r--r--cpp/src/FreezeScript/Parser.cpp691
-rw-r--r--cpp/src/FreezeScript/Parser.h255
-rw-r--r--cpp/src/FreezeScript/Print.cpp240
-rw-r--r--cpp/src/FreezeScript/Print.h27
-rw-r--r--cpp/src/FreezeScript/Scanner.l376
-rw-r--r--cpp/src/FreezeScript/TransformAnalyzer.cpp1143
-rw-r--r--cpp/src/FreezeScript/TransformAnalyzer.h41
-rw-r--r--cpp/src/FreezeScript/TransformDescriptors.cpp2283
-rw-r--r--cpp/src/FreezeScript/TransformDescriptors.h353
-rw-r--r--cpp/src/FreezeScript/TransformVisitor.cpp901
-rw-r--r--cpp/src/FreezeScript/TransformVisitor.h112
-rw-r--r--cpp/src/FreezeScript/Transformer.cpp310
-rw-r--r--cpp/src/FreezeScript/Transformer.h54
-rw-r--r--cpp/src/FreezeScript/Util.cpp273
-rw-r--r--cpp/src/FreezeScript/Util.h66
-rw-r--r--cpp/src/FreezeScript/transformdb.cpp645
-rw-r--r--cpp/src/FreezeScript/transformdb.dsp304
31 files changed, 13292 insertions, 0 deletions
diff --git a/cpp/src/FreezeScript/.depend b/cpp/src/FreezeScript/.depend
new file mode 100644
index 00000000000..64d33f7b8ad
--- /dev/null
+++ b/cpp/src/FreezeScript/.depend
@@ -0,0 +1,15 @@
+Grammar.o: Grammar.cpp ../FreezeScript/GrammarUtil.h ../FreezeScript/Parser.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h
+Scanner.o: Scanner.cpp ../../include/IceUtil/Config.h ../FreezeScript/GrammarUtil.h ../FreezeScript/Parser.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/Grammar.h
+AssignVisitor.o: AssignVisitor.cpp ../FreezeScript/AssignVisitor.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/Util.h
+Data.o: Data.cpp ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/Util.h ../FreezeScript/Exception.h
+Error.o: Error.cpp ../FreezeScript/Error.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Exception.h ../FreezeScript/Util.h
+Functions.o: Functions.cpp ../FreezeScript/Functions.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/Util.h ../../include/IceUtil/UUID.h
+Exception.o: Exception.cpp ../FreezeScript/Exception.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h
+Parser.o: Parser.cpp ../FreezeScript/Parser.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/GrammarUtil.h
+Print.o: Print.cpp ../FreezeScript/Print.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/Util.h ../../include/IceUtil/OutputUtil.h
+TransformAnalyzer.o: TransformAnalyzer.cpp ../FreezeScript/TransformAnalyzer.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Util.h ../../include/IceUtil/OutputUtil.h
+TransformDescriptors.o: TransformDescriptors.cpp ../FreezeScript/TransformDescriptors.h ../FreezeScript/Parser.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/TransformVisitor.h ../../include/IceXML/Parser.h ../FreezeScript/AssignVisitor.h ../FreezeScript/Print.h ../FreezeScript/Functions.h ../FreezeScript/Exception.h ../FreezeScript/Util.h ../../include/IceUtil/UUID.h
+TransformVisitor.o: TransformVisitor.cpp ../FreezeScript/TransformVisitor.h ../FreezeScript/Data.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Error.h ../FreezeScript/Util.h
+Transformer.o: Transformer.cpp ../FreezeScript/Transformer.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Exception.h ../FreezeScript/TransformDescriptors.h ../FreezeScript/Parser.h ../FreezeScript/Data.h ../FreezeScript/Error.h ../FreezeScript/TransformVisitor.h ../../include/IceXML/Parser.h ../FreezeScript/TransformAnalyzer.h ../FreezeScript/Util.h
+Util.o: Util.cpp ../FreezeScript/Util.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Exception.h ../../include/Slice/Preprocessor.h
+TransformDB.o: TransformDB.cpp ../FreezeScript/Transformer.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/Identity.h ../../include/Ice/Facet.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/Outgoing.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/BasicStream.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/Buffer.h ../../include/Ice/Incoming.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/ServantManagerF.h ../../include/Ice/Direct.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocator.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Application.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../FreezeScript/Exception.h ../FreezeScript/Util.h
diff --git a/cpp/src/FreezeScript/AssignVisitor.cpp b/cpp/src/FreezeScript/AssignVisitor.cpp
new file mode 100644
index 00000000000..1037e6e96a3
--- /dev/null
+++ b/cpp/src/FreezeScript/AssignVisitor.cpp
@@ -0,0 +1,598 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/AssignVisitor.h>
+#include <FreezeScript/Util.h>
+
+using namespace std;
+
+FreezeScript::AssignVisitor::AssignVisitor(const DataPtr& src, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter, bool convert,
+ const string& context) :
+ _src(src), _factory(factory), _errorReporter(errorReporter), _convert(convert),
+ _context(context)
+{
+}
+
+void
+FreezeScript::AssignVisitor::visitBoolean(const BooleanDataPtr& dest)
+{
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string v = s->getValue();
+ if(v == "true")
+ {
+ dest->setValue(true);
+ }
+ else if(v == "false")
+ {
+ dest->setValue(false);
+ }
+ else
+ {
+ conversionError(dest->getType(), _src->getType(), v);
+ }
+ }
+ else
+ {
+ dest->setValue(_src->booleanValue(_convert));
+ }
+}
+
+void
+FreezeScript::AssignVisitor::visitInteger(const IntegerDataPtr& dest)
+{
+ dest->setValue(_src->integerValue(_convert), true);
+}
+
+void
+FreezeScript::AssignVisitor::visitDouble(const DoubleDataPtr& dest)
+{
+ dest->setValue(_src->doubleValue(_convert));
+}
+
+void
+FreezeScript::AssignVisitor::visitString(const StringDataPtr& dest)
+{
+ dest->setValue(_src->stringValue(_convert));
+}
+
+void
+FreezeScript::AssignVisitor::visitProxy(const ProxyDataPtr& dest)
+{
+ ProxyDataPtr p = ProxyDataPtr::dynamicCast(_src);
+ if(p)
+ {
+ dest->setValue(p->getValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ dest->setValue(s->getValue(), false);
+ }
+ else
+ {
+ typeMismatchError(dest->getType(), _src->getType());
+ }
+ }
+}
+
+void
+FreezeScript::AssignVisitor::visitStruct(const StructDataPtr& dest)
+{
+ Slice::StructPtr type = Slice::StructPtr::dynamicCast(dest->getType());
+ assert(type);
+ StructDataPtr src = StructDataPtr::dynamicCast(_src);
+ if(src && isCompatible(type, src->getType()))
+ {
+ //
+ // Assign members with the same name.
+ //
+ DataMemberMap srcMap = src->getMembers();
+ DataMemberMap destMap = dest->getMembers();
+ string typeName = typeToString(type);
+ for(DataMemberMap::iterator p = destMap.begin(); p != destMap.end(); ++p)
+ {
+ DataMemberMap::iterator q = srcMap.find(p->first);
+ if(q != srcMap.end())
+ {
+ string context = typeName + " member " + p->first + " value";
+ AssignVisitor v(q->second, _factory, _errorReporter, _convert, context);
+ p->second->visit(v);
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+}
+
+void
+FreezeScript::AssignVisitor::visitSequence(const SequenceDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ SequenceDataPtr src = SequenceDataPtr::dynamicCast(_src);
+ if(src && isCompatible(type, src->getType()))
+ {
+ DataList& srcElements = src->getElements();
+ DataList destElements;
+ Slice::SequencePtr seqType = Slice::SequencePtr::dynamicCast(type);
+ assert(seqType);
+ Slice::TypePtr elemType = seqType->type();
+ string typeName = typeToString(type);
+ for(DataList::const_iterator p = srcElements.begin(); p != srcElements.end(); ++p)
+ {
+ DataPtr element = _factory->create(elemType, false);
+ Destroyer<DataPtr> elementDestroyer(element);
+ AssignVisitor v(*p, _factory, _errorReporter, _convert, typeName + " element");
+ element->visit(v);
+ destElements.push_back(element);
+ elementDestroyer.release();
+ }
+ DataList& l = dest->getElements();
+ l.swap(destElements);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+}
+
+void
+FreezeScript::AssignVisitor::visitEnum(const EnumDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ IntegerDataPtr i = IntegerDataPtr::dynamicCast(_src);
+ if(i)
+ {
+ if(_convert)
+ {
+ if(!dest->setValue(i->integerValue()))
+ {
+ rangeError(i->toString(), type);
+ }
+ }
+ else
+ {
+ conversionError(type, i->getType(), i->toString());
+ }
+ }
+ else
+ {
+ string name;
+ EnumDataPtr e = EnumDataPtr::dynamicCast(_src);
+ if(e && isCompatible(type, _src->getType()))
+ {
+ name = e->toString();
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ name = s->getValue();
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+
+ if(!dest->setValueAsString(name))
+ {
+ conversionError(type, _src->getType(), name);
+ }
+ }
+}
+
+void
+FreezeScript::AssignVisitor::visitDictionary(const DictionaryDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ DictionaryDataPtr d = DictionaryDataPtr::dynamicCast(_src);
+ if(d && isCompatible(type, _src->getType()))
+ {
+ DataMap& srcMap = d->getElements();
+ DataMap destMap;
+ Slice::DictionaryPtr dictType = Slice::DictionaryPtr::dynamicCast(type);
+ assert(dictType);
+ Slice::TypePtr keyType = dictType->keyType();
+ Slice::TypePtr valueType = dictType->valueType();
+ string typeName = typeToString(type);
+ for(DataMap::const_iterator p = srcMap.begin(); p != srcMap.end(); ++p)
+ {
+ DataPtr key = _factory->create(keyType, false);
+ Destroyer<DataPtr> keyDestroyer(key);
+ DataPtr value = _factory->create(valueType, false);
+ Destroyer<DataPtr> valueDestroyer(value);
+
+ AssignVisitor keyVisitor(p->first, _factory, _errorReporter, _convert, typeName + " key");
+ key->visit(keyVisitor);
+
+ AssignVisitor valueVisitor(p->second, _factory, _errorReporter, _convert, typeName + " value");
+ value->visit(valueVisitor);
+
+ DataMap::const_iterator q = destMap.find(key);
+ if(q != destMap.end())
+ {
+ error("duplicate dictionary key in " + typeToString(dictType));
+ }
+ else
+ {
+ destMap.insert(DataMap::value_type(key, value));
+ keyDestroyer.release();
+ valueDestroyer.release();
+ }
+ }
+ DataMap& m = dest->getElements();
+ m.swap(destMap);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+}
+
+void
+FreezeScript::AssignVisitor::visitObject(const ObjectRefPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ ObjectRefPtr src = ObjectRefPtr::dynamicCast(_src);
+ if(!src)
+ {
+ typeMismatchError(type, _src->getType());
+ }
+
+ ObjectDataPtr srcValue = src->getValue();
+ Slice::TypePtr srcType = src->getType();
+ if(!srcValue)
+ {
+ //
+ // Allow a nil value from type Object.
+ //
+ if(Slice::BuiltinPtr::dynamicCast(srcType) || isCompatible(type, srcType))
+ {
+ dest->setValue(0);
+ }
+ else
+ {
+ typeMismatchError(type, srcType);
+ }
+ }
+ else
+ {
+ Slice::TypePtr srcValueType = srcValue->getType();
+ if(isCompatible(type, srcValueType))
+ {
+ dest->setValue(srcValue);
+ }
+ else
+ {
+ typeMismatchError(type, srcValueType);
+ }
+ }
+}
+
+bool
+FreezeScript::AssignVisitor::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ Slice::BuiltinPtr b1 = Slice::BuiltinPtr::dynamicCast(dest);
+ if(b1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ switch(b1->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindString:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindBool:
+ {
+ if(b2 && (b2->kind() == Slice::Builtin::KindBool || b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindString:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObjectProxy:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+
+ return false;
+ }
+ else if(Slice::EnumPtr::dynamicCast(src))
+ {
+ return true;
+ }
+ else if(Slice::ProxyPtr::dynamicCast(src))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindObject:
+ {
+ //
+ // Allow transformation from Object to class. Validation has to
+ // be done during transformation, when the actual type of
+ // an instance can be compared for compatibility with the
+ // new type.
+ //
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(src);
+ if(cl || (b2 && b2->kind() == Slice::Builtin::KindObject))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindObjectProxy:
+ {
+ Slice::ProxyPtr p = Slice::ProxyPtr::dynamicCast(src);
+ if(p || (b2 && b2->kind() == Slice::Builtin::KindObjectProxy) ||
+ (b2 && b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindLocalObject:
+ {
+ assert(false);
+ return false;
+ }
+ }
+
+ assert(false);
+ }
+
+ Slice::ClassDeclPtr cl1 = Slice::ClassDeclPtr::dynamicCast(dest);
+ if(cl1)
+ {
+ Slice::ClassDeclPtr cl2 = Slice::ClassDeclPtr::dynamicCast(src);
+ if(cl2 && checkClasses(cl1, cl2))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::StructPtr s1 = Slice::StructPtr::dynamicCast(dest);
+ if(s1)
+ {
+ Slice::StructPtr s2 = Slice::StructPtr::dynamicCast(src);
+ if(s2 && s1->scoped() == s2->scoped())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::ProxyPtr p1 = Slice::ProxyPtr::dynamicCast(dest);
+ if(p1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ if(b2 && (b2->kind() == Slice::Builtin::KindObjectProxy || b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ Slice::ProxyPtr p2 = Slice::ProxyPtr::dynamicCast(src);
+ if(p2 && checkClasses(p1->_class(), p2->_class()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::DictionaryPtr d1 = Slice::DictionaryPtr::dynamicCast(dest);
+ if(d1)
+ {
+ Slice::DictionaryPtr d2 = Slice::DictionaryPtr::dynamicCast(src);
+ if(d2)
+ {
+ return isCompatible(d1->keyType(), d2->keyType()) &&
+ isCompatible(d1->valueType(), d2->valueType());
+ }
+
+ return false;
+ }
+
+ Slice::SequencePtr seq1 = Slice::SequencePtr::dynamicCast(dest);
+ if(seq1)
+ {
+ Slice::SequencePtr seq2 = Slice::SequencePtr::dynamicCast(src);
+ if(seq2)
+ {
+ return isCompatible(seq1->type(), seq2->type());
+ }
+
+ return false;
+ }
+
+ Slice::EnumPtr e1 = Slice::EnumPtr::dynamicCast(dest);
+ if(e1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ if(b2 && b2->kind() == Slice::Builtin::KindString)
+ {
+ return true;
+ }
+
+ Slice::EnumPtr e2 = Slice::EnumPtr::dynamicCast(src);
+ if(e2 && e1->scoped() == e2->scoped())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ assert(false);
+ return false;
+}
+
+bool
+FreezeScript::AssignVisitor::checkClasses(const Slice::ClassDeclPtr& dest, const Slice::ClassDeclPtr& src)
+{
+ string s1 = dest->scoped();
+ string s2 = src->scoped();
+ if(s1 == s2)
+ {
+ return true;
+ }
+ else
+ {
+ Slice::ClassDefPtr def = src->definition();
+ if(!def)
+ {
+ error("class " + s2 + " declared but not defined");
+ }
+ return def->isA(s1);
+ }
+
+ return false;
+}
+
+void
+FreezeScript::AssignVisitor::typeMismatchError(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ ostringstream ostr;
+ ostr << "unable to transform";
+ if(!_context.empty())
+ {
+ ostr << ' ' << _context;
+ }
+ ostr << " from " << typeToString(src) << " to " << typeToString(dest);
+ error(ostr.str());
+}
+
+void
+FreezeScript::AssignVisitor::conversionError(const Slice::TypePtr& dest, const Slice::TypePtr& src,
+ const string& value)
+{
+ ostringstream ostr;
+ ostr << "unable to convert";
+ if(!_context.empty())
+ {
+ ostr << ' ' << _context;
+ }
+ ostr << " `" << value << "' from " << typeToString(src) << " to " << typeToString(dest);
+ error(ostr.str());
+}
+
+void
+FreezeScript::AssignVisitor::rangeError(const string& value, const Slice::TypePtr& type)
+{
+ ostringstream ostr;
+ if(!_context.empty())
+ {
+ ostr << _context << ' ';
+ }
+ ostr << "`" << value << "' is out of range for type " << typeToString(type);
+ error(ostr.str());
+}
+
+void
+FreezeScript::AssignVisitor::error(const string& msg)
+{
+ _errorReporter->error(msg);
+}
diff --git a/cpp/src/FreezeScript/AssignVisitor.h b/cpp/src/FreezeScript/AssignVisitor.h
new file mode 100644
index 00000000000..f9a4d4031d5
--- /dev/null
+++ b/cpp/src/FreezeScript/AssignVisitor.h
@@ -0,0 +1,59 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_ASSIGN_VISITOR_H
+#define FREEZE_SCRIPT_ASSIGN_VISITOR_H
+
+#include <FreezeScript/Data.h>
+
+namespace FreezeScript
+{
+
+class AssignVisitor : public DataVisitor
+{
+public:
+
+ AssignVisitor(const DataPtr&, const DataFactoryPtr&, const ErrorReporterPtr&, bool,
+ const std::string& = std::string());
+
+ virtual void visitBoolean(const BooleanDataPtr&);
+ virtual void visitInteger(const IntegerDataPtr&);
+ virtual void visitDouble(const DoubleDataPtr&);
+ virtual void visitString(const StringDataPtr&);
+ virtual void visitProxy(const ProxyDataPtr&);
+ virtual void visitStruct(const StructDataPtr&);
+ virtual void visitSequence(const SequenceDataPtr&);
+ virtual void visitEnum(const EnumDataPtr&);
+ virtual void visitDictionary(const DictionaryDataPtr&);
+ virtual void visitObject(const ObjectRefPtr&);
+
+private:
+
+ bool isCompatible(const Slice::TypePtr&, const Slice::TypePtr&);
+ bool checkClasses(const Slice::ClassDeclPtr&, const Slice::ClassDeclPtr&);
+ void typeMismatchError(const Slice::TypePtr&, const Slice::TypePtr&);
+ void conversionError(const Slice::TypePtr&, const Slice::TypePtr&, const std::string&);
+ void rangeError(const std::string&, const Slice::TypePtr&);
+ void error(const std::string&);
+
+ DataPtr _src;
+ DataFactoryPtr _factory;
+ ErrorReporterPtr _errorReporter;
+ bool _convert;
+ std::string _context; // Provides additional detail for use in warning messages.
+};
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Data.cpp b/cpp/src/FreezeScript/Data.cpp
new file mode 100644
index 00000000000..63d56ef8354
--- /dev/null
+++ b/cpp/src/FreezeScript/Data.cpp
@@ -0,0 +1,2637 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Data.h>
+#include <FreezeScript/Util.h>
+#include <FreezeScript/Exception.h>
+#include <IceUtil/InputUtil.h>
+
+using namespace std;
+using namespace IceUtil;
+
+namespace FreezeScript
+{
+
+//
+// ObjectWriter
+//
+class ObjectWriter : public Ice::Object
+{
+public:
+
+ ObjectWriter(const ObjectDataPtr&);
+
+ virtual void __write(IceInternal::BasicStream*, bool) const;
+ virtual void __read(IceInternal::BasicStream*, bool = true);
+
+private:
+
+ ObjectDataPtr _value;
+};
+
+//
+// ObjectReader
+//
+class ObjectReader : public Ice::Object
+{
+public:
+
+ ObjectReader(const DataFactoryPtr&, const Slice::TypePtr&);
+
+ virtual void __write(IceInternal::BasicStream*, bool) const;
+ virtual void __read(IceInternal::BasicStream*, bool = true);
+
+ ObjectDataPtr getValue() const;
+
+private:
+
+ DataFactoryPtr _factory;
+ Slice::TypePtr _type;
+ ObjectDataPtr _value;
+};
+typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr;
+
+} // End of namespace Transform
+
+//
+// ObjectWriter
+//
+FreezeScript::ObjectWriter::ObjectWriter(const ObjectDataPtr& value) :
+ _value(value)
+{
+}
+
+void
+FreezeScript::ObjectWriter::__write(IceInternal::BasicStream* os, bool) const
+{
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(_value->_type);
+ Slice::ClassDefPtr type;
+ if(decl)
+ {
+ type = decl->definition();
+ }
+ while(type)
+ {
+ os->writeTypeId(type->scoped());
+ os->startWriteSlice();
+ Slice::DataMemberList members = type->dataMembers();
+ for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = _value->_members.find((*p)->name());
+ assert(q != _value->_members.end());
+ q->second->marshal(*os);
+ }
+ os->endWriteSlice();
+
+ Slice::ClassList bases = type->bases();
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ type = bases.front();
+ }
+ else
+ {
+ type = 0;
+ }
+ }
+
+ //
+ // Ice::Object slice
+ //
+ os->writeTypeId(Ice::Object::ice_staticId());
+ os->startWriteSlice();
+ _value->_facetMap->marshal(*os);
+ os->endWriteSlice();
+}
+
+void
+FreezeScript::ObjectWriter::__read(IceInternal::BasicStream*, bool)
+{
+ assert(false);
+}
+
+//
+// ObjectReader
+//
+FreezeScript::ObjectReader::ObjectReader(const DataFactoryPtr& factory, const Slice::TypePtr& type) :
+ _factory(factory), _type(type)
+{
+}
+
+void
+FreezeScript::ObjectReader::__write(IceInternal::BasicStream*, bool) const
+{
+ assert(false);
+}
+
+void
+FreezeScript::ObjectReader::__read(IceInternal::BasicStream* is, bool rid)
+{
+ const_cast<ObjectDataPtr&>(_value) = new ObjectData(_factory, _type, true);
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(_type);
+ Slice::ClassDefPtr type;
+ if(decl)
+ {
+ type = decl->definition();
+ }
+ while(type)
+ {
+ if(rid)
+ {
+ string id;
+ is->readTypeId(id);
+ assert(id == type->scoped());
+ }
+
+ is->startReadSlice();
+ Slice::DataMemberList members = type->dataMembers();
+ for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
+ {
+ DataMemberMap::iterator q = _value->_members.find((*p)->name());
+ assert(q != _value->_members.end());
+ q->second->unmarshal(*is);
+ }
+ is->endReadSlice();
+
+ Slice::ClassList bases = type->bases();
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ type = bases.front();
+ }
+ else
+ {
+ type = 0;
+ }
+
+ rid = true;
+ }
+
+ //
+ // Ice::Object slice
+ //
+ if(rid)
+ {
+ string id;
+ is->readTypeId(id);
+ if(id != Ice::Object::ice_staticId())
+ {
+ throw Ice::MarshalException(__FILE__, __LINE__);
+ }
+ }
+ is->startReadSlice();
+ _value->_facetMap->unmarshal(*is);
+ is->endReadSlice();
+}
+
+FreezeScript::ObjectDataPtr
+FreezeScript::ObjectReader::getValue() const
+{
+ return _value;
+}
+
+//
+// DataInitializer
+//
+FreezeScript::DataInitializer::~DataInitializer()
+{
+}
+
+//
+// DataFactory
+//
+FreezeScript::DataFactory::DataFactory(const Ice::CommunicatorPtr& communicator, const Slice::UnitPtr& unit,
+ const ErrorReporterPtr& errorReporter) :
+ _communicator(communicator), _unit(unit), _errorReporter(errorReporter), _initializersEnabled(true)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::create(const Slice::TypePtr& type, bool readOnly)
+{
+ DataPtr data = createImpl(type, readOnly);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createBoolean(bool b, bool readOnly)
+{
+ DataPtr data = new BooleanData(getBuiltin(Slice::Builtin::KindBool), _errorReporter, readOnly, b);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createInteger(Ice::Long i, bool readOnly)
+{
+ DataPtr data = new IntegerData(getBuiltin(Slice::Builtin::KindLong), _errorReporter, readOnly, i);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createDouble(double d, bool readOnly)
+{
+ DataPtr data = new DoubleData(getBuiltin(Slice::Builtin::KindDouble), _errorReporter, readOnly, d);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createString(const string& s, bool readOnly)
+{
+ DataPtr data = new StringData(this, getBuiltin(Slice::Builtin::KindString), _errorReporter, readOnly, s);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createNil(bool readOnly)
+{
+ DataPtr data = new ObjectRef(this, getBuiltin(Slice::Builtin::KindObject), readOnly);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createObject(const Slice::TypePtr& type, bool readOnly)
+{
+ ObjectRefPtr obj;
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ Slice::ClassDefPtr def = cl->definition();
+ if(!def)
+ {
+ _errorReporter->error("class " + cl->scoped() + " declared but not defined");
+ }
+ obj = new ObjectRef(this, cl, readOnly);
+ }
+ else
+ {
+ Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type);
+ if(b && b->kind() == Slice::Builtin::KindObject)
+ {
+ obj = new ObjectRef(this, b, readOnly);
+ }
+ }
+
+ if(!obj)
+ {
+ _errorReporter->error("type `" + typeToString(type) + "' is not a class");
+ }
+
+ obj->instantiate();
+
+ if(!readOnly)
+ {
+ initialize(obj);
+ }
+
+ return obj;
+}
+
+Slice::BuiltinPtr
+FreezeScript::DataFactory::getBuiltin(Slice::Builtin::Kind kind) const
+{
+ return _unit->builtin(kind);
+}
+
+void
+FreezeScript::DataFactory::addInitializer(const string& type, const DataInitializerPtr& init)
+{
+ _initializers.insert(InitMap::value_type(type, init));
+}
+
+void
+FreezeScript::DataFactory::enableInitializers()
+{
+ _initializersEnabled = true;
+}
+
+void
+FreezeScript::DataFactory::disableInitializers()
+{
+ _initializersEnabled = false;
+}
+
+Ice::CommunicatorPtr
+FreezeScript::DataFactory::getCommunicator() const
+{
+ return _communicator;
+}
+
+FreezeScript::ErrorReporterPtr
+FreezeScript::DataFactory::getErrorReporter() const
+{
+ return _errorReporter;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataFactory::createImpl(const Slice::TypePtr& type, bool readOnly)
+{
+ Slice::BuiltinPtr builtin = Slice::BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Slice::Builtin::KindBool:
+ return new BooleanData(builtin, _errorReporter, readOnly);
+
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ return new IntegerData(builtin, _errorReporter, readOnly);
+
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ return new DoubleData(builtin, _errorReporter, readOnly);
+
+ case Slice::Builtin::KindString:
+ return new StringData(this, builtin, _errorReporter, readOnly);
+
+ case Slice::Builtin::KindObject:
+ return new ObjectRef(this, builtin, readOnly);
+
+ case Slice::Builtin::KindObjectProxy:
+ return new ProxyData(builtin, _communicator, _errorReporter, readOnly);
+
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ return 0;
+ }
+ }
+
+ Slice::SequencePtr seq = Slice::SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return new SequenceData(this, seq, _errorReporter, readOnly);
+ }
+
+ Slice::ProxyPtr proxy = Slice::ProxyPtr::dynamicCast(type);
+ if(proxy)
+ {
+ return new ProxyData(proxy, _communicator, _errorReporter, readOnly);
+ }
+
+ Slice::StructPtr st = Slice::StructPtr::dynamicCast(type);
+ if(st)
+ {
+ return new StructData(this, st, _errorReporter, readOnly);
+ }
+
+ Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ return new EnumData(en, _errorReporter, readOnly);
+ }
+
+ Slice::DictionaryPtr dict = Slice::DictionaryPtr::dynamicCast(type);
+ if(dict)
+ {
+ return new DictionaryData(this, dict, _errorReporter, readOnly);
+ }
+
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ Slice::ClassDefPtr def = cl->definition();
+ if(!def)
+ {
+ _errorReporter->error("class " + cl->scoped() + " declared but not defined");
+ }
+ return new ObjectRef(this, cl, readOnly);
+ }
+
+ return 0;
+}
+
+void
+FreezeScript::DataFactory::initialize(const DataPtr& data)
+{
+ if(_initializersEnabled)
+ {
+ string name = typeToString(data->getType());
+ InitMap::iterator p = _initializers.find(name);
+ if(p != _initializers.end())
+ {
+ p->second->initialize(this, data, _communicator);
+ }
+ }
+}
+
+//
+// Data
+//
+FreezeScript::Data::Data(const ErrorReporterPtr& errorReporter, bool readOnly) :
+ _errorReporter(errorReporter), _readOnly(readOnly)
+{
+}
+
+FreezeScript::Data::~Data()
+{
+}
+
+bool
+FreezeScript::Data::readOnly() const
+{
+ return _readOnly;
+}
+
+//
+// PrimitiveData
+//
+FreezeScript::PrimitiveData::PrimitiveData(const ErrorReporterPtr& errorReporter, bool readOnly) :
+ Data(errorReporter, readOnly)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::PrimitiveData::getMember(const string&) const
+{
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::PrimitiveData::getElement(const DataPtr&) const
+{
+ _errorReporter->error("element requested of primitive value");
+ return 0;
+}
+
+void
+FreezeScript::PrimitiveData::destroy()
+{
+}
+
+//
+// BooleanData
+//
+FreezeScript::BooleanData::BooleanData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly) :
+ PrimitiveData(errorReporter, readOnly), _type(type), _value(false)
+{
+}
+
+FreezeScript::BooleanData::BooleanData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly, bool value) :
+ PrimitiveData(errorReporter, readOnly), _type(type), _value(value)
+{
+}
+
+bool
+FreezeScript::BooleanData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::BooleanData::operator!=(const Data& rhs) const
+{
+ const BooleanData* b = dynamic_cast<const BooleanData*>(&rhs);
+ if(!b)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value != b->_value;
+}
+
+bool
+FreezeScript::BooleanData::operator<(const Data& rhs) const
+{
+ const BooleanData* b = dynamic_cast<const BooleanData*>(&rhs);
+ if(!b)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value < b->_value;
+}
+
+FreezeScript::DataPtr
+FreezeScript::BooleanData::clone() const
+{
+ return new BooleanData(_type, _errorReporter, _readOnly, _value);
+}
+
+Slice::TypePtr
+FreezeScript::BooleanData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::BooleanData::marshal(IceInternal::BasicStream& os) const
+{
+ os.write(_value);
+}
+
+void
+FreezeScript::BooleanData::unmarshal(IceInternal::BasicStream& is)
+{
+ is.read(_value);
+}
+
+bool
+FreezeScript::BooleanData::booleanValue(bool) const
+{
+ return _value;
+}
+
+Ice::Long
+FreezeScript::BooleanData::integerValue(bool) const
+{
+ _errorReporter->error("boolean cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::BooleanData::doubleValue(bool) const
+{
+ _errorReporter->error("boolean cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::BooleanData::stringValue(bool convert) const
+{
+ if(convert)
+ {
+ return toString();
+ }
+ else
+ {
+ return string();
+ }
+}
+
+string
+FreezeScript::BooleanData::toString() const
+{
+ return (_value ? "true" : "false");
+}
+
+void
+FreezeScript::BooleanData::visit(DataVisitor& visitor)
+{
+ visitor.visitBoolean(this);
+}
+
+bool
+FreezeScript::BooleanData::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::BooleanData::setValue(bool v)
+{
+ _value = v;
+}
+
+//
+// IntegerData
+//
+FreezeScript::IntegerData::IntegerData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly) :
+ PrimitiveData(errorReporter, readOnly), _type(type), _value(0)
+{
+}
+
+FreezeScript::IntegerData::IntegerData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly, Ice::Long value) :
+ PrimitiveData(errorReporter, readOnly), _type(type), _value(value)
+{
+}
+
+bool
+FreezeScript::IntegerData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::IntegerData::operator!=(const Data& rhs) const
+{
+ const IntegerData* i = dynamic_cast<const IntegerData*>(&rhs);
+ if(!i)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value != i->_value;
+}
+
+bool
+FreezeScript::IntegerData::operator<(const Data& rhs) const
+{
+ const IntegerData* i = dynamic_cast<const IntegerData*>(&rhs);
+ if(!i)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value < i->_value;
+}
+
+FreezeScript::DataPtr
+FreezeScript::IntegerData::clone() const
+{
+ return new IntegerData(_type, _errorReporter, _readOnly, _value);
+}
+
+Slice::TypePtr
+FreezeScript::IntegerData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::IntegerData::marshal(IceInternal::BasicStream& os) const
+{
+ rangeCheck(_value, true);
+
+ switch(_type->kind())
+ {
+ case Slice::Builtin::KindByte:
+ {
+ os.write(static_cast<Ice::Byte>(_value));
+ break;
+ }
+ case Slice::Builtin::KindShort:
+ {
+ os.write(static_cast<Ice::Short>(_value));
+ break;
+ }
+ case Slice::Builtin::KindInt:
+ {
+ os.write(static_cast<Ice::Int>(_value));
+ break;
+ }
+ case Slice::Builtin::KindLong:
+ {
+ os.write(_value);
+ break;
+ }
+
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+}
+
+void
+FreezeScript::IntegerData::unmarshal(IceInternal::BasicStream& is)
+{
+ switch(_type->kind())
+ {
+ case Slice::Builtin::KindByte:
+ {
+ Ice::Byte val;
+ is.read(val);
+ _value = val & 0xff;
+ break;
+ }
+ case Slice::Builtin::KindShort:
+ {
+ Ice::Short val;
+ is.read(val);
+ _value = val;
+ break;
+ }
+ case Slice::Builtin::KindInt:
+ {
+ Ice::Int val;
+ is.read(val);
+ _value = val;
+ break;
+ }
+ case Slice::Builtin::KindLong:
+ {
+ is.read(_value);
+ break;
+ }
+
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+}
+
+bool
+FreezeScript::IntegerData::booleanValue(bool) const
+{
+ _errorReporter->error("integer cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::IntegerData::integerValue(bool) const
+{
+ return _value;
+}
+
+double
+FreezeScript::IntegerData::doubleValue(bool convert) const
+{
+ if(convert)
+ {
+ return static_cast<double>(_value);
+ }
+ else
+ {
+ _errorReporter->error("integer cannot be converted to double");
+ return 0;
+ }
+}
+
+string
+FreezeScript::IntegerData::stringValue(bool convert) const
+{
+ if(convert)
+ {
+ return toString();
+ }
+ else
+ {
+ _errorReporter->error("integer cannot be converted to string");
+ return string();
+ }
+}
+
+string
+FreezeScript::IntegerData::toString() const
+{
+ return toString(_value);
+}
+
+void
+FreezeScript::IntegerData::visit(DataVisitor& visitor)
+{
+ visitor.visitInteger(this);
+}
+
+Ice::Long
+FreezeScript::IntegerData::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::IntegerData::setValue(Ice::Long v, bool fatal)
+{
+ if(rangeCheck(v, fatal))
+ {
+ _value = v;
+ }
+}
+
+bool
+FreezeScript::IntegerData::rangeCheck(Ice::Long value, bool fatal) const
+{
+ switch(_type->kind())
+ {
+ case Slice::Builtin::KindByte:
+ {
+ if(value < 0 || value > 255)
+ {
+ _errorReporter->rangeError(toString(value), _type, fatal);
+ }
+ else
+ {
+ return true;
+ }
+ break;
+ }
+
+ case Slice::Builtin::KindShort:
+ {
+ if(value < SHRT_MIN || value > SHRT_MAX)
+ {
+ _errorReporter->rangeError(toString(value), _type, fatal);
+ }
+ else
+ {
+ return true;
+ }
+ break;
+ }
+
+ case Slice::Builtin::KindInt:
+ {
+ if(value < INT_MIN || value > INT_MAX)
+ {
+ _errorReporter->rangeError(toString(value), _type, fatal);
+ }
+ else
+ {
+ return true;
+ }
+ break;
+ }
+
+ case Slice::Builtin::KindLong:
+ {
+ return true;
+ }
+
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+
+ return false;
+}
+
+string
+FreezeScript::IntegerData::toString(Ice::Long value)
+{
+ char buf[64];
+#ifdef WIN32
+ sprintf(buf, "%I64d", value);
+#else
+ sprintf(buf, "%lld", value);
+#endif
+ return string(buf);
+}
+
+//
+// DoubleData
+//
+FreezeScript::DoubleData::DoubleData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly) :
+ PrimitiveData(errorReporter, readOnly), _type(type), _value(0)
+{
+}
+
+FreezeScript::DoubleData::DoubleData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly, double value) :
+ PrimitiveData(errorReporter, readOnly), _type(type), _value(value)
+{
+}
+
+bool
+FreezeScript::DoubleData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::DoubleData::operator!=(const Data& rhs) const
+{
+ const DoubleData* d = dynamic_cast<const DoubleData*>(&rhs);
+ if(!d)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value != d->_value;
+}
+
+bool
+FreezeScript::DoubleData::operator<(const Data& rhs) const
+{
+ const DoubleData* d = dynamic_cast<const DoubleData*>(&rhs);
+ if(!d)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value < d->_value;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DoubleData::clone() const
+{
+ return new DoubleData(_type, _errorReporter, _readOnly, _value);
+}
+
+Slice::TypePtr
+FreezeScript::DoubleData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::DoubleData::marshal(IceInternal::BasicStream& os) const
+{
+ switch(_type->kind())
+ {
+ case Slice::Builtin::KindFloat:
+ {
+ os.write(static_cast<Ice::Float>(_value));
+ break;
+ }
+ case Slice::Builtin::KindDouble:
+ {
+ os.write(_value);
+ break;
+ }
+
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+}
+
+void
+FreezeScript::DoubleData::unmarshal(IceInternal::BasicStream& is)
+{
+ switch(_type->kind())
+ {
+ case Slice::Builtin::KindFloat:
+ {
+ Ice::Float val;
+ is.read(val);
+ _value = val;
+ break;
+ }
+ case Slice::Builtin::KindDouble:
+ {
+ is.read(_value);
+ break;
+ }
+
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+}
+
+bool
+FreezeScript::DoubleData::booleanValue(bool) const
+{
+ _errorReporter->error("double cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::DoubleData::integerValue(bool convert) const
+{
+ if(convert)
+ {
+ return static_cast<Ice::Long>(_value);
+ }
+ else
+ {
+ _errorReporter->error("double cannot be converted to integer");
+ return 0;
+ }
+}
+
+double
+FreezeScript::DoubleData::doubleValue(bool) const
+{
+ return _value;
+}
+
+string
+FreezeScript::DoubleData::stringValue(bool convert) const
+{
+ if(convert)
+ {
+ return toString();
+ }
+ else
+ {
+ _errorReporter->error("double cannot be converted to string");
+ return string();
+ }
+}
+
+string
+FreezeScript::DoubleData::toString() const
+{
+ char buff[64];
+ sprintf(buff, "%g", _value);
+ return string(buff);
+}
+
+void
+FreezeScript::DoubleData::visit(DataVisitor& visitor)
+{
+ visitor.visitDouble(this);
+}
+
+double
+FreezeScript::DoubleData::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::DoubleData::setValue(double v)
+{
+ _value = v;
+}
+
+//
+// StringData
+//
+FreezeScript::StringData::StringData(const DataFactoryPtr& factory, const Slice::BuiltinPtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly) :
+ PrimitiveData(errorReporter, readOnly), _factory(factory), _type(type)
+{
+ setValue("");
+}
+
+FreezeScript::StringData::StringData(const DataFactoryPtr& factory, const Slice::BuiltinPtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly, const string& value) :
+ PrimitiveData(errorReporter, readOnly), _factory(factory), _type(type)
+{
+ setValue(value);
+}
+
+FreezeScript::DataPtr
+FreezeScript::StringData::getMember(const string& member) const
+{
+ if(member == "length")
+ {
+ _length->setValue(static_cast<Ice::Long>(_value.size()), false);
+ return _length;
+ }
+
+ return 0;
+}
+
+bool
+FreezeScript::StringData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::StringData::operator!=(const Data& rhs) const
+{
+ const StringData* s = dynamic_cast<const StringData*>(&rhs);
+ if(!s)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value != s->_value;
+}
+
+bool
+FreezeScript::StringData::operator<(const Data& rhs) const
+{
+ const StringData* s = dynamic_cast<const StringData*>(&rhs);
+ if(!s)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value < s->_value;
+}
+
+FreezeScript::DataPtr
+FreezeScript::StringData::clone() const
+{
+ return new StringData(_factory, _type, _errorReporter, _readOnly, _value);
+}
+
+Slice::TypePtr
+FreezeScript::StringData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::StringData::marshal(IceInternal::BasicStream& os) const
+{
+ os.write(_value);
+}
+
+void
+FreezeScript::StringData::unmarshal(IceInternal::BasicStream& is)
+{
+ string s;
+ is.read(s);
+ setValue(s);
+}
+
+bool
+FreezeScript::StringData::booleanValue(bool) const
+{
+ _errorReporter->error("string cannot be converted to boolean");
+ return false;
+}
+
+Ice::Long
+FreezeScript::StringData::integerValue(bool) const
+{
+ _errorReporter->error("string cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::StringData::doubleValue(bool) const
+{
+ _errorReporter->error("string cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::StringData::stringValue(bool) const
+{
+ return _value;
+}
+
+string
+FreezeScript::StringData::toString() const
+{
+ return _value;
+}
+
+void
+FreezeScript::StringData::visit(DataVisitor& visitor)
+{
+ visitor.visitString(this);
+}
+
+string
+FreezeScript::StringData::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::StringData::setValue(const string& v)
+{
+ _value = v;
+}
+
+//
+// ProxyData
+//
+FreezeScript::ProxyData::ProxyData(const Slice::TypePtr& type, const Ice::CommunicatorPtr& communicator,
+ const ErrorReporterPtr& errorReporter, bool readOnly) :
+ Data(errorReporter, readOnly), _type(type), _communicator(communicator)
+{
+}
+
+FreezeScript::ProxyData::ProxyData(const Slice::TypePtr& type, const Ice::CommunicatorPtr& communicator,
+ const ErrorReporterPtr& errorReporter, bool readOnly, const Ice::ObjectPrx& value) :
+ Data(errorReporter, readOnly), _type(type), _communicator(communicator), _value(value)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::ProxyData::getMember(const string& member) const
+{
+ // TODO: Support members (id, facet, etc.)?
+
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::ProxyData::getElement(const DataPtr&) const
+{
+ _errorReporter->error("element requested of proxy value");
+ return 0;
+}
+
+bool
+FreezeScript::ProxyData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::ProxyData::operator!=(const Data& rhs) const
+{
+ const ProxyData* p = dynamic_cast<const ProxyData*>(&rhs);
+ if(!p)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value != p->_value;
+}
+
+bool
+FreezeScript::ProxyData::operator<(const Data& rhs) const
+{
+ const ProxyData* p = dynamic_cast<const ProxyData*>(&rhs);
+ if(!p)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value < p->_value;
+}
+
+FreezeScript::DataPtr
+FreezeScript::ProxyData::clone() const
+{
+ return new ProxyData(_type, _communicator, _errorReporter, _readOnly, _value);
+}
+
+Slice::TypePtr
+FreezeScript::ProxyData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::ProxyData::destroy()
+{
+}
+
+void
+FreezeScript::ProxyData::marshal(IceInternal::BasicStream& os) const
+{
+ os.write(_value);
+}
+
+void
+FreezeScript::ProxyData::unmarshal(IceInternal::BasicStream& is)
+{
+ is.read(_value);
+}
+
+bool
+FreezeScript::ProxyData::booleanValue(bool) const
+{
+ _errorReporter->error("proxy cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::ProxyData::integerValue(bool) const
+{
+ _errorReporter->error("proxy cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::ProxyData::doubleValue(bool) const
+{
+ _errorReporter->error("proxy cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::ProxyData::stringValue(bool) const
+{
+ _errorReporter->error("proxy cannot be converted to string");
+ return string();
+}
+
+string
+FreezeScript::ProxyData::toString() const
+{
+ if(_value && _str.empty())
+ {
+ const_cast<string&>(_str) = _communicator->proxyToString(_value);
+ }
+ return _str;
+}
+
+void
+FreezeScript::ProxyData::visit(DataVisitor& visitor)
+{
+ visitor.visitProxy(this);
+}
+
+Ice::ObjectPrx
+FreezeScript::ProxyData::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::ProxyData::setValue(const string& str, bool fatal)
+{
+ try
+ {
+ _value = _communicator->stringToProxy(str);
+ _str = str;
+ }
+ catch(const Ice::LocalException&)
+ {
+ _errorReporter->conversionError(str, _type, fatal);
+ }
+}
+
+void
+FreezeScript::ProxyData::setValue(const Ice::ObjectPrx& v)
+{
+ _value = v;
+ _str.clear();
+}
+
+
+//
+// StructData
+//
+FreezeScript::StructData::StructData(const DataFactoryPtr& factory, const Slice::StructPtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly) :
+ Data(errorReporter, readOnly), _type(type)
+{
+ Slice::DataMemberList members = type->dataMembers();
+ for(Slice::DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ {
+ DataPtr value = factory->create((*q)->type(), _readOnly);
+ assert(value);
+ _members[(*q)->name()] = value;
+ }
+}
+
+FreezeScript::StructData::StructData(const Slice::StructPtr& type, const ErrorReporterPtr& errorReporter,
+ bool readOnly, const DataMemberMap& members) :
+ Data(errorReporter, readOnly), _type(type)
+{
+ for(DataMemberMap::const_iterator p = members.begin(); p != members.end(); ++p)
+ {
+ _members[p->first] = p->second->clone();
+ }
+}
+
+FreezeScript::DataPtr
+FreezeScript::StructData::getMember(const string& member) const
+{
+ DataMemberMap::const_iterator p = _members.find(member);
+ if(p != _members.end())
+ {
+ return p->second;
+ }
+
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::StructData::getElement(const DataPtr&) const
+{
+ _errorReporter->error("element requested of struct value");
+ return 0;
+}
+
+bool
+FreezeScript::StructData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::StructData::operator!=(const Data& rhs) const
+{
+ const StructData* s = dynamic_cast<const StructData*>(&rhs);
+ if(!s || _type->scoped() != s->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ assert(_members.size() == s->_members.size());
+
+ for(DataMemberMap::const_iterator p = _members.begin(); p != _members.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = s->_members.find(p->first);
+ assert(q != s->_members.end());
+
+ if(p->second != q->second)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+FreezeScript::StructData::operator<(const Data& rhs) const
+{
+ const StructData* s = dynamic_cast<const StructData*>(&rhs);
+ if(!s || _type->scoped() != s->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ assert(_members.size() == s->_members.size());
+
+ for(DataMemberMap::const_iterator p = _members.begin(); p != _members.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = s->_members.find(p->first);
+ assert(q != s->_members.end());
+
+ if(p->second < q->second)
+ {
+ return true;
+ }
+ else if(q->second < p->second)
+ {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+FreezeScript::DataPtr
+FreezeScript::StructData::clone() const
+{
+ return new StructData(_type, _errorReporter, _readOnly, _members);
+}
+
+Slice::TypePtr
+FreezeScript::StructData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::StructData::destroy()
+{
+ for(DataMemberMap::const_iterator p = _members.begin(); p != _members.end(); ++p)
+ {
+ p->second->destroy();
+ }
+}
+
+void
+FreezeScript::StructData::marshal(IceInternal::BasicStream& os) const
+{
+ Slice::DataMemberList members = _type->dataMembers();
+ for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = _members.find((*p)->name());
+ assert(q != _members.end());
+ q->second->marshal(os);
+ }
+}
+
+void
+FreezeScript::StructData::unmarshal(IceInternal::BasicStream& is)
+{
+ Slice::DataMemberList members = _type->dataMembers();
+ for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = _members.find((*p)->name());
+ assert(q != _members.end());
+ q->second->unmarshal(is);
+ }
+}
+
+bool
+FreezeScript::StructData::booleanValue(bool) const
+{
+ _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::StructData::integerValue(bool) const
+{
+ _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::StructData::doubleValue(bool) const
+{
+ _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::StructData::stringValue(bool) const
+{
+ _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to string");
+ return string();
+}
+
+string
+FreezeScript::StructData::toString() const
+{
+ return stringValue();
+}
+
+void
+FreezeScript::StructData::visit(DataVisitor& visitor)
+{
+ visitor.visitStruct(this);
+}
+
+FreezeScript::DataMemberMap&
+FreezeScript::StructData::getMembers()
+{
+ return _members;
+}
+
+//
+// SequenceData
+//
+FreezeScript::SequenceData::SequenceData(const DataFactoryPtr& factory, const Slice::SequencePtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly) :
+ Data(errorReporter, readOnly), _factory(factory), _type(type)
+{
+ _length = IntegerDataPtr::dynamicCast(_factory->createInteger(0, true));
+}
+
+FreezeScript::SequenceData::SequenceData(const DataFactoryPtr& factory, const Slice::SequencePtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly,
+ const DataList& elements) :
+ Data(errorReporter, readOnly), _factory(factory), _type(type)
+{
+ for(DataList::const_iterator p = elements.begin(); p != elements.end(); ++p)
+ {
+ _elements.push_back((*p)->clone());
+ }
+ _length = IntegerDataPtr::dynamicCast(_factory->createInteger(static_cast<Ice::Long>(_elements.size()), true));
+}
+
+FreezeScript::DataPtr
+FreezeScript::SequenceData::getMember(const string& member) const
+{
+ if(member == "length")
+ {
+ _length->setValue(static_cast<Ice::Long>(_elements.size()), false);
+ return _length;
+ }
+
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::SequenceData::getElement(const DataPtr& element) const
+{
+ IntegerDataPtr i = IntegerDataPtr::dynamicCast(element);
+ if(!i)
+ {
+ _errorReporter->error("invalid sequence index type " + typeToString(element->getType()));
+ }
+
+ Ice::Long iv = i->integerValue();
+ if(iv < 0 || iv >= _elements.size())
+ {
+ _errorReporter->error("sequence index " + i->toString() + " out of range");
+ }
+
+ return _elements[static_cast<DataList::size_type>(iv)];
+}
+
+bool
+FreezeScript::SequenceData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::SequenceData::operator!=(const Data& rhs) const
+{
+ const SequenceData* s = dynamic_cast<const SequenceData*>(&rhs);
+ if(!s || _type->scoped() != s->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _elements != s->_elements;
+}
+
+bool
+FreezeScript::SequenceData::operator<(const Data& rhs) const
+{
+ const SequenceData* s = dynamic_cast<const SequenceData*>(&rhs);
+ if(!s || _type->scoped() != s->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _elements < s->_elements;
+}
+
+FreezeScript::DataPtr
+FreezeScript::SequenceData::clone() const
+{
+ return new SequenceData(_factory, _type, _errorReporter, _readOnly, _elements);
+}
+
+Slice::TypePtr
+FreezeScript::SequenceData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::SequenceData::destroy()
+{
+ for(DataList::const_iterator p = _elements.begin(); p != _elements.end(); ++p)
+ {
+ (*p)->destroy();
+ }
+}
+
+void
+FreezeScript::SequenceData::marshal(IceInternal::BasicStream& os) const
+{
+ os.writeSize(_elements.size());
+ for(DataList::const_iterator p = _elements.begin(); p != _elements.end(); ++p)
+ {
+ (*p)->marshal(os);
+ }
+}
+
+void
+FreezeScript::SequenceData::unmarshal(IceInternal::BasicStream& is)
+{
+ Slice::TypePtr type = _type->type();
+ Ice::Int sz;
+ is.readSize(sz);
+ _elements.reserve(sz);
+ for(Ice::Int i = 0; i < sz; ++i)
+ {
+ DataPtr v = _factory->create(type, _readOnly);
+ v->unmarshal(is);
+ _elements.push_back(v);
+ }
+ _length->setValue(sz, false);
+}
+
+bool
+FreezeScript::SequenceData::booleanValue(bool) const
+{
+ _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::SequenceData::integerValue(bool) const
+{
+ _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::SequenceData::doubleValue(bool) const
+{
+ _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::SequenceData::stringValue(bool) const
+{
+ _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to string");
+ return string();
+}
+
+string
+FreezeScript::SequenceData::toString() const
+{
+ return stringValue();
+}
+
+void
+FreezeScript::SequenceData::visit(DataVisitor& visitor)
+{
+ visitor.visitSequence(this);
+}
+
+FreezeScript::DataList&
+FreezeScript::SequenceData::getElements()
+{
+ return _elements;
+}
+
+//
+// EnumData
+//
+FreezeScript::EnumData::EnumData(const Slice::EnumPtr& type, const ErrorReporterPtr& errorReporter, bool readOnly) :
+ Data(errorReporter, readOnly), _type(type), _value(0)
+{
+ _count = static_cast<long>(type->getEnumerators().size());
+}
+
+FreezeScript::EnumData::EnumData(const Slice::EnumPtr& type, const ErrorReporterPtr& errorReporter, bool readOnly,
+ Ice::Int value) :
+ Data(errorReporter, readOnly), _type(type), _value(value)
+{
+ _count = static_cast<long>(type->getEnumerators().size());
+}
+
+FreezeScript::DataPtr
+FreezeScript::EnumData::getMember(const string&) const
+{
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::EnumData::getElement(const DataPtr&) const
+{
+ _errorReporter->error("element requested of enum value");
+ return 0;
+}
+
+bool
+FreezeScript::EnumData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::EnumData::operator!=(const Data& rhs) const
+{
+ const EnumData* e = dynamic_cast<const EnumData*>(&rhs);
+ if(!e || _type->scoped() != e->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value != e->_value;
+}
+
+bool
+FreezeScript::EnumData::operator<(const Data& rhs) const
+{
+ const EnumData* e = dynamic_cast<const EnumData*>(&rhs);
+ if(!e || _type->scoped() != e->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _value < e->_value;
+}
+
+FreezeScript::DataPtr
+FreezeScript::EnumData::clone() const
+{
+ return new EnumData(_type, _errorReporter, _value);
+}
+
+Slice::TypePtr
+FreezeScript::EnumData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::EnumData::destroy()
+{
+}
+
+void
+FreezeScript::EnumData::marshal(IceInternal::BasicStream& os) const
+{
+ if(_count <= 127)
+ {
+ os.write(static_cast<Ice::Byte>(_value));
+ }
+ else if(_count <= 32767)
+ {
+ os.write(static_cast<Ice::Short>(_value));
+ }
+ else
+ {
+ os.write(_value);
+ }
+}
+
+void
+FreezeScript::EnumData::unmarshal(IceInternal::BasicStream& is)
+{
+ if(_count <= 127)
+ {
+ Ice::Byte val;
+ is.read(val);
+ _value = val & 0xff;
+ }
+ else if(_count <= 32767)
+ {
+ Ice::Short val;
+ is.read(val);
+ _value = val;
+ }
+ else
+ {
+ is.read(_value);
+ }
+}
+
+bool
+FreezeScript::EnumData::booleanValue(bool) const
+{
+ _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::EnumData::integerValue(bool convert) const
+{
+ if(convert)
+ {
+ return _value;
+ }
+ else
+ {
+ _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to integer");
+ return 0;
+ }
+}
+
+double
+FreezeScript::EnumData::doubleValue(bool) const
+{
+ _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::EnumData::stringValue(bool) const
+{
+ _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to string");
+ return string();
+}
+
+string
+FreezeScript::EnumData::toString() const
+{
+ if(_name.empty())
+ {
+ Slice::EnumeratorList l = _type->getEnumerators();
+ Slice::EnumeratorList::const_iterator p = l.begin();
+ Ice::Int i = _value;
+ while(i > 0)
+ {
+ ++p;
+ assert(p != l.end());
+ --i;
+ }
+ const_cast<string&>(_name) = (*p)->name();
+ }
+ return _name;
+}
+
+void
+FreezeScript::EnumData::visit(DataVisitor& visitor)
+{
+ visitor.visitEnum(this);
+}
+
+Ice::Int
+FreezeScript::EnumData::getValue() const
+{
+ return _value;
+}
+
+bool
+FreezeScript::EnumData::setValue(Ice::Int v)
+{
+ if(v >= 0 && v < _count)
+ {
+ _value = v;
+ _name.clear();
+ return true;
+ }
+ return false;
+}
+
+bool
+FreezeScript::EnumData::setValueAsString(const string& v)
+{
+ Slice::EnumeratorList l = _type->getEnumerators();
+ Slice::EnumeratorList::const_iterator p;
+ Ice::Int i = 0;
+ for(p = l.begin(); p != l.end(); ++p, ++i)
+ {
+ if((*p)->name() == v)
+ {
+ _value = i;
+ _name = v;
+ break;
+ }
+ }
+ return p != l.end();
+}
+
+//
+// DictionaryData
+//
+FreezeScript::DictionaryData::DictionaryData(const DataFactoryPtr& factory, const Slice::DictionaryPtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly) :
+ Data(errorReporter, readOnly), _factory(factory), _type(type)
+{
+ _length = IntegerDataPtr::dynamicCast(_factory->createInteger(0, true));
+}
+
+FreezeScript::DictionaryData::DictionaryData(const DataFactoryPtr& factory, const Slice::DictionaryPtr& type,
+ const ErrorReporterPtr& errorReporter, bool readOnly, const DataMap& m) :
+ Data(errorReporter, readOnly), _factory(factory), _type(type)
+{
+ for(DataMap::const_iterator p = m.begin(); p != m.end(); ++p)
+ {
+ _map.insert(DataMap::value_type(p->first->clone(), p->second->clone()));
+ }
+ _length = IntegerDataPtr::dynamicCast(_factory->createInteger(static_cast<Ice::Long>(_map.size()), true));
+}
+
+FreezeScript::DataPtr
+FreezeScript::DictionaryData::getMember(const string& member) const
+{
+ if(member == "length")
+ {
+ _length->setValue(static_cast<Ice::Long>(_map.size()), false);
+ return _length;
+ }
+
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DictionaryData::getElement(const DataPtr& element) const
+{
+ DataMap::const_iterator p = _map.find(element);
+ if(p != _map.end())
+ {
+ return p->second;
+ }
+
+ return 0;
+}
+
+bool
+FreezeScript::DictionaryData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::DictionaryData::operator!=(const Data& rhs) const
+{
+ const DictionaryData* d = dynamic_cast<const DictionaryData*>(&rhs);
+ if(!d || _type->scoped() != d->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _map != d->_map;
+}
+
+bool
+FreezeScript::DictionaryData::operator<(const Data& rhs) const
+{
+ const DictionaryData* d = dynamic_cast<const DictionaryData*>(&rhs);
+ if(!d || _type->scoped() != d->_type->scoped())
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ assert(false);
+ }
+
+ return _map < d->_map;
+}
+
+FreezeScript::DataPtr
+FreezeScript::DictionaryData::clone() const
+{
+ return new DictionaryData(_factory, _type, _errorReporter, _readOnly, _map);
+}
+
+Slice::TypePtr
+FreezeScript::DictionaryData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::DictionaryData::destroy()
+{
+ for(DataMap::const_iterator p = _map.begin(); p != _map.end(); ++p)
+ {
+ p->first->destroy();
+ p->second->destroy();
+ }
+}
+
+void
+FreezeScript::DictionaryData::marshal(IceInternal::BasicStream& os) const
+{
+ os.writeSize(_map.size());
+ for(DataMap::const_iterator p = _map.begin(); p != _map.end(); ++p)
+ {
+ p->first->marshal(os);
+ p->second->marshal(os);
+ }
+}
+
+void
+FreezeScript::DictionaryData::unmarshal(IceInternal::BasicStream& is)
+{
+ Slice::TypePtr keyType = _type->keyType();
+ Slice::TypePtr valueType = _type->valueType();
+
+ Ice::Int sz;
+ is.readSize(sz);
+
+ for(Ice::Int i = 0; i < sz; ++i)
+ {
+ DataPtr key = _factory->create(keyType, _readOnly);
+ key->unmarshal(is);
+
+ DataPtr value = _factory->create(valueType, _readOnly);
+ value->unmarshal(is);
+
+ _map.insert(DataMap::value_type(key, value));
+ }
+
+ _length->setValue(static_cast<Ice::Long>(_map.size()), false);
+}
+
+bool
+FreezeScript::DictionaryData::booleanValue(bool) const
+{
+ _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::DictionaryData::integerValue(bool) const
+{
+ _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::DictionaryData::doubleValue(bool) const
+{
+ _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::DictionaryData::stringValue(bool) const
+{
+ _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to string");
+ return string();
+}
+
+string
+FreezeScript::DictionaryData::toString() const
+{
+ return stringValue();
+}
+
+void
+FreezeScript::DictionaryData::visit(DataVisitor& visitor)
+{
+ visitor.visitDictionary(this);
+}
+
+FreezeScript::DataMap&
+FreezeScript::DictionaryData::getElements()
+{
+ return _map;
+}
+
+//
+// ObjectData
+//
+FreezeScript::ObjectData::ObjectData(const DataFactoryPtr& factory, const Slice::TypePtr& type, bool readOnly) :
+ Data(factory->getErrorReporter(), readOnly), _type(type), _refCount(0)
+{
+ //
+ // Create a Data object for the facet map. We add this to the _members map so that
+ // the `ice_facets' member is handled like all other members.
+ //
+ Slice::TypeList l = _type->unit()->lookupType("::_FacetMap", false);
+ assert(!l.empty());
+ _facetMap = factory->create(l.front(), readOnly);
+ _members["ice_facets"] = _facetMap;
+
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(type);
+ if(decl)
+ {
+ Slice::ClassDefPtr def = decl->definition();
+ assert(def);
+ Slice::DataMemberList members = def->allDataMembers();
+ for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
+ {
+ _members[(*p)->name()] = factory->create((*p)->type(), _readOnly);
+ }
+ _id = factory->createString(decl->scoped(), true);
+ }
+ else
+ {
+ _id = factory->createString("::Ice::Object", true);
+ }
+}
+
+FreezeScript::DataPtr
+FreezeScript::ObjectData::getMember(const string& member) const
+{
+ if(member == "ice_id")
+ {
+ return _id;
+ }
+
+ DataMemberMap::const_iterator p = _members.find(member);
+ if(p != _members.end())
+ {
+ return p->second;
+ }
+
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::ObjectData::getElement(const DataPtr& element) const
+{
+ _errorReporter->error("element requested of object value");
+ return 0;
+}
+
+bool
+FreezeScript::ObjectData::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::ObjectData::operator!=(const Data& rhs) const
+{
+ _errorReporter->error("object comparison not supported");
+ return false;
+}
+
+bool
+FreezeScript::ObjectData::operator<(const Data& rhs) const
+{
+ _errorReporter->error("object comparison not supported");
+ return false;
+}
+
+FreezeScript::DataPtr
+FreezeScript::ObjectData::clone() const
+{
+ assert(false);
+ return 0;
+}
+
+Slice::TypePtr
+FreezeScript::ObjectData::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::ObjectData::destroy()
+{
+ assert(false);
+}
+
+void
+FreezeScript::ObjectData::marshal(IceInternal::BasicStream& os) const
+{
+ if(!_marshaler)
+ {
+ const_cast<Ice::ObjectPtr&>(_marshaler) = new ObjectWriter(const_cast<ObjectData*>(this));
+ }
+ os.write(_marshaler);
+}
+
+void
+FreezeScript::ObjectData::unmarshal(IceInternal::BasicStream& is)
+{
+ //
+ // Unmarshaling is done by ObjectReader.
+ //
+ assert(false);
+}
+
+bool
+FreezeScript::ObjectData::booleanValue(bool) const
+{
+ assert(false);
+ return 0;
+}
+
+Ice::Long
+FreezeScript::ObjectData::integerValue(bool) const
+{
+ assert(false);
+ return 0;
+}
+
+double
+FreezeScript::ObjectData::doubleValue(bool) const
+{
+ assert(false);
+ return 0;
+}
+
+string
+FreezeScript::ObjectData::stringValue(bool) const
+{
+ assert(false);
+ return string();
+}
+
+string
+FreezeScript::ObjectData::toString() const
+{
+ assert(false);
+ return string();
+}
+
+void
+FreezeScript::ObjectData::visit(DataVisitor& visitor)
+{
+ assert(false);
+}
+
+FreezeScript::DataMemberMap&
+FreezeScript::ObjectData::getMembers()
+{
+ return _members;
+}
+
+void
+FreezeScript::ObjectData::incRef()
+{
+ _refCount++;
+}
+
+void
+FreezeScript::ObjectData::decRef()
+{
+ assert(_refCount > 0);
+ _refCount--;
+ if(_refCount == 0)
+ {
+ destroyI();
+ }
+}
+
+void
+FreezeScript::ObjectData::destroyI()
+{
+ DataMemberMap members = _members;
+
+ _members.clear();
+ _marshaler = 0;
+
+ for(DataMemberMap::const_iterator p = members.begin(); p != members.end(); ++p)
+ {
+ p->second->destroy();
+ }
+}
+
+//
+// ObjectRef
+//
+FreezeScript::ObjectRef::ObjectRef(const DataFactoryPtr& factory, const Slice::TypePtr& type, bool readOnly) :
+ Data(factory->getErrorReporter(), readOnly), _factory(factory), _type(type)
+{
+}
+
+FreezeScript::ObjectRef::ObjectRef(const DataFactoryPtr& factory, const Slice::TypePtr& type, bool readOnly,
+ const ObjectDataPtr& value) :
+ Data(factory->getErrorReporter(), readOnly), _factory(factory), _type(type), _value(value)
+{
+ _value->incRef();
+}
+
+FreezeScript::DataPtr
+FreezeScript::ObjectRef::getMember(const string& member) const
+{
+ if(!_value)
+ {
+ _errorReporter->error("member `" + member + "' requested of nil object");
+ }
+
+ return _value->getMember(member);
+}
+
+FreezeScript::DataPtr
+FreezeScript::ObjectRef::getElement(const DataPtr&) const
+{
+ _errorReporter->error("element requested of object value");
+ return 0;
+}
+
+bool
+FreezeScript::ObjectRef::operator==(const Data& rhs) const
+{
+ return !operator!=(rhs);
+}
+
+bool
+FreezeScript::ObjectRef::operator!=(const Data& rhs) const
+{
+ const ObjectRef* r = dynamic_cast<const ObjectRef*>(&rhs);
+ if(!r)
+ {
+ _errorReporter->typeMismatchError(_type, rhs.getType(), true);
+ }
+
+ //
+ // Reference comparison.
+ //
+ return _value.get() != r->_value.get();
+}
+
+bool
+FreezeScript::ObjectRef::operator<(const Data& rhs) const
+{
+ _errorReporter->error("object comparison not supported");
+ return false;
+}
+
+FreezeScript::DataPtr
+FreezeScript::ObjectRef::clone() const
+{
+ return new ObjectRef(_factory, _type, _value);
+}
+
+Slice::TypePtr
+FreezeScript::ObjectRef::getType() const
+{
+ return _type;
+}
+
+void
+FreezeScript::ObjectRef::destroy()
+{
+ if(_value)
+ {
+ _value->decRef();
+ _value = 0;
+ }
+}
+
+void
+FreezeScript::ObjectRef::marshal(IceInternal::BasicStream& os) const
+{
+ if(!_value)
+ {
+ os.write(Ice::ObjectPtr());
+ return;
+ }
+
+ _value->marshal(os);
+}
+
+static void
+patchObject(void* addr, Ice::ObjectPtr& v)
+{
+ if(v)
+ {
+ FreezeScript::ObjectRef* ref = static_cast<FreezeScript::ObjectRef*>(addr);
+ assert(ref);
+
+ FreezeScript::ObjectReaderPtr reader = FreezeScript::ObjectReaderPtr::dynamicCast(v);
+ assert(reader);
+
+ ref->setValue(reader->getValue());
+ }
+}
+
+void
+FreezeScript::ObjectRef::unmarshal(IceInternal::BasicStream& is)
+{
+ is.read(patchObject, this);
+}
+
+bool
+FreezeScript::ObjectRef::booleanValue(bool) const
+{
+ _errorReporter->error(typeToString(_type) + " cannot be converted to boolean");
+ return 0;
+}
+
+Ice::Long
+FreezeScript::ObjectRef::integerValue(bool) const
+{
+ _errorReporter->error(typeToString(_type) + " cannot be converted to integer");
+ return 0;
+}
+
+double
+FreezeScript::ObjectRef::doubleValue(bool) const
+{
+ _errorReporter->error(typeToString(_type) + " cannot be converted to double");
+ return 0;
+}
+
+string
+FreezeScript::ObjectRef::stringValue(bool) const
+{
+ _errorReporter->error(typeToString(_type) + " cannot be converted to string");
+ return string();
+}
+
+string
+FreezeScript::ObjectRef::toString() const
+{
+ return stringValue();
+}
+
+void
+FreezeScript::ObjectRef::visit(DataVisitor& visitor)
+{
+ visitor.visitObject(this);
+}
+
+void
+FreezeScript::ObjectRef::instantiate()
+{
+ ObjectDataPtr data = new ObjectData(_factory, _type, _readOnly);
+ setValue(data);
+}
+
+FreezeScript::ObjectDataPtr
+FreezeScript::ObjectRef::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::ObjectRef::setValue(const ObjectDataPtr& value)
+{
+ // TODO: Type check?
+ ObjectDataPtr oldValue = _value;
+ _value = value;
+ if(_value)
+ {
+ _value->incRef();
+ }
+ if(oldValue)
+ {
+ oldValue->decRef();
+ }
+}
+
+//
+// ObjectFactory
+//
+FreezeScript::ObjectFactory::ObjectFactory(const DataFactoryPtr& factory, const Slice::UnitPtr& unit) :
+ _factory(factory), _unit(unit)
+{
+}
+
+Ice::ObjectPtr
+FreezeScript::ObjectFactory::create(const string& id)
+{
+ Ice::ObjectPtr result;
+
+ if(id == Ice::Object::ice_staticId())
+ {
+ result = new ObjectReader(_factory, _unit->builtin(Slice::Builtin::KindObject));
+ }
+ else
+ {
+ Slice::TypeList l = _unit->lookupTypeNoBuiltin(id);
+ if(!l.empty())
+ {
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(l.front());
+ if(!decl)
+ {
+ _factory->getErrorReporter()->error("Slice definition for `" + id + "' is not a class");
+ }
+ Slice::ClassDefPtr def = decl->definition();
+ if(!def)
+ {
+ _factory->getErrorReporter()->error("no class definition for `" + id + "'");
+ }
+ result = new ObjectReader(_factory, decl);
+ }
+ }
+
+ return result;
+}
+
+void
+FreezeScript::ObjectFactory::destroy()
+{
+}
+
+//
+// DataVisitor
+//
+FreezeScript::DataVisitor::~DataVisitor()
+{
+}
+
+void
+FreezeScript::DataVisitor::visitBoolean(const BooleanDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitInteger(const IntegerDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitDouble(const DoubleDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitString(const StringDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitProxy(const ProxyDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitStruct(const StructDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitSequence(const SequenceDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitEnum(const EnumDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitDictionary(const DictionaryDataPtr&)
+{
+}
+
+void
+FreezeScript::DataVisitor::visitObject(const ObjectRefPtr&)
+{
+}
diff --git a/cpp/src/FreezeScript/Data.h b/cpp/src/FreezeScript/Data.h
new file mode 100644
index 00000000000..4d0883f951f
--- /dev/null
+++ b/cpp/src/FreezeScript/Data.h
@@ -0,0 +1,639 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_DATA_H
+#define FREEZE_SCRIPT_DATA_H
+
+#include <Ice/Ice.h>
+#include <Slice/Parser.h>
+#include <FreezeScript/Error.h>
+
+namespace FreezeScript
+{
+
+class DataFactory;
+typedef IceUtil::Handle<DataFactory> DataFactoryPtr;
+
+class Data;
+typedef IceUtil::Handle<Data> DataPtr;
+
+class DataVisitor;
+
+typedef std::map<std::string, DataPtr> DataMemberMap;
+typedef std::vector<DataPtr> DataList;
+typedef std::map<DataPtr, DataPtr> DataMap;
+
+class ObjectWriter;
+class ObjectReader;
+
+class ObjectData;
+typedef IceUtil::Handle<ObjectData> ObjectDataPtr;
+
+class DataInitializer : virtual public IceUtil::SimpleShared
+{
+public:
+
+ virtual ~DataInitializer();
+
+ virtual void initialize(const DataFactoryPtr&, const DataPtr&, const Ice::CommunicatorPtr&) = 0;
+};
+typedef IceUtil::Handle<DataInitializer> DataInitializerPtr;
+
+class DataFactory : public IceUtil::SimpleShared
+{
+public:
+
+ DataFactory(const Ice::CommunicatorPtr&, const Slice::UnitPtr&, const ErrorReporterPtr&);
+
+ DataPtr create(const Slice::TypePtr&, bool);
+ DataPtr createBoolean(bool, bool);
+ DataPtr createInteger(Ice::Long, bool);
+ DataPtr createDouble(double, bool);
+ DataPtr createString(const std::string&, bool);
+ DataPtr createNil(bool);
+ DataPtr createObject(const Slice::TypePtr&, bool);
+
+ Slice::BuiltinPtr getBuiltin(Slice::Builtin::Kind) const;
+
+ void addInitializer(const std::string&, const DataInitializerPtr&);
+ void enableInitializers();
+ void disableInitializers();
+
+ Ice::CommunicatorPtr getCommunicator() const;
+ ErrorReporterPtr getErrorReporter() const;
+
+private:
+
+ DataPtr createImpl(const Slice::TypePtr&, bool);
+ void initialize(const DataPtr&);
+
+ Ice::CommunicatorPtr _communicator;
+ Slice::UnitPtr _unit; // Only used for creating builtin types.
+ ErrorReporterPtr _errorReporter;
+ typedef std::map<std::string, DataInitializerPtr> InitMap;
+ InitMap _initializers;
+ bool _initializersEnabled;
+};
+
+class Data : public IceUtil::SimpleShared
+{
+public:
+
+ virtual ~Data();
+
+ virtual DataPtr getMember(const std::string&) const = 0;
+ virtual DataPtr getElement(const DataPtr&) const = 0;
+
+ virtual bool operator==(const Data&) const = 0;
+ virtual bool operator!=(const Data&) const = 0;
+ virtual bool operator<(const Data&) const = 0;
+
+ virtual DataPtr clone() const = 0;
+
+ bool readOnly() const;
+ virtual Slice::TypePtr getType() const = 0;
+ virtual void destroy() = 0;
+
+ virtual void marshal(IceInternal::BasicStream&) const = 0;
+ virtual void unmarshal(IceInternal::BasicStream&) = 0;
+
+ virtual bool booleanValue(bool = false) const = 0;
+ virtual Ice::Long integerValue(bool = false) const = 0;
+ virtual double doubleValue(bool = false) const = 0;
+ virtual std::string stringValue(bool = false) const = 0;
+ virtual std::string toString() const = 0;
+
+ virtual void visit(DataVisitor&) = 0;
+
+protected:
+
+ Data(const ErrorReporterPtr&, bool);
+
+ ErrorReporterPtr _errorReporter;
+ bool _readOnly;
+};
+
+class PrimitiveData : public Data
+{
+public:
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual void destroy();
+
+protected:
+
+ PrimitiveData(const ErrorReporterPtr&, bool);
+};
+typedef IceUtil::Handle<PrimitiveData> PrimitiveDataPtr;
+
+class BooleanData : public PrimitiveData
+{
+public:
+
+ BooleanData(const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool);
+ BooleanData(const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool, bool);
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ bool getValue() const;
+ void setValue(bool);
+
+private:
+
+ Slice::BuiltinPtr _type;
+ bool _value;
+};
+typedef IceUtil::Handle<BooleanData> BooleanDataPtr;
+
+class IntegerData : public PrimitiveData
+{
+public:
+
+ IntegerData(const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool);
+ IntegerData(const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool, Ice::Long);
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ Ice::Long getValue() const;
+ void setValue(Ice::Long, bool);
+
+private:
+
+ bool rangeCheck(Ice::Long, bool) const;
+ static std::string toString(Ice::Long);
+
+ Slice::BuiltinPtr _type;
+ Ice::Long _value;
+};
+typedef IceUtil::Handle<IntegerData> IntegerDataPtr;
+
+class DoubleData : public PrimitiveData
+{
+public:
+
+ DoubleData(const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool);
+ DoubleData(const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool, double);
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ double getValue() const;
+ void setValue(double);
+
+private:
+
+ Slice::BuiltinPtr _type;
+ double _value;
+};
+typedef IceUtil::Handle<DoubleData> DoubleDataPtr;
+
+class StringData : public PrimitiveData
+{
+public:
+
+ StringData(const DataFactoryPtr&, const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool);
+ StringData(const DataFactoryPtr&, const Slice::BuiltinPtr&, const ErrorReporterPtr&, bool, const std::string&);
+
+ virtual DataPtr getMember(const std::string&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ std::string getValue() const;
+ void setValue(const std::string&);
+
+private:
+
+ DataFactoryPtr _factory;
+ Slice::BuiltinPtr _type;
+ std::string _value;
+ IntegerDataPtr _length;
+};
+typedef IceUtil::Handle<StringData> StringDataPtr;
+
+class ProxyData : public Data
+{
+public:
+
+ ProxyData(const Slice::TypePtr&, const Ice::CommunicatorPtr&, const ErrorReporterPtr&, bool);
+ ProxyData(const Slice::TypePtr&, const Ice::CommunicatorPtr&, const ErrorReporterPtr&, bool, const Ice::ObjectPrx&);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+ virtual void destroy();
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ Ice::ObjectPrx getValue() const;
+ void setValue(const std::string&, bool);
+ void setValue(const Ice::ObjectPrx&);
+
+private:
+
+ Slice::TypePtr _type; // Can be Builtin or Proxy
+ Ice::CommunicatorPtr _communicator;
+ Ice::ObjectPrx _value;
+ std::string _str;
+};
+typedef IceUtil::Handle<ProxyData> ProxyDataPtr;
+
+class StructData : public Data
+{
+public:
+
+ StructData(const DataFactoryPtr&, const Slice::StructPtr&, const ErrorReporterPtr&, bool);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual void destroy();
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ DataMemberMap& getMembers();
+
+private:
+
+ StructData(const Slice::StructPtr&, const ErrorReporterPtr&, bool, const DataMemberMap&);
+
+ Slice::StructPtr _type;
+ DataMemberMap _members;
+};
+typedef IceUtil::Handle<StructData> StructDataPtr;
+
+class SequenceData : public Data
+{
+public:
+
+ SequenceData(const DataFactoryPtr&, const Slice::SequencePtr&, const ErrorReporterPtr&, bool);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+ virtual void destroy();
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ DataList& getElements();
+
+private:
+
+ SequenceData(const DataFactoryPtr&, const Slice::SequencePtr&, const ErrorReporterPtr&, bool, const DataList&);
+
+ DataFactoryPtr _factory;
+ Slice::SequencePtr _type;
+ DataList _elements;
+ IntegerDataPtr _length;
+};
+typedef IceUtil::Handle<SequenceData> SequenceDataPtr;
+
+class EnumData : public Data
+{
+public:
+
+ EnumData(const Slice::EnumPtr&, const ErrorReporterPtr&, bool);
+ EnumData(const Slice::EnumPtr&, const ErrorReporterPtr&, bool, Ice::Int);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+ virtual void destroy();
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ Ice::Int getValue() const;
+ bool setValue(Ice::Int);
+ bool setValueAsString(const std::string&);
+
+private:
+
+ Slice::EnumPtr _type;
+ Ice::Int _value;
+ std::string _name;
+ Ice::Int _count;
+};
+typedef IceUtil::Handle<EnumData> EnumDataPtr;
+
+class DictionaryData : public Data
+{
+public:
+
+ DictionaryData(const DataFactoryPtr&, const Slice::DictionaryPtr&, const ErrorReporterPtr&, bool);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+ virtual void destroy();
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ DataMap& getElements();
+
+private:
+
+ DictionaryData(const DataFactoryPtr&, const Slice::DictionaryPtr&, const ErrorReporterPtr&, bool, const DataMap&);
+
+ DataFactoryPtr _factory;
+ Slice::DictionaryPtr _type;
+ DataMap _map;
+ IntegerDataPtr _length;
+};
+typedef IceUtil::Handle<DictionaryData> DictionaryDataPtr;
+
+class ObjectData : public Data
+{
+public:
+
+ ObjectData(const DataFactoryPtr&, const Slice::TypePtr&, bool);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+ virtual void destroy();
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ DataMemberMap& getMembers();
+
+ void incRef();
+ void decRef();
+
+private:
+
+ void destroyI();
+
+ Slice::TypePtr _type; // Can be Builtin (Object) or ClassDecl
+ DataPtr _facetMap;
+ DataMemberMap _members;
+ Ice::ObjectPtr _marshaler;
+ Ice::Int _refCount;
+ DataPtr _id;
+
+ friend class ObjectWriter;
+ friend class ObjectReader;
+};
+
+class ObjectRef : public Data
+{
+public:
+
+ ObjectRef(const DataFactoryPtr&, const Slice::TypePtr&, bool);
+ ObjectRef(const DataFactoryPtr&, const Slice::TypePtr&, bool, const ObjectDataPtr&);
+
+ virtual DataPtr getMember(const std::string&) const;
+ virtual DataPtr getElement(const DataPtr&) const;
+
+ virtual bool operator==(const Data&) const;
+ virtual bool operator!=(const Data&) const;
+ virtual bool operator<(const Data&) const;
+
+ virtual DataPtr clone() const;
+
+ virtual Slice::TypePtr getType() const;
+ virtual void destroy();
+
+ virtual void marshal(IceInternal::BasicStream&) const;
+ virtual void unmarshal(IceInternal::BasicStream&);
+
+ virtual bool booleanValue(bool = false) const;
+ virtual Ice::Long integerValue(bool = false) const;
+ virtual double doubleValue(bool = false) const;
+ virtual std::string stringValue(bool = false) const;
+ virtual std::string toString() const;
+
+ virtual void visit(DataVisitor&);
+
+ void instantiate();
+ ObjectDataPtr getValue() const;
+ void setValue(const ObjectDataPtr&);
+
+private:
+
+ DataFactoryPtr _factory;
+ Slice::TypePtr _type; // Formal type: can be Builtin (Object) or ClassDecl
+ ObjectDataPtr _value;
+};
+typedef IceUtil::Handle<ObjectRef> ObjectRefPtr;
+
+class ObjectFactory : public Ice::ObjectFactory
+{
+public:
+
+ ObjectFactory(const DataFactoryPtr&, const Slice::UnitPtr&);
+
+ virtual Ice::ObjectPtr create(const std::string&);
+ virtual void destroy();
+
+private:
+
+ DataFactoryPtr _factory;
+ Slice::UnitPtr _unit;
+};
+
+class ClassNotFoundException
+{
+public:
+
+ ClassNotFoundException(const std::string& s) : id(s) {}
+
+ std::string id;
+};
+
+class DataVisitor
+{
+public:
+
+ virtual ~DataVisitor();
+
+ virtual void visitBoolean(const BooleanDataPtr&);
+ virtual void visitInteger(const IntegerDataPtr&);
+ virtual void visitDouble(const DoubleDataPtr&);
+ virtual void visitString(const StringDataPtr&);
+ virtual void visitProxy(const ProxyDataPtr&);
+ virtual void visitStruct(const StructDataPtr&);
+ virtual void visitSequence(const SequenceDataPtr&);
+ virtual void visitEnum(const EnumDataPtr&);
+ virtual void visitDictionary(const DictionaryDataPtr&);
+ virtual void visitObject(const ObjectRefPtr&);
+};
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Error.cpp b/cpp/src/FreezeScript/Error.cpp
new file mode 100644
index 00000000000..7262827c1d6
--- /dev/null
+++ b/cpp/src/FreezeScript/Error.cpp
@@ -0,0 +1,193 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Error.h>
+#include <FreezeScript/Exception.h>
+#include <FreezeScript/Util.h>
+
+using namespace std;
+
+//
+// ErrorReporter
+//
+FreezeScript::ErrorReporter::ErrorReporter(ostream& out, bool suppress) :
+ _out(out), _suppress(suppress)
+{
+}
+
+ostream&
+FreezeScript::ErrorReporter::stream() const
+{
+ return _out;
+}
+
+void
+FreezeScript::ErrorReporter::warning(const string& msg)
+{
+ ostringstream ostr;
+ if(!_descName.empty())
+ {
+ ostr << "warning in <" << _descName << "> descriptor, line " << _descLine << ": " << msg << endl;
+ }
+ else
+ {
+ ostr << "warning: " << msg << endl;
+ }
+ string warn = ostr.str();
+ if(_suppress)
+ {
+ map<string, bool>::iterator p = _warningHistory.find(warn);
+ if(p != _warningHistory.end())
+ {
+ return;
+ }
+ _warningHistory.insert(map<string, bool>::value_type(warn, true));
+ }
+ _out << warn;
+}
+
+void
+FreezeScript::ErrorReporter::error(const string& msg)
+{
+ ostringstream ostr;
+ if(!_descName.empty())
+ {
+ ostr << "error in <" << _descName << "> descriptor, line " << _descLine << ": " << msg << endl;
+ }
+ else
+ {
+ ostr << "error: " << msg << endl;
+ }
+ throw Exception(__FILE__, __LINE__, ostr.str());
+}
+
+void
+FreezeScript::ErrorReporter::typeMismatchError(const Slice::TypePtr& expected, const Slice::TypePtr& received,
+ bool fatal)
+{
+ ostringstream ostr;
+ ostr << "type mismatch: expected " << typeToString(expected) << " but received " << typeToString(received);
+
+ if(fatal)
+ {
+ error(ostr.str());
+ }
+ else
+ {
+ warning(ostr.str());
+ }
+}
+
+void
+FreezeScript::ErrorReporter::conversionError(const string& value, const Slice::TypePtr& type, bool fatal)
+{
+ ostringstream ostr;
+ ostr << "unable to convert `" << value << "' to " << typeToString(type);
+
+ if(fatal)
+ {
+ error(ostr.str());
+ }
+ else
+ {
+ warning(ostr.str());
+ }
+}
+
+void
+FreezeScript::ErrorReporter::rangeError(const string& value, const Slice::TypePtr& type, bool fatal)
+{
+ ostringstream ostr;
+ ostr << "value `" << value << "' is out of range for type " << typeToString(type);
+
+ if(fatal)
+ {
+ error(ostr.str());
+ }
+ else
+ {
+ warning(ostr.str());
+ }
+}
+
+void
+FreezeScript::ErrorReporter::expressionSyntaxError(const string& msg)
+{
+ assert(!_expression.empty());
+ ostringstream ostr;
+ ostr << "syntax error in expression `" << _expression << "': " << msg;
+ error(ostr.str());
+}
+
+void
+FreezeScript::ErrorReporter::descriptorError(const string& msg, int line)
+{
+ ostringstream ostr;
+ ostr << "XML error on line " << line << ":" << endl << msg;
+ error(ostr.str());
+}
+
+void
+FreezeScript::ErrorReporter::setDescriptor(const string& name, int line)
+{
+ _descName = name;
+ _descLine = line;
+}
+
+void
+FreezeScript::ErrorReporter::getDescriptor(string& name, int& line)
+{
+ name = _descName;
+ line = _descLine;
+}
+
+void
+FreezeScript::ErrorReporter::clearDescriptor()
+{
+ _descName.clear();
+}
+
+void
+FreezeScript::ErrorReporter::setExpression(const string& expr)
+{
+ _expression = expr;
+}
+
+void
+FreezeScript::ErrorReporter::clearExpression()
+{
+ _expression.clear();
+}
+
+//
+// DescriptorErrorContext
+//
+FreezeScript::DescriptorErrorContext::DescriptorErrorContext(const ErrorReporterPtr& errorReporter, const string& name,
+ int line) :
+ _errorReporter(errorReporter)
+{
+ //
+ // Save the existing descriptor information before changing it.
+ //
+ _errorReporter->getDescriptor(_name, _line);
+ _errorReporter->setDescriptor(name, line);
+}
+
+FreezeScript::DescriptorErrorContext::~DescriptorErrorContext()
+{
+ //
+ // Restore the original descriptor information.
+ //
+ _errorReporter->setDescriptor(_name, _line);
+}
diff --git a/cpp/src/FreezeScript/Error.h b/cpp/src/FreezeScript/Error.h
new file mode 100644
index 00000000000..33affea978d
--- /dev/null
+++ b/cpp/src/FreezeScript/Error.h
@@ -0,0 +1,73 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_ERROR_H
+#define FREEZE_SCRIPT_ERROR_H
+
+#include <Slice/Parser.h>
+
+namespace FreezeScript
+{
+
+class ErrorReporter : public IceUtil::SimpleShared
+{
+public:
+
+ ErrorReporter(std::ostream&, bool);
+
+ std::ostream& stream() const;
+
+ void warning(const std::string&);
+ void error(const std::string&);
+ void typeMismatchError(const Slice::TypePtr&, const Slice::TypePtr&, bool);
+ void conversionError(const std::string&, const Slice::TypePtr&, bool);
+ void rangeError(const std::string&, const Slice::TypePtr&, bool);
+ void expressionSyntaxError(const std::string&);
+ void descriptorError(const std::string&, int);
+
+ void setDescriptor(const std::string&, int);
+ void getDescriptor(std::string&, int&);
+ void clearDescriptor();
+
+ void setExpression(const std::string&);
+ void clearExpression();
+
+private:
+
+ std::ostream& _out;
+ bool _suppress;
+ std::map<std::string, bool> _warningHistory;
+ std::string _descName;
+ int _descLine;
+ std::string _expression;
+};
+typedef IceUtil::Handle<ErrorReporter> ErrorReporterPtr;
+
+class DescriptorErrorContext
+{
+public:
+
+ DescriptorErrorContext(const ErrorReporterPtr&, const std::string&, int);
+ ~DescriptorErrorContext();
+
+private:
+
+ ErrorReporterPtr _errorReporter;
+ std::string _name;
+ int _line;
+};
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Exception.cpp b/cpp/src/FreezeScript/Exception.cpp
new file mode 100644
index 00000000000..6d1eabb6f3d
--- /dev/null
+++ b/cpp/src/FreezeScript/Exception.cpp
@@ -0,0 +1,62 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Exception.h>
+
+using namespace std;
+
+//
+// Exception
+//
+FreezeScript::Exception::Exception(const char* file, int line, const string& reason) :
+ IceUtil::Exception(file, line), _reason(reason)
+{
+}
+
+string FreezeScript::Exception::_name = "FreezeScript::Exception";
+
+const string&
+FreezeScript::Exception::ice_name() const
+{
+ return _name;
+}
+
+void
+FreezeScript::Exception::ice_print(ostream& out) const
+{
+ Exception::ice_print(out);
+ out << ":\nerror occurred during transformation"; // TODO
+ if(!_reason.empty())
+ {
+ out << ":\n" << _reason;
+ }
+}
+
+IceUtil::Exception*
+FreezeScript::Exception::ice_clone() const
+{
+ return new Exception(ice_file(), ice_line(), _reason);
+}
+
+void
+FreezeScript::Exception::ice_throw() const
+{
+ throw *this;
+}
+
+string
+FreezeScript::Exception::reason() const
+{
+ return _reason;
+}
diff --git a/cpp/src/FreezeScript/Exception.h b/cpp/src/FreezeScript/Exception.h
new file mode 100644
index 00000000000..c3ab406ffb9
--- /dev/null
+++ b/cpp/src/FreezeScript/Exception.h
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_EXCEPTION_H
+#define FREEZE_SCRIPT_EXCEPTION_H
+
+#include <IceUtil/Exception.h>
+
+namespace FreezeScript
+{
+
+class Exception : public IceUtil::Exception
+{
+public:
+
+ Exception(const char*, int, const std::string&);
+ virtual const std::string& ice_name() const;
+ virtual void ice_print(std::ostream&) const;
+ virtual IceUtil::Exception* ice_clone() const;
+ virtual void ice_throw() const;
+
+ std::string reason() const;
+
+private:
+
+ std::string _reason;
+ static std::string _name;
+};
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Functions.cpp b/cpp/src/FreezeScript/Functions.cpp
new file mode 100644
index 00000000000..d1b6344e907
--- /dev/null
+++ b/cpp/src/FreezeScript/Functions.cpp
@@ -0,0 +1,350 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Functions.h>
+#include <FreezeScript/Util.h>
+#include <IceUtil/UUID.h>
+
+using namespace std;
+
+bool
+FreezeScript::invokeGlobalFunction(const string& name, const DataList& args, DataPtr& result,
+ const DataFactoryPtr& factory, const ErrorReporterPtr& errorReporter)
+{
+ //
+ // Global function.
+ //
+ if(name == "typeOf")
+ {
+ if(args.size() != 1)
+ {
+ errorReporter->error("typeOf() requires one argument");
+ }
+ result = factory->createString(typeToString(args.front()->getType()), false);
+ return true;
+ }
+ else if(name == "generateUUID")
+ {
+ if(args.size() != 0)
+ {
+ errorReporter->error("generateUUID() accepts no arguments");
+ }
+ result = factory->createString(IceUtil::generateUUID(), false);
+ return true;
+ }
+ else if(name == "stringToIdentity")
+ {
+ StringDataPtr str;
+ if(args.size() > 0)
+ {
+ str = StringDataPtr::dynamicCast(args.front());
+ }
+ if(args.size() != 1 || !str)
+ {
+ errorReporter->error("stringToIdentity() requires a string argument");
+ }
+
+ //
+ // Parse the identity string.
+ //
+ string idstr = str->stringValue();
+ Ice::Identity id;
+ try
+ {
+ id = Ice::stringToIdentity(idstr);
+ }
+ catch(const Ice::IdentityParseException& ex)
+ {
+ errorReporter->error("error in stringToIdentity():\n" + ex.str);
+ }
+
+ //
+ // Create a data representation of Ice::Identity.
+ //
+ Slice::UnitPtr unit = str->getType()->unit();
+ Slice::TypeList l = unit->lookupType("::Ice::Identity", false);
+ assert(!l.empty());
+ DataPtr identity = factory->create(l.front(), false);
+ StringDataPtr member;
+ member = StringDataPtr::dynamicCast(identity->getMember("name"));
+ assert(member);
+ member->setValue(id.name);
+ member = StringDataPtr::dynamicCast(identity->getMember("category"));
+ assert(member);
+ member->setValue(id.category);
+ result = identity;
+ return true;
+ }
+ else if(name == "identityToString")
+ {
+ StructDataPtr identity;
+ if(args.size() > 0)
+ {
+ identity = StructDataPtr::dynamicCast(args.front());
+ }
+ if(identity)
+ {
+ Slice::TypePtr argType = identity->getType();
+ Slice::StructPtr st = Slice::StructPtr::dynamicCast(argType);
+ if(!st || st->scoped() != "::Ice::Identity")
+ {
+ identity = 0;
+ }
+ }
+ if(args.size() != 1 || !identity)
+ {
+ errorReporter->error("identityToString() requires a argument of type ::Ice::Identity");
+ }
+
+ //
+ // Compose the identity.
+ //
+ Ice::Identity id;
+ StringDataPtr member;
+ member = StringDataPtr::dynamicCast(identity->getMember("name"));
+ assert(member);
+ id.name = member->stringValue();
+ member = StringDataPtr::dynamicCast(identity->getMember("category"));
+ assert(member);
+ id.category = member->stringValue();
+
+ result = factory->createString(Ice::identityToString(id), false);
+ return true;
+ }
+ else if(name == "stringToProxy")
+ {
+ StringDataPtr str;
+ if(args.size() > 0)
+ {
+ str = StringDataPtr::dynamicCast(args.front());
+ }
+ if(args.size() != 1 || !str)
+ {
+ errorReporter->error("stringToProxy() requires a string argument");
+ }
+
+ //
+ // Parse the proxy;
+ //
+ string sprx = str->stringValue();
+ Ice::ObjectPrx prx;
+ try
+ {
+ prx = factory->getCommunicator()->stringToProxy(sprx);
+ }
+ catch(const Ice::ProxyParseException& ex)
+ {
+ errorReporter->error("error in stringToProxy():\n" + ex.str);
+ }
+
+ Slice::UnitPtr unit = str->getType()->unit();
+ ProxyDataPtr p =
+ ProxyDataPtr::dynamicCast(factory->create(unit->builtin(Slice::Builtin::KindObjectProxy), false));
+ p->setValue(prx);
+ result = p;
+ return true;
+ }
+ else if(name == "proxyToString")
+ {
+ ProxyDataPtr prx;
+ if(args.size() > 0)
+ {
+ prx = ProxyDataPtr::dynamicCast(args.front());
+ }
+ if(args.size() != 1 || !prx)
+ {
+ errorReporter->error("proxyToString() requires a proxy argument");
+ }
+
+ result = factory->createString(prx->toString(), false);
+ return true;
+ }
+ else if(name == "lowercase")
+ {
+ StringDataPtr str;
+ if(args.size() > 0)
+ {
+ str = StringDataPtr::dynamicCast(args.front());
+ }
+ if(args.size() != 1 || !str)
+ {
+ errorReporter->error("lowercase() requires a string argument");
+ }
+ string val = str->stringValue();
+ transform(val.begin(), val.end(), val.begin(), ::tolower);
+ result = factory->createString(val, false);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+FreezeScript::invokeMemberFunction(const string& name, const DataPtr& target, const DataList& args, DataPtr& result,
+ const DataFactoryPtr& factory, const ErrorReporterPtr& errorReporter)
+{
+ //
+ // string
+ //
+ StringDataPtr targetStr = StringDataPtr::dynamicCast(target);
+ if(targetStr)
+ {
+ if(name == "find")
+ {
+ StringDataPtr argData;
+ IntegerDataPtr startData;
+ if(args.size() > 0)
+ {
+ argData = StringDataPtr::dynamicCast(args[0]);
+ }
+ if(args.size() > 1)
+ {
+ startData = IntegerDataPtr::dynamicCast(args[1]);
+ }
+ if(args.size() == 0 || args.size() > 2 || !argData || (args.size() == 2 && !startData))
+ {
+ errorReporter->error("invalid arguments to find(string str[, int len])");
+ }
+ string targ = targetStr->stringValue();
+ string arg = argData->stringValue();
+ string::size_type pos;
+ if(startData)
+ {
+ string::size_type start = static_cast<string::size_type>(startData->integerValue());
+ pos = targ.find(arg, start);
+ }
+ else
+ {
+ pos = targ.find(arg);
+ }
+ result = factory->createInteger(pos == string::npos ? -1 : static_cast<Ice::Long>(pos), false);
+ return true;
+ }
+ else if(name == "substr")
+ {
+ IntegerDataPtr startData;
+ IntegerDataPtr lenData;
+ if(args.size() > 0)
+ {
+ startData = IntegerDataPtr::dynamicCast(args[0]);
+ }
+ if(args.size() > 1)
+ {
+ lenData = IntegerDataPtr::dynamicCast(args[1]);
+ }
+ if(args.size() == 0 || args.size() > 2 || !startData || (args.size() == 2 && !lenData))
+ {
+ errorReporter->error("invalid arguments to substr(int start[, int len])");
+ }
+ string targ = targetStr->stringValue();
+ string::size_type start = static_cast<string::size_type>(startData->integerValue());
+ string::size_type len = string::npos;
+ if(lenData)
+ {
+ len = static_cast<string::size_type>(lenData->integerValue());
+ }
+ if(start > targ.size())
+ {
+ ostringstream ostr;
+ ostr << "substr() starting position (" << start << ") is greater than string length ("
+ << targ.size() << ")";
+ errorReporter->error(ostr.str());
+ }
+ result = factory->createString(targ.substr(start, len), false);
+ return true;
+ }
+ else if(name == "replace")
+ {
+ IntegerDataPtr startData;
+ IntegerDataPtr lenData;
+ StringDataPtr strData;
+ if(args.size() == 3)
+ {
+ startData = IntegerDataPtr::dynamicCast(args[0]);
+ lenData = IntegerDataPtr::dynamicCast(args[1]);
+ strData = StringDataPtr::dynamicCast(args[2]);
+ }
+ if(args.size() != 3 || !startData || !lenData || !strData)
+ {
+ errorReporter->error("invalid arguments to replace(int start, int len, string val)");
+ }
+ string targ = targetStr->stringValue();
+ string::size_type start = static_cast<string::size_type>(startData->integerValue());
+ string::size_type len = static_cast<string::size_type>(lenData->integerValue());
+ string str = strData->stringValue();
+ if(start > targ.size())
+ {
+ ostringstream ostr;
+ ostr << "replace() starting position (" << start << ") is greater than string length ("
+ << targ.size() << ")";
+ errorReporter->error(ostr.str());
+ }
+ result = factory->createString(targ.replace(start, len, str), false);
+ return true;
+ }
+
+ return false;
+ }
+
+ //
+ // Object
+ //
+ ObjectRefPtr targetObj = ObjectRefPtr::dynamicCast(target);
+ if(targetObj)
+ {
+ if(name == "ice_isA")
+ {
+ ObjectDataPtr value = targetObj->getValue();
+ if(!value)
+ {
+ errorReporter->error("ice_isA() invoked on nil object");
+ }
+ StringDataPtr str;
+ if(args.size() > 0)
+ {
+ str = StringDataPtr::dynamicCast(args.front());
+ }
+ if(args.size() != 1 || !str)
+ {
+ errorReporter->error("invalid arguments to ice_isA(string id)");
+ }
+
+ string id = str->stringValue();
+ if(id == "::Ice::Object")
+ {
+ result = factory->createBoolean(true, false);
+ return true;
+ }
+
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(value->getType());
+ if(!decl)
+ {
+ //
+ // Ice::Object
+ //
+ result = factory->createBoolean(false, false);
+ return true;
+ }
+
+ Slice::ClassDefPtr def = decl->definition();
+ assert(def);
+ result = factory->createBoolean(def->isA(id), false);
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
diff --git a/cpp/src/FreezeScript/Functions.h b/cpp/src/FreezeScript/Functions.h
new file mode 100644
index 00000000000..0dcb9f272b9
--- /dev/null
+++ b/cpp/src/FreezeScript/Functions.h
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_FUNCTIONS_H
+#define FREEZE_SCRIPT_FUNCTIONS_H
+
+#include <FreezeScript/Data.h>
+
+namespace FreezeScript
+{
+
+bool invokeGlobalFunction(const std::string&, const DataList&, DataPtr&, const DataFactoryPtr&,
+ const ErrorReporterPtr&);
+
+bool invokeMemberFunction(const std::string&, const DataPtr&, const DataList&, DataPtr&, const DataFactoryPtr&,
+ const ErrorReporterPtr&);
+
+}
+
+#endif
diff --git a/cpp/src/FreezeScript/Grammar.y b/cpp/src/FreezeScript/Grammar.y
new file mode 100644
index 00000000000..225be134a29
--- /dev/null
+++ b/cpp/src/FreezeScript/Grammar.y
@@ -0,0 +1,320 @@
+%{
+
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/GrammarUtil.h>
+
+#ifdef _WIN32
+// I get these warnings from some bison versions:
+// warning C4102: 'yyoverflowlab' : unreferenced label
+# pragma warning( disable : 4102 )
+// warning C4065: switch statement contains 'default' but no 'case' labels
+# pragma warning( disable : 4065 )
+#endif
+
+using namespace std;
+using namespace FreezeScript;
+
+void
+freeze_script_error(const char* s)
+{
+ // yacc and recent versions of Bison use "syntax error" instead
+ // of "parse error".
+
+ if(strcmp(s, "parse error") == 0)
+ {
+ parseErrorReporter->expressionSyntaxError("syntax error");
+ }
+ else
+ {
+ parseErrorReporter->expressionSyntaxError(s);
+ }
+}
+
+%}
+
+%pure_parser
+%name_prefix="freeze_script_"
+
+%token TOK_AND
+%token TOK_OR
+%token TOK_NOT
+%token TOK_ADD
+%token TOK_SUB
+%token TOK_MUL
+%token TOK_DIV
+%token TOK_MOD
+%token TOK_LPAREN
+%token TOK_RPAREN
+%token TOK_LBRACKET
+%token TOK_RBRACKET
+%token TOK_LESS_THAN
+%token TOK_GREATER_THAN
+%token TOK_LESS_EQUAL
+%token TOK_GREATER_EQUAL
+%token TOK_EQUAL
+%token TOK_NEQ
+%token TOK_TRUE
+%token TOK_FALSE
+%token TOK_NIL
+%token TOK_SCOPE_DELIMITER
+%token TOK_IDENTIFIER
+%token TOK_STRING_LITERAL
+%token TOK_INTEGER_LITERAL
+%token TOK_FLOATING_POINT_LITERAL
+
+%left TOK_OR
+%left TOK_AND
+%nonassoc TOK_LESS_THAN TOK_GREATER_THAN TOK_LESS_EQUAL TOK_GREATER_EQUAL TOK_EQUAL TOK_NEQ
+%left TOK_ADD TOK_SUB
+%left TOK_MUL TOK_DIV TOK_MOD
+%right UNARY_OP
+
+%%
+
+// ----------------------------------------------------------------------
+start
+// ----------------------------------------------------------------------
+: expr
+{
+ parseResult = $1;
+}
+;
+
+// ----------------------------------------------------------------------
+expr
+// ----------------------------------------------------------------------
+: binary
+{
+ $$ = $1;
+}
+;
+
+// ----------------------------------------------------------------------
+binary
+// ----------------------------------------------------------------------
+: binary TOK_LESS_THAN binary
+{
+ $$ = new BinaryNode(BinOpLess, parseDataFactory, $1, $3);
+}
+| binary TOK_GREATER_THAN binary
+{
+ $$ = new BinaryNode(BinOpGreater, parseDataFactory, $1, $3);
+}
+| binary TOK_LESS_EQUAL binary
+{
+ $$ = new BinaryNode(BinOpLessEq, parseDataFactory, $1, $3);
+}
+| binary TOK_GREATER_EQUAL binary
+{
+ $$ = new BinaryNode(BinOpGrEq, parseDataFactory, $1, $3);
+}
+| binary TOK_EQUAL binary
+{
+ $$ = new BinaryNode(BinOpEq, parseDataFactory, $1, $3);
+}
+| binary TOK_NEQ binary
+{
+ $$ = new BinaryNode(BinOpNotEq, parseDataFactory, $1, $3);
+}
+| binary TOK_OR binary
+{
+ $$ = new BinaryNode(BinOpOr, parseDataFactory, $1, $3);
+}
+| binary TOK_AND binary
+{
+ $$ = new BinaryNode(BinOpAnd, parseDataFactory, $1, $3);
+}
+| binary TOK_MUL binary
+{
+ $$ = new BinaryNode(BinOpMul, parseDataFactory, $1, $3);
+}
+| binary TOK_DIV binary
+{
+ $$ = new BinaryNode(BinOpDiv, parseDataFactory, $1, $3);
+}
+| binary TOK_MOD binary
+{
+ $$ = new BinaryNode(BinOpMod, parseDataFactory, $1, $3);
+}
+| binary TOK_ADD binary
+{
+ $$ = new BinaryNode(BinOpAdd, parseDataFactory, $1, $3);
+}
+| binary TOK_SUB binary
+{
+ $$ = new BinaryNode(BinOpSub, parseDataFactory, $1, $3);
+}
+| unary
+{
+ $$ = $1;
+}
+;
+
+// ----------------------------------------------------------------------
+unary
+// ----------------------------------------------------------------------
+: TOK_LPAREN expr TOK_RPAREN
+{
+ $$ = $2;
+}
+| TOK_SUB unary %prec UNARY_OP
+{
+ $$ = new UnaryNode(UnaryOpNeg, parseDataFactory, $2);
+}
+| TOK_NOT unary %prec UNARY_OP
+{
+ $$ = new UnaryNode(UnaryOpNot, parseDataFactory, $2);
+}
+| TOK_INTEGER_LITERAL
+{
+ IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1);
+ assert(intVal);
+ $$ = new DataNode(parseDataFactory->createInteger(intVal->v, true));
+}
+| TOK_FLOATING_POINT_LITERAL
+{
+ FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1);
+ assert(floatVal);
+ $$ = new DataNode(parseDataFactory->createDouble(floatVal->v, true));
+}
+| TOK_STRING_LITERAL
+{
+ StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
+ assert(stringVal);
+ $$ = new DataNode(parseDataFactory->createString(stringVal->v, true));
+}
+| TOK_TRUE
+{
+ $$ = new DataNode(parseDataFactory->createBoolean(true, true));
+}
+| TOK_FALSE
+{
+ $$ = new DataNode(parseDataFactory->createBoolean(false, true));
+}
+| TOK_NIL
+{
+ $$ = new DataNode(parseDataFactory->createNil(true));
+}
+| entity
+{
+ $$ = $1;
+}
+| entity '.' function
+{
+ EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
+ assert(entity);
+ FunctionNodePtr func = FunctionNodePtr::dynamicCast($3);
+ assert(func);
+ func->setTarget(entity);
+ $$ = $3;
+}
+| function
+{
+ $$ = $1;
+}
+| constant
+{
+ StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
+ assert(stringVal);
+ $$ = new ConstantNode(stringVal->v);
+}
+;
+
+// ----------------------------------------------------------------------
+entity
+// ----------------------------------------------------------------------
+: entity TOK_LBRACKET expr TOK_RBRACKET
+{
+ EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
+ assert(entity);
+ entity->append(new ElementNode($3));
+ $$ = $1;
+}
+| entity '.' TOK_IDENTIFIER
+{
+ StringTokPtr stringVal = StringTokPtr::dynamicCast($3);
+ assert(stringVal);
+ EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
+ assert(entity);
+ entity->append(new IdentNode(stringVal->v));
+ $$ = $1;
+}
+| TOK_IDENTIFIER
+{
+ StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
+ assert(stringVal);
+ $$ = new IdentNode(stringVal->v);
+}
+;
+
+// ----------------------------------------------------------------------
+function
+// ----------------------------------------------------------------------
+: TOK_IDENTIFIER TOK_LPAREN arg_list TOK_RPAREN
+{
+ StringTokPtr func = StringTokPtr::dynamicCast($1);
+ assert(func);
+ NodeListTokPtr args = NodeListTokPtr::dynamicCast($3);
+ assert(args);
+ $$ = new FunctionNode(func->v, args->v);
+}
+;
+
+// ----------------------------------------------------------------------
+arg_list
+// ----------------------------------------------------------------------
+: arg_list ',' expr
+{
+ NodeListTokPtr l = NodeListTokPtr::dynamicCast($1);
+ assert(l);
+ l->v.push_back($3);
+ $$ = $1;
+}
+| expr
+{
+ NodeListTokPtr result = new NodeListTok;
+ result->v.push_back($1);
+ $$ = result;
+}
+|
+{
+ $$ = new NodeListTok;
+}
+;
+
+// ----------------------------------------------------------------------
+constant
+// ----------------------------------------------------------------------
+: constant TOK_SCOPE_DELIMITER TOK_IDENTIFIER
+{
+ StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
+ assert(stringVal);
+ StringTokPtr idVal = StringTokPtr::dynamicCast($3);
+ assert(idVal);
+ stringVal->v.append("::" + idVal->v);
+ $$ = $1;
+}
+| TOK_SCOPE_DELIMITER TOK_IDENTIFIER
+{
+ StringTokPtr idVal = StringTokPtr::dynamicCast($2);
+ assert(idVal);
+ StringTokPtr stringVal = new StringTok;
+ stringVal->v.append("::" + idVal->v);
+ $$ = stringVal;
+}
+;
+
+%%
diff --git a/cpp/src/FreezeScript/GrammarUtil.h b/cpp/src/FreezeScript/GrammarUtil.h
new file mode 100644
index 00000000000..1a438a1f573
--- /dev/null
+++ b/cpp/src/FreezeScript/GrammarUtil.h
@@ -0,0 +1,141 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_GRAMMAR_UTIL_H
+#define FREEZE_SCRIPT_GRAMMAR_UTIL_H
+
+#include <FreezeScript/Parser.h>
+
+namespace FreezeScript
+{
+
+extern DataFactoryPtr parseDataFactory;
+extern ErrorReporterPtr parseErrorReporter;
+extern NodePtr parseResult;
+extern int parseLine;
+
+int getInput(char*, int);
+
+class StringTok;
+class IdentifierTok;
+class BoolTok;
+class IntegerTok;
+class FloatingTok;
+class NodeListTok;
+
+typedef ::IceUtil::Handle<StringTok> StringTokPtr;
+typedef ::IceUtil::Handle<IdentifierTok> IdentifierTokPtr;
+typedef ::IceUtil::Handle<BoolTok> BoolTokPtr;
+typedef ::IceUtil::Handle<IntegerTok> IntegerTokPtr;
+typedef ::IceUtil::Handle<FloatingTok> FloatingTokPtr;
+typedef ::IceUtil::Handle<NodeListTok> NodeListTokPtr;
+
+// ----------------------------------------------------------------------
+// Token
+// ----------------------------------------------------------------------
+
+class Token : public Node
+{
+public:
+
+ Token() { }
+ virtual DataPtr evaluate(const SymbolTablePtr&) { return 0; }
+ virtual void print(std::ostream&) const {}
+};
+
+// ----------------------------------------------------------------------
+// StringTok
+// ----------------------------------------------------------------------
+
+class StringTok : public Token
+{
+public:
+
+ StringTok() { }
+
+ std::string v;
+};
+
+// ----------------------------------------------------------------------
+// BoolTok
+// ----------------------------------------------------------------------
+
+class BoolTok : public Token
+{
+public:
+
+ BoolTok() { }
+ bool v;
+};
+
+// ----------------------------------------------------------------------
+// IntegerTok
+// ----------------------------------------------------------------------
+
+class IntegerTok : public Token
+{
+public:
+
+ IntegerTok() { }
+ IceUtil::Int64 v;
+};
+
+// ----------------------------------------------------------------------
+// FloatingTok
+// ----------------------------------------------------------------------
+
+class FloatingTok : public Token
+{
+public:
+
+ FloatingTok() { }
+ double v;
+};
+
+class NodeListTok : public Token
+{
+public:
+
+ NodeListTok() { }
+ NodeList v;
+};
+
+} // End of namespace FreezeScript
+
+//
+// Stuff for flex and bison
+//
+
+#define YYSTYPE FreezeScript::NodePtr
+#define YY_DECL int freeze_script_lex(YYSTYPE* yylvalp)
+YY_DECL;
+int freeze_script_parse();
+
+//
+// I must set the initial stack depth to the maximum stack depth to
+// disable bison stack resizing. The bison stack resizing routines use
+// simple malloc/alloc/memcpy calls, which do not work for the
+// YYSTYPE, since YYSTYPE is a C++ type, with constructor, destructor,
+// assignment operator, etc.
+//
+#define YYMAXDEPTH 20000 // 20000 should suffice. Bison default is 10000 as maximum.
+#define YYINITDEPTH YYMAXDEPTH // Initial depth is set to max depth, for the reasons described above.
+
+//
+// Newer bison versions allow to disable stack resizing by defining
+// yyoverflow.
+//
+#define yyoverflow(a, b, c, d, e, f) freeze_script_error(a)
+
+#endif
diff --git a/cpp/src/FreezeScript/Makefile b/cpp/src/FreezeScript/Makefile
new file mode 100644
index 00000000000..8bcb57c0ccf
--- /dev/null
+++ b/cpp/src/FreezeScript/Makefile
@@ -0,0 +1,57 @@
+# **********************************************************************
+#
+# Copyright (c) 2004
+# ZeroC, Inc.
+# Billerica, MA, USA
+#
+# All Rights Reserved.
+#
+# Ice is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License version 2 as published by
+# the Free Software Foundation.
+#
+# **********************************************************************
+
+top_srcdir = ../..
+
+TRANSFORMDB = $(top_srcdir)/bin/transformdb
+
+TARGETS = $(TRANSFORMDB)
+
+OBJS = Grammar.o \
+ Scanner.o \
+ AssignVisitor.o \
+ Data.o \
+ Error.o \
+ Functions.o \
+ Exception.o \
+ Parser.o \
+ Print.o \
+ TransformAnalyzer.o \
+ TransformDescriptors.o \
+ TransformVisitor.o \
+ Transformer.o \
+ Util.o
+
+TRANSFORM_OBJS = TransformDB.o
+
+SRCS = $(OBJS:.o=.cpp) $(TRANSFORM_OBJS:.o=.cpp)
+
+HDIR = $(includedir)/FreezeScript
+
+include $(top_srcdir)/config/Make.rules
+
+CPPFLAGS := -I.. $(CPPFLAGS) $(DB_FLAGS)
+
+$(TRANSFORMDB): $(TRANSFORM_OBJS) $(OBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(TRANSFORM_OBJS) $(OBJS) -lSlice -lIceXML $(LIBS) $(DB_LIBS)
+
+clean::
+ rm -f Grammar.cpp Grammar.h
+ rm -f Scanner.cpp
+
+install:: all
+ $(INSTALL_PROGRAM) $(TRANSFORMDB) $(install_bindir)
+
+include .depend
diff --git a/cpp/src/FreezeScript/Parser.cpp b/cpp/src/FreezeScript/Parser.cpp
new file mode 100644
index 00000000000..a3f0db5b42c
--- /dev/null
+++ b/cpp/src/FreezeScript/Parser.cpp
@@ -0,0 +1,691 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Parser.h>
+#include <FreezeScript/GrammarUtil.h>
+#include <IceUtil/Mutex.h>
+
+using namespace std;
+
+namespace FreezeScript
+{
+
+class EntityNodePrinter : public EntityNodeVisitor
+{
+public:
+
+ EntityNodePrinter(ostream& os) :
+ _os(os), _first(true)
+ {
+ }
+
+ virtual void
+ visitIdentifier(const std::string& name)
+ {
+ if(_first)
+ {
+ _first = false;
+ }
+ else
+ {
+ _os << '.';
+ }
+ _os << name;
+ }
+
+ virtual void
+ visitElement(const NodePtr& value)
+ {
+ assert(!_first);
+ _os << '[';
+ value->print(_os);
+ _os << ']';
+ }
+
+private:
+
+ ostream& _os;
+ bool _first;
+};
+
+} // End of namespace FreezeScript
+
+//
+// Globals required by the Bison grammar.
+//
+FreezeScript::DataFactoryPtr FreezeScript::parseDataFactory;
+FreezeScript::ErrorReporterPtr FreezeScript::parseErrorReporter;
+FreezeScript::NodePtr FreezeScript::parseResult;
+int FreezeScript::parseLine;
+
+static string _input;
+static string::size_type _pos;
+static IceUtil::Mutex _parserMutex;
+
+//
+// parseExpression
+//
+FreezeScript::NodePtr
+FreezeScript::parseExpression(const string& expr, const DataFactoryPtr& factory, const ErrorReporterPtr& errorReporter)
+{
+ //
+ // The bison grammar is not thread-safe.
+ //
+ IceUtil::Mutex::Lock sync(_parserMutex);
+
+ parseDataFactory = factory;
+ parseErrorReporter = errorReporter;
+ parseLine = 1;
+
+ parseErrorReporter->setExpression(expr);
+
+ _input = expr;
+ _pos = 0;
+
+ int status = freeze_script_parse();
+ if(status != 0)
+ {
+ parseResult = 0;
+ }
+
+ parseErrorReporter->clearExpression();
+ parseErrorReporter = 0;
+
+ return parseResult;
+}
+
+//
+// getInput supplies characters to the lexical scanner.
+//
+int
+FreezeScript::getInput(char* buf, int maxSize)
+{
+ if(_pos < _input.length())
+ {
+ buf[0] = _input[_pos];
+ _pos++;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+//
+// EvaluateException
+//
+FreezeScript::EvaluateException::EvaluateException(const char* file, int line, const string& reason) :
+ IceUtil::Exception(file, line), _reason(reason)
+{
+}
+
+string FreezeScript::EvaluateException::_name = "FreezeScript::EvaluateException";
+
+const string&
+FreezeScript::EvaluateException::ice_name() const
+{
+ return _name;
+}
+
+void
+FreezeScript::EvaluateException::ice_print(ostream& out) const
+{
+ Exception::ice_print(out);
+ out << ":\nerror occurred while evaluating expression";
+ if(!_reason.empty())
+ {
+ out << ":\n" << _reason;
+ }
+}
+
+IceUtil::Exception*
+FreezeScript::EvaluateException::ice_clone() const
+{
+ return new EvaluateException(ice_file(), ice_line(), _reason);
+}
+
+void
+FreezeScript::EvaluateException::ice_throw() const
+{
+ throw *this;
+}
+
+string
+FreezeScript::EvaluateException::reason() const
+{
+ return _reason;
+}
+
+//
+// SymbolTable
+//
+FreezeScript::SymbolTable::~SymbolTable()
+{
+}
+
+//
+// Node
+//
+FreezeScript::Node::~Node()
+{
+}
+
+//
+// BinaryNode
+//
+FreezeScript::BinaryNode::BinaryNode(BinaryOperator op, const DataFactoryPtr& factory, const NodePtr& left,
+ const NodePtr& right) :
+ _op(op), _factory(factory), _left(left), _right(right)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::BinaryNode::evaluate(const SymbolTablePtr& st)
+{
+ DataPtr result;
+
+ switch(_op)
+ {
+ case BinOpOr:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ if(leftValue->booleanValue())
+ {
+ result = leftValue;
+ }
+ else
+ {
+ result = _right->evaluate(st);
+ }
+ break;
+ }
+
+ case BinOpAnd:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ if(!leftValue->booleanValue())
+ {
+ result = leftValue;
+ }
+ else
+ {
+ result = _right->evaluate(st);
+ }
+ break;
+ }
+
+ case BinOpMul:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ IntegerDataPtr ileft = IntegerDataPtr::dynamicCast(leftValue);
+ IntegerDataPtr iright = IntegerDataPtr::dynamicCast(rightValue);
+ if(ileft && iright)
+ {
+ result = _factory->createInteger(leftValue->integerValue() * rightValue->integerValue(), true);
+ }
+ else
+ {
+ result = _factory->createDouble(leftValue->doubleValue(true) * rightValue->doubleValue(true), true);
+ }
+ break;
+ }
+
+ case BinOpDiv:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ IntegerDataPtr ileft = IntegerDataPtr::dynamicCast(leftValue);
+ IntegerDataPtr iright = IntegerDataPtr::dynamicCast(rightValue);
+ if(ileft && iright)
+ {
+ result = _factory->createInteger(leftValue->integerValue() / rightValue->integerValue(), true);
+ }
+ else
+ {
+ result = _factory->createDouble(leftValue->doubleValue(true) / rightValue->doubleValue(true), true);
+ }
+ break;
+ }
+
+ case BinOpMod:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ result = _factory->createInteger(leftValue->integerValue() % rightValue->integerValue(), true);
+ break;
+ }
+
+ case BinOpAdd:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ IntegerDataPtr ileft = IntegerDataPtr::dynamicCast(leftValue);
+ IntegerDataPtr iright = IntegerDataPtr::dynamicCast(rightValue);
+ if(ileft && iright)
+ {
+ result = _factory->createInteger(leftValue->integerValue() + rightValue->integerValue(), true);
+ }
+ else
+ {
+ result = _factory->createDouble(leftValue->doubleValue(true) + rightValue->doubleValue(true), true);
+ }
+ break;
+ }
+
+ case BinOpSub:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ IntegerDataPtr ileft = IntegerDataPtr::dynamicCast(leftValue);
+ IntegerDataPtr iright = IntegerDataPtr::dynamicCast(rightValue);
+ if(ileft && iright)
+ {
+ result = _factory->createInteger(leftValue->integerValue() - rightValue->integerValue(), true);
+ }
+ else
+ {
+ result = _factory->createDouble(leftValue->doubleValue(true) - rightValue->doubleValue(true), true);
+ }
+ break;
+ }
+
+ case BinOpLess:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ bool b = leftValue < rightValue;
+ result = _factory->createBoolean(b, true);
+ break;
+ }
+
+ case BinOpGreater:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ bool b = (leftValue < rightValue) || (leftValue == rightValue);
+ result = _factory->createBoolean(!b, true);
+ break;
+ }
+
+ case BinOpLessEq:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ bool b = (leftValue < rightValue) || (leftValue == rightValue);
+ result = _factory->createBoolean(b, true);
+ break;
+ }
+
+ case BinOpGrEq:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ bool b = leftValue < rightValue;
+ result = _factory->createBoolean(!b, true);
+ break;
+ }
+
+ case BinOpEq:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ bool b = leftValue == rightValue;
+ result = _factory->createBoolean(b, true);
+ break;
+ }
+
+ case BinOpNotEq:
+ {
+ DataPtr leftValue = _left->evaluate(st);
+ DataPtr rightValue = _right->evaluate(st);
+ bool b = leftValue == rightValue;
+ result = _factory->createBoolean(!b, true);
+ break;
+ }
+ }
+
+ if(!result)
+ {
+ throw EvaluateException(__FILE__, __LINE__, "invalid operands to operator " + opToString(_op));
+ }
+
+ return result;
+}
+
+void
+FreezeScript::BinaryNode::print(ostream& os) const
+{
+ os << opToString(_op) << ": left=";
+ _left->print(os);
+ os << ", right=";
+ _right->print(os);
+}
+
+string
+FreezeScript::BinaryNode::opToString(BinaryOperator op)
+{
+ switch(op)
+ {
+ case BinOpOr:
+ return "OR";
+
+ case BinOpAnd:
+ return "AND";
+
+ case BinOpMul:
+ return "*";
+
+ case BinOpDiv:
+ return "/";
+
+ case BinOpMod:
+ return "%";
+
+ case BinOpAdd:
+ return "+";
+
+ case BinOpSub:
+ return "-";
+
+ case BinOpLess:
+ return "<";
+
+ case BinOpGreater:
+ return ">";
+
+ case BinOpLessEq:
+ return "<=";
+
+ case BinOpGrEq:
+ return ">=";
+
+ case BinOpEq:
+ return "==";
+
+ case BinOpNotEq:
+ return "!=";
+ }
+
+ assert(false);
+ return string();
+}
+
+//
+// UnaryNode
+//
+FreezeScript::UnaryNode::UnaryNode(UnaryOperator op, const DataFactoryPtr& factory, const NodePtr& right) :
+ _op(op), _factory(factory), _right(right)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::UnaryNode::evaluate(const SymbolTablePtr& st)
+{
+ DataPtr result;
+
+ switch(_op)
+ {
+ case UnaryOpNeg:
+ {
+ DataPtr rightValue = _right->evaluate(st);
+ IntegerDataPtr iright = IntegerDataPtr::dynamicCast(rightValue);
+ if(iright)
+ {
+ result = _factory->createInteger(-rightValue->integerValue(), true);
+ }
+ else
+ {
+ result = _factory->createDouble(-rightValue->doubleValue(), true);
+ }
+ break;
+ }
+
+ case UnaryOpNot:
+ {
+ DataPtr rightValue = _right->evaluate(st);
+ result = _factory->createBoolean(!rightValue->booleanValue(), true);
+ break;
+ }
+ }
+
+ if(!result)
+ {
+ throw EvaluateException(__FILE__, __LINE__, "invalid operand to operator " + opToString(_op));
+ }
+
+ return result;
+}
+
+void
+FreezeScript::UnaryNode::print(ostream& os) const
+{
+ os << opToString(_op) << ": right=";
+ _right->print(os);
+}
+
+string
+FreezeScript::UnaryNode::opToString(UnaryOperator op)
+{
+ switch(op)
+ {
+ case UnaryOpNeg:
+ return "-";
+
+ case UnaryOpNot:
+ return "!";
+ }
+
+ assert(false);
+ return string();
+}
+
+//
+// DataNode
+//
+FreezeScript::DataNode::DataNode(const DataPtr& data) :
+ _data(data)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::DataNode::evaluate(const SymbolTablePtr&)
+{
+ return _data;
+}
+
+void
+FreezeScript::DataNode::print(ostream& os) const
+{
+ // TODO
+ //_data->print(os);
+}
+
+//
+// EntityNodeVisitor
+//
+FreezeScript::EntityNodeVisitor::~EntityNodeVisitor()
+{
+}
+
+//
+// EntityNode
+//
+FreezeScript::DataPtr
+FreezeScript::EntityNode::evaluate(const SymbolTablePtr& st)
+{
+ DataPtr result = st->getValue(this);
+ if(!result)
+ {
+ ostringstream ostr;
+ print(ostr);
+ throw EvaluateException(__FILE__, __LINE__, "unknown entity `" + ostr.str() + "'");
+ }
+ return result;
+}
+
+void
+FreezeScript::EntityNode::print(ostream& os) const
+{
+ EntityNodePrinter printer(os);
+ visit(printer);
+}
+
+void
+FreezeScript::EntityNode::append(const EntityNodePtr& next)
+{
+ if(_next)
+ {
+ _next->append(next);
+ }
+ else
+ {
+ _next = next;
+ }
+}
+
+//
+// IdentNode
+//
+FreezeScript::IdentNode::IdentNode(const string& value) :
+ _value(value)
+{
+}
+
+string
+FreezeScript::IdentNode::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::IdentNode::visit(EntityNodeVisitor& visitor) const
+{
+ visitor.visitIdentifier(_value);
+ if(_next)
+ {
+ _next->visit(visitor);
+ }
+}
+
+//
+// ElementNode
+//
+FreezeScript::ElementNode::ElementNode(const NodePtr& value) :
+ _value(value)
+{
+}
+
+FreezeScript::NodePtr
+FreezeScript::ElementNode::getValue() const
+{
+ return _value;
+}
+
+void
+FreezeScript::ElementNode::visit(EntityNodeVisitor& visitor) const
+{
+ visitor.visitElement(_value);
+ if(_next)
+ {
+ _next->visit(visitor);
+ }
+}
+
+//
+// FunctionNode
+//
+FreezeScript::FunctionNode::FunctionNode(const string& name, const NodeList& args) :
+ _name(name), _args(args)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::FunctionNode::evaluate(const SymbolTablePtr& st)
+{
+ DataPtr target;
+ if(_target)
+ {
+ target = _target->evaluate(st);
+ }
+ DataList args;
+ for(NodeList::iterator p = _args.begin(); p != _args.end(); ++p)
+ {
+ args.push_back((*p)->evaluate(st));
+ }
+ return st->invokeFunction(_name, target, args);
+}
+
+void
+FreezeScript::FunctionNode::print(ostream& os) const
+{
+ if(_target)
+ {
+ _target->print(os);
+ os << '.';
+ }
+ os << _name << '(';
+ for(NodeList::const_iterator p = _args.begin(); p != _args.end(); ++p)
+ {
+ if(p != _args.begin())
+ {
+ os << ", ";
+ }
+ (*p)->print(os);
+ }
+ os << ')';
+}
+
+void
+FreezeScript::FunctionNode::setTarget(const EntityNodePtr& target)
+{
+ _target = target;
+}
+
+//
+// ConstantNode
+//
+FreezeScript::ConstantNode::ConstantNode(const string& value) :
+ _value(value)
+{
+}
+
+FreezeScript::DataPtr
+FreezeScript::ConstantNode::evaluate(const SymbolTablePtr& st)
+{
+ DataPtr result = st->getConstantValue(_value);
+ if(!result)
+ {
+ throw EvaluateException(__FILE__, __LINE__, "unknown constant `" + _value + "'");
+ }
+ return result;
+}
+
+void
+FreezeScript::ConstantNode::print(ostream& os) const
+{
+ os << _value;
+}
+
+//
+// Stream insertion for an entity node.
+//
+ostream&
+operator<<(ostream& os, const FreezeScript::EntityNodePtr& entity)
+{
+ FreezeScript::EntityNodePrinter printer(os);
+ entity->visit(printer);
+ return os;
+}
diff --git a/cpp/src/FreezeScript/Parser.h b/cpp/src/FreezeScript/Parser.h
new file mode 100644
index 00000000000..82e15e5cb1f
--- /dev/null
+++ b/cpp/src/FreezeScript/Parser.h
@@ -0,0 +1,255 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_PARSER_H
+#define FREEZE_SCRIPT_PARSER_H
+
+#include <FreezeScript/Data.h>
+
+namespace FreezeScript
+{
+
+class SymbolTable;
+typedef IceUtil::Handle<SymbolTable> SymbolTablePtr;
+
+class Node;
+typedef IceUtil::Handle<Node> NodePtr;
+
+typedef std::vector<NodePtr> NodeList;
+
+class EntityNode;
+typedef IceUtil::Handle<EntityNode> EntityNodePtr;
+
+//
+// parseExpression parses the given expression and returns the root node of the parse tree.
+//
+NodePtr parseExpression(const std::string&, const DataFactoryPtr&, const ErrorReporterPtr&);
+
+//
+// EvaluateException is raised by Node::evaluate().
+//
+class EvaluateException : public IceUtil::Exception
+{
+public:
+
+ EvaluateException(const char*, int, const std::string&);
+ virtual const std::string& ice_name() const;
+ virtual void ice_print(std::ostream&) const;
+ virtual IceUtil::Exception* ice_clone() const;
+ virtual void ice_throw() const;
+
+ std::string reason() const;
+
+private:
+
+ std::string _reason;
+ static std::string _name;
+};
+
+//
+// SymbolTable is an interface for the lookup operations required by node evaluation.
+//
+class SymbolTable : public IceUtil::SimpleShared
+{
+public:
+
+ virtual ~SymbolTable();
+
+ virtual void add(const std::string&, const DataPtr&) = 0;
+
+ virtual DataPtr getValue(const EntityNodePtr&) const = 0;
+
+ virtual DataPtr getConstantValue(const std::string&) const = 0;
+
+ virtual SymbolTablePtr createChild() = 0;
+
+ virtual Slice::TypePtr lookupType(const std::string&) = 0;
+
+ virtual DataPtr invokeFunction(const std::string&, const DataPtr&, const DataList&) = 0;
+};
+
+class Node : public IceUtil::SimpleShared
+{
+public:
+
+ virtual ~Node();
+
+ virtual DataPtr evaluate(const SymbolTablePtr&) = 0;
+
+ virtual void print(std::ostream&) const = 0;
+};
+
+enum BinaryOperator
+{
+ BinOpOr, BinOpAnd,
+ BinOpMul, BinOpDiv, BinOpMod,
+ BinOpAdd, BinOpSub,
+ BinOpLess, BinOpGreater, BinOpLessEq, BinOpGrEq, BinOpEq, BinOpNotEq
+};
+
+class BinaryNode : public Node
+{
+public:
+
+ BinaryNode(BinaryOperator, const DataFactoryPtr&, const NodePtr&, const NodePtr&);
+
+ virtual DataPtr evaluate(const SymbolTablePtr&);
+
+ virtual void print(std::ostream&) const;
+
+private:
+
+ static std::string opToString(BinaryOperator);
+
+ BinaryOperator _op;
+ DataFactoryPtr _factory;
+ NodePtr _left;
+ NodePtr _right;
+};
+
+enum UnaryOperator { UnaryOpNeg, UnaryOpNot };
+
+class UnaryNode : public Node
+{
+public:
+
+ UnaryNode(UnaryOperator, const DataFactoryPtr&, const NodePtr&);
+
+ virtual DataPtr evaluate(const SymbolTablePtr&);
+
+ virtual void print(std::ostream&) const;
+
+private:
+
+ static std::string opToString(UnaryOperator);
+
+ UnaryOperator _op;
+ DataFactoryPtr _factory;
+ NodePtr _right;
+};
+
+class DataNode : public Node
+{
+public:
+
+ DataNode(const DataPtr&);
+
+ virtual DataPtr evaluate(const SymbolTablePtr&);
+
+ virtual void print(std::ostream&) const;
+
+private:
+
+ DataPtr _data;
+};
+
+class EntityNodeVisitor
+{
+public:
+
+ virtual ~EntityNodeVisitor();
+
+ virtual void visitIdentifier(const std::string&) = 0;
+ virtual void visitElement(const NodePtr&) = 0;
+};
+
+class EntityNode : public Node
+{
+public:
+
+ virtual DataPtr evaluate(const SymbolTablePtr&);
+
+ virtual void print(std::ostream&) const;
+
+ virtual void visit(EntityNodeVisitor&) const = 0;
+
+ void append(const EntityNodePtr&);
+
+protected:
+
+ EntityNodePtr _next;
+};
+
+class IdentNode : public EntityNode
+{
+public:
+
+ IdentNode(const std::string&);
+
+ virtual void visit(EntityNodeVisitor&) const;
+
+ std::string getValue() const;
+
+private:
+
+ std::string _value;
+};
+typedef IceUtil::Handle<IdentNode> IdentNodePtr;
+
+class ElementNode : public EntityNode
+{
+public:
+
+ ElementNode(const NodePtr&);
+
+ virtual void visit(EntityNodeVisitor&) const;
+
+ NodePtr getValue() const;
+
+private:
+
+ NodePtr _value;
+};
+typedef IceUtil::Handle<ElementNode> ElementNodePtr;
+
+class FunctionNode : public Node
+{
+public:
+
+ FunctionNode(const std::string&, const NodeList&);
+
+ virtual DataPtr evaluate(const SymbolTablePtr&);
+
+ virtual void print(std::ostream&) const;
+
+ void setTarget(const EntityNodePtr&);
+
+private:
+
+ std::string _name;
+ NodeList _args;
+ EntityNodePtr _target;
+};
+typedef IceUtil::Handle<FunctionNode> FunctionNodePtr;
+
+class ConstantNode : public Node
+{
+public:
+
+ ConstantNode(const std::string&);
+
+ virtual DataPtr evaluate(const SymbolTablePtr&);
+
+ virtual void print(std::ostream&) const;
+
+private:
+
+ std::string _value;
+};
+
+} // End of namespace FreezeScript
+
+std::ostream& operator<<(std::ostream&, const FreezeScript::EntityNodePtr&);
+
+#endif
diff --git a/cpp/src/FreezeScript/Print.cpp b/cpp/src/FreezeScript/Print.cpp
new file mode 100644
index 00000000000..e35be8f762a
--- /dev/null
+++ b/cpp/src/FreezeScript/Print.cpp
@@ -0,0 +1,240 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Print.h>
+#include <FreezeScript/Util.h>
+#include <IceUtil/OutputUtil.h>
+
+using namespace std;
+using namespace IceUtil;
+
+namespace FreezeScript
+{
+
+class PrintVisitor : public DataVisitor
+{
+public:
+
+ PrintVisitor(ostream&);
+ ~PrintVisitor();
+
+ virtual void visitBoolean(const BooleanDataPtr&);
+ virtual void visitInteger(const IntegerDataPtr&);
+ virtual void visitDouble(const DoubleDataPtr&);
+ virtual void visitString(const StringDataPtr&);
+ virtual void visitProxy(const ProxyDataPtr&);
+ virtual void visitStruct(const StructDataPtr&);
+ virtual void visitSequence(const SequenceDataPtr&);
+ virtual void visitEnum(const EnumDataPtr&);
+ virtual void visitDictionary(const DictionaryDataPtr&);
+ virtual void visitObject(const ObjectRefPtr&);
+
+private:
+
+ void printObjectMembers(const Slice::ClassDefPtr&, const DataMemberMap&);
+
+ IceUtil::Output _out;
+ typedef map<const ObjectData*, int> ObjectHistoryMap;
+ ObjectHistoryMap _objectHistory;
+ int _objectCount;
+};
+
+} // End of namespace FreezeScript
+
+//
+// printData
+//
+void
+FreezeScript::printData(const DataPtr& data, ostream& os)
+{
+ PrintVisitor visitor(os);
+ data->visit(visitor);
+}
+
+//
+// PrintVisitor
+//
+FreezeScript::PrintVisitor::PrintVisitor(ostream& os) :
+ _out(os), _objectCount(0)
+{
+}
+
+FreezeScript::PrintVisitor::~PrintVisitor()
+{
+}
+
+void
+FreezeScript::PrintVisitor::visitBoolean(const BooleanDataPtr& data)
+{
+ _out << "bool(" << data->toString() << ")";
+}
+
+void
+FreezeScript::PrintVisitor::visitInteger(const IntegerDataPtr& data)
+{
+ _out << typeToString(data->getType()) << "(" << data->toString() << ")";
+}
+
+void
+FreezeScript::PrintVisitor::visitDouble(const DoubleDataPtr& data)
+{
+ _out << typeToString(data->getType()) << "(" << data->toString() << ")";
+}
+
+void
+FreezeScript::PrintVisitor::visitString(const StringDataPtr& data)
+{
+ _out << "'" << data->toString() << "'";
+}
+
+void
+FreezeScript::PrintVisitor::visitProxy(const ProxyDataPtr& data)
+{
+ string str = data->toString();
+ _out << typeToString(data->getType()) << '(' << (str.empty() ? "nil" : str) << ')';
+}
+
+void
+FreezeScript::PrintVisitor::visitStruct(const StructDataPtr& data)
+{
+ Slice::StructPtr type = Slice::StructPtr::dynamicCast(data->getType());
+ assert(type);
+ _out << "struct " << typeToString(type);
+ _out << sb;
+ //
+ // Print members in order of declaration.
+ //
+ Slice::DataMemberList l = type->dataMembers();
+ DataMemberMap members = data->getMembers();
+ for(Slice::DataMemberList::const_iterator p = l.begin(); p != l.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = members.find((*p)->name());
+ assert(q != members.end());
+ _out << nl;
+ _out << q->first << " = ";
+ q->second->visit(*this);
+ }
+ _out << eb;
+}
+
+void
+FreezeScript::PrintVisitor::visitSequence(const SequenceDataPtr& data)
+{
+ DataList& elements = data->getElements();
+ _out << "sequence " << typeToString(data->getType()) << " (size = " << elements.size() << ")";
+ _out << sb;
+ Ice::Int i = 0;
+ for(DataList::const_iterator p = elements.begin(); p != elements.end(); ++p, ++i)
+ {
+ _out << nl << "[" << i << "] = ";
+ (*p)->visit(*this);
+ }
+ _out << eb;
+}
+
+void
+FreezeScript::PrintVisitor::visitEnum(const EnumDataPtr& data)
+{
+ _out << typeToString(data->getType()) << "(" << data->toString() << ")";
+}
+
+void
+FreezeScript::PrintVisitor::visitDictionary(const DictionaryDataPtr& data)
+{
+ DataMap& map = data->getElements();
+ _out << "dictionary " << typeToString(data->getType()) << " (size = " << map.size() << ")";
+ _out << sb;
+ for(DataMap::const_iterator p = map.begin(); p != map.end(); ++p)
+ {
+ _out << nl;
+ p->first->visit(*this);
+ _out << " => ";
+ p->second->visit(*this);
+ }
+ _out << eb;
+}
+
+void
+FreezeScript::PrintVisitor::visitObject(const ObjectRefPtr& data)
+{
+ ObjectDataPtr value = data->getValue();
+ if(!value)
+ {
+ _out << typeToString(data->getType()) << "(nil)";
+ }
+ else
+ {
+ Slice::TypePtr type = value->getType();
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(type); // May be nil for Ice::Object
+
+ _out << "class " << typeToString(type);
+ ObjectHistoryMap::iterator p = _objectHistory.find(value.get());
+ if(p != _objectHistory.end())
+ {
+ ostringstream ostr;
+ ostr << " (object #" << p->second << ")";
+ _out << ostr.str();
+ }
+ else
+ {
+ _objectHistory.insert(ObjectHistoryMap::value_type(value.get(), _objectCount));
+ ostringstream ostr;
+ ostr << " (object #" << _objectCount << ")";
+ _out << ostr.str();
+ _objectCount++;
+ _out << sb;
+
+ //
+ // Print Ice::Object members.
+ //
+ DataMemberMap members = value->getMembers();
+ DataMemberMap::const_iterator q = members.find("ice_facets");
+ assert(q != members.end());
+ _out << nl << q->first << " = ";
+ q->second->visit(*this);
+
+ if(decl)
+ {
+ Slice::ClassDefPtr def = decl->definition();
+ assert(def);
+ printObjectMembers(def, members);
+ }
+
+ _out << eb;
+ }
+ }
+}
+
+void
+FreezeScript::PrintVisitor::printObjectMembers(const Slice::ClassDefPtr& type, const DataMemberMap& members)
+{
+ Slice::ClassList bases = type->bases();
+ if(!bases.empty() && !bases.front()->isAbstract())
+ {
+ printObjectMembers(bases.front(), members);
+ }
+
+ //
+ // Print members in order of declaration.
+ //
+ Slice::DataMemberList l = type->dataMembers();
+ for(Slice::DataMemberList::const_iterator p = l.begin(); p != l.end(); ++p)
+ {
+ DataMemberMap::const_iterator q = members.find((*p)->name());
+ assert(q != members.end());
+ _out << nl;
+ _out << q->first << " = ";
+ q->second->visit(*this);
+ }
+}
diff --git a/cpp/src/FreezeScript/Print.h b/cpp/src/FreezeScript/Print.h
new file mode 100644
index 00000000000..b4ece9e8fe3
--- /dev/null
+++ b/cpp/src/FreezeScript/Print.h
@@ -0,0 +1,27 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_PRINT_H
+#define FREEZE_SCRIPT_PRINT_H
+
+#include <FreezeScript/Data.h>
+
+namespace FreezeScript
+{
+
+void printData(const DataPtr&, std::ostream&);
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Scanner.l b/cpp/src/FreezeScript/Scanner.l
new file mode 100644
index 00000000000..75643e79423
--- /dev/null
+++ b/cpp/src/FreezeScript/Scanner.l
@@ -0,0 +1,376 @@
+%{
+
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/GrammarUtil.h> // Before Grammar.h, so that YYSTYPE is defined
+#include <FreezeScript/Grammar.h>
+#include <IceUtil/InputUtil.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+#include <map>
+
+#ifdef _WIN32
+ // I get these warnings from some flex versions:
+ // warning C4003: not enough actual parameters for macro 'yywrap'
+# pragma warning( disable : 4003 )
+#endif
+
+using namespace std;
+using namespace FreezeScript;
+
+namespace FreezeScript
+{
+
+typedef map<string, int> KeywordMap;
+static KeywordMap keywordMap;
+
+void initScanner();
+int checkKeyword(const string&);
+StringTokPtr parseString(char);
+
+}
+
+#define YY_USER_INIT initScanner();
+
+#define YY_INPUT(buf, result, max_size) { result = getInput(buf, max_size); }
+%}
+
+%option noyywrap
+%option never-interactive
+%option prefix="freeze_script_"
+%option outfile="lex.yy.c"
+
+identifier [[:alpha:]_][[:alnum:]_]*
+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]?
+
+%%
+
+"//" {
+ // C++-style comment
+ int c;
+ do
+ {
+ c = yyinput();
+ if(c == '\n')
+ {
+ parseLine++;
+ }
+ }
+ while(c != '\n' && c != EOF);
+}
+
+"/*" {
+ // C-style comment
+ while(true)
+ {
+ int c = yyinput();
+ if(c == '\n')
+ {
+ parseLine++;
+ }
+ else if(c == '*')
+ {
+ int next = yyinput();
+ if(next == '/')
+ {
+ break;
+ }
+ else
+ {
+ unput(next);
+ }
+ }
+ else if(c == EOF)
+ {
+ parseErrorReporter->expressionSyntaxError("EOF in comment");
+ break;
+ }
+ }
+}
+
+{identifier} {
+ StringTokPtr ident = new StringTok;
+ ident->v = yytext;
+ *yylvalp = ident;
+ return checkKeyword(ident->v);
+}
+
+\" {
+ StringTokPtr str = parseString('"');
+ *yylvalp = str;
+ return TOK_STRING_LITERAL;
+}
+
+\' {
+ StringTokPtr str = parseString('\'');
+ *yylvalp = str;
+ return TOK_STRING_LITERAL;
+}
+
+{integer_constant} {
+ IntegerTokPtr itp = new IntegerTok;
+ *yylvalp = itp;
+ errno = 0;
+ itp->v = IceUtil::strToInt64(yytext, 0, 0);
+ if(errno == ERANGE && (itp->v == IceUtil::Int64Min || itp->v == IceUtil::Int64Max))
+ {
+ string msg = "integer constant `";
+ msg += yytext;
+ msg += "' out of range";
+ parseErrorReporter->expressionSyntaxError(msg);
+ }
+ return TOK_INTEGER_LITERAL;
+}
+
+{floating_literal} {
+ errno = 0;
+ FloatingTokPtr ftp = new FloatingTok;
+ *yylvalp = ftp;
+ string literal(yytext);
+ char lastChar = literal[literal.size() - 1];
+ if(lastChar == 'f' || lastChar == 'F')
+ {
+ literal = literal.substr(0, literal.size() - 1); // Clobber trailing 'f' or 'F' suffix
+ }
+ ftp->v = strtod(literal.c_str(), 0);
+ if((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE)
+ {
+ string msg = "floating-point constant `";
+ msg += yytext;
+ msg += "' too large (overflow)";
+ parseErrorReporter->expressionSyntaxError(msg);
+ }
+ else if(ftp->v == 0 && errno == ERANGE)
+ {
+ string msg = "floating-point constant `";
+ msg += yytext;
+ msg += "' too small (underflow)";
+ parseErrorReporter->expressionSyntaxError(msg);
+ }
+ return TOK_FLOATING_POINT_LITERAL;
+}
+
+[[:space:]] {
+ // Igore white-space
+
+ if(yytext[0] == '\n')
+ {
+ parseLine++;
+ }
+}
+
+"<" return TOK_LESS_THAN;
+">" return TOK_GREATER_THAN;
+"<=" return TOK_LESS_EQUAL;
+">=" return TOK_GREATER_EQUAL;
+"==" return TOK_EQUAL;
+"!=" return TOK_NEQ;
+"+" return TOK_ADD;
+"-" return TOK_SUB;
+"*" return TOK_MUL;
+"/" return TOK_DIV;
+"%" return TOK_MOD;
+"(" return TOK_LPAREN;
+")" return TOK_RPAREN;
+"[" return TOK_LBRACKET;
+"]" return TOK_RBRACKET;
+"::" return TOK_SCOPE_DELIMITER;
+
+. {
+ return yytext[0];
+}
+
+%%
+
+namespace FreezeScript
+{
+
+void
+initScanner()
+{
+ keywordMap["true"] = TOK_TRUE;
+ keywordMap["false"] = TOK_FALSE;
+ keywordMap["and"] = TOK_AND;
+ keywordMap["or"] = TOK_OR;
+ keywordMap["not"] = TOK_NOT;
+ keywordMap["nil"] = TOK_NIL;
+}
+
+int
+checkKeyword(const string& id)
+{
+ KeywordMap::const_iterator pos = keywordMap.find(id);
+ if(pos != keywordMap.end())
+ {
+ return pos->second;
+ }
+ return TOK_IDENTIFIER;
+}
+
+StringTokPtr
+parseString(char start)
+{
+ StringTokPtr str = new StringTok;
+ while(true)
+ {
+ char c = static_cast<char>(yyinput());
+ if(c == start)
+ {
+ break;
+ }
+ else if(c == EOF)
+ {
+ parseErrorReporter->expressionSyntaxError("EOF in string");
+ break;
+ }
+ else if(c == '\n')
+ {
+ parseErrorReporter->expressionSyntaxError("newline in string");
+ }
+ else if(c == '\\')
+ {
+ char next = static_cast<char>(yyinput());
+ switch(next)
+ {
+ case '\\':
+ case '"':
+ case '\'':
+ {
+ str->v += next;
+ break;
+ }
+
+ case 'n':
+ {
+ str->v += '\n';
+ break;
+ }
+
+ case 'r':
+ {
+ str->v += '\r';
+ break;
+ }
+
+ case 't':
+ {
+ str->v += '\t';
+ break;
+ }
+
+ case 'v':
+ {
+ str->v += '\v';
+ break;
+ }
+
+ case 'f':
+ {
+ str->v += '\f';
+ break;
+ }
+
+ case 'a':
+ {
+ str->v += '\a';
+ break;
+ }
+
+ case 'b':
+ {
+ str->v += '\b';
+ break;
+ }
+
+ case '?':
+ {
+ str->v += '\?';
+ break;
+ }
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ {
+ static string octalDigits = "01234567";
+ unsigned short us = next - '0';
+ if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos)
+ {
+ us = us * 8 + next - '0';
+ if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos)
+ {
+ us = us * 8 + next - '0';
+ }
+ else
+ {
+ unput(next);
+ }
+ }
+ else
+ {
+ unput(next);
+ }
+ str->v += static_cast<char>(us);
+ break;
+ }
+ case 'x':
+ {
+ IceUtil::Int64 ull = 0;
+ while(isxdigit(next = static_cast<char>(yyinput())))
+ {
+ ull *= 16;
+ if(isdigit(next))
+ {
+ ull += next - '0';
+ }
+ else if(islower(next))
+ {
+ ull += next - 'a' + 10;
+ }
+ else
+ {
+ ull += next - 'A' + 10;
+ }
+ }
+ unput(next);
+ str->v += static_cast<char>(ull);
+ break;
+ }
+
+ // TODO: add universal character names
+
+ default:
+ {
+ str->v += c;
+ unput(next);
+ }
+ }
+ }
+ else
+ {
+ str->v += c;
+ }
+ }
+
+ return str;
+}
+
+} // End of namespace FreezeScript
diff --git a/cpp/src/FreezeScript/TransformAnalyzer.cpp b/cpp/src/FreezeScript/TransformAnalyzer.cpp
new file mode 100644
index 00000000000..5d056381d16
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformAnalyzer.cpp
@@ -0,0 +1,1143 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/TransformAnalyzer.h>
+#include <FreezeScript/Util.h>
+#include <IceUtil/OutputUtil.h>
+#include <map>
+
+using namespace std;
+using namespace Slice;
+using namespace IceUtil;
+
+namespace FreezeScript
+{
+
+//
+// TransformVisitor visits the old definitions and compares them with
+// the new definitions.
+//
+class AnalyzeTransformVisitor : public ParserVisitor
+{
+public:
+
+ AnalyzeTransformVisitor(XMLOutput&, const UnitPtr&, const TypePtr&, const TypePtr&, const TypePtr&, const TypePtr&,
+ bool, vector<string>&, vector<string>&);
+
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual void visitSequence(const SequencePtr&);
+ virtual void visitDictionary(const DictionaryPtr&);
+ virtual void visitEnum(const EnumPtr&);
+
+private:
+
+ void compareMembers(const DataMemberList&, const DataMemberList&);
+ void compareTypes(const string&, const TypePtr&, const TypePtr&);
+ void typeChange(const string&, const TypePtr&, const TypePtr&);
+ bool checkClasses(const ClassDeclPtr&, const ClassDeclPtr&);
+
+ XMLOutput& _out;
+ UnitPtr _newUnit;
+ bool _ignoreTypeChanges;
+ vector<string>& _missingTypes;
+ vector<string>& _errors;
+};
+
+//
+// InitVisitor visits the new definitions to find any that are not present
+// in the old definitions, and generates init elements for them.
+//
+class AnalyzeInitVisitor : public ParserVisitor
+{
+public:
+
+ AnalyzeInitVisitor(XMLOutput&, const UnitPtr&);
+
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual void visitSequence(const SequencePtr&);
+ virtual void visitDictionary(const DictionaryPtr&);
+ virtual void visitEnum(const EnumPtr&);
+
+private:
+
+ void typeChange(const TypePtr&, const string&, const string&);
+
+ XMLOutput& _out;
+ UnitPtr _oldUnit;
+};
+
+}
+
+////////////////////////////////////
+// TransformVisitor
+////////////////////////////////////
+
+FreezeScript::AnalyzeTransformVisitor::AnalyzeTransformVisitor(XMLOutput& out, const UnitPtr& newUnit,
+ const TypePtr& oldKey, const TypePtr& newKey,
+ const TypePtr& oldValue, const TypePtr& newValue,
+ bool ignoreTypeChanges, vector<string>& missingTypes,
+ vector<string>& errors) :
+ _out(out), _newUnit(newUnit), _ignoreTypeChanges(ignoreTypeChanges), _missingTypes(missingTypes), _errors(errors)
+{
+ out << se("database");
+
+ string oldKeyName = typeToString(oldKey);
+ string newKeyName = typeToString(newKey);
+ if(oldKeyName == newKeyName)
+ {
+ out << attr("key", oldKeyName);
+ }
+ else
+ {
+ out << attr("key", oldKeyName + "," + newKeyName);
+ }
+
+ string oldValueName = typeToString(oldValue);
+ string newValueName = typeToString(newValue);
+ if(oldValueName == newValueName)
+ {
+ out << attr("value", oldValueName);
+ }
+ else
+ {
+ out << attr("value", oldValueName + "," + newValueName);
+ }
+
+ out << se("record");
+ compareTypes("database key", oldKey, newKey);
+ compareTypes("database value", oldValue, newValue);
+ out << ee;
+
+ out << ee;
+}
+
+bool
+FreezeScript::AnalyzeTransformVisitor::visitClassDefStart(const ClassDefPtr& v)
+{
+ if(v->isInterface() || v->isLocal())
+ {
+ return false;
+ }
+
+ string scoped = v->scoped();
+ if(ignoreType(scoped))
+ {
+ return false;
+ }
+
+ TypeList l = _newUnit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ _missingTypes.push_back(scoped);
+ return false;
+ }
+
+ ClassDeclPtr decl = ClassDeclPtr::dynamicCast(l.front());
+ if(!decl || decl->isInterface())
+ {
+ if(!_ignoreTypeChanges)
+ {
+ typeChange(scoped, v->declaration(), l.front());
+ }
+ return false;
+ }
+
+ ClassDefPtr newClass = decl->definition();
+ if(!newClass)
+ {
+ _missingTypes.push_back(scoped);
+ return false;
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- class " << scoped << " -->";
+ _out << se("transform") << attr("type", scoped);
+
+ DataMemberList oldMembers = v->dataMembers();
+ DataMemberList newMembers = newClass->dataMembers();
+ compareMembers(oldMembers, newMembers);
+
+ _out << ee;
+
+ return false;
+}
+
+bool
+FreezeScript::AnalyzeTransformVisitor::visitStructStart(const StructPtr& v)
+{
+ if(v->isLocal())
+ {
+ return false;
+ }
+
+ string scoped = v->scoped();
+ if(ignoreType(scoped))
+ {
+ return false;
+ }
+
+ TypeList l = _newUnit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ _missingTypes.push_back(scoped);
+ return false;
+ }
+
+ StructPtr newStruct = StructPtr::dynamicCast(l.front());
+ if(!newStruct)
+ {
+ if(!_ignoreTypeChanges)
+ {
+ typeChange(scoped, v, l.front());
+ }
+ return false;
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- struct " << scoped << " -->";
+ _out << se("transform") << attr("type", scoped);
+
+ DataMemberList oldMembers = v->dataMembers();
+ DataMemberList newMembers = newStruct->dataMembers();
+ compareMembers(oldMembers, newMembers);
+
+ _out << ee;
+
+ return false;
+}
+
+void
+FreezeScript::AnalyzeTransformVisitor::visitSequence(const SequencePtr& v)
+{
+ if(v->isLocal())
+ {
+ return;
+ }
+
+ string scoped = v->scoped();
+ if(ignoreType(scoped))
+ {
+ return;
+ }
+
+ TypeList l = _newUnit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ _missingTypes.push_back(scoped);
+ return;
+ }
+
+ SequencePtr newSeq = SequencePtr::dynamicCast(l.front());
+ if(!newSeq)
+ {
+ if(!_ignoreTypeChanges)
+ {
+ typeChange(scoped, v, l.front());
+ }
+ return;
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- sequence " << scoped << " -->";
+ _out << se("transform") << attr("type", scoped);
+
+ compareTypes(scoped + " sequence type", v->type(), newSeq->type());
+
+ _out << ee;
+}
+
+void
+FreezeScript::AnalyzeTransformVisitor::visitDictionary(const DictionaryPtr& v)
+{
+ if(v->isLocal())
+ {
+ return;
+ }
+
+ string scoped = v->scoped();
+ if(ignoreType(scoped))
+ {
+ return;
+ }
+
+ TypeList l = _newUnit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ _missingTypes.push_back(scoped);
+ return;
+ }
+
+ DictionaryPtr newDict = DictionaryPtr::dynamicCast(l.front());
+ if(!newDict)
+ {
+ if(!_ignoreTypeChanges)
+ {
+ typeChange(scoped, v, l.front());
+ }
+ return;
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- dictionary " << scoped << " -->";
+ _out << se("transform") << attr("type", scoped);
+
+ compareTypes(scoped + " key type", v->keyType(), newDict->keyType());
+ compareTypes(scoped + " value type", v->valueType(), newDict->valueType());
+
+ _out << ee;
+}
+
+void
+FreezeScript::AnalyzeTransformVisitor::visitEnum(const EnumPtr& v)
+{
+ if(v->isLocal())
+ {
+ return;
+ }
+
+ string scoped = v->scoped();
+ if(ignoreType(scoped))
+ {
+ return;
+ }
+
+ TypeList l = _newUnit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ _missingTypes.push_back(scoped);
+ return;
+ }
+
+ EnumPtr newEnum = EnumPtr::dynamicCast(l.front());
+ if(!newEnum)
+ {
+ if(!_ignoreTypeChanges)
+ {
+ typeChange(scoped, v, l.front());
+ }
+ return;
+ }
+
+ map<string, int> m;
+ {
+ Slice::EnumeratorList enumerators = newEnum->getEnumerators();
+ int i = 0;
+ for(Slice::EnumeratorList::iterator p = enumerators.begin(); p != enumerators.end(); ++p, ++i)
+ {
+ m.insert(map<string, int>::value_type((*p)->name(), i));
+ }
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- enum " << scoped << " -->";
+ _out << se("transform") << attr("type", scoped);
+
+ Slice::EnumeratorList enumerators = v->getEnumerators();
+ int i = 0;
+ for(Slice::EnumeratorList::iterator p = enumerators.begin(); p != enumerators.end(); ++p, ++i)
+ {
+ map<string, int>::const_iterator q = m.find((*p)->name());
+ if(q == m.end())
+ {
+ _out.nl();
+ _out << "<!-- NOTICE: enumerator `" << (*p)->name() << "' has been removed -->";
+ }
+ else if(q->second != i)
+ {
+ _out.nl();
+ _out << "<!-- NOTICE: enumerator `" << (*p)->name() << "' has changed position -->";
+ }
+ }
+
+ _out << ee;
+}
+
+void
+FreezeScript::AnalyzeTransformVisitor::compareMembers(const DataMemberList& oldMembers,
+ const DataMemberList& newMembers)
+{
+ map<string, DataMemberPtr> oldMap, newMap;
+ map<string, DataMemberPtr>::iterator q;
+ DataMemberList::const_iterator p;
+
+ for(p = oldMembers.begin(); p != oldMembers.end(); ++p)
+ {
+ oldMap.insert(pair<string, DataMemberPtr>((*p)->name(), *p));
+ }
+
+ for(p = newMembers.begin(); p != newMembers.end(); ++p)
+ {
+ newMap.insert(pair<string, DataMemberPtr>((*p)->name(), *p));
+ }
+
+ for(p = oldMembers.begin(); p != oldMembers.end(); ++p)
+ {
+ string name = (*p)->name();
+ q = newMap.find(name);
+ if(q == newMap.end())
+ {
+ _out.nl();
+ _out << "<!-- NOTICE: " << name << " has been removed -->";
+ }
+ else
+ {
+ TypePtr oldType = (*p)->type();
+ TypePtr newType = q->second->type();
+ compareTypes(name, oldType, newType);
+
+ //
+ // Remove this entry from the map to indicate that we've
+ // already seen it.
+ //
+ newMap.erase(q);
+ }
+ }
+
+ //
+ // Iterate over the remaining entries in newMap. These represent
+ // members that were added in the new definition.
+ //
+ for(q = newMap.begin(); q != newMap.end(); ++q)
+ {
+ _out.nl();
+ _out << "<!-- NOTICE: " << q->first << " has been added -->";
+ }
+}
+
+void
+FreezeScript::AnalyzeTransformVisitor::compareTypes(const string& desc, const TypePtr& oldType, const TypePtr& newType)
+{
+ assert(!oldType->isLocal());
+ if(newType->isLocal())
+ {
+ ostringstream ostr;
+ ostr << desc << " has changed to a local type";
+ _errors.push_back(ostr.str());
+ return;
+ }
+
+ BuiltinPtr b = BuiltinPtr::dynamicCast(oldType);
+ if(b)
+ {
+ BuiltinPtr newb = BuiltinPtr::dynamicCast(newType);
+ switch(b->kind())
+ {
+ case Builtin::KindByte:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindString:
+ {
+ return;
+ }
+ case Builtin::KindBool:
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case Builtin::KindBool:
+ {
+ if(newb && (newb->kind() == Builtin::KindBool || newb->kind() == Builtin::KindString))
+ {
+ return;
+ }
+
+ break;
+ }
+ case Builtin::KindShort:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindString:
+ {
+ return;
+ }
+ case Builtin::KindBool:
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case Builtin::KindInt:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindString:
+ {
+ return;
+ }
+ case Builtin::KindBool:
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case Builtin::KindLong:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindString:
+ {
+ return;
+ }
+ case Builtin::KindBool:
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case Builtin::KindFloat:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindString:
+ {
+ return;
+ }
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindBool:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case Builtin::KindDouble:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindString:
+ {
+ return;
+ }
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindBool:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case Builtin::KindString:
+ {
+ if(newb)
+ {
+ switch(newb->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindBool:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindString:
+ case Builtin::KindObjectProxy:
+ {
+ return;
+ }
+ case Builtin::KindObject:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+
+ break;
+ }
+
+ if(EnumPtr::dynamicCast(newType))
+ {
+ return;
+ }
+
+ if(ProxyPtr::dynamicCast(newType))
+ {
+ return;
+ }
+
+ break;
+ }
+ case Builtin::KindObject:
+ {
+ //
+ // Allow change from Object to class. Validation has to
+ // be done during transformation, when the actual type of
+ // an instance can be compared for compatibility with the
+ // new type.
+ //
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(newType);
+ if(cl || (newb && newb->kind() == Builtin::KindObject))
+ {
+ return;
+ }
+
+ break;
+ }
+ case Builtin::KindObjectProxy:
+ {
+ ProxyPtr p = ProxyPtr::dynamicCast(newType);
+ if(p || (newb && newb->kind() == Builtin::KindObjectProxy) || (newb && newb->kind() == Builtin::KindString))
+ {
+ return;
+ }
+
+ break;
+ }
+ case Builtin::KindLocalObject:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(oldType);
+ if(cl)
+ {
+ if(!cl->definition())
+ {
+ _errors.push_back("class " + cl->scoped() + " declared but not defined");
+ return;
+ }
+
+ //
+ // Allow target type of Object.
+ //
+ BuiltinPtr newb = BuiltinPtr::dynamicCast(newType);
+ if(newb && newb->kind() == Builtin::KindObject)
+ {
+ return;
+ }
+
+ ClassDeclPtr newcl = ClassDeclPtr::dynamicCast(newType);
+ if(newcl)
+ {
+ if(!newcl->definition())
+ {
+ _errors.push_back("class " + newcl->scoped() + " declared but not defined");
+ return;
+ }
+
+ if(checkClasses(cl, newcl))
+ {
+ return;
+ }
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ StructPtr s = StructPtr::dynamicCast(oldType);
+ if(s)
+ {
+ StructPtr news = StructPtr::dynamicCast(newType);
+ if(news && s->scoped() == news->scoped())
+ {
+ return;
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(oldType);
+ if(proxy)
+ {
+ //
+ // Allow target type of Object* and string.
+ //
+ BuiltinPtr newb = BuiltinPtr::dynamicCast(newType);
+ if(newb && (newb->kind() == Builtin::KindObjectProxy || newb->kind() == Builtin::KindString))
+ {
+ return;
+ }
+
+ ProxyPtr newProxy = ProxyPtr::dynamicCast(newType);
+ if(newProxy && checkClasses(proxy->_class(), newProxy->_class()))
+ {
+ return;
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ DictionaryPtr dict = DictionaryPtr::dynamicCast(oldType);
+ if(dict)
+ {
+ DictionaryPtr newDict = DictionaryPtr::dynamicCast(newType);
+ if(newDict && dict->scoped() == newDict->scoped())
+ {
+ return;
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(oldType);
+ if(seq)
+ {
+ SequencePtr newSeq = SequencePtr::dynamicCast(newType);
+ if(newSeq && seq->scoped() == newSeq->scoped())
+ {
+ return;
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(oldType);
+ if(en)
+ {
+ EnumPtr newen = EnumPtr::dynamicCast(newType);
+ BuiltinPtr newb = BuiltinPtr::dynamicCast(newType);
+ if((newen && en->scoped() == newen->scoped()) || (newb && newb->kind() == Builtin::KindString))
+ {
+ return;
+ }
+
+ typeChange(desc, oldType, newType);
+ return;
+ }
+
+ assert(false);
+}
+
+void
+FreezeScript::AnalyzeTransformVisitor::typeChange(const string& desc, const TypePtr& t1, const TypePtr& t2)
+{
+ BuiltinPtr b1 = BuiltinPtr::dynamicCast(t1);
+ BuiltinPtr b2 = BuiltinPtr::dynamicCast(t2);
+ ContainedPtr c1 = ContainedPtr::dynamicCast(t1);
+ ContainedPtr c2 = ContainedPtr::dynamicCast(t2);
+ ProxyPtr p1 = ProxyPtr::dynamicCast(t1);
+ ProxyPtr p2 = ProxyPtr::dynamicCast(t2);
+
+ if(_ignoreTypeChanges)
+ {
+ _out.nl();
+ _out << "<!-- NOTICE: " << desc << " has changed from ";
+ if(b1)
+ {
+ _out << b1->kindAsString();
+ }
+ else if(p1)
+ {
+ _out << p1->_class()->scoped() << '*';
+ }
+ else
+ {
+ assert(c1);
+ _out << c1->kindOf() << ' ' << c1->scoped();
+ }
+ _out << " to ";
+ if(b2)
+ {
+ _out << b2->kindAsString();
+ }
+ else if(p2)
+ {
+ _out << p2->_class()->scoped() << '*';
+ }
+ else
+ {
+ assert(c2);
+ _out << c2->kindOf() << ' ' << c2->scoped();
+ }
+ _out << " -->";
+ }
+ else
+ {
+ ostringstream ostr;
+ ostr << "unsupported type change in " << desc << " from ";
+ if(b1)
+ {
+ ostr << b1->kindAsString();
+ }
+ else if(p1)
+ {
+ ostr << p1->_class()->scoped() << '*';
+ }
+ else
+ {
+ assert(c1);
+ ostr << c1->kindOf() << ' ' << c1->scoped();
+ }
+ ostr << " to ";
+ if(b2)
+ {
+ ostr << b2->kindAsString();
+ }
+ else if(p2)
+ {
+ ostr << p2->_class()->scoped() << '*';
+ }
+ else
+ {
+ assert(c2);
+ ostr << c2->kindOf() << ' ' << c2->scoped();
+ }
+ _errors.push_back(ostr.str());
+ }
+}
+
+bool
+FreezeScript::AnalyzeTransformVisitor::checkClasses(const ClassDeclPtr& from, const ClassDeclPtr& to)
+{
+ string fromScoped = from->scoped();
+ string toScoped = to->scoped();
+
+ if(fromScoped == toScoped)
+ {
+ return true;
+ }
+
+ //
+ // The types don't match, so check them for compatibility. Specifically,
+ // look up the old type id in the new Slice and see if it has the target
+ // type as a base class.
+ //
+ TypeList l = to->unit()->lookupTypeNoBuiltin(from->scoped(), false);
+ if(!l.empty())
+ {
+ ClassDeclPtr decl = ClassDeclPtr::dynamicCast(l.front());
+ if(decl)
+ {
+ ClassDefPtr def = decl->definition();
+ if(def)
+ {
+ ClassList bases = def->allBases();
+ for(ClassList::iterator p = bases.begin(); p != bases.end(); ++p)
+ {
+ if((*p)->scoped() == toScoped)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+////////////////////////////////////
+// InitVisitor
+////////////////////////////////////
+
+FreezeScript::AnalyzeInitVisitor::AnalyzeInitVisitor(XMLOutput& out, const UnitPtr& oldUnit) :
+ _out(out), _oldUnit(oldUnit)
+{
+}
+
+bool
+FreezeScript::AnalyzeInitVisitor::visitClassDefStart(const ClassDefPtr& v)
+{
+ if(v->isInterface() || v->isLocal())
+ {
+ return false;
+ }
+
+ string scoped = v->scoped();
+ TypeList l = _oldUnit->lookupTypeNoBuiltin(scoped, false);
+ if(!l.empty())
+ {
+ ClassDeclPtr decl = ClassDeclPtr::dynamicCast(l.front());
+ if(!decl || decl->isInterface())
+ {
+ typeChange(l.front(), scoped, "class");
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- class " << scoped << " -->";
+ _out << se("init") << attr("type", scoped);
+ _out << ee;
+
+ return false;
+}
+
+bool
+FreezeScript::AnalyzeInitVisitor::visitStructStart(const StructPtr& v)
+{
+ if(v->isLocal())
+ {
+ return false;
+ }
+
+ string scoped = v->scoped();
+ TypeList l = _oldUnit->lookupTypeNoBuiltin(scoped, false);
+ if(!l.empty())
+ {
+ StructPtr s = StructPtr::dynamicCast(l.front());
+ if(!s)
+ {
+ typeChange(l.front(), scoped, "struct");
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- struct " << scoped << " -->";
+ _out << se("init") << attr("type", scoped);
+ _out << ee;
+
+ return false;
+}
+
+void
+FreezeScript::AnalyzeInitVisitor::visitSequence(const SequencePtr& v)
+{
+ if(v->isLocal())
+ {
+ return;
+ }
+
+ string scoped = v->scoped();
+ TypeList l = _oldUnit->lookupTypeNoBuiltin(scoped, false);
+ if(!l.empty())
+ {
+ SequencePtr s = SequencePtr::dynamicCast(l.front());
+ if(!s)
+ {
+ typeChange(l.front(), scoped, "sequence");
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- sequence " << scoped << " -->";
+ _out << se("init") << attr("type", scoped);
+ _out << ee;
+}
+
+void
+FreezeScript::AnalyzeInitVisitor::visitDictionary(const DictionaryPtr& v)
+{
+ if(v->isLocal())
+ {
+ return;
+ }
+
+ string scoped = v->scoped();
+ TypeList l = _oldUnit->lookupTypeNoBuiltin(scoped, false);
+ if(!l.empty())
+ {
+ DictionaryPtr d = DictionaryPtr::dynamicCast(l.front());
+ if(!d)
+ {
+ typeChange(l.front(), scoped, "dictionary");
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- dictionary " << scoped << " -->";
+ _out << se("init") << attr("type", scoped);
+ _out << ee;
+}
+
+void
+FreezeScript::AnalyzeInitVisitor::visitEnum(const EnumPtr& v)
+{
+ if(v->isLocal())
+ {
+ return;
+ }
+
+ string scoped = v->scoped();
+ TypeList l = _oldUnit->lookupTypeNoBuiltin(scoped, false);
+ if(!l.empty())
+ {
+ EnumPtr e = EnumPtr::dynamicCast(l.front());
+ if(!e)
+ {
+ typeChange(l.front(), scoped, "enum");
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ _out.nl();
+ _out.nl();
+ _out << "<!-- enum " << scoped << " -->";
+ _out << se("init") << attr("type", scoped);
+ _out << ee;
+}
+
+
+void
+FreezeScript::AnalyzeInitVisitor::typeChange(const TypePtr& t, const string& scoped, const string& kind)
+{
+ BuiltinPtr b = BuiltinPtr::dynamicCast(t);
+ ContainedPtr c = ContainedPtr::dynamicCast(t);
+ ProxyPtr p = ProxyPtr::dynamicCast(t);
+
+ _out.nl();
+ _out << "<!-- NOTICE: " << scoped << " has changed from ";
+ if(b)
+ {
+ _out << b->kindAsString();
+ }
+ else if(p)
+ {
+ _out << "proxy";
+ }
+ else
+ {
+ assert(c);
+ _out << c->kindOf();
+ }
+ _out << " to " << kind << " -->";
+}
+
+FreezeScript::TransformAnalyzer::TransformAnalyzer(const UnitPtr& oldUnit, const UnitPtr& newUnit,
+ bool ignoreTypeChanges) :
+ _old(oldUnit), _new(newUnit), _ignoreTypeChanges(ignoreTypeChanges)
+{
+}
+
+void
+FreezeScript::TransformAnalyzer::analyze(const TypePtr& oldKey, const TypePtr& newKey, const TypePtr& oldValue,
+ const TypePtr& newValue, ostream& os, vector<string>& missingTypes,
+ vector<string>& errors)
+{
+ XMLOutput out(os);
+
+ out << se("transformdb");
+
+ AnalyzeTransformVisitor transformVisitor(out, _new, oldKey, newKey, oldValue, newValue, _ignoreTypeChanges,
+ missingTypes, errors);
+ _old->visit(&transformVisitor);
+
+ AnalyzeInitVisitor initVisitor(out, _old);
+ _new->visit(&initVisitor);
+
+ out << ee;
+ out << '\n';
+}
diff --git a/cpp/src/FreezeScript/TransformAnalyzer.h b/cpp/src/FreezeScript/TransformAnalyzer.h
new file mode 100644
index 00000000000..6415f0a26ab
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformAnalyzer.h
@@ -0,0 +1,41 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_TRANSFORM_ANALYZER_H
+#define FREEZE_SCRIPT_TRANSFORM_ANALYZER_H
+
+#include <Slice/Parser.h>
+#include <ostream>
+
+namespace FreezeScript
+{
+
+class TransformAnalyzer
+{
+public:
+
+ TransformAnalyzer(const Slice::UnitPtr&, const Slice::UnitPtr&, bool);
+ void analyze(const Slice::TypePtr&, const Slice::TypePtr&, const Slice::TypePtr&, const Slice::TypePtr&,
+ std::ostream&, std::vector<std::string>&, std::vector<std::string>&);
+
+private:
+
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ bool _ignoreTypeChanges;
+};
+
+}
+
+#endif
diff --git a/cpp/src/FreezeScript/TransformDescriptors.cpp b/cpp/src/FreezeScript/TransformDescriptors.cpp
new file mode 100644
index 00000000000..8416887975a
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformDescriptors.cpp
@@ -0,0 +1,2283 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/TransformDescriptors.h>
+#include <FreezeScript/AssignVisitor.h>
+#include <FreezeScript/Print.h>
+#include <FreezeScript/Functions.h>
+#include <FreezeScript/Exception.h>
+#include <FreezeScript/Util.h>
+#include <IceUtil/UUID.h>
+#include <db_cxx.h>
+
+using namespace std;
+
+namespace FreezeScript
+{
+
+class SymbolTableI;
+typedef IceUtil::Handle<SymbolTableI> SymbolTableIPtr;
+
+class SymbolTableI : public SymbolTable
+{
+public:
+
+ SymbolTableI(const DataFactoryPtr&, const Slice::UnitPtr&, const Slice::UnitPtr&, const ErrorReporterPtr&,
+ TransformInfo*, const SymbolTablePtr& = SymbolTablePtr());
+
+ virtual void add(const string&, const DataPtr&);
+
+ virtual DataPtr getValue(const EntityNodePtr&) const;
+
+ virtual DataPtr getConstantValue(const string&) const;
+
+ virtual SymbolTablePtr createChild();
+
+ virtual Slice::TypePtr lookupType(const string&);
+
+ virtual DataPtr invokeFunction(const string&, const DataPtr&, const DataList&);
+
+private:
+
+ DataPtr findValue(const string&) const;
+
+ class EntityVisitor : public EntityNodeVisitor
+ {
+ public:
+
+ EntityVisitor(SymbolTableI*);
+
+ virtual void visitIdentifier(const string&);
+ virtual void visitElement(const NodePtr&);
+
+ DataPtr getCurrent() const;
+
+ private:
+
+ SymbolTableI* _table;
+ DataPtr _current;
+ bool _error;
+ };
+
+ friend class EntityVisitor;
+
+ DataFactoryPtr _factory;
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ ErrorReporterPtr _errorReporter;
+ TransformInfo* _info;
+ SymbolTablePtr _parent;
+ typedef map<string, DataPtr> DataMap;
+ DataMap _dataMap;
+ DataMap _constantCache;
+};
+
+class ObjectVisitor : public DataVisitor
+{
+public:
+
+ ObjectVisitor(ObjectDataMap&);
+
+ virtual void visitStruct(const StructDataPtr&);
+ virtual void visitSequence(const SequenceDataPtr&);
+ virtual void visitDictionary(const DictionaryDataPtr&);
+ virtual void visitObject(const ObjectRefPtr&);
+
+private:
+
+ ObjectDataMap& _map;
+};
+
+typedef map<string, TransformDescriptorPtr> TransformMap;
+typedef map<string, Slice::TypePtr> RenameMap;
+
+class TransformInfoI : public TransformInfo
+{
+public:
+
+ TransformInfoI(const DataFactoryPtr&, const ErrorReporterPtr&, const Slice::UnitPtr&, const Slice::UnitPtr&);
+
+ virtual bool doDefaultTransform(const Slice::TypePtr&);
+ virtual bool doBaseTransform(const Slice::ClassDefPtr&);
+ virtual Slice::TypePtr getRenamedType(const Slice::TypePtr&);
+ virtual void executeCustomTransform(const DataPtr&, const DataPtr&);
+ virtual bool purgeObjects();
+ virtual ObjectDataMap& getObjectDataMap();
+
+ DataFactoryPtr factory;
+ ErrorReporterPtr errorReporter;
+ Slice::UnitPtr oldUnit;
+ Slice::UnitPtr newUnit;
+ SymbolTablePtr symbolTable;
+ TransformMap transformMap;
+ RenameMap renameMap;
+ ObjectDataMap objectDataMap;
+ Slice::TypePtr oldKeyType;
+ Slice::TypePtr oldValueType;
+ Slice::TypePtr newKeyType;
+ Slice::TypePtr newValueType;
+ Ice::CommunicatorPtr communicator;
+ bool purge;
+ Db* oldDb;
+ DbTxn* oldDbTxn;
+ Db* newDb;
+ DbTxn* newDbTxn;
+};
+
+void assignOrTransform(const DataPtr&, const DataPtr&, bool, const DataFactoryPtr&, const ErrorReporterPtr&,
+ TransformInfo*);
+
+} // End of namespace FreezeScript
+
+//
+// Descriptor
+//
+FreezeScript::Descriptor::Descriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter) :
+ _parent(parent), _line(line), _factory(factory), _errorReporter(errorReporter)
+{
+}
+
+FreezeScript::Descriptor::~Descriptor()
+{
+}
+
+FreezeScript::DescriptorPtr
+FreezeScript::Descriptor::parent() const
+{
+ return _parent;
+}
+
+FreezeScript::NodePtr
+FreezeScript::Descriptor::parse(const string& expr) const
+{
+ return parseExpression(expr, _factory, _errorReporter);
+}
+
+Slice::TypePtr
+FreezeScript::Descriptor::findType(const Slice::UnitPtr& u, const string& type)
+{
+ Slice::TypeList l;
+
+ l = u->lookupType(type, false);
+ if(l.empty())
+ {
+ _errorReporter->error("unknown type `" + type + "'");
+ }
+
+ return l.front();
+}
+
+//
+// SetDescriptor
+//
+FreezeScript::SetDescriptor::SetDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+ DescriptorErrorContext ctx(_errorReporter, "set", _line);
+
+ IceXML::Attributes::const_iterator p;
+
+ string target;
+ p = attributes.find("target");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `target' is missing");
+ }
+ target = p->second;
+
+ p = attributes.find("value");
+ if(p != attributes.end())
+ {
+ _valueStr = p->second;
+ }
+
+ p = attributes.find("type");
+ if(p != attributes.end())
+ {
+ _type = p->second;
+ }
+
+ p = attributes.find("length");
+ if(p != attributes.end())
+ {
+ _lengthStr = p->second;
+ }
+
+ p = attributes.find("convert");
+ if(p != attributes.end())
+ {
+ _convert = p->second == "true";
+ }
+
+ if(!_valueStr.empty() && !_type.empty())
+ {
+ _errorReporter->error("attributes `value' and 'type' are mutually exclusive");
+ }
+
+ if(_valueStr.empty() && _type.empty() && _lengthStr.empty())
+ {
+ _errorReporter->error("requires a value for attributes `value', 'type' or 'length'");
+ }
+
+ NodePtr node = parse(target);
+ _target = EntityNodePtr::dynamicCast(node);
+ if(!_target)
+ {
+ _errorReporter->error("`target' attribute is not an entity: `" + target + "'");
+ }
+
+ if(!_valueStr.empty())
+ {
+ _value = parse(_valueStr);
+ }
+
+ if(!_lengthStr.empty())
+ {
+ _length = parse(_lengthStr);
+ }
+}
+
+void
+FreezeScript::SetDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "set", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::SetDescriptor::validate()
+{
+}
+
+void
+FreezeScript::SetDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ DescriptorErrorContext ctx(_errorReporter, "set", _line);
+
+ DataPtr data = sym->getValue(_target);
+ if(data->readOnly())
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' cannot be modified");
+ }
+
+ DataPtr value;
+ if(_value)
+ {
+ try
+ {
+ value = _value->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of value `" + _valueStr + "' failed:\n" + ex.reason());
+ }
+ }
+
+ Destroyer<DataPtr> valueDestroyer;
+ if(!_type.empty())
+ {
+ assert(!value);
+ Slice::TypePtr type = sym->lookupType(_type);
+ if(!type)
+ {
+ _errorReporter->error("type `" + _type + "' not found");
+ }
+ value = _factory->createObject(type, false);
+ valueDestroyer.set(value);
+ }
+
+ DataPtr length;
+ if(_length)
+ {
+ SequenceDataPtr seq = SequenceDataPtr::dynamicCast(data);
+ if(!seq)
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' is not a sequence");
+ }
+
+ try
+ {
+ length = _length->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of length `" + _lengthStr + "' failed:\n" + ex.reason());
+ }
+
+ DataList& elements = seq->getElements();
+ Ice::Long l = length->integerValue();
+ if(l < 0 || l > INT_MAX)
+ {
+ _errorReporter->error("sequence length " + length->toString() + " is out of range");
+ }
+
+ DataList::size_type len = static_cast<DataList::size_type>(l);
+ if(len < elements.size())
+ {
+ for(DataList::size_type i = len; i < elements.size(); ++i)
+ {
+ elements[i]->destroy();
+ }
+ elements.resize(len);
+ }
+ else if(len > elements.size())
+ {
+ Slice::SequencePtr seqType = Slice::SequencePtr::dynamicCast(seq->getType());
+ assert(seqType);
+ Slice::TypePtr elemType = seqType->type();
+ for(DataList::size_type i = elements.size(); i < len; ++i)
+ {
+ DataPtr v = _factory->create(elemType, false);
+ if(value)
+ {
+ assignOrTransform(v, value, _convert, _factory, _errorReporter, info);
+ }
+ elements.push_back(v);
+ }
+ }
+ }
+ else
+ {
+ assignOrTransform(data, value, _convert, _factory, _errorReporter, info);
+ }
+}
+
+//
+// DefineDescriptor
+//
+FreezeScript::DefineDescriptor::DefineDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes, const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+ DescriptorErrorContext ctx(_errorReporter, "define", _line);
+
+ IceXML::Attributes::const_iterator p;
+
+ p = attributes.find("name");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `name' is missing");
+ }
+ _name = p->second;
+
+ p = attributes.find("type");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `type' is missing");
+ }
+ if(p->second.find("::New") != string::npos)
+ {
+ Slice::TypeList l = newUnit->lookupType(p->second.substr(5), false);
+ if(l.empty())
+ {
+ _errorReporter->error("type `" + p->second + "' not found");
+ }
+ _type = l.front();
+ }
+ else if(p->second.find("::Old") != string::npos)
+ {
+ Slice::TypeList l = oldUnit->lookupType(p->second.substr(5), false);
+ if(l.empty())
+ {
+ _errorReporter->error("type `" + p->second + "' not found");
+ }
+ _type = l.front();
+ }
+ else
+ {
+ Slice::TypeList l = newUnit->lookupType(p->second, false);
+ if(l.empty())
+ {
+ _errorReporter->error("type `" + p->second + "' not found");
+ }
+ _type = l.front();
+ }
+
+ p = attributes.find("value");
+ if(p != attributes.end())
+ {
+ _valueStr = p->second;
+ }
+
+ p = attributes.find("length");
+ if(p != attributes.end())
+ {
+ _lengthStr = p->second;
+ }
+
+ p = attributes.find("convert");
+ if(p != attributes.end())
+ {
+ _convert = p->second == "true";
+ }
+
+ if(!_valueStr.empty())
+ {
+ _value = parse(_valueStr);
+ }
+
+ if(!_lengthStr.empty())
+ {
+ _length = parse(_lengthStr);
+ }
+}
+
+void
+FreezeScript::DefineDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "define", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::DefineDescriptor::validate()
+{
+}
+
+void
+FreezeScript::DefineDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ DescriptorErrorContext ctx(_errorReporter, "define", _line);
+
+ DataPtr data = _factory->create(_type, false);
+
+ DataPtr value;
+ if(_value)
+ {
+ try
+ {
+ value = _value->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of value `" + _valueStr + "' failed:\n" + ex.reason());
+ }
+ }
+
+ DataPtr length;
+ if(_length)
+ {
+ SequenceDataPtr seq = SequenceDataPtr::dynamicCast(data);
+ if(!seq)
+ {
+ _errorReporter->error("length attribute specified but type is not a sequence");
+ }
+
+ try
+ {
+ length = _length->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of length `" + _lengthStr + "' failed:\n" + ex.reason());
+ }
+
+ DataList& elements = seq->getElements();
+ Ice::Long l = length->integerValue();
+ if(l < 0 || l > INT_MAX)
+ {
+ _errorReporter->error("sequence length " + length->toString() + " is out of range");
+ }
+
+ DataList::size_type len = static_cast<DataList::size_type>(l);
+ Slice::SequencePtr seqType = Slice::SequencePtr::dynamicCast(seq->getType());
+ assert(seqType);
+ Slice::TypePtr elemType = seqType->type();
+ for(DataList::size_type i = elements.size(); i < len; ++i)
+ {
+ DataPtr v = _factory->create(elemType, false);
+ if(value)
+ {
+ assignOrTransform(v, value, _convert, _factory, _errorReporter, info);
+ }
+ elements.push_back(v);
+ }
+ }
+ else if(value)
+ {
+ assignOrTransform(data, value, _convert, _factory, _errorReporter, info);
+ }
+
+ sym->add(_name, data);
+}
+
+//
+// AddDescriptor
+//
+FreezeScript::AddDescriptor::AddDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+ DescriptorErrorContext ctx(_errorReporter, "add", _line);
+
+ IceXML::Attributes::const_iterator p;
+
+ string target;
+ p = attributes.find("target");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `target' is missing");
+ }
+ target = p->second;
+
+ p = attributes.find("key");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `key' is missing");
+ }
+ _keyStr = p->second;
+
+ p = attributes.find("value");
+ if(p != attributes.end())
+ {
+ _valueStr = p->second;
+ }
+
+ p = attributes.find("type");
+ if(p != attributes.end())
+ {
+ _type = p->second;
+ }
+
+ p = attributes.find("convert");
+ if(p != attributes.end())
+ {
+ _convert = p->second == "true";
+ }
+
+ if(!_valueStr.empty() && !_type.empty())
+ {
+ _errorReporter->error("attributes `value' and 'type' are mutually exclusive");
+ }
+
+ NodePtr node = parse(target);
+ _target = EntityNodePtr::dynamicCast(node);
+ if(!_target)
+ {
+ _errorReporter->error("`target' attribute is not an entity: `" + target + "'");
+ }
+
+ assert(!_keyStr.empty());
+ _key = parse(_keyStr);
+
+ if(!_valueStr.empty())
+ {
+ _value = parse(_valueStr);
+ }
+}
+
+void
+FreezeScript::AddDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "add", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::AddDescriptor::validate()
+{
+}
+
+void
+FreezeScript::AddDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ DescriptorErrorContext ctx(_errorReporter, "add", _line);
+
+ DataPtr data = sym->getValue(_target);
+ if(data->readOnly())
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' cannot be modified");
+ }
+
+ DictionaryDataPtr dict = DictionaryDataPtr::dynamicCast(data);
+ if(!dict)
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' is not a dictionary");
+ }
+
+ Slice::DictionaryPtr type = Slice::DictionaryPtr::dynamicCast(dict->getType());
+ assert(type);
+
+ DataPtr key;
+ Destroyer<DataPtr> keyDestroyer;
+ try
+ {
+ DataPtr v = _key->evaluate(sym);
+ key = _factory->create(type->keyType(), false);
+ keyDestroyer.set(key);
+ assignOrTransform(key, v, _convert, _factory, _errorReporter, info);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of key `" + _keyStr + "' failed:\n" + ex.reason());
+ }
+
+ if(dict->getElement(key))
+ {
+ ostringstream ostr;
+ printData(key, ostr);
+ _errorReporter->error("key " + ostr.str() + " already exists in dictionary");
+ }
+
+ DataPtr elem = _factory->create(type->valueType(), false);
+ Destroyer<DataPtr> elemDestroyer(elem);
+
+ DataPtr value;
+ if(_value)
+ {
+ try
+ {
+ value = _value->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of value `" + _valueStr + "' failed:\n" + ex.reason());
+ }
+ }
+
+ Destroyer<DataPtr> valueDestroyer;
+ if(!_type.empty())
+ {
+ assert(!value);
+ Slice::TypePtr type = sym->lookupType(_type);
+ if(!type)
+ {
+ _errorReporter->error("type `" + _type + "' not found");
+ }
+ value = _factory->createObject(type, false);
+ valueDestroyer.set(value);
+ }
+
+ if(value)
+ {
+ assignOrTransform(elem, value, _convert, _factory, _errorReporter, info);
+ }
+ DataMap& map = dict->getElements();
+ map.insert(DataMap::value_type(key, elem));
+ keyDestroyer.release();
+ elemDestroyer.release();
+}
+
+//
+// RemoveDescriptor
+//
+FreezeScript::RemoveDescriptor::RemoveDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+ DescriptorErrorContext ctx(_errorReporter, "remove", _line);
+
+ IceXML::Attributes::const_iterator p;
+
+ string target;
+ p = attributes.find("target");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `target' is missing");
+ }
+ target = p->second;
+
+ p = attributes.find("key");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `key' is missing");
+ }
+ _keyStr = p->second;
+
+ NodePtr node = parse(target);
+ _target = EntityNodePtr::dynamicCast(node);
+ if(!_target)
+ {
+ _errorReporter->error("`target' attribute is not an entity: `" + target + "'");
+ }
+
+ _key = parse(_keyStr);
+}
+
+void
+FreezeScript::RemoveDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "remove", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::RemoveDescriptor::validate()
+{
+}
+
+void
+FreezeScript::RemoveDescriptor::execute(const SymbolTablePtr& sym, TransformInfo*)
+{
+ DescriptorErrorContext ctx(_errorReporter, "remove", _line);
+
+ DataPtr key;
+ try
+ {
+ key = _key->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of key `" + _keyStr + "' failed:\n" + ex.reason());
+ }
+
+ DataPtr data = sym->getValue(_target);
+ if(data->readOnly())
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' cannot be modified");
+ }
+
+ DictionaryDataPtr dict = DictionaryDataPtr::dynamicCast(data);
+ if(!dict)
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' is not a dictionary");
+ }
+
+ DataMap& map = dict->getElements();
+ DataMap::iterator p = map.find(key);
+ if(p != map.end())
+ {
+ p->first->destroy();
+ p->second->destroy();
+ map.erase(p);
+ }
+}
+
+//
+// DeleteDescriptor
+//
+FreezeScript::DeleteDescriptor::DeleteDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter, const IceXML::Attributes&) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+}
+
+void
+FreezeScript::DeleteDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "delete", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::DeleteDescriptor::validate()
+{
+}
+
+void
+FreezeScript::DeleteDescriptor::execute(const SymbolTablePtr&, TransformInfo*)
+{
+ throw DeleteRecordException();
+}
+
+//
+// FailDescriptor
+//
+FreezeScript::FailDescriptor::FailDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+ IceXML::Attributes::const_iterator p;
+
+ p = attributes.find("test");
+ if(p != attributes.end())
+ {
+ _testStr = p->second;
+ }
+
+ p = attributes.find("message");
+ if(p != attributes.end())
+ {
+ _message = p->second;
+ }
+
+ if(!_testStr.empty())
+ {
+ _test = parse(_testStr);
+ }
+
+ if(_message.empty())
+ {
+ ostringstream ostr;
+ ostr << "<fail> executed at line " << line << endl;
+ _message = ostr.str();
+ }
+}
+
+void
+FreezeScript::FailDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "fail", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::FailDescriptor::validate()
+{
+}
+
+void
+FreezeScript::FailDescriptor::execute(const SymbolTablePtr& sym, TransformInfo*)
+{
+ DescriptorErrorContext ctx(_errorReporter, "fail", _line);
+
+ if(_test)
+ {
+ try
+ {
+ DataPtr b = _test->evaluate(sym);
+ BooleanDataPtr bd = BooleanDataPtr::dynamicCast(b);
+ if(!bd)
+ {
+ _errorReporter->error("expression `" + _testStr + "' does not evaluate to a boolean");
+ }
+ if(!bd->booleanValue())
+ {
+ return;
+ }
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of expression `" + _testStr + "' failed:\n" + ex.reason());
+ }
+ }
+
+ throw Exception(__FILE__, __LINE__, _message);
+}
+
+//
+// EchoDescriptor
+//
+FreezeScript::EchoDescriptor::EchoDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ Descriptor(parent, line, factory, errorReporter)
+{
+ IceXML::Attributes::const_iterator p;
+
+ p = attributes.find("message");
+ if(p != attributes.end())
+ {
+ _message = p->second;
+ }
+
+ p = attributes.find("value");
+ if(p != attributes.end())
+ {
+ _valueStr = p->second;
+ }
+
+ if(!_valueStr.empty())
+ {
+ _value = parse(_valueStr);
+ }
+}
+
+void
+FreezeScript::EchoDescriptor::addChild(const DescriptorPtr&)
+{
+ DescriptorErrorContext ctx(_errorReporter, "echo", _line);
+ _errorReporter->error("child elements are not supported");
+}
+
+void
+FreezeScript::EchoDescriptor::validate()
+{
+}
+
+void
+FreezeScript::EchoDescriptor::execute(const SymbolTablePtr& sym, TransformInfo*)
+{
+ DescriptorErrorContext ctx(_errorReporter, "echo", _line);
+
+ ostream& out = _errorReporter->stream();
+
+ if(!_message.empty())
+ {
+ out << _message;
+ }
+
+ if(_value)
+ {
+ DataPtr v;
+ try
+ {
+ v = _value->evaluate(sym);
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of value `" + _valueStr + "' failed:\n" + ex.reason());
+ }
+ printData(v, out);
+ }
+
+ out << endl;
+}
+
+//
+// ExecutableContainerDescriptor
+//
+FreezeScript::ExecutableContainerDescriptor::ExecutableContainerDescriptor(const DescriptorPtr& parent, int line,
+ const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes&,
+ const string& name) :
+ Descriptor(parent, line, factory, errorReporter), _name(name)
+{
+}
+
+void
+FreezeScript::ExecutableContainerDescriptor::addChild(const DescriptorPtr& child)
+{
+ _children.push_back(child);
+}
+
+void
+FreezeScript::ExecutableContainerDescriptor::validate()
+{
+ for(vector<DescriptorPtr>::iterator p = _children.begin(); p != _children.end(); ++p)
+ {
+ (*p)->validate();
+ }
+}
+
+void
+FreezeScript::ExecutableContainerDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ for(vector<DescriptorPtr>::iterator p = _children.begin(); p != _children.end(); ++p)
+ {
+ (*p)->execute(sym, info);
+ }
+}
+
+//
+// IfDescriptor
+//
+FreezeScript::IfDescriptor::IfDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ ExecutableContainerDescriptor(parent, line, factory, errorReporter, attributes, "if"),
+ Descriptor(parent, line, factory, errorReporter)
+{
+ DescriptorErrorContext ctx(_errorReporter, "if", _line);
+
+ IceXML::Attributes::const_iterator p = attributes.find("test");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `test' is missing");
+ }
+ _testStr = p->second;
+
+ _test = parse(_testStr);
+}
+
+void
+FreezeScript::IfDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ DescriptorErrorContext ctx(_errorReporter, "if", _line);
+
+ try
+ {
+ DataPtr b = _test->evaluate(sym);
+ BooleanDataPtr bd = BooleanDataPtr::dynamicCast(b);
+ if(!bd)
+ {
+ _errorReporter->error("expression `" + _testStr + "' does not evaluate to a boolean");
+ }
+ if(bd->booleanValue())
+ {
+ ExecutableContainerDescriptor::execute(sym, info);
+ }
+ }
+ catch(const EvaluateException& ex)
+ {
+ _errorReporter->error("evaluation of conditional expression `" + _testStr + "' failed:\n" + ex.reason());
+ }
+}
+
+//
+// IterateDescriptor
+//
+FreezeScript::IterateDescriptor::IterateDescriptor(const DescriptorPtr& parent, int line,
+ const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes) :
+ ExecutableContainerDescriptor(parent, line, factory, errorReporter, attributes, "iterate"),
+ Descriptor(parent, line, factory, errorReporter)
+{
+ DescriptorErrorContext ctx(_errorReporter, "iterate", _line);
+
+ IceXML::Attributes::const_iterator p;
+ string target;
+
+ p = attributes.find("target");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `target' is missing");
+ }
+ target = p->second;
+
+ p = attributes.find("key");
+ if(p != attributes.end())
+ {
+ _key = p->second;
+ }
+
+ p = attributes.find("value");
+ if(p != attributes.end())
+ {
+ _value = p->second;
+ }
+
+ p = attributes.find("element");
+ if(p != attributes.end())
+ {
+ _element = p->second;
+ }
+
+ p = attributes.find("index");
+ if(p != attributes.end())
+ {
+ _index = p->second;
+ }
+
+ NodePtr node = parse(target);
+ _target = EntityNodePtr::dynamicCast(node);
+ if(!_target)
+ {
+ _errorReporter->error("`target' attribute is not an entity: `" + target + "'");
+ }
+}
+
+void
+FreezeScript::IterateDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ DescriptorErrorContext ctx(_errorReporter, "iterate", _line);
+
+ DataPtr data = sym->getValue(_target);
+
+ DictionaryDataPtr dict = DictionaryDataPtr::dynamicCast(data);
+ SequenceDataPtr seq = SequenceDataPtr::dynamicCast(data);
+ if(!dict && !seq)
+ {
+ ostringstream ostr;
+ ostr << _target;
+ _errorReporter->error("target `" + ostr.str() + "' is not a dictionary or sequence");
+ }
+
+ if(dict)
+ {
+ if(!_element.empty())
+ {
+ _errorReporter->error("attribute `element' specified for dictionary target");
+ }
+ if(!_index.empty())
+ {
+ _errorReporter->error("attribute `index' specified for dictionary target");
+ }
+
+ string key = _key;
+ if(key.empty())
+ {
+ key = "key";
+ }
+
+ string value = _value;
+ if(value.empty())
+ {
+ value = "value";
+ }
+
+ DataMap& map = dict->getElements();
+ for(DataMap::iterator p = map.begin(); p != map.end(); ++p)
+ {
+ SymbolTablePtr elemSym = sym->createChild();
+ elemSym->add(key, p->first);
+ elemSym->add(value, p->second);
+ ExecutableContainerDescriptor::execute(elemSym, info);
+ }
+ }
+ else
+ {
+ if(!_key.empty())
+ {
+ _errorReporter->error("attribute `key' specified for sequence target");
+ }
+ if(!_value.empty())
+ {
+ _errorReporter->error("attribute `value' specified for sequence target");
+ }
+
+ string element = _element;
+ if(element.empty())
+ {
+ element = "elem";
+ }
+
+ string index = _index;
+ if(index.empty())
+ {
+ index = "i";
+ }
+
+ DataList& l = seq->getElements();
+ Ice::Long i = 0;
+ for(DataList::iterator p = l.begin(); p != l.end(); ++p, ++i)
+ {
+ SymbolTablePtr elemSym = sym->createChild();
+ elemSym->add(element, *p);
+ elemSym->add(index, _factory->createInteger(i, true));
+ ExecutableContainerDescriptor::execute(elemSym, info);
+ }
+ }
+}
+
+//
+// TransformDescriptor
+//
+FreezeScript::TransformDescriptor::TransformDescriptor(const DescriptorPtr& parent, int line,
+ const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes,
+ const Slice::UnitPtr& oldUnit, const Slice::UnitPtr& newUnit) :
+ ExecutableContainerDescriptor(parent, line, factory, errorReporter, attributes, "transform"),
+ Descriptor(parent, line, factory, errorReporter), _default(true), _base(true)
+{
+ DescriptorErrorContext ctx(_errorReporter, "transform", _line);
+
+ IceXML::Attributes::const_iterator p;
+
+ string type, rename;
+
+ p = attributes.find("type");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `type' is missing");
+ }
+ type = p->second;
+
+ p = attributes.find("default");
+ if(p != attributes.end())
+ {
+ if(p->second == "false")
+ {
+ _default = false;
+ }
+ }
+
+ p = attributes.find("base");
+ if(p != attributes.end())
+ {
+ if(p->second == "false")
+ {
+ _base = false;
+ }
+ }
+
+ p = attributes.find("rename");
+ if(p != attributes.end())
+ {
+ rename = p->second;
+ }
+
+ Slice::TypeList l;
+
+ l = newUnit->lookupType(type, false);
+ if(l.empty())
+ {
+ _errorReporter->error("unable to find type `" + type + "' in new Slice definitions");
+ }
+ else
+ {
+ _newType = l.front();
+ }
+
+ if(!rename.empty())
+ {
+ l = oldUnit->lookupType(rename, false);
+ if(l.empty())
+ {
+ _errorReporter->error("unable to find type `" + rename + "' in old Slice definitions");
+ }
+ _renameType = l.front();
+ }
+}
+
+Slice::TypePtr
+FreezeScript::TransformDescriptor::type() const
+{
+ return _newType;
+}
+
+string
+FreezeScript::TransformDescriptor::typeName() const
+{
+ return typeToString(_newType);
+}
+
+Slice::TypePtr
+FreezeScript::TransformDescriptor::renameType() const
+{
+ return _renameType;
+}
+
+string
+FreezeScript::TransformDescriptor::renameTypeName() const
+{
+ string result;
+ if(_renameType)
+ {
+ result = typeToString(_renameType);
+ }
+ return result;
+}
+
+bool
+FreezeScript::TransformDescriptor::doDefaultTransform() const
+{
+ return _default;
+}
+
+bool
+FreezeScript::TransformDescriptor::doBaseTransform() const
+{
+ return _base;
+}
+
+//
+// InitDescriptor
+//
+FreezeScript::InitDescriptor::InitDescriptor(const DescriptorPtr& parent, int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes,
+ const Slice::UnitPtr& oldUnit, const Slice::UnitPtr& newUnit) :
+ ExecutableContainerDescriptor(parent, line, factory, errorReporter, attributes, "init"),
+ Descriptor(parent, line, factory, errorReporter), _old(oldUnit), _new(newUnit)
+{
+ DescriptorErrorContext ctx(_errorReporter, "init", _line);
+
+ IceXML::Attributes::const_iterator p = attributes.find("type");
+
+ string type;
+
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `type' is missing");
+ }
+ type = p->second;
+
+ Slice::TypeList l = _new->lookupType(type, false);
+ if(l.empty())
+ {
+ _errorReporter->error("unable to find type `" + type + "' in new Slice definitions");
+ }
+ else
+ {
+ _type = l.front();
+ }
+}
+
+void
+FreezeScript::InitDescriptor::initialize(const DataFactoryPtr& factory, const DataPtr& data,
+ const Ice::CommunicatorPtr& communicator)
+{
+ //
+ // Create a new symbol table for the initializer and add the value to be initialized
+ // as the symbol "value".
+ //
+ TransformInfo* info = 0;
+
+ // TODO: Initialializers should have access to the main symbol table.
+ SymbolTablePtr sym = new SymbolTableI(factory, _old, _new, _errorReporter, info);
+ sym->add("value", data);
+
+ execute(sym, info);
+}
+
+string
+FreezeScript::InitDescriptor::typeName() const
+{
+ return typeToString(_type);
+}
+
+//
+// RecordDescriptor
+//
+FreezeScript::RecordDescriptor::RecordDescriptor(const DescriptorPtr& parent, int line,
+ const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes,
+ const Slice::UnitPtr& oldUnit, const Slice::UnitPtr& newUnit) :
+ ExecutableContainerDescriptor(parent, line, factory, errorReporter, attributes, "record"),
+ Descriptor(parent, line, factory, errorReporter), _old(oldUnit), _new(newUnit)
+{
+}
+
+void
+FreezeScript::RecordDescriptor::execute(const SymbolTablePtr& sym, TransformInfo* info)
+{
+ TransformInfoI* infoI = dynamic_cast<TransformInfoI*>(info);
+ assert(infoI);
+
+ //
+ // We need the Instance in order to use BasicStream.
+ //
+ IceInternal::InstancePtr instance = IceInternal::getInstance(infoI->communicator);
+
+ //
+ // Temporarily add an object factory.
+ //
+ infoI->communicator->addObjectFactory(new FreezeScript::ObjectFactory(_factory, _old), "");
+
+ //
+ // Iterate over the database.
+ //
+ Dbc* dbc = 0;
+ infoI->oldDb->cursor(infoI->oldDbTxn, &dbc, 0);
+ try
+ {
+ Dbt dbKey, dbValue;
+ while(dbc->get(&dbKey, &dbValue, DB_NEXT) == 0)
+ {
+ IceInternal::BasicStream inKey(instance.get());
+ inKey.b.resize(dbKey.get_size());
+ memcpy(&inKey.b[0], dbKey.get_data(), dbKey.get_size());
+ inKey.i = inKey.b.begin();
+
+ IceInternal::BasicStream inValue(instance.get());
+ inValue.b.resize(dbValue.get_size());
+ memcpy(&inValue.b[0], dbValue.get_data(), dbValue.get_size());
+ inValue.i = inValue.b.begin();
+ inValue.startReadEncaps();
+
+ IceInternal::BasicStream outKey(instance.get());
+ IceInternal::BasicStream outValue(instance.get());
+ outValue.startWriteEncaps();
+ try
+ {
+ transformRecord(inKey, inValue, outKey, outValue, info);
+ outValue.endWriteEncaps();
+ Dbt dbNewKey(&outKey.b[0], outKey.b.size()), dbNewValue(&outValue.b[0], outValue.b.size());
+ if(infoI->newDb->put(infoI->newDbTxn, &dbNewKey, &dbNewValue, DB_NOOVERWRITE) == DB_KEYEXIST)
+ {
+ _errorReporter->error("duplicate key encountered");
+ }
+ }
+ catch(const DeleteRecordException&)
+ {
+ // The record is deleted simply by not adding it to the new database.
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ if(!infoI->purge)
+ {
+ _errorReporter->error("class " + ex.id + " not found in new Slice definitions");
+ }
+ else
+ {
+ // The record is deleted simply by not adding it to the new database.
+ _errorReporter->warning("purging database record due to missing class type " + ex.id);
+ }
+ }
+ }
+ }
+ catch(...)
+ {
+ if(dbc)
+ {
+ dbc->close();
+ }
+ infoI->communicator->removeObjectFactory("");
+ throw;
+ }
+
+ infoI->communicator->removeObjectFactory("");
+
+ if(dbc)
+ {
+ dbc->close();
+ }
+}
+
+void
+FreezeScript::RecordDescriptor::transformRecord(IceInternal::BasicStream& inKey, IceInternal::BasicStream& inValue,
+ IceInternal::BasicStream& outKey, IceInternal::BasicStream& outValue,
+ TransformInfo* info)
+{
+ TransformInfoI* infoI = dynamic_cast<TransformInfoI*>(info);
+ assert(infoI);
+
+ //
+ // Create data representations of the old key and value types.
+ //
+ _factory->disableInitializers();
+ DataPtr oldKeyData = _factory->create(infoI->oldKeyType, true);
+ Destroyer<DataPtr> oldKeyDataDestroyer(oldKeyData);
+ DataPtr oldValueData = _factory->create(infoI->oldValueType, true);
+ Destroyer<DataPtr> oldValueDataDestroyer(oldValueData);
+
+ //
+ // Unmarshal the old key and value.
+ //
+ oldKeyData->unmarshal(inKey);
+ oldValueData->unmarshal(inValue);
+ infoI->objectDataMap.clear();
+ if(infoI->oldValueType->usesClasses())
+ {
+ inValue.readPendingObjects();
+ ObjectVisitor visitor(infoI->objectDataMap);
+ oldValueData->visit(visitor);
+ }
+ _factory->enableInitializers();
+
+ //
+ // Create data representations of the new key and value types.
+ //
+ DataPtr newKeyData = _factory->create(infoI->newKeyType, false);
+ Destroyer<DataPtr> newKeyDataDestroyer(newKeyData);
+ DataPtr newValueData = _factory->create(infoI->newValueType, false);
+ Destroyer<DataPtr> newValueDataDestroyer(newValueData);
+
+ //
+ // Copy the data from the old key and value to the new key and value, if possible.
+ //
+ TransformVisitor keyVisitor(oldKeyData, _factory, _errorReporter, info);
+ newKeyData->visit(keyVisitor);
+ TransformVisitor valueVisitor(oldValueData, _factory, _errorReporter, info);
+ newValueData->visit(valueVisitor);
+
+ if(!_children.empty())
+ {
+ //
+ // Execute the child descriptors.
+ //
+ // TODO: Revisit identifiers.
+ //
+ SymbolTablePtr st = new SymbolTableI(_factory, _old, _new, _errorReporter, info, infoI->symbolTable);
+ st->add("oldkey", oldKeyData);
+ st->add("newkey", newKeyData);
+ st->add("oldvalue", oldValueData);
+ st->add("newvalue", newValueData);
+ ExecutableContainerDescriptor::execute(st, info);
+ }
+
+ newKeyData->marshal(outKey);
+ newValueData->marshal(outValue);
+ if(infoI->newValueType->usesClasses())
+ {
+ outValue.writePendingObjects();
+ }
+}
+
+//
+// DatabaseDescriptor
+//
+FreezeScript::DatabaseDescriptor::DatabaseDescriptor(const DescriptorPtr& parent, int line,
+ const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes,
+ const Slice::UnitPtr& oldUnit, const Slice::UnitPtr& newUnit) :
+ ExecutableContainerDescriptor(parent, line, factory, errorReporter, attributes, "database"),
+ Descriptor(parent, line, factory, errorReporter), _old(oldUnit), _new(newUnit)
+{
+ DescriptorErrorContext ctx(_errorReporter, "database", _line);
+
+ IceXML::Attributes::const_iterator p = attributes.find("key");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `key' is missing");
+ }
+ string keyTypes = p->second;
+
+ p = attributes.find("value");
+ if(p == attributes.end())
+ {
+ _errorReporter->error("required attribute `value' is missing");
+ }
+ string valueTypes = p->second;
+
+ string oldKeyName, newKeyName;
+ string oldValueName, newValueName;
+ string::size_type pos;
+
+ pos = keyTypes.find(',');
+ if(pos == 0 || pos == keyTypes.size())
+ {
+ _errorReporter->error("invalid key type specification `" + keyTypes +"'");
+ }
+ if(pos == string::npos)
+ {
+ oldKeyName = keyTypes;
+ newKeyName = keyTypes;
+ }
+ else
+ {
+ oldKeyName = keyTypes.substr(0, pos);
+ newKeyName = keyTypes.substr(pos + 1);
+ }
+
+ pos = valueTypes.find(',');
+ if(pos == 0 || pos == valueTypes.size())
+ {
+ _errorReporter->error("invalid value type specification `" + valueTypes +"'");
+ }
+ if(pos == string::npos)
+ {
+ oldValueName = valueTypes;
+ newValueName = valueTypes;
+ }
+ else
+ {
+ oldValueName = valueTypes.substr(0, pos);
+ newValueName = valueTypes.substr(pos + 1);
+ }
+
+ //
+ // Look up the Slice definitions for the key and value types.
+ //
+ _oldKey = findType(_old, oldKeyName);
+ _newKey = findType(_new, newKeyName);
+ _oldValue = findType(_old, oldValueName);
+ _newValue = findType(_new, newValueName);
+}
+
+void
+FreezeScript::DatabaseDescriptor::addChild(const DescriptorPtr& child)
+{
+ DescriptorErrorContext ctx(_errorReporter, "database", _line);
+
+ RecordDescriptorPtr rec = RecordDescriptorPtr::dynamicCast(child);
+ if(rec)
+ {
+ if(_record)
+ {
+ _errorReporter->error("only one <record> element can be specified");
+ }
+ _record = rec;
+ }
+
+ ExecutableContainerDescriptor::addChild(child);
+}
+
+void
+FreezeScript::DatabaseDescriptor::execute(const SymbolTablePtr&, TransformInfo* info)
+{
+ TransformInfoI* infoI = dynamic_cast<TransformInfoI*>(info);
+ assert(infoI);
+
+ //
+ // Store the key and value types.
+ //
+ infoI->oldKeyType = _oldKey;
+ infoI->oldValueType = _oldValue;
+ infoI->newKeyType = _newKey;
+ infoI->newValueType = _newValue;
+
+ ExecutableContainerDescriptor::execute(infoI->symbolTable, info);
+}
+
+//
+// TransformDBDescriptor
+//
+FreezeScript::TransformDBDescriptor::TransformDBDescriptor(int line, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter,
+ const IceXML::Attributes& attributes,
+ const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit) :
+ Descriptor(0, line, factory, errorReporter), _old(oldUnit), _new(newUnit),
+ _info(new TransformInfoI(factory, errorReporter, oldUnit, newUnit))
+{
+}
+
+FreezeScript::TransformDBDescriptor::~TransformDBDescriptor()
+{
+ delete _info;
+}
+
+void
+FreezeScript::TransformDBDescriptor::addChild(const DescriptorPtr& child)
+{
+ DescriptorErrorContext ctx(_errorReporter, "transformdb", _line);
+
+ DatabaseDescriptorPtr db = DatabaseDescriptorPtr::dynamicCast(child);
+ TransformDescriptorPtr transform = TransformDescriptorPtr::dynamicCast(child);
+ InitDescriptorPtr init = InitDescriptorPtr::dynamicCast(child);
+
+ if(db)
+ {
+ if(_database)
+ {
+ _errorReporter->error("only one <database> element can be specified");
+ }
+ else
+ {
+ _database = db;
+ _children.push_back(db);
+ }
+ }
+ else if(transform)
+ {
+ string name = transform->typeName();
+ TransformMap::iterator p = _info->transformMap.find(name);
+ if(p != _info->transformMap.end())
+ {
+ _errorReporter->error("transform `" + name + "' specified more than once");
+ }
+ _info->transformMap.insert(TransformMap::value_type(name, transform));
+
+ string renameTypeName = transform->renameTypeName();
+ if(!renameTypeName.empty())
+ {
+ RenameMap::iterator q = _info->renameMap.find(renameTypeName);
+ if(q != _info->renameMap.end())
+ {
+ _errorReporter->error("multiple transform descriptors specify the rename value `" + renameTypeName +
+ "'");
+ }
+ _info->renameMap.insert(RenameMap::value_type(renameTypeName, transform->type()));
+ }
+
+ _children.push_back(transform);
+ }
+ else if(init)
+ {
+ string name = init->typeName();
+ _factory->addInitializer(name, init);
+ _children.push_back(init);
+ }
+ else
+ {
+ _errorReporter->error("invalid child element");
+ }
+}
+
+void
+FreezeScript::TransformDBDescriptor::validate()
+{
+ DescriptorErrorContext ctx(_errorReporter, "transformdb", _line);
+
+ if(!_database)
+ {
+ _errorReporter->error("no <database> element specified");
+ }
+
+ for(vector<DescriptorPtr>::iterator p = _children.begin(); p != _children.end(); ++p)
+ {
+ (*p)->validate();
+ }
+}
+
+void
+FreezeScript::TransformDBDescriptor::execute(const SymbolTablePtr&, TransformInfo*)
+{
+ assert(false);
+}
+
+void
+FreezeScript::TransformDBDescriptor::transform(const Ice::CommunicatorPtr& communicator, Db* oldDb, DbTxn* oldDbTxn,
+ Db* newDb, DbTxn* newDbTxn, bool purgeObjects)
+{
+ _info->communicator = communicator;
+ _info->oldDb = oldDb;
+ _info->oldDbTxn = oldDbTxn;
+ _info->newDb = newDb;
+ _info->newDbTxn = newDbTxn;
+ _info->purge = purgeObjects;
+
+ try
+ {
+ _database->execute(0, _info);
+ }
+ catch(...)
+ {
+ _info->communicator = 0;
+ _info->oldDb = 0;
+ _info->oldDbTxn = 0;
+ _info->newDb = 0;
+ _info->newDbTxn = 0;
+ throw;
+ }
+
+ _info->communicator = 0;
+ _info->oldDb = 0;
+ _info->oldDbTxn = 0;
+ _info->newDb = 0;
+ _info->newDbTxn = 0;
+}
+
+//
+// SymbolTableI
+//
+FreezeScript::SymbolTableI::SymbolTableI(const DataFactoryPtr& factory, const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit,
+ const ErrorReporterPtr& errorReporter, TransformInfo* info,
+ const SymbolTablePtr& parent) :
+ _factory(factory), _old(oldUnit), _new(newUnit), _errorReporter(errorReporter), _info(info), _parent(parent)
+{
+}
+
+void
+FreezeScript::SymbolTableI::add(const string& name, const DataPtr& data)
+{
+ DataPtr d = findValue(name);
+ if(d)
+ {
+ _errorReporter->error("`" + name + "' is already defined");
+ }
+
+ _dataMap.insert(DataMap::value_type(name, data));
+}
+
+FreezeScript::DataPtr
+FreezeScript::SymbolTableI::getValue(const EntityNodePtr& entity) const
+{
+ EntityVisitor visitor(const_cast<SymbolTableI*>(this));
+ entity->visit(visitor);
+ DataPtr result = visitor.getCurrent();
+ if(!result)
+ {
+ ostringstream ostr;
+ ostr << "invalid entity `" << entity << "'";
+ _errorReporter->error(ostr.str());
+ }
+
+ return result;
+}
+
+FreezeScript::DataPtr
+FreezeScript::SymbolTableI::getConstantValue(const string& name) const
+{
+ string::size_type pos;
+ Slice::UnitPtr unit;
+ string key;
+
+ DataMap::const_iterator p = _constantCache.find(name);
+ if(p != _constantCache.end())
+ {
+ return p->second;
+ }
+
+ if(_parent)
+ {
+ return _parent->getConstantValue(name);
+ }
+
+ //
+ // Name must start with "::Old" or "::New" to indicate the Slice unit.
+ //
+ pos = name.find("::Old");
+ if(pos == 0)
+ {
+ if(name.length() > 5)
+ {
+ key = name.substr(5);
+ unit = _old;
+ }
+ }
+ else
+ {
+ pos = name.find("::New");
+ if(pos == 0)
+ {
+ if(name.length() > 5)
+ {
+ key = name.substr(5);
+ unit = _new;
+ }
+ }
+ }
+
+ if(key.empty())
+ {
+ _errorReporter->error("invalid constant name `" + name + "'");
+ }
+
+ Slice::ContainedList l = unit->findContents(key);
+ if(l.empty())
+ {
+ _errorReporter->error("unknown constant `" + name + "'");
+ }
+
+ Slice::EnumeratorPtr e = Slice::EnumeratorPtr::dynamicCast(l.front());
+ Slice::ConstPtr c = Slice::ConstPtr::dynamicCast(l.front());
+ if(!e && !c)
+ {
+ _errorReporter->error("`" + name + "' does not refer to a Slice constant or enumerator");
+ }
+
+ DataPtr result;
+
+ if(c)
+ {
+ Slice::TypePtr type = c->type();
+ string value = c->value();
+ Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type);
+ if(b)
+ {
+ switch(b->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ {
+ string::size_type end;
+ Ice::Long n;
+ if(!IceUtil::stringToInt64(value, n, end))
+ {
+ assert(false);
+ }
+ result = _factory->createInteger(n, true);
+ break;
+ }
+
+ case Slice::Builtin::KindBool:
+ {
+ result = _factory->createBoolean(value == "true", true);
+ break;
+ }
+
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ {
+ double v = strtod(value.c_str(), 0);
+ result = _factory->createDouble(v, true);
+ break;
+ }
+
+ case Slice::Builtin::KindString:
+ {
+ result = _factory->createString(value, true);
+ break;
+ }
+
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+ }
+ else
+ {
+ Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type);
+ assert(en);
+ Slice::EnumeratorList el = en->getEnumerators();
+ for(Slice::EnumeratorList::iterator q = el.begin(); q != el.end(); ++q)
+ {
+ if((*q)->name() == value)
+ {
+ e = *q;
+ break;
+ }
+ }
+ assert(e);
+ }
+ }
+
+ if(!result)
+ {
+ assert(e);
+ result = _factory->create(e->type(), true);
+ EnumDataPtr ed = EnumDataPtr::dynamicCast(result);
+ assert(ed);
+ ed->setValueAsString(e->name());
+ }
+
+ //
+ // Cache the value.
+ //
+ const_cast<DataMap&>(_constantCache).insert(DataMap::value_type(name, result));
+
+ return result;
+}
+
+FreezeScript::SymbolTablePtr
+FreezeScript::SymbolTableI::createChild()
+{
+ return new SymbolTableI(_factory, _old, _new, _errorReporter, _info, this);
+}
+
+Slice::TypePtr
+FreezeScript::SymbolTableI::lookupType(const string& name)
+{
+ Slice::TypeList l = _new->lookupType(name, false);
+ Slice::TypePtr result;
+ if(!l.empty())
+ {
+ result = l.front();
+ }
+ return result;
+}
+
+FreezeScript::DataPtr
+FreezeScript::SymbolTableI::invokeFunction(const string& name, const DataPtr& target, const DataList& args)
+{
+ if(target)
+ {
+ DictionaryDataPtr targetDict = DictionaryDataPtr::dynamicCast(target);
+ if(targetDict && name == "containsKey")
+ {
+ if(args.size() != 1)
+ {
+ _errorReporter->error("containsKey() requires one argument");
+ }
+ Slice::DictionaryPtr dictType = Slice::DictionaryPtr::dynamicCast(targetDict->getType());
+ assert(dictType);
+ DataPtr key = _factory->create(dictType->keyType(), false);
+ assignOrTransform(key, args[0], false, _factory, _errorReporter, _info);
+ DataPtr value = targetDict->getElement(key);
+ return _factory->createBoolean(value ? true : false, false);
+ }
+
+ DataPtr result;
+ if(invokeMemberFunction(name, target, args, result, _factory, _errorReporter))
+ {
+ return result;
+ }
+
+ _errorReporter->error("unknown function `" + name + "' invoked on type " + typeToString(target->getType()));
+ }
+ else
+ {
+ //
+ // Global function.
+ //
+ DataPtr result;
+ if(invokeGlobalFunction(name, args, result, _factory, _errorReporter))
+ {
+ return result;
+ }
+ else
+ {
+ _errorReporter->error("unknown global function `" + name + "'");
+ }
+ }
+
+ return 0;
+}
+
+FreezeScript::DataPtr
+FreezeScript::SymbolTableI::findValue(const string& name) const
+{
+ DataMap::const_iterator p = _dataMap.find(name);
+ if(p != _dataMap.end())
+ {
+ return p->second;
+ }
+
+ if(_parent)
+ {
+ SymbolTableIPtr parentI = SymbolTableIPtr::dynamicCast(_parent);
+ assert(parentI);
+ return parentI->findValue(name);
+ }
+
+ return 0;
+}
+
+FreezeScript::SymbolTableI::EntityVisitor::EntityVisitor(SymbolTableI* table) :
+ _table(table), _error(false)
+{
+}
+
+void
+FreezeScript::SymbolTableI::EntityVisitor::visitIdentifier(const string& name)
+{
+ if(!_error)
+ {
+ if(!_current)
+ {
+ _current = _table->findValue(name);
+ }
+ else
+ {
+ _current = _current->getMember(name);
+ }
+
+ if(!_current)
+ {
+ _error = true;
+ }
+ }
+}
+
+void
+FreezeScript::SymbolTableI::EntityVisitor::visitElement(const NodePtr& value)
+{
+ if(!_error)
+ {
+ assert(_current);
+
+ DataPtr val = value->evaluate(_table);
+ _current = _current->getElement(val);
+
+ if(!_current)
+ {
+ _error = true;
+ }
+ }
+}
+
+FreezeScript::DataPtr
+FreezeScript::SymbolTableI::EntityVisitor::getCurrent() const
+{
+ return _current;
+}
+
+//
+// ObjectVisitor
+//
+FreezeScript::ObjectVisitor::ObjectVisitor(ObjectDataMap& map) :
+ _map(map)
+{
+}
+
+void
+FreezeScript::ObjectVisitor::visitStruct(const StructDataPtr& data)
+{
+ Slice::TypePtr type = data->getType();
+ if(type->usesClasses())
+ {
+ DataMemberMap& members = data->getMembers();
+ for(DataMemberMap::iterator p = members.begin(); p != members.end(); ++p)
+ {
+ p->second->visit(*this);
+ }
+ }
+}
+
+void
+FreezeScript::ObjectVisitor::visitSequence(const SequenceDataPtr& data)
+{
+ Slice::TypePtr type = data->getType();
+ if(type->usesClasses())
+ {
+ DataList& elements = data->getElements();
+ for(DataList::iterator p = elements.begin(); p != elements.end(); ++p)
+ {
+ (*p)->visit(*this);
+ }
+ }
+}
+
+void
+FreezeScript::ObjectVisitor::visitDictionary(const DictionaryDataPtr& data)
+{
+ Slice::TypePtr type = data->getType();
+ if(type->usesClasses())
+ {
+ DataMap& elements = data->getElements();
+ for(DataMap::iterator p = elements.begin(); p != elements.end(); ++p)
+ {
+ //
+ // NOTE: There's no need to visit the key.
+ //
+ p->second->visit(*this);
+ }
+ }
+}
+
+void
+FreezeScript::ObjectVisitor::visitObject(const ObjectRefPtr& data)
+{
+ ObjectDataPtr value = data->getValue();
+ if(value)
+ {
+ ObjectDataMap::iterator p = _map.find(value.get());
+ if(p == _map.end())
+ {
+ _map.insert(ObjectDataMap::value_type(value.get(), 0));
+ DataMemberMap& members = value->getMembers();
+ for(DataMemberMap::iterator q = members.begin(); q != members.end(); ++q)
+ {
+ q->second->visit(*this);
+ }
+ }
+ }
+}
+
+//
+// TransformInfoI
+//
+FreezeScript::TransformInfoI::TransformInfoI(const DataFactoryPtr& fact, const ErrorReporterPtr& err,
+ const Slice::UnitPtr& oldU, const Slice::UnitPtr& newU) :
+ factory(fact), errorReporter(err), oldUnit(oldU), newUnit(newU), purge(false), oldDb(0), oldDbTxn(0), newDb(0),
+ newDbTxn(0)
+{
+ symbolTable = new SymbolTableI(factory, oldUnit, newUnit, errorReporter, this);
+}
+
+bool
+FreezeScript::TransformInfoI::doDefaultTransform(const Slice::TypePtr& type)
+{
+ TransformMap::const_iterator p = transformMap.find(typeToString(type));
+ if(p != transformMap.end())
+ {
+ return p->second->doDefaultTransform();
+ }
+ return true;
+}
+
+bool
+FreezeScript::TransformInfoI::doBaseTransform(const Slice::ClassDefPtr& type)
+{
+ TransformMap::const_iterator p = transformMap.find(type->scoped());
+ if(p != transformMap.end())
+ {
+ return p->second->doBaseTransform();
+ }
+ return true;
+}
+
+Slice::TypePtr
+FreezeScript::TransformInfoI::getRenamedType(const Slice::TypePtr& old)
+{
+ RenameMap::iterator p = renameMap.find(typeToString(old));
+ if(p != renameMap.end())
+ {
+ return p->second;
+ }
+ return 0;
+}
+
+void
+FreezeScript::TransformInfoI::executeCustomTransform(const DataPtr& dest, const DataPtr& src)
+{
+ //
+ // Execute the type's transform (if any). Non-nil objects need special consideration,
+ // for two reasons:
+ //
+ // 1. The dest and src arguments are ObjectRef instances whose getType()
+ // function returns the formal type, which may not match the actual type
+ // if inheritance is being used. Therefore, we need to look for the
+ // transform of the actual type of the object.
+ //
+ // 2. It's not sufficient to execute only the transform for the actual type;
+ // the transform descriptors for base types must also be executed (if not
+ // explicitly precluded).
+ //
+ // The algorithm goes like this:
+ //
+ // 1. If a transform exists for the actual type, execute it.
+ // 2. If the transform doesn't exist, or if it does exist and does not preclude
+ // the execution of the base transform, then obtain the base type. If the
+ // type has no user-defined base class, use Object.
+ // 3. If a base type was found and a transform exists for the base type, execute it.
+ // 4. Repeat step 2.
+ //
+ ObjectRefPtr obj = ObjectRefPtr::dynamicCast(dest);
+ if(obj && obj->getValue())
+ {
+ ObjectDataPtr data = obj->getValue();
+ Slice::TypePtr cls = data->getType(); // Actual type
+ bool transformBase = true;
+ while(cls)
+ {
+ string type = typeToString(cls);
+ TransformMap::const_iterator p = transformMap.find(type);
+ if(p != transformMap.end())
+ {
+ SymbolTablePtr sym = new SymbolTableI(factory, oldUnit, newUnit, errorReporter, this, symbolTable);
+ sym->add("new", dest);
+ sym->add("old", src);
+ p->second->execute(sym, this);
+ transformBase = p->second->doBaseTransform();
+ }
+ Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(cls);
+ cls = 0;
+ if(transformBase && decl)
+ {
+ Slice::ClassDefPtr def = decl->definition();
+ assert(def);
+ Slice::ClassList bases = def->bases();
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ cls = bases.front()->declaration();
+ }
+ else
+ {
+ cls = newUnit->builtin(Slice::Builtin::KindObject);
+ }
+ }
+ }
+ }
+ else
+ {
+ string type = typeToString(dest->getType());
+ TransformMap::const_iterator p = transformMap.find(type);
+ if(p != transformMap.end())
+ {
+ SymbolTablePtr sym = new SymbolTableI(factory, oldUnit, newUnit, errorReporter, this, symbolTable);
+ sym->add("new", dest);
+ sym->add("old", src);
+ p->second->execute(sym, this);
+ }
+ }
+}
+
+bool
+FreezeScript::TransformInfoI::purgeObjects()
+{
+ return purge;
+}
+
+FreezeScript::ObjectDataMap&
+FreezeScript::TransformInfoI::getObjectDataMap()
+{
+ return objectDataMap;
+}
+
+//
+// assignOrTransform
+//
+void
+FreezeScript::assignOrTransform(const DataPtr& dest, const DataPtr& src, bool convert, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter, TransformInfo* info)
+{
+ Slice::TypePtr destType = dest->getType();
+ Slice::TypePtr srcType = src->getType();
+ Slice::BuiltinPtr b1 = Slice::BuiltinPtr::dynamicCast(destType);
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(srcType);
+
+ if(!b1 && !b2 && dest->getType()->unit().get() != src->getType()->unit().get())
+ {
+ TransformVisitor v(src, factory, errorReporter, info);
+ dest->visit(v);
+ }
+ else
+ {
+ AssignVisitor v(src, factory, errorReporter, convert);
+ dest->visit(v);
+ }
+}
diff --git a/cpp/src/FreezeScript/TransformDescriptors.h b/cpp/src/FreezeScript/TransformDescriptors.h
new file mode 100644
index 00000000000..d0d33085796
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformDescriptors.h
@@ -0,0 +1,353 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_TRANSFORM_DESCRIPTORS_H
+#define FREEZE_SCRIPT_TRANSFORM_DESCRIPTORS_H
+
+#include <FreezeScript/Parser.h>
+#include <FreezeScript/TransformVisitor.h>
+#include <IceXML/Parser.h>
+
+class Db;
+class DbTxn;
+
+namespace FreezeScript
+{
+
+class Descriptor;
+typedef IceUtil::Handle<Descriptor> DescriptorPtr;
+
+class DeleteRecordException {};
+
+class Descriptor : virtual public IceUtil::SimpleShared
+{
+public:
+
+ virtual ~Descriptor();
+
+ virtual DescriptorPtr parent() const;
+ virtual void addChild(const DescriptorPtr&) = 0;
+ virtual void validate() = 0;
+ virtual void execute(const SymbolTablePtr&, TransformInfo*) = 0;
+
+protected:
+
+ Descriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&);
+
+ NodePtr parse(const std::string&) const;
+
+ Slice::TypePtr findType(const Slice::UnitPtr&, const std::string&);
+
+ DescriptorPtr _parent;
+ int _line;
+ DataFactoryPtr _factory;
+ ErrorReporterPtr _errorReporter;
+};
+
+class SetDescriptor : public Descriptor
+{
+public:
+
+ SetDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ EntityNodePtr _target;
+ NodePtr _value;
+ std::string _valueStr;
+ std::string _type;
+ NodePtr _length;
+ std::string _lengthStr;
+ bool _convert;
+};
+
+class DefineDescriptor : public Descriptor
+{
+public:
+
+ DefineDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&, const Slice::UnitPtr&, const Slice::UnitPtr&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ std::string _name;
+ NodePtr _value;
+ std::string _valueStr;
+ Slice::TypePtr _type;
+ NodePtr _length;
+ std::string _lengthStr;
+ bool _convert;
+};
+
+class AddDescriptor : public Descriptor
+{
+public:
+
+ AddDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ EntityNodePtr _target;
+ NodePtr _key;
+ std::string _keyStr;
+ NodePtr _value;
+ std::string _valueStr;
+ std::string _type;
+ bool _convert;
+};
+
+class RemoveDescriptor : public Descriptor
+{
+public:
+
+ RemoveDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ EntityNodePtr _target;
+ NodePtr _key;
+ std::string _keyStr;
+};
+
+class DeleteDescriptor : public Descriptor
+{
+public:
+
+ DeleteDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+};
+
+class FailDescriptor : public Descriptor
+{
+public:
+
+ FailDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ NodePtr _test;
+ std::string _testStr;
+ std::string _message;
+};
+
+class EchoDescriptor : public Descriptor
+{
+public:
+
+ EchoDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ std::string _message;
+ NodePtr _value;
+ std::string _valueStr;
+};
+
+class ExecutableContainerDescriptor : virtual public Descriptor
+{
+public:
+
+ ExecutableContainerDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&, const std::string&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+protected:
+
+ std::vector<DescriptorPtr> _children;
+
+private:
+
+ std::string _name;
+};
+
+class IfDescriptor : public ExecutableContainerDescriptor
+{
+public:
+
+ IfDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&, const IceXML::Attributes&);
+
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ NodePtr _test;
+ std::string _testStr;
+};
+
+class IterateDescriptor : public ExecutableContainerDescriptor
+{
+public:
+
+ IterateDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&);
+
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ EntityNodePtr _target;
+ std::string _key;
+ std::string _value;
+ std::string _element;
+ std::string _index;
+};
+
+class TransformDescriptor : public ExecutableContainerDescriptor
+{
+public:
+
+ TransformDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&, const Slice::UnitPtr&, const Slice::UnitPtr&);
+
+ Slice::TypePtr type() const;
+ std::string typeName() const;
+ Slice::TypePtr renameType() const;
+ std::string renameTypeName() const;
+ bool doDefaultTransform() const;
+ bool doBaseTransform() const;
+
+private:
+
+ bool _default;
+ bool _base;
+ Slice::TypePtr _newType;
+ Slice::TypePtr _renameType;
+};
+typedef IceUtil::Handle<TransformDescriptor> TransformDescriptorPtr;
+
+class InitDescriptor : virtual public ExecutableContainerDescriptor, virtual public DataInitializer
+{
+public:
+
+ InitDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&, const Slice::UnitPtr&, const Slice::UnitPtr&);
+
+ virtual void initialize(const DataFactoryPtr&, const DataPtr&, const Ice::CommunicatorPtr&);
+
+ std::string typeName() const;
+
+private:
+
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ Slice::TypePtr _type;
+};
+typedef IceUtil::Handle<InitDescriptor> InitDescriptorPtr;
+
+class RecordDescriptor : public ExecutableContainerDescriptor
+{
+public:
+
+ RecordDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&, const Slice::UnitPtr&, const Slice::UnitPtr&);
+
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ void transformRecord(IceInternal::BasicStream&, IceInternal::BasicStream&, IceInternal::BasicStream&,
+ IceInternal::BasicStream&, TransformInfo*);
+
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+};
+typedef IceUtil::Handle<RecordDescriptor> RecordDescriptorPtr;
+
+class DatabaseDescriptor : public ExecutableContainerDescriptor
+{
+public:
+
+ DatabaseDescriptor(const DescriptorPtr&, int, const DataFactoryPtr&, const ErrorReporterPtr&,
+ const IceXML::Attributes&, const Slice::UnitPtr&, const Slice::UnitPtr&);
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+private:
+
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ Slice::TypePtr _oldKey;
+ Slice::TypePtr _newKey;
+ Slice::TypePtr _oldValue;
+ Slice::TypePtr _newValue;
+ RecordDescriptorPtr _record;
+};
+typedef IceUtil::Handle<DatabaseDescriptor> DatabaseDescriptorPtr;
+
+class TransformInfoI;
+
+class TransformDBDescriptor : public Descriptor
+{
+public:
+
+ TransformDBDescriptor(int, const DataFactoryPtr&, const ErrorReporterPtr&, const IceXML::Attributes&,
+ const Slice::UnitPtr&, const Slice::UnitPtr&);
+ ~TransformDBDescriptor();
+
+ virtual void addChild(const DescriptorPtr&);
+ virtual void validate();
+ virtual void execute(const SymbolTablePtr&, TransformInfo*);
+
+ void transform(const Ice::CommunicatorPtr&, Db*, DbTxn*, Db*, DbTxn*, bool);
+
+private:
+
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ DatabaseDescriptorPtr _database;
+ std::vector<DescriptorPtr> _children;
+ TransformInfoI* _info;
+};
+typedef IceUtil::Handle<TransformDBDescriptor> TransformDBDescriptorPtr;
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/TransformVisitor.cpp b/cpp/src/FreezeScript/TransformVisitor.cpp
new file mode 100644
index 00000000000..864b46dc66a
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformVisitor.cpp
@@ -0,0 +1,901 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/TransformVisitor.h>
+#include <FreezeScript/Util.h>
+
+using namespace std;
+
+FreezeScript::TransformVisitor::TransformVisitor(const DataPtr& src, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter, TransformInfo* info,
+ const string& context) :
+ _src(src), _factory(factory), _errorReporter(errorReporter), _info(info), _context(context)
+{
+ assert(_info != 0);
+}
+
+void
+FreezeScript::TransformVisitor::visitBoolean(const BooleanDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ BooleanDataPtr b = BooleanDataPtr::dynamicCast(_src);
+ if(b)
+ {
+ dest->setValue(b->getValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string v = s->getValue();
+ if(v == "true")
+ {
+ dest->setValue(true);
+ }
+ else if(v == "false")
+ {
+ dest->setValue(false);
+ }
+ else
+ {
+ conversionError(type, _src->getType(), v);
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitInteger(const IntegerDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ IntegerDataPtr i = IntegerDataPtr::dynamicCast(_src);
+ if(i)
+ {
+ dest->setValue(i->getValue(), false);
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string str = s->getValue();
+ string::size_type pos;
+ Ice::Long value;
+ if(IceUtil::stringToInt64(str, value, pos))
+ {
+ dest->setValue(value, false);
+ }
+ else
+ {
+ conversionError(type, _src->getType(), str);
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitDouble(const DoubleDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ DoubleDataPtr d = DoubleDataPtr::dynamicCast(_src);
+ if(d)
+ {
+ dest->setValue(d->doubleValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string str = s->stringValue();
+ const char* start = str.c_str();
+ char* end;
+ double v = strtod(start, &end);
+ if(errno == ERANGE)
+ {
+ rangeError(str, type);
+ }
+ else
+ {
+ while(*end)
+ {
+ if(!isspace(*end))
+ {
+ conversionError(type, _src->getType(), str);
+ return;
+ }
+ end++;
+ }
+ if(!*end)
+ {
+ dest->setValue(v);
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitString(const StringDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ BooleanDataPtr b = BooleanDataPtr::dynamicCast(_src);
+ IntegerDataPtr i = IntegerDataPtr::dynamicCast(_src);
+ DoubleDataPtr d = DoubleDataPtr::dynamicCast(_src);
+ EnumDataPtr e = EnumDataPtr::dynamicCast(_src);
+ ProxyDataPtr p = ProxyDataPtr::dynamicCast(_src);
+ if(s || b || i || d || e || p)
+ {
+ dest->setValue(_src->toString());
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitProxy(const ProxyDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ ProxyDataPtr p = ProxyDataPtr::dynamicCast(_src);
+ if(p)
+ {
+ dest->setValue(p->getValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ dest->setValue(s->getValue(), false);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitStruct(const StructDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ StructDataPtr s = StructDataPtr::dynamicCast(_src);
+ if(s && isCompatible(type, _src->getType()))
+ {
+ //
+ // Transform members with the same name.
+ //
+ DataMemberMap srcMap = s->getMembers();
+ DataMemberMap destMap = dest->getMembers();
+ string typeName = typeToString(type);
+ for(DataMemberMap::iterator p = destMap.begin(); p != destMap.end(); ++p)
+ {
+ DataMemberMap::iterator q = srcMap.find(p->first);
+ if(q != srcMap.end())
+ {
+ string context = typeName + " member " + p->first + " value";
+ TransformVisitor v(q->second, _factory, _errorReporter, _info, context);
+ p->second->visit(v);
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitSequence(const SequenceDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ SequenceDataPtr s = SequenceDataPtr::dynamicCast(_src);
+ if(s && isCompatible(type, _src->getType()))
+ {
+ DataList& srcElements = s->getElements();
+ DataList destElements;
+ Slice::SequencePtr seqType = Slice::SequencePtr::dynamicCast(type);
+ assert(seqType);
+ Slice::TypePtr elemType = seqType->type();
+ string typeName = typeToString(type);
+ for(DataList::const_iterator p = srcElements.begin(); p != srcElements.end(); ++p)
+ {
+ DataPtr element = _factory->create(elemType, false);
+ Destroyer<DataPtr> elementDestroyer(element);
+ try
+ {
+ TransformVisitor v(*p, _factory, _errorReporter, _info, typeName + " element");
+ element->visit(v);
+ destElements.push_back(element);
+ elementDestroyer.release();
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the sequence element fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the sequence) or raise the exception again.
+ //
+ if(!_info->purgeObjects())
+ {
+ throw;
+ }
+ warning("purging element of sequence " + typeToString(type) +
+ " due to missing class type " + ex.id);
+ }
+ }
+ DataList& l = dest->getElements();
+ l.swap(destElements);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitEnum(const EnumDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ string name;
+ EnumDataPtr e = EnumDataPtr::dynamicCast(_src);
+ if(e && isCompatible(type, _src->getType()))
+ {
+ name = e->toString();
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ name = s->getValue();
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ return;
+ }
+ }
+
+ if(!dest->setValueAsString(name))
+ {
+ conversionError(type, _src->getType(), name);
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitDictionary(const DictionaryDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ DictionaryDataPtr d = DictionaryDataPtr::dynamicCast(_src);
+ if(d && isCompatible(type, _src->getType()))
+ {
+ DataMap& srcMap = d->getElements();
+ DataMap destMap;
+ Slice::DictionaryPtr dictType = Slice::DictionaryPtr::dynamicCast(type);
+ assert(dictType);
+ Slice::TypePtr keyType = dictType->keyType();
+ Slice::TypePtr valueType = dictType->valueType();
+ string typeName = typeToString(type);
+ for(DataMap::const_iterator p = srcMap.begin(); p != srcMap.end(); ++p)
+ {
+ DataPtr key = _factory->create(keyType, false);
+ Destroyer<DataPtr> keyDestroyer(key);
+ DataPtr value = _factory->create(valueType, false);
+ Destroyer<DataPtr> valueDestroyer(value);
+
+ TransformVisitor keyVisitor(p->first, _factory, _errorReporter, _info, typeName + " key");
+ key->visit(keyVisitor);
+
+ try
+ {
+ TransformVisitor valueVisitor(p->second, _factory, _errorReporter, _info, typeName + " value");
+ value->visit(valueVisitor);
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the dictionary value fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the dictionary) or raise the exception again.
+ //
+ if(!_info->purgeObjects())
+ {
+ throw;
+ }
+ warning("purging element of dictionary " + typeToString(dictType) + " due to missing class type " +
+ ex.id);
+ continue;
+ }
+
+ DataMap::const_iterator q = destMap.find(key);
+ if(q != destMap.end())
+ {
+ warning("duplicate dictionary key in " + typeToString(dictType));
+ }
+ else
+ {
+ destMap.insert(DataMap::value_type(key, value));
+ keyDestroyer.release();
+ valueDestroyer.release();
+ }
+ }
+ DataMap& m = dest->getElements();
+ m.swap(destMap);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitObject(const ObjectRefPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ ObjectRefPtr src = ObjectRefPtr::dynamicCast(_src);
+ if(!src)
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ else if(_info->doDefaultTransform(type))
+ {
+ ObjectDataPtr srcValue = src->getValue();
+ Slice::TypePtr srcType = src->getType();
+ if(!srcValue)
+ {
+ //
+ // Allow a nil value from type Object.
+ //
+ if(Slice::BuiltinPtr::dynamicCast(srcType) || isCompatible(type, srcType))
+ {
+ dest->setValue(0);
+ }
+ else
+ {
+ typeMismatchError(type, srcType);
+ }
+ }
+ else
+ {
+ Slice::TypePtr srcValueType = srcValue->getType();
+ if(isCompatible(type, srcValueType))
+ {
+ //
+ // If the types are in the same Slice unit, then we can simply
+ // copy the reference. Otherwise, we check the object map to
+ // see if an equivalent object has already been created, and
+ // if not, then we have to create one.
+ //
+ if(type->unit().get() == srcValueType->unit().get())
+ {
+ dest->setValue(srcValue);
+ }
+ else
+ {
+ ObjectDataMap& objectDataMap = _info->getObjectDataMap();
+ ObjectDataMap::iterator p = objectDataMap.find(srcValue.get());
+ if(p != objectDataMap.end() && p->second)
+ {
+ dest->setValue(p->second);
+ }
+ else
+ {
+ //
+ // If the type has been renamed, we need to get its equivalent
+ // in the new Slice definitions.
+ //
+ Slice::TypePtr newType = _info->getRenamedType(srcValueType);
+ if(!newType)
+ {
+ string name = typeToString(srcValueType);
+ Slice::TypeList l = type->unit()->lookupType(name, false);
+ if(l.empty())
+ {
+ throw ClassNotFoundException(name);
+ }
+ newType = l.front();
+ }
+
+ //
+ // Use createObject() so that an initializer is invoked if necessary.
+ //
+ DataPtr newObj = _factory->createObject(newType, false);
+ ObjectRefPtr newRef = ObjectRefPtr::dynamicCast(newObj);
+ assert(newRef);
+
+ ObjectDataPtr newValue = newRef->getValue();
+ try
+ {
+ transformObject(newValue, srcValue);
+ }
+ catch(...)
+ {
+ newObj->destroy();
+ throw;
+ }
+
+ dest->setValue(newValue);
+ newObj->destroy();
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, srcValueType);
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::transformObject(const ObjectDataPtr& dest, const ObjectDataPtr& src)
+{
+ //
+ // The source object must be present in the object map (we currently don't support
+ // transforming two ObjectData instances from the same Slice unit - this transform
+ // would be handled by-reference at the ObjectRef level). We must update the object
+ // map before transforming members in order to handle cycles.
+ //
+ ObjectDataMap& objectDataMap = _info->getObjectDataMap();
+ ObjectDataMap::iterator p = objectDataMap.find(src.get());
+ assert(p != objectDataMap.end());
+ assert(p->second == 0);
+ objectDataMap.erase(p);
+ objectDataMap.insert(ObjectDataMap::value_type(src.get(), dest));
+
+ try
+ {
+ //
+ // Transform members with the same name.
+ //
+ DataMemberMap srcMap = src->getMembers();
+ DataMemberMap destMap = dest->getMembers();
+ string typeName = typeToString(dest->getType());
+ for(DataMemberMap::iterator p = destMap.begin(); p != destMap.end(); ++p)
+ {
+ DataMemberMap::iterator q = srcMap.find(p->first);
+ if(q != srcMap.end())
+ {
+ string context = typeName + " member " + p->first + " value";
+ TransformVisitor v(q->second, _factory, _errorReporter, _info, context);
+ p->second->visit(v);
+ }
+ }
+ }
+ catch(...)
+ {
+ objectDataMap.erase(p);
+ objectDataMap.insert(ObjectDataMap::value_type(src.get(), 0));
+ throw;
+ }
+}
+
+bool
+FreezeScript::TransformVisitor::checkRename(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ if(dest->unit().get() != src->unit().get())
+ {
+ Slice::TypePtr t = _info->getRenamedType(src);
+ return t.get() == dest.get();
+ }
+
+ return false;
+}
+
+bool
+FreezeScript::TransformVisitor::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ Slice::BuiltinPtr b1 = Slice::BuiltinPtr::dynamicCast(dest);
+ if(b1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ switch(b1->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindString:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindBool:
+ {
+ if(b2 && (b2->kind() == Slice::Builtin::KindBool || b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindString:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObjectProxy:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+
+ return false;
+ }
+ else if(Slice::EnumPtr::dynamicCast(src))
+ {
+ return true;
+ }
+ else if(Slice::ProxyPtr::dynamicCast(src))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindObject:
+ {
+ //
+ // Allow transformation from Object to class. Validation has to
+ // be done during transformation, when the actual type of
+ // an instance can be compared for compatibility with the
+ // new type.
+ //
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(src);
+ if(cl || (b2 && b2->kind() == Slice::Builtin::KindObject))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindObjectProxy:
+ {
+ Slice::ProxyPtr p = Slice::ProxyPtr::dynamicCast(src);
+ if(p || (b2 && b2->kind() == Slice::Builtin::KindObjectProxy) ||
+ (b2 && b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindLocalObject:
+ {
+ assert(false);
+ return false;
+ }
+ }
+
+ assert(false);
+ }
+
+ Slice::ClassDeclPtr cl1 = Slice::ClassDeclPtr::dynamicCast(dest);
+ if(cl1)
+ {
+ Slice::ClassDeclPtr cl2 = Slice::ClassDeclPtr::dynamicCast(src);
+ if(cl2 && checkClasses(cl1, cl2))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::StructPtr s1 = Slice::StructPtr::dynamicCast(dest);
+ if(s1)
+ {
+ if(checkRename(dest, src))
+ {
+ return true;
+ }
+
+ Slice::StructPtr s2 = Slice::StructPtr::dynamicCast(src);
+ if(s2 && s1->scoped() == s2->scoped())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::ProxyPtr p1 = Slice::ProxyPtr::dynamicCast(dest);
+ if(p1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ if(b2 && (b2->kind() == Slice::Builtin::KindObjectProxy || b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ Slice::ProxyPtr p2 = Slice::ProxyPtr::dynamicCast(src);
+ if(p2 && checkClasses(p1->_class(), p2->_class()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::DictionaryPtr d1 = Slice::DictionaryPtr::dynamicCast(dest);
+ if(d1)
+ {
+ Slice::DictionaryPtr d2 = Slice::DictionaryPtr::dynamicCast(src);
+ if(d2)
+ {
+ return isCompatible(d1->keyType(), d2->keyType()) &&
+ isCompatible(d1->valueType(), d2->valueType());
+ }
+
+ return false;
+ }
+
+ Slice::SequencePtr seq1 = Slice::SequencePtr::dynamicCast(dest);
+ if(seq1)
+ {
+ Slice::SequencePtr seq2 = Slice::SequencePtr::dynamicCast(src);
+ if(seq2)
+ {
+ return isCompatible(seq1->type(), seq2->type());
+ }
+
+ return false;
+ }
+
+ Slice::EnumPtr e1 = Slice::EnumPtr::dynamicCast(dest);
+ if(e1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ if(b2 && b2->kind() == Slice::Builtin::KindString)
+ {
+ return true;
+ }
+
+ if(checkRename(dest, src))
+ {
+ return true;
+ }
+
+ Slice::EnumPtr e2 = Slice::EnumPtr::dynamicCast(src);
+ if(e2 && e1->scoped() == e2->scoped())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ assert(false);
+ return false;
+}
+
+bool
+FreezeScript::TransformVisitor::checkClasses(const Slice::ClassDeclPtr& dest, const Slice::ClassDeclPtr& src)
+{
+ //
+ // Here are the rules for verifying class compatibility:
+ //
+ // 1. If the type ids are the same, assume they are compatible.
+ // 2. If the source type has been renamed, then check its equivalent new definition for compatibility.
+ // 3. Otherwise, the types are only compatible if they are defined in the same Slice unit, and if the
+ // destination type is a base type of the source type.
+ //
+ string s1 = dest->scoped();
+ string s2 = src->scoped();
+ if(s1 == s2)
+ {
+ return true;
+ }
+ else
+ {
+ Slice::TypePtr t = _info->getRenamedType(src);
+ Slice::ClassDeclPtr s = Slice::ClassDeclPtr::dynamicCast(t);
+ if(s)
+ {
+ return checkClasses(dest, s);
+ }
+
+ if(dest->unit().get() != src->unit().get())
+ {
+ Slice::TypeList l = dest->unit()->lookupTypeNoBuiltin(s2, false);
+ if(l.empty())
+ {
+ _errorReporter->error("class " + s2 + " not found in new Slice definitions");
+ }
+ s = Slice::ClassDeclPtr::dynamicCast(l.front());
+ }
+ else
+ {
+ s = src;
+ }
+
+ if(s)
+ {
+ Slice::ClassDefPtr def = s->definition();
+ if(!def)
+ {
+ _errorReporter->error("class " + s2 + " declared but not defined");
+ }
+ return def->isA(s1);
+ }
+ }
+
+ return false;
+}
+
+void
+FreezeScript::TransformVisitor::typeMismatchError(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ ostringstream ostr;
+ ostr << "unable to transform";
+ if(!_context.empty())
+ {
+ ostr << ' ' << _context;
+ }
+ ostr << " from " << typeToString(src) << " to " << typeToString(dest);
+ warning(ostr.str());
+}
+
+void
+FreezeScript::TransformVisitor::conversionError(const Slice::TypePtr& dest, const Slice::TypePtr& src,
+ const string& value)
+{
+ ostringstream ostr;
+ ostr << "unable to convert";
+ if(!_context.empty())
+ {
+ ostr << ' ' << _context;
+ }
+ ostr << " `" << value << "' from " << typeToString(src) << " to " << typeToString(dest);
+ warning(ostr.str());
+}
+
+void
+FreezeScript::TransformVisitor::rangeError(const string& value, const Slice::TypePtr& type)
+{
+ ostringstream ostr;
+ if(!_context.empty())
+ {
+ ostr << _context << ' ';
+ }
+ ostr << "`" << value << "' is out of range for type " << typeToString(type);
+ warning(ostr.str());
+}
+
+void
+FreezeScript::TransformVisitor::warning(const string& msg)
+{
+ _errorReporter->warning(msg);
+}
diff --git a/cpp/src/FreezeScript/TransformVisitor.h b/cpp/src/FreezeScript/TransformVisitor.h
new file mode 100644
index 00000000000..6abf97509d6
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformVisitor.h
@@ -0,0 +1,112 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_TRANSFORM_VISITOR_H
+#define FREEZE_SCRIPT_TRANSFORM_VISITOR_H
+
+#include <FreezeScript/Data.h>
+
+namespace FreezeScript
+{
+
+//
+// ObjectDataMap associates old instances of ObjectData to their
+// transformed equivalents.
+//
+typedef std::map<const ObjectData*, ObjectDataPtr> ObjectDataMap;
+
+//
+// TransformInfo supplies information required by TransformVisitor.
+//
+class TransformInfo
+{
+public:
+
+ virtual ~TransformInfo() {}
+
+ //
+ // Indicates whether the default transformation should be performed.
+ //
+ virtual bool doDefaultTransform(const Slice::TypePtr&) = 0;
+
+ //
+ // Indicates whether a base class transformation should be performed.
+ //
+ virtual bool doBaseTransform(const Slice::ClassDefPtr&) = 0;
+
+ //
+ // Given an old type, return the equivalent new type if the type
+ // has been renamed.
+ //
+ virtual Slice::TypePtr getRenamedType(const Slice::TypePtr&) = 0;
+
+ //
+ // Execute the custom transformation for the given old and new Data values.
+ //
+ virtual void executeCustomTransform(const DataPtr&, const DataPtr&) = 0;
+
+ //
+ // Indicates whether objects should be removed if no class definition is found.
+ //
+ virtual bool purgeObjects() = 0;
+
+ //
+ // Associates old object instances with their transformed equivalents.
+ //
+ virtual ObjectDataMap& getObjectDataMap() = 0;
+};
+
+//
+// TransformVisitor is used to visit a destination Data value and
+// preserve as much information as possible from the source Data value.
+//
+class TransformVisitor : public DataVisitor
+{
+public:
+
+ TransformVisitor(const DataPtr&, const DataFactoryPtr&, const ErrorReporterPtr&, TransformInfo*,
+ const std::string& = std::string());
+
+ virtual void visitBoolean(const BooleanDataPtr&);
+ virtual void visitInteger(const IntegerDataPtr&);
+ virtual void visitDouble(const DoubleDataPtr&);
+ virtual void visitString(const StringDataPtr&);
+ virtual void visitProxy(const ProxyDataPtr&);
+ virtual void visitStruct(const StructDataPtr&);
+ virtual void visitSequence(const SequenceDataPtr&);
+ virtual void visitEnum(const EnumDataPtr&);
+ virtual void visitDictionary(const DictionaryDataPtr&);
+ virtual void visitObject(const ObjectRefPtr&);
+
+private:
+
+ void transformObject(const ObjectDataPtr&, const ObjectDataPtr&);
+ bool checkRename(const Slice::TypePtr&, const Slice::TypePtr&);
+ bool isCompatible(const Slice::TypePtr&, const Slice::TypePtr&);
+ bool checkClasses(const Slice::ClassDeclPtr&, const Slice::ClassDeclPtr&);
+ void typeMismatchError(const Slice::TypePtr&, const Slice::TypePtr&);
+ void conversionError(const Slice::TypePtr&, const Slice::TypePtr&, const std::string&);
+ void rangeError(const std::string&, const Slice::TypePtr&);
+ void warning(const std::string&);
+
+ DataPtr _src;
+ DataFactoryPtr _factory;
+ ErrorReporterPtr _errorReporter;
+ TransformInfo* _info;
+ std::string _context; // Provides additional detail for use in warning messages.
+};
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Transformer.cpp b/cpp/src/FreezeScript/Transformer.cpp
new file mode 100644
index 00000000000..01a1c7519f1
--- /dev/null
+++ b/cpp/src/FreezeScript/Transformer.cpp
@@ -0,0 +1,310 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Transformer.h>
+#include <FreezeScript/TransformDescriptors.h>
+#include <FreezeScript/Exception.h>
+#include <FreezeScript/TransformAnalyzer.h>
+#include <FreezeScript/Util.h>
+#include <db_cxx.h>
+
+using namespace std;
+
+namespace FreezeScript
+{
+
+class DescriptorHandler : public IceXML::Handler
+{
+public:
+
+ DescriptorHandler(const DataFactoryPtr&, const Slice::UnitPtr&, const Slice::UnitPtr&, const ErrorReporterPtr&);
+
+ virtual void startElement(const std::string&, const IceXML::Attributes&, int, int);
+ virtual void endElement(const std::string&, int, int);
+ virtual void characters(const std::string&, int, int);
+ virtual void error(const std::string&, int, int);
+
+ TransformDBDescriptorPtr descriptor() const;
+
+private:
+
+ DataFactoryPtr _factory;
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ ErrorReporterPtr _errorReporter;
+ DescriptorPtr _current;
+ TransformDBDescriptorPtr _descriptor;
+};
+
+} // End of namespace FreezeScript
+
+//
+// DescriptorHandler
+//
+FreezeScript::DescriptorHandler::DescriptorHandler(const DataFactoryPtr& factory, const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit,
+ const ErrorReporterPtr& errorReporter) :
+ _factory(factory), _old(oldUnit), _new(newUnit), _errorReporter(errorReporter)
+{
+}
+
+void
+FreezeScript::DescriptorHandler::startElement(const string& name, const IceXML::Attributes& attributes, int line,
+ int column)
+{
+ DescriptorPtr d;
+
+ if(name == "transformdb")
+ {
+ if(_current)
+ {
+ _errorReporter->descriptorError("<transformdb> must be the top-level element", line);
+ }
+
+ _descriptor = new TransformDBDescriptor(line, _factory, _errorReporter, attributes, _old, _new);
+ d = _descriptor;
+ }
+ else if(name == "database")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<database> must be a child of <transformdb>", line);
+ }
+
+ d = new DatabaseDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "record")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<record> must be a child of <database>", line);
+ }
+
+ d = new RecordDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "transform")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<transform> must be a child of <transformdb>", line);
+ }
+
+ d = new TransformDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "init")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<init> must be a child of <transformdb>", line);
+ }
+
+ d = new InitDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "set")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<set> cannot be a top-level element", line);
+ }
+
+ d = new SetDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "define")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<define> cannot be a top-level element", line);
+ }
+
+ d = new DefineDescriptor(_current, line, _factory, _errorReporter, attributes, _old, _new);
+ }
+ else if(name == "add")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<add> cannot be a top-level element", line);
+ }
+
+ d = new AddDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "remove")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<remove> cannot be a top-level element", line);
+ }
+
+ d = new RemoveDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "delete")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<delete> cannot be a top-level element", line);
+ }
+
+ d = new DeleteDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "fail")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<fail> cannot be a top-level element", line);
+ }
+
+ d = new FailDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "echo")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<echo> cannot be a top-level element", line);
+ }
+
+ d = new EchoDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "if")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<if> cannot be a top-level element", line);
+ }
+
+ d = new IfDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else if(name == "iterate")
+ {
+ if(!_current)
+ {
+ _errorReporter->descriptorError("<iterate> cannot be a top-level element", line);
+ }
+
+ d = new IterateDescriptor(_current, line, _factory, _errorReporter, attributes);
+ }
+ else
+ {
+ _errorReporter->descriptorError("unknown descriptor `" + name + "'", line);
+ }
+
+ if(_current)
+ {
+ _current->addChild(d);
+ }
+ _current = d;
+}
+
+void
+FreezeScript::DescriptorHandler::endElement(const std::string& name, int, int)
+{
+ assert(_current);
+ _current = _current->parent();
+}
+
+void
+FreezeScript::DescriptorHandler::characters(const std::string&, int, int)
+{
+}
+
+void
+FreezeScript::DescriptorHandler::error(const std::string& msg, int line, int col)
+{
+ _errorReporter->descriptorError(msg, line);
+}
+
+FreezeScript::TransformDBDescriptorPtr
+FreezeScript::DescriptorHandler::descriptor() const
+{
+ return _descriptor;
+}
+
+//
+// Transformer
+//
+FreezeScript::Transformer::Transformer(const Ice::CommunicatorPtr& communicator, const Slice::UnitPtr& oldUnit,
+ const Slice::UnitPtr& newUnit, bool ignoreTypeChanges, bool purgeObjects) :
+ _communicator(communicator), _old(oldUnit), _new(newUnit), _ignoreTypeChanges(ignoreTypeChanges),
+ _purgeObjects(purgeObjects)
+{
+ createCoreSliceTypes(_old);
+ createCoreSliceTypes(_new);
+
+ createEvictorSliceTypes(_old);
+ createEvictorSliceTypes(_new);
+}
+
+void
+FreezeScript::Transformer::analyze(const string& oldKey, const string& newKey, const string& oldValue,
+ const string& newValue, ostream& descriptors, Ice::StringSeq& missingTypes,
+ Ice::StringSeq& errors)
+{
+ //
+ // Look up the Slice definitions for the key and value types.
+ //
+ Slice::TypePtr oldKeyType = findType(_old, oldKey, errors);
+ Slice::TypePtr newKeyType = findType(_new, newKey, errors);
+ Slice::TypePtr oldValueType = findType(_old, oldValue, errors);
+ Slice::TypePtr newValueType = findType(_new, newValue, errors);
+ if(!oldKeyType || !newKeyType || !oldValueType || !newValueType)
+ {
+ return;
+ }
+
+ TransformAnalyzer analyzer(_old, _new, _ignoreTypeChanges);
+ analyzer.analyze(oldKeyType, newKeyType, oldValueType, newValueType, descriptors, missingTypes, errors);
+}
+
+void
+FreezeScript::Transformer::analyze(ostream& descriptors, Ice::StringSeq& missingTypes, Ice::StringSeq& errors)
+{
+ const string keyType = "::Freeze::EvictorStorageKey";
+ const string valueType = "::Freeze::ObjectRecord";
+ analyze(keyType, keyType, valueType, valueType, descriptors, missingTypes, errors);
+}
+
+void
+FreezeScript::Transformer::transform(istream& is, Db* db, DbTxn* txn, Db* dbNew, DbTxn* txnNew, ostream& errors,
+ bool suppress)
+{
+ ErrorReporterPtr errorReporter = new ErrorReporter(errors, suppress);
+
+ try
+ {
+ DataFactoryPtr factory = new DataFactory(_communicator, _new, errorReporter);
+ DescriptorHandler dh(factory, _old, _new, errorReporter);
+ IceXML::Parser::parse(is, dh);
+
+ TransformDBDescriptorPtr descriptor = dh.descriptor();
+ descriptor->validate();
+ descriptor->transform(_communicator, db, txn, dbNew, txnNew, _purgeObjects);
+ }
+ catch(const IceXML::ParserException& ex)
+ {
+ errorReporter->error(ex.reason());
+ }
+}
+
+Slice::TypePtr
+FreezeScript::Transformer::findType(const Slice::UnitPtr& u, const string& type, Ice::StringSeq& errors)
+{
+ Slice::TypeList l;
+
+ l = u->lookupType(type, false);
+ if(l.empty())
+ {
+ errors.push_back("error: unknown type `" + type + "'");
+ return 0;
+ }
+
+ return l.front();
+}
diff --git a/cpp/src/FreezeScript/Transformer.h b/cpp/src/FreezeScript/Transformer.h
new file mode 100644
index 00000000000..1bdaa56fc81
--- /dev/null
+++ b/cpp/src/FreezeScript/Transformer.h
@@ -0,0 +1,54 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_TRANSFORMER_H
+#define FREEZE_SCRIPT_TRANSFORMER_H
+
+#include <Ice/Ice.h>
+#include <Slice/Parser.h>
+#include <FreezeScript/Exception.h>
+
+class Db;
+class DbTxn;
+
+namespace FreezeScript
+{
+
+class Transformer
+{
+public:
+
+ Transformer(const Ice::CommunicatorPtr&, const Slice::UnitPtr&, const Slice::UnitPtr&, bool, bool);
+
+ void analyze(const std::string&, const std::string&, const std::string&, const std::string&, std::ostream&,
+ Ice::StringSeq&, Ice::StringSeq&);
+
+ void analyze(std::ostream&, Ice::StringSeq&, Ice::StringSeq&);
+
+ void transform(std::istream&, Db*, DbTxn*, Db*, DbTxn*, std::ostream&, bool);
+
+private:
+
+ static Slice::TypePtr findType(const Slice::UnitPtr&, const std::string&, Ice::StringSeq&);
+
+ Ice::CommunicatorPtr _communicator;
+ Slice::UnitPtr _old;
+ Slice::UnitPtr _new;
+ bool _ignoreTypeChanges;
+ bool _purgeObjects;
+};
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/Util.cpp b/cpp/src/FreezeScript/Util.cpp
new file mode 100644
index 00000000000..9012bf63cea
--- /dev/null
+++ b/cpp/src/FreezeScript/Util.cpp
@@ -0,0 +1,273 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Util.h>
+#include <FreezeScript/Exception.h>
+#include <Slice/Preprocessor.h>
+
+using namespace std;
+using namespace Slice;
+
+string
+FreezeScript::typeToString(const TypePtr& type)
+{
+ BuiltinPtr b = BuiltinPtr::dynamicCast(type);
+ ContainedPtr c = ContainedPtr::dynamicCast(type);
+ ProxyPtr p = ProxyPtr::dynamicCast(type);
+ if(b)
+ {
+ return b->kindAsString();
+ }
+ else if(c)
+ {
+ return c->scoped();
+ }
+ else
+ {
+ ProxyPtr p = ProxyPtr::dynamicCast(type);
+ assert(p);
+ return p->_class()->scoped() + "*";
+ }
+}
+
+bool
+FreezeScript::ignoreType(const string& type)
+{
+ //
+ // Suppress descriptors for the following pre-defined types. Must be kept in ascending alphabetical order.
+ //
+ static const string ignoreTypeList[] =
+ {
+ "::Freeze::EvictorStorageKey",
+ "::Freeze::ObjectRecord",
+ "::Freeze::Statistics",
+ "::Ice::FacetPath",
+ "::Ice::Identity",
+ "::_FacetMap"
+ };
+
+ return binary_search(&ignoreTypeList[0], &ignoreTypeList[sizeof(ignoreTypeList) / sizeof(*ignoreTypeList)], type);
+}
+
+void
+FreezeScript::createCoreSliceTypes(const Slice::UnitPtr& unit)
+{
+ string scoped;
+ Slice::TypeList l;
+ Slice::ContainedList c;
+
+ //
+ // Create the Slice definition for _FacetMap if it doesn't exist. This type is
+ // necessary for marshaling an object's facet map.
+ //
+ l = unit->lookupTypeNoBuiltin("::_FacetMap", false);
+ if(l.empty())
+ {
+ Slice::TypePtr str = unit->builtin(Slice::Builtin::KindString);
+ Slice::TypePtr obj = unit->builtin(Slice::Builtin::KindObject);
+ unit->createDictionary("_FacetMap", str, obj, false);
+ }
+ else
+ {
+ assert(Slice::DictionaryPtr::dynamicCast(l.front()));
+ }
+}
+
+void
+FreezeScript::createEvictorSliceTypes(const Slice::UnitPtr& unit)
+{
+ string scoped;
+ Slice::TypeList l;
+ Slice::ContainedList c;
+
+ //
+ // Create the Ice module if necessary.
+ //
+ c = unit->lookupContained("Ice", false);
+ Slice::ModulePtr ice;
+ if(c.empty())
+ {
+ ice = unit->createModule("Ice");
+ }
+ else
+ {
+ ice = Slice::ModulePtr::dynamicCast(c.front());
+ if(!ice)
+ {
+ throw Exception(__FILE__, __LINE__, "the symbol `::Ice' is defined in Slice but is not a module");
+ }
+ }
+
+ //
+ // Create the Slice definition for Ice::Identity if it doesn't exist.
+ //
+ scoped = "::Ice::Identity";
+ l = unit->lookupTypeNoBuiltin(scoped, false);
+ Slice::StructPtr identity;
+ if(l.empty())
+ {
+ identity = ice->createStruct("Identity", false);
+ Slice::TypePtr str = unit->builtin(Slice::Builtin::KindString);
+ identity->createDataMember("category", str);
+ identity->createDataMember("name", str);
+ }
+ else
+ {
+ identity = Slice::StructPtr::dynamicCast(l.front());
+ if(!identity)
+ {
+ throw Exception(__FILE__, __LINE__, "the symbol `::Ice::Identity' is defined in Slice but is not a struct");
+ }
+ }
+
+ //
+ // Create the Slice definition for Ice::FacetPath if it doesn't exist.
+ //
+ scoped = "::Ice::FacetPath";
+ l = unit->lookupTypeNoBuiltin(scoped, false);
+ Slice::SequencePtr facetPath;
+ if(l.empty())
+ {
+ Slice::TypePtr str = unit->builtin(Slice::Builtin::KindString);
+ facetPath = ice->createSequence("FacetPath", str, false);
+ }
+ else
+ {
+ facetPath = Slice::SequencePtr::dynamicCast(l.front());
+ if(!facetPath)
+ {
+ throw Exception(__FILE__, __LINE__,
+ "the symbol `::Ice::FacetPath' is defined in Slice but is not a sequence");
+ }
+ }
+
+ //
+ // Create the Freeze module if necessary.
+ //
+ c = unit->lookupContained("Freeze", false);
+ Slice::ModulePtr freeze;
+ if(c.empty())
+ {
+ freeze = unit->createModule("Freeze");
+ }
+ else
+ {
+ freeze = Slice::ModulePtr::dynamicCast(c.front());
+ if(!freeze)
+ {
+ throw Exception(__FILE__, __LINE__, "the symbol `::Freeze' is defined in Slice but is not a module");
+ }
+ }
+
+ //
+ // Create the Slice definition for Freeze::EvictorStorageKey if it doesn't exist.
+ //
+ scoped = "::Freeze::EvictorStorageKey";
+ l = unit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ Slice::StructPtr esk = freeze->createStruct("EvictorStorageKey", false);
+ esk->createDataMember("identity", identity);
+ esk->createDataMember("facet", facetPath);
+ }
+ else
+ {
+ if(!Slice::StructPtr::dynamicCast(l.front()))
+ {
+ throw Exception(__FILE__, __LINE__, "the symbol `::Freeze::EvictorStorageKey' is defined in "
+ "Slice but is not a struct");
+ }
+ }
+
+ //
+ // Create the Slice definition for Freeze::Statistics if it doesn't exist.
+ //
+ scoped = "::Freeze::Statistics";
+ l = unit->lookupTypeNoBuiltin(scoped, false);
+ Slice::StructPtr stats;
+ if(l.empty())
+ {
+ stats = freeze->createStruct("Statistics", false);
+ Slice::TypePtr tl = unit->builtin(Slice::Builtin::KindLong);
+ stats->createDataMember("creationTime", tl);
+ stats->createDataMember("lastSaveTime", tl);
+ stats->createDataMember("avgSaveTime", tl);
+ }
+ else
+ {
+ stats = Slice::StructPtr::dynamicCast(l.front());
+ if(!stats)
+ {
+ throw Exception(__FILE__, __LINE__, "the symbol `::Freeze::Statistics' is defined in "
+ "Slice but is not a struct");
+ }
+ }
+
+ //
+ // Create the Slice definition for Freeze::ObjectRecord if it doesn't exist.
+ //
+ scoped = "::Freeze::ObjectRecord";
+ l = unit->lookupTypeNoBuiltin(scoped, false);
+ if(l.empty())
+ {
+ Slice::StructPtr rec = freeze->createStruct("ObjectRecord", false);
+ Slice::TypePtr obj = unit->builtin(Slice::Builtin::KindObject);
+ rec->createDataMember("servant", obj);
+ rec->createDataMember("stats", stats);
+ }
+ else
+ {
+ if(!Slice::StructPtr::dynamicCast(l.front()))
+ {
+ throw Exception(__FILE__, __LINE__, "the symbol `::Freeze::ObjectRecord' is defined in "
+ "Slice but is not a struct");
+ }
+ }
+}
+
+bool
+FreezeScript::parseSlice(const string& n, const Slice::UnitPtr& u, const vector<string>& files, const string& cppArgs,
+ bool debug)
+{
+ //
+ // Parse the Slice files.
+ //
+ for(vector<string>::const_iterator p = files.begin(); p != files.end(); ++p)
+ {
+ Preprocessor icecpp(n, *p, cppArgs);
+
+ FILE* cppHandle = icecpp.preprocess(false);
+
+ if(cppHandle == 0)
+ {
+ return false;
+ }
+
+ int status = u->parse(cppHandle, debug);
+
+ if(!icecpp.close())
+ {
+ return false;
+ }
+
+ if(status != EXIT_SUCCESS)
+ {
+ return false;
+ }
+ }
+
+ u->mergeModules();
+
+ return true;
+}
diff --git a/cpp/src/FreezeScript/Util.h b/cpp/src/FreezeScript/Util.h
new file mode 100644
index 00000000000..e180c775e1f
--- /dev/null
+++ b/cpp/src/FreezeScript/Util.h
@@ -0,0 +1,66 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef FREEZE_SCRIPT_UTIL_H
+#define FREEZE_SCRIPT_UTIL_H
+
+#include <Slice/Parser.h>
+
+namespace FreezeScript
+{
+
+template<class T>
+class Destroyer
+{
+public:
+
+ Destroyer() {}
+ Destroyer(T p) : _p(p) {}
+ ~Destroyer()
+ {
+ if(_p)
+ {
+ _p->destroy();
+ }
+ }
+
+ void set(T p)
+ {
+ if(_p)
+ {
+ _p->destroy();
+ }
+ _p = p;
+ }
+
+ void release()
+ {
+ _p = 0;
+ }
+
+private:
+
+ T _p;
+};
+
+std::string typeName(const Slice::TypePtr&);
+std::string typeToString(const Slice::TypePtr&);
+bool ignoreType(const std::string&);
+void createCoreSliceTypes(const Slice::UnitPtr&);
+void createEvictorSliceTypes(const Slice::UnitPtr&);
+bool parseSlice(const std::string&, const Slice::UnitPtr&, const std::vector<std::string>&, const std::string&, bool);
+
+} // End of namespace FreezeScript
+
+#endif
diff --git a/cpp/src/FreezeScript/transformdb.cpp b/cpp/src/FreezeScript/transformdb.cpp
new file mode 100644
index 00000000000..b85365a8cb7
--- /dev/null
+++ b/cpp/src/FreezeScript/transformdb.cpp
@@ -0,0 +1,645 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/Transformer.h>
+#include <FreezeScript/Util.h>
+#include <db_cxx.h>
+#include <sys/stat.h>
+#include <fstream>
+#include <algorithm>
+
+using namespace std;
+
+#ifdef _WIN32
+# define FREEZE_SCRIPT_DB_MODE 0
+#else
+# define FREEZE_SCRIPT_DB_MODE (S_IRUSR | S_IWUSR)
+#endif
+
+static void
+usage(const char* n)
+{
+ cerr << "Usage: " << n << " [options] [dbenv db newdbenv]\n";
+ cerr <<
+ "Options:\n"
+ "-h, --help Show this message.\n"
+ "-v, --version Display the Ice version.\n"
+ "-DNAME Define NAME as 1.\n"
+ "-DNAME=DEF Define NAME as DEF.\n"
+ "-UNAME Remove any definition for NAME.\n"
+ "-d, --debug Print debug messages.\n"
+ "--ice Permit `Ice' prefix (for building Ice source code only)\n"
+ "-o FILE Output transformation descriptors into the file FILE.\n"
+ " Database transformation is not performed.\n"
+ "-i Ignore incompatible type changes.\n"
+ "-p Purge objects whose types no longer exist.\n"
+ "-c Use catastrophic recovery on the old database environment.\n"
+ "-w Suppress duplicate warnings during transformation.\n"
+ "-f FILE Execute the transformation descriptors in the file FILE.\n"
+ "--include-old DIR Put DIR in the include file search path for old Slice\n"
+ " definitions.\n"
+ "--include-new DIR Put DIR in the include file search path for new Slice\n"
+ " definitions.\n"
+ "--old SLICE Load old Slice definitions from the file SLICE.\n"
+ "--new SLICE Load new Slice definitions from the file SLICE.\n"
+ "-e Indicates the database is an Evictor database.\n"
+ "--key TYPE[,TYPE] Specifies the Slice types of the database key. If the\n"
+ " type names have not changed, only one needs to be\n"
+ " specified. Otherwise, the type names are specified as\n"
+ " old-type,new-type.\n"
+ "--value TYPE[,TYPE] Specifies the Slice types of the database value. If the\n"
+ " type names have not changed, only one needs to be\n"
+ " specified. Otherwise, the type names are specified as\n"
+ " old-type,new-type.\n"
+ ;
+ // Note: --case-sensitive is intentionally not shown here!
+}
+
+static int
+run(int argc, char** argv, const Ice::CommunicatorPtr& communicator)
+{
+ string oldCppArgs;
+ string newCppArgs;
+ bool debug = false;
+ bool ice = true; // Needs to be true in order to create default definitions.
+ bool caseSensitive = false;
+ string outputFile;
+ bool ignoreTypeChanges = false;
+ bool purgeObjects = false;
+ bool catastrophicRecover = false;
+ bool suppress = false;
+ string inputFile;
+ vector<string> oldSlice;
+ vector<string> newSlice;
+ bool evictor = false;
+ string keyTypeNames;
+ string valueTypeNames;
+ string dbEnvName, dbName, dbEnvNameNew;
+
+ int idx = 1;
+ while(idx < argc)
+ {
+ if(strcmp(argv[idx], "-h") == 0 || strcmp(argv[idx], "--help") == 0)
+ {
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+ else if(strcmp(argv[idx], "-v") == 0 || strcmp(argv[idx], "--version") == 0)
+ {
+ cout << ICE_STRING_VERSION << endl;
+ return EXIT_SUCCESS;
+ }
+ else if(strncmp(argv[idx], "-D", 2) == 0 || strncmp(argv[idx], "-U", 2) == 0)
+ {
+ oldCppArgs += ' ';
+ oldCppArgs += argv[idx];
+ newCppArgs += ' ';
+ newCppArgs += argv[idx];
+
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-d") == 0 || strcmp(argv[idx], "--debug") == 0)
+ {
+ debug = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--ice") == 0)
+ {
+ ice = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--case-sensitive") == 0)
+ {
+ caseSensitive = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-o") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ outputFile = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "-i") == 0)
+ {
+ ignoreTypeChanges = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-p") == 0)
+ {
+ purgeObjects = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-c") == 0)
+ {
+ catastrophicRecover = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-w") == 0)
+ {
+ suppress = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-f") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ inputFile = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--include-old") == 0)
+ {
+ oldCppArgs += " -I";
+ oldCppArgs += argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--include-new") == 0)
+ {
+ newCppArgs += " -I";
+ newCppArgs += argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--old") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ oldSlice.push_back(argv[idx + 1]);
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--new") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ newSlice.push_back(argv[idx + 1]);
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "-e") == 0)
+ {
+ evictor = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--key") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ keyTypeNames = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--value") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ valueTypeNames = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(argv[idx][0] == '-')
+ {
+ cerr << argv[0] << ": unknown option `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ ++idx;
+ }
+ }
+
+ if(outputFile.empty() && argc < 4)
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if(argc > 1)
+ {
+ dbEnvName = argv[1];
+ }
+ if(argc > 2)
+ {
+ dbName = argv[2];
+ }
+ if(argc > 3)
+ {
+ dbEnvNameNew = argv[3];
+ }
+
+ Slice::UnitPtr oldUnit = Slice::Unit::createUnit(true, true, ice, caseSensitive);
+ FreezeScript::Destroyer<Slice::UnitPtr> oldD(oldUnit);
+ if(!FreezeScript::parseSlice(argv[0], oldUnit, oldSlice, oldCppArgs, debug))
+ {
+ return EXIT_FAILURE;
+ }
+
+ Slice::UnitPtr newUnit = Slice::Unit::createUnit(true, true, ice, caseSensitive);
+ FreezeScript::Destroyer<Slice::UnitPtr> newD(newUnit);
+ if(!FreezeScript::parseSlice(argv[0], newUnit, newSlice, newCppArgs, debug))
+ {
+ return EXIT_FAILURE;
+ }
+
+ //
+ // Create the Transformer.
+ //
+ FreezeScript::Transformer transformer(communicator, oldUnit, newUnit, ignoreTypeChanges, purgeObjects);
+
+ //
+ // If no input file was provided, then we need to analyze the Slice types.
+ //
+ string descriptors;
+ if(inputFile.empty())
+ {
+ ostringstream out;
+ vector<string> missingTypes;
+ vector<string> analyzeErrors;
+
+ if(evictor)
+ {
+ transformer.analyze(out, missingTypes, analyzeErrors);
+ }
+ else
+ {
+ string oldKeyName, newKeyName, oldValueName, newValueName;
+ string::size_type pos;
+
+ if(keyTypeNames.empty() || valueTypeNames.empty())
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ pos = keyTypeNames.find(',');
+ if(pos == 0 || pos == keyTypeNames.size())
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ if(pos == string::npos)
+ {
+ oldKeyName = keyTypeNames;
+ newKeyName = keyTypeNames;
+ }
+ else
+ {
+ oldKeyName = keyTypeNames.substr(0, pos);
+ newKeyName = keyTypeNames.substr(pos + 1);
+ }
+
+ pos = valueTypeNames.find(',');
+ if(pos == 0 || pos == valueTypeNames.size())
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ if(pos == string::npos)
+ {
+ oldValueName = valueTypeNames;
+ newValueName = valueTypeNames;
+ }
+ else
+ {
+ oldValueName = valueTypeNames.substr(0, pos);
+ newValueName = valueTypeNames.substr(pos + 1);
+ }
+
+ transformer.analyze(oldKeyName, newKeyName, oldValueName, newValueName, out, missingTypes, analyzeErrors);
+ }
+
+ if(!analyzeErrors.empty())
+ {
+ for(vector<string>::const_iterator p = analyzeErrors.begin(); p != analyzeErrors.end(); ++p)
+ {
+ cerr << argv[0] << ": " << *p << endl;
+ }
+ }
+
+ if(!missingTypes.empty())
+ {
+ sort(missingTypes.begin(), missingTypes.end());
+ unique(missingTypes.begin(), missingTypes.end());
+ if(!analyzeErrors.empty())
+ {
+ cerr << endl;
+ }
+ cerr << "The following types had no matching definitions in the new Slice:" << endl;
+ for(vector<string>::const_iterator p = missingTypes.begin(); p != missingTypes.end(); ++p)
+ {
+ cerr << " " << *p << endl;
+ }
+ }
+
+ if(!analyzeErrors.empty())
+ {
+ return EXIT_FAILURE;
+ }
+
+ descriptors = out.str();
+
+ if(!outputFile.empty())
+ {
+ ofstream of(outputFile.c_str());
+ if(!of.good())
+ {
+ cerr << argv[0] << ": unable to open file `" << outputFile << "'" << endl;
+ return EXIT_FAILURE;
+ }
+ of << descriptors;
+ of.close();
+ return EXIT_SUCCESS;
+ }
+ }
+ else
+ {
+ ifstream in(inputFile.c_str());
+ char buff[1024];
+ while(true)
+ {
+ in.read(buff, 1024);
+ descriptors.append(buff, in.gcount());
+ if(in.gcount() < 1024)
+ {
+ break;
+ }
+ }
+ in.close();
+ }
+
+ if(dbEnvName == dbEnvNameNew)
+ {
+ cerr << argv[0] << ": database environment names must be different" << endl;
+ return EXIT_FAILURE;
+ }
+
+ DbEnv dbEnv(0);
+ DbEnv dbEnvNew(0);
+ DbTxn* txn = 0;
+ DbTxn* txnNew = 0;
+ Db* db = 0;
+ Db* dbNew = 0;
+ int status = EXIT_SUCCESS;
+ try
+ {
+#ifdef _WIN32
+ //
+ // Berkeley DB may use a different C++ runtime.
+ //
+ dbEnv.set_alloc(::malloc, ::realloc, ::free);
+ dbEnvNew.set_alloc(::malloc, ::realloc, ::free);
+#endif
+
+ //
+ // Open the old database environment. Use DB_RECOVER_FATAL if -c is specified.
+ //
+ {
+ u_int32_t flags = DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE;
+ if(catastrophicRecover)
+ {
+ flags |= DB_RECOVER_FATAL;
+ }
+ else
+ {
+ flags |= DB_RECOVER;
+ }
+ dbEnv.open(dbEnvName.c_str(), flags, FREEZE_SCRIPT_DB_MODE);
+ }
+
+ //
+ // Open the new database environment.
+ //
+ {
+ u_int32_t flags = DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_CREATE;
+ dbEnvNew.open(dbEnvNameNew.c_str(), flags, FREEZE_SCRIPT_DB_MODE);
+ }
+
+ //
+ // Open the old database in a transaction.
+ //
+ db = new Db(&dbEnv, 0);
+ dbEnv.txn_begin(0, &txn, 0);
+ db->open(txn, dbName.c_str(), 0, DB_BTREE, DB_RDONLY, FREEZE_SCRIPT_DB_MODE);
+
+ //
+ // Open the new database in a transaction.
+ //
+ dbNew = new Db(&dbEnvNew, 0);
+ dbEnvNew.txn_begin(0, &txnNew, 0);
+ dbNew->open(txnNew, dbName.c_str(), 0, DB_BTREE, DB_CREATE | DB_EXCL, FREEZE_SCRIPT_DB_MODE);
+
+ istringstream istr(descriptors);
+ transformer.transform(istr, db, txn, dbNew, txnNew, cerr, suppress);
+
+ //
+ // Checkpoint to migrate changes from the log to the database.
+ //
+ dbEnvNew.txn_checkpoint(0, 0, DB_FORCE);
+ }
+ catch(const DbException& ex)
+ {
+ cerr << argv[0] << ": database error: " << ex.what() << endl;
+ status = EXIT_FAILURE;
+ }
+ catch(...)
+ {
+ if(txn)
+ {
+ txn->abort();
+ }
+ if(db)
+ {
+ db->close(0);
+ delete db;
+ }
+ if(txnNew)
+ {
+ txnNew->abort();
+ }
+ if(dbNew)
+ {
+ dbNew->close(0);
+ delete dbNew;
+ }
+ dbEnv.close(0);
+ dbEnvNew.close(0);
+ throw;
+ }
+
+ if(txn)
+ {
+ txn->abort();
+ }
+ if(db)
+ {
+ db->close(0);
+ delete db;
+ }
+ if(txnNew)
+ {
+ if(status == EXIT_FAILURE)
+ {
+ txnNew->abort();
+ }
+ else
+ {
+ txnNew->commit(0);
+ }
+ }
+ if(dbNew)
+ {
+ dbNew->close(0);
+ delete dbNew;
+ }
+ dbEnv.close(0);
+ dbEnvNew.close(0);
+
+ return status;
+}
+
+int
+main(int argc, char* argv[])
+{
+ Ice::CommunicatorPtr communicator;
+ int status = EXIT_SUCCESS;
+ try
+ {
+ communicator = Ice::initialize(argc, argv);
+ status = run(argc, argv, communicator);
+ }
+ catch(const FreezeScript::Exception& ex)
+ {
+ string reason = ex.reason();
+ cerr << argv[0] << ": " << reason;
+ if(reason[reason.size() - 1] != '\n')
+ {
+ cerr << endl;
+ }
+ return EXIT_FAILURE;
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << argv[0] << ": " << ex << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(communicator)
+ {
+ communicator->destroy();
+ }
+
+ return status;
+}
diff --git a/cpp/src/FreezeScript/transformdb.dsp b/cpp/src/FreezeScript/transformdb.dsp
new file mode 100644
index 00000000000..9bbfbac1ba2
--- /dev/null
+++ b/cpp/src/FreezeScript/transformdb.dsp
@@ -0,0 +1,304 @@
+# Microsoft Developer Studio Project File - Name="TransformDB" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=TransformDB - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "TransformDB.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "TransformDB.mak" CFG="TransformDB - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "TransformDB - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "TransformDB - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "TransformDB - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /WX /GR /GX /O2 /I ".." /I "../../include" /I "dummyinclude" /D "NDEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdb41.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"Release/transformdb.exe" /libpath:"../../../lib"
+# SUBTRACT LINK32 /debug /nodefaultlib
+# Begin Special Build Tool
+OutDir=.\Release
+TargetName=transformdb
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\$(TargetName).exe ..\..\bin
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "TransformDB - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /WX /Gm /GR /GX /Zi /Od /I ".." /I "../../include" /I "dummyinclude" /D "_DEBUG" /D "_CONSOLE" /FD /GZ /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdb41d.lib setargv.obj /nologo /subsystem:console /debug /machine:I386 /out:"Debug/transformdb.exe" /pdbtype:sept /libpath:"../../../lib"
+# SUBTRACT LINK32 /nodefaultlib
+# Begin Special Build Tool
+OutDir=.\Debug
+TargetName=transformdb
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\$(TargetName).exe ..\..\bin
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "TransformDB - Win32 Release"
+# Name "TransformDB - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\AssignVisitor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Data.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Exception.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Functions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Grammar.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Parser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Print.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Scanner.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformAnalyzer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformDB.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformDescriptors.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformVisitor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Transformer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Util.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\AssignVisitor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Data.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Error.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Exception.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Functions.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GrammarUtil.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Grammar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Parser.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Print.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformAnalyzer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformDescriptors.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TransformVisitor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Transformer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Grammar.y
+
+!IF "$(CFG)" == "Transform - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\Grammar.y
+
+BuildCmds= \
+ bison -dvt Grammar.y \
+ move Grammar.tab.c Grammar.cpp \
+ move Grammar.tab.h Grammar.h \
+
+
+"Grammar.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"Grammar.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Transform - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\Grammar.y
+
+BuildCmds= \
+ bison -dvt Grammar.y \
+ move Grammar.tab.c Grammar.cpp \
+ move Grammar.tab.h Grammar.h \
+
+
+"Grammar.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"Grammar.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\Scanner.l
+
+!IF "$(CFG)" == "Transform - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\Scanner.l
+
+"Scanner.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ flex Scanner.l
+ echo #include "IceUtil/Config.h" > Scanner.cpp
+ type lex.yy.c >> Scanner.cpp
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Transform - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\Scanner.l
+
+"Scanner.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ flex Scanner.l
+ echo #include "IceUtil/Config.h" > Scanner.cpp
+ type lex.yy.c >> Scanner.cpp
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Group
+# End Target
+# End Project