Merge
authorRaj Bhattacharjea <raj.b@gatech.edu>
Tue, 20 Jan 2009 11:41:57 -0500
changeset 4220 bdce17c3a0e8
parent 4219 7f7331a4c165 (current diff)
parent 4110 04170734fa8b (diff)
child 4221 73b49aa25221
Merge
--- a/bindings/python/ns3modulegen.py	Tue Jan 13 17:17:37 2009 -0500
+++ b/bindings/python/ns3modulegen.py	Tue Jan 20 11:41:57 2009 -0500
@@ -137,7 +137,7 @@
             root_module.classes.remove(root_module['ns3::%s' % clsname])
 
     if 'RealTime' not in enabled_features:
-        for clsname in ['WallClockSynchronizer', 'RealtimeSimulatorImpl', 'RealtimeEventLock']:
+        for clsname in ['WallClockSynchronizer', 'RealtimeSimulatorImpl']:
             root_module.classes.remove(root_module['ns3::%s' % clsname])
         root_module.enums.remove(root_module['ns3::RealtimeSimulatorImpl::SynchronizationMode'])
 
@@ -146,5 +146,14 @@
     out.close()
 
 if __name__ == '__main__':
-    main()
+    if 0:
+        try:
+            import cProfile as profile
+        except ImportError:
+            main()
+        else:
+            print >> sys.stderr, "** running under profiler"
+            profile.run('main()', 'ns3modulegen.pstat')
+    else:
+        main()
 
--- a/bindings/python/wscript	Tue Jan 13 17:17:37 2009 -0500
+++ b/bindings/python/wscript	Tue Jan 20 11:41:57 2009 -0500
@@ -14,11 +14,6 @@
 import Build
 import Utils
 
-## Adjust python path to look for our local copy of pybindgen
-LOCAL_PYBINDGEN_PATH = os.path.join(os.getcwd(), "bindings", "python", "pybindgen")
-#PYBINDGEN_BRANCH = 'lp:pybindgen'
-PYBINDGEN_BRANCH = 'https://launchpad.net/pybindgen'
-
 ## https://launchpad.net/pybindgen/
 REQUIRED_PYBINDGEN_VERSION = (0, 9, 0, 605)
 REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
@@ -33,8 +28,6 @@
 def set_pybindgen_pythonpath(env):
     if env['WITH_PYBINDGEN']:
         add_to_python_path(env['WITH_PYBINDGEN'])
-    else:
-        add_to_python_path(LOCAL_PYBINDGEN_PATH)
 
 
 def set_options(opt):
@@ -47,67 +40,11 @@
                    help=("Rescan Python bindings.  Needs working GCCXML / pygccxml environment."),
                    action="store_true", default=False,
                    dest='python_scan')
-    opt.add_option('--pybindgen-checkout',
-                   help=("During configure, force checkout of pybingen inside ns-3, "
-                         "instead of using the system installed version."),
-                   action="store_true", default=False,
-                   dest='pybindgen_checkout')
     opt.add_option('--with-pybindgen',
                    help=('Path to an existing pybindgen source tree to use.'),
                    default=None,
                    dest='with_pybindgen', type="string")
 
-def fetch_pybindgen(conf):
-    """
-    Fetches pybindgen from launchpad as bindings/python/pybindgen.
-    Returns True if successful, False it not.
-    """
-    bzr = conf.find_program("bzr")
-    if not bzr:
-        Logs.warn("the program 'bzr' is needed in order to fetch pybindgen")
-        return False
-    if len(REQUIRED_PYBINDGEN_VERSION) == 4:
-        rev = "-rrevno:%i" % REQUIRED_PYBINDGEN_VERSION[3]
-    else:
-        rev = "-rtag:%s" % '.'.join([str(x) for x in REQUIRED_PYBINDGEN_VERSION])
-        
-    if os.path.exists(LOCAL_PYBINDGEN_PATH):
-        print "Trying to update pybindgen; this will fail if no network connection is available.  Hit Ctrl-C to skip."
-
-        cmd = [bzr, "pull", rev, PYBINDGEN_BRANCH]
-        print " => ", ' '.join(cmd)
-        try:
-            if subprocess.Popen(cmd, cwd=LOCAL_PYBINDGEN_PATH).wait():
-                return False
-        except KeyboardInterrupt:
-            print "Interrupted; Python bindings will be disabled."
-            return False
-        print "Update was successful."
-    else:
-        print "Trying to fetch pybindgen; this will fail if no network connection is available.  Hit Ctrl-C to skip."
-        cmd = [bzr, "checkout", rev, PYBINDGEN_BRANCH, LOCAL_PYBINDGEN_PATH]
-        print " => ", ' '.join(cmd)
-        try:
-            if subprocess.Popen(cmd).wait():
-                return False
-        except KeyboardInterrupt:
-            print "Interrupted; Python bindings will be disabled."
-            shutil.rmtree(LOCAL_PYBINDGEN_PATH, True)
-            return False
-        print "Fetch was successful."
-
-    ## generate a fake version.py file in pybindgen it's safer this
-    ## way, since the normal version generation process requires
-    ## bazaar python bindings, which may not be available.
-    vfile = open(os.path.join(LOCAL_PYBINDGEN_PATH, "pybindgen", "version.py"), "wt")
-    vfile.write("""
-# (fake version generated by ns-3)
-__version__ = %r
-""" % list(REQUIRED_PYBINDGEN_VERSION))
-    vfile.close()
-
-    return True
-
 
 def configure(conf):
     conf.env['ENABLE_PYTHON_BINDINGS'] = False
@@ -140,9 +77,6 @@
         conf.env['WITH_PYBINDGEN'] = os.path.abspath(Options.options.with_pybindgen)
         no_net = True
 
-    if Options.options.pybindgen_checkout:
-        fetch_pybindgen(conf)
-
     set_pybindgen_pythonpath(conf.env)
 
     try:
@@ -484,7 +418,8 @@
 
         bindgen = bld.new_task_gen('command', source=source, target=target,
                                    command=argv, variables=dict(FEATURES=(','.join(features))))
-
+        bindgen.before = 'cxx'
+        bindgen.after = 'gen_everything_h_task'
 
     ## we build python bindings if either we have the tools to
     ## generate them or if the pregenerated source file is already
@@ -499,7 +434,15 @@
         pymod.target = 'ns3/_ns3'
         pymod.name = 'ns3module'
         pymod.uselib_local = "ns3"
