Code drop from //branches/cupcake/...@124589
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
index feb1561..65ff042 100644
--- a/libc/tools/bionic_utils.py
+++ b/libc/tools/bionic_utils.py
@@ -136,6 +136,11 @@
         print "%d: %s" % (self.lineno, msg)
 
     def parse_line(self, line):
+        """ parse a syscall spec line.
+
+        line processing, format is
+           return type    func_name[:syscall_name[:call_id]] ( [paramlist] )   (syscall_number[,syscall_number_x86])|stub
+        """
         pos_lparen = line.find('(')
         E          = self.E
         if pos_lparen < 0:
@@ -154,6 +159,7 @@
 
         syscall_func = return_type[-1]
         return_type  = string.join(return_type[:-1],' ')
+        call_id = -1
 
         pos_colon = syscall_func.find(':')
         if pos_colon < 0:
@@ -162,8 +168,20 @@
             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]
+
+            # now find if there is a call_id for a dispatch-type syscall
+            # after the optional 2nd colon
+            pos_colon2 = syscall_func.find(':', pos_colon + 1)
+            if pos_colon2 < 0:
+                syscall_name = syscall_func[pos_colon+1:]
+                syscall_func = syscall_func[:pos_colon]
+            else:
+                if pos_colon2+1 >= len(syscall_func):
+                    E("misplaced colon2 in '%s'" % line)
+                    return
+                syscall_name = syscall_func[(pos_colon+1):pos_colon2]
+                call_id = int(syscall_func[pos_colon2+1:])
+                syscall_func = syscall_func[:pos_colon]
 
         if pos_rparen > pos_lparen+1:
             syscall_params = line[pos_lparen+1:pos_rparen].split(',')
