[rtems-tools commit] Update rtems-tool to support Python 2 and 3.

Chris Johns chrisj at rtems.org
Thu Mar 3 05:57:48 UTC 2016


Module:    rtems-tools
Branch:    4.11
Commit:    4001a74869c5e37443e20c3ff107f6ccf8e378f8
Changeset: http://git.rtems.org/rtems-tools/commit/?id=4001a74869c5e37443e20c3ff107f6ccf8e378f8

Author:    Chris Johns <chrisj at rtems.org>
Date:      Wed Mar  2 20:54:06 2016 +1100

Update rtems-tool to support Python 2 and 3.

Add solaris and netbsd.

Close #2619.

---

 rtemstoolkit/__init__.py     |  15 ++++++-
 rtemstoolkit/check.py        |  44 +++++++++++-------
 rtemstoolkit/config.py       |  71 +++++++++++++++++------------
 rtemstoolkit/darwin.py       |   5 ++-
 rtemstoolkit/error.py        |  10 +++--
 rtemstoolkit/execute.py      |  83 +++++++++++++++++++++-------------
 rtemstoolkit/freebsd.py      |  14 ++++--
 rtemstoolkit/git.py          |  59 ++++++++++++++++--------
 rtemstoolkit/linux.py        |  16 +++++--
 rtemstoolkit/log.py          |  53 +++++++++++++---------
 rtemstoolkit/macros.py       |  78 +++++++++++++++++++++-----------
 rtemstoolkit/mailer.py       |  31 ++++++++-----
 rtemstoolkit/netbsd.py       |  96 +++++++++++++++++++++++++++++++++++++++
 rtemstoolkit/options.py      | 105 ++++++++++++++++++++++++++++++-------------
 rtemstoolkit/path.py         |  60 ++++++++++++++-----------
 rtemstoolkit/solaris.py      |  90 +++++++++++++++++++++++++++++++++++++
 rtemstoolkit/stacktraces.py  |   5 +--
 rtemstoolkit/version.py      |  19 ++++++--
 rtemstoolkit/windows.py      |  18 +++++---
 tester/rt/config.py          |  10 +++--
 tester/rt/console.py         |  16 ++++---
 tester/rt/gdb.py             |  61 ++++++++++++++-----------
 tester/rt/options.py         |  15 ++++---
 tester/rt/pygdb/__init__.py  |   5 ++-
 tester/rt/pygdb/mi_parser.py |  32 ++++++-------
 tester/rt/pygdb/spark.py     |  79 ++++++++++++++++----------------
 tester/rt/stty.py            |  10 +++--
 tester/rt/test.py            |  38 ++++++++--------
 tester/rt/version.py         |  16 +++----
 tester/rtems-test            |   6 ++-
 30 files changed, 793 insertions(+), 367 deletions(-)

diff --git a/rtemstoolkit/__init__.py b/rtemstoolkit/__init__.py
index 33f49f0..82b14b3 100644
--- a/rtemstoolkit/__init__.py
+++ b/rtemstoolkit/__init__.py
@@ -37,4 +37,17 @@ all = ['check',
        'macros',
        'mailer',
        'options',
-       'path']
+       'path',
+       'version']
+
+from . import check
+from . import config
+from . import error
+from . import execute
+from . import git
+from . import log
+from . import macros
+from . import mailer
+from . import options
+from . import path
+from . import version
diff --git a/rtemstoolkit/check.py b/rtemstoolkit/check.py
index f4c05b8..2890bd8 100644
--- a/rtemstoolkit/check.py
+++ b/rtemstoolkit/check.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,14 +32,28 @@
 # Check the defaults for a specific host.
 #
 
+from __future__ import print_function
+
 import os
 
-import error
-import execute
-import log
-import options
-import path
-import version
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import execute
+    from . import log
+    from . import options
+    from . import path
+    from . import version
+except (ValueError, SystemError):
+    import error
+    import execute
+    import log
+    import options
+    import path
+    import version
 
 def _check_none(_opts, macro, value, constraint):
     return True
@@ -117,7 +131,7 @@ def host_setup(opts):
 
     sane = True
 
-    for d in opts.defaults.keys():
+    for d in list(opts.defaults.keys()):
         try:
             (test, constraint, value) = opts.defaults.get(d)
         except:
@@ -155,16 +169,16 @@ def run():
         _opts = options.load(args = sys.argv)
         log.notice('RTEMS Source Builder - Check, v%s' % (version.str()))
         if host_setup(_opts):
-            print 'Environment is ok'
+            print('Environment is ok')
         else:
-            print 'Environment is not correctly set up'
-    except error.general, gerr:
-        print gerr
+            print('Environment is not correctly set up')
+    except error.general as gerr:
+        print(gerr)
         sys.exit(1)
-    except error.internal, ierr:
-        print ierr
+    except error.internal as ierr:
+        print(ierr)
         sys.exit(1)
-    except error.exit, eerr:
+    except error.exit as eerr:
         pass
     except KeyboardInterrupt:
         log.notice('abort: user terminated')
diff --git a/rtemstoolkit/config.py b/rtemstoolkit/config.py
index 306e3df..697bcaf 100644
--- a/rtemstoolkit/config.py
+++ b/rtemstoolkit/config.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -36,23 +36,30 @@
 # other software modules.
 #
 
+from __future__ import print_function
+
 import copy
+import functools
 import os
 import re
 import sys
 
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
 try:
+    from . import error
+    from . import execute
+    from . import log
+    from . import options
+    from . import path
+except (ValueError, SystemError):
     import error
     import execute
     import log
     import options
     import path
-except KeyboardInterrupt:
-    print 'user terminated'
-    sys.exit(1)
-except:
-    print 'error: unknown application load error'
-    sys.exit(1)
 
 def _check_bool(value):
     if value.isdigit():
@@ -90,6 +97,8 @@ class file(object):
                 self.macros.define(label)
         self._includes = []
         self.load_depth = 0
+        self.lc = 0
+        self.name = 'none'
 
     def __del__(self):
         pass
@@ -98,7 +107,7 @@ class file(object):
 
         def _dict(dd):
             s = ''
-            ddl = dd.keys()
+            ddl = list(dd.keys())
             ddl.sort()
             for d in ddl:
                 s += '  ' + d + ': ' + dd[d] + '\n'