-        pymod.env.append_value('CXXDEFINES', ['NS_DEPRECATED=', 'NS3_DEPRECATED_H'])
+
+        defines = list(pymod.env['CXXDEFINES'])
+        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['CXXDEFINES'] = defines
 
         # copy the __init__.py file to the build dir. waf can't handle
         # this, it's against waf's principles to have build dir files
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wifi-ap.py	Tue Jan 20 11:41:57 2009 -0500
@@ -0,0 +1,166 @@
+# -*-  Mode: Python; -*-
+# /*
+#  * Copyright (c) 2005,2006,2007 INRIA
+#  * Copyright (c) 2009 INESC Porto
+#  *
+#  * This program is free software; you can redistribute it and/or modify
+#  * it under the terms of the GNU General Public License version 2 as
+#  * published by the Free Software Foundation;
+#  *
+#  * 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
+#  *
+#  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+#  *          Gustavo Carneiro <gjc@inescporto.pt>
+#  */
+
+import sys
+import ns3
+
+# void
+# DevTxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+# {
+#   std::cout << " TX to=" << address << " p: " << *p << std::endl;
+# }
+# void
+# DevRxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+# {
+#   std::cout << " RX from=" << address << " p: " << *p << std::endl;
+# }
+# void
+# PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
+# {
+#   std::cout << "PHYRXOK mode=" << mode << " snr=" << snr << " " << *packet << std::endl;
+# }
+# void
+# PhyRxErrorTrace (std::string context, Ptr<const Packet> packet, double snr)
+# {
+#   std::cout << "PHYRXERROR snr=" << snr << " " << *packet << std::endl;
+# }
+# void
+# PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower)
+# {
+#   std::cout << "PHYTX mode=" << mode << " " << *packet << std::endl;
+# }
+# void
+# PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state)
+# {
+#   std::cout << " state=";
+#   switch (state) {
+#   case WifiPhy::TX:
+#     std::cout << "tx      ";
+#     break;
+#   case WifiPhy::SYNC:
+#     std::cout << "sync    ";
+#     break;
+#   case WifiPhy::CCA_BUSY:
+#     std::cout << "cca-busy";
+#     break;
+#   case WifiPhy::IDLE:
+#     std::cout << "idle    ";
+#     break;
+#   }
+#   std::cout << " start="<<start<<" duration="<<duration<<std::endl;
+# }
+
+def SetPosition(node, position):
+    mobility = node.GetObject(ns3.MobilityModel.GetTypeId())
+    mobility.SetPosition(position)
+
+
+def GetPosition(node):
+    mobility = node.GetObject(ns3.MobilityModel.GetTypeId())
+    return mobility.GetPosition()
+
+def AdvancePosition(node):
+    pos = GetPosition (node);
+    pos.x += 5.0
+    if pos.x >= 210.0:
+      return
+    SetPosition(node, pos)
+    ns3.Simulator.Schedule(ns3.Seconds(1.0), AdvancePosition, node)
+
+
+def main(argv):
+    ns3.Packet.EnablePrinting ();
+
+    # enable rts cts all the time.
+    ns3.Config.SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", ns3.StringValue("0"))
+    # disable fragmentation
+    ns3.Config.SetDefault("ns3::WifiRemoteStationManager::FragmentationThreshold", ns3.StringValue ("2200"))
+
+    wifi = ns3.WifiHelper.Default()
+    mobility = ns3.MobilityHelper()
+    stas = ns3.NodeContainer()
+    ap = ns3.NodeContainer()
+    #NetDeviceContainer staDevs;
+    packetSocket = ns3.PacketSocketHelper()
+
+    stas.Create(2)
+    ap.Create(1)
+
+    # give packet socket powers to nodes.
+    packetSocket.Install(stas)
+    packetSocket.Install(ap)
+
+    wifiPhy = ns3.YansWifiPhyHelper.Default()
+    wifiChannel = ns3.YansWifiChannelHelper.Default()
+    wifiPhy.SetChannel(wifiChannel.Create())
+
+    ssid = ns3.Ssid("wifi-default")
+    wifi.SetRemoteStationManager("ns3::ArfWifiManager")
+    # setup stas.
+    wifi.SetMac("ns3::NqstaWifiMac", 
+               "Ssid", ns3.SsidValue(ssid),
+               "ActiveProbing", ns3.BooleanValue(False))
+    staDevs = wifi.Install(wifiPhy, stas)
+    # setup ap.
+    wifi.SetMac("ns3::NqapWifiMac", "Ssid", ns3.SsidValue(ssid),
+                "BeaconGeneration", ns3.BooleanValue(True),
+                "BeaconInterval", ns3.TimeValue(ns3.Seconds(2.5)))
+    wifi.Install(wifiPhy, ap)
+
+    # mobility.
+    mobility.Install(stas)
+    mobility.Install(ap)
+
+    ns3.Simulator.Schedule(ns3.Seconds(1.0), AdvancePosition, ap.Get(0))
+
+    socket = ns3.PacketSocketAddress()
+    socket.SetSingleDevice(staDevs.Get(0).GetIfIndex())
+    socket.SetPhysicalAddress(staDevs.Get(1).GetAddress())
+    socket.SetProtocol(1)
+
+    onoff = ns3.OnOffHelper("ns3::PacketSocketFactory", ns3.Address(socket))
+    onoff.SetAttribute("OnTime", ns3.RandomVariableValue(ns3.ConstantVariable(42)))
+    onoff.SetAttribute("OffTime", ns3.RandomVariableValue(ns3.ConstantVariable(0)))
+
+    apps = onoff.Install(ns3.NodeContainer(stas.Get(0)))
+    apps.Start(ns3.Seconds(0.5))
+    apps.Stop(ns3.Seconds(43.0))
+
+    ns3.Simulator.Stop(ns3.Seconds(44.0))
+
+  #   Config::Connect ("/NodeList/*/DeviceList/*/Tx", MakeCallback (&DevTxTrace));
+  #   Config::Connect ("/NodeList/*/DeviceList/*/Rx", MakeCallback (&DevRxTrace));
+  #   Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxOk", MakeCallback (&PhyRxOkTrace));
+  #   Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxError", MakeCallback (&PhyRxErrorTrace));
+  #   Config::Connect ("/NodeList/*/DeviceList/*/Phy/Tx", MakeCallback (&PhyTxTrace));
+  #   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State", MakeCallback (&PhyStateTrace));
+
+    ns3.Simulator.Run()
+
+    ns3.Simulator.Destroy()
+
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
+
--- a/regression.py	Tue Jan 13 17:17:37 2009 -0500
+++ b/regression.py	Tue Jan 20 11:41:57 2009 -0500
@@ -14,32 +14,6 @@
 import wutils
 
 
