Initial Contribution
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
new file mode 100644
index 0000000..feb1561
--- /dev/null
+++ b/libc/tools/bionic_utils.py
@@ -0,0 +1,287 @@
+# common python utility routines for the Bionic tool scripts
+
+import sys, os, commands, string
+
+# support Bionic architectures, add new ones as appropriate
+#
+bionic_archs = [ "arm", "x86" ]
+
+# basic debugging trace support
+# call D_setlevel to set the verbosity level
+# and D(), D2(), D3(), D4() to add traces
+#
+verbose = 1
+
+def D(msg):
+    global verbose
+    if verbose > 0:
+        print msg
+
+def D2(msg):
+    global verbose
+    if verbose >= 2:
+        print msg
+
+def D3(msg):
+    global verbose
+    if verbose >= 3:
+        print msg
+
+def D4(msg):
+    global verbose
+    if verbose >= 4:
+        print msg
+
+def D_setlevel(level):
+    global verbose
+    verbose = level
+
+
+def find_dir_of(path):
+    '''return the directory name of 'path', or "." if there is none'''
+    # remove trailing slash
+    if len(path) > 1 and path[-1] == '/':
+        path = path[:-1]
+
+    # find parent directory name
+    d = os.path.dirname(path)
+    if d == "":
+        return "."
+    else:
+        return d
+
+#  other stuff
+#
+#
+def find_file_from_upwards(from_path,target_file):
+    """find a file in the current directory or its parents. if 'from_path' is None,
+       seach from the current program's directory"""
+    path = from_path
+    if path == None:
+        path = find_dir_of(sys.argv[0])
+        D("this script seems to be located in: %s" % path)
+
+    while 1:
+        if path == "":
+            path = "."
+
+        file = path + "/" + target_file
+        D("probing "+file)
+
+        if os.path.isfile(file):
+            D("found %s in %s" % (target_file, path))
+            return file
+
+        if path == ".":
+            break
+
+        path = os.path.dirname(path)
+
+    path = ""
+    while 1:
+        path = "../" + path
+        file = path + target_file
+        D("probing "+file)
+
+        if os.path.isfile(file):
+            D("found %s in %s" % (target_file, path))
+            return file
+
+
+    return None
+
+def find_bionic_root():
+    '''find the root of the Bionic source tree. we check for the SYSCALLS.TXT file
+       from the location of the current program's directory.'''
+
+    # note that we can't use find_file_from_upwards() since we can't use os.path.abspath
+    # that's because in some cases the p4 client is in a symlinked directory, and this
+    # function will return the real path instead, which later creates problems when
+    # p4 commands are issued
+    #
+    file = find_file_from_upwards(None, "SYSCALLS.TXT")
+    if file:
+        return os.path.dirname(file)
+    else:
+        return None
+
+def find_kernel_headers():
+    """try to find the directory containing the kernel headers for this machine"""
+    status, version = commands.getstatusoutput( "uname -r" )  # get Linux kernel version
+    if status != 0:
+        D("could not execute 'uname -r' command properly")
+        return None
+
+    # get rid of the "-xenU" suffix that is found in Xen virtual machines
+    if len(version) > 5 and version[-5:] == "-xenU":
+        version = version[:-5]
+
+    path = "/usr/src/linux-headers-" + version
+    D("probing %s for kernel headers" % (path+"/include"))
+    ret = os.path.isdir( path )
+    if ret:
+        D("found kernel headers in: %s" % (path + "/include"))
+        return path
+    return None
+
+
+# parser for the SYSCALLS.TXT file
+#
+class SysCallsTxtParser:
+    def __init__(self):
+        self.syscalls = []
+        self.lineno   = 0
+
+    def E(msg):
+        print "%d: %s" % (self.lineno, msg)
+
+    def parse_line(self, line):
+        pos_lparen = line.find('(')
+        E          = self.E
+        if pos_lparen < 0:
+            E("missing left parenthesis in '%s'" % line)
+            return
+
+        pos_rparen = line.rfind(')')
+        if pos_rparen < 0 or pos_rparen <= pos_lparen:
+            E("missing or misplaced right parenthesis in '%s'" % line)
+            return
+
+        return_type = line[:pos_lparen].strip().split()
+        if len(return_type) < 2:
+            E("missing return type in '%s'" % line)
+            return
+
+        syscall_func = return_type[-1]
+        return_type  = string.join(return_type[:-1],' ')
+
+        pos_colon = syscall_func.find(':')
+        if pos_colon < 0:
+            syscall_name = syscall_func
+        else:
+            if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
+                E("misplaced colon in '%s'" % line)
+                return
+            syscall_name = syscall_func[pos_colon+1:]
+            syscall_func = syscall_func[:pos_colon]
+
+        if pos_rparen > pos_lparen+1:
+            syscall_params = line[pos_lparen+1:pos_rparen].split(',')
+            params         = string.join(syscall_params,',')
+        else:
+            syscall_params = []
+            params         = "void"
+
+        number = line[pos_rparen+1:].strip()
+        if number == "stub":
+            syscall_id  = -1
+            syscall_id2 = -1
+        else:
+            try:
+                if number[0] == '#':
+                    number = number[1:].strip()
+                numbers = string.split(number,',')
+                syscall_id  = int(numbers[0])
+                syscall_id2 = syscall_id
+                if len(numbers) > 1:
+                    syscall_id2 = int(numbers[1])
+            except:
+                E("invalid syscall number in '%s'" % line)
+                return
+
+        t = { "id"     : syscall_id,
+              "id2"    : syscall_id2,
+              "name"   : syscall_name,
+              "func"   : syscall_func,
+              "params" : syscall_params,
+              "decl"   : "%-15s  %s (%s);" % (return_type, syscall_func, params) }
+
+        self.syscalls.append(t)
+
+    def parse_file(self, file_path):
+        D2("parse_file: %s" % file_path)
+        fp = open(file_path)
+        for line in fp.xreadlines():
+            self.lineno += 1
+            line = line.strip()
+            if not line: continue
+            if line[0] == '#': continue
+            self.parse_line(line)
+
+        fp.close()
+
+
+class Output:
+    def  __init__(self,out=sys.stdout):
+        self.out = out
+
+    def write(self,msg):
+        self.out.write(msg)
+
+    def writeln(self,msg):
+        self.out.write(msg)
+        self.out.write("\n")
+
+class StringOutput:
+    def __init__(self):
+        self.line = ""
+
+    def write(self,msg):
+        self.line += msg
+        D2("write '%s'" % msg)
+
+    def writeln(self,msg):
+        self.line += msg + '\n'
+        D2("write '%s\\n'"% msg)
+
+    def get(self):
+        return self.line
+
+
+def create_file_path(path):
+    dirs = []
+    while 1:
+        parent = os.path.dirname(path)
+        if parent == "/":
+            break
+        dirs.append(parent)
+        path = parent
+
+    dirs.reverse()
+    for dir in dirs:
+        #print "dir %s" % dir
+        if os.path.isdir(dir):
+            continue
+        os.mkdir(dir)
+
+def walk_source_files(paths,callback,args,excludes=[]):
+    """recursively walk a list of paths and files, only keeping the source files in directories"""
+    for path in paths:
+        if not os.path.isdir(path):
+            callback(path,args)
+        else:
+            for root, dirs, files in os.walk(path):
+                #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
+                if len(excludes):
+                    for d in dirs[:]:
+                        if d in excludes:
+                            dirs.remove(d)
+                for f in files:
+                    r, ext = os.path.splitext(f)
+                    if ext in [ ".h", ".c", ".cpp", ".S" ]:
+                        callback( "%s/%s" % (root,f), args )
+
+def cleanup_dir(path):
+    """create a directory if needed, and ensure that it is totally empty
+       by removing any existing content in it"""
+    if not os.path.exists(path):
+        os.mkdir(path)
+    else:
+        for root, dirs, files in os.walk(path, topdown=False):
+            if root.endswith("kernel_headers/"):
+                # skip 'kernel_headers'
+                continue
+            for name in files:
+                os.remove(os.path.join(root, name))
+            for name in dirs:
+                os.rmdir(os.path.join(root, name))
diff --git a/libc/tools/checksyscalls.py b/libc/tools/checksyscalls.py
new file mode 100755
index 0000000..9edb390
--- /dev/null
+++ b/libc/tools/checksyscalls.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+#
+# this tool is used to check that the syscall numbers that are in
+# SYSCALLS.TXT correspond to those found in the Linux kernel sources
+# for the arm and i386 architectures
+#
+
+import sys, re, string, os, commands
+from   bionic_utils import *
+
+# change this if necessary
+syscalls_txt = "SYSCALLS.TXT"
+
+def usage():
+    print "usage: checksyscalls [options] [kernel_headers_rootdir]"
+    print "    options:    -v   enable verbose mode"
+    sys.exit(1)
+
+
+linux_root    = None
+syscalls_file = None
+
+def parse_command_line(args):
+    global linux_root, syscalls_file, verbose
+
+    program = args[0]
+    args    = args[1:]
+    while len(args) > 0 and args[0][0] == "-":
+        option = args[0][1:]
+        args   = args[1:]
+
+        if option == "v":
+            D_setlevel(1)
+        else:
+            usage()
+
+    if len(args) > 2:
+        usage()
+
+    if len(args) == 0:
+        linux_root = find_kernel_headers()
+        if linux_root == None:
+            print "could not locate this system kernel headers root directory, please"
+            print "specify one when calling this program, i.e. 'checksyscalls <headers-directory>'"
+            sys.exit(1)
+        print "using the following kernel headers root: '%s'" % linux_root
+    else:
+        linux_root = args[0]
+        if not os.path.isdir(linux_root):
+            print "the directory '%s' does not exist. aborting\n" % headers_root
+            sys.exit(1)
+
+parse_command_line(sys.argv)
+
+syscalls_file = find_file_from_upwards(None, syscalls_txt)
+if not syscalls_file:
+    print "could not locate the %s file. Aborting" % syscalls_txt
+    sys.exit(1)
+
+print "parsing %s" % syscalls_file
+
+# read the syscalls description file
+#
+
+parser = SysCallsTxtParser()
+parser.parse_file(syscalls_file)
+syscalls = parser.syscalls
+
+re_nr_line       = re.compile( r"#define __NR_(\w*)\s*\(__NR_SYSCALL_BASE\+\s*(\w*)\)" )
+re_nr_clock_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_timer_create\+(\w*)\)" )
+re_arm_nr_line   = re.compile( r"#define __ARM_NR_(\w*)\s*\(__ARM_NR_BASE\+\s*(\w*)\)" )
+re_x86_line      = re.compile( r"#define __NR_(\w*)\s*([0-9]*)" )
+
+# now read the Linux arm header
+def process_nr_line(line,dict):
+
+    m = re_nr_line.match(line)
+    if m:
+        dict[m.group(1)] = int(m.group(2))
+        return
+
+    m = re_nr_clock_line.match(line)
+    if m:
+        dict[m.group(1)] = int(m.group(2)) + 259
+        return
+
+    m = re_arm_nr_line.match(line)
+    if m:
+        #print "%s = %s" % (m.group(1), m.group(2))
+        dict["ARM_"+m.group(1)] = int(m.group(2)) + 0x0f0000
+        return
+
+    m = re_x86_line.match(line)
+    if m:
+        # try block because the ARM header has some #define _NR_XXXXX  /* nothing */
+        try:
+            #print "%s = %s" % (m.group(1), m.group(2))
+            dict[m.group(1)] = int(m.group(2))
+        except:
+            pass
+        return
+
+
+def process_header(header_file,dict):
+    fp = open(header_file)
+    D("reading "+header_file)
+    for line in fp.xreadlines():
+        line = line.strip()
+        if not line: continue
+        process_nr_line(line,dict)
+    fp.close()
+
+arm_dict = {}
+x86_dict = {}
+
+
+# remove trailing slash and '/include' from the linux_root, if any
+if linux_root[-1] == '/':
+    linux_root = linux_root[:-1]
+
+if len(linux_root) > 8 and linux_root[-8:] == '/include':
+    linux_root = linux_root[:-8]
+
+arm_unistd = linux_root + "/include/asm-arm/unistd.h"
+if not os.path.exists(arm_unistd):
+    print "WEIRD: could not locate the ARM unistd.h header file"
+    print "tried searching in '%s'" % arm_unistd
+    print "maybe using a different set of kernel headers might help"
+    sys.exit(1)
+
+# on recent kernels, asm-i386 and asm-x64_64 have been merged into asm-x86
+# with two distinct unistd_32.h and unistd_64.h definition files.
+# take care of this here
+#
+x86_unistd = linux_root + "/include/asm-i386/unistd.h"
+if not os.path.exists(x86_unistd):
+    x86_unistd1 = x86_unistd
+    x86_unistd = linux_root + "/include/asm-x86/unistd_32.h"
+    if not os.path.exists(x86_unistd):
+        print "WEIRD: could not locate the i386/x86 unistd.h header file"
+        print "tried searching in '%s' and '%s'" % (x86_unistd1, x86_unistd)
+        print "maybe using a different set of kernel headers might help"
+        sys.exit(1)
+
+process_header( linux_root+"/include/asm-arm/unistd.h", arm_dict )
+process_header( x86_unistd, x86_dict )
+
+# now perform the comparison
+errors = 0
+for sc in syscalls:
+    sc_name = sc["name"]
+    sc_id   = sc["id"]
+    if sc_id >= 0:
+        if not arm_dict.has_key(sc_name):
+            print "arm syscall %s not defined !!" % sc_name
+            errors += 1
+        elif arm_dict[sc_name] != sc_id:
+            print "arm syscall %s should be %d instead of %d !!" % (sc_name, arm_dict[sc_name], sc_id)
+            errors += 1
+
+for sc in syscalls:
+    sc_name = sc["name"]
+    sc_id2  = sc["id2"]
+    if sc_id2 >= 0:
+        if not x86_dict.has_key(sc_name):
+            print "x86 syscall %s not defined !!" % sc_name
+            errors += 1
+        elif x86_dict[sc_name] != sc_id2:
+            print "x86 syscall %s should be %d instead of %d !!" % (sc_name, x86_dict[sc_name], sc_id2)
+            errors += 1
+
+if errors == 0:
+    print "congratulations, everything's fine !!"
+else:
+    print "correct %d errors !!" % errors
diff --git a/libc/tools/genserv.py b/libc/tools/genserv.py
new file mode 100755
index 0000000..e37d28f
--- /dev/null
+++ b/libc/tools/genserv.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+
+import sys, os, string, re
+
+def usage():
+    print """\
+  usage:  genserv < /etc/services > netbsd/net/services.h
+
+  this program is used to generate the hard-coded internet service list for the
+  Bionic C library.
+"""
+
+re_service = re.compile(r"([\d\w\-_]+)\s+(\d+)/(tcp|udp)(.*)")
+re_alias   = re.compile(r"([\d\w\-_]+)(.*)")
+
+class Service:
+    def __init__(self,name,port,proto):
+        self.name    = name
+        self.port    = port
+        self.proto   = proto
+        self.aliases = []
+
+    def add_alias(self,alias):
+        self.aliases.append(alias)
+
+    def __str__(self):
+        result  = "\\%0o%s" % (len(self.name),self.name)
+        result += "\\%0o\\%0o" % (((self.port >> 8) & 255), self.port & 255)
+        if self.proto == "tcp":
+            result += "t"
+        else:
+            result += "u"
+
+        result += "\\%0o" % len(self.aliases)
+        for alias in self.aliases:
+            result += "\\%0o%s" % (len(alias), alias)
+
+        return result
+
+def parse(f):
+    result = []  # list of Service objects
+    for line in f.xreadlines():
+        if len(line) > 0 and line[-1] == "\n":
+            line = line[:-1]
+        if len(line) > 0 and line[-1] == "\r":
+            line = line[:-1]
+
+        line = string.strip(line)
+        if len(line) == 0 or line[0] == "#":
+            continue
+
+        m = re_service.match(line)
+        if m:
+            service = Service( m.group(1), int(m.group(2)), m.group(3) )
+            rest    = string.strip(m.group(4))
+
+            while 1:
+                m = re_alias.match(rest)
+                if not m:
+                    break
+                service.add_alias(m.group(1))
+                rest = string.strip(m.group(2))
+
+            result.append(service)
+
+    return result
+
+services = parse(sys.stdin)
+line = '/* generated by genserv.py - do not edit */\nstatic const char  _services[] = "\\\n'
+for s in services:
+    line += str(s)+"\\\n"
+line += '\\0";\n'
+print line
+
+
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
new file mode 100755
index 0000000..37e356d
--- /dev/null
+++ b/libc/tools/gensyscalls.py
@@ -0,0 +1,451 @@
+#!/usr/bin/python
+#
+# this tool is used to generate the syscall assmbler templates
+# to be placed into arch-x86/syscalls, as well as the content
+# of arch-x86/linux/_syscalls.h
+#
+
+import sys, os.path, glob, re, string, commands, filecmp, shutil
+
+from bionic_utils import *
+
+# set this to 1 if you want to generate thumb stubs
+gen_thumb_stubs = 0
+
+# set this to 1 if you want to generate ARM EABI stubs
+gen_eabi_stubs = 1
+
+# get the root Bionic directory, simply this script's dirname
+#
+bionic_root = find_bionic_root()
+if not bionic_root:
+    print "could not find the Bionic root directory. aborting"
+    sys.exit(1)
+
+if bionic_root[-1] != '/':
+    bionic_root += "/"
+
+print "bionic_root is %s" % bionic_root
+
+# temp directory where we store all intermediate files
+bionic_temp = "/tmp/bionic_gensyscalls/"
+
+# all architectures, update as you see fit
+all_archs = [ "arm", "x86" ]
+
+def make_dir( path ):
+    if not os.path.exists(path):
+        parent = os.path.dirname(path)
+        if parent:
+            make_dir(parent)
+        os.mkdir(path)
+
+def create_file( relpath ):
+    dir = os.path.dirname( bionic_temp + relpath )
+    make_dir(dir)
+    return open( bionic_temp + relpath, "w" )
+
+# x86 assembler templates for each syscall stub
+#
+
+x86_header = """/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type %(fname)s, @function
+    .globl %(fname)s
+    .align 4
+
+%(fname)s:
+"""
+
+x86_registers = [ "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp" ]
+
+x86_call = """    movl    $%(idname)s, %%eax
+    int     $0x80
+    cmpl    $-129, %%eax
+    jb      1f
+    negl    %%eax
+    pushl   %%eax
+    call    __set_errno
+    addl    $4, %%esp
+    orl     $-1, %%eax
+1:
+"""
+
+x86_return = """    ret
+"""
+
+# ARM assembler templates for each syscall stub
+#
+arm_header = """/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type %(fname)s, #function
+    .globl %(fname)s
+    .align 4
+    .fnstart
+
+%(fname)s:
+"""
+
+arm_call_default = arm_header + """\
+    swi   #%(idname)s
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
+"""
+
+arm_call_long = arm_header + """\
+    .save   {r4, r5, lr}
+    stmfd   sp!, {r4, r5, lr}
+    ldr     r4, [sp, #12]
+    ldr     r5, [sp, #16]
+    swi     # %(idname)s
+    ldmfd   sp!, {r4, r5, lr}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
+"""
+
+arm_eabi_call_default = arm_header + """\
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =%(idname)s
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
+"""
+
+arm_eabi_call_long = arm_header + """\
+    mov     ip, sp
+    .save   {r4, r5, r6, r7}
+    stmfd   sp!, {r4, r5, r6, r7}
+    ldmfd   ip, {r4, r5, r6}
+    ldr     r7, =%(idname)s
+    swi     #0
+    ldmfd   sp!, {r4, r5, r6, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
+"""
+
+# ARM thumb assembler templates for each syscall stub
+#
+thumb_header = """/* autogenerated by gensyscalls.py */
+    .text
+    .type %(fname)s, #function
+    .globl %(fname)s
+    .align 4
+    .thumb_func
+    .fnstart
+
+#define  __thumb__
+#include <sys/linux-syscalls.h>
+
+
+%(fname)s:
+"""
+
+thumb_call_default = thumb_header + """\
+    .save   {r7,lr}
+    push    {r7,lr}
+    ldr     r7, =%(idname)s
+    swi     #0
+    tst     r0, r0
+    bmi     1f
+    pop     {r7,pc}
+1:
+    neg     r0, r0
+    ldr     r1, =__set_errno
+    blx     r1
+    pop     {r7,pc}
+    .fnend
+"""
+
+thumb_call_long = thumb_header + """\
+    .save  {r4,r5,r7,lr}
+    push   {r4,r5,r7,lr}
+    ldr    r4, [sp,#16]
+    ldr    r5, [sp,#20]
+    ldr    r7, =%(idname)s
+    swi    #0
+    tst    r0, r0
+    bmi    1f
+    pop    {r4,r5,r7,pc}
+1:
+    neg    r0, r0
+    ldr    r1, =__set_errno
+    blx    r1
+    pop    {r4,r5,r7,pc}
+    .fnend
+"""
+
+
+class State:
+    def __init__(self):
+        self.old_stubs = []
+        self.new_stubs = []
+        self.other_files = []
+        self.syscalls = []
+
+    def x86_genstub(self,fname, numparams, idname):
+        t = { "fname"  : fname,
+              "idname" : idname }
+
+        result     = x86_header % t
+        stack_bias = 4
+        for r in range(numparams):
+            result     += "    pushl   " + x86_registers[r] + "\n"
+            stack_bias += 4
+
+        for r in range(numparams):
+            result += "    mov     %d(%%esp), %s" % (stack_bias+r*4, x86_registers[r]) + "\n"
+
+        result += x86_call % t
+
+        for r in range(numparams):
+            result += "    popl    " + x86_registers[numparams-r-1] + "\n"
+
+        result += x86_return
+        return result
+
+
+    def arm_genstub(self,fname, flags, idname):
+        t = { "fname"  : fname,
+              "idname" : idname }
+        if flags:
+            numargs = int(flags)
+            if numargs > 4:
+                return arm_call_long % t
+        return arm_call_default % t
+
+
+    def arm_eabi_genstub(self,fname, flags, idname):
+        t = { "fname"  : fname,
+              "idname" : idname }
+        if flags:
+            numargs = int(flags)
+            if numargs > 4:
+                return arm_eabi_call_long % t
+        return arm_eabi_call_default % t
+
+
+    def thumb_genstub(self,fname, flags, idname):
+        t = { "fname"  : fname,
+              "idname" : idname }
+        if flags:
+            numargs = int(flags)
+            if numargs > 4:
+                return thumb_call_long % t
+        return thumb_call_default % t
+
+
+    def process_file(self,input):
+        parser = SysCallsTxtParser()
+        parser.parse_file(input)
+        self.syscalls = parser.syscalls
+        parser = None
+
+        for t in self.syscalls:
+            syscall_func   = t["func"]
+            syscall_params = t["params"]
+            syscall_name   = t["name"]
+
+            if t["id"] >= 0:
+                if gen_thumb_stubs:
+                    t["asm-thumb"] = self.thumb_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                else:
+                    if gen_eabi_stubs:
+                        t["asm-arm"]   = self.arm_eabi_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                    else:
+                        t["asm-arm"]   = self.arm_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+
+            if t["id2"] >= 0:
+                t["asm-x86"] = self.x86_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+
+    def gen_NR_syscall(self,fp,name,id):
+        fp.write( "#define __NR_%-25s    (__NR_SYSCALL_BASE + %d)\n" % (name,id) )
+
+    # now dump the content of linux/_syscalls.h
+    def gen_linux_syscalls_h(self):
+        path = "include/sys/linux-syscalls.h"
+        D( "generating "+path )
+        fp = create_file( path )
+        fp.write( "/* auto-generated by gensyscalls.py, do not touch */\n" )
+        fp.write( "#ifndef _BIONIC_LINUX_SYSCALLS_H_\n\n" )
+        fp.write( "#if !defined __ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H\n" )
+        fp.write( "#if defined __arm__ && !defined __ARM_EABI__ && !defined __thumb__\n" )
+        fp.write( "  #  define __NR_SYSCALL_BASE  0x900000\n" )
+        fp.write( "  #else\n" )
+        fp.write( "  #  define  __NR_SYSCALL_BASE  0\n" )
+        fp.write( "  #endif\n\n" )
+
+        # first, all common syscalls
+        for sc in self.syscalls:
+            sc_id  = sc["id"]
+            sc_id2 = sc["id2"]
+            sc_name = sc["name"]
+            if sc_id == sc_id2 and sc_id >= 0:
+                self.gen_NR_syscall( fp, sc_name, sc_id )
+
+        # now, all arm-specific syscalls
+        fp.write( "\n#ifdef __arm__\n" );
+        for sc in self.syscalls:
+            sc_id  = sc["id"]
+            sc_id2 = sc["id2"]
+            sc_name = sc["name"]
+            if sc_id != sc_id2 and sc_id >= 0:
+                self.gen_NR_syscall( fp, sc_name, sc_id )
+        fp.write( "#endif\n" );
+
+        # finally, all i386-specific syscalls
+        fp.write( "\n#ifdef __i386__\n" );
+        for sc in self.syscalls:
+            sc_id  = sc["id"]
+            sc_id2 = sc["id2"]
+            sc_name = sc["name"]
+            if sc_id != sc_id2 and sc_id2 >= 0:
+                self.gen_NR_syscall( fp, sc_name, sc_id2 )
+        fp.write( "#endif\n" );
+
+        fp.write( "\n#endif\n" )
+        fp.write( "\n#endif /* _BIONIC_LINUX_SYSCALLS_H_ */\n" );
+        fp.close()
+        self.other_files.append( path )
+
+
+    # now dump the content of linux/_syscalls.h
+    def gen_linux_unistd_h(self):
+        path = "include/sys/linux-unistd.h"
+        D( "generating "+path )
+        fp = create_file( path )
+        fp.write( "/* auto-generated by gensyscalls.py, do not touch */\n" )
+        fp.write( "#ifndef _BIONIC_LINUX_UNISTD_H_\n\n" );
+        fp.write( "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n" )
+
+        for sc in self.syscalls:
+            fp.write( sc["decl"]+"\n" )
+
+        fp.write( "#ifdef __cplusplus\n}\n#endif\n" )
+        fp.write( "\n#endif /* _BIONIC_LINUX_UNISTD_H_ */\n" );
+        fp.close()
+        self.other_files.append( path )
+
+    # now dump the contents of syscalls.mk
+    def gen_arch_arm_syscalls_mk(self):
+        path = "arch-arm/syscalls.mk"
+        D( "generating "+path )
+        fp = create_file( path )
+        fp.write( "# auto-generated by gensyscalls.py, do not touch\n" )
+        fp.write( "syscall_src := \n" )
+        for sc in self.syscalls:
+                if sc["id"] >= 0:
+                        fp.write( "syscall_src += arch-arm/syscalls/%s.S\n" % sc["func"] )
+        fp.close()
+        self.other_files.append( path )
+
+    # now generate each syscall stub
+    def gen_syscall_stubs(self):
+        for sc in self.syscalls:
+            if sc.has_key("asm-arm"):
+                fname = "arch-arm/syscalls/%s.S" % sc["func"]
+                D( ">>> generating "+fname )
+                fp = create_file( fname )
+                fp.write(sc["asm-arm"])
+                fp.close()
+                self.new_stubs.append( fname )
+
+            if sc.has_key("asm-thumb"):
+                fname = "arch-arm/syscalls/%s.S" % sc["func"]
+                D( ">>> generating "+fname )
+                fp = create_file( fname )
+                fp.write(sc["asm-thumb"])
+                fp.close()
+                self.new_stubs.append( fname )
+
+            if sc.has_key("asm-x86"):
+                fname = "arch-x86/syscalls/%s.S" % sc["func"]
+                D( ">>> generating "+fname )
+                fp = create_file( fname )
+                fp.write(sc["asm-x86"])
+                fp.close()
+                self.new_stubs.append( fname )
+
+
+    def  regenerate(self):
+        D( "scanning for existing architecture-specific stub files" )
+
+        bionic_root_len = len(bionic_root)
+
+        for arch in all_archs:
+            arch_path = bionic_root + "arch-" + arch
+            D( "scanning " + arch_path )
+            files = glob.glob( arch_path + "/syscalls/*.S" )
+            for f in files:
+                self.old_stubs.append( f[bionic_root_len:] )
+
+        D( "found %d stub files" % len(self.old_stubs) )
+
+        if not os.path.exists( bionic_temp ):
+            D( "creating %s" % bionic_temp )
+            os.mkdir( bionic_temp )
+
+#        D( "p4 editing source files" )
+#        for arch in all_archs:
+#            commands.getoutput( "p4 edit " + arch + "/syscalls/*.S " )
+#            commands.getoutput( "p4 edit " + arch + "/syscalls.mk" )
+#        commands.getoutput( "p4 edit " + bionic_root + "include/sys/linux-syscalls.h" )
+
+        D( "re-generating stubs and support files" )
+
+        self.gen_linux_syscalls_h()
+        self.gen_arch_arm_syscalls_mk()
+        self.gen_linux_unistd_h()
+        self.gen_syscall_stubs()
+
+        D( "comparing files" )
+        adds    = []
+        edits   = []
+
+        for stub in self.new_stubs + self.other_files:
+            if not os.path.exists( bionic_root + stub ):
+                # new file, P4 add it
+                D( "new file:     " + stub)
+                adds.append( bionic_root + stub )
+                shutil.copyfile( bionic_temp + stub, bionic_root + stub )
+
+            elif not filecmp.cmp( bionic_temp + stub, bionic_root + stub ):
+                D( "changed file: " + stub)
+                edits.append( stub )
+
+        deletes = []
+        for stub in self.old_stubs:
+            if not stub in self.new_stubs:
+                D( "deleted file: " + stub)
+                deletes.append( bionic_root + stub )
+
+
+        if adds:
+            commands.getoutput( "p4 add " + string.join( adds, " " ) )
+        if deletes:
+            commands.getoutput( "p4 delete " + string.join( deletes, " " ) )
+        if edits:
+            commands.getoutput( "p4 edit " + string.join( edits, " " ) )
+            for file in edits:
+                shutil.copyfile( bionic_temp + file, bionic_root + file )
+
+        D("ready to go !!")
+
+D_setlevel(1)
+
+state = State()
+state.process_file(bionic_root+"SYSCALLS.TXT")
+state.regenerate()