@@ -137,14 +146,14 @@ class file(object):
            outter level. Nested levels will need to split with futher calls.'''
         trace_me = False
         if trace_me:
-            print '------------------------------------------------------'
+            print('------------------------------------------------------')
         macros = []
         nesting = []
         has_braces = False
         c = 0
         while c < len(s):
             if trace_me:
-                print 'ms:', c, '"' + s[c:] + '"', has_braces, len(nesting), nesting
+                print('ms:', c, '"' + s[c:] + '"', has_braces, len(nesting), nesting)
             #
             # We need to watch for shell type variables or the form '${var}' because
             # they can upset the brace matching.
@@ -192,9 +201,9 @@ class file(object):
                             macros.append(s[macro_start:c + 1].strip())
             c += 1
         if trace_me:
-            print 'ms:', macros
+            print('ms:', macros)
         if trace_me:
-            print '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-='
+            print('-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
         return macros
 
     def _shell(self, line):
@@ -432,13 +441,13 @@ class file(object):
                 else:
                     istrue = _check_bool(ifls[0])
                     if istrue == None:
-                        self._error('invalid if bool value: ' + reduce(add, ls, ''))
+                        self._error('invalid if bool value: ' + functools.reduce(add, ls, ''))
                         istrue = False
             elif len(ifls) == 2:
                 if ifls[0] == '!':
                     istrue = _check_bool(ifls[1])
                     if istrue == None:
-                        self._error('invalid if bool value: ' + reduce(add, ls, ''))
+                        self._error('invalid if bool value: ' + functools.reduce(add, ls, ''))
                         istrue = False
                     else:
                         istrue = not istrue
@@ -454,7 +463,7 @@ class file(object):
                     elif  ifls[1] == '!=':
                         istrue = True
                     else:
-                        self._error('invalid if bool operator: ' + reduce(add, ls, ''))
+                        self._error('invalid if bool operator: ' + functools.reduce(add, ls, ''))
             elif len(ifls) == 3:
                 if ifls[1] == '==':
                     if ifls[0] == ifls[2]:
@@ -487,9 +496,9 @@ class file(object):
                     else:
                         istrue = False
                 else:
-                    self._error('invalid %if operator: ' + reduce(add, ls, ''))
+                    self._error('invalid %if operator: ' + functools.reduce(add, ls, ''))
             else:
-                self._error('malformed if: ' + reduce(add, ls, ''))
+                self._error('malformed if: ' + functools.reduce(add, ls, ''))
             if invert:
                 istrue = not istrue
             log.trace('config: %s: _if:  %s %s' % (self.init_name, ifls, str(istrue)))
@@ -750,7 +759,7 @@ class file(object):
         try:
             log.trace('config: %s: _open: %s' % (self.init_name, path.host(configname)))
             config = open(path.host(configname), 'r')
-        except IOError, err:
+        except IOError as err:
             raise error.general('error opening config file: %s' % (path.host(configname)))
         self.configpath += [configname]
 
@@ -836,17 +845,23 @@ def run():
         #
         # Run where defaults.mc is located
         #
-        opts = options.load(sys.argv, defaults = 'defaults.mc')
-        log.trace('config: count %d' % (len(opts.config_files())))
-        for config_file in opts.config_files():
-            s = file(config_file, opts)
-            print s
-            del s
-    except error.general, gerr:
-        print gerr
+        long_opts = {
+            # key              macro        handler   param  defs   init
+            '--file'  :      ('_file',      'path',   True,  None,  False)
+        }
+        opts = options.command_line(base_path = '.',
+                                    argv = sys.argv,
+                                    long_opts = long_opts)
+        options.load(opts)
+        s = file(opts.defaults['_file'], opts)
+        s.load(opts.defaults['_file'])
+        print(s)
+        del s
+    except error.general as gerr:
+        print(gerr)
         sys.exit(1)
-    except error.internal, ierr:
-        print ierr
+    except error.internal as ierr:
+        print(ierr)
         sys.exit(1)
     except KeyboardInterrupt:
         log.notice('abort: user terminated')
diff --git a/rtemstoolkit/darwin.py b/rtemstoolkit/darwin.py
index 1d092cb..216dea2 100644
--- a/rtemstoolkit/darwin.py
+++ b/rtemstoolkit/darwin.py
@@ -35,7 +35,10 @@
 
 import os
 
-import execute
+try:
+    from . import execute
+except (ValueError, SystemError):
+    import execute
 
 def load():
     uname = os.uname()
diff --git a/rtemstoolkit/error.py b/rtemstoolkit/error.py
index 89ea181..9fe1b8c 100644
--- a/rtemstoolkit/error.py
+++ b/rtemstoolkit/error.py
@@ -32,6 +32,8 @@
 # Various errors we can raise.
 #
 
+from __future__ import print_function
+
 class error(Exception):
     """Base class for Builder exceptions."""
     def set_output(self, msg):
@@ -57,9 +59,9 @@ class exit(error):
 if __name__ == '__main__':
     try:
         raise general('a general error')
-    except general, gerr:
-        print 'caught:', gerr
+    except general as gerr:
+        print('caught:', gerr)
     try:
         raise internal('an internal error')
-    except internal, ierr:
-        print 'caught:', ierr
+    except internal as ierr:
+        print('caught:', ierr)
diff --git a/rtemstoolkit/execute.py b/rtemstoolkit/execute.py
index b1afc7c..147d501 100755
--- a/rtemstoolkit/execute.py
+++ b/rtemstoolkit/execute.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -34,6 +34,9 @@
 # Note, the subprocess module is only in Python 2.4 or higher.
 #
 
+from __future__ import print_function
+
+import functools
 import os
 import re
 import sys
@@ -41,8 +44,16 @@ import subprocess
 import threading
 import time
 
-import error
-import log
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import log
+except (ValueError, SystemError):
+    import error
+    import log
 
 # Trace exceptions
 trace_threads = False
@@ -96,7 +107,7 @@ def arg_subst(command, substs):
 def arg_subst_str(command, subst):
     cmd = arg_subst(command, subst)
     def add(x, y): return x + ' ' + str(y)
-    return reduce(add, cmd, '')
+    return functools.reduce(add, cmd, '')
 
 class execute(object):
     """Execute commands or scripts. The 'output' is a funtion that handles the
@@ -118,7 +129,7 @@ class execute(object):
         self.timing_out = False
         self.proc = None
 
-    def _capture(self, command, proc, timeout = None):
+    def capture(self, proc, command = 'pipe', timeout = None):
         """Create 3 threads to read stdout and stderr and send to the output handler
         and call an input handler is provided. Based on the 'communicate' code
         in the subprocess module."""
@@ -127,13 +138,13 @@ class execute(object):
             block and return None or False if this thread is to exit and True if this
             is a timeout check."""
             if trace_threads:
-                print 'executte:_writethread: start'
+                print('executte:_writethread: start')
             try:
                 while True:
-                    lines = input()
+                    lines = eval(input())
                     if type(lines) == str:
                         try:
-                            fh.write(lines)
+                            fh.write(bytes(lines, sys.stdin.encoding))
                         except:
                             break
                     if lines == None or \
@@ -142,23 +153,22 @@ class execute(object):
                         break
             except:
                 if trace_threads:
-                    print 'executte:_writethread: exception'
+                    print('executte:_writethread: exception')
                 pass
             try:
                 fh.close()
             except:
                 pass
             if trace_threads:
-                print 'executte:_writethread: finished'
+                print('executte:_writethread: finished')
 
         def _readthread(exe, fh, out, prefix = ''):
             """Read from a file handle and write to the output handler
             until the file closes."""
             def _output_line(line, exe, prefix, out, count):
-                #print 'LINE:%d: %s' % (count, line)
-                exe.lock.acquire()
+                #exe.lock.acquire()
                 #exe.outputting = True
-                exe.lock.release()
+                #exe.lock.release()
                 if out:
                     out(prefix + line)
                 else:
@@ -167,7 +177,7 @@ class execute(object):
                         log.flush()
 
             if trace_threads:
-                print 'executte:_readthread: start'
+                print('executte:_readthread: start')
             count = 0
             line = ''
             try:
@@ -175,7 +185,8 @@ class execute(object):
                     data = fh.read(1)
                     if len(data) == 0:
                         break
-                    #print '))))) %02x "%s"' % (ord(data), data)
+                    if type(data) == bytes:
+                        data = data.decode(sys.stdout.encoding)
                     for c in data:
                         line += c
                         if c == '\n':
@@ -187,7 +198,7 @@ class execute(object):
             except:
                 raise
                 if trace_threads:
-                    print 'executte:_readthread: exception'
+                    print('executte:_readthread: exception')
                 pass
             try:
                 fh.close()
@@ -196,7 +207,7 @@ class execute(object):
             if len(line):
                 _output_line(line, exe, prefix, out, 100)
             if trace_threads:
-                print 'executte:_readthread: finished'
+                print('executte:_readthread: finished')
 
         def _timerthread(exe, interval, function):
             """Timer thread is used to timeout a process if no output is
@@ -305,11 +316,13 @@ class execute(object):
             s = command
             if type(command) is list:
                 def add(x, y): return x + ' ' + str(y)
-                s = reduce(add, command, '')[1:]
+                s = functools.reduce(add, command, '')[1:]
             what = 'spawn'
             if shell:
                 what = 'shell'
             log.output(what + ': ' + s)
+        if self.output is None:
+            raise error.general('capture needs an output handler')
         if shell and self.shell_exe:
             command = arg_list(command)
             command[:0] = self.shell_exe
@@ -340,12 +353,10 @@ class execute(object):
                                     stderr = stderr)
             if not capture:
                 return (0, proc)
-            if self.output is None:
-                raise error.general('capture needs an output handler')
-            exit_code = self._capture(command, proc, timeout)
+            exit_code = self.capture(proc, command, timeout)
             if self.verbose:
                 log.output('exit: ' + str(exit_code))
-        except OSError, ose:
+        except OSError as ose:
             exit_code = ose.errno
             if self.verbose:
                 log.output('exit: ' + str(ose))
@@ -395,7 +406,7 @@ class execute(object):
                             shell = shell or self.shell_commands,
                             cwd = cwd, env = env,
                             stdin = stdin, stdout = stdout, stderr = stderr,
-                            itmeout = timeout)
+                            timeout = timeout)
 
     def set_shell(self, execute):
         """Set the shell to execute when issuing a shell command."""
@@ -453,7 +464,7 @@ class execute(object):
         self.lock.acquire()
         try:
             if self.proc is not None:
-                print "sending sig"
+                print("sending sig")
                 self.proc.send_signal(signal)
         except:
             raise
@@ -502,6 +513,7 @@ class capture_execution(execute):
         raise error.general('output capture cannot be overrided')
 
 if __name__ == "__main__":
+
     def run_tests(e, commands, use_shell):
         for c in commands['shell']:
             e.shell(c)
@@ -517,13 +529,20 @@ if __name__ == "__main__":
         ec, proc = e.command(commands['pipe'][0], commands['pipe'][1],
                              capture = False, stdin = subprocess.PIPE)
         if ec == 0:
-            print 'piping input into ' + commands['pipe'][0] + ': ' + \
-                  commands['pipe'][2]
-            proc.stdin.write(commands['pipe'][2])
+            print('piping input into ' + commands['pipe'][0] + ': ' + \
+                  commands['pipe'][2])
+            try:
+                out = bytes(commands['pipe'][2], sys.stdin.encoding)
+            except:
+                out = bytes(commands['pipe'][2])
+            proc.stdin.write(out)
             proc.stdin.close()
             e.capture(proc)
             del proc
 
+    def capture_output(text):
+        print(text, end = '')
+
     cmd_shell_test = 'if "%OS%" == "Windows_NT" (echo It is WinNT) else echo Is is not WinNT'
     sh_shell_test = 'x="me"; if [ $x = "me" ]; then echo "It was me"; else "It was him"; fi'
 
@@ -544,12 +563,12 @@ if __name__ == "__main__":
                                    ('date %0 %1', ['-u', '+%d %D %S'])]
     commands['unix']['pipe'] = ('grep', 'hello', 'hello world')
 
-    print arg_list('cmd a1 a2 "a3 is a string" a4')
-    print arg_list('cmd b1 b2 "b3 is a string a4')
-    print arg_subst(['nothing', 'xx-%0-yyy', '%1', '%2-something'],
-                    ['subst0', 'subst1', 'subst2'])
+    print(arg_list('cmd a1 a2 "a3 is a string" a4'))
+    print(arg_list('cmd b1 b2 "b3 is a string a4'))
+    print(arg_subst(['nothing', 'xx-%0-yyy', '%1', '%2-something'],
+                    ['subst0', 'subst1', 'subst2']))
 
-    e = execute(error_prefix = 'ERR: ', verbose = True)
+    e = execute(error_prefix = 'ERR: ', output = capture_output, verbose = True)
     if sys.platform == "win32":
         run_tests(e, commands['windows'], False)
         if os.path.exists('c:\\msys\\1.0\\bin\\sh.exe'):
diff --git a/rtemstoolkit/freebsd.py b/rtemstoolkit/freebsd.py
index 11a827f..499d7dd 100644
--- a/rtemstoolkit/freebsd.py
+++ b/rtemstoolkit/freebsd.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -36,8 +36,16 @@
 import pprint
 import os
 
-import check
-import execute
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import check
+    from . import execute
+except (ValueError, SystemError):
+    import check
+    import execute
 
 def load():
     uname = os.uname()
diff --git a/rtemstoolkit/git.py b/rtemstoolkit/git.py
index c77347c..b89b3d8 100644
--- a/rtemstoolkit/git.py
+++ b/rtemstoolkit/git.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2015 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -29,19 +29,31 @@
 # Provide some basic access to the git command.
 #
 
+from __future__ import print_function
+
 import os
 
-import error
-import execute
-import log
-import options
-import path
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import execute
+    from . import log
+    from . import path
+except (ValueError, SystemError):
+    import error
+    import execute
+    import log
+    import path
 
 class repo:
     """An object to manage a git repo."""
 
-    def _git_exit_code(self, ec):
+    def _git_exit_code(self, ec, cmd, output):
         if ec:
+            print(output)
             raise error.general('git command failed (%s): %d' % (self.git, ec))
 
     def _run(self, args, check = False):
@@ -55,7 +67,7 @@ class repo:
         exit_code, proc, output = e.spawn(cmd, cwd = path.host(cwd))
         log.trace(output)
         if check:
-            self._git_exit_code(exit_code)
+            self._git_exit_code(exit_code, cmd, output)
         return exit_code, output
 
     def __init__(self, _path, opts = None, macros = None):
@@ -76,9 +88,11 @@ class repo:
         if len(gvs) < 3:
             raise error.general('invalid version string from git: %s' % (output))
         vs = gvs[2].split('.')
-        if len(vs) != 4:
-            raise error.general('invalid version number from git: %s' % (gvs[2]))
-        return (int(vs[0]), int(vs[1]), int(vs[2]), int(vs[3]))
+        if len(vs) == 4:
+            return (int(vs[0]), int(vs[1]), int(vs[2]), int(vs[3]))
+        if len(vs) == 3:
+            return (int(vs[0]), int(vs[1]), int(vs[2]))
+        raise error.general('invalid version number from git: %s' % (gvs[2]))
 
     def clone(self, url, _path):
         ec, output = self._run(['clone', url, path.host(_path)], check = True)
@@ -207,12 +221,19 @@ class repo:
 
 if __name__ == '__main__':
     import sys
-    opts = options.load(sys.argv)
+    import options
+    long_opts = {
+        # key              macro        handler   param  defs   init
+    }
+    opts = options.command_line(base_path = '.',
+                                argv = sys.argv,
+                                long_opts = long_opts)
+    options.load(opts)
     g = repo('.', opts)
-    print g.git_version()
-    print g.valid()
-    print g.status()
-    print g.clean()
-    print g.remotes()
-    print g.email()
-    print g.head()
+    print('version:', g.git_version())
+    print('valid:', g.valid())
+    print('status:', g.status())
+    print('dirty:', g.dirty())
+    print('remotes:', g.remotes())
+    print('email:', g.email())
+    print('head:', g.head())
diff --git a/rtemstoolkit/linux.py b/rtemstoolkit/linux.py
index 022bcd0..d011f67 100644
--- a/rtemstoolkit/linux.py
+++ b/rtemstoolkit/linux.py
@@ -35,10 +35,18 @@
 
 import pprint
 import os
-
 import platform
-import execute
-import path
+
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import execute
+    from . import path
+except (ValueError, SystemError):
+    import execute
+    import path
 
 def load():
     uname = os.uname()
@@ -130,7 +138,7 @@ def load():
                      '__chown':        ('exe',     'required', '/usr/sbin/chown') },
         }
 
-    if variations.has_key(distro):
+    if variations in distro:
         for v in variations[distro]:
             if path.exists(variations[distro][v][2]):
                 defines[v] = variations[distro][v]
diff --git a/rtemstoolkit/log.py b/rtemstoolkit/log.py
index 92d3ed2..5f1e385 100755
--- a/rtemstoolkit/log.py
+++ b/rtemstoolkit/log.py
@@ -32,11 +32,20 @@
 # Log output to stdout and/or a file.
 #
 
+from __future__ import print_function
+
 import os
 import sys
 import threading
 
-import error
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+except (ValueError, SystemError):
+    import error
 
 #
 # A global log.
@@ -74,13 +83,13 @@ def _output(text = os.linesep, log = None):
     else:
         lock.acquire()
         for l in text.replace(chr(13), '').splitlines():
-            print l
+            print(l)
         lock.release()
 
 def stderr(text = os.linesep, log = None):
     lock.acquire()
     for l in text.replace(chr(13), '').splitlines():
-        print >> sys.stderr, l
+        print(l, file = sys.stderr)
     lock.release()
 
 def output(text = os.linesep, log = None):
@@ -92,7 +101,7 @@ def notice(text = os.linesep, log = None, stdout_only = False):
             (default is not None and not default.has_stdout() or stdout_only):
         lock.acquire()
         for l in text.replace(chr(13), '').splitlines():
-            print l
+            print(l)
         lock.release()
     if not stdout_only:
         _output(text, log)
@@ -126,8 +135,8 @@ class log:
                     self.fhs[1] = sys.stderr
                 else:
                     try:
-                        self.fhs.append(file(s, 'w'))
-                    except IOError, ioe:
+                        self.fhs.append(open(s, 'w'))
+                    except IOError as ioe:
                          raise error.general("creating log file '" + s + \
                                              "': " + str(ioe))
 
@@ -186,41 +195,41 @@ if __name__ == "__main__":
     l.output('log: hello world CRLF\r\n')
     l.output('log: hello world NONE')
     l.flush()
-    print '=-' * 40
-    print 'tail: %d' % (len(l.tail))
-    print l
-    print '=-' * 40
+    print('=-' * 40)
+    print('tail: %d' % (len(l.tail)))
+    print(l)
+    print('=-' * 40)
     for i in range(0, 10):
         l.output('log: hello world 2: %d\n' % (i))
     l.flush()
-    print '=-' * 40
-    print 'tail: %d' % (len(l.tail))
-    print l
-    print '=-' * 40
+    print('=-' * 40)
+    print('tail: %d' % (len(l.tail)))
+    print(l)
+    print('=-' * 40)
     for i in [0, 1]:
         quiet = False
         tracing = False
-        print '- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30)
+        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
         trace('trace with quiet and trace off')
         notice('notice with quiet and trace off')
         quiet = True
         tracing = False
-        print '- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30)
+        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
         trace('trace with quiet on and trace off')
         notice('notice with quiet on and trace off')
         quiet = False
         tracing = True
-        print '- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30)
+        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
         trace('trace with quiet off and trace on')
         notice('notice with quiet off and trace on')
         quiet = True
         tracing = True
-        print '- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30)
+        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
         trace('trace with quiet on and trace on')
         notice('notice with quiet on and trace on')
         default = l
-    print '=-' * 40
-    print 'tail: %d' % (len(l.tail))
-    print l
-    print '=-' * 40
+    print('=-' * 40)
+    print('tail: %d' % (len(l.tail)))
+    print(l)
+    print('=-' * 40)
     del l
diff --git a/rtemstoolkit/macros.py b/rtemstoolkit/macros.py
index 8db0729..c9410ae 100644
--- a/rtemstoolkit/macros.py
+++ b/rtemstoolkit/macros.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,14 +32,24 @@
 # Macro tables.
 #
 
+from __future__ import print_function
+
 import copy
 import inspect
 import re
 import os
 import string
 
-import error
-import path
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import path
+except (ValueError, SystemError):
+    import error
+    import path
 
 #
 # Macro tables
@@ -54,7 +64,7 @@ class macros:
         def __iter__(self):
             return self
 
-        def next(self):
+        def __next__(self):
             if self.index < len(self.keys):
                 key = self.keys[self.index]
                 self.index += 1
@@ -64,6 +74,19 @@ class macros:
         def iterkeys(self):
             return self.keys
 
+    def _unicode_to_str(self, us):
+        try:
+            if type(us) == unicode:
+                return us.encode('ascii', 'replace')
+        except:
+            pass
+        try:
+            if type(us) == bytes:
+                return us.encode('ascii', 'replace')
+        except:
+            pass
+        return us
+
     def __init__(self, name = None, original = None, rtdir = '.'):
         self.files = []
         self.macro_filter = re.compile(r'%{[^}]+}')
@@ -156,7 +179,7 @@ class macros:
         return text
 
     def __iter__(self):
-        return macros.macro_iterator(self.keys())
+        return macros.macro_iterator(list(self.keys()))
 
     def __getitem__(self, key):
         macro = self.get(key)
@@ -167,12 +190,17 @@ class macros:
     def __setitem__(self, key, value):
         if type(key) is not str:
             raise TypeError('bad key type (want str): %s' % (type(key)))
+        if type(value) is not tuple:
+            value = self._unicode_to_str(value)
         if type(value) is str:
             value = ('none', 'none', value)
         if type(value) is not tuple:
             raise TypeError('bad value type (want tuple): %s' % (type(value)))
         if len(value) != 3:
             raise TypeError('bad value tuple (len not 3): %d' % (len(value)))
+        value = (self._unicode_to_str(value[0]),
+                 self._unicode_to_str(value[1]),
+                 self._unicode_to_str(value[2]))
         if type(value[0]) is not str:
             raise TypeError('bad value tuple type field: %s' % (type(value[0])))
         if type(value[1]) is not str:
@@ -195,10 +223,10 @@ class macros:
         return self.has_key(key)
 
     def __len__(self):
-        return len(self.keys())
+        return len(list(self.keys()))
 
     def keys(self):
-        keys = self.macros['global'].keys()
+        keys = list(self.macros['global'].keys())
         for rm in self.get_read_maps():
             for mk in self.macros[rm]:
                 if self.macros[rm][mk][1] == 'undefine':
@@ -211,12 +239,12 @@ class macros:
     def has_key(self, key):
         if type(key) is not str:
             raise TypeError('bad key type (want str): %s' % (type(key)))
-        if self.key_filter(key) not in self.keys():
+        if self.key_filter(key) not in list(self.keys()):
             return False
         return True
 
     def maps(self):
-        return self.macros.keys()
+        return list(self.macros.keys())
 
     def get_read_maps(self):
         return [rm[5:] for rm in self.read_maps]
@@ -239,7 +267,7 @@ class macros:
 
         trace_me = False
         if trace_me:
-            print '[[[[]]]] parsing macros'
+            print('[[[[]]]] parsing macros')
         orig_macros = copy.copy(self.macros)
         map = 'global'
         lc = 0
@@ -254,8 +282,8 @@ class macros:
             l_remaining = l
             for c in l:
                 if trace_me:
-                    print ']]]]]]]] c:%s(%d) s:%s t:"%s" m:%r M:%s' % \
-                        (c, ord(c), state, token, macro, map)
+                    print(']]]]]]]] c:%s(%d) s:%s t:"%s" m:%r M:%s' % \
+                        (c, ord(c), state, token, macro, map))
                 l_remaining = l_remaining[1:]
                 if c is '#' and not state.startswith('value'):
                     break
@@ -378,7 +406,7 @@ class macros:
                     mc.close()
                     self.files += [n]
                     return
-                except IOError, err:
+                except IOError as err:
                     pass
         raise error.general('opening macro file: %s' % \
                                 (path.host(self.expand(name))))
@@ -452,7 +480,7 @@ class macros:
     def find(self, regex):
         what = re.compile(regex)
         keys = []
-        for key in self.keys():
+        for key in list(self.keys()):
             if what.match(key):
                 keys += [key]
         return keys
@@ -490,23 +518,23 @@ class macros:
 if __name__ == "__main__":
     import copy
     import sys
-    print inspect.getfile(macros)
-    m = macros(name = 'defaults.mc')
+    print(inspect.getfile(macros))
+    m = macros()
     d = copy.copy(m)
     m['test1'] = 'something'
-    if d.has_key('test1'):
-        print 'error: copy failed.'
+    if 'test1' in d:
+        print('error: copy failed.')
         sys.exit(1)
     m.parse("[test]\n" \
             "test1: none, undefine, ''\n" \
             "name:  none, override, 'pink'\n")
-    print 'set test:', m.set_read_map('test')
+    print('set test:', m.set_read_map('test'))
     if m['name'] != 'pink':
-        print 'error: override failed. name is %s' % (m['name'])
+        print('error: override failed. name is %s' % (m['name']))
         sys.exit(1)
-    if m.has_key('test1'):
-        print 'error: map undefine failed.'
+    if 'test1' in m:
+        print('error: map undefine failed.')
         sys.exit(1)
-    print 'unset test:', m.unset_read_map('test')
-    print m
-    print m.keys()
+    print('unset test:', m.unset_read_map('test'))
+    print(m)
+    print(list(m.keys()))
diff --git a/rtemstoolkit/mailer.py b/rtemstoolkit/mailer.py
index df42580..abb7106 100644
--- a/rtemstoolkit/mailer.py
+++ b/rtemstoolkit/mailer.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,13 +32,24 @@
 # Manage emailing results or reports.
 #
 
+from __future__ import print_function
+
 import os
 import smtplib
 import socket
 
-import error
-import options
-import path
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import options
+    from . import path
+except (ValueError, SystemError):
+    import error
+    import options
+    import path
 
 def append_options(opts):
     opts['--mail'] = 'Send email report or results.'
@@ -75,7 +86,7 @@ class mail:
                 mrc = open(mailrc, 'r')
                 lines = mrc.readlines()
                 mrc.close()
-            except IOError, err:
+            except IOError as err:
                 raise error.general('error reading: %s' % (mailrc))
             for l in lines:
                 l = _clean(l)
@@ -104,17 +115,17 @@ class mail:
         try:
             s = smtplib.SMTP(self.smtp_host())
             s.sendmail(from_addr, [to_addr], msg)
-        except smtplib.SMTPException, se:
+        except smtplib.SMTPException as se:
             raise error.general('sending mail: %s' % (str(se)))
-        except socket.error, se:
+        except socket.error as se:
             raise error.general('sending mail: %s' % (str(se)))
 
 if __name__ == '__main__':
     import sys
     optargs = {}
     append_options(optargs)
-    opts = options.load(sys.argv, optargs = optargs, defaults = 'defaults.mc')
+    opts = options.load(sys.argv)
     m = mail(opts)
-    print 'From: %s' % (m.from_address())
-    print 'SMTP Host: %s' % (m.smtp_host())
+    print('From: %s' % (m.from_address()))
+    print('SMTP Host: %s' % (m.smtp_host()))
     m.send(m.from_address(), 'Test mailer.py', 'This is a test')
diff --git a/rtemstoolkit/netbsd.py b/rtemstoolkit/netbsd.py
new file mode 100644
index 0000000..5883682
--- /dev/null
+++ b/rtemstoolkit/netbsd.py
@@ -0,0 +1,96 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# RTEMS Tools 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 3 of the License, or
+# (at your option) any later version.
+#
+# RTEMS Tools 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 RTEMS Tools.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# This code is based on what ever doco about spec files I could find and
+# RTEMS project's spec files.
+#
+
+import pprint
+import os
+
+try:
+    from . import check
+    from . import execute
+except (ValueError, SystemError):
+    import check
+    import execute
+
+def load():
+    uname = os.uname()
+    sysctl = '/sbin/sysctl '
+    e = execute.capture_execution()
+    exit_code, proc, output = e.shell(sysctl + 'hw.ncpu')
+    if exit_code == 0:
+        ncpus = output.split(' ')[1].strip()
+    else:
+        ncpus = '1'
+    if uname[4] == 'amd64':
+        cpu = 'x86_64'
+    else:
+        cpu = uname[4]
+    version = uname[2]
+    if version.find('-') > 0:
+        version = version.split('-')[0]
+    defines = {
+        '_ncpus':            ('none',    'none',    '1'),
+        '_os':               ('none',    'none',     'netbsd'),
+        '_host':             ('triplet', 'required', cpu + '-netbsd' + version),
+        '_host_vendor':      ('none',    'none',     'pc'),
+        '_host_os':          ('none',    'none',     'netbsd'),
+        '_host_os_version':  ('none',    'none',     version),
+        '_host_cpu':         ('none',    'none',     cpu),
+        '_host_alias':       ('none',    'none',     '%{nil}'),
+        '_host_arch':        ('none',    'none',     cpu),
+        '_usr':              ('dir',     'required', '/usr'),
+        '_var':              ('dir',     'optional', '/var'),
+        'optincludes_build': ('none',    'none',     '-I/usr/pkg/include -L/usr/pkg/lib'),
+        '__bash':            ('exe',     'optional', '/usr/pkg/bin/bash'),
+        '__bison':           ('exe',     'required', '/usr/pkg/bin/bison'),
+        '__git':             ('exe',     'required', '/usr/pkg/bin/git'),
+        '__svn':             ('exe',     'required', '/usr/pkg/bin/svn'),
+        '__xz':              ('exe',     'optional', '/usr/pkg/bin/xz'),
+        '__make':            ('exe',     'required', 'gmake'),
+        '__patch_opts':      ('none',     'none',    '-E')
+        }
+
+    defines['_build']        = defines['_host']
+    defines['_build_vendor'] = defines['_host_vendor']
+    defines['_build_os']     = defines['_host_os']
+    defines['_build_cpu']    = defines['_host_cpu']
+    defines['_build_alias']  = defines['_host_alias']
+    defines['_build_arch']   = defines['_host_arch']
+
+    for gv in ['47', '48', '49']:
+        gcc = '%s-portbld-netbsd%s-gcc%s' % (cpu, version, gv)
+        if check.check_exe(gcc, gcc):
+            defines['__cc'] = gcc
+            break
+    for gv in ['47', '48', '49']:
+        gxx = '%s-portbld-netbsd%s-g++%s' % (cpu, version, gv)
+        if check.check_exe(gxx, gxx):
+            defines['__cxx'] = gxx
+            break
+
+    return defines
+
+if __name__ == '__main__':
+    pprint.pprint(load())
diff --git a/rtemstoolkit/options.py b/rtemstoolkit/options.py
index 657921d..d0e4c81 100644
--- a/rtemstoolkit/options.py
+++ b/rtemstoolkit/options.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,22 +32,36 @@
 # Determine the defaults and load the specific file.
 #
 
+from __future__ import print_function
+
 import copy
 import glob
 import pprint
 import re
 import os
 import string
-
-import error
-import execute
-import git
-import log
-import macros
-import path
 import sys
 
-import version
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import execute
+    from . import git
+    from . import log
+    from . import macros
+    from . import path
+    from . import version
+except (ValueError, SystemError):
+    import error
+    import execute
+    import git
+    import log
+    import macros
+    import path
+    import version
 
 basepath = 'tb'
 
@@ -61,7 +75,7 @@ class command_line(object):
 
     def __init__(self, base_path = None, argv = None, optargs = None,
                  defaults = None, long_opts = None, long_opts_help = None,
-                 command_path = None, log_default = None):
+                 command_path = '', log_default = None):
 
         if argv is None:
             return
@@ -77,6 +91,9 @@ class command_line(object):
             raise error.general('log default is a list')
         self.log_default = log_default
 
+        if defaults is None:
+            defaults = macros.macros()
+
         self.long_opts = {
             # key                 macro                handler            param  defs       init
             '--jobs'           : ('_jobs',             self._lo_jobs,     True,  'default', True),
@@ -128,7 +145,7 @@ class command_line(object):
             elif long_opts[lo][1] == 'string':
                 handler = self._lo_string
             elif long_opts[lo][1] == 'path':
-                hanlder = self._lo_path
+                handler = self._lo_path
             elif long_opts[lo][1] == 'jobs':
                 handler = self._lo_jobs
             elif long_opts[lo][1] == 'bool':
@@ -139,9 +156,10 @@ class command_line(object):
                 raise error.general('invalid option handler: %s: %s' % (lo, long_opts[lo][1]))
             self.long_opts[lo] = (long_opts[lo][0], handler, long_opts[lo][2],
                                    long_opts[lo][3], long_opts[lo][4])
-            if lo not in long_opts_help:
-                raise error.general('no help for option: %s' % (lo))
-            self.long_opts_help[lo] = long_opts_help[lo]
+            if long_opts_help is not None:
+                if lo not in long_opts_help:
+                    raise error.general('no help for option: %s' % (lo))
+                self.long_opts_help[lo] = long_opts_help[lo]
 
     def __copy__(self):
         new = type(self)()
@@ -159,7 +177,7 @@ class command_line(object):
     def __str__(self):
         def _dict(dd):
             s = ''
-            ddl = dd.keys()
+            ddl = list(dd.keys())
             ddl.sort()
             for d in ddl:
                 s += '  ' + d + ': ' + str(dd[d]) + '\n'
@@ -273,12 +291,12 @@ class command_line(object):
         return indent
 
     def help(self):
-        print '%s: [options] [args]' % (self.command_name)
-        print 'RTEMS Tools Project (c) 2012-2014 Chris Johns'
-        print 'Options and arguments:'
-        opts = self.long_opts_help.keys()
+        print('%s: [options] [args]' % (self.command_name))
+        print('RTEMS Tools Project (c) 2012-2014 Chris Johns')
+        print('Options and arguments:')
+        opts = list(self.long_opts_help.keys())
         if self.optargs:
-            opts += self.optargs.keys()
+            opts += list(self.optargs.keys())
         indent = self._help_indent()
         for o in sorted(opts):
             if o in self.long_opts_help:
@@ -287,7 +305,7 @@ class command_line(object):
                 h = self.optargs[o]
             else:
                 raise error.general('invalid help data: %s' %(o))
-            print '%-*s : %s' % (indent, o, h)
+            print('%-*s : %s' % (indent, o, h))
         raise error.exit()
 
     def process(self):
@@ -518,6 +536,9 @@ def load(opts):
     command line.
     """
 
+    if not isinstance(opts, command_line):
+        raise error.general('invalid opt type')
+
     global host_windows
 
     overrides = None
@@ -532,20 +553,40 @@ def load(opts):
         uname = os.uname()
         try:
             if uname[0].startswith('CYGWIN_NT'):
-                import windows
+                try:
+                    from . import windows
+                except:
+                    import windows
                 overrides = windows.load()
             elif uname[0] == 'Darwin':
-                import darwin
+                try:
+                    from . import darwin
+                except:
+                    import darwin
                 overrides = darwin.load()
             elif uname[0] == 'FreeBSD':
-                import freebsd
+                try:
+                    from . import freebsd
+                except:
+                    import freebsd
                 overrides = freebsd.load()
             elif uname[0] == 'NetBSD':
-                import netbsd
+                try:
+                    from . import netbsd
+                except:
+                    import netbsd
                 overrides = netbsd.load()
             elif uname[0] == 'Linux':
-                import linux
-                overrides = linux.load()
+                try:
+                    from . import linux
+                except:
+                    import linux
+            elif uname[0] == 'SunOS':
+                try:
+                    from . import solaris
+                except:
+                    import solaris
+                overrides = solaris.load()
         except:
             raise error.general('failed to load %s host support' % (uname[0]))
     else:
@@ -580,13 +621,13 @@ def run(args):
         log.notice(str(opts))
         log.notice('Defaults:')
         log.notice(str(opts.defaults))
-    except error.general, gerr:
-        print gerr
+    except error.general as gerr:
+        print(gerr)
         sys.exit(1)
-    except error.internal, ierr:
-        print ierr
+    except error.internal as ierr:
+        print(ierr)
         sys.exit(1)
-    except error.exit, eerr:
+    except error.exit as eerr:
         pass
     except KeyboardInterrupt:
         _notice(opts, 'abort: user terminated')
diff --git a/rtemstoolkit/path.py b/rtemstoolkit/path.py
index 238e6d9..2e235b3 100644
--- a/rtemstoolkit/path.py
+++ b/rtemstoolkit/path.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -34,13 +34,23 @@
 # level. This allows macro expansion to work.
 #
 
+from __future__ import print_function
+
 import glob
-import log
 import os
 import shutil
 import string
 
-import error
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import log
+except (ValueError, SystemError):
+    import error
+    import log
 
 windows = os.name == 'nt'
 
@@ -122,24 +132,24 @@ def mkdir(path):
         if windows:
             try:
                 os.makedirs(host(path))
-            except IOError, err:
+            except IOError as err:
                 raise error.general('cannot make directory: %s' % (path))
-            except OSError, err:
+            except OSError as err:
                 raise error.general('cannot make directory: %s' % (path))
-            except WindowsError, err:
+            except WindowsError as err:
                 raise error.general('cannot make directory: %s' % (path))
         else:
             try:
                 os.makedirs(host(path))
-            except IOError, err:
+            except IOError as err:
                 raise error.general('cannot make directory: %s' % (path))
-            except OSError, err:
+            except OSError as err:
                 raise error.general('cannot make directory: %s' % (path))
 
 def removeall(path):
 
     def _onerror(function, path, excinfo):
-        print 'removeall error: (%s) %s' % (excinfo, path)
+        print('removeall error: (%s) %s' % (excinfo, path))
 
     path = host(path)
     shutil.rmtree(path, onerror = _onerror)
@@ -208,13 +218,13 @@ def copy_tree(src, dst):
                 copy_tree(srcname, dstname)
             else:
                 shutil.copy2(srcname, dstname)
-        except shutil.Error, err:
+        except shutil.Error as err:
             raise error.general('copying tree: %s -> %s: %s' % (src, dst, str(err)))
-        except EnvironmentError, why:
+        except EnvironmentError as why:
             raise error.general('copying tree: %s -> %s: %s' % (srcname, dstname, str(why)))
     try:
         shutil.copystat(src, dst)
-    except OSError, why:
+    except OSError as why:
         ok = False
         if windows:
             if WindowsError is not None and isinstance(why, WindowsError):
@@ -223,17 +233,17 @@ def copy_tree(src, dst):
             raise error.general('copying tree: %s -> %s: %s' % (src, dst, str(why)))
 
 if __name__ == '__main__':
-    print host('/a/b/c/d-e-f')
-    print host('//a/b//c/d-e-f')
-    print shell('/w/x/y/z')
-    print basename('/as/sd/df/fg/me.txt')
-    print dirname('/as/sd/df/fg/me.txt')
-    print join('/d', 'g', '/tyty/fgfg')
+    print(host('/a/b/c/d-e-f'))
+    print(host('//a/b//c/d-e-f'))
+    print(shell('/w/x/y/z'))
+    print(basename('/as/sd/df/fg/me.txt'))
+    print(dirname('/as/sd/df/fg/me.txt'))
+    print(join('/d', 'g', '/tyty/fgfg'))
     windows = True
-    print host('/a/b/c/d-e-f')
-    print host('//a/b//c/d-e-f')
-    print shell('/w/x/y/z')
-    print shell('w:/x/y/z')
-    print basename('x:/sd/df/fg/me.txt')
-    print dirname('x:/sd/df/fg/me.txt')
-    print join('s:/d/', '/g', '/tyty/fgfg')
+    print(host('/a/b/c/d-e-f'))
+    print(host('//a/b//c/d-e-f'))
+    print(shell('/w/x/y/z'))
+    print(shell('w:/x/y/z'))
+    print(basename('x:/sd/df/fg/me.txt'))
+    print(dirname('x:/sd/df/fg/me.txt'))
+    print(join('s:/d/', '/g', '/tyty/fgfg'))
diff --git a/rtemstoolkit/solaris.py b/rtemstoolkit/solaris.py
new file mode 100644
index 0000000..397df68
--- /dev/null
+++ b/rtemstoolkit/solaris.py
@@ -0,0 +1,90 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# This code is based on what ever doco about spec files I could find and
+# RTEMS project's spec files.
+#
+
+import pprint
+import os
+
+try:
+    from . import check
+    from . import error
+    from . import execute
+except (ValueError, SystemError):
+    import check
+    import error
+    import execute
+
+def load():
+    uname = os.uname()
+    psrinfo = '/sbin/psrinfo|wc -l'
+    e = execute.capture_execution()
+    exit_code, proc, output = e.shell(psrinfo)
+    if exit_code == 0:
+        ncpus = output
+    else:
+        ncpus = '1'
+    if uname[4] == 'i86pc':
+        cpu = 'i386'
+    else:
+        cpu = uname[4]
+    version = uname[2]
+    if version.find('-') > 0:
+        version = version.split('-')[0]
+    defines = {
+        '_ncpus':           ('none',    'none',     ncpus),
+        '_os':              ('none',    'none',     'solaris'),
+        '_host':            ('triplet', 'required', cpu + '-pc-solaris2'),
+        '_host_vendor':     ('none',    'none',     'pc'),
+        '_host_os':         ('none',    'none',     'solaris'),
+        '_host_os_version': ('none',    'none',     version),
+        '_host_cpu':        ('none',    'none',     cpu),
+        '_host_alias':      ('none',    'none',     '%{nil}'),
+        '_host_arch':       ('none',    'none',     cpu),
+        '_usr':             ('dir',     'required', '/usr'),
+        '_var':             ('dir',     'optional', '/var'),
+        '__bash':           ('exe',     'optional', '/usr/bin/bash'),
+        '__bison':          ('exe',     'required', '/usr/bin/bison'),
+        '__git':            ('exe',     'required', '/usr/bin/git'),
+        '__svn':            ('exe',     'required', '/usr/bin/svn'),
+        '__cvs':            ('exe',     'required', '/usr/bin/cvs'),
+        '__xz':             ('exe',     'optional', '/usr/bin/xz'),
+        '__make':           ('exe',     'required', 'gmake'),
+        '__patch_opts':     ('none',     'none',    '-E'),
+        '__chown':          ('exe',     'required', '/usr/bin/chown'),
+        '__install':        ('exe',     'required', '/usr/bin/ginstall'),
+        '__cc':             ('exe',     'required', '/usr/bin/gcc'),
+        '__cxx':            ('exe',     'required', '/usr/bin/g++'),
+        'with_iconv':       ('none',    'none',     '0')
+        }
+
+    defines['_build']        = defines['_host']
+    defines['_build_vendor'] = defines['_host_vendor']
+    defines['_build_os']     = defines['_host_os']
+    defines['_build_cpu']    = defines['_host_cpu']
+    defines['_build_alias']  = defines['_host_alias']
+    defines['_build_arch']   = defines['_host_arch']
+
+    return defines
+
+if __name__ == '__main__':
+    pprint.pprint(load())
diff --git a/rtemstoolkit/stacktraces.py b/rtemstoolkit/stacktraces.py
index e589618..dc1dbad 100644
--- a/rtemstoolkit/stacktraces.py
+++ b/rtemstoolkit/stacktraces.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -33,11 +33,10 @@ import traceback
 
 def trace():
     code = []
-    for threadId, stack in sys._current_frames().items():
+    for threadId, stack in list(sys._current_frames().items()):
         code.append("\n# thread-id: %s" % threadId)
         for filename, lineno, name, line in traceback.extract_stack(stack):
             code.append('file: "%s", line %d, in %s' % (filename, lineno, name))
             if line:
                 code.append("  %s" % (line.strip()))
     return '\n'.join(code)
-
diff --git a/rtemstoolkit/version.py b/rtemstoolkit/version.py
index 26ac655..6d00fb3 100644
--- a/rtemstoolkit/version.py
+++ b/rtemstoolkit/version.py
@@ -33,11 +33,22 @@
 # file to the top directory.
 #
 
+from __future__ import print_function
+
 import sys
 
-import error
-import git
-import path
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import git
+    from . import path
+except (ValueError, SystemError):
+    import error
+    import git
+    import path
 
 #
 # Default to an internal string.
@@ -94,4 +105,4 @@ def str():
     return _version_str
 
 if __name__ == '__main__':
-    print 'Version: %s' % (str())
+    print('Version: %s' % (str()))
diff --git a/rtemstoolkit/windows.py b/rtemstoolkit/windows.py
index be4e1f6..f8007d8 100644
--- a/rtemstoolkit/windows.py
+++ b/rtemstoolkit/windows.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,17 +32,25 @@
 # Windows specific support and overrides.
 #
 
-import error
 import pprint
 import os
 
-import execute
+#
+# Support to handle use in a package and as a unit test.
+# If there is a better way to let us know.
+#
+try:
+    from . import error
+    from . import execute
+except (ValueError, SystemError):
+    import error
+    import execute
 
 def load():
     # Default to the native Windows Python.
     uname = 'win32'
     system = 'mingw32'
-    if os.environ.has_key('HOSTTYPE'):
+    if 'HOSTTYPE' in os.environ:
         hosttype = os.environ['HOSTTYPE']
     else:
         hosttype = 'i686'
@@ -68,7 +76,7 @@ def load():
         except:
             pass
 
-    if os.environ.has_key('NUMBER_OF_PROCESSORS'):
+    if 'NUMBER_OF_PROCESSORS' in os.environ:
         ncpus = os.environ['NUMBER_OF_PROCESSORS']
     else:
         ncpus = '1'
diff --git a/tester/rt/config.py b/tester/rt/config.py
index ac9c8aa..1662f52 100644
--- a/tester/rt/config.py
+++ b/tester/rt/config.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,6 +32,8 @@
 # RTEMS Testing Config
 #
 
+from __future__ import print_function
+
 import datetime
 import os
 import threading
@@ -42,8 +44,8 @@ from rtemstoolkit import execute
 from rtemstoolkit import log
 from rtemstoolkit import path
 
-import console
-import gdb
+from . import console
+from . import gdb
 
 timeout = 15
 
@@ -185,7 +187,7 @@ class file(config.file):
     def _realtime_trace(self, text):
         if self.realtime_trace:
             for l in text:
-                print ' '.join(l)
+                print(' '.join(l))
 
     def run(self):
         self.load(self.name)
diff --git a/tester/rt/console.py b/tester/rt/console.py
index 74ec3bf..c473ad2 100644
--- a/tester/rt/console.py
+++ b/tester/rt/console.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,13 +32,15 @@
 # RTEMS Testing Consoles
 #
 
+from __future__ import print_function
+
 import errno
 import fcntl
 import os
 import threading
 import time
 
-import stty
+from . import stty
 
 def save():
     return stty.save()
@@ -90,7 +92,7 @@ class tty(console):
     def __del__(self):
         super(tty, self).__del__()
         if self._tracing():
-            print ':: tty close', self.dev
+            print(':: tty close', self.dev)
         fcntl.fcntl(me.tty.fd, fcntl.F_SETFL,
                     fcntl.fcntl(me.tty.fd, fcntl.F_GETFL) & ~os.O_NONBLOCK)
         self.close()
@@ -98,7 +100,7 @@ class tty(console):
     def open(self):
         def _readthread(me, x):
             if self._tracing():
-                print ':: tty runner started', self.dev
+                print(':: tty runner started', self.dev)
             fcntl.fcntl(me.tty.fd, fcntl.F_SETFL,
                         fcntl.fcntl(me.tty.fd, fcntl.F_GETFL) | os.O_NONBLOCK)
             line = ''
@@ -106,7 +108,7 @@ class tty(console):
                 time.sleep(0.05)
                 try:
                     data = me.tty.fd.read()
-                except IOError, ioe:
+                except IOError as ioe:
                     if ioe.errno == errno.EAGAIN:
                         continue
                     raise
@@ -121,9 +123,9 @@ class tty(console):
                         me.output(line)
                         line = ''
             if self._tracing():
-                print ':: tty runner finished', self.dev
+                print(':: tty runner finished', self.dev)
         if self._tracing():
-            print ':: tty open', self.dev
+            print(':: tty open', self.dev)
         self.tty = stty.tty(self.dev)
         self.tty.set(self.setup)
         self.tty.on()
diff --git a/tester/rt/gdb.py b/tester/rt/gdb.py
index 956b395..c054422 100644
--- a/tester/rt/gdb.py
+++ b/tester/rt/gdb.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,19 +32,26 @@
 # RTEMS Testing GDB Interface
 #
 
+from __future__ import print_function
+
 import os
-import Queue
 import sys
 import termios
 import threading
 
+try:
+    import queue
+except ImportError:
+    import Queue
+    queue = Queue
+
 from rtemstoolkit import error
 from rtemstoolkit import execute
 from rtemstoolkit import options
 from rtemstoolkit import path
 
-import console
-import pygdb
+from . import console
+from . import pygdb
 
 #
 # The MI parser needs a global lock. It has global objects.
@@ -65,8 +72,8 @@ class gdb(object):
         self.bsp_arch = bsp_arch
         self.output = None
         self.gdb_console = None
-        self.input = Queue.Queue()
-        self.commands = Queue.Queue()
+        self.input = queue.Queue()
+        self.commands = queue.Queue()
         self.process = None
         self.state = {}
         self.running = False
@@ -77,12 +84,12 @@ class gdb(object):
 
     def _lock(self, msg):
         if self.lock_trace:
-            print '|[   LOCK:%s ]|' % (msg)
+            print('|[   LOCK:%s ]|' % (msg))
         self.lock.acquire()
 
     def _unlock(self, msg):
         if self.lock_trace:
-            print '|] UNLOCK:%s [|' % (msg)
+            print('|] UNLOCK:%s [|' % (msg))
         self.lock.release()
 
     def _mi_lock(self):
@@ -93,7 +100,7 @@ class gdb(object):
 
     def _put(self, text):
         if self.trace:
-            print ')))', text
+            print(')))', text)
         self.commands.put(text)
 
     def _input_commands(self):
@@ -101,11 +108,11 @@ class gdb(object):
             return False
         try:
             if self.trace:
-                print '... input empty ', self.input.empty()
+                print('... input empty ', self.input.empty())
             if self.input.empty():
                 line = self.commands.get(block = False)
                 if self.trace:
-                    print '+++', line
+                    print('+++', line)
                 self.input.put(line)
         except:
             pass
@@ -114,12 +121,12 @@ class gdb(object):
     def _reader(self, line):
         self._lock('_reader')
         if self.trace:
-            print '<<<', line
+            print('<<<', line)
         try:
             self.lc += 1
             if line.startswith('(gdb)'):
                 if self.trace:
-                    print '^^^ (gdb)'
+                    print('^^^ (gdb)')
                 if not self._input_commands():
                     self.gdb_expect()
                     self._input_commands()
@@ -139,18 +146,18 @@ class gdb(object):
                     self._unlock('_open')
                 line = self.input.get(timeout = 0.5)
                 if self.trace:
-                    print '>>> input: queue=%d' % (self.input.qsize()), line
-            except Queue.Empty:
+                    print('>>> input: queue=%d' % (self.input.qsize()), line)
+            except queue.Empty:
                 return True
             if line is None:
                 return None
             return line + os.linesep
         except:
             if self.trace:
-                print 'writer exception'
+                print('writer exception')
             pass
         if self.trace:
-            print 'writer closing'
+            print('writer closing')
         return False
 
     def _timeout(self):
@@ -207,7 +214,7 @@ class gdb(object):
             self.gdb_console('gdb: %s' % (' '.join(cmds)))
             ec, proc = self.process.open(cmds, timeout = (timeout, self._timeout))
             if self.trace:
-                print 'gdb done', ec
+                print('gdb done', ec)
             if ec > 0:
                 raise error.general('gdb exec: %s: %s' % (cmds[0], os.strerror(ec)))
         except:
@@ -220,7 +227,7 @@ class gdb(object):
 
     def gdb_expect(self):
         if self.trace:
-            print '}}} gdb-expect'
+            print('}}} gdb-expect')
         if self.process and not self.running and self.script is not None:
             if self.script_line == len(self.script):
                 self._put(None)
@@ -239,12 +246,12 @@ class gdb(object):
             self._mi_lock()
             try:
                 if self.mi_trace:
-                    print 'mi-data:', lines
+                    print('mi-data:', lines)
                 rec = pygdb.mi_parser.process(lines)
             finally:
                 self._mi_unlock()
             if self.mi_trace:
-                print 'mi-rec:', rec
+                print('mi-rec:', rec)
             if rec.record_type == 'result':
                 if rec.type == 'result':
                     if rec.class_ == 'error':
@@ -256,12 +263,12 @@ class gdb(object):
                 elif rec.type == 'exec':
                     if rec.class_ == 'running':
                         if self.trace:
-                            print '*** running'
+                            print('*** running')
                         self._put('')
                         self.running = True
                     elif rec.class_ == 'stopped':
                         if self.trace:
-                            print '*** stopped'
+                            print('*** stopped')
                         self.running = False
                         #self._put('-data-list-register-values')
                 elif rec.type == 'breakpoint':
@@ -284,13 +291,13 @@ class gdb(object):
                     if last_lf >= 0:
                         lines = self.output_buffer[:last_lf]
                         if self.trace:
-                            print '/// console output'
+                            print('/// console output')
                         for line in lines.splitlines():
                             self.output(line)
                         self.output_buffer = self.output_buffer[last_lf + 1:]
         except:
             if self.trace:
-                print '/// console output'
+                print('/// console output')
             for line in lines.splitlines():
                 self.output(line)
 
@@ -298,9 +305,9 @@ if __name__ == "__main__":
     stdtty = console.save()
     try:
         def output(text):
-            print ']', text
+            print(']', text)
         def gdb_console(text):
-            print '>', text
+            print('>', text)
         script = ['target sim']
         if len(sys.argv) > 1:
             executable = sys.argv[1]
diff --git a/tester/rt/options.py b/tester/rt/options.py
index a916cbb..3b1adef 100644
--- a/tester/rt/options.py
+++ b/tester/rt/options.py
@@ -32,6 +32,8 @@
 # Determine the defaults and load the specific file.
 #
 
+from __future__ import print_function
+
 import glob
 import pprint
 import re
@@ -45,8 +47,7 @@ from rtemstoolkit import log
 from rtemstoolkit import macros
 from rtemstoolkit import options
 from rtemstoolkit import path
-
-import version
+from rtemstoolkit import version
 
 #
 # The path for the defaults.
@@ -114,13 +115,13 @@ def run(args):
         log.notice(str(_opts))
         log.notice('Defaults:')
         log.notice(str(_opts.defaults))
-    except error.general, gerr:
-        print gerr
+    except error.general as gerr:
+        print(gerr)
         sys.exit(1)
-    except error.internal, ierr:
-        print ierr
+    except error.internal as ierr:
+        print(ierr)
         sys.exit(1)
-    except error.exit, eerr:
+    except error.exit as eerr:
         pass
     except KeyboardInterrupt:
         log.notice('abort: user terminated')
diff --git a/tester/rt/pygdb/__init__.py b/tester/rt/pygdb/__init__.py
index b52f6f9..00b3364 100644
--- a/tester/rt/pygdb/__init__.py
+++ b/tester/rt/pygdb/__init__.py
@@ -17,5 +17,6 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 all = ['mi_parser']
-from mi_parser import scan
-from mi_parser import process
+from . import mi_parser
+scan = mi_parser.scan
+process = mi_parser.process
diff --git a/tester/rt/pygdb/mi_parser.py b/tester/rt/pygdb/mi_parser.py
index 65ea5e0..dd1d08f 100755
--- a/tester/rt/pygdb/mi_parser.py
+++ b/tester/rt/pygdb/mi_parser.py
@@ -28,10 +28,12 @@
 
 # $Id$
 
+from __future__ import print_function
 
 import re
 import pprint
-import spark
+
+from . import spark
 
 def __private():
 	class Token:
@@ -93,7 +95,7 @@ def __private():
 
 		def t_default(self, s):
 			r'( . | \n )+'
-			raise Exception, "Specification error: unmatched input for '%s'" % s
+			raise Exception("Specification error: unmatched input for '%s'" % s)
 
 		def __unescape(self, s):
 			s = re.sub(r'\\r', r'\r', s)
@@ -167,8 +169,8 @@ def __private():
 
 		def error(self, token, i=0, tokens=None):
 			if i > 2:
-				print '%s %s %s %s' % (tokens[i-3], tokens[i-2], tokens[i-1], tokens[i])
-			raise Exception, "Syntax error at or near %d:'%s' token" % (i, token)
+				print('%s %s %s %s' % (tokens[i-3], tokens[i-2], tokens[i-1], tokens[i]))
+			raise Exception("Syntax error at or near %d:'%s' token" % (i, token))
 
 	class GdbMiInterpreter(spark.GenericASTTraversal):
 		def __init__(self, ast):
@@ -203,8 +205,8 @@ def __private():
 				# tuple ::= { result result_list }
 				node.value = node[1].value
 				for result in node[2].value:
-					for n, v in result.items():
-						if node.value.has_key(n):
+					for n, v in list(result.items()):
+						if n in node.value:
 							#print '**********list conversion: [%s] %s -> %s' % (n, node.value[n], v)
 							old = node.value[n]
 							if not isinstance(old, list):
@@ -213,7 +215,7 @@ def __private():
 						else:
 							node.value[n] = v
 			else:
-				raise Exception, 'Invalid tuple'
+				raise Exception('Invalid tuple')
 			#print 'tuple: %s' % node.value
 
 		def n_list(self, node):
@@ -305,7 +307,7 @@ def __private():
 		def __repr__(self):
 			return pprint.pformat(self.__dict__)
 
-		def __nonzero__(self):
+		def __bool__(self):
 			return len(self.__dict__) > 0
 
 		def __getitem__(self, i):
@@ -320,7 +322,7 @@ def __private():
 			return None
 
 		def graft(self, dict_):
-			for name, value in dict_.items():
+			for name, value in list(dict_.items()):
 				name = name.replace('-', '_')
 				if isinstance(value, dict):
 					value = GdbDynamicObject(value)
@@ -336,7 +338,7 @@ def __private():
 	class GdbMiRecord:
 		def __init__(self, record):
 			self.result = None
-			for name, value in record[0].items():
+			for name, value in list(record[0].items()):
 				name = name.replace('-', '_')
 				if name == 'results':
 					for result in value:
@@ -363,19 +365,19 @@ def parse(tokens):
 
 def process(input):
 	tokens = scan(input)
-        ast = parse(tokens)
+	ast = parse(tokens)
 	__the_interpreter(ast)
 	return __the_output(ast.value)
 
 if __name__ == '__main__':
 	def main():
 		def print_tokens(tokens):
-			print
+			print()
 			for token in tokens:
 				if token.value:
-					print token.type + ': ' + token.value
+					print(token.type + ': ' + token.value)
 				else:
-					print token.type
+					print(token.type)
 
 		def run_test(test):
 			lines = test.splitlines()
@@ -386,7 +388,7 @@ if __name__ == '__main__':
 				ast = parse(tokens)
 				__the_interpreter(ast)
 				output = __the_output(ast.value)
-				print output
+				print(output)
 
 		x = '"No symbol table is loaded.  Use the \\"file\\" command."'
 		m = re.match('\".*?(?<![\\\\])\"', x)
diff --git a/tester/rt/pygdb/spark.py b/tester/rt/pygdb/spark.py
index aab2d19..0eac365 100644
--- a/tester/rt/pygdb/spark.py
+++ b/tester/rt/pygdb/spark.py
@@ -19,6 +19,8 @@
 #  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 #  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+from __future__ import print_function
+
 __version__ = 'SPARK-0.7 (pre-alpha-7)'
 
 import re
@@ -30,8 +32,8 @@ def _namelist(instance):
 	for c in classlist:
 		for b in c.__bases__:
 			classlist.append(b)
-		for name in c.__dict__.keys():
-			if not namedict.has_key(name):
+		for name in list(c.__dict__.keys()):
+			if name not in namedict:
 				namelist.append(name)
 				namedict[name] = 1
 	return namelist
@@ -42,7 +44,7 @@ class GenericScanner:
 		self.re = re.compile(pattern, re.VERBOSE|flags)
 
 		self.index2func = {}
-		for name, number in self.re.groupindex.items():
+		for name, number in list(self.re.groupindex.items()):
 			self.index2func[number-1] = getattr(self, 't_' + name)
 
 	def makeRE(self, name):
@@ -57,10 +59,10 @@ class GenericScanner:
 				rv.append(self.makeRE(name))
 
 		rv.append(self.makeRE('t_default'))
-		return string.join(rv, '|')
+		return '|'.join(rv)
 
 	def error(self, s, pos):
-		print "Lexical error at position %s" % pos
+		print("Lexical error at position %s" % pos)
 		raise SystemExit
 
 	def position(self, newpos=None):
@@ -81,12 +83,12 @@ class GenericScanner:
 			groups = m.groups()
 			self.pos = m.end()
 			for i in range(len(groups)):
-				if groups[i] is not None and self.index2func.has_key(i):
+				if groups[i] is not None and i in self.index2func:
 					self.index2func[i](groups[i])
 
 	def t_default(self, s):
 		r'( . | \n )+'
-		print "Specification error: unmatched input"
+		print("Specification error: unmatched input")
 		raise SystemExit
 
 #
@@ -145,14 +147,14 @@ class GenericParser:
 		changes = 1
 		while changes:
 			changes = 0
-			for k, v in self.edges.items():
+			for k, v in list(self.edges.items()):
 				if v is None:
 					state, sym = k
-					if self.states.has_key(state):
+					if state in self.states:
 						self.goto(state, sym)
 						changes = 1
 		rv = self.__dict__.copy()
-		for s in self.states.values():
+		for s in list(self.states.values()):
 			del s.items
 		del rv['rule2func']
 		del rv['nullable']
@@ -179,7 +181,7 @@ class GenericParser:
 
 	def addRule(self, doc, func, _preprocess=1):
 		fn = func
-		rules = string.split(doc)
+		rules = doc.split()
 
 		index = []
 		for i in range(len(rules)):
@@ -195,7 +197,7 @@ class GenericParser:
 			if _preprocess:
 				rule, fn = self.preprocess(rule, func)
 
-			if self.rules.has_key(lhs):
+			if lhs in self.rules:
 				self.rules[lhs].append(rule)
 			else:
 				self.rules[lhs] = [ rule ]
@@ -218,7 +220,7 @@ class GenericParser:
 		self.nullable = {}
 		tbd = []
 
-		for rulelist in self.rules.values():
+		for rulelist in list(self.rules.values()):
 			lhs = rulelist[0][0]
 			self.nullable[lhs] = 0
 			for rule in rulelist:
@@ -233,7 +235,7 @@ class GenericParser:
 				#  grammars.
 				#
 				for sym in rhs:
-					if not self.rules.has_key(sym):
+					if sym not in self.rules:
 						break
 				else:
 					tbd.append(rule)
@@ -267,7 +269,7 @@ class GenericParser:
 
 	def makeNewRules(self):
 		worklist = []
-		for rulelist in self.rules.values():
+		for rulelist in list(self.rules.values()):
 			for rule in rulelist:
 				worklist.append((rule, 0, 1, rule))
 
@@ -276,7 +278,7 @@ class GenericParser:
 			n = len(rhs)
 			while i < n:
 				sym = rhs[i]
-				if not self.rules.has_key(sym) or \
+				if sym not in self.rules or \
 				   not self.nullable[sym]:
 					candidate = 0
 					i = i + 1
@@ -293,7 +295,7 @@ class GenericParser:
 				if candidate:
 					lhs = self._NULLABLE+lhs
 					rule = (lhs, rhs)
-				if self.newrules.has_key(lhs):
+				if lhs in self.newrules:
 					self.newrules[lhs].append(rule)
 				else:
 					self.newrules[lhs] = [ rule ]
@@ -303,7 +305,7 @@ class GenericParser:
 		return None
 
 	def error(self, token):
-		print "Syntax error at or near `%s' token" % token
+		print("Syntax error at or near `%s' token" % token)
 		raise SystemExit
 
 	def parse(self, tokens):
@@ -320,7 +322,7 @@ class GenericParser:
 			self.states = { 0: self.makeState0() }
 			self.makeState(0, self._BOF)
 
-		for i in xrange(len(tokens)):
+		for i in range(len(tokens)):
 			sets.append([])
 
 			if sets[i] == []:
@@ -349,7 +351,8 @@ class GenericParser:
 		#
 		return self._NULLABLE == sym[0:len(self._NULLABLE)]
 
-	def skip(self, (lhs, rhs), pos=0):
+	def skip(self, xxx_todo_changeme, pos=0):
+		(lhs, rhs) = xxx_todo_changeme
 		n = len(rhs)
 		while pos < n:
 			if not self.isnullable(rhs[pos]):
@@ -372,7 +375,7 @@ class GenericParser:
 
 		core.sort()
 		tcore = tuple(core)
-		if self.cores.has_key(tcore):
+		if tcore in self.cores:
 			return self.cores[tcore]
 		#
 		#  Nope, doesn't exist.  Compute it and the associated
@@ -396,13 +399,13 @@ class GenericParser:
 
 				nextSym = rhs[pos]
 				key = (X.stateno, nextSym)
-				if not rules.has_key(nextSym):
-					if not edges.has_key(key):
+				if nextSym not in rules:
+					if key not in edges:
 						edges[key] = None
 						X.T.append(nextSym)
 				else:
 					edges[key] = None
-					if not predicted.has_key(nextSym):
+					if nextSym not in predicted:
 						predicted[nextSym] = 1
 						for prule in rules[nextSym]:
 							ppos = self.skip(prule)
@@ -426,10 +429,10 @@ class GenericParser:
 		#  need to know the entire set of predicted nonterminals
 		#  to do this without accidentally duplicating states.
 		#
-		core = predicted.keys()
+		core = list(predicted.keys())
 		core.sort()
 		tcore = tuple(core)
-		if self.cores.has_key(tcore):
+		if tcore in self.cores:
 			self.edges[(k, None)] = self.cores[tcore]
 			return k
 
@@ -440,7 +443,7 @@ class GenericParser:
 
 	def goto(self, state, sym):
 		key = (state, sym)
-		if not self.edges.has_key(key):
+		if key not in self.edges:
 			#
 			#  No transitions from state on sym.
 			#
@@ -638,7 +641,7 @@ class GenericParser:
 
 		for i in range(len(rhs)-1, -1, -1):
 			sym = rhs[i]
-			if not self.newrules.has_key(sym):
+			if sym not in self.newrules:
 				if sym != self._BOF:
 					attr[i] = tokens[k-1]
 					key = (item, k)
@@ -668,7 +671,7 @@ class GenericParser:
 			sortlist.append((len(rhs), name))
 			name2index[name] = i
 		sortlist.sort()
-		list = map(lambda (a,b): b, sortlist)
+		list = [a_b[1] for a_b in sortlist]
 		return rules[name2index[self.resolve(list)]]
 
 	def resolve(self, list):
@@ -833,15 +836,15 @@ class GenericASTMatcher(GenericParser):
 
 def _dump(tokens, sets, states):
 	for i in range(len(sets)):
-		print 'set', i
+		print('set', i)
 		for item in sets[i]:
-			print '\t', item
+			print('\t', item)
 			for (lhs, rhs), pos in states[item[0]].items:
-				print '\t\t', lhs, '::=',
-				print string.join(rhs[:pos]),
-				print '.',
-				print string.join(rhs[pos:])
+				print('\t\t', lhs, '::=', end=' ')
+				print(string.join(rhs[:pos]), end=' ')
+				print('.', end=' ')
+				print(string.join(rhs[pos:]))
 		if i < len(tokens):
-			print
-			print 'token', str(tokens[i])
-			print
+			print()
+			print('token', str(tokens[i]))
+			print()
diff --git a/tester/rt/stty.py b/tester/rt/stty.py
index d059b40..1483d56 100644
--- a/tester/rt/stty.py
+++ b/tester/rt/stty.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -32,6 +32,8 @@
 # RTEMS Testing Consoles
 #
 
+from __future__ import print_function
+
 import os
 import sys
 import termios
@@ -72,7 +74,7 @@ class tty:
             raise error.general('dev not found: %s' % (dev))
         try:
             self.fd = open(dev, 'rw')
-        except IOError, ioe:
+        except IOError as ioe:
             raise error.general('opening tty dev: %s: %s' % (dev, ioe))
         except:
             raise error.general('opening tty dev: %s: unknown' % (dev))
@@ -558,9 +560,9 @@ if __name__ == "__main__":
         t.control('CRTSCTS', False)
         t.vmin(1)
         t.vtime(2)
-        print t
+        print(t)
         t.set('B115200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,CLOCAL,~CRTSCTS')
-        print t
+        print(t)
         t.on()
         while True:
             c = t.fd.read(1)
diff --git a/tester/rt/test.py b/tester/rt/test.py
index b0e041a..c118382 100644
--- a/tester/rt/test.py
+++ b/tester/rt/test.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -28,8 +28,11 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+from __future__ import print_function
+
 import copy
 import datetime
+import fnmatch
 import os
 import sys
 import threading
@@ -41,12 +44,11 @@ from rtemstoolkit import path
 from rtemstoolkit import stacktraces
 from rtemstoolkit import version
 
-import bsps
-import config
-import console
-import options
-import report
-import fnmatch
+from . import bsps
+from . import config
+from . import console
+from . import options
+from . import report
 
 class test(object):
     def __init__(self, index, total, report, executable, rtems_tools, bsp, bsp_config, opts):
@@ -118,7 +120,7 @@ class test_run(object):
 
     def reraise(self):
         if self.result is not None:
-            raise self.result[0], self.result[1], self.result[2]
+            raise self.result[0](self.result[1]).with_traceback(self.result[2])
 
     def kill(self):
         if self.test:
@@ -157,9 +159,9 @@ def report_finished(reports, report_mode, reporting, finished, job_trace):
         if len(reported):
             del reported[:]
             if job_trace:
-                print '}} threading:', threading.active_count()
+                print('}} threading:', threading.active_count())
                 for t in threading.enumerate():
-                    print '}} ', t.name
+                    print('}} ', t.name)
     return reporting
 
 def _job_trace(tst, msg, total, exe, active, reporting):
@@ -302,20 +304,20 @@ def run(command_path = None):
         end_time = datetime.datetime.now()
         log.notice('Average test time: %s' % (str((end_time - start_time) / total)))
         log.notice('Testing time     : %s' % (str(end_time - start_time)))
-    except error.general, gerr:
-        print gerr
+    except error.general as gerr:
+        print(gerr)
         sys.exit(1)
-    except error.internal, ierr:
-        print ierr
+    except error.internal as ierr:
+        print(ierr)
         sys.exit(1)
-    except error.exit, eerr:
+    except error.exit as eerr:
         sys.exit(2)
     except KeyboardInterrupt:
         if opts is not None and opts.find_arg('--stacktrace'):
-            print '}} dumping:', threading.active_count()
+            print('}} dumping:', threading.active_count())
             for t in threading.enumerate():
-                print '}} ', t.name
-            print stacktraces.trace()
+                print('}} ', t.name)
+            print(stacktraces.trace())
         log.notice('abort: user terminated')
         killall(tests)
         sys.exit(1)
diff --git a/tester/rt/version.py b/tester/rt/version.py
index 7c82de3..b9b040d 100644
--- a/tester/rt/version.py
+++ b/tester/rt/version.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013-2014 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -28,11 +28,7 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-#
-# Manage paths locally. The internally the path is in Unix or shell format and
-# we convert to the native format when performing operations at the Python
-# level. This allows macro expansion to work.
-#
+from __future__ import print_function
 
 major = 0
 minor = 2
@@ -42,7 +38,7 @@ def str():
     return '%d.%d.%d'% (major, minor, revision)
 
 if __name__ == '__main__':
-    print 'major = %d' % (major)
-    print 'minor = %d' % (minor)
-    print 'revision = %d' % (revision)
-    print 'Version: %s' % (str())
+    print('major = %d' % (major))
+    print('minor = %d' % (minor))
+    print('revision = %d' % (revision))
+    print('Version: %s' % (str()))
diff --git a/tester/rtems-test b/tester/rtems-test
index f573fea..13025cc 100755
--- a/tester/rtems-test
+++ b/tester/rtems-test
@@ -1,7 +1,7 @@
 #! /usr/bin/env python
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013, 2015 Chris Johns (chrisj at rtems.org)
+# Copyright 2013-2016 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -29,6 +29,8 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+from __future__ import print_function
+
 import sys, os
 base = os.path.dirname(os.path.abspath(sys.argv[0]))
 parent = os.path.dirname(base)
@@ -39,5 +41,5 @@ try:
     import rt.test
     rt.test.run()
 except ImportError:
-    print >> sys.stderr, "Incorrect RTEMS Tools installation"
+    print("Incorrect RTEMS Tools installation", file = sys.stderr)
     sys.exit(1)




More information about the vc mailing list