-#
-# The directory in which the tarball of the reference traces lives.  This is
-# used if Mercurial is not on the system.
-#
-REGRESSION_TRACES_URL = "http://www.nsnam.org/releases/"
-
-#
-# The path to the Mercurial repository used to find the reference traces if
-# we find "hg" on the system.  We expect that the repository will be named
-# identically to refDirName below
-#
-REGRESSION_TRACES_REPO = "http://code.nsnam.org/"
-
-#
-# Name of the local directory where the regression code lives.
-#
-REGRESSION_DIR = "regression"
-
-#
-# The last part of the path name to use to find the regression traces.  The
-# path will be APPNAME + '-' + VERSION + REGRESSION_SUFFIX, e.g.,
-# ns-3-dev-ref-traces
-#
-REGRESSION_SUFFIX = "-ref-traces"
-
-
 def dev_null():
     if sys.platform == 'win32':
         return open("NUL:", "w")
@@ -90,19 +64,13 @@
                 os.mkdir(refTestDirName)
 
             if pyscript is None:
-                Options.options.cwd_launch = refTestDirName
                 tmpl = "%s"
                 for arg in arguments:
                     tmpl = tmpl + " " + arg
-                wutils.run_program(testName, tmpl)
+                wutils.run_program(testName, tmpl, cwd=refTestDirName)
             else:
                 argv = [self.env['PYTHON'], os.path.join(Options.cwd_launch, *os.path.split(pyscript))] + arguments
-                before = os.getcwd()
-                os.chdir(refTestDirName)
-                try:
-                    wutils.run_argv(argv)
-                finally:
-                    os.chdir(before)
+                wutils.run_argv(argv, cwd=refTestDirName)
             print "Remember to commit " + refTestDirName
             return 0
         else:
@@ -110,12 +78,11 @@
                 print "Cannot locate reference traces in " + refTestDirName
                 return 1
 
-            
             if refTestName is None:
                 traceDirName = testName + ".ref"
             else:
                 traceDirName = refTestName
-            traceDirName = os.path.join ('traces', traceDirName)
+            traceDirName = os.path.join('regression', 'traces', traceDirName)
 
             try:
                 shutil.rmtree(traceDirName)
@@ -123,20 +90,13 @@
                 pass
             os.mkdir(traceDirName)
 
-            #os.system("./waf --cwd regression/traces --run " +
-            #  testName + " > /dev/null 2>&1")
-
             if pyscript is None:
-                Options.options.cwd_launch = traceDirName
-                wutils.run_program(testName, command_template=wutils.get_command_template(*arguments))
+                wutils.run_program(testName,
+                                   command_template=wutils.get_command_template(*arguments),
+                                   cwd=traceDirName)
             else:
                 argv = [self.env['PYTHON'], os.path.join('..', '..', '..', *os.path.split(pyscript))] + arguments
-                before = os.getcwd()
-                os.chdir(traceDirName)
-                try:
-                    wutils.run_argv(argv)
-                finally:
-                    os.chdir(before)
+                wutils.run_argv(argv, cwd=traceDirName)
 
             if verbose:
                 #diffCmd = "diff traces " + refTestDirName + " | head"
@@ -179,22 +139,15 @@
 def run_regression(reference_traces):
     """Execute regression tests.  Called with cwd set to the 'regression' subdir of ns-3.
 
-    @param reference_traces: reference traces directory, or None for default.
+    @param reference_traces: reference traces directory.
 
     """
 
-    testdir = "tests"
+    testdir = os.path.join("regression", "tests")
     if not os.path.exists(testdir):
         print "Tests directory does not exist"
         sys.exit(3)
 
-    dir_name = (wutils.APPNAME + '-' + wutils.VERSION + REGRESSION_SUFFIX)
-    if reference_traces is None:
-        reference_traces = dir_name
-        no_net = False
-    else:
-        no_net = True
-    
     sys.path.append(testdir)
     sys.modules['tracediff'] = Regression(testdir, reference_traces)
 
@@ -205,32 +158,6 @@
 
     print "========== Running Regression Tests =========="
     env = Build.bld.env
-    if not no_net:
-        if env['MERCURIAL']:
-            print "Synchronizing reference traces using Mercurial."
-            if not os.path.exists(reference_traces):
-                print "Cloning " + REGRESSION_TRACES_REPO + dir_name + " from repo."
-                argv = ["hg", "clone", REGRESSION_TRACES_REPO + dir_name, reference_traces]
-                rv = subprocess.Popen(argv).wait()
-            else:
-                _dir = os.getcwd()
-                os.chdir(reference_traces)
-                try:
-                    print "Pulling " + REGRESSION_TRACES_REPO + dir_name + " from repo."
-                    result = subprocess.Popen(["hg", "-q", "pull", REGRESSION_TRACES_REPO + dir_name]).wait()
-                    if not result:
-                        result = subprocess.Popen(["hg", "-q", "update"]).wait()
-                finally:
-                    os.chdir("..")
-                if result:
-                    raise Utils.WafError("Synchronizing reference traces using Mercurial failed.")
-        else:
-            if not os.path.exists(reference_traces):
-                traceball = dir_name + wutils.TRACEBALL_SUFFIX
-                print "Retrieving " + traceball + " from web."
-                urllib.urlretrieve(REGRESSION_TRACES_URL + traceball, traceball)
-                os.system("tar -xjf %s -C .." % (traceball))
-                print "Done."
 
     if not os.path.exists(reference_traces):
         print "Reference traces directory (%s) does not exist" % reference_traces
@@ -252,7 +179,7 @@
         except NotImplementedError:
             print "SKIP " + test            
 
-    return len(bad) > 0
+    return (len(bad) > 0)
 
 
 def _run_regression_test(test):
@@ -261,15 +188,15 @@
     Arguments:
     test -- the name of the test
     """
-
-    if os.path.exists("traces"):
-        files = os.listdir("traces")
+    traces_dir = os.path.join("regression", "traces")
+    if os.path.exists(traces_dir):
+        files = os.listdir(traces_dir)
         for file in files:
             if file == '.' or file == '..':
                 continue
             shutil.rmtree(os.path.join("traces", file), ignore_errors=True)
     else:
-        os.mkdir("traces")
+        os.mkdir(traces_dir)
     
     mod = __import__(test, globals(), locals(), [])
     return mod.run(verbose=(Options.options.verbose > 0),
--- a/samples/wscript	Tue Jan 13 17:17:37 2009 -0500
+++ b/samples/wscript	Tue Jan 20 11:41:57 2009 -0500
@@ -19,8 +19,9 @@
     obj = bld.create_ns3_program('main-test')
     obj.source = 'main-test.cc'
 
-    obj = bld.create_ns3_program('main-test-sync')
-    obj.source = 'main-test-sync.cc'
+    if bld.env['ENABLE_THREADING']:
+        obj = bld.create_ns3_program('main-test-sync')
+        obj.source = 'main-test-sync.cc'
 
     obj = bld.create_ns3_program('main-simple',
                                  ['node', 'internet-stack', 'onoff'])
--- a/src/common/pcap-writer.cc	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/common/pcap-writer.cc	Tue Jan 20 11:41:57 2009 -0500
@@ -86,7 +86,7 @@
 
   NS_LOG_LOGIC ("Created writer " << m_writer);
 
-  m_writer->open (name.c_str ());
+  m_writer->open (name.c_str (), std::ios_base::binary | std::ios_base::out);
   NS_ABORT_MSG_IF (m_writer->fail (), "PcapWriter::Open(): m_writer->open(" << name.c_str () << ") failed");
 
   NS_ASSERT_MSG (m_writer->is_open (), "PcapWriter::Open(): m_writer not open");
--- a/src/devices/wifi/wifi-mac-queue.cc	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/devices/wifi/wifi-mac-queue.cc	Tue Jan 20 11:41:57 2009 -0500
@@ -28,6 +28,9 @@
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (WifiMacQueue);
+
+
 WifiMacQueue::Item::Item (Ptr<const Packet> packet, 
                           WifiMacHeader const &hdr, 
                           Time tstamp)
@@ -37,7 +40,7 @@
 TypeId 
 WifiMacQueue::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("WifiMacQueue")
+  static TypeId tid = TypeId ("ns3::WifiMacQueue")
     .SetParent<Object> ()
     .AddConstructor<WifiMacQueue> ()
     .AddAttribute ("MaxPacketNumber", "If a packet arrives when there are already this number of packets, it is dropped.",
--- a/src/simulator/calendar-scheduler.cc	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/calendar-scheduler.cc	Tue Jan 20 11:41:57 2009 -0500
@@ -331,6 +331,7 @@
           DoInsert (*j);
         }
     }
+  delete [] oldBuckets;
 }
 void 
 CalendarScheduler::Resize (uint32_t newSize)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/ns2-calendar-scheduler.cc	Tue Jan 20 11:41:57 2009 -0500
@@ -0,0 +1,495 @@
+/* -*- Mode:C++; c-basic-offset:8; tab-width:8; -*- */
+/*
+ * Copyright (c) 1997 David Wetherall
+ * Copyright (c) 2005 David Wei
+ * Copyright (c) 2009 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * 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
+ */
+
+#include "ns2-calendar-scheduler.h"
+#include "event-impl.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include <cassert>
+#include <math.h>
+#include <string.h>
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("Ns2CalendarScheduler");
+
+NS_OBJECT_ENSURE_REGISTERED (Ns2CalendarScheduler);
+
+#define CALENDAR_HASH(key) ((key.m_ts / width_) % nbuckets_)
+
+TypeId 
+Ns2CalendarScheduler::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::Ns2CalendarScheduler")
+		.SetParent<Scheduler> ()
+		.AddConstructor<Ns2CalendarScheduler> ()
+		;
+	return tid;
+}
+
+Ns2CalendarScheduler::Ns2CalendarScheduler ()
+{
+	NS_LOG_FUNCTION (this);
+
+	adjust_new_width_interval_ = 10;
+	min_bin_width_ = 1;
+	avg_gap_ = -2;
+	last_time_ = 0;
+	gap_num_ = 0;
+	head_search_ = 0;
+	insert_search_ = 0; 
+	round_num_ = 0; 
+	time_to_newwidth_ = adjust_new_width_interval_;
+	cal_clock_ = Scheduler::EventKey ();
+	reinit(4, 1, cal_clock_);
+}
+Ns2CalendarScheduler::~Ns2CalendarScheduler ()
+{
+	NS_LOG_FUNCTION (this);
+	
+	for (int i = 0; i < nbuckets_; i++) {
+		Bucket *bucket = &buckets_[i];
+		if (bucket->list_ == 0) {
+			continue;
+		}
+		if (bucket->list_->next_ == bucket->list_) {
+			delete bucket->list_;
+			continue;
+		}
+		BucketItem *next;
+		BucketItem *cur;
+		for (cur = bucket->list_; 
+		     cur->next_ != bucket->list_; 
+		     cur = next) {
+			next = cur->next_;
+			delete cur;
+		}
+		delete cur;
+	}
+	delete [] buckets_;
+	qsize_ = 0;
+	stat_qsize_ = 0;
+}
+void
+Ns2CalendarScheduler::Insert (const Event &event)
+{
+	NS_LOG_FUNCTION (this);
+
+	Scheduler::EventKey newtime = event.key;
+	int i = CALENDAR_HASH(newtime);
+
+	Bucket* current=(&buckets_[i]);
+	BucketItem *head = current->list_;
+	BucketItem *after=0;
+	BucketItem *e = new BucketItem ();
+	e->event = event;
+
+	if (!head) {
+		current->list_ = e;
+		e->next_ = e->prev_ = e;
+		++stat_qsize_; 
+		++(current->count_);
+	} else {
+		insert_search_++;
+		if (newtime < head->event.key) {
+			//  e-> head -> ...
+			e->next_ = head;
+			e->prev_ = head->prev_;
+			e->prev_->next_ = e;
+			head->prev_ = e;
+			current->list_ = e;
+			++stat_qsize_;
+			++(current->count_);
+		} else {
+			for (after = head->prev_; newtime < after->event.key; after = after->prev_) 
+				{ insert_search_++; };
+			//...-> after -> e -> ...
+			e->next_ = after->next_;
+			e->prev_ = after;
+			e->next_->prev_ = e;
+			after->next_ = e;
+			if (after->event.key < newtime) {
+				//unique timing
+				++stat_qsize_; 
+				++(current->count_);
+			}
+		}
+	}
+	++qsize_;
+	//assert(e == buckets_[i].list_ ||  e->prev_->time_ <= e->time_);
+	//assert(e == buckets_[i].list_->prev_ || e->next_->time_ >= e->time_);
+
+	if (stat_qsize_ > top_threshold_) {
+		resize(nbuckets_ << 1, cal_clock_);
+		return;
+	}
+}
+bool 
+Ns2CalendarScheduler::IsEmpty (void) const
+{
+	return qsize_ == 0;
+}
+Scheduler::Event
+Ns2CalendarScheduler::PeekNext (void) const
+{
+	NS_LOG_FUNCTION (this);
+	NS_ASSERT (!IsEmpty ());
+
+	BucketItem *e = const_cast<Ns2CalendarScheduler *> (this)->head ();
+	NS_ASSERT (e != 0);
+	
+	return e->event;
+}
+
+
+Scheduler::Event
+Ns2CalendarScheduler::RemoveNext (void)
+{
+	NS_LOG_FUNCTION (this);
+	NS_ASSERT (!IsEmpty ());
+
+	BucketItem *e = head ();
+	NS_ASSERT (e != 0);
+
+	if (last_time_ == 0) last_time_ = e->event.key.m_ts;
+	else 
+	{
+		gap_num_ ++;
+		if (gap_num_ >= qsize_ ) {
+			uint64_t tt_gap_ = e->event.key.m_ts - last_time_;
+			avg_gap_ = tt_gap_ / gap_num_;
+			gap_num_ = 0;
+			last_time_ = e->event.key.m_ts;
+			round_num_ ++;
+			if ((round_num_ > 20) &&
+			    (( head_search_> (insert_search_<<1))
+			     ||( insert_search_> (head_search_<<1)) )) 
+				{
+					resize(nbuckets_, cal_clock_);
+					round_num_ = 0;
+				} else {
+				if (round_num_ > 100) {
+					round_num_ = 0;
+					head_search_ = 0;
+					insert_search_ = 0;
+				}
+			}
+		}
+	}
+
+	int l = lastbucket_;
+
+	// update stats and unlink
+	if (e->next_ == e || e->next_->event.key != e->event.key) {
+		--stat_qsize_;
+		//assert(stat_qsize_ >= 0);
+		--buckets_[l].count_;
+		//assert(buckets_[l].count_ >= 0);
+	}
+	--qsize_;
+
+	if (e->next_ == e)
+		buckets_[l].list_ = 0;
+	else {
+		e->next_->prev_ = e->prev_;
+		e->prev_->next_ = e->next_;
+		buckets_[l].list_ = e->next_;
+	}
+
+	e->next_ = e->prev_ = NULL;
+
+
+	//if (buckets_[l].count_ == 0)
+	//	assert(buckets_[l].list_ == 0);
+  
+	if (stat_qsize_ < bot_threshold_) {
+		resize(nbuckets_ >> 1, cal_clock_);
+	}
+
+	Scheduler::Event event = e->event;
+	delete e;
+	return event;
+}
+
+void
+Ns2CalendarScheduler::Remove (const Event &ev)
+{
+	NS_ASSERT (!IsEmpty ());
+
+
+	int i = CALENDAR_HASH(ev.key);
+
+	Bucket* current=(&buckets_[i]);
+	BucketItem *head = current->list_;
+	BucketItem *e=0;
+
+	if (!head) {
+		NS_LOG_DEBUG ("event not in scheduler");
+		return;
+	}
+	for (e = head->prev_; ev.key != e->event.key; e = e->prev_) {}
+	--stat_qsize_;
+	--buckets_[i].count_;
+	if (e->next_ == e) {
+		assert(buckets_[i].list_ == e);
+		buckets_[i].list_ = 0;
+	} else {
+		e->next_->prev_ = e->prev_;
+		e->prev_->next_ = e->next_;
+		if (buckets_[i].list_ == e)
+			buckets_[i].list_ = e->next_;
+	}
+
+	if (buckets_[i].count_ == 0)
+		assert(buckets_[i].list_ == 0);
+
+	e->next_ = e->prev_ = NULL;
+
+	delete e;
+
+	--qsize_;
+
+	return;
+}
+
+Ns2CalendarScheduler::BucketItem *
+Ns2CalendarScheduler::head (void)
+{
+	NS_ASSERT (!IsEmpty ());
+	
+	int l = -1, i = lastbucket_;
+	int lastbucket_dec = (lastbucket_) ? lastbucket_ - 1 : nbuckets_ - 1;
+	uint64_t diff;
+	BucketItem *e, *min_e = NULL;
+#define CAL_DEQUEUE(x) 						\
+do {							\
+	head_search_++;						\
+	if ((e = buckets_[i].list_) != NULL) {			\
+		diff = e->event.key.m_ts - cal_clock_.m_ts;	\
+		if (diff < diff##x##_)	{			\
+			l = i;					\
+			goto found_l;				\
+		}						\
+		if (min_e == NULL || min_e->event.key > e->event.key) {	\
+			min_e = e;					\
+			l = i;						\
+		}							\
+	}								\
+	if (++i == nbuckets_) i = 0;					\
+} while (0)
+  
+	// CAL_DEQUEUE applied successively will find the event to
+	// dequeue (within one year) and keep track of the
+	// minimum-priority event seen so far; the argument controls
+	// the criteria used to decide whether the event should be
+	// considered `within one year'.  Importantly, the number of
+	// buckets should not be less than 4.
+	CAL_DEQUEUE(0); 
+	CAL_DEQUEUE(1); 
+	for (; i != lastbucket_dec; ) {
+		CAL_DEQUEUE(2);
+	}
+	// one last bucket is left unchecked - take the minimum
+	// [could have done CAL_DEQUEUE(3) with diff3_ = bwidth*(nbuck*3/2-1)]
+	e = buckets_[i].list_;
+	if (min_e != NULL && 
+	    (e == NULL || min_e->event.key < e->event.key))
+		e = min_e;
+	else {
+		//assert(e);
+		l = i;
+	}
+ found_l:
+	//assert(buckets_[l].count_ >= 0);
+	//assert(buckets_[l].list_ == e);
+  
+	/* l is the index of the bucket to dequeue, e is the event */
+	/* 
+	 * still want to advance lastbucket_ and cal_clock_ to save
+	 * time when deque() follows. 
+	 */
+	assert (l != -1);
+	lastbucket_ = l;
+	cal_clock_  = e->event.key;
+
+	return e;
+}
+
+void 
+Ns2CalendarScheduler::reinit(int nbuck, uint64_t bwidth, Scheduler::EventKey start)
+{
+	buckets_ = new Bucket[nbuck];
+
+	memset(buckets_, 0, sizeof(Bucket)*nbuck); //faster than ctor
+  
+	width_ = bwidth;
+	nbuckets_ = nbuck;
+	qsize_ = 0;
+	stat_qsize_ = 0;
+        
+	lastbucket_ =  CALENDAR_HASH(start);
+
+	diff0_ = bwidth*nbuck/2;
+	diff1_ = diff0_ + bwidth;
+	diff2_ = bwidth*nbuck;
+	//diff3_ = bwidth*(nbuck*3/2-1);
+  
+	bot_threshold_ = (nbuck >> 1) - 2;
+	top_threshold_ = (nbuck << 1);
+}
+
+void 
+Ns2CalendarScheduler::resize(int newsize, Scheduler::EventKey start)
+{
+	uint64_t bwidth;
+	if (newsize == nbuckets_) {
+		/* we resize for bwidth*/
+		if (head_search_) bwidth = head_search_; else bwidth = 1;
+		if (insert_search_) bwidth = bwidth / insert_search_;
+		bwidth = static_cast<uint64_t> (sqrt (bwidth) * width_);
+		if (bwidth < min_bin_width_) {
+			if (time_to_newwidth_>0) {
+				time_to_newwidth_ --;
+				head_search_ = 0;
+				insert_search_ = 0;
+				round_num_ = 0;
+				return; //failed to adjust bwidth
+			} else {
+				// We have many (adjust_new_width_interval_) times failure in adjusting bwidth.
+				// should do a reshuffle with newwidth 
+				bwidth = newwidth(newsize);
+			}
+		}
+		//snoopy queue calculation
+	} else {
+		/* we resize for size */
+		bwidth = newwidth(newsize);
+		if (newsize < 4)
+			newsize = 4;
+	}
+
+	Bucket *oldb = buckets_;
+	int oldn = nbuckets_;
+
+	reinit(newsize, bwidth, start);
+
+	// copy events to new buckets
+	int i;
+
+	for (i = 0; i < oldn; ++i) {
+		// we can do inserts faster, if we use insert2, but to
+		// preserve FIFO, we have to start from the end of
+		// each bucket and use insert2
+		if  (oldb[i].list_) {
+			BucketItem *tail = oldb[i].list_->prev_;
+			BucketItem *e = tail; 
+			do {
+				BucketItem* ep = e->prev_;
+				e->next_ = e->prev_ = 0;
+				insert2(e);
+				e = ep;
+			} while (e != tail);
+		}
+	}
+	head_search_ = 0;
+	insert_search_ = 0;
+	round_num_ = 0;
+	delete [] oldb;
+}
+
+void 
+Ns2CalendarScheduler::insert2(Ns2CalendarScheduler::BucketItem* e)
+{
+	// Same as insert, but for inserts e *before* any same-time-events, if
+	//   there should be any.  Since it is used only by CalendarScheduler::newwidth(),
+	//   some important checks present in insert() need not be performed.
+
+	int i = CALENDAR_HASH(e->event.key);
+	BucketItem *head = buckets_[i].list_;
+	BucketItem *before=0;
+	if (!head) {
+		buckets_[i].list_ = e;
+		e->next_ = e->prev_ = e;
+		++stat_qsize_; 
+		++buckets_[i].count_;
+	} else {
+		bool newhead;
+		if (e->event.key > head->prev_->event.key) { //strict LIFO, so > and not >=
+			// insert at the tail
+			before = head;
+			newhead = false;
+		} else {
+			// insert event in time sorted order, LIFO for sim-time events
+			for (before = head; e->event.key > before->event.key; before = before->next_)
+				;
+			newhead = (before == head);
+		}
+
+		e->next_ = before;
+		e->prev_ = before->prev_;
+		before->prev_ = e;
+		e->prev_->next_ = e;
+		if (newhead) {
+			buckets_[i].list_ = e;
+			//assert(e->time_ <= e->next_->time_);
+		}
+
+		if (e != e->next_ && e->next_->event.key != e->event.key) {
+			// unique timing
+			++stat_qsize_; 
+			++buckets_[i].count_;
+		}
+	}
+	//assert(e == buckets_[i].list_ ||  e->prev_->time_ <= e->time_);
+	//assert(e == buckets_[i].list_->prev_ || e->next_->time_ >= e->time_);
+
+	++qsize_;
+	// no need to check resizing
+}
+
+uint64_t
+Ns2CalendarScheduler::newwidth(int newsize)
+{
+	if (adjust_new_width_interval_) {
+		time_to_newwidth_ = adjust_new_width_interval_;
+		if (avg_gap_ > 0) return avg_gap_*4;
+	}
+	int i;
+	int max_bucket = 0; // index of the fullest bucket
+	for (i = 1; i < nbuckets_; ++i) {
+		if (buckets_[i].count_ > buckets_[max_bucket].count_)
+			max_bucket = i;
+	}
+	int nsamples = buckets_[max_bucket].count_;
+
+	if (nsamples <= 4) return width_;
+	
+	uint64_t nw = (buckets_[max_bucket].list_->prev_->event.key.m_ts 
+		       - buckets_[max_bucket].list_->event.key.m_ts) * 4;
+	
+	nw /= ((newsize < nsamples) ? newsize : nsamples); // min (newsize, nsamples)
+
+	nw = std::max (nw, min_bin_width_);
+	
+	return nw;
+}
+
+  
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/ns2-calendar-scheduler.h	Tue Jan 20 11:41:57 2009 -0500
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 1997 David Wetherall
+ * Copyright (c) 2005 David Wei
+ * Copyright (c) 2009 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * 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
+ *
+ * Authors: 
+ *  David Wetherall <djw@juniper.lcs.mit.edu>: originally, in ns-2, back in 1997
+ *  David X. Wei: optimizations in ns-2.28
+ *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>: port to ns-3
+ */
+
+#ifndef NS2_CALENDAR_SCHEDULER_H
+#define NS2_CALENDAR_SCHEDULER_H
+
+#include "scheduler.h"
+#include <stdint.h>
+#include <list>
+
+namespace ns3 {
+
+class EventImpl;
+
+/**
+ * \ingroup scheduler
+ * \brief a calendar queue event scheduler
+ *
+ * This event scheduler is a copy/paste of the ns2.29 calendar scheduler.
+ */
+class Ns2CalendarScheduler : public Scheduler 
+{
+public:
+  static TypeId GetTypeId (void);
+
+  Ns2CalendarScheduler ();
+  virtual ~Ns2CalendarScheduler ();
+
+  virtual void Insert (const Event &ev);
+  virtual bool IsEmpty (void) const;
+  virtual Event PeekNext (void) const;
+  virtual Event RemoveNext (void);
+  virtual void Remove (const Event &ev);
+
+private:
+  struct BucketItem {
+    ns3::Scheduler::Event event;
+    struct BucketItem *next_;
+    struct BucketItem *prev_;
+  };
+  struct Bucket {
+    struct BucketItem *list_;
+    int count_;
+  };
+
+  void reinit(int nbuck, uint64_t bwidth, Scheduler::EventKey start);
+  void resize(int newsize, Scheduler::EventKey start);
+  uint64_t newwidth(int newsize);
+  void insert2 (Ns2CalendarScheduler::BucketItem *e);
+  Ns2CalendarScheduler::BucketItem *head (void);
+
+  
+  uint64_t min_bin_width_;		// minimum bin width for Calendar Queue
+  unsigned int adjust_new_width_interval_; // The interval (in unit of resize time) for adjustment of bin width. A zero value disables automatic bin width adjustment
+  unsigned time_to_newwidth_;	// how many time we failed to adjust the width based on snoopy-queue
+  long unsigned head_search_;
+  long unsigned insert_search_;
+  int round_num_;
+  long int gap_num_;		//the number of gap samples in this window (in process of calculation)
+  uint64_t last_time_;		//the departure time of first event in this window
+  int64_t avg_gap_;		//the average gap in last window (finished calculation)
+
+  uint64_t width_;
+  uint64_t diff0_, diff1_, diff2_; /* wrap-around checks */
+
+  int stat_qsize_;		/* # of distinct priorities in queue*/
+  int nbuckets_;
+  int lastbucket_;
+  int top_threshold_;
+  int bot_threshold_;
+  int qsize_;
+  struct Bucket *buckets_;
+  Scheduler::EventKey cal_clock_;
+};
+
+} // namespace ns3
+
+#endif /* NS2_CALENDAR_SCHEDULER_H */
--- a/src/simulator/scheduler.h	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/scheduler.h	Tue Jan 20 11:41:57 2009 -0500
@@ -115,6 +115,28 @@
       return false;
     }
 }
+inline bool operator != (const Scheduler::EventKey &a, const Scheduler::EventKey &b)
+{
+  return a.m_uid != b.m_uid;
+}
+inline bool operator > (const Scheduler::EventKey &a, const Scheduler::EventKey &b)
+{
+  if (a.m_ts > b.m_ts)
+    {
+      return true;
+    }
+  else if (a.m_ts == b.m_ts &&
+           a.m_uid > b.m_uid)
+    {
+      return true;
+    }
+  else
+    {
+      return false;
+    }
+}
+
+
 
 inline bool operator < (const Scheduler::Event &a, const Scheduler::Event &b)
 {
--- a/src/simulator/simulator.cc	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/simulator.cc	Tue Jan 20 11:41:57 2009 -0500
@@ -17,11 +17,13 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-
+#include "ns3/core-config.h"
 #include "simulator.h"
 #include "simulator-impl.h"
 #include "default-simulator-impl.h"
-#include "realtime-simulator-impl.h"
+#ifdef HAVE_PTHREAD_H
+# include "realtime-simulator-impl.h"
+#endif
 #include "scheduler.h"
 #include "event-impl.h"
 
@@ -314,6 +316,8 @@
 #include "list-scheduler.h"
 #include "heap-scheduler.h"
 #include "map-scheduler.h"
+#include "calendar-scheduler.h"
+#include "ns2-calendar-scheduler.h"
 
 namespace ns3 {
 
@@ -740,6 +744,20 @@
     }
   Simulator::Destroy ();
 
+  Simulator::SetScheduler (CreateObject<CalendarScheduler> ());
+  if (!RunOneTest ()) 
+    {
+      result = false;
+    }
+  Simulator::Destroy ();
+
+  Simulator::SetScheduler (CreateObject<Ns2CalendarScheduler> ());
+  if (!RunOneTest ()) 
+    {
+      result = false;
+    }
+  Simulator::Destroy ();
+
   Simulator::Schedule (Seconds (0.0), &foo0);
   Simulator::Schedule (Seconds (0.0), &foo1, 0);
   Simulator::Schedule (Seconds (0.0), &foo2, 0, 0);
--- a/src/simulator/simulator.h	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/simulator.h	Tue Jan 20 11:41:57 2009 -0500
@@ -97,8 +97,8 @@
   static void Destroy (void);
 
   /**
-   * If there any any events lefts to be scheduled and simulation time
-   * has not yet reached the "stop time" (see Simulator::Stop()),
+   * If there are no more events lefts to be scheduled, or if simulation
+   * time has already reached the "stop time" (see Simulator::Stop()),
    * return true. Return false otherwise.
    */
   static bool IsFinished (void);
--- a/src/simulator/wscript	Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/wscript	Tue Jan 20 11:41:57 2009 -0500
@@ -49,6 +49,7 @@
         'map-scheduler.cc',
         'heap-scheduler.cc',
         'calendar-scheduler.cc',
+        'ns2-calendar-scheduler.cc',
         'event-impl.cc',
         'simulator.cc',
         'default-simulator-impl.cc',
@@ -73,6 +74,7 @@
         'map-scheduler.h',
         'heap-scheduler.h',
         'calendar-scheduler.h',
+        'ns2-calendar-scheduler.h',
         'simulation-singleton.h',
         'timer.h',
         'timer-impl.h',
Binary file waf has changed
--- a/wscript	Tue Jan 13 17:17:37 2009 -0500
+++ b/wscript	Tue Jan 20 11:41:57 2009 -0500
@@ -53,9 +53,6 @@
     shutil.rmtree("doc/latex", True)
     shutil.rmtree("nsc", True)
 
-    if not os.path.exists("bindings/python/pybindgen"):
-        raise Utils.WafError("Missing pybindgen checkout; run './waf configure --pybindgen-checkout' first.")
-
     ## build the name of the traces subdirectory.  Will be something like
     ## ns-3-dev-ref-traces
     traces_name = APPNAME + '-' + VERSION + regression.REGRESSION_SUFFIX
@@ -197,9 +194,7 @@
     variant_name = Options.options.build_profile
 
     if Options.options.regression_traces is not None:
-        variant_env['REGRESSION_TRACES'] = os.path.join("..", Options.options.regression_traces)
-    else:
-        variant_env['REGRESSION_TRACES'] = None
+        variant_env['REGRESSION_TRACES'] = os.path.abspath(Options.options.regression_traces)
 
     if Options.options.enable_gcov:
         variant_name += '-gcov'
@@ -309,33 +304,19 @@
 	    continue
         if os.path.isdir(os.path.join("scratch", filename)):
             obj = bld.create_ns3_program(filename, all_modules)
-            obj.path = obj.path.find_dir('scratch')
-            obj.find_sources_in_dirs(filename)
-            obj.target = os.path.join(filename, filename)
+            obj.path = obj.path.find_dir('scratch').find_dir(filename)
+            obj.find_sources_in_dirs('.')
+            obj.target = filename
             obj.name = obj.target
         elif filename.endswith(".cc"):
             name = filename[:-len(".cc")]
             obj = bld.create_ns3_program(name, all_modules)
-            obj.source = "scratch/%s" % filename
-            obj.target = "scratch/%s" % name
+            obj.path = obj.path.find_dir('scratch')
+            obj.source = filename
+            obj.target = name
             obj.name = obj.target
 
 
-##
-## This replacement spawn function increases the maximum command line length to 32k
-##
-def _exec_command_interact_win32(s):
-    if Params.g_verbose:
-        print s
-    startupinfo = subprocess.STARTUPINFO()
-    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
-    proc = subprocess.Popen(s, shell=False, startupinfo=startupinfo)
-    stat = proc.wait()
-    if stat & 0xff:
-        return stat | 0x80
-    return stat >> 8
-
-
 def build(bld):
     if Options.options.no_task_lines:
         import Runner
@@ -343,10 +324,6 @@
             pass
         Runner.printout = null_printout
 
-    if sys.platform == 'win32':
-        import Runner
-        Runner.exec_command = _exec_command_interact_win32
-
     Options.cwd_launch = bld.path.abspath()
     bld.create_ns3_program = types.MethodType(create_ns3_program, bld)
     bld.create_suid_program = types.MethodType(create_suid_program, bld)
@@ -436,7 +413,7 @@
         # nothing more; this greatly speeds up compilation when all you
         # want to do is run a test program.
         if not Options.options.compile_targets:
-            Options.options.compile_targets = program_name
+            Options.options.compile_targets = os.path.basename(program_name)
 
 
 
@@ -462,15 +439,11 @@
         if not env['DIFF']:
             raise Utils.WafError("Cannot run regression tests: the 'diff' program is not installed.")
 
-        _dir = os.getcwd()
-        os.chdir("regression")
         regression_traces = env['REGRESSION_TRACES']
         if not regression_traces:
-            regression_traces = None
-        try:
-            retval = regression.run_regression(regression_traces)
-        finally:
-            os.chdir(_dir)
+            raise Utils.WafError("Cannot run regression tests: reference traces directory not given"
+                                 " (--with-regression-traces configure option)")
+        retval = regression.run_regression(regression_traces)
         if retval:
             sys.exit(retval)
 
--- a/wutils.py	Tue Jan 13 17:17:37 2009 -0500
+++ b/wutils.py	Tue Jan 20 11:41:57 2009 -0500
@@ -38,9 +38,30 @@
     return cmd
 
 
+if hasattr(os.path, "relpath"):
+    relpath = os.path.relpath # since Python 2.6
+else:
+    def relpath(path, start=os.path.curdir):
+        """Return a relative version of a path"""
+
+        if not path:
+            raise ValueError("no path specified")
+
+        start_list = os.path.abspath(start).split(os.path.sep)
+        path_list = os.path.abspath(path).split(os.path.sep)
+
+        # Work out how much of the filepath is shared by start and path.
+        i = len(os.path.commonprefix([start_list, path_list]))
+
+        rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+        if not rel_list:
+            return os.path.curdir
+        return os.path.join(*rel_list)
+
 
 def find_program(program_name, env):
     launch_dir = os.path.abspath(Options.cwd_launch)
+    top_dir = os.path.abspath(Options.launch_dir)
     found_programs = []
     for obj in Build.bld.all_task_gen:
         if not getattr(obj, 'is_ns3_program', False):
@@ -51,8 +72,11 @@
                 or obj.path.abspath(env).startswith(launch_dir)):
             continue
         
-        found_programs.append(obj.target)
-        if obj.target == program_name:
+        name1 = obj.target
+        name2 = os.path.join(relpath(obj.path.abspath(), top_dir), obj.target)
+        names = [name1, name2]
+        found_programs.extend(names)
+        if program_name in names:
             return obj
     raise ValueError("program '%s' not found; available programs are: %r"
                      % (program_name, found_programs))
@@ -93,10 +117,10 @@
 
     return proc_env
 
-def run_argv(argv, os_env=None):
+def run_argv(argv, os_env=None, cwd=None):
     proc_env = get_proc_env(os_env)
     #env = Build.bld.env
-    retval = subprocess.Popen(argv, env=proc_env).wait()
+    retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
     if retval:
         raise Utils.WafError("Command %s exited with code %i" % (argv, retval))
     return retval
@@ -143,7 +167,7 @@
         execvec = shlex.split(command_template % (program_node.abspath(env),))
     return program_name, execvec
 
-def run_program(program_string, command_template=None):
+def run_program(program_string, command_template=None, cwd=None):
     """
     if command_template is not None, then program_string == program
     name and argv is given by command_template with %s replaced by the
@@ -151,34 +175,23 @@
     a shell command with first name being the program name.
     """
     dummy_program_name, execvec = get_run_program(program_string, command_template)
-    former_cwd = os.getcwd()
-    if (Options.options.cwd_launch):
-        os.chdir(Options.options.cwd_launch)
-    else:
-        os.chdir(Options.cwd_launch)
-    try:
-        retval = run_argv(execvec)
-    finally:
-        os.chdir(former_cwd)
-
-    return retval
+    if cwd is None:
+        if (Options.options.cwd_launch):
+            cwd = Options.options.cwd_launch
+        else:
+            cwd = Options.cwd_launch
+    return run_argv(execvec, cwd=cwd)
 
 
 
 def run_python_program(program_string):
     env = Build.bld.env
     execvec = shlex.split(program_string)
-
-    former_cwd = os.getcwd()
-    if (Options.options.cwd_launch):
-        os.chdir(Options.options.cwd_launch)
-    else:
-        os.chdir(Options.cwd_launch)
-    try:
-        retval = run_argv([env['PYTHON']] + execvec)
-    finally:
-        os.chdir(former_cwd)
-
-    return retval
+    if cwd is None:
+        if (Options.options.cwd_launch):
+            cwd = Options.options.cwd_launch
+        else:
+            cwd = Options.cwd_launch
+    return run_argv([env['PYTHON']] + execvec, cwd=cwd)