[Contribs] Add command-line utility for looking up gPXE error codes.
authorStefan Hajnoczi <stefanha@gmail.com>
Sat, 10 May 2008 11:57:13 +0000 (12:57 +0100)
committerMichael Brown <mcb30@etherboot.org>
Tue, 20 May 2008 19:26:44 +0000 (20:26 +0100)
contrib/errcode/build_errcodedb.py [new file with mode: 0755]
contrib/errcode/errcode.py [new file with mode: 0755]

diff --git a/contrib/errcode/build_errcodedb.py b/contrib/errcode/build_errcodedb.py
new file mode 100755 (executable)
index 0000000..295c927
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+import sys
+import re
+
+pxenv_status_files = ('../../src/include/errno.h', )
+errfile_files = ('../../src/include/gpxe/errfile.h',
+            '../../src/arch/i386/include/bits/errfile.h')
+posix_errno_files = ('../../src/include/errno.h', )
+
+PXENV_STATUS_RE = re.compile(r'^#define\s+(PXENV_STATUS_[^\s]+)\s+(.+)$')
+ERRFILE_RE = re.compile(r'^#define\s+(ERRFILE_[^\s]+)\s+(.+)$')
+POSIX_ERRNO_RE = re.compile(r'^#define\s+(E[A-Z]+)\s+.*(0x[0-9a-f]+).*$')
+
+def err(msg):
+    sys.stderr.write('%s: %s\n' % (sys.argv[0], msg))
+    sys.exit(1)
+
+def load_header_file(filename, regexp):
+    defines = {}
+    for line in open(filename, 'r'):
+        m = regexp.match(line)
+        if m:
+            key, val = m.groups()
+            defines[key] = val
+    return defines
+
+def evaluate(defines, expr):
+    pyexpr = ''
+    for token in expr.split():
+        if token in '()':
+            pass
+        elif token.startswith('/*') or token.startswith('//'):
+            break
+        elif token.startswith('0x') or token == '|':
+            pyexpr += token
+        else:
+            if token in defines:
+                pyexpr += '0x%x' % defines[token]
+            else:
+                return -1
+    if not re.match(r'^[0-9a-zA-Z_|]+$', pyexpr):
+        err('invalid expression')
+    return eval(pyexpr)
+
+def build(filenames, regexp):
+    unevaluated = {}
+    for filename in filenames:
+        unevaluated.update(load_header_file(filename, regexp))
+
+    evaluated = {}
+    changed = True
+    while changed:
+        changed = False
+        for key in list(unevaluated.keys()):
+            val = evaluate(evaluated, unevaluated[key])
+            if val != -1:
+                del unevaluated[key]
+                evaluated[key] = val
+                changed = True
+    if unevaluated:
+        err('unable to evaluate all #defines')
+    return evaluated
+
+print 'pxenv_status =', repr(build(pxenv_status_files, PXENV_STATUS_RE))
+print 'errfile =', repr(build(errfile_files, ERRFILE_RE))
+print 'posix_errno =', repr(build(posix_errno_files, POSIX_ERRNO_RE))
diff --git a/contrib/errcode/errcode.py b/contrib/errcode/errcode.py
new file mode 100755 (executable)
index 0000000..b7a1e03
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+import sys
+
+try:
+    import errcodedb
+except ImportError:
+    sys.stderr.write('Please run this first: ./build_errcodedb.py >errcodedb.py\n')
+    sys.exit(1)
+
+def to_pxenv_status(errno):
+    return errno & 0xff
+
+def to_uniq(errno):
+    return (errno >> 8) & 0x1f
+
+def to_errfile(errno):
+    return (errno >> 13) & 0x7ff
+
+def to_posix_errno(errno):
+    return (errno >> 24) & 0x7f
+
+def lookup_errno_component(defines, selector, component):
+    for key, val in defines.iteritems():
+        if selector(val) == component:
+            return key
+    return '0x%x' % component
+
+class Errno(object):
+    def __init__(self, errno):
+        self.pxenv_status = to_pxenv_status(errno)
+        self.uniq = to_uniq(errno)
+        self.errfile = to_errfile(errno)
+        self.posix_errno = to_posix_errno(errno)
+
+    def rawstr(self):
+        return 'pxenv_status=0x%x uniq=%d errfile=0x%x posix_errno=0x%x' % (self.pxenv_status, self.uniq, self.errfile, self.posix_errno)
+
+    def prettystr(self):
+        return 'pxenv_status=%s uniq=%d errfile=%s posix_errno=%s' % (
+                lookup_errno_component(errcodedb.pxenv_status, to_pxenv_status, self.pxenv_status),
+                self.uniq,
+                lookup_errno_component(errcodedb.errfile, to_errfile, self.errfile),
+                lookup_errno_component(errcodedb.posix_errno, to_posix_errno, self.posix_errno)
+                )
+
+    def __str__(self):
+        return self.prettystr()
+
+def usage():
+    sys.stderr.write('usage: %s ERROR_NUMBER\n' % sys.argv[0])
+    sys.exit(1)
+
+if __name__ == '__main__':
+    if len(sys.argv) != 2:
+        usage()
+
+    try:
+        errno = int(sys.argv[1], 16)
+    except ValueError:
+        usage()
+
+    print Errno(errno)
+    sys.exit(0)