--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/python-binding.patch Thu Jun 20 09:56:26 2013 +0900
@@ -0,0 +1,4120 @@
+diff --git a/bindings/callbacks_list.py b/bindings/callbacks_list.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/callbacks_list.py
+@@ -0,0 +1,1 @@
++callback_classes = [
+diff --git a/bindings/modulegen__gcc_ILP32.py b/bindings/modulegen__gcc_ILP32.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/modulegen__gcc_ILP32.py
+@@ -0,0 +1,33 @@
++from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
++
++
++import pybindgen.settings
++import warnings
++
++class ErrorHandler(pybindgen.settings.ErrorHandler):
++ def handle_error(self, wrapper, exception, traceback_):
++ warnings.warn("exception %r in wrapper %s" % (exception, wrapper))
++ return True
++pybindgen.settings.error_handler = ErrorHandler()
++
++
++import sys
++
++def module_init():
++ root_module = Module('ns.dce_netlink', cpp_namespace='::ns3')
++ return root_module
++
++def register_types(module):
++ root_module = module.get_root()
++
++
++ ## Register a nested module for the namespace FatalImpl
++
++ nested_module = module.add_cpp_namespace('FatalImpl')
++ register_types_ns3_FatalImpl(nested_module)
++
++
++def register_types_ns3_FatalImpl(module):
++ root_module = module.get_root()
++
++
+diff --git a/bindings/modulegen__gcc_LP64.py b/bindings/modulegen__gcc_LP64.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/modulegen__gcc_LP64.py
+@@ -0,0 +1,391 @@
++from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
++
++
++import pybindgen.settings
++import warnings
++
++class ErrorHandler(pybindgen.settings.ErrorHandler):
++ def handle_error(self, wrapper, exception, traceback_):
++ warnings.warn("exception %r in wrapper %s" % (exception, wrapper))
++ return True
++pybindgen.settings.error_handler = ErrorHandler()
++
++
++import sys
++
++def module_init():
++ root_module = Module('ns.dce', cpp_namespace='::ns3')
++ return root_module
++
++def register_types(module):
++ root_module = module.get_root()
++
++ ## dce-application-helper.h (module 'dce'): ns3::DceApplicationHelper [class]
++ module.add_class('DceApplicationHelper', allow_subclassing=True)
++ ## linux-stack-helper.h (module 'dce'): ns3::LinuxStackHelper [class]
++ module.add_class('LinuxStackHelper')
++ ## loader-factory.h (module 'dce'): ns3::Loader [class]
++ module.add_class('Loader', allow_subclassing=True)
++ ## dce-manager-helper.h (module 'dce'): ns3::ProcStatus [class]
++ module.add_class('ProcStatus')
++ ## task-manager.h (module 'dce'): ns3::Sleeper [class]
++ module.add_class('Sleeper')
++ ## task-manager.h (module 'dce'): ns3::Task [class]
++ module.add_class('Task', destructor_visibility='private')
++ ## task-manager.h (module 'dce'): ns3::Task::SwitchType [enumeration]
++ module.add_enum('SwitchType', ['TO', 'FROM'], outer_class=root_module['ns3::Task'])
++ ## ccn-client-helper.h (module 'dce'): ns3::CcnClientHelper [class]
++ module.add_class('CcnClientHelper', parent=root_module['ns3::DceApplicationHelper'])
++
++ ## Register a nested module for the namespace FatalImpl
++
++ nested_module = module.add_cpp_namespace('FatalImpl')
++ register_types_ns3_FatalImpl(nested_module)
++
++
++def register_types_ns3_FatalImpl(module):
++ root_module = module.get_root()
++
++
++def register_methods(root_module):
++ register_Ns3DceApplicationHelper_methods(root_module, root_module['ns3::DceApplicationHelper'])
++ register_Ns3LinuxStackHelper_methods(root_module, root_module['ns3::LinuxStackHelper'])
++ register_Ns3Loader_methods(root_module, root_module['ns3::Loader'])
++ register_Ns3ProcStatus_methods(root_module, root_module['ns3::ProcStatus'])
++ register_Ns3Sleeper_methods(root_module, root_module['ns3::Sleeper'])
++ register_Ns3Task_methods(root_module, root_module['ns3::Task'])
++ register_Ns3CcnClientHelper_methods(root_module, root_module['ns3::CcnClientHelper'])
++ return
++
++def register_Ns3DceApplicationHelper_methods(root_module, cls):
++ ## dce-application-helper.h (module 'dce'): ns3::DceApplicationHelper::DceApplicationHelper(ns3::DceApplicationHelper const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::DceApplicationHelper const &', 'arg0')])
++ ## dce-application-helper.h (module 'dce'): ns3::DceApplicationHelper::DceApplicationHelper() [constructor]
++ cls.add_constructor([])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArgument(std::string arg) [member function]
++ cls.add_method('AddArgument',
++ 'void',
++ [param('std::string', 'arg')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1, std::string a2) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1'), param('std::string', 'a2')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1, std::string a2, std::string a3) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1'), param('std::string', 'a2'), param('std::string', 'a3')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1, std::string a2, std::string a3, std::string a4) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1'), param('std::string', 'a2'), param('std::string', 'a3'), param('std::string', 'a4')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1, std::string a2, std::string a3, std::string a4, std::string a5) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1'), param('std::string', 'a2'), param('std::string', 'a3'), param('std::string', 'a4'), param('std::string', 'a5')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1, std::string a2, std::string a3, std::string a4, std::string a5, std::string a6) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1'), param('std::string', 'a2'), param('std::string', 'a3'), param('std::string', 'a4'), param('std::string', 'a5'), param('std::string', 'a6')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddArguments(std::string a0, std::string a1, std::string a2, std::string a3, std::string a4, std::string a5, std::string a6, std::string a7) [member function]
++ cls.add_method('AddArguments',
++ 'void',
++ [param('std::string', 'a0'), param('std::string', 'a1'), param('std::string', 'a2'), param('std::string', 'a3'), param('std::string', 'a4'), param('std::string', 'a5'), param('std::string', 'a6'), param('std::string', 'a7')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::AddEnvironment(std::string name, std::string value) [member function]
++ cls.add_method('AddEnvironment',
++ 'void',
++ [param('std::string', 'name'), param('std::string', 'value')])
++ ## dce-application-helper.h (module 'dce'): ns3::ApplicationContainer ns3::DceApplicationHelper::Install(ns3::NodeContainer c) [member function]
++ cls.add_method('Install',
++ 'ns3::ApplicationContainer',
++ [param('ns3::NodeContainer', 'c')],
++ is_virtual=True)
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::ParseArguments(std::string args) [member function]
++ cls.add_method('ParseArguments',
++ 'void',
++ [param('std::string', 'args')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::ResetArguments() [member function]
++ cls.add_method('ResetArguments',
++ 'void',
++ [])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::ResetEnvironment() [member function]
++ cls.add_method('ResetEnvironment',
++ 'void',
++ [])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetBinary(std::string filename) [member function]
++ cls.add_method('SetBinary',
++ 'void',
++ [param('std::string', 'filename')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetEgid(uid_t i) [member function]
++ cls.add_method('SetEgid',
++ 'void',
++ [param('uid_t', 'i')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetEuid(uid_t i) [member function]
++ cls.add_method('SetEuid',
++ 'void',
++ [param('uid_t', 'i')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetFinishedCallback(ns3::Callback<void, unsigned short, int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty> cb) [member function]
++ cls.add_method('SetFinishedCallback',
++ 'void',
++ [param('ns3::Callback< void, unsigned short, int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'cb')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetGid(uid_t i) [member function]
++ cls.add_method('SetGid',
++ 'void',
++ [param('uid_t', 'i')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetStackSize(uint32_t stackSize) [member function]
++ cls.add_method('SetStackSize',
++ 'void',
++ [param('uint32_t', 'stackSize')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetStdinFile(std::string filename) [member function]
++ cls.add_method('SetStdinFile',
++ 'void',
++ [param('std::string', 'filename')])
++ ## dce-application-helper.h (module 'dce'): void ns3::DceApplicationHelper::SetUid(uid_t i) [member function]
++ cls.add_method('SetUid',
++ 'void',
++ [param('uid_t', 'i')])
++ return
++
++def register_Ns3LinuxStackHelper_methods(root_module, cls):
++ ## linux-stack-helper.h (module 'dce'): ns3::LinuxStackHelper::LinuxStackHelper() [constructor]
++ cls.add_constructor([])
++ ## linux-stack-helper.h (module 'dce'): ns3::LinuxStackHelper::LinuxStackHelper(ns3::LinuxStackHelper const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::LinuxStackHelper const &', 'arg0')])
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::Install(std::string nodeName) [member function]
++ cls.add_method('Install',
++ 'void',
++ [param('std::string', 'nodeName')],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::Install(ns3::Ptr<ns3::Node> node) [member function]
++ cls.add_method('Install',
++ 'void',
++ [param('ns3::Ptr< ns3::Node >', 'node')],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::Install(ns3::NodeContainer c) [member function]
++ cls.add_method('Install',
++ 'void',
++ [param('ns3::NodeContainer', 'c')],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::InstallAll() [member function]
++ cls.add_method('InstallAll',
++ 'void',
++ [],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::PopulateRoutingTables() [member function]
++ cls.add_method('PopulateRoutingTables',
++ 'void',
++ [],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::RunIp(ns3::Ptr<ns3::Node> node, ns3::Time at, std::string str) [member function]
++ cls.add_method('RunIp',
++ 'void',
++ [param('ns3::Ptr< ns3::Node >', 'node'), param('ns3::Time', 'at'), param('std::string', 'str')],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): static void ns3::LinuxStackHelper::SysctlGet(ns3::Ptr<ns3::Node> node, ns3::Time at, std::string path, void (*)( ::std::string,::std::string ) * callback) [member function]
++ cls.add_method('SysctlGet',
++ 'void',
++ [param('ns3::Ptr< ns3::Node >', 'node'), param('ns3::Time', 'at'), param('std::string', 'path'), param('void ( * ) ( std::string, std::string ) *', 'callback')],
++ is_static=True)
++ ## linux-stack-helper.h (module 'dce'): void ns3::LinuxStackHelper::SysctlSet(ns3::NodeContainer c, std::string path, std::string value) [member function]
++ cls.add_method('SysctlSet',
++ 'void',
++ [param('ns3::NodeContainer', 'c'), param('std::string', 'path'), param('std::string', 'value')])
++ return
++
++def register_Ns3Loader_methods(root_module, cls):
++ ## loader-factory.h (module 'dce'): ns3::Loader::Loader() [constructor]
++ cls.add_constructor([])
++ ## loader-factory.h (module 'dce'): ns3::Loader::Loader(ns3::Loader const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::Loader const &', 'arg0')])
++ ## loader-factory.h (module 'dce'): ns3::Loader * ns3::Loader::Clone() [member function]
++ cls.add_method('Clone',
++ 'ns3::Loader *',
++ [],
++ is_pure_virtual=True, is_virtual=True)
++ ## loader-factory.h (module 'dce'): void * ns3::Loader::Load(std::string filename, int flag) [member function]
++ cls.add_method('Load',
++ 'void *',
++ [param('std::string', 'filename'), param('int', 'flag')],
++ is_pure_virtual=True, is_virtual=True)
++ ## loader-factory.h (module 'dce'): void * ns3::Loader::Lookup(void * module, std::string symbol) [member function]
++ cls.add_method('Lookup',
++ 'void *',
++ [param('void *', 'module'), param('std::string', 'symbol')],
++ is_pure_virtual=True, is_virtual=True)
++ ## loader-factory.h (module 'dce'): void ns3::Loader::NotifyEndExecute() [member function]
++ cls.add_method('NotifyEndExecute',
++ 'void',
++ [],
++ is_virtual=True)
++ ## loader-factory.h (module 'dce'): void ns3::Loader::NotifyStartExecute() [member function]
++ cls.add_method('NotifyStartExecute',
++ 'void',
++ [],
++ is_virtual=True)
++ ## loader-factory.h (module 'dce'): void ns3::Loader::Unload(void * module) [member function]
++ cls.add_method('Unload',
++ 'void',
++ [param('void *', 'module')],
++ is_pure_virtual=True, is_virtual=True)
++ ## loader-factory.h (module 'dce'): void ns3::Loader::UnloadAll() [member function]
++ cls.add_method('UnloadAll',
++ 'void',
++ [],
++ is_pure_virtual=True, is_virtual=True)
++ return
++
++def register_Ns3ProcStatus_methods(root_module, cls):
++ ## dce-manager-helper.h (module 'dce'): ns3::ProcStatus::ProcStatus(ns3::ProcStatus const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::ProcStatus const &', 'arg0')])
++ ## dce-manager-helper.h (module 'dce'): ns3::ProcStatus::ProcStatus(int n, int e, int p, int64_t ns, int64_t ne, long int rs, long int re, double nd, long int rd, std::string cmd) [constructor]
++ cls.add_constructor([param('int', 'n'), param('int', 'e'), param('int', 'p'), param('int64_t', 'ns'), param('int64_t', 'ne'), param('long int', 'rs'), param('long int', 're'), param('double', 'nd'), param('long int', 'rd'), param('std::string', 'cmd')])
++ ## dce-manager-helper.h (module 'dce'): std::string ns3::ProcStatus::GetCmdLine() const [member function]
++ cls.add_method('GetCmdLine',
++ 'std::string',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): int ns3::ProcStatus::GetExitCode() const [member function]
++ cls.add_method('GetExitCode',
++ 'int',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): int ns3::ProcStatus::GetNode() const [member function]
++ cls.add_method('GetNode',
++ 'int',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): int ns3::ProcStatus::GetPid() const [member function]
++ cls.add_method('GetPid',
++ 'int',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): long int ns3::ProcStatus::GetRealDuration() const [member function]
++ cls.add_method('GetRealDuration',
++ 'long int',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): long int ns3::ProcStatus::GetRealEndTime() const [member function]
++ cls.add_method('GetRealEndTime',
++ 'long int',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): long int ns3::ProcStatus::GetRealStartTime() const [member function]
++ cls.add_method('GetRealStartTime',
++ 'long int',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): double ns3::ProcStatus::GetSimulatedDuration() const [member function]
++ cls.add_method('GetSimulatedDuration',
++ 'double',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): int64_t ns3::ProcStatus::GetSimulatedEndTime() const [member function]
++ cls.add_method('GetSimulatedEndTime',
++ 'int64_t',
++ [],
++ is_const=True)
++ ## dce-manager-helper.h (module 'dce'): int64_t ns3::ProcStatus::GetSimulatedStartTime() const [member function]
++ cls.add_method('GetSimulatedStartTime',
++ 'int64_t',
++ [],
++ is_const=True)
++ return
++
++def register_Ns3Sleeper_methods(root_module, cls):
++ ## task-manager.h (module 'dce'): ns3::Sleeper::m_task [variable]
++ cls.add_instance_attribute('m_task', 'ns3::Task * const', is_const=True)
++ ## task-manager.h (module 'dce'): ns3::Sleeper::m_timeout [variable]
++ cls.add_instance_attribute('m_timeout', 'ns3::Time const', is_const=True)
++ ## task-manager.h (module 'dce'): ns3::Sleeper::Sleeper(ns3::Sleeper const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::Sleeper const &', 'arg0')])
++ ## task-manager.h (module 'dce'): ns3::Sleeper::Sleeper(ns3::Task * t, ns3::Time to) [constructor]
++ cls.add_constructor([param('ns3::Task *', 't'), param('ns3::Time', 'to')])
++ return
++
++def register_Ns3Task_methods(root_module, cls):
++ ## task-manager.h (module 'dce'): ns3::Task::Task() [constructor]
++ cls.add_constructor([])
++ ## task-manager.h (module 'dce'): ns3::Task::Task(ns3::Task const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::Task const &', 'arg0')])
++ ## task-manager.h (module 'dce'): void * ns3::Task::GetContext() const [member function]
++ cls.add_method('GetContext',
++ 'void *',
++ [],
++ is_const=True)
++ ## task-manager.h (module 'dce'): void * ns3::Task::GetExtraContext() const [member function]
++ cls.add_method('GetExtraContext',
++ 'void *',
++ [],
++ is_const=True)
++ ## task-manager.h (module 'dce'): bool ns3::Task::IsActive() const [member function]
++ cls.add_method('IsActive',
++ 'bool',
++ [],
++ is_const=True)
++ ## task-manager.h (module 'dce'): bool ns3::Task::IsBlocked() const [member function]
++ cls.add_method('IsBlocked',
++ 'bool',
++ [],
++ is_const=True)
++ ## task-manager.h (module 'dce'): bool ns3::Task::IsDead() const [member function]
++ cls.add_method('IsDead',
++ 'bool',
++ [],
++ is_const=True)
++ ## task-manager.h (module 'dce'): bool ns3::Task::IsRunning() const [member function]
++ cls.add_method('IsRunning',
++ 'bool',
++ [],
++ is_const=True)
++ ## task-manager.h (module 'dce'): void ns3::Task::SetContext(void * ctx) [member function]
++ cls.add_method('SetContext',
++ 'void',
++ [param('void *', 'ctx')])
++ ## task-manager.h (module 'dce'): void ns3::Task::SetExtraContext(void * ctx) [member function]
++ cls.add_method('SetExtraContext',
++ 'void',
++ [param('void *', 'ctx')])
++ ## task-manager.h (module 'dce'): void ns3::Task::SetSwitchNotifier(void (*)( ::ns3::Task::SwitchType,void * ) * fn, void * context) [member function]
++ cls.add_method('SetSwitchNotifier',
++ 'void',
++ [param('void ( * ) ( ns3::Task::SwitchType, void * ) *', 'fn'), param('void *', 'context')])
++ return
++
++def register_Ns3CcnClientHelper_methods(root_module, cls):
++ ## ccn-client-helper.h (module 'dce'): ns3::CcnClientHelper::CcnClientHelper(ns3::CcnClientHelper const & arg0) [copy constructor]
++ cls.add_constructor([param('ns3::CcnClientHelper const &', 'arg0')])
++ ## ccn-client-helper.h (module 'dce'): ns3::CcnClientHelper::CcnClientHelper() [constructor]
++ cls.add_constructor([])
++ ## ccn-client-helper.h (module 'dce'): void ns3::CcnClientHelper::AddFile(std::string from, std::string to) [member function]
++ cls.add_method('AddFile',
++ 'void',
++ [param('std::string', 'from'), param('std::string', 'to')])
++ ## ccn-client-helper.h (module 'dce'): ns3::ApplicationContainer ns3::CcnClientHelper::Install(ns3::NodeContainer c) [member function]
++ cls.add_method('Install',
++ 'ns3::ApplicationContainer',
++ [param('ns3::NodeContainer', 'c')],
++ is_virtual=True)
++ return
++
++def register_functions(root_module):
++ module = root_module
++ register_functions_ns3_FatalImpl(module.get_submodule('FatalImpl'), root_module)
++ return
++
++def register_functions_ns3_FatalImpl(module, root_module):
++ return
++
++def main():
++ out = FileCodeSink(sys.stdout)
++ root_module = module_init()
++ register_types(root_module)
++ register_methods(root_module)
++ register_functions(root_module)
++ root_module.generate(out)
++
++if __name__ == '__main__':
++ main()
++
+diff --git a/bindings/ns/_placeholder_ b/bindings/ns/_placeholder_
+new file mode 100644
+diff --git a/bindings/ns3modulegen-modular.py b/bindings/ns3modulegen-modular.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/ns3modulegen-modular.py
+@@ -0,0 +1,132 @@
++import warnings
++import sys
++import os
++import pybindgen.settings
++from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
++from pybindgen.module import MultiSectionFactory
++import ns3modulegen_core_customizations
++
++pybindgen.settings.wrapper_registry = pybindgen.settings.StdMapWrapperRegistry
++
++import traceback
++
++class ErrorHandler(pybindgen.settings.ErrorHandler):
++
++ def __init__(self, apidefs_file):
++ self.apidefs_file = apidefs_file
++
++ def handle_error(self, wrapper, exception, traceback_):
++ stack = getattr(wrapper, 'stack_where_defined', [])
++ stack.reverse()
++ for l in stack:
++ if l[0] == self.apidefs_file:
++ warnings.warn_explicit("exception %r in wrapper %s" % (exception, wrapper),
++ Warning, l[0], l[1])
++ break
++ else:
++ warnings.warn("exception %r in wrapper %s" % (exception, wrapper))
++ return True
++
++
++#print >> sys.stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>> ", bool(eval(os.environ["GCC_RTTI_ABI_COMPLETE"]))
++pybindgen.settings.gcc_rtti_abi_complete = bool(eval(os.environ["GCC_RTTI_ABI_COMPLETE"]))
++
++class MyMultiSectionFactory(MultiSectionFactory):
++ def __init__(self, main_file_name):
++ super(MyMultiSectionFactory, self).__init__()
++ self.main_file_name = main_file_name
++ self.main_sink = FileCodeSink(open(main_file_name, "wt"))
++ self.header_name = "ns3module.h"
++ header_file_name = os.path.join(os.path.dirname(self.main_file_name), self.header_name)
++ #print >> sys.stderr, ">>>>>>>>>>>>>>>>>", header_file_name, main_file_name
++ self.header_sink = FileCodeSink(open(header_file_name, "wt"))
++ def get_section_code_sink(self, section_name):
++ return self.main_sink
++ def get_main_code_sink(self):
++ return self.main_sink
++ def get_common_header_code_sink(self):
++ return self.header_sink
++ def get_common_header_include(self):
++ return '"%s"' % self.header_name
++ def close(self):
++ self.header_sink.file.close()
++ self.main_sink.file.close()
++
++
++
++def main(argv):
++ module_abs_src_path, target, extension_name, output_cc_file_name = argv[1:]
++ if module_abs_src_path.endswith('build'):
++ module_name = extension_name
++ else:
++ module_name = os.path.basename(module_abs_src_path).replace('ns-3-','')
++ print module_name
++ print extension_name
++ out = MyMultiSectionFactory(output_cc_file_name)
++
++ sys.path.insert(0, os.path.join(module_abs_src_path, "bindings"))
++ try:
++ module_apidefs = __import__("modulegen__%s" % target)
++ del sys.modules["modulegen__%s" % target]
++ try:
++ module_customization = __import__("modulegen_customizations")
++ del sys.modules["modulegen_customizations"]
++ except ImportError:
++ module_customization = object()
++
++ try:
++ from callbacks_list import callback_classes
++ except ImportError, ex:
++ print >> sys.stderr, "***************", repr(ex)
++ callback_classes = []
++ else:
++ print >> sys.stderr, ">>>>>>>>>>>>>>>>", repr(callback_classes)
++
++ finally:
++ sys.path.pop(0)
++
++ apidefs_file, dummy = os.path.splitext(module_apidefs.__file__)
++ apidefs_file += '.py'
++ pybindgen.settings.error_handler = ErrorHandler(apidefs_file)
++
++ root_module = module_apidefs.module_init()
++ root_module.set_name(extension_name)
++ root_module.add_include('"ns3/%s-module.h"' % module_name)
++
++ ns3modulegen_core_customizations.add_std_ios_openmode(root_module)
++
++ # -----------
++ module_apidefs.register_types(root_module)
++
++ if hasattr(module_customization, 'post_register_types'):
++ module_customization.post_register_types(root_module)
++
++ # register Callback<...> type handlers
++ ns3modulegen_core_customizations.generate_callback_classes(root_module.after_forward_declarations,
++ callback_classes)
++
++ # -----------
++ module_apidefs.register_methods(root_module)
++
++ if hasattr(module_customization, 'post_register_methods'):
++ module_customization.post_register_methods(root_module)
++
++ ns3modulegen_core_customizations.Object_customizations(root_module)
++ ns3modulegen_core_customizations.Attribute_customizations(root_module)
++
++
++ # -----------
++ module_apidefs.register_functions(root_module)
++
++ if hasattr(module_customization, 'post_register_functions'):
++ module_customization.post_register_functions(root_module)
++
++
++ # -----------
++ root_module.generate(out)
++
++if __name__ == '__main__':
++ import sys
++ main(sys.argv)
++
++
+diff --git a/bindings/ns3modulegen_core_customizations.pyc b/bindings/ns3modulegen_core_customizations.pyc
+new file mode 100644
+index 0000000000000000000000000000000000000000..ce57d2480927177d87cce5535d01e7b1eb9f3422
+GIT binary patch
+literal 18612
+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
+
+diff --git a/bindings/ns3modulescan-modular.py b/bindings/ns3modulescan-modular.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/ns3modulescan-modular.py
+@@ -0,0 +1,281 @@
++#! /usr/bin/env python
++
++import sys
++import os.path
++
++import pybindgen.settings
++from pybindgen.gccxmlparser import ModuleParser, PygenClassifier, PygenSection, WrapperWarning, find_declaration_from_name
++from pybindgen.typehandlers.codesink import FileCodeSink
++from pygccxml.declarations import templates
++from pygccxml.declarations.enumeration import enumeration_t
++from pygccxml.declarations.class_declaration import class_t
++from pygccxml.declarations.calldef import free_function_t, member_function_t, constructor_t, calldef_t
++
++
++## we need the smart pointer type transformation to be active even
++## during gccxml scanning.
++import ns3modulegen_core_customizations
++
++
++## silence gccxmlparser errors; we only want error handling in the
++## generated python script, not while scanning.
++class ErrorHandler(pybindgen.settings.ErrorHandler):
++ def handle_error(self, dummy_wrapper, dummy_exception, dummy_traceback_):
++ return True
++pybindgen.settings.error_handler = ErrorHandler()
++import warnings
++warnings.filterwarnings(category=WrapperWarning, action='ignore')
++
++
++import ns3modulescan
++type_annotations = ns3modulescan.type_annotations
++
++
++def get_ns3_relative_path(path):
++ l = []
++ head = path
++ while head:
++ new_head, tail = os.path.split(head)
++ if new_head == head:
++ raise ValueError
++ head = new_head
++ if tail == 'ns3':
++ return os.path.join(*l)
++ l.insert(0, tail)
++ raise AssertionError("is the path %r inside ns3?!" % path)
++
++class PreScanHook:
++
++ def __init__(self, headers_map, module):
++ self.headers_map = headers_map
++ self.module = module
++
++ def __call__(self, module_parser,
++ pygccxml_definition,
++ global_annotations,
++ parameter_annotations):
++ try:
++ ns3_header = get_ns3_relative_path(pygccxml_definition.location.file_name)
++ except ValueError: # the header is not from ns3
++ return # ignore the definition, it's not ns-3 def.
++
++ definition_module = self.headers_map[ns3_header]
++
++ ## Note: we don't include line numbers in the comments because
++ ## those numbers are very likely to change frequently, which would
++ ## cause needless changes, since the generated python files are
++ ## kept under version control.
++
++ #global_annotations['pygen_comment'] = "%s:%i: %s" % \
++ # (ns3_header, pygccxml_definition.location.line, pygccxml_definition)
++ global_annotations['pygen_comment'] = "%s (module %r): %s" % \
++ (ns3_header, definition_module, pygccxml_definition)
++
++
++ ## handle ns3::Object::GetObject (left to its own devices,
++ ## pybindgen will generate a mangled name containing the template
++ ## argument type name).
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Object' \
++ and pygccxml_definition.name == 'GetObject':
++ template_args = templates.args(pygccxml_definition.demangled_name)
++ if template_args == ['ns3::Object']:
++ global_annotations['template_instance_names'] = 'ns3::Object=>GetObject'
++
++ ## Don't wrap Simulator::Schedule* (manually wrapped)
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Simulator' \
++ and pygccxml_definition.name.startswith('Schedule'):
++ global_annotations['ignore'] = None
++
++ # manually wrapped
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Simulator' \
++ and pygccxml_definition.name == 'Run':
++ global_annotations['ignore'] = True
++
++ ## http://www.gccxml.org/Bug/view.php?id=9915
++ if isinstance(pygccxml_definition, calldef_t):
++ for arg in pygccxml_definition.arguments:
++ if arg.default_value is None:
++ continue
++ elif arg.default_value == "ns3::MilliSeconds( )":
++ arg.default_value = "ns3::MilliSeconds(0)"
++ elif arg.default_value == "ns3::Seconds( )":
++ arg.default_value = "ns3::Seconds(0)"
++
++ ## classes
++ if isinstance(pygccxml_definition, class_t):
++ print >> sys.stderr, pygccxml_definition
++ # no need for helper classes to allow subclassing in Python, I think...
++ #if pygccxml_definition.name.endswith('Helper'):
++ # global_annotations['allow_subclassing'] = 'false'
++
++ #
++ # If a class is template instantiation, even if the
++ # template was defined in some other module, if a template
++ # argument belongs to this module then the template
++ # instantiation will belong to this module.
++ #
++ if templates.is_instantiation(pygccxml_definition.decl_string):
++ cls_name, template_parameters = templates.split(pygccxml_definition.name)
++ template_parameters_decls = [find_declaration_from_name(module_parser.global_ns, templ_param)
++ for templ_param in template_parameters]
++ #print >> sys.stderr, "********************", cls_name, repr(template_parameters_decls)
++
++ template_parameters_modules = []
++ for templ in template_parameters_decls:
++ if not hasattr(templ, 'location'):
++ continue
++ try:
++ h = get_ns3_relative_path(templ.location.file_name)
++ except ValueError:
++ continue
++ template_parameters_modules.append(self.headers_map[h])
++
++ for templ_mod in template_parameters_modules:
++ if templ_mod == self.module:
++ definition_module = templ_mod
++ break
++ #print >> sys.stderr, "********************", cls_name, repr(template_parameters_modules)
++
++
++ if definition_module != self.module:
++ global_annotations['import_from_module'] = 'ns.%s' % (definition_module.replace('-', '_'),)
++
++ if pygccxml_definition.decl_string.startswith('::ns3::SimpleRefCount<'):
++ global_annotations['incref_method'] = 'Ref'
++ global_annotations['decref_method'] = 'Unref'
++ global_annotations['peekref_method'] = 'GetReferenceCount'
++ global_annotations['automatic_type_narrowing'] = 'true'
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::Callback<'):
++ # manually handled in ns3modulegen_core_customizations.py
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::TracedCallback<'):
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::Ptr<'):
++ # handled by pybindgen "type transformation"
++ global_annotations['ignore'] = None
++ return
++
++ # table driven class customization
++ try:
++ annotations = type_annotations[pygccxml_definition.decl_string]
++ except KeyError:
++ pass
++ else:
++ global_annotations.update(annotations)
++
++ ## enums
++ if isinstance(pygccxml_definition, enumeration_t):
++ if definition_module != self.module:
++ global_annotations['import_from_module'] = 'ns.%s' % definition_module
++
++ ## free functions
++ if isinstance(pygccxml_definition, free_function_t):
++
++ if definition_module != self.module:
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.name == 'PeekPointer':
++ global_annotations['ignore'] = None
++ return
++
++ ## table driven methods/constructors/functions customization
++ if isinstance(pygccxml_definition, (free_function_t, member_function_t, constructor_t)):
++ try:
++ annotations = type_annotations[str(pygccxml_definition)]
++ except KeyError:
++ pass
++ else:
++ for key,value in annotations.items():
++ if key == 'params':
++ parameter_annotations.update (value)
++ del annotations['params']
++ global_annotations.update(annotations)
++
++
++# def post_scan_hook(dummy_module_parser, dummy_pygccxml_definition, pybindgen_wrapper):
++# ## classes
++# if isinstance(pybindgen_wrapper, CppClass):
++# if pybindgen_wrapper.name.endswith('Checker'):
++# print >> sys.stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", pybindgen_wrapper
++# #pybindgen_wrapper.set_instance_creation_function(AttributeChecker_instance_creation_function)
++
++
++def scan_callback_classes(module_parser, callback_classes_file):
++ callback_classes_file.write("callback_classes = [\n")
++ for cls in module_parser.module_namespace.classes(function=module_parser.location_filter,
++ recursive=False):
++ if not cls.name.startswith("Callback<"):
++ continue
++ assert templates.is_instantiation(cls.decl_string), "%s is not a template instantiation" % cls
++ dummy_cls_name, template_parameters = templates.split(cls.decl_string)
++ callback_classes_file.write(" %r,\n" % template_parameters)
++ callback_classes_file.write("]\n")
++
++
++def ns3_module_scan(top_builddir, module_name, headers_map, output_file_name, cflags):
++ module_parser = ModuleParser('ns.%s' % module_name.replace('-', '_'), 'ns3')
++ module_parser.add_pre_scan_hook(PreScanHook(headers_map, module_name))
++ #module_parser.add_post_scan_hook(post_scan_hook)
++
++ gccxml_options = dict(
++ include_paths=[top_builddir],
++ define_symbols={
++ #'NS3_ASSERT_ENABLE': None,
++ #'NS3_LOG_ENABLE': None,
++ },
++ cflags=('--gccxml-cxxflags "%s -DPYTHON_SCAN"' % cflags)
++ )
++
++ try:
++ os.unlink(output_file_name)
++ except OSError:
++ pass
++ try:
++ os.makedirs(os.path.dirname(output_file_name))
++ except OSError:
++ pass
++ output_file = open(output_file_name, "wt")
++ output_sink = FileCodeSink(output_file)
++
++ # if there exists a scan-header.h file in src/<module>/bindings,
++ # scan it, otherwise scan ns3/xxxx-module.h.
++ scan_header = os.path.join(os.path.dirname(output_file_name), "scan-header.h")
++ if not os.path.exists(scan_header):
++ scan_header = os.path.join(top_builddir, "ns3", "%s-module.h" % module_name)
++
++ module_parser.parse_init([scan_header],
++ None, whitelist_paths=[top_builddir],
++ #includes=['"ns3/everything.h"'],
++ pygen_sink=output_sink,
++ gccxml_options=gccxml_options)
++ module_parser.scan_types()
++
++ callback_classes_file = open(os.path.join(os.path.dirname(output_file_name), "callbacks_list.py"), "wt")
++ scan_callback_classes(module_parser, callback_classes_file)
++ callback_classes_file.close()
++
++
++ module_parser.scan_methods()
++ module_parser.scan_functions()
++ module_parser.parse_finalize()
++
++ output_file.close()
++ os.chmod(output_file_name, 0400)
++
++
++if __name__ == '__main__':
++ if len(sys.argv) != 6:
++ print "ns3modulescan-modular.py top_builddir module_path module_headers output_file_name cflags"
++ sys.exit(1)
++ ns3_module_scan(sys.argv[1], sys.argv[2], eval(sys.argv[3]), sys.argv[4], sys.argv[5])
++ sys.exit(0)
+diff --git a/bindings/ns3modulescan-modular.py~ b/bindings/ns3modulescan-modular.py~
+new file mode 100644
+--- /dev/null
++++ b/bindings/ns3modulescan-modular.py~
+@@ -0,0 +1,282 @@
++#! /usr/bin/env python
++
++import sys
++import os.path
++
++import pybindgen.settings
++from pybindgen.gccxmlparser import ModuleParser, PygenClassifier, PygenSection, WrapperWarning, find_declaration_from_name
++from pybindgen.typehandlers.codesink import FileCodeSink
++from pygccxml.declarations import templates
++from pygccxml.declarations.enumeration import enumeration_t
++from pygccxml.declarations.class_declaration import class_t
++from pygccxml.declarations.calldef import free_function_t, member_function_t, constructor_t, calldef_t
++
++
++## we need the smart pointer type transformation to be active even
++## during gccxml scanning.
++import ns3modulegen_core_customizations
++
++
++## silence gccxmlparser errors; we only want error handling in the
++## generated python script, not while scanning.
++class ErrorHandler(pybindgen.settings.ErrorHandler):
++ def handle_error(self, dummy_wrapper, dummy_exception, dummy_traceback_):
++ return True
++pybindgen.settings.error_handler = ErrorHandler()
++import warnings
++warnings.filterwarnings(category=WrapperWarning, action='ignore')
++
++
++import ns3modulescan
++type_annotations = ns3modulescan.type_annotations
++
++
++def get_ns3_relative_path(path):
++ l = []
++ head = path
++ while head:
++ new_head, tail = os.path.split(head)
++ if new_head == head:
++ raise ValueError
++ head = new_head
++ if tail == 'ns3':
++ return os.path.join(*l)
++ l.insert(0, tail)
++ raise AssertionError("is the path %r inside ns3?!" % path)
++
++class PreScanHook:
++
++ def __init__(self, headers_map, module):
++ self.headers_map = headers_map
++ self.module = module
++
++ def __call__(self, module_parser,
++ pygccxml_definition,
++ global_annotations,
++ parameter_annotations):
++ print "==="% pygccxml_definition
++ try:
++ ns3_header = get_ns3_relative_path(pygccxml_definition.location.file_name)
++ except ValueError: # the header is not from ns3
++ return # ignore the definition, it's not ns-3 def.
++
++ definition_module = self.headers_map[ns3_header]
++
++ ## Note: we don't include line numbers in the comments because
++ ## those numbers are very likely to change frequently, which would
++ ## cause needless changes, since the generated python files are
++ ## kept under version control.
++
++ #global_annotations['pygen_comment'] = "%s:%i: %s" % \
++ # (ns3_header, pygccxml_definition.location.line, pygccxml_definition)
++ global_annotations['pygen_comment'] = "%s (module %r): %s" % \
++ (ns3_header, definition_module, pygccxml_definition)
++
++
++ ## handle ns3::Object::GetObject (left to its own devices,
++ ## pybindgen will generate a mangled name containing the template
++ ## argument type name).
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Object' \
++ and pygccxml_definition.name == 'GetObject':
++ template_args = templates.args(pygccxml_definition.demangled_name)
++ if template_args == ['ns3::Object']:
++ global_annotations['template_instance_names'] = 'ns3::Object=>GetObject'
++
++ ## Don't wrap Simulator::Schedule* (manually wrapped)
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Simulator' \
++ and pygccxml_definition.name.startswith('Schedule'):
++ global_annotations['ignore'] = None
++
++ # manually wrapped
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Simulator' \
++ and pygccxml_definition.name == 'Run':
++ global_annotations['ignore'] = True
++
++ ## http://www.gccxml.org/Bug/view.php?id=9915
++ if isinstance(pygccxml_definition, calldef_t):
++ for arg in pygccxml_definition.arguments:
++ if arg.default_value is None:
++ continue
++ elif arg.default_value == "ns3::MilliSeconds( )":
++ arg.default_value = "ns3::MilliSeconds(0)"
++ elif arg.default_value == "ns3::Seconds( )":
++ arg.default_value = "ns3::Seconds(0)"
++
++ ## classes
++ if isinstance(pygccxml_definition, class_t):
++ print >> sys.stderr, pygccxml_definition
++ # no need for helper classes to allow subclassing in Python, I think...
++ #if pygccxml_definition.name.endswith('Helper'):
++ # global_annotations['allow_subclassing'] = 'false'
++
++ #
++ # If a class is template instantiation, even if the
++ # template was defined in some other module, if a template
++ # argument belongs to this module then the template
++ # instantiation will belong to this module.
++ #
++ if templates.is_instantiation(pygccxml_definition.decl_string):
++ cls_name, template_parameters = templates.split(pygccxml_definition.name)
++ template_parameters_decls = [find_declaration_from_name(module_parser.global_ns, templ_param)
++ for templ_param in template_parameters]
++ #print >> sys.stderr, "********************", cls_name, repr(template_parameters_decls)
++
++ template_parameters_modules = []
++ for templ in template_parameters_decls:
++ if not hasattr(templ, 'location'):
++ continue
++ try:
++ h = get_ns3_relative_path(templ.location.file_name)
++ except ValueError:
++ continue
++ template_parameters_modules.append(self.headers_map[h])
++
++ for templ_mod in template_parameters_modules:
++ if templ_mod == self.module:
++ definition_module = templ_mod
++ break
++ #print >> sys.stderr, "********************", cls_name, repr(template_parameters_modules)
++
++
++ if definition_module != self.module:
++ global_annotations['import_from_module'] = 'ns.%s' % (definition_module.replace('-', '_'),)
++
++ if pygccxml_definition.decl_string.startswith('::ns3::SimpleRefCount<'):
++ global_annotations['incref_method'] = 'Ref'
++ global_annotations['decref_method'] = 'Unref'
++ global_annotations['peekref_method'] = 'GetReferenceCount'
++ global_annotations['automatic_type_narrowing'] = 'true'
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::Callback<'):
++ # manually handled in ns3modulegen_core_customizations.py
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::TracedCallback<'):
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::Ptr<'):
++ # handled by pybindgen "type transformation"
++ global_annotations['ignore'] = None
++ return
++
++ # table driven class customization
++ try:
++ annotations = type_annotations[pygccxml_definition.decl_string]
++ except KeyError:
++ pass
++ else:
++ global_annotations.update(annotations)
++
++ ## enums
++ if isinstance(pygccxml_definition, enumeration_t):
++ if definition_module != self.module:
++ global_annotations['import_from_module'] = 'ns.%s' % definition_module
++
++ ## free functions
++ if isinstance(pygccxml_definition, free_function_t):
++
++ if definition_module != self.module:
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.name == 'PeekPointer':
++ global_annotations['ignore'] = None
++ return
++
++ ## table driven methods/constructors/functions customization
++ if isinstance(pygccxml_definition, (free_function_t, member_function_t, constructor_t)):
++ try:
++ annotations = type_annotations[str(pygccxml_definition)]
++ except KeyError:
++ pass
++ else:
++ for key,value in annotations.items():
++ if key == 'params':
++ parameter_annotations.update (value)
++ del annotations['params']
++ global_annotations.update(annotations)
++
++
++# def post_scan_hook(dummy_module_parser, dummy_pygccxml_definition, pybindgen_wrapper):
++# ## classes
++# if isinstance(pybindgen_wrapper, CppClass):
++# if pybindgen_wrapper.name.endswith('Checker'):
++# print >> sys.stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", pybindgen_wrapper
++# #pybindgen_wrapper.set_instance_creation_function(AttributeChecker_instance_creation_function)
++
++
++def scan_callback_classes(module_parser, callback_classes_file):
++ callback_classes_file.write("callback_classes = [\n")
++ for cls in module_parser.module_namespace.classes(function=module_parser.location_filter,
++ recursive=False):
++ if not cls.name.startswith("Callback<"):
++ continue
++ assert templates.is_instantiation(cls.decl_string), "%s is not a template instantiation" % cls
++ dummy_cls_name, template_parameters = templates.split(cls.decl_string)
++ callback_classes_file.write(" %r,\n" % template_parameters)
++ callback_classes_file.write("]\n")
++
++
++def ns3_module_scan(top_builddir, module_name, headers_map, output_file_name, cflags):
++ module_parser = ModuleParser('ns.%s' % module_name.replace('-', '_'), 'ns3')
++ module_parser.add_pre_scan_hook(PreScanHook(headers_map, module_name))
++ #module_parser.add_post_scan_hook(post_scan_hook)
++
++ gccxml_options = dict(
++ include_paths=[top_builddir],
++ define_symbols={
++ #'NS3_ASSERT_ENABLE': None,
++ #'NS3_LOG_ENABLE': None,
++ },
++ cflags=('--gccxml-cxxflags "%s -DPYTHON_SCAN"' % cflags)
++ )
++
++ try:
++ os.unlink(output_file_name)
++ except OSError:
++ pass
++ try:
++ os.makedirs(os.path.dirname(output_file_name))
++ except OSError:
++ pass
++ output_file = open(output_file_name, "wt")
++ output_sink = FileCodeSink(output_file)
++
++ # if there exists a scan-header.h file in src/<module>/bindings,
++ # scan it, otherwise scan ns3/xxxx-module.h.
++ scan_header = os.path.join(os.path.dirname(output_file_name), "scan-header.h")
++ if not os.path.exists(scan_header):
++ scan_header = os.path.join(top_builddir, "ns3", "%s-module.h" % module_name)
++
++ module_parser.parse_init([scan_header],
++ None, whitelist_paths=[top_builddir],
++ #includes=['"ns3/everything.h"'],
++ pygen_sink=output_sink,
++ gccxml_options=gccxml_options)
++ module_parser.scan_types()
++
++ callback_classes_file = open(os.path.join(os.path.dirname(output_file_name), "callbacks_list.py"), "wt")
++ scan_callback_classes(module_parser, callback_classes_file)
++ callback_classes_file.close()
++
++
++ module_parser.scan_methods()
++ module_parser.scan_functions()
++ module_parser.parse_finalize()
++
++ output_file.close()
++ os.chmod(output_file_name, 0400)
++
++
++if __name__ == '__main__':
++ if len(sys.argv) != 6:
++ print "ns3modulescan-modular.py top_builddir module_path module_headers output_file_name cflags"
++ sys.exit(1)
++ ns3_module_scan(sys.argv[1], sys.argv[2], eval(sys.argv[3]), sys.argv[4], sys.argv[5])
++ sys.exit(0)
+diff --git a/bindings/ns3modulescan.py b/bindings/ns3modulescan.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/ns3modulescan.py
+@@ -0,0 +1,333 @@
++#! /usr/bin/env python
++
++import sys
++import os.path
++
++import pybindgen.settings
++from pybindgen.gccxmlparser import ModuleParser, PygenClassifier, PygenSection, WrapperWarning
++from pybindgen.typehandlers.codesink import FileCodeSink
++from pygccxml.declarations import templates
++from pygccxml.declarations.class_declaration import class_t
++from pygccxml.declarations.calldef import free_function_t, member_function_t, constructor_t, calldef_t
++
++
++## we need the smart pointer type transformation to be active even
++## during gccxml scanning.
++import ns3modulegen_core_customizations
++
++
++## silence gccxmlparser errors; we only want error handling in the
++## generated python script, not while scanning.
++class ErrorHandler(pybindgen.settings.ErrorHandler):
++ def handle_error(self, dummy_wrapper, dummy_exception, dummy_traceback_):
++ return True
++pybindgen.settings.error_handler = ErrorHandler()
++import warnings
++warnings.filterwarnings(category=WrapperWarning, action='ignore')
++
++type_annotations = {
++ '::ns3::AttributeChecker': {
++ 'automatic_type_narrowing': 'true',
++ 'allow_subclassing': 'false',
++ },
++ '::ns3::AttributeValue': {
++ 'automatic_type_narrowing': 'true',
++ 'allow_subclassing': 'false',
++ },
++
++ '::ns3::CommandLine': {
++ 'allow_subclassing': 'true', # needed so that AddValue is able to set attributes on the object
++ },
++
++ '::ns3::NscTcpL4Protocol': {
++ 'ignore': 'true', # this class is implementation detail
++ },
++
++
++ 'ns3::RandomVariable::RandomVariable(ns3::RandomVariableBase const & variable) [constructor]': {
++ 'ignore': None,
++ },
++ 'ns3::RandomVariableBase * ns3::RandomVariable::Peek() const [member function]': {
++ 'ignore': None,
++ },
++ 'void ns3::RandomVariable::GetSeed(uint32_t * seed) const [member function]': {
++ 'params': {'seed':{'direction':'out',
++ 'array_length':'6'}}
++ },
++ 'bool ns3::TypeId::LookupAttributeByName(std::string name, ns3::TypeId::AttributeInformation * info) const [member function]': {
++ 'params': {'info':{'transfer_ownership': 'false'}}
++ },
++ 'static bool ns3::TypeId::LookupByNameFailSafe(std::string name, ns3::TypeId * tid) [member function]': {
++ 'ignore': None, # manually wrapped in
++ },
++ 'bool ns3::TraceSourceAccessor::ConnectWithoutContext(ns3::ObjectBase * obj, ns3::CallbackBase const & cb) const [member function]': {
++ 'params': {'obj': {'transfer_ownership':'false'}}
++ },
++ 'bool ns3::TraceSourceAccessor::Connect(ns3::ObjectBase * obj, std::string context, ns3::CallbackBase const & cb) const [member function]': {
++ 'params': {'obj': {'transfer_ownership':'false'}}
++ },
++ 'bool ns3::TraceSourceAccessor::DisconnectWithoutContext(ns3::ObjectBase * obj, ns3::CallbackBase const & cb) const [member function]': {
++ 'params': {'obj': {'transfer_ownership':'false'}}
++ },
++ 'bool ns3::TraceSourceAccessor::Disconnect(ns3::ObjectBase * obj, std::string context, ns3::CallbackBase const & cb) const [member function]': {
++ 'params': {'obj': {'transfer_ownership':'false'}}
++ },
++ 'bool ns3::AttributeAccessor::Set(ns3::ObjectBase * object, ns3::AttributeValue const & value) const [member function]': {
++ 'params': {'object': {'transfer_ownership':'false'}}
++ },
++ 'ns3::EmpiricalVariable::EmpiricalVariable(ns3::RandomVariableBase const & variable) [constructor]': {
++ 'ignore': None
++ },
++ 'static ns3::AttributeList * ns3::AttributeList::GetGlobal() [member function]': {
++ 'caller_owns_return': 'false'
++ },
++ 'void ns3::CommandLine::Parse(int argc, char * * argv) const [member function]': {
++ 'ignore': None # manually wrapped
++ },
++ 'extern void ns3::PythonCompleteConstruct(ns3::Ptr<ns3::Object> object, ns3::TypeId typeId, ns3::AttributeList const & attributes) [free function]': {
++ 'ignore': None # used transparently by, should not be wrapped
++ },
++
++ 'ns3::Ptr<ns3::Ipv4RoutingProtocol> ns3::Ipv4ListRouting::GetRoutingProtocol(uint32_t index, int16_t & priority) const [member function]': {
++ 'params': {'priority':{'direction':'out'}}
++ },
++ 'ns3::Ipv4RoutingTableEntry * ns3::GlobalRouter::GetInjectedRoute(uint32_t i) [member function]': {
++ 'params': {'return': { 'caller_owns_return': 'false',}},
++ },
++ 'ns3::Ipv4RoutingTableEntry * ns3::Ipv4GlobalRouting::GetRoute(uint32_t i) const [member function]': {
++ 'params': {'return': { 'caller_owns_return': 'false',}},
++ },
++
++ '::ns3::TestCase': {
++ 'ignore': 'true', # we don't need to write test cases in Python
++ },
++ '::ns3::TestRunner': {
++ 'ignore': 'true', # we don't need to write test cases in Python
++ },
++ '::ns3::TestSuite': {
++ 'ignore': 'true', # we don't need to write test cases in Python
++ },
++
++ }
++
++def get_ns3_relative_path(path):
++ l = []
++ head = path
++ while head:
++ head, tail = os.path.split(head)
++ if tail == 'ns3':
++ return os.path.join(*l)
++ l.insert(0, tail)
++ raise AssertionError("is the path %r inside ns3?!" % path)
++
++
++def pre_scan_hook(dummy_module_parser,
++ pygccxml_definition,
++ global_annotations,
++ parameter_annotations):
++ ns3_header = get_ns3_relative_path(pygccxml_definition.location.file_name)
++
++ ## Note: we don't include line numbers in the comments because
++ ## those numbers are very likely to change frequently, which would
++ ## cause needless changes, since the generated python files are
++ ## kept under version control.
++
++ #global_annotations['pygen_comment'] = "%s:%i: %s" % \
++ # (ns3_header, pygccxml_definition.location.line, pygccxml_definition)
++ global_annotations['pygen_comment'] = "%s: %s" % \
++ (ns3_header, pygccxml_definition)
++
++
++ ## handle ns3::Object::GetObject (left to its own devices,
++ ## pybindgen will generate a mangled name containing the template
++ ## argument type name).
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Object' \
++ and pygccxml_definition.name == 'GetObject':
++ template_args = templates.args(pygccxml_definition.demangled_name)
++ if template_args == ['ns3::Object']:
++ global_annotations['template_instance_names'] = 'ns3::Object=>GetObject'
++
++ ## Don't wrap Simulator::Schedule* (manually wrapped)
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Simulator' \
++ and pygccxml_definition.name.startswith('Schedule'):
++ global_annotations['ignore'] = None
++
++ # manually wrapped
++ if isinstance(pygccxml_definition, member_function_t) \
++ and pygccxml_definition.parent.name == 'Simulator' \
++ and pygccxml_definition.name == 'Run':
++ global_annotations['ignore'] = True
++
++ ## http://www.gccxml.org/Bug/view.php?id=9915
++ if isinstance(pygccxml_definition, calldef_t):
++ for arg in pygccxml_definition.arguments:
++ if arg.default_value is None:
++ continue
++ if "ns3::MilliSeconds( )" == arg.default_value:
++ arg.default_value = "ns3::MilliSeconds(0)"
++ if "ns3::Seconds( )" == arg.default_value:
++ arg.default_value = "ns3::Seconds(0)"
++
++ ## classes
++ if isinstance(pygccxml_definition, class_t):
++ # no need for helper classes to allow subclassing in Python, I think...
++ #if pygccxml_definition.name.endswith('Helper'):
++ # global_annotations['allow_subclassing'] = 'false'
++
++ if pygccxml_definition.decl_string.startswith('::ns3::SimpleRefCount<'):
++ global_annotations['incref_method'] = 'Ref'
++ global_annotations['decref_method'] = 'Unref'
++ global_annotations['peekref_method'] = 'GetReferenceCount'
++ global_annotations['automatic_type_narrowing'] = 'true'
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::Callback<'):
++ # manually handled in ns3modulegen_core_customizations.py
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::TracedCallback<'):
++ global_annotations['ignore'] = None
++ return
++
++ if pygccxml_definition.decl_string.startswith('::ns3::Ptr<'):
++ # handled by pybindgen "type transformation"
++ global_annotations['ignore'] = None
++ return
++
++ # table driven class customization
++ try:
++ annotations = type_annotations[pygccxml_definition.decl_string]
++ except KeyError:
++ pass
++ else:
++ global_annotations.update(annotations)
++
++ ## free functions
++ if isinstance(pygccxml_definition, free_function_t):
++ if pygccxml_definition.name == 'PeekPointer':
++ global_annotations['ignore'] = None
++ return
++
++ ## table driven methods/constructors/functions customization
++ if isinstance(pygccxml_definition, (free_function_t, member_function_t, constructor_t)):
++ try:
++ annotations = type_annotations[str(pygccxml_definition)]
++ except KeyError:
++ pass
++ else:
++ for key,value in annotations.items():
++ if key == 'params':
++ parameter_annotations.update (value)
++ del annotations['params']
++ global_annotations.update(annotations)
++
++
++# def post_scan_hook(dummy_module_parser, dummy_pygccxml_definition, pybindgen_wrapper):
++# ## classes
++# if isinstance(pybindgen_wrapper, CppClass):
++# if pybindgen_wrapper.name.endswith('Checker'):
++# print >> sys.stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", pybindgen_wrapper
++# #pybindgen_wrapper.set_instance_creation_function(AttributeChecker_instance_creation_function)
++
++
++def scan_callback_classes(module_parser, callback_classes_file):
++ callback_classes_file.write("callback_classes = [\n")
++ for cls in module_parser.module_namespace.classes(function=module_parser.location_filter,
++ recursive=False):
++ if not cls.name.startswith("Callback<"):
++ continue
++ assert templates.is_instantiation(cls.decl_string), "%s is not a template instantiation" % cls
++ dummy_cls_name, template_parameters = templates.split(cls.decl_string)
++ callback_classes_file.write(" %r,\n" % template_parameters)
++ callback_classes_file.write("]\n")
++
++
++class MyPygenClassifier(PygenClassifier):
++ def __init__(self, headers_map, section_precendences):
++ self.headers_map = headers_map
++ self.section_precendences = section_precendences
++
++ def classify(self, pygccxml_definition):
++ name = os.path.basename(pygccxml_definition.location.file_name)
++ try:
++ return self.headers_map[name]
++ except KeyError:
++ return '__main__'
++
++ def get_section_precedence(self, section_name):
++ if section_name == '__main__':
++ return -1
++ return self.section_precendences[section_name]
++
++
++def ns3_module_scan(top_builddir, pygen_file_name, everything_h, cflags):
++
++ ns3_modules = eval(sys.stdin.readline())
++
++ ## do a topological sort on the modules graph
++ from topsort import topsort
++ graph = []
++ module_names = ns3_modules.keys()
++ module_names.sort()
++ for ns3_module_name in module_names:
++ ns3_module_deps = list(ns3_modules[ns3_module_name][0])
++ ns3_module_deps.sort()
++ for dep in ns3_module_deps:
++ graph.append((dep, ns3_module_name))
++ sorted_ns3_modules = topsort(graph)
++ #print >> sys.stderr, "******* topological sort: ", sorted_ns3_modules
++
++ sections = [PygenSection('__main__', FileCodeSink(open(pygen_file_name, "wt")))]
++ headers_map = {} # header_name -> section_name
++ section_precendences = {} # section_name -> precedence
++ for prec, ns3_module in enumerate(sorted_ns3_modules):
++ section_name = "ns3_module_%s" % ns3_module.replace('-', '_')
++ file_name = os.path.join(os.path.dirname(pygen_file_name), "%s.py" % section_name)
++ sections.append(PygenSection(section_name, FileCodeSink(open(file_name, "wt")),
++ section_name + "__local"))
++ for header in ns3_modules[ns3_module][1]:
++ headers_map[header] = section_name
++ section_precendences[section_name] = prec
++
++ module_parser = ModuleParser('ns3', 'ns3')
++
++ module_parser.add_pre_scan_hook(pre_scan_hook)
++ #module_parser.add_post_scan_hook(post_scan_hook)
++
++ gccxml_options = dict(
++ include_paths=[top_builddir],
++ define_symbols={
++ #'NS3_ASSERT_ENABLE': None,
++ #'NS3_LOG_ENABLE': None,
++ },
++ cflags=('--gccxml-cxxflags "%s -DPYTHON_SCAN"' % cflags)
++ )
++
++ module_parser.parse_init([everything_h],
++ None, whitelist_paths=[top_builddir, os.path.dirname(everything_h)],
++ #includes=['"ns3/everything.h"'],
++ pygen_sink=sections,
++ pygen_classifier=MyPygenClassifier(headers_map, section_precendences),
++ gccxml_options=gccxml_options)
++ module_parser.scan_types()
++
++ callback_classes_file = open(os.path.join(os.path.dirname(pygen_file_name), "callbacks_list.py"), "wt")
++ scan_callback_classes(module_parser, callback_classes_file)
++ callback_classes_file.close()
++
++
++ module_parser.scan_methods()
++ module_parser.scan_functions()
++ module_parser.parse_finalize()
++
++ for section in sections:
++ section.code_sink.file.close()
++
++
++
++if __name__ == '__main__':
++ ns3_module_scan(sys.argv[1], sys.argv[3], sys.argv[2], sys.argv[4])
++
+diff --git a/bindings/ns3modulescan.pyc b/bindings/ns3modulescan.pyc
+new file mode 100644
+index 0000000000000000000000000000000000000000..c7d2db0c669ed9783e23ca852462136e50bdfe0e
+GIT binary patch
+literal 10599
+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
+
+diff --git a/bindings/ns__init__.py b/bindings/ns__init__.py
+new file mode 100644
+--- /dev/null
++++ b/bindings/ns__init__.py
+@@ -0,0 +1,1 @@
++
+diff --git a/bindings/wscript b/bindings/wscript
+new file mode 100644
+--- /dev/null
++++ b/bindings/wscript
+@@ -0,0 +1,655 @@
++## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
++import types
++import re
++import os
++import subprocess
++import shutil
++import sys
++import warnings
++
++import Task
++import Options
++import Configure
++import TaskGen
++import Logs
++import Build
++import Utils
++import ns3waf
++
++from waflib.Errors import WafError
++
++## https://launchpad.net/pybindgen/
++REQUIRED_PYBINDGEN_VERSION = (0, 15, 0, 809)
++REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
++
++
++from TaskGen import feature, after
++import Task
++
++def add_to_python_path(path):
++ if os.environ.get('PYTHONPATH', ''):
++ os.environ['PYTHONPATH'] = path + os.pathsep + os.environ.get('PYTHONPATH')
++ else:
++ os.environ['PYTHONPATH'] = path
++
++def set_pybindgen_pythonpath(env):
++ env['WITH_PYBINDGEN'] = '../pybindgen'
++ if env['WITH_PYBINDGEN']:
++ add_to_python_path(env['WITH_PYBINDGEN'])
++
++def options(opt):
++ opt.tool_options('python')
++ opt.add_option('--apiscan',
++ help=("Rescan the API for the indicated module(s), for Python bindings. "
++ "Needs working GCCXML / pygccxml environment. "
++ "The metamodule 'all' expands to all available ns-3 modules."),
++ default=None, dest='apiscan', metavar="MODULE[,MODULE...]")
++
++def _check_nonfatal(conf, *args, **kwargs):
++ try:
++ return conf.check(*args, **kwargs)
++ except conf.errors.ConfigurationError:
++ return None
++
++def configure(conf):
++ # conf.env['ENABLE_PYTHON_BINDINGS'] = False
++ # if Options.options.python_disable:
++ # conf.report_optional_feature("python", "Python Bindings", False,
++ # "disabled by user request")
++ # return
++ # Disable python in static builds (bug #1253)
++ if ((conf.env['ENABLE_STATIC_NS3']) or \
++ (conf.env['ENABLE_SHARED_AND_STATIC_NS3'])):
++ conf.report_optional_feature("python", "Python Bindings", False,
++ "bindings incompatible with static build")
++ return
++
++ enabled_modules = list(conf.env['NS3_ENABLED_MODULES'])
++ enabled_modules.sort()
++ available_modules = list(conf.env['NS3_MODULES'])
++ available_modules.sort()
++ all_modules_enabled = (enabled_modules == available_modules)
++
++ conf.check_tool('misc', tooldir=['waf-tools'])
++
++ if sys.platform == 'cygwin':
++ conf.report_optional_feature("python", "Python Bindings", False,
++ "unsupported platform 'cygwin'")
++ Logs.warn("Python is not supported in CygWin environment. Try MingW instead.")
++ return
++
++
++ ## Check for Python
++
++ # if Options.options.with_python is not None:
++ # conf.env.PYTHON = Options.options.with_python
++
++ try:
++ conf.check_tool('python')
++ except Configure.ConfigurationError, ex:
++ conf.report_optional_feature("python", "Python Bindings", False,
++ "The python interpreter was not found")
++ return
++ try:
++ conf.check_python_version((2,3))
++ except Configure.ConfigurationError, ex:
++ conf.report_optional_feature("python", "Python Bindings", False,
++ "The python found version is too low (2.3 required)")
++ return
++ try:
++ conf.check_python_headers()
++ except Configure.ConfigurationError, ex:
++ conf.report_optional_feature("python", "Python Bindings", False,
++ "Python library or headers missing")
++ return
++
++ # stupid Mac OSX Python wants to build extensions as "universal
++ # binaries", i386, x86_64, and ppc, but this way the type
++ # __uint128_t is not available. We need to disable the multiarch
++ # crap by removing the -arch parameters.
++ for flags_var in ["CFLAGS_PYEXT", "CFLAGS_PYEMBED", "CXXFLAGS_PYEMBED",
++ "CXXFLAGS_PYEXT", "LINKFLAGS_PYEMBED", "LINKFLAGS_PYEXT"]:
++ flags = conf.env[flags_var]
++ i = 0
++ while i < len(flags):
++ if flags[i] == '-arch':
++ del flags[i]
++ del flags[i]
++ continue
++ i += 1
++ conf.env[flags_var] = flags
++
++ # -fvisibility=hidden optimization
++ # if (conf.env['CXX_NAME'] == 'gcc' and [int(x) for x in conf.env['CC_VERSION']] >= [4,0,0]
++ # and conf.check_compilation_flag('-fvisibility=hidden')):
++ conf.env.append_value('CXXFLAGS_PYEXT', '-fvisibility=hidden')
++ conf.env.append_value('CCFLAGS_PYEXT', '-fvisibility=hidden')
++
++ # if conf.check_compilation_flag('-Wno-array-bounds'):
++ conf.env.append_value('CXXFLAGS_PYEXT', '-Wno-array-bounds')
++
++ # Check for the location of pybindgen
++ # if Options.options.with_pybindgen is not None:
++ # if os.path.isdir(Options.options.with_pybindgen):
++ # conf.msg("Checking for pybindgen location", ("%s (given)" % Options.options.with_pybindgen))
++ # conf.env['WITH_PYBINDGEN'] = os.path.abspath(Options.options.with_pybindgen)
++ # else:
++ # # ns-3-dev uses ../pybindgen, while ns-3 releases use ../REQUIRED_PYBINDGEN_VERSION
++ # pybindgen_dir = os.path.join('..', "pybindgen")
++ # pybindgen_release_str = "pybindgen-" + '.'.join([str(x) for x in REQUIRED_PYBINDGEN_VERSION])
++ # pybindgen_release_dir = os.path.join('..', pybindgen_release_str)
++ # if os.path.isdir(pybindgen_dir):
++ # conf.msg("Checking for pybindgen location", ("%s (guessed)" % pybindgen_dir))
++ # conf.env['WITH_PYBINDGEN'] = os.path.abspath(pybindgen_dir)
++ # elif os.path.isdir(pybindgen_release_dir):
++ # conf.msg("Checking for pybindgen location", ("%s (guessed)" % pybindgen_release_dir))
++ # conf.env['WITH_PYBINDGEN'] = os.path.abspath(pybindgen_release_dir)
++ # del pybindgen_dir
++ # del pybindgen_release_dir
++ # if not conf.env['WITH_PYBINDGEN']:
++ # conf.msg("Checking for pybindgen location", False)
++
++ # Check for pybindgen
++
++ set_pybindgen_pythonpath(conf.env)
++
++ # try:
++ # conf.check_python_module('pybindgen')
++ # except Configure.ConfigurationError:
++ # Logs.warn("pybindgen missing => no python bindings")
++ # conf.report_optional_feature("python", "Python Bindings", False,
++ # "PyBindGen missing")
++ # return
++ # else:
++ # out = subprocess.Popen([conf.env['PYTHON'][0], "-c",
++ # "import pybindgen.version; "
++ # "print '.'.join([str(x) for x in pybindgen.version.__version__])"],
++ # stdout=subprocess.PIPE).communicate()[0]
++ # pybindgen_version_str = out.strip()
++ # pybindgen_version = tuple([int(x) for x in pybindgen_version_str.split('.')])
++ # conf.msg('Checking for pybindgen version', pybindgen_version_str)
++ # if not (pybindgen_version == REQUIRED_PYBINDGEN_VERSION):
++ # Logs.warn("pybindgen (found %s), (need %s)" %
++ # (pybindgen_version_str,
++ # '.'.join([str(x) for x in REQUIRED_PYBINDGEN_VERSION])))
++ # conf.report_optional_feature("python", "Python Bindings", False,
++ # "PyBindGen version not correct and newer version could not be retrieved")
++ # return
++
++
++ def test(t1, t2):
++ test_program = '''
++#include <stdint.h>
++#include <vector>
++
++int main ()
++{
++ std::vector< %(type1)s > t = std::vector< %(type2)s > ();
++ return 0;
++}
++''' % dict(type1=t1, type2=t2)
++
++ try:
++ ret = conf.run_c_code(code=test_program,
++ env=conf.env.copy(), compile_filename='test.cc',
++ features='cxx cprogram', execute=False)
++ except Configure.ConfigurationError:
++ ret = 1
++ conf.msg('Checking for types %s and %s equivalence' % (t1, t2), (ret and 'no' or 'yes'))
++ return not ret
++
++ uint64_is_long = test("uint64_t", "unsigned long")
++ uint64_is_long_long = test("uint64_t", "unsigned long long")
++
++ if uint64_is_long:
++ conf.env['PYTHON_BINDINGS_APIDEFS'] = 'gcc-LP64'
++ elif uint64_is_long_long:
++ conf.env['PYTHON_BINDINGS_APIDEFS'] = 'gcc-ILP32'
++ else:
++ conf.env['PYTHON_BINDINGS_APIDEFS'] = None
++ if conf.env['PYTHON_BINDINGS_APIDEFS'] is None:
++ msg = 'none available'
++ else:
++ msg = conf.env['PYTHON_BINDINGS_APIDEFS']
++
++ conf.msg('Checking for the apidefs that can be used for Python bindings', msg)
++
++ if conf.env['PYTHON_BINDINGS_APIDEFS'] is None:
++ ns3waf._report_optional_feature(conf, "python", "Python Bindings", False,
++ "No apidefs are available that can be used in this system")
++ return
++
++
++ ## If all has gone well, we finally enable the Python bindings
++ conf.env['ENABLE_PYTHON_BINDINGS'] = True
++ ns3waf._report_optional_feature(conf, "python", "Python Bindings", True, None)
++
++
++ # check cxxabi stuff (which Mac OS X Lion breaks)
++ fragment = r"""
++# include <cxxabi.h>
++int main ()
++{
++ const abi::__si_class_type_info *_typeinfo __attribute__((unused)) = NULL;
++ return 0;
++}
++"""
++ gcc_rtti_abi = _check_nonfatal(conf, fragment=fragment, msg="Checking for internal GCC cxxabi",
++ okmsg="complete", errmsg='incomplete',
++ mandatory=False)
++ conf.env["GCC_RTTI_ABI_COMPLETE"] = str(bool(gcc_rtti_abi))
++
++
++
++ ## Check for pygccxml
++ try:
++ conf.check_python_module('pygccxml')
++ except Configure.ConfigurationError:
++ ns3waf._report_optional_feature(conf, "pygccxml", "Python API Scanning Support", False,
++ "Missing 'pygccxml' Python module")
++ return
++
++ out = subprocess.Popen([conf.env['PYTHON'][0], "-c",
++ "import pygccxml; print pygccxml.__version__"],
++ stdout=subprocess.PIPE).communicate()[0]
++ pygccxml_version_str = out.strip()
++ pygccxml_version = tuple([int(x) for x in pygccxml_version_str.split('.')])
++ conf.msg('Checking for pygccxml version', pygccxml_version_str)
++ if not (pygccxml_version >= REQUIRED_PYGCCXML_VERSION):
++ Logs.warn("pygccxml (found %s) is too old (need %s) => "
++ "automatic scanning of API definitions will not be possible" %
++ (pygccxml_version_str,
++ '.'.join([str(x) for x in REQUIRED_PYGCCXML_VERSION])))
++ ns3waf._report_optional_feature(conf, "pygccxml", "Python API Scanning Support", False,
++ "pygccxml too old")
++ return
++
++
++ ## Check gccxml version
++ try:
++ gccxml = conf.find_program('gccxml', var='GCCXML')
++ except WafError:
++ gccxml = None
++ if not gccxml:
++ Logs.warn("gccxml missing; automatic scanning of API definitions will not be possible")
++ ns3waf._report_optional_feature(conf, "pygccxml", "Python API Scanning Support", False,
++ "gccxml missing")
++ return
++
++ gccxml_version_line = os.popen(gccxml + " --version").readline().strip()
++ m = re.match( "^GCC-XML version (\d\.\d(\.\d)?)$", gccxml_version_line)
++ gccxml_version = m.group(1)
++ gccxml_version_ok = ([int(s) for s in gccxml_version.split('.')] >= [0, 9])
++ conf.msg('Checking for gccxml version', gccxml_version)
++ if not gccxml_version_ok:
++ Logs.warn("gccxml too old, need version >= 0.9; automatic scanning of API definitions will not be possible")
++ ns3waf._report_optional_feature(conf, "pygccxml", "Python API Scanning Support", False,
++ "gccxml too old")
++ return
++
++ ## If we reached
++ conf.env['ENABLE_PYTHON_SCANNING'] = True
++ ns3waf._report_optional_feature(conf, "pygccxml", "Python API Scanning Support", True, None)
++
++# ---------------------
++def get_headers_map(headers, module):
++ headers_map = {} # header => module
++ for header in headers:
++ headers_map[os.path.basename(header)] = module
++ return headers_map
++# def get_headers_map(bld, module):
++# headers_map = {} # header => module
++# for ns3headers in bld.all_task_gen:
++# if 'ns3header' in getattr(ns3headers, "headers", []):
++# if ns3headers.name.find('lib/ns3-') is -1:
++# continue
++# if ns3headers.name.find('-test') is not -1:
++# continue
++# for h in ns3headers.to_list(ns3headers.headers):
++# print "h = %s" % h
++# headers_map[os.path.basename(h)] = ns3headers.module
++# return headers_map
++
++def get_module_path(bld, module):
++ for ns3headers in bld.all_task_gen:
++ if 'ns3header' in getattr(ns3headers, "features", []):
++ if ns3headers.module == module:
++ break
++ else:
++ raise ValueError("Module %r not found" % module)
++ return ns3headers.path.abspath()
++
++def python_bin_scan(bld, target, module):
++ for root, dirs, files in os.walk(str(module.bld.bldnode)):
++ for f in files:
++ if os.path.basename(module.headers[0]) == f:
++ # XXX: FIXME
++ top_builddir = os.path.dirname(os.path.join(root, f)).replace('/ns3','')
++ out_topdir = os.path.dirname(os.path.join(root, f)).replace('build/','./').replace('include/ns3','')
++
++ argv = [
++ 'python',
++ os.path.join('bindings', 'ns3modulescan-modular.py'), # scanning script
++ top_builddir, #'build/include',
++ module.name.split('lib/ns3-')[1], #self.module,
++ repr(get_headers_map(module.headers, module.name.split('lib/ns3-')[1])), #repr(get_headers_map(bld, module)),
++ os.path.join(out_topdir, "bindings", 'modulegen__%s.py' % (target)), # output file
++ # XXX: FIXME
++ "-I../build/include/ns3-dev -I./build/include/", #self.cflags,
++ ]
++ print argv
++ scan = subprocess.Popen(argv, stdin=subprocess.PIPE)
++ retval = scan.wait()
++ return retval
++
++class apiscan_task(Task.TaskBase):
++ """Uses gccxml to scan the file 'everything.h' and extract API definitions.
++ """
++ after = 'gen_ns3_module_header ns3header'
++ before = 'cc cxx command'
++ color = "BLUE"
++ def __init__(self, curdirnode, env, bld, target, cflags, module):
++ self.bld = bld
++ super(apiscan_task, self).__init__(generator=self)
++ self.curdirnode = curdirnode
++ self.env = env
++ self.target = target
++ self.cflags = cflags
++ self.module = module
++
++ def display(self):
++ return 'api-scan-%s\n' % (self.target,)
++
++ def run(self):
++ top_builddir = self.bld.bldnode.abspath()
++ #module_path = get_module_path(self.bld, self.module)
++ #headers_map = get_headers_map(self.bld)
++ # scan_header = os.path.join(top_builddir, "ns3", "%s-module.h" % self.module)
++
++ # if not os.path.exists(scan_header):
++ # Logs.error("Cannot apiscan module %r: %s does not exist" % (self.module, scan_header))
++ # return 0
++
++ # python scan
++ retval = python_bin_scan(self.bld, self.target, self.module)
++ return retval
++
++
++def get_modules_and_headers(bld):
++ """
++ Gets a dict of
++ module_name => ([module_dep1, module_dep2, ...], [module_header1, module_header2, ...])
++ tuples, one for each module.
++ """
++
++ retval = {}
++ for module in bld.all_task_gen:
++ if not module.name.startswith('ns3-'):
++ continue
++ if module.name.endswith('-test'):
++ continue
++ module_name = module.name[4:] # strip the ns3- prefix
++ ## find the headers object for this module
++ headers = []
++ for ns3headers in bld.all_task_gen:
++ if 'ns3header' not in getattr(ns3headers, "features", []):
++ continue
++ if ns3headers.module != module_name:
++ continue
++ for source in ns3headers.to_list(ns3headers.headers):
++ headers.append(os.path.basename(source))
++ retval[module_name] = (list(module.module_deps), headers)
++ return retval
++
++
++
++
++class python_scan_task_collector(Task.TaskBase):
++ """Tasks that waits for the python-scan-* tasks to complete and then signals WAF to exit
++ """
++ after = 'apiscan'
++ before = 'cc cxx'
++ color = "BLUE"
++ def __init__(self, curdirnode, env, bld):
++ self.bld = bld
++ super(python_scan_task_collector, self).__init__(generator=self)
++ self.curdirnode = curdirnode
++ self.env = env
++
++ def display(self):
++ return 'python-scan-collector\n'
++
++ def run(self):
++ # signal stop (we generated files into the source dir and WAF
++ # can't cope with it, so we have to force the user to restart
++ # WAF)
++ self.bld.producer.stop = 1
++ return 0
++
++
++
++class gen_ns3_compat_pymod_task(Task.Task):
++ """Generates a 'ns3.py' compatibility module."""
++ before = 'cc cxx'
++ color = 'BLUE'
++
++ def run(self):
++ assert len(self.outputs) == 1
++ outfile = file(self.outputs[0].abspath(), "w")
++ print >> outfile, "import warnings"
++ print >> outfile, 'warnings.warn("the ns3 module is a compatibility layer '\
++ 'and should not be used in newly written code", DeprecationWarning, stacklevel=2)'
++ print >> outfile
++ for module in self.bld.env['PYTHON_MODULES_BUILT']:
++ print >> outfile, "from ns.%s import *" % (module.replace('-', '_'))
++ outfile.close()
++ return 0
++
++
++def _ns3_python_apiscan(bld):
++ env = bld.env
++ #if not env['ENABLE_PYTHON_SCANNING']:
++ # raise WafError("Cannot re-scan python bindings: (py)gccxml not available")
++ scan_targets = []
++ if sys.platform == 'cygwin':
++ scan_targets.append(('gcc_cygwin', ''))
++ else:
++ import struct
++ if struct.calcsize('I') == 4 and struct.calcsize('L') == 8 and struct.calcsize('P') == 8:
++ scan_targets.extend([('gcc_ILP32', '-m32'), ('gcc_LP64', '-m64')])
++ elif struct.calcsize('I') == 4 and struct.calcsize('L') == 4 and struct.calcsize('P') == 4:
++ scan_targets.append(('gcc_ILP32', ''))
++ else:
++ raise WafError("Cannot scan python bindings for unsupported data model")
++
++ test_module_path = bld.path.find_dir("./test")
++ scan_modules = []
++ for mod in bld.all_task_gen:
++ if hasattr(mod, 'name') is False:
++ continue
++ if mod.name.find('lib/ns3-') is -1:
++ continue
++ if mod.name.find('-test') is not -1:
++ continue
++ #bindings_enabled = (mod.name in env.MODULAR_BINDINGS_MODULES)
++ bindings_enabled = True
++ #print mod.name, bindings_enabled
++ if bindings_enabled:
++ if Options.options.apiscan == 'all':
++ #scan_modules.append(mod.name.split('lib/ns3-')[1])
++ scan_modules.append(mod)
++ else:
++ if mod.name.split('lib/ns3-')[1] == Options.options.apiscan:
++ scan_modules.append(mod)
++ print "Modules to scan: ", [mod.name for mod in scan_modules]
++ for target, cflags in scan_targets:
++ group = bld.get_group(bld.current_group)
++ for module in scan_modules:
++ group.append(apiscan_task(bld.path, env, bld, target, cflags, module))
++ group.append(python_scan_task_collector(bld.path, env, bld))
++ return
++
++def _ns3_python_bindings(bld, module):
++ for root, dirs, files in os.walk(str(module.bld.bldnode)):
++ for f in files:
++ if os.path.basename(module.headers[0]) == f:
++ # XXX: FIXME
++ out_binding_dir = os.path.dirname(os.path.join(root, f)).replace('/include/ns3','').replace('build','./')
++ include_dir = '../' + os.path.dirname(os.path.join(root, f)).replace('/ns3','').replace('build','./')
++
++ # this method is called from a module wscript, so remember bld.path is not bindings/python!
++ module_abs_src_path = os.path.abspath(os.path.join('build', out_binding_dir))
++ # module = os.path.basename(module_abs_src_path)
++ env = bld.env
++ # env.append_value("MODULAR_BINDINGS_MODULES", "ns3-"+module)
++
++ # if Options.options.apiscan:
++ # return
++
++ # if not env['ENABLE_PYTHON_BINDINGS']:
++ # return
++
++ bindings_dir = bld.path
++ if bindings_dir is None or not os.path.exists(bindings_dir.abspath()):
++ warnings.warn("(in %s) Requested to build modular python bindings, but apidefs dir not found "
++ "=> skipped the bindings." % str(bld.path),
++ Warning, stacklevel=2)
++ return
++
++ # if ("ns3-%s" % (module,)) not in env.NS3_ENABLED_MODULES:
++ # #print "bindings for module %s which is not enabled, skip" % module
++ # return
++
++ #env.append_value('PYTHON_MODULES_BUILT', module)
++ apidefs = env['PYTHON_BINDINGS_APIDEFS'].replace("-", "_")
++
++ #debug = ('PYBINDGEN_DEBUG' in os.environ)
++ debug = True # XXX
++ source = [bld.srcnode.find_resource('bindings/ns3modulegen-modular.py').relpath_gen(bld.path),
++ "modulegen__%s.py" % apidefs]
++
++ if bindings_dir.find_resource("modulegen_customizations.py") is not None:
++ source.append("bindings/modulegen_customizations.py")
++
++ # the local customization file may or not exist
++ if bld.path.find_resource("bindings/modulegen_local.py"):
++ source.append("bindings/modulegen_local.py")
++
++ module_py_name = module.name.split('lib/ns3-')[1].replace('-', '_')
++ module_target_dir = bld.srcnode.find_dir("bindings/ns").relpath_gen(bld.path)
++
++ # if bindings/<module>.py exists, it becomes the module frontend, and the C extension befomes _<module>
++ if bld.path.find_resource("bindings/%s.py" % (module_py_name,)) is not None:
++ bld.new_task_gen(
++ features='copy',
++ source=("bindings/%s.py" % (module_py_name,)),
++ target=('%s/%s.py' % (module_target_dir, module_py_name)))
++ extension_name = '_%s' % (module_py_name,)
++ bld.install_files('${PYTHONARCHDIR}/ns', ["bindings/%s.py" % (module_py_name,)])
++ else:
++ extension_name = module_py_name
++
++ target = ['../' + out_binding_dir + '/bindings/ns3module.cc',
++ '../' + out_binding_dir + '/bindings/ns3module.h',
++ '../' + out_binding_dir + '/bindings/ns3modulegen.log']
++ #if not debug:
++ # target.append('ns3modulegen.log')
++
++ argv = ['NS3_ENABLED_FEATURES=${FEATURES}',
++ 'GCC_RTTI_ABI_COMPLETE=${GCC_RTTI_ABI_COMPLETE}',
++ '${PYTHON}']
++ #if debug:
++ # argv.extend(["-m", "pdb"])
++
++ argv.extend(['${SRC[0]}', module_abs_src_path, apidefs, extension_name, '${TGT[0]}'])
++
++ argv.extend(['2>', '${TGT[2]}']) # 2> ns3modulegen.log
++
++ features = []
++ for (name, caption, was_enabled, reason_not_enabled) in env['NS3_OPTIONAL_FEATURES']:
++ if was_enabled:
++ features.append(name)
++
++ bindgen = bld.new_task_gen(features=['command'], source=source, target=target, command=argv)
++ bindgen.env['FEATURES'] = ','.join(features)
++ bindgen.dep_vars = ['FEATURES', "GCC_RTTI_ABI_COMPLETE"]
++ bindgen.before = 'cxx'
++ bindgen.after = 'gen_ns3_module_header'
++ bindgen.name = "pybindgen(ns3 module %s)" % module.name.split('lib/ns3-')[1]
++ bindgen.install_path = None
++
++ # generate the extension module
++ pymod = bld.new_task_gen(features='cxx cxxshlib pyext')
++ pymod.source = ['../' + out_binding_dir + '/bindings/ns3module.cc']
++ pymod.target = '%s/%s' % (module_target_dir, extension_name)
++ pymod.name = 'ns3module_%s' % module.name.split('lib/ns3-')[1]
++ pymod.use = ["%s" % mod for mod in pymod.env['NS3_ENABLED_MODULES']] # Should be '"ns3-"+module', but see bug 1117
++ if pymod.env['ENABLE_STATIC_NS3']:
++ if sys.platform == 'darwin':
++ pymod.env.append_value('LINKFLAGS', '-Wl,-all_load')
++ for mod in pymod.usel:
++ #mod = mod.split("--lib")[0]
++ pymod.env.append_value('LINKFLAGS', '-l' + mod)
++ else:
++ pymod.env.append_value('LINKFLAGS', '-Wl,--whole-archive,-Bstatic')
++ for mod in pymod.use:
++ #mod = mod.split("--lib")[0]
++ pymod.env.append_value('LINKFLAGS', '-l' + mod)
++ pymod.env.append_value('LINKFLAGS', '-Wl,-Bdynamic,--no-whole-archive')
++ defines = list(pymod.env['DEFINES'])
++ defines.extend(['NS_DEPRECATED=', 'NS3_DEPRECATED_H'])
++ if Options.platform == 'win32':
++ try:
++ defines.remove('_DEBUG') # causes undefined symbols on win32
++ except ValueError:
++ pass
++ pymod.env['DEFINES'] = defines
++ # XXX: FIXME
++ pymod.includes = '# ../include # ../../build/include/ns3-dev # ' + include_dir #'# bindings'
++ pymod.install_path = '${PYTHONARCHDIR}/ns'
++
++ # Workaround to a WAF bug, remove this when ns-3 upgrades to WAF > 1.6.10
++ # https://www.nsnam.org/bugzilla/show_bug.cgi?id=1335
++ # http://code.google.com/p/waf/issues/detail?id=1098
++ if Utils.unversioned_sys_platform() == 'darwin':
++ pymod.mac_bundle = True
++
++ return pymod
++
++def build(bld):
++ #if Options.options.python_disable:
++ # return
++
++ bld.ns3_python_apiscan = types.MethodType(_ns3_python_apiscan, bld)
++ bld.ns3_python_bindings = types.MethodType(_ns3_python_bindings, bld)
++ env = bld.env
++ curdir = bld.path.abspath()
++
++ set_pybindgen_pythonpath(env)
++
++ if Options.options.apiscan:
++ bld.ns3_python_apiscan()
++ return
++
++ if env['ENABLE_PYTHON_BINDINGS']:
++ task = gen_ns3_compat_pymod_task(env=env.derive())
++ task.set_outputs(bld.path.find_or_declare("ns3.py"))
++ task.dep_vars = ['PYTHON_MODULES_BUILT']
++ task.bld = bld
++ grp = bld.get_group(bld.current_group)
++ grp.append(task)
++
++ bld.new_task_gen(features='copy',
++ source="ns__init__.py",
++ target='ns/__init__.py')
++ bld.install_as('${PYTHONARCHDIR}/ns/__init__.py', 'ns__init__.py')
++
++ for mod in bld.all_task_gen:
++ if hasattr(mod, 'name') is False:
++ continue
++ if mod.name.find('lib/ns3-') is -1:
++ continue
++ if mod.name.find('-test') is not -1:
++ continue
++ bld.ns3_python_bindings(mod)
++
+diff --git a/example/dce-tcp-simple.py b/example/dce-tcp-simple.py
+new file mode 100644
+--- /dev/null
++++ b/example/dce-tcp-simple.py
+@@ -0,0 +1,21 @@
++# -*- coding: utf-8 -*-
++
++from ns.dce import *
++from ns.core import *
++from ns.network import *
++from ns.internet import *
++
++nodes = NodeContainer()
++nodes.Create (1)
++stack = InternetStackHelper()
++stack.Install (nodes)
++dceManager = DceManagerHelper()
++dceManager.Install (nodes);
++dce = DceApplicationHelper()
++apps = ApplicationContainer ()
++dce.SetBinary ("/ns3-dev-tcp-loopback-debug")
++dce.SetStackSize (1<<20)
++apps = dce.Install (nodes)
++apps.Start (Seconds (4.0))
++Simulator.Stop (Seconds(10.0))
++Simulator.Run ()
+diff --git a/test/netlink-socket-test.cc b/test/netlink-socket-test.cc
+--- a/test/netlink-socket-test.cc
++++ b/test/netlink-socket-test.cc
+@@ -33,8 +33,8 @@
+ #include "ns3/assert.h"
+ #include "ns3/log.h"
+ #include "ns3/socket.h"
+-#include "netlink-message.h"
+-#include "netlink-socket-address.h"
++#include "../netlink/netlink-message.h"
++#include "../netlink/netlink-socket-address.h"
+ #include <sys/socket.h>
+ #include <string>
+ #include <list>
+diff --git a/waf-tools/boost.py b/waf-tools/boost.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/boost.py
+@@ -0,0 +1,278 @@
++#!/usr/bin/env python
++# encoding: utf-8
++#
++# partially based on boost.py written by Gernot Vormayr
++# written by Ruediger Sonderfeld <ruediger@c-plusplus.de>, 2008
++# modified by Bjoern Michaelsen, 2008
++# modified by Luca Fossati, 2008
++# rewritten for waf 1.5.1, Thomas Nagy, 2008
++# rewritten for waf 1.6.2, Sylvain Rouquette, 2011
++
++'''
++To add the boost tool to the waf file:
++$ ./waf-light --tools=compat15,boost
++ or, if you have waf >= 1.6.2
++$ ./waf update --files=boost
++
++The wscript will look like:
++
++def options(opt):
++ opt.load('compiler_cxx boost')
++
++def configure(conf):
++ conf.load('compiler_cxx boost')
++ conf.check_boost(lib='system filesystem', mt=True, static=True)
++
++def build(bld):
++ bld(source='main.cpp', target='app', use='BOOST')
++'''
++
++import sys
++import re
++from waflib import Utils, Logs
++from waflib.Configure import conf
++from waflib.Errors import WafError
++
++BOOST_LIBS = ('/usr/lib', '/usr/local/lib',
++ '/opt/local/lib', '/sw/lib', '/lib')
++BOOST_INCLUDES = ('/usr/include', '/usr/local/include',
++ '/opt/local/include', '/sw/include')
++BOOST_VERSION_FILE = 'boost/version.hpp'
++BOOST_VERSION_CODE = '''
++#include <iostream>
++#include <boost/version.hpp>
++int main() { std::cout << BOOST_LIB_VERSION << std::endl; }
++'''
++
++# toolsets from {boost_dir}/tools/build/v2/tools/common.jam
++PLATFORM = Utils.unversioned_sys_platform()
++detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il'
++detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang'
++detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc'
++BOOST_TOOLSETS = {
++ 'borland': 'bcb',
++ 'clang': detect_clang,
++ 'como': 'como',
++ 'cw': 'cw',
++ 'darwin': 'xgcc',
++ 'edg': 'edg',
++ 'g++': detect_mingw,
++ 'gcc': detect_mingw,
++ 'icpc': detect_intel,
++ 'intel': detect_intel,
++ 'kcc': 'kcc',
++ 'kylix': 'bck',
++ 'mipspro': 'mp',
++ 'mingw': 'mgw',
++ 'msvc': 'vc',
++ 'qcc': 'qcc',
++ 'sun': 'sw',
++ 'sunc++': 'sw',
++ 'tru64cxx': 'tru',
++ 'vacpp': 'xlc'
++}
++
++
++def options(opt):
++ opt.add_option('--boost-includes', type='string',
++ default='', dest='boost_includes',
++ help='''path to the boost directory where the includes are
++ e.g. /boost_1_45_0/include''')
++ opt.add_option('--boost-libs', type='string',
++ default='', dest='boost_libs',
++ help='''path to the directory where the boost libs are
++ e.g. /boost_1_45_0/stage/lib''')
++ opt.add_option('--boost-static', action='store_true',
++ default=False, dest='boost_static',
++ help='link static libraries')
++ opt.add_option('--boost-mt', action='store_true',
++ default=False, dest='boost_mt',
++ help='select multi-threaded libraries')
++ opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
++ help='''select libraries with tags (dgsyp, d for debug),
++ see doc Boost, Getting Started, chapter 6.1''')
++ opt.add_option('--boost-toolset', type='string',
++ default='', dest='boost_toolset',
++ help='force a toolset e.g. msvc, vc90, \
++ gcc, mingw, mgw45 (default: auto)')
++ py_version = '%d%d' % (sys.version_info[0], sys.version_info[1])
++ opt.add_option('--boost-python', type='string',
++ default=py_version, dest='boost_python',
++ help='select the lib python with this version \
++ (default: %s)' % py_version)
++
++
++@conf
++def __boost_get_version_file(self, dir):
++ try:
++ return self.root.find_dir(dir).find_node(BOOST_VERSION_FILE)
++ except:
++ return None
++
++
++@conf
++def boost_get_version(self, dir):
++ """silently retrieve the boost version number"""
++ re_but = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"$', re.M)
++ try:
++ val = re_but.search(self.__boost_get_version_file(dir).read()).group(1)
++ except:
++ val = self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[dir],
++ execute=True, define_ret=True)
++ return val
++
++
++@conf
++def boost_get_includes(self, *k, **kw):
++ includes = k and k[0] or kw.get('includes', None)
++ if includes and self.__boost_get_version_file(includes):
++ return includes
++ for dir in BOOST_INCLUDES:
++ if self.__boost_get_version_file(dir):
++ return dir
++ if includes:
++ self.fatal('headers not found in %s' % includes)
++ else:
++ self.fatal('headers not found, use --boost-includes=/path/to/boost')
++
++
++@conf
++def boost_get_toolset(self, cc):
++ toolset = cc
++ if not cc:
++ build_platform = Utils.unversioned_sys_platform()
++ if build_platform in BOOST_TOOLSETS:
++ cc = build_platform
++ else:
++ cc = self.env.CXX_NAME
++ if cc in BOOST_TOOLSETS:
++ toolset = BOOST_TOOLSETS[cc]
++ return isinstance(toolset, str) and toolset or toolset(self.env)
++
++
++@conf
++def __boost_get_libs_path(self, *k, **kw):
++ ''' return the lib path and all the files in it '''
++ if 'files' in kw:
++ return self.root.find_dir('.'), Utils.to_list(kw['files'])
++ libs = k and k[0] or kw.get('libs', None)
++ if libs:
++ path = self.root.find_dir(libs)
++ files = path.ant_glob('*boost_*')
++ if not libs or not files:
++ for dir in BOOST_LIBS:
++ try:
++ path = self.root.find_dir(dir)
++ files = path.ant_glob('*boost_*')
++ if files:
++ break
++ path = self.root.find_dir(dir + '64')
++ files = path.ant_glob('*boost_*')
++ if files:
++ break
++ except:
++ path = None
++ if not path:
++ if libs:
++ self.fatal('libs not found in %s' % libs)
++ else:
++ self.fatal('libs not found, \
++ use --boost-includes=/path/to/boost/lib')
++ return path, files
++
++
++@conf
++def boost_get_libs(self, *k, **kw):
++ '''
++ return the lib path and the required libs
++ according to the parameters
++ '''
++ path, files = self.__boost_get_libs_path(**kw)
++ t = []
++ if kw.get('mt', False):
++ t.append('mt')
++ if kw.get('abi', None):
++ t.append(kw['abi'])
++ tags = t and '(-%s)+' % '-'.join(t) or ''
++ toolset = '(-%s[0-9]{0,3})+' % self.boost_get_toolset(kw.get('toolset', ''))
++ version = '(-%s)+' % self.env.BOOST_VERSION
++
++ def find_lib(re_lib, files):
++ for file in files:
++ if re_lib.search(file.name):
++ return file
++ return None
++
++ def format_lib_name(name):
++ if name.startswith('lib'):
++ name = name[3:]
++ return name.split('.')[0]
++
++ libs = []
++ for lib in Utils.to_list(k and k[0] or kw.get('lib', None)):
++ py = (lib == 'python') and '(-py%s)+' % kw['python'] or ''
++ # Trying libraries, from most strict match to least one
++ for pattern in ['boost_%s%s%s%s%s' % (lib, toolset, tags, py, version),
++ 'boost_%s%s%s%s' % (lib, tags, py, version),
++ 'boost_%s%s%s' % (lib, tags, version),
++ # Give up trying to find the right version
++ 'boost_%s%s%s%s' % (lib, toolset, tags, py),
++ 'boost_%s%s%s' % (lib, tags, py),
++ 'boost_%s%s' % (lib, tags)]:
++ file = find_lib(re.compile(pattern), files)
++ if file:
++ libs.append(format_lib_name(file.name))
++ break
++ else:
++ self.fatal('lib %s not found in %s' % (lib, path))
++
++ return path.abspath(), libs
++
++
++@conf
++def check_boost(self, *k, **kw):
++ """
++ initialize boost
++
++ You can pass the same parameters as the command line (without "--boost-"),
++ but the command line has the priority.
++ """
++ if not self.env['CXX']:
++ self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
++
++ params = {'lib': k and k[0] or kw.get('lib', None)}
++ for key, value in self.options.__dict__.items():
++ if not key.startswith('boost_'):
++ continue
++ key = key[len('boost_'):]
++ params[key] = value and value or kw.get(key, '')
++
++ var = kw.get('uselib_store', 'BOOST')
++
++ self.start_msg('Checking boost includes')
++ try:
++ self.env['INCLUDES_%s' % var] = self.boost_get_includes(**params)
++ self.env.BOOST_VERSION = self.boost_get_version(self.env['INCLUDES_%s' % var])
++ except WafError:
++ self.end_msg("not found", 'YELLOW')
++ raise
++ self.end_msg(self.env.BOOST_VERSION)
++ if Logs.verbose:
++ Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
++
++ if not params['lib']:
++ return
++ self.start_msg('Checking boost libs')
++ try:
++ suffix = params.get('static', 'ST') or ''
++ path, libs = self.boost_get_libs(**params)
++ except WafError:
++ self.end_msg("not found", 'YELLOW')
++ raise
++ self.env['%sLIBPATH_%s' % (suffix, var)] = [path]
++ self.env['%sLIB_%s' % (suffix, var)] = libs
++ self.end_msg('ok')
++ if Logs.verbose:
++ Logs.pprint('CYAN', ' path : %s' % path)
++ Logs.pprint('CYAN', ' libs : %s' % libs)
++
+diff --git a/waf-tools/cflags.py b/waf-tools/cflags.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/cflags.py
+@@ -0,0 +1,192 @@
++import Logs
++import Options
++import Utils
++
++
++class CompilerTraits(object):
++ def get_warnings_flags(self, level):
++ """get_warnings_flags(level) -> list of cflags"""
++ raise NotImplementedError
++
++ def get_optimization_flags(self, level):
++ """get_optimization_flags(level) -> list of cflags"""
++ raise NotImplementedError
++
++ def get_debug_flags(self, level):
++ """get_debug_flags(level) -> (list of cflags, list of cppdefines)"""
++ raise NotImplementedError
++
++
++class GccTraits(CompilerTraits):
++ def __init__(self):
++ super(GccTraits, self).__init__()
++ # cumulative list of warnings per level
++ self.warnings_flags = [['-Wall'], ['-Werror'], ['-Wextra']]
++
++ def get_warnings_flags(self, level):
++ warnings = []
++ for l in range(level):
++ if l < len(self.warnings_flags):
++ warnings.extend(self.warnings_flags[l])
++ else:
++ break
++ return warnings
++
++ def get_optimization_flags(self, level):
++ if level == 0:
++ return ['-O0']
++ elif level == 1:
++ return ['-O']
++ elif level == 2:
++ return ['-O2']
++ elif level == 3:
++ return ['-O3']
++
++ def get_debug_flags(self, level):
++ if level == 0:
++ return (['-g0'], ['NDEBUG'])
++ elif level == 1:
++ return (['-g'], [])
++ elif level >= 2:
++ return (['-ggdb', '-g3'], ['_DEBUG'])
++
++
++class IccTraits(CompilerTraits):
++ def __init__(self):
++ super(IccTraits, self).__init__()
++ # cumulative list of warnings per level
++ # icc is _very_ verbose with -Wall, -Werror is barely achievable
++ self.warnings_flags = [[], [], ['-Wall']]
++
++ def get_warnings_flags(self, level):
++ warnings = []
++ for l in range(level):
++ if l < len(self.warnings_flags):
++ warnings.extend(self.warnings_flags[l])
++ else:
++ break
++ return warnings
++
++ def get_optimization_flags(self, level):
++ if level == 0:
++ return ['-O0']
++ elif level == 1:
++ return ['-O']
++ elif level == 2:
++ return ['-O2']
++ elif level == 3:
++ return ['-O3']
++
++ def get_debug_flags(self, level):
++ if level == 0:
++ return (['-g0'], ['NDEBUG'])
++ elif level == 1:
++ return (['-g'], [])
++ elif level >= 2:
++ return (['-ggdb', '-g3'], ['_DEBUG'])
++
++
++
++class MsvcTraits(CompilerTraits):
++ def __init__(self):
++ super(MsvcTraits, self).__init__()
++ # cumulative list of warnings per level
++ self.warnings_flags = [['/W2'], ['/WX'], ['/Wall']]
++
++ def get_warnings_flags(self, level):
++ warnings = []
++ for l in range(level):
++ if l < len(self.warnings_flags):
++ warnings.extend(self.warnings_flags[l])
++ else:
++ break
++ return warnings
++
++ def get_optimization_flags(self, level):
++ if level == 0:
++ return ['/Od']
++ elif level == 1:
++ return []
++ elif level == 2:
++ return ['/O2']
++ elif level == 3:
++ return ['/Ox']
++
++ def get_debug_flags(self, level):
++ if level == 0:
++ return ([], ['NDEBUG'])
++ elif level == 1:
++ return (['/ZI', '/RTC1'], [])
++ elif level >= 2:
++ return (['/ZI', '/RTC1'], ['_DEBUG'])
++
++
++
++gcc = GccTraits()
++icc = IccTraits()
++msvc = MsvcTraits()
++
++# how to map env['COMPILER_CC'] or env['COMPILER_CXX'] into a traits object
++compiler_mapping = {
++ 'gcc': gcc,
++ 'g++': gcc,
++ 'msvc': msvc,
++ 'icc': icc,
++ 'icpc': icc,
++}
++
++profiles = {
++ # profile name: [optimization_level, warnings_level, debug_level]
++ 'default': [2, 1, 1],
++ 'debug': [0, 2, 3],
++ 'release': [3, 1, 0],
++ }
++
++default_profile = 'default'
++
++def options(opt):
++ assert default_profile in profiles
++ opt.add_option('-d', '--build-profile',
++ action='store',
++ default=default_profile,
++ help=("Specify the build profile. "
++ "Build profiles control the default compilation flags"
++ " used for C/C++ programs, if CCFLAGS/CXXFLAGS are not"
++ " set set in the environment. [Allowed Values: %s]"
++ % ", ".join([repr(p) for p in profiles.keys()])),
++ choices=profiles.keys(),
++ dest='build_profile')
++
++def configure(conf):
++ cc = conf.env['COMPILER_CC'] or None
++ cxx = conf.env['COMPILER_CXX'] or None
++ if not (cc or cxx):
++ raise Utils.WafError("neither COMPILER_CC nor COMPILER_CXX are defined; "
++ "maybe the compiler_cc or compiler_cxx tool has not been configured yet?")
++
++ try:
++ compiler = compiler_mapping[cc]
++ except KeyError:
++ try:
++ compiler = compiler_mapping[cxx]
++ except KeyError:
++ Logs.warn("No compiler flags support for compiler %r or %r"
++ % (cc, cxx))
++ return
++
++ opt_level, warn_level, dbg_level = profiles[Options.options.build_profile]
++
++ optimizations = compiler.get_optimization_flags(opt_level)
++ debug, debug_defs = compiler.get_debug_flags(dbg_level)
++ warnings = compiler.get_warnings_flags(warn_level)
++
++ if cc and not conf.env['CCFLAGS']:
++ conf.env.append_value('CCFLAGS', optimizations)
++ conf.env.append_value('CCFLAGS', debug)
++ conf.env.append_value('CCFLAGS', warnings)
++ conf.env.append_value('CCDEFINES', debug_defs)
++ if cxx and not conf.env['CXXFLAGS']:
++ conf.env.append_value('CXXFLAGS', optimizations)
++ conf.env.append_value('CXXFLAGS', debug)
++ conf.env.append_value('CXXFLAGS', warnings)
++ conf.env.append_value('CXXDEFINES', debug_defs)
+diff --git a/waf-tools/command.py b/waf-tools/command.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/command.py
+@@ -0,0 +1,134 @@
++import TaskGen# import feature, taskgen_method, before_method, task_gen
++import Node, Task, Utils, Build
++import subprocess
++import Options
++
++import shellcmd
++#shellcmd.subprocess = pproc # the WAF version of the subprocess module is supposedly less buggy
++
++from Logs import debug, error
++shellcmd.debug = debug
++
++import Task
++
++import re
++
++
++arg_rx = re.compile(r"(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})", re.M)
++
++class command_task(Task.Task):
++ color = "BLUE"
++ def __init__(self, env, generator):
++ Task.Task.__init__(self, env=env, normal=1, generator=generator)
++
++ def __str__(self):
++ "string to display to the user"
++ env = self.env
++ src_str = ' '.join([a.nice_path(env) for a in self.inputs])
++ tgt_str = ' '.join([a.nice_path(env) for a in self.outputs])
++ if self.outputs:
++ sep = ' -> '
++ else:
++ sep = ''
++
++ pipeline = shellcmd.Pipeline()
++ pipeline.parse(self.generator.command)
++ cmd = pipeline.get_abbreviated_command()
++ return 'command (%s): %s%s%s\n' % (cmd, src_str, sep, tgt_str)
++
++ def _subst_arg(self, arg, direction, namespace):
++ """
++ @param arg: the command argument (or stdin/stdout/stderr) to substitute
++ @param direction: direction of the argument: 'in', 'out', or None
++ """
++ def repl(match):
++ if match.group('dollar'):
++ return "$"
++ elif match.group('subst'):
++ var = match.group('var')
++ code = match.group('code')
++ result = eval(var+code, namespace)
++ if isinstance(result, Node.Node):
++ if var == 'TGT':
++ return result.get_bld().abspath()
++ elif var == 'SRC':
++ return result.srcpath()
++ else:
++ raise ValueError("Bad subst variable %r" % var)
++ elif result is self.inputs:
++ if len(self.inputs) == 1:
++ return result[0].srcpath()
++ else:
++ raise ValueError("${SRC} requested but have multiple sources; which one?")
++ elif result is self.outputs:
++ if len(self.outputs) == 1:
++ return result[0].get_bld().abspath()
++ else:
++ raise ValueError("${TGT} requested but have multiple targets; which one?")
++ elif isinstance(result, list):
++ assert len(result) == 1
++ return result[0]
++ else:
++ return result
++ return None
++
++ return arg_rx.sub(repl, arg)
++
++ def run(self):
++ pipeline = shellcmd.Pipeline()
++ pipeline.parse(self.generator.command)
++ namespace = self.env.get_merged_dict()
++ if self.generator.variables is not None:
++ namespace.update(self.generator.variables)
++ namespace.update(env=self.env, SRC=self.inputs, TGT=self.outputs)
++ for cmd in pipeline.pipeline:
++ if isinstance(cmd, shellcmd.Command):
++ if isinstance(cmd.stdin, basestring):
++ cmd.stdin = self._subst_arg(cmd.stdin, 'in', namespace)
++ if isinstance(cmd.stdout, basestring):
++ cmd.stdout = self._subst_arg(cmd.stdout, 'out', namespace)
++ if isinstance(cmd.stderr, basestring):
++ cmd.stderr = self._subst_arg(cmd.stderr, 'out', namespace)
++ for argI in xrange(len(cmd.argv)):
++ cmd.argv[argI] = self._subst_arg(cmd.argv[argI], None, namespace)
++ if cmd.env_vars is not None:
++ env_vars = dict()
++ for name, value in cmd.env_vars.iteritems():
++ env_vars[name] = self._subst_arg(value, None, namespace)
++ cmd.env_vars = env_vars
++ elif isinstance(cmd, shellcmd.Chdir):
++ cmd.dir = self._subst_arg(cmd.dir, None, namespace)
++ return pipeline.run(verbose=(Options.options.verbose > 0))
++
++@TaskGen.taskgen_method
++@TaskGen.feature('command')
++def init_command(self):
++ Utils.def_attrs(self,
++ # other variables that can be used in the command: ${VARIABLE}
++ variables = None,
++ rule='')
++
++
++
++@TaskGen.feature('command')
++@TaskGen.after_method('process_rule')
++def apply_command(self):
++ #self.meths.remove('apply_core')
++ # create the task
++ task = self.create_task('command')
++ setattr(task, "dep_vars", getattr(self, "dep_vars", None))
++ # process the sources
++ inputs = []
++ for node in self.source:
++ inputs.append(node)
++ task.set_inputs(inputs)
++ task.set_outputs([self.path.find_or_declare(tgt) for tgt in self.to_list(self.target)])
++ self.source = ''
++ #Task.file_deps = Task.extract_deps
++
++
++
++# class command_taskgen(task_gen):
++# def __init__(self, *k, **kw):
++# task_gen.__init__(self, *k, **kw)
++# self.features.append('command')
+diff --git a/waf-tools/misc.py b/waf-tools/misc.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/misc.py
+@@ -0,0 +1,416 @@
++#!/usr/bin/env python
++# encoding: utf-8
++# Thomas Nagy, 2006-2010 (ita)
++
++"""
++This tool is totally deprecated
++
++Try using:
++ .pc.in files for .pc files
++ the feature intltool_in - see demos/intltool
++ make-like rules
++"""
++
++import shutil, re, os
++from waflib import TaskGen, Node, Task, Utils, Build, Errors
++from waflib.TaskGen import feature, after_method, before_method
++from waflib.Logs import debug
++
++def copy_attrs(orig, dest, names, only_if_set=False):
++ """
++ copy class attributes from an object to another
++ """
++ for a in Utils.to_list(names):
++ u = getattr(orig, a, ())
++ if u or not only_if_set:
++ setattr(dest, a, u)
++
++def copy_func(tsk):
++ "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)"
++ env = tsk.env
++ infile = tsk.inputs[0].abspath()
++ outfile = tsk.outputs[0].abspath()
++ try:
++ shutil.copy2(infile, outfile)
++ except (OSError, IOError):
++ return 1
++ else:
++ if tsk.chmod: os.chmod(outfile, tsk.chmod)
++ return 0
++
++def action_process_file_func(tsk):
++ "Ask the function attached to the task to process it"
++ if not tsk.fun: raise Errors.WafError('task must have a function attached to it for copy_func to work!')
++ return tsk.fun(tsk)
++
++@feature('cmd')
++def apply_cmd(self):
++ "call a command everytime"
++ if not self.fun: raise Errors.WafError('cmdobj needs a function!')
++ tsk = Task.TaskBase()
++ tsk.fun = self.fun
++ tsk.env = self.env
++ self.tasks.append(tsk)
++ tsk.install_path = self.install_path
++
++@feature('copy')
++@before_method('process_source')
++def apply_copy(self):
++ Utils.def_attrs(self, fun=copy_func)
++ self.default_install_path = 0
++
++ lst = self.to_list(self.source)
++ self.meths.remove('process_source')
++
++ for filename in lst:
++ node = self.path.find_resource(filename)
++ if not node: raise Errors.WafError('cannot find input file %s for processing' % filename)
++
++ target = self.target
++ if not target or len(lst)>1: target = node.name
++
++ # TODO the file path may be incorrect
++ newnode = self.path.find_or_declare(target)
++
++ tsk = self.create_task('copy', node, newnode)
++ tsk.fun = self.fun
++ tsk.chmod = getattr(self, 'chmod', Utils.O644)
++
++ if not tsk.env:
++ tsk.debug()
++ raise Errors.WafError('task without an environment')
++
++def subst_func(tsk):
++ "Substitutes variables in a .in file"
++
++ m4_re = re.compile('@(\w+)@', re.M)
++
++ code = tsk.inputs[0].read() #Utils.readf(infile)
++
++ # replace all % by %% to prevent errors by % signs in the input file while string formatting
++ code = code.replace('%', '%%')
++
++ s = m4_re.sub(r'%(\1)s', code)
++
++ env = tsk.env
++ di = getattr(tsk, 'dict', {}) or getattr(tsk.generator, 'dict', {})
++ if not di:
++ names = m4_re.findall(code)
++ for i in names:
++ di[i] = env.get_flat(i) or env.get_flat(i.upper())
++
++ tsk.outputs[0].write(s % di)
++
++@feature('subst')
++@before_method('process_source')
++def apply_subst(self):
++ Utils.def_attrs(self, fun=subst_func)
++ lst = self.to_list(self.source)
++ self.meths.remove('process_source')
++
++ self.dict = getattr(self, 'dict', {})
++
++ for filename in lst:
++ node = self.path.find_resource(filename)
++ if not node: raise Errors.WafError('cannot find input file %s for processing' % filename)
++
++ if self.target:
++ newnode = self.path.find_or_declare(self.target)
++ else:
++ newnode = node.change_ext('')
++
++ try:
++ self.dict = self.dict.get_merged_dict()
++ except AttributeError:
++ pass
++
++ if self.dict and not self.env['DICT_HASH']:
++ self.env = self.env.derive()
++ keys = list(self.dict.keys())
++ keys.sort()
++ lst = [self.dict[x] for x in keys]
++ self.env['DICT_HASH'] = str(Utils.h_list(lst))
++
++ tsk = self.create_task('copy', node, newnode)
++ tsk.fun = self.fun
++ tsk.dict = self.dict
++ tsk.dep_vars = ['DICT_HASH']
++ tsk.chmod = getattr(self, 'chmod', Utils.O644)
++
++ if not tsk.env:
++ tsk.debug()
++ raise Errors.WafError('task without an environment')
++
++####################
++## command-output ####
++####################
++
++class cmd_arg(object):
++ """command-output arguments for representing files or folders"""
++ def __init__(self, name, template='%s'):
++ self.name = name
++ self.template = template
++ self.node = None
++
++class input_file(cmd_arg):
++ def find_node(self, base_path):
++ assert isinstance(base_path, Node.Node)
++ self.node = base_path.find_resource(self.name)
++ if self.node is None:
++ raise Errors.WafError("Input file %s not found in " % (self.name, base_path))
++
++ def get_path(self, env, absolute):
++ if absolute:
++ return self.template % self.node.abspath()
++ else:
++ return self.template % self.node.srcpath()
++
++class output_file(cmd_arg):
++ def find_node(self, base_path):
++ assert isinstance(base_path, Node.Node)
++ self.node = base_path.find_or_declare(self.name)
++ if self.node is None:
++ raise Errors.WafError("Output file %s not found in " % (self.name, base_path))
++
++ def get_path(self, env, absolute):
++ if absolute:
++ return self.template % self.node.abspath()
++ else:
++ return self.template % self.node.bldpath()
++
++class cmd_dir_arg(cmd_arg):
++ def find_node(self, base_path):
++ assert isinstance(base_path, Node.Node)
++ self.node = base_path.find_dir(self.name)
++ if self.node is None:
++ raise Errors.WafError("Directory %s not found in " % (self.name, base_path))
++
++class input_dir(cmd_dir_arg):
++ def get_path(self, dummy_env, dummy_absolute):
++ return self.template % self.node.abspath()
++
++class output_dir(cmd_dir_arg):
++ def get_path(self, env, dummy_absolute):
++ return self.template % self.node.abspath()
++
++
++class command_output(Task.Task):
++ color = "BLUE"
++ def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr):
++ Task.Task.__init__(self, env=env)
++ assert isinstance(command, (str, Node.Node))
++ self.command = command
++ self.command_args = command_args
++ self.stdin = stdin
++ self.stdout = stdout
++ self.cwd = cwd
++ self.os_env = os_env
++ self.stderr = stderr
++
++ if command_node is not None: self.dep_nodes = [command_node]
++ self.dep_vars = [] # additional environment variables to look
++
++ def run(self):
++ task = self
++ #assert len(task.inputs) > 0
++
++ def input_path(node, template):
++ if task.cwd is None:
++ return template % node.bldpath()
++ else:
++ return template % node.abspath()
++ def output_path(node, template):
++ fun = node.abspath
++ if task.cwd is None: fun = node.bldpath
++ return template % fun()
++
++ if isinstance(task.command, Node.Node):
++ argv = [input_path(task.command, '%s')]
++ else:
++ argv = [task.command]
++
++ for arg in task.command_args:
++ if isinstance(arg, str):
++ argv.append(arg)
++ else:
++ assert isinstance(arg, cmd_arg)
++ argv.append(arg.get_path(task.env, (task.cwd is not None)))
++
++ if task.stdin:
++ stdin = open(input_path(task.stdin, '%s'))
++ else:
++ stdin = None
++
++ if task.stdout:
++ stdout = open(output_path(task.stdout, '%s'), "w")
++ else:
++ stdout = None
++
++ if task.stderr:
++ stderr = open(output_path(task.stderr, '%s'), "w")
++ else:
++ stderr = None
++
++ if task.cwd is None:
++ cwd = ('None (actually %r)' % os.getcwd())
++ else:
++ cwd = repr(task.cwd)
++ debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" %
++ (cwd, stdin, stdout, argv))
++
++ if task.os_env is None:
++ os_env = os.environ
++ else:
++ os_env = task.os_env
++ command = Utils.subprocess.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env)
++ return command.wait()
++
++@feature('command-output')
++def init_cmd_output(self):
++ Utils.def_attrs(self,
++ stdin = None,
++ stdout = None,
++ stderr = None,
++ # the command to execute
++ command = None,
++
++ # whether it is an external command; otherwise it is assumed
++ # to be an executable binary or script that lives in the
++ # source or build tree.
++ command_is_external = False,
++
++ # extra parameters (argv) to pass to the command (excluding
++ # the command itself)
++ argv = [],
++
++ # dependencies to other objects -> this is probably not what you want (ita)
++ # values must be 'task_gen' instances (not names!)
++ dependencies = [],
++
++ # dependencies on env variable contents
++ dep_vars = [],
++
++ # input files that are implicit, i.e. they are not
++ # stdin, nor are they mentioned explicitly in argv
++ hidden_inputs = [],
++
++ # output files that are implicit, i.e. they are not
++ # stdout, nor are they mentioned explicitly in argv
++ hidden_outputs = [],
++
++ # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here)
++ cwd = None,
++
++ # OS environment variables to pass to the subprocess
++ # if None, use the default environment variables unchanged
++ os_env = None)
++
++@feature('command-output')
++@after_method('init_cmd_output')
++def apply_cmd_output(self):
++ if self.command is None:
++ raise Errors.WafError("command-output missing command")
++ if self.command_is_external:
++ cmd = self.command
++ cmd_node = None
++ else:
++ cmd_node = self.path.find_resource(self.command)
++ assert cmd_node is not None, ('''Could not find command '%s' in source tree.
++Hint: if this is an external command,
++use command_is_external=True''') % (self.command,)
++ cmd = cmd_node
++
++ if self.cwd is None:
++ cwd = None
++ else:
++ assert isinstance(cwd, CmdDirArg)
++ self.cwd.find_node(self.path)
++
++ args = []
++ inputs = []
++ outputs = []
++
++ for arg in self.argv:
++ if isinstance(arg, cmd_arg):
++ arg.find_node(self.path)
++ if isinstance(arg, input_file):
++ inputs.append(arg.node)
++ if isinstance(arg, output_file):
++ outputs.append(arg.node)
++
++ if self.stdout is None:
++ stdout = None
++ else:
++ assert isinstance(self.stdout, str)
++ stdout = self.path.find_or_declare(self.stdout)
++ if stdout is None:
++ raise Errors.WafError("File %s not found" % (self.stdout,))
++ outputs.append(stdout)
++
++ if self.stderr is None:
++ stderr = None
++ else:
++ assert isinstance(self.stderr, str)
++ stderr = self.path.find_or_declare(self.stderr)
++ if stderr is None:
++ raise Errors.WafError("File %s not found" % (self.stderr,))
++ outputs.append(stderr)
++
++ if self.stdin is None:
++ stdin = None
++ else:
++ assert isinstance(self.stdin, str)
++ stdin = self.path.find_resource(self.stdin)
++ if stdin is None:
++ raise Errors.WafError("File %s not found" % (self.stdin,))
++ inputs.append(stdin)
++
++ for hidden_input in self.to_list(self.hidden_inputs):
++ node = self.path.find_resource(hidden_input)
++ if node is None:
++ raise Errors.WafError("File %s not found in dir %s" % (hidden_input, self.path))
++ inputs.append(node)
++
++ for hidden_output in self.to_list(self.hidden_outputs):
++ node = self.path.find_or_declare(hidden_output)
++ if node is None:
++ raise Errors.WafError("File %s not found in dir %s" % (hidden_output, self.path))
++ outputs.append(node)
++
++ if not (inputs or getattr(self, 'no_inputs', None)):
++ raise Errors.WafError('command-output objects must have at least one input file or give self.no_inputs')
++ if not (outputs or getattr(self, 'no_outputs', None)):
++ raise Errors.WafError('command-output objects must have at least one output file or give self.no_outputs')
++
++ cwd = self.bld.variant_dir
++ task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr)
++ task.generator = self
++ copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True)
++ self.tasks.append(task)
++
++ task.inputs = inputs
++ task.outputs = outputs
++ task.dep_vars = self.to_list(self.dep_vars)
++
++ for dep in self.dependencies:
++ assert dep is not self
++ dep.post()
++ for dep_task in dep.tasks:
++ task.set_run_after(dep_task)
++
++ if not task.inputs:
++ # the case for svnversion, always run, and update the output nodes
++ task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run
++ task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__)
++
++ # TODO the case with no outputs?
++
++def post_run(self):
++ for x in self.outputs:
++ x.sig = Utils.h_file(x.abspath())
++
++def runnable_status(self):
++ return self.RUN_ME
++
++Task.task_factory('copy', vars=[], func=action_process_file_func)
++
+diff --git a/waf-tools/pkgconfig.py b/waf-tools/pkgconfig.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/pkgconfig.py
+@@ -0,0 +1,78 @@
++# -*- mode: python; encoding: utf-8 -*-
++# Gustavo Carneiro (gjamc) 2008
++
++import Options
++import Configure
++import subprocess
++import config_c
++import sys
++
++def configure(conf):
++ pkg_config = conf.find_program('pkg-config', var='PKG_CONFIG')
++ if not pkg_config: return
++
++@Configure.conf
++def pkg_check_modules(conf, uselib_name, expression, mandatory=True):
++ pkg_config = conf.env['PKG_CONFIG']
++ if not pkg_config:
++ if mandatory:
++ conf.fatal("pkg-config is not available")
++ else:
++ return False
++
++ if Options.options.verbose:
++ extra_msg = ' (%s)' % expression
++ else:
++ extra_msg = ''
++
++ conf.start_msg('Checking for pkg-config flags for %s%s' % (uselib_name, extra_msg))
++
++ argv = [pkg_config, '--cflags', '--libs', expression]
++ cmd = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
++ out, err = cmd.communicate()
++ retval = cmd.wait()
++
++ conf.to_log('%r: %r (exit code %i)\n%s' % (argv, out, retval, err))
++
++ if retval != 0:
++ conf.end_msg(False)
++ sys.stderr.write(err)
++ else:
++ if Options.options.verbose:
++ conf.end_msg(out)
++ else:
++ conf.end_msg(True)
++
++ if retval == 0:
++ conf.parse_flags(out, uselib_name, conf.env)
++ conf.env[uselib_name] = True
++ return True
++
++ else:
++
++ conf.env[uselib_name] = False
++ if mandatory:
++ raise Configure.ConfigurationError('pkg-config check failed')
++ else:
++ return False
++
++@Configure.conf
++def pkg_check_module_variable(conf, module, variable):
++ pkg_config = conf.env['PKG_CONFIG']
++ if not pkg_config:
++ conf.fatal("pkg-config is not available")
++
++ argv = [pkg_config, '--variable', variable, module]
++ cmd = subprocess.Popen(argv, stdout=subprocess.PIPE)
++ out, dummy = cmd.communicate()
++ retval = cmd.wait()
++ out = out.rstrip() # strip the trailing newline
++
++ msg_checking = ("Checking for pkg-config variable %r in %s" % (variable, module,))
++ conf.check_message_custom(msg_checking, '', out)
++ conf.log.write('%r: %r (exit code %i)\n' % (argv, out, retval))
++
++ if retval == 0:
++ return out
++ else:
++ raise Configure.ConfigurationError('pkg-config check failed')
+diff --git a/waf-tools/relocation.py b/waf-tools/relocation.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/relocation.py
+@@ -0,0 +1,85 @@
++#! /usr/bin/env python
++# encoding: utf-8
++
++"""
++Waf 1.6
++
++Try to detect if the project directory was relocated, and if it was,
++change the node representing the project directory. Just call:
++
++ waf configure build
++
++Note that if the project directory name changes, the signatures for the tasks using
++files in that directory will change, causing a partial build.
++"""
++
++import os
++from waflib import Build, ConfigSet, Task, Utils, Errors
++from waflib.TaskGen import feature, before_method, after_method
++
++EXTRA_LOCK = '.old_srcdir'
++
++old1 = Build.BuildContext.store
++def store(self):
++ old1(self)
++ db = os.path.join(self.variant_dir, EXTRA_LOCK)
++ env = ConfigSet.ConfigSet()
++ env.SRCDIR = self.srcnode.abspath()
++ env.store(db)
++Build.BuildContext.store = store
++
++old2 = Build.BuildContext.init_dirs
++def init_dirs(self):
++
++ if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)):
++ raise Errors.WafError('The project was not configured: run "waf configure" first!')
++
++ srcdir = None
++ db = os.path.join(self.variant_dir, EXTRA_LOCK)
++ env = ConfigSet.ConfigSet()
++ try:
++ env.load(db)
++ srcdir = env.SRCDIR
++ except:
++ pass
++
++ if srcdir:
++ d = self.root.find_node(srcdir)
++ if d and srcdir != self.top_dir and getattr(d, 'children', ''):
++ srcnode = self.root.make_node(self.top_dir)
++ print("relocating the source directory %r -> %r" % (srcdir, self.top_dir))
++ srcnode.children = {}
++
++ for (k, v) in d.children.items():
++ srcnode.children[k] = v
++ v.parent = srcnode
++ d.children = {}
++
++ old2(self)
++
++Build.BuildContext.init_dirs = init_dirs
++
++
++def uid(self):
++ try:
++ return self.uid_
++ except AttributeError:
++ # this is not a real hot zone, but we want to avoid surprizes here
++ m = Utils.md5()
++ up = m.update
++ up(self.__class__.__name__.encode())
++ for x in self.inputs + self.outputs:
++ up(x.path_from(x.ctx.srcnode).encode())
++ self.uid_ = m.digest()
++ return self.uid_
++Task.Task.uid = uid
++
++@feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes')
++@after_method('propagate_uselib_vars', 'process_source')
++def apply_incpaths(self):
++ lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES'])
++ self.includes_nodes = lst
++ bld = self.bld
++ self.env['INCPATHS'] = [x.is_child_of(bld.srcnode) and x.path_from(bld.srcnode) or x.abspath() for x in lst]
++
++
+diff --git a/waf-tools/shellcmd.py b/waf-tools/shellcmd.py
+new file mode 100644
+--- /dev/null
++++ b/waf-tools/shellcmd.py
+@@ -0,0 +1,356 @@
++# Copyright (C) 2008 Gustavo J. A. M. Carneiro <gjcarneiro@gmail.com>
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++import shlex
++import subprocess
++import sys
++import re
++import os
++
++env_var_rx = re.compile(r"^([a-zA-Z0-9_]+)=(\S+)$")
++
++def debug(message):
++ print >> sys.stderr, message
++
++
++if sys.platform == 'win32':
++ dev_null = open("NUL:", "w")
++else:
++ dev_null = open("/dev/null", "w")
++
++fcntl = fd = fl = None
++try:
++ import fcntl
++except ImportError:
++ pass
++else:
++ fd = dev_null.fileno()
++ fl = fcntl.fcntl(fd, fcntl.F_GETFD)
++ fcntl.fcntl(fd, fcntl.F_SETFD, fl | fcntl.FD_CLOEXEC)
++del fcntl, fd, fl
++
++def _open_out_file(filename):
++ if filename in ['NUL:', '/dev/null']:
++ return dev_null
++ else:
++ return open(filename, 'wb')
++
++
++class Node(object):
++ pass
++
++class Op(Node):
++ pass
++
++class Pipe(Op):
++ pass
++
++class And(Op):
++ pass
++
++class Or(Op):
++ pass
++
++class Command(Node):
++ class PIPE(object):
++ pass # PIPE is a constant
++ class STDOUT(object):
++ pass # PIPE is a constant
++
++ def __init__(self, name):
++ super(Command, self).__init__()
++ self.name = name # command name
++ self.argv = [name] # command argv
++ self.stdin = None
++ self.stdout = None
++ self.stderr = None
++ self.env_vars = None
++
++ def __repr__(self):
++ return "Command(%r, argv=%r, stdin=%r, stdout=%r, stderr=%r)" \
++ % (self.name, self.argv, self.stdin, self.stdout, self.stderr)
++
++class Chdir(Node):
++ def __init__(self):
++ super(Chdir, self).__init__()
++ self.dir = None
++
++ def __repr__(self):
++ return "Chdir(%r)" \
++ % (self.dir)
++
++class Pipeline(object):
++ def __init__(self):
++ self.current_command = None
++ self.pipeline = []
++
++ def _commit_command(self):
++ assert self.current_command is not None
++ self.pipeline.append(self.current_command)
++ self.current_command = None
++
++ def get_abbreviated_command(self):
++ l = []
++ for node in self.pipeline:
++ if isinstance(node, Command):
++ l.append(node.name)
++ if isinstance(node, Chdir):
++ l.append('cd %s' % node.dir)
++ elif isinstance(node, Pipe):
++ l.append('|')
++ elif isinstance(node, And):
++ l.append('&&')
++ elif isinstance(node, And):
++ l.append('||')
++ return ' '.join(l)
++
++ def parse(self, command):
++ self.current_command = None
++ self.pipeline = []
++
++ if isinstance(command, list):
++ tokens = list(command)
++ else:
++ tokens = shlex.split(command)
++ debug("command: shlex: %r" % (tokens,))
++
++ BEGIN, COMMAND, CHDIR, STDERR, STDOUT, STDIN = range(6)
++ state = BEGIN
++ self.current_command = None
++ env_vars = dict()
++
++ while tokens:
++ token = tokens.pop(0)
++ if state == BEGIN:
++ env_var_match = env_var_rx.match(token)
++ if env_var_match is not None:
++ env_vars[env_var_match.group(1)] = env_var_match.group(2)
++ else:
++ assert self.current_command is None
++ if token == 'cd':
++ self.current_command = Chdir()
++ assert not env_vars
++ state = CHDIR
++ else:
++ self.current_command = Command(token)
++ if env_vars:
++ self.current_command.env_vars = env_vars
++ env_vars = dict()
++ state = COMMAND
++ elif state == COMMAND:
++ if token == '>':
++ state = STDOUT
++ elif token == '2>':
++ state = STDERR
++ elif token == '2>&1':
++ assert self.current_command.stderr is None
++ self.current_command.stderr = Command.STDOUT
++ elif token == '<':
++ state = STDIN
++ elif token == '|':
++ assert self.current_command.stdout is None
++ self.current_command.stdout = Command.PIPE
++ self._commit_command()
++ self.pipeline.append(Pipe())
++ state = BEGIN
++ elif token == '&&':
++ self._commit_command()
++ self.pipeline.append(And())
++ state = BEGIN
++ elif token == '||':
++ self._commit_command()
++ self.pipeline.append(Or())
++ state = BEGIN
++ else:
++ self.current_command.argv.append(token)
++ elif state == CHDIR:
++ if token == '&&':
++ self._commit_command()
++ self.pipeline.append(And())
++ state = BEGIN
++ else:
++ assert self.current_command.dir is None
++ self.current_command.dir = token
++ elif state == STDOUT:
++ assert self.current_command.stdout is None
++ self.current_command.stdout = token
++ state = COMMAND
++ elif state == STDERR:
++ assert self.current_command.stderr is None
++ self.current_command.stderr = token
++ state = COMMAND
++ elif state == STDIN:
++ assert self.current_command.stdin is None
++ self.current_command.stdin = token
++ state = COMMAND
++ self._commit_command()
++ return self.pipeline
++
++ def _exec_piped_commands(self, commands):
++ retvals = []
++ for cmd in commands:
++ retvals.append(cmd.wait())
++ retval = 0
++ for r in retvals:
++ if r:
++ retval = retvals[-1]
++ break
++ return retval
++
++ def run(self, verbose=False):
++ pipeline = list(self.pipeline)
++ files_to_close = []
++ piped_commands = []
++ piped_commands_display = []
++ BEGIN, PIPE = range(2)
++ state = BEGIN
++ cwd = '.'
++ while pipeline:
++ node = pipeline.pop(0)
++
++ if isinstance(node, Chdir):
++ next_op = pipeline.pop(0)
++ assert isinstance(next_op, And)
++ cwd = os.path.join(cwd, node.dir)
++ if verbose:
++ piped_commands_display.append("cd %s &&" % node.dir)
++ continue
++
++ assert isinstance(node, (Command, Chdir))
++ cmd = node
++ if verbose:
++ if cmd.env_vars:
++ env_vars_str = ' '.join(['%s=%s' % (key, val) for key, val in cmd.env_vars.iteritems()])
++ piped_commands_display.append("%s %s" % (env_vars_str, ' '.join(cmd.argv)))
++ else:
++ piped_commands_display.append(' '.join(cmd.argv))
++
++ if state == PIPE:
++ stdin = piped_commands[-1].stdout
++ elif cmd.stdin is not None:
++ stdin = open(cmd.stdin, "r")
++ if verbose:
++ piped_commands_display.append('< %s' % cmd.stdin)
++ files_to_close.append(stdin)
++ else:
++ stdin = None
++
++ if cmd.stdout is None:
++ stdout = None
++ elif cmd.stdout is Command.PIPE:
++ stdout = subprocess.PIPE
++ else:
++ stdout = _open_out_file(cmd.stdout)
++ files_to_close.append(stdout)
++ if verbose:
++ piped_commands_display.append('> %s' % cmd.stdout)
++
++ if cmd.stderr is None:
++ stderr = None
++ elif cmd.stderr is Command.PIPE:
++ stderr = subprocess.PIPE
++ elif cmd.stderr is Command.STDOUT:
++ stderr = subprocess.STDOUT
++ if verbose:
++ piped_commands_display.append('2>&1')
++ else:
++ stderr = _open_out_file(cmd.stderr)
++ files_to_close.append(stderr)
++ if verbose:
++ piped_commands_display.append('2> %s' % cmd.stderr)
++
++ if cmd.env_vars:
++ env = dict(os.environ)
++ env.update(cmd.env_vars)
++ else:
++ env = None
++
++ if cwd == '.':
++ proc_cwd = None
++ else:
++ proc_cwd = cwd
++
++ debug("command: subprocess.Popen(argv=%r, stdin=%r, stdout=%r, stderr=%r, env_vars=%r, cwd=%r)"
++ % (cmd.argv, stdin, stdout, stderr, cmd.env_vars, proc_cwd))
++ proc = subprocess.Popen(cmd.argv, stdin=stdin, stdout=stdout, stderr=stderr, env=env, cwd=proc_cwd)
++ del stdin, stdout, stderr
++ piped_commands.append(proc)
++
++ try:
++ next_node = pipeline.pop(0)
++ except IndexError:
++ try:
++ retval = self._exec_piped_commands(piped_commands)
++ if verbose:
++ print "%s: exit code %i" % (' '.join(piped_commands_display), retval)
++ finally:
++ for f in files_to_close:
++ if f is not dev_null:
++ f.close()
++ files_to_close = []
++ return retval
++ else:
++
++ if isinstance(next_node, Pipe):
++ state = PIPE
++ piped_commands_display.append('|')
++
++ elif isinstance(next_node, Or):
++ try:
++ this_retval = self._exec_piped_commands(piped_commands)
++ finally:
++ for f in files_to_close:
++ if f is not dev_null:
++ f.close()
++ files_to_close = []
++ if this_retval == 0:
++ if verbose:
++ print "%s: exit code %i (|| is short-circuited)" % (' '.join(piped_commands_display), retval)
++ return this_retval
++ if verbose:
++ print "%s: exit code %i (|| proceeds)" % (' '.join(piped_commands_display), retval)
++ state = BEGIN
++ piped_commands = []
++ piped_commands_display = []
++
++ elif isinstance(next_node, And):
++ try:
++ this_retval = self._exec_piped_commands(piped_commands)
++ finally:
++ for f in files_to_close:
++ if f is not dev_null:
++ f.close()
++ files_to_close = []
++ if this_retval != 0:
++ if verbose:
++ print "%s: exit code %i (&& is short-circuited)" % (' '.join(piped_commands_display), retval)
++ return this_retval
++ if verbose:
++ print "%s: exit code %i (&& proceeds)" % (' '.join(piped_commands_display), retval)
++ state = BEGIN
++ piped_commands = []
++ piped_commands_display = []
++
++
++
++def _main():
++ pipeline = Pipeline()
++ pipeline.parse('./foo.py 2>&1 < xxx | cat && ls')
++ print pipeline.run()
++
++if __name__ == '__main__':
++ _main()
++
+diff --git a/wscript b/wscript
+--- a/wscript
++++ b/wscript
+@@ -54,10 +54,21 @@
+ opt.add_option('--visualize',
+ help=('Modify --run arguments to enable the visualizer'),
+ action="store_true", default=False, dest='visualize')
++ opt.add_option('--command-template',
++ help=('Template of the command used to run the program given by --run;'
++ ' It should be a shell command string containing %s inside,'
++ ' which will be replaced by the actual program.'),
++ type="string", default=None, dest='command_template')
++ opt.add_option('--pyrun',
++ help=('Run a python program using locally built ns3 python module;'
++ ' argument is the path to the python program, optionally followed'
++ ' by command-line options that are passed to the program.'),
++ type="string", default='', dest='pyrun')
+ opt.add_option('--valgrind',
+ help=('Change the default command template to run programs and unit tests with valgrind'),
+ action="store_true", default=False,
+ dest='valgrind')
++ opt.sub_options('bindings/')
+
+ def search_file(files):
+ for f in files:
+@@ -81,6 +92,8 @@
+ ns3waf.check_modules(conf, ['visualizer'], mandatory = False)
+ ns3waf.check_modules(conf, ['applications'], mandatory = False)
+ conf.check_tool('compiler_cc')
++ conf.check_tool('command', ['waf-tools'])
++ conf.check_tool('copy', ['waf-tools'])
+ conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H', mandatory=False)
+ conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H', mandatory=False)
+ conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H', mandatory=False)
+@@ -123,6 +136,7 @@
+ pass
+
+ conf.recurse(os.path.join('utils'))
++ conf.sub_config('bindings')
+ ns3waf.print_feature_summary(conf)
+
+ def build_netlink(bld):
+@@ -139,7 +153,7 @@
+ 'netlink/netlink-socket-address.h',
+ ]
+ module = ns3waf.create_module(bld,
+- name='netlink',
++ name='dce-netlink',
+ needed = ['internet', 'core'],
+ source=module_source,
+ headers=module_headers)
+@@ -514,7 +528,7 @@
+ ]
+ module_source = module_source + kernel_source
+ module_headers = module_headers + kernel_headers
+- uselib = ns3waf.modules_uselib(bld, ['core', 'network', 'internet', 'netlink'])
++ uselib = ns3waf.modules_uselib(bld, ['core', 'network', 'internet', 'dce-netlink'])
+ module = ns3waf.create_module(bld, name='dce',
+ source=module_source,
+ headers=module_headers,
+@@ -526,18 +540,22 @@
+ build_dce_examples(module, bld)
+
+ # no idea to solve this two-way dependency (dce <-> netlink)
+- module.add_runner_test(needed = ['internet', 'point-to-point', 'core', 'dce'],
++ module.add_runner_test(needed = ['core', 'internet', 'point-to-point', 'dce'],
+ use=uselib,
+- includes=['netlink'],
++ includes=['dce-netlink'],
+ source=['test/netlink-socket-test.cc'],
+- name='netlink')
++ name='dce-netlink')
+
+ if bld.env['KERNEL_STACK']:
+ build_dce_kernel_examples(module)
+
+ bld.build_a_script = types.MethodType(build_a_script, bld)
++ bld.__class__.all_task_gen = property(_get_all_task_gen)
++ # sub-modules
++ add_myscripts(bld)
++ # python bindings
++ bld.add_subdirs(['bindings'])
+
+- add_myscripts(bld)
+ # build test-runner
+ module.add_test(**dce_kw(target='bin/test-runner',
+ source = ['utils/test-runner.cc'],
+@@ -605,7 +623,6 @@
+ out.close()
+
+ wutils.bld = bld
+- bld.__class__.all_task_gen = property(_get_all_task_gen)
+ Options.cwd_launch = bld.path.abspath()
+ if Options.options.run:
+ # Check that the requested program name is valid
+@@ -751,3 +768,7 @@
+ visualize=Options.options.visualize)
+ raise SystemExit(0)
+
++ if Options.options.pyrun:
++ wutils.run_python_program(Options.options.pyrun, env,
++ visualize=Options.options.visualize)
++ raise SystemExit(0)
+diff --git a/wutils.py b/wutils.py
+--- a/wutils.py
++++ b/wutils.py
+@@ -114,7 +114,7 @@
+ proc_env['DCE_ROOT'] = os.pathsep.join([os.path.join(bld.out_dir), \
+ os.path.join(bld.env.PREFIX)])
+
+- pymoddir = bld.path.find_dir('bindings/python')
++ pymoddir = bld.path.find_dir('bindings')
+ if pymoddir is not None:
+ pymoddir = pymoddir.get_bld().abspath()
+ else: