[klibc] Detect the sizes of various types, and make available to sysstub.ph.

This additional code effectively queries the C compiler for the sizes of
various types, and makes an associative array %typesize available to
sysstub.ph.  This is currently not used, but it's expected that some
architectures, e.g. s390, will need this to determine which registers
go where, and how many registers are needed.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/usr/klibc/syscalls.pl b/usr/klibc/syscalls.pl
index c425137..92f4306 100644
--- a/usr/klibc/syscalls.pl
+++ b/usr/klibc/syscalls.pl
@@ -2,15 +2,24 @@
 #
 # Script to parse the SYSCALLS file and generate appropriate
 # stubs.
+#
+# Pass 1: generate the C array of sizes
+# Pass 2: generate the syscall stubs and other output
+#
 
 $v = $ENV{'KBUILD_VERBOSE'};
-$quiet = defined($v) ? !$v : 0;
+$quiet = defined($v) && ($v == 0) ? 1 : undef;
 
 @args = ();
+undef $pass;
 for $arg ( @ARGV ) {
     if ( $arg =~ /^-/ ) {
 	if ( $arg eq '-q' ) {
 	    $quiet = 1;
+	} elsif ( $arg eq '-v' ) {
+	    $quiet = 0;
+	} elsif ( $arg =~ /\-([0-9]+)$/ ) {
+	    $pass = $1+0;
 	} else {
 	    die "$0: Unknown option: $arg\n";
 	}
@@ -18,7 +27,14 @@
 	push(@args, $arg);
     }
 }
-($file, $sysstub, $arch, $bits, $unistd, $outputdir, $havesyscall) = @args;
+($file, $sysstub, $arch, $bits, $unistd, $outputdir,
+ $havesyscall, $typesize) = @args;
+
+if (!$pass) {
+    die "$0: Need to specify pass\n";
+}
+
+$quiet = ($pass != 2) unless defined($quiet);
 
 require "$sysstub";
 
@@ -36,18 +52,66 @@
 }
 close(UNISTD);
 
-if (!open(HAVESYS, '>', $havesyscall)) {
-    die "$0: $havesyscall: $!\n";
+if ($pass == 2) {
+    use bytes;
+
+    if (!open(TYPESIZE, '<', $typesize)) {
+	die "$0: $typesize: $!\n";
+    }
+    
+    binmode TYPESIZE;
+
+    $len = -s TYPESIZE;
+    if (read(TYPESIZE, $typebin, $len) != $len) {
+	die "$0: $typesize: short read: $!\n";
+    }
+    close(TYPESIZE);
+
+    $ix = index($typebin, "\x7a\xc8\xdb\x4e\x97\xb4\xc9\x19");
+    if ($ix < 0) {
+	die "$0: $typesize: magic number not found\n";
+    }
+
+    # Remove magic number and bytes before it
+    $typebin = substr($typebin, $ix+8);
+
+    @size_table = unpack("C*", $typebin);
 }
 
-print HAVESYS "#ifndef _KLIBC_HAVESYSCALL_H\n";
-print HAVESYS "#define _KLIBC_HAVESYSCALL_H 1\n\n";
+if ($pass == 2) {
+    if (!open(HAVESYS, '>', $havesyscall)) {
+	die "$0: $havesyscall: $!\n";
+    }
+    
+    print HAVESYS "#ifndef _KLIBC_HAVESYSCALL_H\n";
+    print HAVESYS "#define _KLIBC_HAVESYSCALL_H 1\n\n";
+}
 
 if (!open(FILE, '<', $file)) {
     die "$0: $file: $!\n";
 }
 
-print "syscall-objs := ";
+
+if ($pass == 2) {
+    print "syscall-objs := ";
+}
+
+
+# List here any types which should be sized even if they never occur
+# in any system calls at all.
+@type_list = ('int', 'long', 'void *', 'intptr_t', 'uintptr_t',
+	      'intmax_t', 'uintmax_t');
+
+%type_index = ();
+%typesize = ();
+$n = 0;
+foreach $t (@type_list) {
+    $type_index{$t} = $n;
+    if ($pass == 2) {
+	$typesize{$t} = $size_table[$n];
+    }
+    $n++;
+}
 
 while ( defined($line = <FILE>) ) {
     chomp $line;
@@ -106,15 +170,50 @@
 
 	@args = split(/\s*\,\s*/, $argv);
 
-	print HAVESYS "#define _KLIBC_HAVE_SYSCALL_${fname} ${sname}\n";
-	print " \\\n\t${fname}.o";
-	make_sysstub($outputdir, $fname, $type, $sname, $stype, @args);
+	# Assign types indexes in order of appearance, so that in pass 2
+	# we know where to find it.
+	foreach $a (@args) {
+	    if (!defined($type_index{$a})) {
+		$a_index = scalar(@type_list);
+		push(@type_list, $a);
+		$type_index{$a} = $a_index;
+		if ($pass == 2) {
+		    $typesize{$a} = $size_table[$a_index];
+		}
+	    }
+	    if ($pass == 2) {
+		print STDERR "sizeof($a) = ", $typesize{$a}, "\n";
+	    }
+	}
+
+	if ($pass == 2) {
+	    print HAVESYS "#define _KLIBC_HAVE_SYSCALL_${fname} ${sname}\n";
+	    print " \\\n\t${fname}.o";
+	    make_sysstub($outputdir, $fname, $type, $sname, $stype, @args);
+	}
     } else {
 	die "$file:$.: Could not parse input: \"$line\"\n";
     }
 }
 
-print "\n";
+if ($pass == 1) {
+    if (!open(TYPESIZE, '>', $typesize)) {
+	die "$0: cannot create file: $typesize: $!\n";
+    }
 
-print HAVESYS "\n#endif\n";
-close(HAVESYS);
+    print TYPESIZE "#include \"syscommon.h\"\n";
+    print TYPESIZE "\n";
+    print TYPESIZE "const unsigned char type_sizes[] = {\n";
+    print TYPESIZE "\t0x7a,0xc8,0xdb,0x4e,0x97,0xb4,0xc9,0x19, /* magic */\n";
+    foreach $t (@type_list) {
+	print TYPESIZE "\tsizeof($t),\n";
+    }
+    print TYPESIZE "};\n";
+    close(TYPESIZE);
+} else {
+    print "\n";
+
+    print HAVESYS "\n#endif\n";
+    close(HAVESYS);
+}
+
diff --git a/usr/klibc/syscalls/Kbuild b/usr/klibc/syscalls/Kbuild
index 487ebf7..d9c7e44 100644
--- a/usr/klibc/syscalls/Kbuild
+++ b/usr/klibc/syscalls/Kbuild
@@ -25,7 +25,7 @@
 clean-files += $(objtree)/$(KLIBCINC)/klibc/havesyscall.h
 clean-files += $(KLIBCINC)/klibc/havesyscall.h
 # All the syscall stubs
-clean-files += *.o *.S *.c *.list
+clean-files += *.o *.S *.c *.list *.bin
 
 quiet_cmd_makelist = LIST    $@
       cmd_makelist = echo '$(filter-out FORCE,$^)' > $@
@@ -48,19 +48,45 @@
 $(obj)/syscalls.nrs: $(KLIBCINC)/sys/syscall.h FORCE
 	$(call if_changed_dep,syscall.nrs)
 
+# Generate typesize.c
+quiet_cmd_syscalsz = GEN     $@
+      cmd_syscalsz = mkdir -p $(KLIBCINC)/klibc/;                           \
+                     $(PERL) $(KLIBCSRC)/syscalls.pl -1 $(obj)/SYSCALLS.i   \
+                             $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph    \
+                             $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs \
+                             $(obj)                                         \
+                             $(KLIBCINC)/klibc/havesyscall.h 		    \
+			     $(obj)/typesize.c > $@                      \
+                             || rm -f $@
+
+$(obj)/typesize.c: $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \
+                      $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \
+                      $(call objectify, $(syscall-objs:.o=.S)) \
+                      $(src)/syscommon.h $(obj)/syscalls.nrs
+	$(call cmd,syscalsz)
+
+# Convert typesize.o to typesize.bin
+quiet_cmd_mkbin = OBJCOPY $@
+      cmd_mkbin = $(KLIBCOBJCOPY) -O binary $< $@
+
+$(obj)/typesize.bin: $(obj)/typesize.o
+	$(call cmd,mkbin)
+
 # Generate $(KLIBINC)/klibc/havesyscall.h + makefile fragment
 # Using sysstub.pl in arch dir generate all .S files
 quiet_cmd_syscalls = GEN     $@
       cmd_syscalls = mkdir -p $(KLIBCINC)/klibc/;                           \
-                     $(PERL) $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i      \
-                             $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph            \
-                             $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs    \
+                     $(PERL) $(KLIBCSRC)/syscalls.pl -2 $(obj)/SYSCALLS.i   \
+                             $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph    \
+                             $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs \
                              $(obj)                                         \
-                             $(KLIBCINC)/klibc/havesyscall.h > $@           \
+                             $(KLIBCINC)/klibc/havesyscall.h 		    \
+			     $(obj)/typesize.bin > $@                    \
                              || rm -f $@
 
 $(obj)/syscalls.mk: $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \
-                    $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph       \
-                    $(call objectify, $(syscall-objs:.o=.S))  \
-                    $(KLIBCSRC)/syscommon.h $(obj)/syscalls.nrs
+                    $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \
+                    $(call objectify, $(syscall-objs:.o=.S)) \
+                    $(src)/syscommon.h $(obj)/syscalls.nrs \
+		    $(obj)/typesize.bin
 	$(call cmd,syscalls)
diff --git a/usr/klibc/syscommon.h b/usr/klibc/syscalls/syscommon.h
similarity index 95%
rename from usr/klibc/syscommon.h
rename to usr/klibc/syscalls/syscommon.h
index 4290252..0acae12 100644
--- a/usr/klibc/syscommon.h
+++ b/usr/klibc/syscalls/syscommon.h
@@ -17,6 +17,7 @@
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/select.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/times.h>