@@ -191,6 +209,7 @@
 
         t = { "id"     : syscall_id,
               "id2"    : syscall_id2,
+              "cid"    : call_id,
               "name"   : syscall_name,
               "func"   : syscall_func,
               "params" : syscall_params,
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 37e356d..530e565 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -5,7 +5,7 @@
 # of arch-x86/linux/_syscalls.h
 #
 
-import sys, os.path, glob, re, string, commands, filecmp, shutil
+import sys, os.path, glob, re, commands, filecmp, shutil
 
 from bionic_utils import *
 
@@ -196,7 +196,7 @@
         self.other_files = []
         self.syscalls = []
 
-    def x86_genstub(self,fname, numparams, idname):
+    def x86_genstub(self, fname, numparams, idname):
         t = { "fname"  : fname,
               "idname" : idname }
 
@@ -217,6 +217,43 @@
         result += x86_return
         return result
 
+    def x86_genstub_cid(self, fname, numparams, idname, cid):
+        # We'll ignore numparams here because in reality, if there is a
+        # dispatch call (like a socketcall syscall) there are actually
+        # only 2 arguments to the syscall and 2 regs we have to save:
+        #   %ebx <--- Argument 1 - The call id of the needed vectored
+        #                          syscall (socket, bind, recv, etc)
+        #   %ecx <--- Argument 2 - Pointer to the rest of the arguments
+        #                          from the original function called (socket())
+        t = { "fname"  : fname,
+              "idname" : idname }
+
+        result = x86_header % t
+        stack_bias = 4
+
+        # save the regs we need
+        result += "    pushl   %ebx" + "\n"
+        stack_bias += 4
+        result += "    pushl   %ecx" + "\n"
+        stack_bias += 4
+
+        # set the call id (%ebx)
+        result += "    mov     $%d, %%ebx" % (cid) + "\n"
+
+        # set the pointer to the rest of the args into %ecx
+        result += "    mov     %esp, %ecx" + "\n"
+        result += "    addl    $%d, %%ecx" % (stack_bias) + "\n"
+
+        # now do the syscall code itself
+        result += x86_call % t
+
+        # now restore the saved regs
+        result += "    popl    %ecx" + "\n"
+        result += "    popl    %ebx" + "\n"
+
+        # epilog
+        result += x86_return
+        return result
 
     def arm_genstub(self,fname, flags, idname):
         t = { "fname"  : fname,
@@ -269,7 +306,15 @@
                         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)
+                if t["cid"] >= 0:
+                    t["asm-x86"] = self.x86_genstub_cid(syscall_func, len(syscall_params), "__NR_"+syscall_name, t["cid"])
+                else:
+                    t["asm-x86"] = self.x86_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+            elif t["cid"] >= 0:
+                E("cid for dispatch syscalls is only supported for x86 in "
+                  "'%s'" % syscall_name)
+                return
+
 
     def gen_NR_syscall(self,fp,name,id):
         fp.write( "#define __NR_%-25s    (__NR_SYSCALL_BASE + %d)\n" % (name,id) )
@@ -306,14 +351,16 @@
                 self.gen_NR_syscall( fp, sc_name, sc_id )
         fp.write( "#endif\n" );
 
+        gen_syscalls = {}
         # 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:
+            if sc_id != sc_id2 and sc_id2 >= 0 and sc_name not in gen_syscalls:
                 self.gen_NR_syscall( fp, sc_name, sc_id2 )
+                gen_syscalls[sc_name] = True
         fp.write( "#endif\n" );
 
         fp.write( "\n#endif\n" )
@@ -340,22 +387,28 @@
         self.other_files.append( path )
 
     # now dump the contents of syscalls.mk
-    def gen_arch_arm_syscalls_mk(self):
-        path = "arch-arm/syscalls.mk"
+    def gen_arch_syscalls_mk(self, arch):
+        path = "arch-%s/syscalls.mk" % arch
         D( "generating "+path )
         fp = create_file( path )
         fp.write( "# auto-generated by gensyscalls.py, do not touch\n" )
         fp.write( "syscall_src := \n" )
+        arch_test = {
+            "arm": lambda x: x.has_key("asm-arm") or x.has_key("asm-thumb"),
+            "x86": lambda x: x.has_key("asm-x86")
+        }
+
         for sc in self.syscalls:
-                if sc["id"] >= 0:
-                        fp.write( "syscall_src += arch-arm/syscalls/%s.S\n" % sc["func"] )
+            if arch_test[arch](sc):
+                fp.write("syscall_src += arch-%s/syscalls/%s.S\n" %
+                         (arch, 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"):
+            if sc.has_key("asm-arm") and 'arm' in all_archs:
                 fname = "arch-arm/syscalls/%s.S" % sc["func"]
                 D( ">>> generating "+fname )
                 fp = create_file( fname )
@@ -363,7 +416,7 @@
                 fp.close()
                 self.new_stubs.append( fname )
 
-            if sc.has_key("asm-thumb"):
+            if sc.has_key("asm-thumb") and 'arm' in all_archs:
                 fname = "arch-arm/syscalls/%s.S" % sc["func"]
                 D( ">>> generating "+fname )
                 fp = create_file( fname )
@@ -371,7 +424,7 @@
                 fp.close()
                 self.new_stubs.append( fname )
 
-            if sc.has_key("asm-x86"):
+            if sc.has_key("asm-x86") and 'x86' in all_archs:
                 fname = "arch-x86/syscalls/%s.S" % sc["func"]
                 D( ">>> generating "+fname )
                 fp = create_file( fname )
@@ -407,7 +460,8 @@
         D( "re-generating stubs and support files" )
 
         self.gen_linux_syscalls_h()
-        self.gen_arch_arm_syscalls_mk()
+        for arch in all_archs:
+            self.gen_arch_syscalls_mk(arch)
         self.gen_linux_unistd_h()
         self.gen_syscall_stubs()
 
@@ -434,11 +488,12 @@
 
 
         if adds:
-            commands.getoutput( "p4 add " + string.join( adds, " " ) )
+            commands.getoutput("p4 add " + " ".join(adds))
         if deletes:
-            commands.getoutput( "p4 delete " + string.join( deletes, " " ) )
+            commands.getoutput("p4 delete " + " ".join(deletes))
         if edits:
-            commands.getoutput( "p4 edit " + string.join( edits, " " ) )
+            commands.getoutput("p4 edit " +
+                               " ".join((bionic_root + file) for file in edits))
             for file in edits:
                 shutil.copyfile( bionic_temp + file, bionic_root + file )